@mikeargento/bitgraph-audit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/dist/anchors.d.ts +31 -0
- package/dist/anchors.d.ts.map +1 -0
- package/dist/anchors.js +116 -0
- package/dist/anchors.js.map +1 -0
- package/dist/anomalies.d.ts +42 -0
- package/dist/anomalies.d.ts.map +1 -0
- package/dist/anomalies.js +642 -0
- package/dist/anomalies.js.map +1 -0
- package/dist/attestation.d.ts +20 -0
- package/dist/attestation.d.ts.map +1 -0
- package/dist/attestation.js +795 -0
- package/dist/attestation.js.map +1 -0
- package/dist/audit.d.ts +19 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +116 -0
- package/dist/audit.js.map +1 -0
- package/dist/authority.d.ts +37 -0
- package/dist/authority.d.ts.map +1 -0
- package/dist/authority.js +126 -0
- package/dist/authority.js.map +1 -0
- package/dist/aws-nitro-root-ca.d.ts +24 -0
- package/dist/aws-nitro-root-ca.d.ts.map +1 -0
- package/dist/aws-nitro-root-ca.js +44 -0
- package/dist/aws-nitro-root-ca.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +257 -0
- package/dist/cli.js.map +1 -0
- package/dist/contents-hash.d.ts +30 -0
- package/dist/contents-hash.d.ts.map +1 -0
- package/dist/contents-hash.js +73 -0
- package/dist/contents-hash.js.map +1 -0
- package/dist/export.d.ts +64 -0
- package/dist/export.d.ts.map +1 -0
- package/dist/export.js +192 -0
- package/dist/export.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest.d.ts +36 -0
- package/dist/ingest.d.ts.map +1 -0
- package/dist/ingest.js +828 -0
- package/dist/ingest.js.map +1 -0
- package/dist/reconstruct.d.ts +40 -0
- package/dist/reconstruct.d.ts.map +1 -0
- package/dist/reconstruct.js +400 -0
- package/dist/reconstruct.js.map +1 -0
- package/dist/report-json.d.ts +3 -0
- package/dist/report-json.d.ts.map +1 -0
- package/dist/report-json.js +290 -0
- package/dist/report-json.js.map +1 -0
- package/dist/report-md.d.ts +3 -0
- package/dist/report-md.d.ts.map +1 -0
- package/dist/report-md.js +853 -0
- package/dist/report-md.js.map +1 -0
- package/dist/rlp.d.ts +37 -0
- package/dist/rlp.d.ts.map +1 -0
- package/dist/rlp.js +120 -0
- package/dist/rlp.js.map +1 -0
- package/dist/tar.d.ts +47 -0
- package/dist/tar.d.ts.map +1 -0
- package/dist/tar.js +483 -0
- package/dist/tar.js.map +1 -0
- package/dist/temporal.d.ts +55 -0
- package/dist/temporal.d.ts.map +1 -0
- package/dist/temporal.js +461 -0
- package/dist/temporal.js.map +1 -0
- package/dist/types.d.ts +1389 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/validity.d.ts +21 -0
- package/dist/validity.d.ts.map +1 -0
- package/dist/validity.js +86 -0
- package/dist/validity.js.map +1 -0
- package/dist/verify-tiers.d.ts +11 -0
- package/dist/verify-tiers.d.ts.map +1 -0
- package/dist/verify-tiers.js +120 -0
- package/dist/verify-tiers.js.map +1 -0
- package/dist/witness.d.ts +25 -0
- package/dist/witness.d.ts.map +1 -0
- package/dist/witness.js +308 -0
- package/dist/witness.js.map +1 -0
- package/package.json +42 -0
- package/src/anchors.ts +168 -0
- package/src/anomalies.ts +773 -0
- package/src/attestation.ts +878 -0
- package/src/audit.ts +136 -0
- package/src/authority.ts +165 -0
- package/src/aws-nitro-root-ca.ts +47 -0
- package/src/cli.ts +284 -0
- package/src/contents-hash.ts +95 -0
- package/src/export.ts +278 -0
- package/src/index.ts +122 -0
- package/src/ingest.ts +967 -0
- package/src/reconstruct.ts +491 -0
- package/src/report-json.ts +331 -0
- package/src/report-md.ts +1067 -0
- package/src/rlp.ts +142 -0
- package/src/tar.ts +587 -0
- package/src/temporal.ts +629 -0
- package/src/types.ts +1528 -0
- package/src/validity.ts +90 -0
- package/src/verify-tiers.ts +137 -0
- package/src/witness.ts +407 -0
package/src/rlp.ts
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// Copyright (c) 2024-2026 Mike Argento. Licensed under the MIT License. See LICENSE.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* bitgraph-audit minimal RLP decoder (internal)
|
|
5
|
+
*
|
|
6
|
+
* Just enough RLP to decode an Ethereum block header for the anchor
|
|
7
|
+
* witness procedure (bundle spec section 10.3 step 1): a single
|
|
8
|
+
* well-formed list of items, where an item is a byte string or a nested
|
|
9
|
+
* list. No dependency, no encoding support (tests carry their own tiny
|
|
10
|
+
* encoder), no network.
|
|
11
|
+
*
|
|
12
|
+
* Strictness: offsets and lengths are bounds-checked and the top-level
|
|
13
|
+
* decode must consume the input exactly ("a single well-formed RLP
|
|
14
|
+
* list"). Canonical-form minimality (shortest-length encodings) is NOT
|
|
15
|
+
* enforced: the witness procedure recomputes Keccak-256 over the exact
|
|
16
|
+
* raw bytes, so any alternative encoding of the same header changes the
|
|
17
|
+
* hash and fails the hash comparison, which is the actual gate.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
export type RlpItem = Uint8Array | RlpItem[];
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Decode a complete RLP buffer whose top level is a list. Throws Error
|
|
24
|
+
* with a precise message on malformed input or trailing bytes.
|
|
25
|
+
*/
|
|
26
|
+
export function decodeRlpList(bytes: Uint8Array): RlpItem[] {
|
|
27
|
+
if (bytes.length === 0) throw new Error("RLP: empty input");
|
|
28
|
+
const { item, next } = decodeItem(bytes, 0);
|
|
29
|
+
if (next !== bytes.length) {
|
|
30
|
+
throw new Error(`RLP: ${bytes.length - next} trailing byte(s) after the top-level item`);
|
|
31
|
+
}
|
|
32
|
+
if (!Array.isArray(item)) throw new Error("RLP: top-level item is not a list");
|
|
33
|
+
return item;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function decodeItem(bytes: Uint8Array, offset: number): { item: RlpItem; next: number } {
|
|
37
|
+
const prefix = at(bytes, offset);
|
|
38
|
+
|
|
39
|
+
// Single byte, self-encoding.
|
|
40
|
+
if (prefix < 0x80) {
|
|
41
|
+
return { item: bytes.subarray(offset, offset + 1), next: offset + 1 };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Short byte string (0..55 bytes).
|
|
45
|
+
if (prefix <= 0xb7) {
|
|
46
|
+
const length = prefix - 0x80;
|
|
47
|
+
const end = checkedEnd(bytes, offset + 1, length);
|
|
48
|
+
return { item: bytes.subarray(offset + 1, end), next: end };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Long byte string.
|
|
52
|
+
if (prefix <= 0xbf) {
|
|
53
|
+
const lengthOfLength = prefix - 0xb7;
|
|
54
|
+
const length = readLength(bytes, offset + 1, lengthOfLength);
|
|
55
|
+
const start = offset + 1 + lengthOfLength;
|
|
56
|
+
const end = checkedEnd(bytes, start, length);
|
|
57
|
+
return { item: bytes.subarray(start, end), next: end };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Short list (payload 0..55 bytes).
|
|
61
|
+
if (prefix <= 0xf7) {
|
|
62
|
+
const payloadLength = prefix - 0xc0;
|
|
63
|
+
const end = checkedEnd(bytes, offset + 1, payloadLength);
|
|
64
|
+
return { item: decodeListPayload(bytes, offset + 1, end), next: end };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Long list.
|
|
68
|
+
const lengthOfLength = prefix - 0xf7;
|
|
69
|
+
const payloadLength = readLength(bytes, offset + 1, lengthOfLength);
|
|
70
|
+
const start = offset + 1 + lengthOfLength;
|
|
71
|
+
const end = checkedEnd(bytes, start, payloadLength);
|
|
72
|
+
return { item: decodeListPayload(bytes, start, end), next: end };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function decodeListPayload(bytes: Uint8Array, start: number, end: number): RlpItem[] {
|
|
76
|
+
const items: RlpItem[] = [];
|
|
77
|
+
let cursor = start;
|
|
78
|
+
while (cursor < end) {
|
|
79
|
+
const decoded = decodeItem(bytes, cursor);
|
|
80
|
+
if (decoded.next > end) throw new Error("RLP: list item overruns its list payload");
|
|
81
|
+
items.push(decoded.item);
|
|
82
|
+
cursor = decoded.next;
|
|
83
|
+
}
|
|
84
|
+
return items;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function readLength(bytes: Uint8Array, offset: number, lengthOfLength: number): number {
|
|
88
|
+
if (lengthOfLength < 1 || lengthOfLength > 8) {
|
|
89
|
+
throw new Error(`RLP: invalid length-of-length ${lengthOfLength}`);
|
|
90
|
+
}
|
|
91
|
+
let value = 0;
|
|
92
|
+
for (let i = 0; i < lengthOfLength; i++) {
|
|
93
|
+
value = value * 256 + at(bytes, offset + i);
|
|
94
|
+
}
|
|
95
|
+
if (value > bytes.length) throw new Error("RLP: declared length exceeds the input size");
|
|
96
|
+
return value;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function checkedEnd(bytes: Uint8Array, start: number, length: number): number {
|
|
100
|
+
const end = start + length;
|
|
101
|
+
if (end > bytes.length) throw new Error("RLP: item is truncated");
|
|
102
|
+
return end;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function at(bytes: Uint8Array, offset: number): number {
|
|
106
|
+
const value = bytes[offset];
|
|
107
|
+
if (value === undefined) throw new Error("RLP: unexpected end of input");
|
|
108
|
+
return value;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Interpret an RLP byte string as a big-endian unsigned integer, the
|
|
113
|
+
* encoding Ethereum headers use for the number and timestamp fields. An
|
|
114
|
+
* empty byte string means zero.
|
|
115
|
+
*/
|
|
116
|
+
export function rlpBytesToBigInt(bytes: Uint8Array): bigint {
|
|
117
|
+
let value = 0n;
|
|
118
|
+
for (const byte of bytes) value = (value << 8n) | BigInt(byte);
|
|
119
|
+
return value;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Decode a 0x-prefixed, even-length, case-insensitive hex string to
|
|
124
|
+
* bytes. Returns null on any format violation (missing prefix, odd
|
|
125
|
+
* length, non-hex characters).
|
|
126
|
+
*/
|
|
127
|
+
export function hexToBytes(hex: string): Uint8Array | null {
|
|
128
|
+
if (!hex.startsWith("0x")) return null;
|
|
129
|
+
const body = hex.slice(2);
|
|
130
|
+
if (body.length % 2 !== 0) return null;
|
|
131
|
+
if (!/^[0-9a-fA-F]*$/.test(body)) return null;
|
|
132
|
+
const out = new Uint8Array(body.length / 2);
|
|
133
|
+
for (let i = 0; i < out.length; i++) {
|
|
134
|
+
out[i] = Number.parseInt(body.slice(i * 2, i * 2 + 2), 16);
|
|
135
|
+
}
|
|
136
|
+
return out;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Lowercase 0x-prefixed hex of bytes. */
|
|
140
|
+
export function bytesToHex0x(bytes: Uint8Array): string {
|
|
141
|
+
return `0x${Buffer.from(bytes).toString("hex")}`;
|
|
142
|
+
}
|