@sig-net/midnight-serde 0.23.0 → 0.24.0-rc.10
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/README.md +47 -173
- package/dist/index.d.ts +23 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -4
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
- package/dist/deserialize.d.ts +0 -26
- package/dist/deserialize.d.ts.map +0 -1
- package/dist/deserialize.js +0 -178
- package/dist/deserialize.js.map +0 -1
- package/dist/serialize.d.ts +0 -48
- package/dist/serialize.d.ts.map +0 -1
- package/dist/serialize.js +0 -292
- package/dist/serialize.js.map +0 -1
- package/dist/types.d.ts +0 -134
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -22
- package/dist/types.js.map +0 -1
- package/dist/validate.d.ts +0 -39
- package/dist/validate.d.ts.map +0 -1
- package/dist/validate.js +0 -185
- package/dist/validate.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,184 +1,58 @@
|
|
|
1
1
|
# @sig-net/midnight-serde
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
pair (CompactStandardLibrary). Produce bytes off-chain that a contract reads
|
|
5
|
-
with one `deserialize<T, N>` call, and decode bytes a contract produced with
|
|
6
|
-
`serialize<T, N>`. Zero runtime dependencies.
|
|
7
|
-
|
|
8
|
-
Every claim is pinned byte-for-byte against COMPILED circuits: the fixture
|
|
9
|
-
contract in [`tests/fixtures/serde-fixtures.compact`](tests/fixtures/serde-fixtures.compact)
|
|
10
|
-
wraps the builtins over structs exercising all supported types and combos, and
|
|
11
|
-
the tests assert twin/circuit equality in both directions. A second oracle
|
|
12
|
-
backs the serialize direction: `toBinaryRepr` from
|
|
13
|
-
`@midnight-ntwrk/compact-runtime` (test-only, never a runtime dependency)
|
|
14
|
-
must agree with the twin on every shape, including the shapes compactc cannot
|
|
15
|
-
compile `serialize<T, N>` for. The oracle adapter computes its byte widths
|
|
16
|
-
independently of the twin's width logic, so a width bug cannot cancel out of
|
|
17
|
-
the comparison, and a seeded randomised suite sweeps hundreds of generated
|
|
18
|
-
descriptor/value pairs through the roundtrip and the oracle on every run.
|
|
19
|
-
|
|
20
|
-
One honest caveat on what "circuit-pinned" means: the pins execute the
|
|
21
|
-
compiler's JS emission of each circuit (via `@midnight-ntwrk/compact-runtime`
|
|
22
|
-
under vitest), not the Impact VM or a prover. That JS is generated by the
|
|
23
|
-
same expand-serialize compiler pass as the in-circuit code, and the ledger
|
|
24
|
-
sources define the identical atom layout (see Sources), but no test in this
|
|
25
|
-
package runs a proof or a node.
|
|
3
|
+
A thin wrapper around the real [borsh-js](https://github.com/near/borsh-js) package, declared as an exact 2.0.0 dependency for workspace and published consumers. Schemas and value representations are native Borsh. Optional zero padding supports Midnight fixed byte containers.
|
|
26
4
|
|
|
27
5
|
## Use
|
|
28
6
|
|
|
29
|
-
Describe the Compact type as a descriptor tree, then encode/decode values.
|
|
30
|
-
Declare descriptors `as const satisfies CompactType` and the value types are
|
|
31
|
-
INFERRED from the descriptor (`CompactValueOf<T>`), both in and out, so no
|
|
32
|
-
casts and no hand-written interfaces:
|
|
33
|
-
|
|
34
7
|
```ts
|
|
35
|
-
import { compactSerialize, compactDeserialize, type
|
|
36
|
-
|
|
37
|
-
// Compact: struct Result { ok: Boolean; amount: Uint<128>; }
|
|
38
|
-
const RESULT = {
|
|
39
|
-
kind: "struct",
|
|
40
|
-
fields: [
|
|
41
|
-
{ name: "ok", type: { kind: "boolean" } },
|
|
42
|
-
{ name: "amount", type: { kind: "uint", bits: 128 } },
|
|
43
|
-
],
|
|
44
|
-
} as const satisfies CompactType;
|
|
45
|
-
|
|
46
|
-
// serialize<Result, 128> twin: packed value at the start, zero-padded to 128.
|
|
47
|
-
// The value parameter is compile-time checked against the descriptor.
|
|
48
|
-
const bytes = compactSerialize(RESULT, { ok: true, amount: 4242n }, 128);
|
|
8
|
+
import { compactSerialize, compactDeserialize, type Schema } from "@sig-net/midnight-serde";
|
|
49
9
|
|
|
50
|
-
|
|
10
|
+
const RESULT = { struct: { ok: "bool", amount: "u128" } } satisfies Schema;
|
|
11
|
+
const bytes = compactSerialize(RESULT, { ok: true, amount: 4242n }, 128);
|
|
51
12
|
const value = compactDeserialize(RESULT, bytes);
|
|
52
|
-
// ^? { ok: boolean; amount: bigint }
|
|
53
13
|
```
|
|
54
14
|
|
|
55
|
-
A
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
a
|
|
64
|
-
|
|
65
|
-
| Compact type |
|
|
66
|
-
| --- | --- | --- |
|
|
67
|
-
| `Boolean` |
|
|
68
|
-
| `Uint<
|
|
69
|
-
|
|
|
70
|
-
| `
|
|
71
|
-
| `
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
| `
|
|
75
|
-
|
|
|
76
|
-
|
|
77
|
-
The
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
`
|
|
85
|
-
|
|
86
|
-
and
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
`
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
circuit-pinned, straight from the constructors).
|
|
96
|
-
|
|
97
|
-
## Divergences from the circuit
|
|
98
|
-
|
|
99
|
-
Two divergences, both strict-by-default on DECODE, both pinned by tests with
|
|
100
|
-
bytes the circuit actually receives, and both with an opt-out. Bytes a
|
|
101
|
-
circuit produced never trigger either one, since `serialize<T, N>` only ever
|
|
102
|
-
writes zero padding and 0x00/0x01 booleans:
|
|
103
|
-
|
|
104
|
-
- **Padding:** the circuit ignores bytes in the padding region entirely, the
|
|
105
|
-
twin rejects non-zero padding. Pass `{ ignorePadding: true }` to mirror
|
|
106
|
-
the circuit's padding behaviour.
|
|
107
|
-
- **Booleans:** the circuit decodes ANY byte other than 0x01 as `false`
|
|
108
|
-
(0x02..0xff included), the twin rejects bytes above 1. Pass
|
|
109
|
-
`{ lenientBooleans: true }` to mirror the circuit's boolean behaviour.
|
|
110
|
-
|
|
111
|
-
With both options set, `compactDeserialize` is circuit-exact on arbitrary
|
|
112
|
-
bytes (pinned by tests). Everything else mirrors the circuit exactly,
|
|
113
|
-
including rejections: out-of-range bounded Uint, sized Uint, enum and Field
|
|
114
|
-
encodings throw in-circuit and throw here (all pinned by the tests).
|
|
115
|
-
|
|
116
|
-
The ENCODE side is stricter than TypeScript alone would be, in line with the
|
|
117
|
-
strict descriptor validation: a struct value with a property the descriptor
|
|
118
|
-
does not declare is rejected (a typo'd key alongside the correct ones would
|
|
119
|
-
otherwise vanish silently), array and byte lengths must match the descriptor
|
|
120
|
-
exactly, and out-of-range numerics throw. Two resource guards round this
|
|
121
|
-
off: descriptor lengths must be safe integers and computed packed sizes must
|
|
122
|
-
stay below `Number.MAX_SAFE_INTEGER` (never a silently rounded size), and a
|
|
123
|
-
decode refuses to materialise more than 65536 zero-width vector elements
|
|
124
|
-
(`Vector<huge, Nothing>` decodes from no input at all, so a hostile
|
|
125
|
-
descriptor could otherwise hang the process on an empty buffer).
|
|
126
|
-
|
|
127
|
-
Known compactc 0.33 limits (pinned by the tests): `serialize<T, N>` crashes
|
|
128
|
-
the COMPILER on vectors of structs, vectors of vectors, and struct nesting
|
|
129
|
-
deeper than one level. `deserialize<T, N>` handles all of those, so contracts
|
|
130
|
-
can still READ such payloads from off-chain encoders. Tuples are unaffected:
|
|
131
|
-
`serialize<[Pair, Boolean], N>` compiles fine.
|
|
132
|
-
|
|
133
|
-
## Develop
|
|
134
|
-
|
|
135
|
-
```bash
|
|
136
|
-
yarn compile # compile the fixture contract (needed before test/build)
|
|
137
|
-
yarn test # pin the twin against the compiled circuits + toBinaryRepr
|
|
138
|
-
yarn build # typecheck + emit ./dist for publishing
|
|
139
|
-
```
|
|
15
|
+
`compactSerialize(schema, value, length?)` calls `borsh.serialize` and optionally extends the bytes with zeros. A total length smaller than the encoded value throws. `compactDeserialize(schema, bytes)` calls `borsh.deserialize`. Its return type is the native decoder's value union, not schema-derived TypeScript inference.
|
|
16
|
+
|
|
17
|
+
Use JavaScript numbers for `u8`, `u16` and `u32`, and bigints for `u64` and `u128`. Fixed arrays use `{ array: { type: "u8", len: 32 } }`. A response schema is native Borsh JSON, for example `{"struct":{"success":"bool","amount":"u128"}}`.
|
|
18
|
+
|
|
19
|
+
There is no Compact descriptor translation, custom integer encoder or compatibility check. Native Borsh schema validation remains enabled.
|
|
20
|
+
|
|
21
|
+
## Compact-compatible types
|
|
22
|
+
|
|
23
|
+
These are caller responsibilities, documented here without a runtime Compact compatibility gate. Native Borsh also accepts types outside this subset. Use the following representations to obtain bytes compatible with Compact's standard-library `serialize<T, N>` and `deserialize<T, N>` on valid values:
|
|
24
|
+
|
|
25
|
+
| Compact type | Native Borsh representation | Conditions |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| `Boolean` | Boolean | Use canonical values and encodings 0 or 1. |
|
|
28
|
+
| `Uint<8>`, `Uint<16>`, `Uint<32>`, `Uint<64>`, `Uint<128>` | `u8`, `u16`, `u32`, `u64`, `u128` | Values must fit the unsigned width. |
|
|
29
|
+
| Other sized or bounded uint | Unsigned integer of exactly the same byte width | That width must be 1, 2, 4, 8 or 16. The value must also satisfy Compact's narrower bound. For example, `Uint<12>` uses `u16` but values must be below 4096. |
|
|
30
|
+
| `Bytes<n>` | Fixed byte array | Exact length. For interoperability with borsh-js 2.0.0, use positive lengths. |
|
|
31
|
+
| `Vector<n, T>` | Fixed array | Exact length, positive for cross-language interoperability, and compatible element types. |
|
|
32
|
+
| Struct or tuple | Fields in the same order | Every member must satisfy this table recursively. |
|
|
33
|
+
| Enum with 2 to 256 variants | Payload-free enum with matching ordinal | Same variant order. |
|
|
34
|
+
| `Maybe<T>` | Struct with `is_some: bool`, then `value: T` | Always include the value arm, including when absent. |
|
|
35
|
+
| `Either<A, B>` | Struct with `is_left: bool`, then `left: A`, then `right: B` | Always include both arms. |
|
|
36
|
+
|
|
37
|
+
The byte layout and the value constraints are separate contracts. The wrappers do not impose Compact integer bounds, field moduli or an allowlist. They use native Borsh behaviour. A successful Borsh round trip does not prove that Compact accepts the value or that the complete bytes are canonical for a chosen `N`.
|
|
38
|
+
|
|
39
|
+
## Types and behaviours that need care
|
|
40
|
+
|
|
41
|
+
- `Uint<24>`, `Uint<40>`, `Uint<248>` and `Field` have no matching native Borsh integer. Do not substitute a wider or narrower integer. Explicit fixed byte arrays require application-owned numeric conversions and validation.
|
|
42
|
+
- `Uint<0..1>` and a singleton Compact enum occupy zero bytes. Borsh integers and enum tags do not. There is no automatic singleton conversion here.
|
|
43
|
+
- Borsh dynamic arrays and strings include a four-byte length. Compact vectors and byte buffers are fixed-size. Use fixed arrays for direct compatibility.
|
|
44
|
+
- Native Borsh options and payload enums differ from Compact `Maybe` and `Either`. In particular, an absent Borsh `Option<u64>` is one byte, while Compact `Maybe<Uint<64>>` occupies nine bytes.
|
|
45
|
+
- Signed integers, floats, maps and sets have native Borsh meanings, but this package makes no claim that they correspond to Compact types.
|
|
46
|
+
- Compact `serialize<T, N>` pads to `N`. Pass the optional total output length to the wrapper when padding is needed. The decoding wrapper reads the Borsh value prefix and accepts trailing bytes. It does not validate padding.
|
|
47
|
+
- borsh-js 2.0.0 treats fixed arrays with `len: 0` as dynamic arrays and adds a four-byte prefix. Rust Borsh fixed empty arrays occupy zero bytes. This is an implementation difference, not the fixed-array rule of the Borsh format.
|
|
48
|
+
- borsh-js 2.0.0 accepts non-zero Boolean bytes as true and can silently truncate overflowing integers. Rust's native Boolean decoder rejects byte 2. Do not use malformed-input behaviour as a cross-language contract.
|
|
49
|
+
|
|
50
|
+
For the EVM response path, `@sig-net/midnight` derives the Borsh schema from the request's ABI output schema (`bool` to `bool`, `uint256` to a 32-byte fixed array holding the value little-endian, `address` to a 20-byte fixed array, `bytesN` to an N-byte fixed array) and calls this package with it. No integer is narrowed off chain: a Compact circuit narrows the `Bytes<32>` with `checkedTruncationU128`. That mapping belongs to the EVM layer, not to these generic Borsh wrappers.
|
|
51
|
+
|
|
52
|
+
## Evidence and references
|
|
53
|
+
|
|
54
|
+
The [conformance kit](../midnight-serde-conformance/README.md) compares native Borsh encodings with compiler-generated Compact fixtures for the documented subset. It also records examples of incompatibility. These tests execute generated JavaScript, not proof verification, and do not establish equivalence for the entire Compact type system.
|
|
140
55
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
the compiler monomorphises every call site into circuit code that walks the
|
|
145
|
-
type in declaration order and packs each atom at its natural width,
|
|
146
|
-
little-endian, with no tags, prefixes or gaps, then zero-pads the result on
|
|
147
|
-
the right to `Bytes<N>`. The layout it emits is the binary form of Midnight's
|
|
148
|
-
field-aligned binary (FAB) representation, the same bytes the ledger writes as
|
|
149
|
-
`persistentHash` preimages and that `toBinaryRepr` reproduces in the TS
|
|
150
|
-
runtime. This library is an independent TypeScript implementation of that
|
|
151
|
-
layout, pinned byte-for-byte against compiled circuits and against
|
|
152
|
-
`toBinaryRepr`.
|
|
153
|
-
|
|
154
|
-
There is consequently NO reusable serializer for this layout anywhere in
|
|
155
|
-
Midnight's own code: no function producing `Bytes<N>` from a value, no
|
|
156
|
-
`Serialize` opcode in the Impact VM, no ZKIR instruction, nothing in
|
|
157
|
-
`onchain-runtime`. What exists instead is one generator (the compiler pass),
|
|
158
|
-
one Rust preimage writer over the same atoms (`transient-crypto/src/fab.rs`
|
|
159
|
-
plus its in-circuit mirror in `zkir*/src/ir_vm.rs`), one TS flattener
|
|
160
|
-
(`toBinaryRepr`), and hand-rolled decoders in the SDK and the indexer. Beware
|
|
161
|
-
the name collision: the ledger's top-level `serialize/` crate is a different,
|
|
162
|
-
tagged transport format (streams begin with the ASCII string
|
|
163
|
-
`midnight:<tag>:`), not this layout.
|
|
164
|
-
|
|
165
|
-
Repositories are pinned at `LFDT-Minokawa/compact @ 5d8c66c`,
|
|
166
|
-
`midnightntwrk/midnight-ledger @ e1edad2` (branch `ledger-8`),
|
|
167
|
-
`midnightntwrk/midnight-sdk @ 80e6707`, `midnightntwrk/midnight-indexer @
|
|
168
|
-
345fcc2`.
|
|
169
|
-
|
|
170
|
-
| Source | What is here that is relevant |
|
|
171
|
-
| --- | --- |
|
|
172
|
-
| [compact: `compiler/analysis-passes/expand-serialize.ss`](https://github.com/LFDT-Minokawa/compact/blob/5d8c66c/compiler/analysis-passes/expand-serialize.ss) | The generator, and the closest thing to ground truth for the serialize direction. A nanopass that expands every `serialize`/`deserialize` call site into circuit expressions: declaration-order field walk, `field->bytes` at natural widths, booleans as literal `0x00`/`0x01`, enums cast to bounded Uint, right zero-padding, and the "serialized size exceeds specified length" compile error. |
|
|
173
|
-
| [compact: PR #470](https://github.com/LFDT-Minokawa/compact/pull/470) | The origin. Commit `0b3be94` ("[Issue 377] Events, phase 1", merged 2026-06-26) introduced the expand-serialize pass inside `analysis-passes.ss` as the canonical event encoding (the standalone file split out later in #632). |
|
|
174
|
-
| [compact: `doc/release-notes/toolchain-0.33.0.md`](https://github.com/LFDT-Minokawa/compact/blob/5d8c66c/doc/release-notes/toolchain-0.33.0.md) | Prose semantics of the user-facing builtins (lines 119-127): works for all Compact types except `Opaque` and contract types, too-small `N` is a compile error, zero padding on serialize, extra trailing bytes ignored on deserialize, events use "the equivalent of `serialize<T, #n>`". |
|
|
175
|
-
| [compact: `compiler/midnight-inlines.ss#L16-L24`](https://github.com/LFDT-Minokawa/compact/blob/5d8c66c/compiler/midnight-inlines.ss#L16-L24) | Where the standard library actually declares the builtins: `serialize` and `deserialize` are registered as inline entries (`[T (nat n)] ([value T]) (Bytes n)`) that expand into the IR forms the expand-serialize pass consumes. No event-type restriction exists in code. |
|
|
176
|
-
| [compact: `doc/api/CompactStandardLibrary/exports.md#L981`](https://github.com/LFDT-Minokawa/compact/blob/5d8c66c/doc/api/CompactStandardLibrary/exports.md#L981) | The documented `circuit serialize<T, #n>` / `deserialize<T, #n>` signatures. Beware: the doc says "`serialize` can only be instantiated for an event type and its canonical serialized size" (L983-985), left over from PR #470 where serialisation existed only for events. The 0.33 compiler accepts any serializable type. |
|
|
177
|
-
| [compact: `runtime/src/compact-types.ts#L651`](https://github.com/LFDT-Minokawa/compact/blob/5d8c66c/runtime/src/compact-types.ts#L651) | `toBinaryRepr`, the undocumented TS runtime re-implementation and our second test oracle. Flattens a descriptor's `ocrt.Value` along its `Alignment` (bytes atoms zero-filled to declared width, field atoms to 32 bytes, compress atoms rejected). |
|
|
178
|
-
| [Compact language reference](https://docs.midnight.network/compact/reference/compact-reference) | The type system: exclusive `Uint<0..n>` bounds, TS representations of each type, implementation limits. |
|
|
179
|
-
| [midnight-ledger: `spec/field-aligned-binary.md`](https://github.com/midnightntwrk/midnight-ledger/blob/e1edad2/spec/field-aligned-binary.md) | The normative FAB spec. It covers two encodings, and only one is ours: the self-describing flagged-int wire format is NOT the `serialize<T, N>` layout, the binary representation of atoms is. The high-level mapping section (lines 186-218) pins declaration-order struct encoding and explicitly assigns the Compact-type-to-FAB mapping to the compiler. |
|
|
180
|
-
| [midnight-ledger: `base-crypto/src/fab/`](https://github.com/midnightntwrk/midnight-ledger/tree/e1edad2/base-crypto/src/fab) | The core FAB data model (`transient-crypto/src/fab.rs` only extends it): `Value`, `ValueAtom`, `Alignment`, `AlignmentAtom`, `AlignedValue` in `encoding.rs`, normal form via trailing-zero strip, declaration-order tuple concat in `alignments.rs`, little-endian integer conversions in `conversions.rs`. |
|
|
181
|
-
| [midnight-ledger: `transient-crypto/src/fab.rs`](https://github.com/midnightntwrk/midnight-ledger/blob/e1edad2/transient-crypto/src/fab.rs) | The byte layout as Rust: the `ValueExt` trait (L35), the `Value::binary_repr_unchecked` traversal with zero-fill padding (L273), and the per-atom byte rules in `ValueAtomExt::binary_repr_unchecked` (L513): `Bytes{n}` as raw LE bytes zero-filled to `n`, `Field` as 32 bytes, `Compress` as a 32-byte Poseidon commitment. |
|
|
182
|
-
| [midnight-ledger: `base-crypto/src/hash.rs`](https://github.com/midnightntwrk/midnight-ledger/blob/e1edad2/base-crypto/src/hash.rs) and [`zkir-v3/src/ir_vm.rs`](https://github.com/midnightntwrk/midnight-ledger/blob/e1edad2/zkir-v3/src/ir_vm.rs) | Proof the layout is load-bearing: `persistent_hash` is SHA-256 over exactly these bytes (`ValueReprAlignedValue(value).binary_repr` at `ir_vm.rs` L524), and `fab_decode_to_bytes` (L80-181) is the in-circuit mirror of the same atom rules. |
|
|
183
|
-
| [midnight-sdk: `compact-js/compact-js/src/effect/ContractLog.ts`](https://github.com/midnightntwrk/midnight-sdk/blob/80e6707/compact-js/compact-js/src/effect/ContractLog.ts) | Hand-rolled decode of the eleven built-in ledger events from this same layout, decode only: 65-byte `Either` as `[is_left:1][left:32][right:32]`, little-endian `Uint<128>`. |
|
|
184
|
-
| [midnight-indexer: `indexer-common/src/domain/ledger/ledger_state.rs`](https://github.com/midnightntwrk/midnight-indexer/blob/345fcc2/indexer-common/src/domain/ledger/ledger_state.rs) | Midnight's production Rust decoder of the same event payload bytes, the reference `ContractLog.ts` itself calls authoritative (`EITHER_SIZE = 1 + 2 * 32`, `make_contract_event_attributes`). |
|
|
56
|
+
- [Borsh specification](https://borsh.io/#specification)
|
|
57
|
+
- [borsh-js](https://github.com/near/borsh-js)
|
|
58
|
+
- [Rust Borsh](https://docs.rs/borsh/1.8.1/borsh/)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
3
|
-
|
|
4
|
-
export
|
|
1
|
+
import { deserialize, type Schema } from "borsh";
|
|
2
|
+
export type { Schema } from "borsh";
|
|
3
|
+
/** Values accepted by the native Borsh decoder and encoder. */
|
|
4
|
+
export type BorshValue = ReturnType<typeof deserialize>;
|
|
5
|
+
/**
|
|
6
|
+
* Encode a value using borsh-js, optionally extending the output with zero padding.
|
|
7
|
+
*
|
|
8
|
+
* @param schema - Native borsh-js schema.
|
|
9
|
+
* @param value - Value in the representation required by borsh-js.
|
|
10
|
+
* @param length - Optional total output length.
|
|
11
|
+
* @returns Borsh bytes with optional trailing zeros.
|
|
12
|
+
* @throws {Error} If Borsh rejects the input or the requested length is invalid or too small.
|
|
13
|
+
*/
|
|
14
|
+
export declare function compactSerialize(schema: Schema, value: BorshValue, length?: number): Uint8Array;
|
|
15
|
+
/**
|
|
16
|
+
* Decode using borsh-js, including its native trailing-byte behaviour.
|
|
17
|
+
*
|
|
18
|
+
* @param schema - Native borsh-js schema.
|
|
19
|
+
* @param bytes - Borsh bytes, optionally followed by padding.
|
|
20
|
+
* @returns The value returned by borsh-js.
|
|
21
|
+
* @throws {Error} If Borsh rejects the schema or bytes.
|
|
22
|
+
*/
|
|
23
|
+
export declare function compactDeserialize(schema: Schema, bytes: Uint8Array): BorshValue;
|
|
5
24
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,MAAM,EAAa,MAAM,OAAO,CAAC;AAE5D,YAAY,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAEpC,+DAA+D;AAC/D,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAExD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU,CAW/F;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,UAAU,CAEhF"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { deserialize, serialize } from "borsh";
|
|
2
|
+
/**
|
|
3
|
+
* Encode a value using borsh-js, optionally extending the output with zero padding.
|
|
4
|
+
*
|
|
5
|
+
* @param schema - Native borsh-js schema.
|
|
6
|
+
* @param value - Value in the representation required by borsh-js.
|
|
7
|
+
* @param length - Optional total output length.
|
|
8
|
+
* @returns Borsh bytes with optional trailing zeros.
|
|
9
|
+
* @throws {Error} If Borsh rejects the input or the requested length is invalid or too small.
|
|
10
|
+
*/
|
|
11
|
+
export function compactSerialize(schema, value, length) {
|
|
12
|
+
const bytes = serialize(schema, value);
|
|
13
|
+
if (length === undefined)
|
|
14
|
+
return bytes;
|
|
15
|
+
if (!Number.isSafeInteger(length) || length < bytes.length) {
|
|
16
|
+
throw new RangeError("Output length must be an integer at least as large as the Borsh encoding");
|
|
17
|
+
}
|
|
18
|
+
const padded = new Uint8Array(length);
|
|
19
|
+
padded.set(bytes);
|
|
20
|
+
return padded;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Decode using borsh-js, including its native trailing-byte behaviour.
|
|
24
|
+
*
|
|
25
|
+
* @param schema - Native borsh-js schema.
|
|
26
|
+
* @param bytes - Borsh bytes, optionally followed by padding.
|
|
27
|
+
* @returns The value returned by borsh-js.
|
|
28
|
+
* @throws {Error} If Borsh rejects the schema or bytes.
|
|
29
|
+
*/
|
|
30
|
+
export function compactDeserialize(schema, bytes) {
|
|
31
|
+
return deserialize(schema, bytes);
|
|
32
|
+
}
|
|
5
33
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAe,SAAS,EAAE,MAAM,OAAO,CAAC;AAO5D;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,KAAiB,EAAE,MAAe;IACjF,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACvC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACvC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAC3D,MAAM,IAAI,UAAU,CAClB,0EAA0E,CAC3E,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACtC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAClB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,KAAiB;IAClE,OAAO,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACpC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sig-net/midnight-serde",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0-rc.10",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/sig-net/midnight-integration",
|
|
7
|
-
"directory": "packages/midnight-serde"
|
|
7
|
+
"directory": "packages/midnight-serde-ts"
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
|
-
"description": "
|
|
10
|
+
"description": "Native Borsh serialisation with optional zero padding for Midnight callers.",
|
|
11
11
|
"//exports": "Local dev consumes raw TS source. `publishConfig.exports` below swaps this to the emitted ./dist at publish time, so npm consumers get JS + .d.ts while the monorepo keeps resolving to src.",
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
"dist"
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
|
-
"compile": "compact compile --skip-zk --feature-zkir-v3 tests/fixtures/serde-fixtures.compact tests/fixtures/managed",
|
|
23
22
|
"build": "rm -rf dist && tsc -p tsconfig.json && tsc -p tsconfig.build.json",
|
|
24
23
|
"prepack": "yarn build",
|
|
25
24
|
"test": "vitest run"
|
|
@@ -36,13 +35,15 @@
|
|
|
36
35
|
}
|
|
37
36
|
},
|
|
38
37
|
"devDependencies": {
|
|
39
|
-
"@midnight-ntwrk/compact-runtime": "0.18.0-rc.1",
|
|
40
38
|
"@types/node": "^26.1.0",
|
|
41
39
|
"@vitest/coverage-v8": "^5.0.0",
|
|
42
40
|
"typescript": "^7.0.2",
|
|
43
41
|
"vite": "^8.2.2",
|
|
44
42
|
"vitest": "^5.0.0"
|
|
45
43
|
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"borsh": "2.0.0"
|
|
46
|
+
},
|
|
46
47
|
"main": "./dist/index.js",
|
|
47
48
|
"types": "./dist/index.d.ts"
|
|
48
49
|
}
|
package/dist/deserialize.d.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { CompactType, CompactValueOf } from "./types.ts";
|
|
2
|
-
/** Options controlling how strictly {@link compactDeserialize} reads a value. */
|
|
3
|
-
export interface CompactDeserializeOptions {
|
|
4
|
-
/** Skip the all-zero check on bytes after the packed value (circuit behaviour). */
|
|
5
|
-
ignorePadding?: boolean;
|
|
6
|
-
/**
|
|
7
|
-
* Decode boolean bytes above 0x01 as false instead of throwing (circuit
|
|
8
|
-
* behaviour: only 0x01 is true, anything else is false).
|
|
9
|
-
*/
|
|
10
|
-
lenientBooleans?: boolean;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Inverse of `compactSerialize`: decode the packed prefix of `bytes`.
|
|
14
|
-
*
|
|
15
|
-
* The return type is derived from the descriptor (see `CompactValueOf`), so a
|
|
16
|
-
* literal descriptor yields a fully typed value with no cast at the call site.
|
|
17
|
-
*
|
|
18
|
-
* @param type - The descriptor describing the packed layout.
|
|
19
|
-
* @param bytes - Buffer whose prefix holds the packed value.
|
|
20
|
-
* @param options - Decode options; see {@link CompactDeserializeOptions}.
|
|
21
|
-
* @returns The decoded value, shaped by the descriptor.
|
|
22
|
-
* @throws {Error} If the descriptor is malformed, the buffer is too short, or a
|
|
23
|
-
* decoded value falls outside its declared range.
|
|
24
|
-
*/
|
|
25
|
-
export declare function compactDeserialize<const T extends CompactType>(type: T, bytes: Uint8Array, options?: CompactDeserializeOptions): CompactValueOf<T>;
|
|
26
|
-
//# sourceMappingURL=deserialize.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deserialize.d.ts","sourceRoot":"","sources":["../src/deserialize.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,WAAW,EAAgB,cAAc,EAAE,MAAM,YAAY,CAAC;AAI5E,iFAAiF;AACjF,MAAM,WAAW,yBAAyB;IACxC,mFAAmF;IACnF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAcD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,CAAC,SAAS,WAAW,EAC5D,IAAI,EAAE,CAAC,EACP,KAAK,EAAE,UAAU,EACjB,OAAO,GAAE,yBAA8B,GACtC,cAAc,CAAC,CAAC,CAAC,CA2BnB"}
|
package/dist/deserialize.js
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
// Byte-exact twin of Compact's builtin `deserialize<T, N>` from
|
|
2
|
-
// CompactStandardLibrary, pinned against compiled circuits by tests/.
|
|
3
|
-
//
|
|
4
|
-
// Two deliberate divergences from the circuit, both strict-by-default
|
|
5
|
-
// (garbage in a buffer means corruption or mis-framing, and failing loudly
|
|
6
|
-
// off-chain is the safer default), and both with an opt-out:
|
|
7
|
-
// - PADDING: the circuit IGNORES bytes in the padding region entirely
|
|
8
|
-
// (pinned by tests), while this decoder rejects non-zero padding. Pass
|
|
9
|
-
// `{ ignorePadding: true }` to mirror the circuit.
|
|
10
|
-
// - BOOLEANS: the circuit decodes ANY byte other than 0x01 as false, so
|
|
11
|
-
// 0x02..0xff all quietly become false (pinned by tests), while this
|
|
12
|
-
// decoder rejects bytes above 1. Pass `{ lenientBooleans: true }` to
|
|
13
|
-
// mirror the circuit.
|
|
14
|
-
// With both options set the decode is circuit-exact. Circuit-produced bytes
|
|
15
|
-
// never trigger either divergence: `serialize<T, N>` only writes zero padding
|
|
16
|
-
// and 0x00/0x01 booleans.
|
|
17
|
-
//
|
|
18
|
-
// Everything else mirrors the circuit exactly, including its rejections: the
|
|
19
|
-
// descriptor is fully validated (src/validate.ts) and the input buffer
|
|
20
|
-
// type-checked before any decoding, and out-of-range Uint, enum and Field
|
|
21
|
-
// encodings all throw exactly where the circuit throws (pinned by tests).
|
|
22
|
-
import { packedSize, uintBound, uintName } from "./serialize.js";
|
|
23
|
-
import { FIELD_MODULUS } from "./types.js";
|
|
24
|
-
import { assertCompactType, assertUnreachable, isUint8Array } from "./validate.js";
|
|
25
|
-
// Zero-width elements (empty structs/tuples, `Uint<0..1>`, single-variant
|
|
26
|
-
// enums, `Bytes<0>`) consume no input, so a vector of them decodes purely
|
|
27
|
-
// from the descriptor: a validated-but-hostile `Vector<10^15, Nothing>`
|
|
28
|
-
// would loop forever on an EMPTY buffer. No real circuit is anywhere near
|
|
29
|
-
// this many zero-width elements, so cap them rather than hang.
|
|
30
|
-
const MAX_ZERO_WIDTH_ELEMENTS = 65536;
|
|
31
|
-
/**
|
|
32
|
-
* Inverse of `compactSerialize`: decode the packed prefix of `bytes`.
|
|
33
|
-
*
|
|
34
|
-
* The return type is derived from the descriptor (see `CompactValueOf`), so a
|
|
35
|
-
* literal descriptor yields a fully typed value with no cast at the call site.
|
|
36
|
-
*
|
|
37
|
-
* @param type - The descriptor describing the packed layout.
|
|
38
|
-
* @param bytes - Buffer whose prefix holds the packed value.
|
|
39
|
-
* @param options - Decode options; see {@link CompactDeserializeOptions}.
|
|
40
|
-
* @returns The decoded value, shaped by the descriptor.
|
|
41
|
-
* @throws {Error} If the descriptor is malformed, the buffer is too short, or a
|
|
42
|
-
* decoded value falls outside its declared range.
|
|
43
|
-
*/
|
|
44
|
-
export function compactDeserialize(type, bytes, options = {}) {
|
|
45
|
-
assertCompactType(type);
|
|
46
|
-
if (!isUint8Array(bytes)) {
|
|
47
|
-
throw new Error("bytes must be a Uint8Array");
|
|
48
|
-
}
|
|
49
|
-
// One size check up front covers every read below: fields and elements
|
|
50
|
-
// tile the packed prefix exactly, so no per-node re-check is needed.
|
|
51
|
-
const need = packedSize(type);
|
|
52
|
-
if (need > bytes.length) {
|
|
53
|
-
throw new Error(`value: needs ${String(need)} bytes, buffer has ${String(bytes.length)}`);
|
|
54
|
-
}
|
|
55
|
-
const context = {
|
|
56
|
-
lenientBooleans: options.lenientBooleans === true,
|
|
57
|
-
zeroWidthElements: 0,
|
|
58
|
-
};
|
|
59
|
-
const [value, consumed] = decodeFrom(bytes, 0, type, "value", context);
|
|
60
|
-
if (!options.ignorePadding) {
|
|
61
|
-
for (const [i, padding] of bytes.subarray(consumed).entries()) {
|
|
62
|
-
if (padding !== 0) {
|
|
63
|
-
throw new Error(`non-zero padding byte 0x${padding.toString(16)} at offset ${String(consumed + i)} ` +
|
|
64
|
-
`(pass ignorePadding to mirror the circuit, which reads only the packed prefix)`);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return value;
|
|
69
|
-
}
|
|
70
|
-
function decodeFrom(bytes, offset, type, label, context) {
|
|
71
|
-
switch (type.kind) {
|
|
72
|
-
case "boolean": {
|
|
73
|
-
const b = bytes[offset];
|
|
74
|
-
if (b === undefined) {
|
|
75
|
-
throw new Error(`${label}: buffer ends before the boolean byte at ${String(offset)}`);
|
|
76
|
-
}
|
|
77
|
-
// Strict by default; the circuit decodes any byte != 0x01 as false
|
|
78
|
-
// (see the header comment).
|
|
79
|
-
if (b > 1 && !context.lenientBooleans) {
|
|
80
|
-
throw new Error(`${label}: invalid boolean byte 0x${b.toString(16)}`);
|
|
81
|
-
}
|
|
82
|
-
return [b === 1, offset + 1];
|
|
83
|
-
}
|
|
84
|
-
case "uint": {
|
|
85
|
-
const bound = uintBound(type);
|
|
86
|
-
const size = packedSize(type);
|
|
87
|
-
const value = readUintLE(bytes, offset, size);
|
|
88
|
-
// Mirrors the circuit, which rejects encodings at or above the bound
|
|
89
|
-
// (pinned by tests via the Bounded, Wide and U12 fixtures). Reachable
|
|
90
|
-
// for any bounded uint whose max is not all-ones, and for sized uints
|
|
91
|
-
// only when the width is not byte-aligned.
|
|
92
|
-
if (value >= bound) {
|
|
93
|
-
throw new Error(`${label}: encoding ${String(value)} exceeds ${uintName(type)}`);
|
|
94
|
-
}
|
|
95
|
-
return [value, offset + size];
|
|
96
|
-
}
|
|
97
|
-
case "field": {
|
|
98
|
-
const value = readUintLE(bytes, offset, 32);
|
|
99
|
-
// The circuit rejects out-of-range Field encodings at runtime too
|
|
100
|
-
// (pinned by tests): mirror it.
|
|
101
|
-
if (value >= FIELD_MODULUS) {
|
|
102
|
-
throw new Error(`${label}: encoding ${String(value)} is not below the Field modulus`);
|
|
103
|
-
}
|
|
104
|
-
return [value, offset + 32];
|
|
105
|
-
}
|
|
106
|
-
case "bytes":
|
|
107
|
-
// A copy into a PLAIN Uint8Array, never `bytes.slice(...)`: subclasses
|
|
108
|
-
// may override slice with a non-copying view (Buffer does), and a
|
|
109
|
-
// decoded value must not alias caller memory the caller may reuse.
|
|
110
|
-
return [new Uint8Array(bytes.subarray(offset, offset + type.length)), offset + type.length];
|
|
111
|
-
case "enum": {
|
|
112
|
-
const size = packedSize(type);
|
|
113
|
-
const value = readUintLE(bytes, offset, size);
|
|
114
|
-
// Mirrors the circuit's variant-index range check (pinned by tests).
|
|
115
|
-
if (value >= BigInt(type.variants)) {
|
|
116
|
-
throw new Error(`${label}: encoding ${String(value)} exceeds the last variant index ${String(type.variants - 1)}`);
|
|
117
|
-
}
|
|
118
|
-
return [Number(value), offset + size];
|
|
119
|
-
}
|
|
120
|
-
case "vector": {
|
|
121
|
-
if (packedSize(type.element) === 0) {
|
|
122
|
-
context.zeroWidthElements += type.length;
|
|
123
|
-
if (context.zeroWidthElements > MAX_ZERO_WIDTH_ELEMENTS) {
|
|
124
|
-
throw new Error(`${label}: refusing to materialise over ${String(MAX_ZERO_WIDTH_ELEMENTS)} ` +
|
|
125
|
-
`zero-width vector elements (the descriptor decodes them from no input at all)`);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
const elements = [];
|
|
129
|
-
let cursor = offset;
|
|
130
|
-
for (let i = 0; i < type.length; i++) {
|
|
131
|
-
const [element, next] = decodeFrom(bytes, cursor, type.element, `${label}[${String(i)}]`, context);
|
|
132
|
-
elements.push(element);
|
|
133
|
-
cursor = next;
|
|
134
|
-
}
|
|
135
|
-
return [elements, cursor];
|
|
136
|
-
}
|
|
137
|
-
case "tuple": {
|
|
138
|
-
const elements = [];
|
|
139
|
-
let cursor = offset;
|
|
140
|
-
type.elements.forEach((element, i) => {
|
|
141
|
-
const [decoded, next] = decodeFrom(bytes, cursor, element, `${label}[${String(i)}]`, context);
|
|
142
|
-
elements.push(decoded);
|
|
143
|
-
cursor = next;
|
|
144
|
-
});
|
|
145
|
-
return [elements, cursor];
|
|
146
|
-
}
|
|
147
|
-
case "struct": {
|
|
148
|
-
const value = {};
|
|
149
|
-
let cursor = offset;
|
|
150
|
-
for (const field of type.fields) {
|
|
151
|
-
const [fieldValue, next] = decodeFrom(bytes, cursor, field.type, `${label}.${field.name}`, context);
|
|
152
|
-
// defineProperty, not assignment: a field named '__proto__' is a
|
|
153
|
-
// legal Compact identifier, and plain assignment would hit the
|
|
154
|
-
// prototype setter and silently drop it.
|
|
155
|
-
Object.defineProperty(value, field.name, {
|
|
156
|
-
value: fieldValue,
|
|
157
|
-
enumerable: true,
|
|
158
|
-
writable: true,
|
|
159
|
-
configurable: true,
|
|
160
|
-
});
|
|
161
|
-
cursor = next;
|
|
162
|
-
}
|
|
163
|
-
return [value, cursor];
|
|
164
|
-
}
|
|
165
|
-
default:
|
|
166
|
-
return assertUnreachable(type, label);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
function readUintLE(bytes, offset, size) {
|
|
170
|
-
let v = 0n;
|
|
171
|
-
let shift = 0n;
|
|
172
|
-
for (const byte of bytes.subarray(offset, offset + size)) {
|
|
173
|
-
v |= BigInt(byte) << shift;
|
|
174
|
-
shift += 8n;
|
|
175
|
-
}
|
|
176
|
-
return v;
|
|
177
|
-
}
|
|
178
|
-
//# sourceMappingURL=deserialize.js.map
|
package/dist/deserialize.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deserialize.js","sourceRoot":"","sources":["../src/deserialize.ts"],"names":[],"mappings":"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"}
|