@thru/programs 0.2.22 → 0.2.23
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/dist/multicall/index.cjs +2579 -0
- package/dist/multicall/index.cjs.map +1 -0
- package/dist/multicall/index.d.cts +253 -0
- package/dist/multicall/index.d.ts +253 -0
- package/dist/multicall/index.js +2573 -0
- package/dist/multicall/index.js.map +1 -0
- package/dist/passkey-manager/index.cjs +582 -706
- package/dist/passkey-manager/index.cjs.map +1 -1
- package/dist/passkey-manager/index.d.cts +20 -14
- package/dist/passkey-manager/index.d.ts +20 -14
- package/dist/passkey-manager/index.js +551 -673
- package/dist/passkey-manager/index.js.map +1 -1
- package/package.json +7 -2
- package/src/multicall/abi/thru/common/primitives/types.ts +2265 -0
- package/src/multicall/abi/thru/program/multicall/types.ts +1232 -0
- package/src/multicall/index.test.ts +46 -0
- package/src/multicall/index.ts +81 -0
- package/src/passkey-manager/abi/thru/blockchain/state_proof/types.ts +95 -19
- package/src/passkey-manager/abi/thru/common/primitives/types.ts +111 -37
- package/src/passkey-manager/abi/thru/program/passkey_manager/types.ts +248 -660
- package/src/passkey-manager/challenge.ts +52 -12
- package/src/passkey-manager/constants.ts +0 -1
- package/src/passkey-manager/index.ts +4 -4
- package/src/passkey-manager/instructions/add-authority.ts +8 -2
- package/src/passkey-manager/instructions/remove-authority.ts +9 -2
- package/src/passkey-manager/instructions/validate.ts +60 -14
- package/src/passkey-manager/target-instruction.ts +29 -0
- package/src/passkey-manager/types.ts +16 -0
- package/src/passkey-manager/validate.test.ts +173 -0
- package/tsup.config.ts +1 -0
- package/src/passkey-manager/instructions/invoke.ts +0 -25
- package/src/passkey-manager/instructions/shared.ts +0 -12
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
MULTICALL_PROGRAM_ADDRESS,
|
|
4
|
+
MULTICALL_PROGRAM_PUBKEY,
|
|
5
|
+
InstructionDataBuilder,
|
|
6
|
+
MulticallArgs,
|
|
7
|
+
buildMulticallInstruction,
|
|
8
|
+
} from './index';
|
|
9
|
+
|
|
10
|
+
function instructionData(programIdx: number, data: Uint8Array): number[] {
|
|
11
|
+
const builder = new InstructionDataBuilder();
|
|
12
|
+
builder.set_program_idx(programIdx);
|
|
13
|
+
builder.data().write(data).finish();
|
|
14
|
+
return Array.from(builder.build());
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe('multicall helpers', () => {
|
|
18
|
+
it('encodes calls with generated InstructionData views', () => {
|
|
19
|
+
expect(MULTICALL_PROGRAM_ADDRESS).toBe(
|
|
20
|
+
'taAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkJ'
|
|
21
|
+
);
|
|
22
|
+
expect(MULTICALL_PROGRAM_PUBKEY[31]).toBe(9);
|
|
23
|
+
|
|
24
|
+
const encoded = buildMulticallInstruction([
|
|
25
|
+
{ programIdx: 2, instructionData: new Uint8Array([0xaa]) },
|
|
26
|
+
{ programIdx: 5, instructionData: new Uint8Array([0xbb, 0xcc]) },
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
expect(encoded).toEqual(
|
|
30
|
+
new Uint8Array([
|
|
31
|
+
0x02, 0x00,
|
|
32
|
+
...instructionData(2, new Uint8Array([0xaa])),
|
|
33
|
+
...instructionData(5, new Uint8Array([0xbb, 0xcc])),
|
|
34
|
+
])
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const validation = MulticallArgs.validate(encoded);
|
|
38
|
+
expect(validation).toMatchObject({ ok: true, consumed: encoded.length });
|
|
39
|
+
|
|
40
|
+
const view = MulticallArgs.from_array(encoded);
|
|
41
|
+
expect(view?.get_calls_count()).toBe(2);
|
|
42
|
+
const calls = view?.get_calls();
|
|
43
|
+
expect(calls?.map((call) => call.get_program_idx())).toEqual([2, 5]);
|
|
44
|
+
expect(calls?.map((call) => call.get_data())).toEqual([[0xaa], [0xbb, 0xcc]]);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { encodeAddress } from '@thru/sdk/helpers';
|
|
2
|
+
import {
|
|
3
|
+
InstructionData,
|
|
4
|
+
InstructionDataBuilder,
|
|
5
|
+
} from './abi/thru/common/primitives/types';
|
|
6
|
+
import { MulticallArgs } from './abi/thru/program/multicall/types';
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
InstructionData,
|
|
10
|
+
InstructionDataBuilder,
|
|
11
|
+
} from './abi/thru/common/primitives/types';
|
|
12
|
+
export {
|
|
13
|
+
MulticallArgs,
|
|
14
|
+
MulticallError,
|
|
15
|
+
} from './abi/thru/program/multicall/types';
|
|
16
|
+
|
|
17
|
+
export type MulticallCall = {
|
|
18
|
+
programIdx: number;
|
|
19
|
+
instructionData: Uint8Array;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const MULTICALL_PROGRAM_PUBKEY = new Uint8Array([
|
|
23
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
export const MULTICALL_PROGRAM_ADDRESS = encodeAddress(MULTICALL_PROGRAM_PUBKEY);
|
|
27
|
+
|
|
28
|
+
function writeU16LE(target: Uint8Array, offset: number, value: number): void {
|
|
29
|
+
target[offset] = value & 0xff;
|
|
30
|
+
target[offset + 1] = (value >> 8) & 0xff;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function assertProgramIdx(programIdx: number): void {
|
|
34
|
+
if (!Number.isInteger(programIdx) || programIdx < 0 || programIdx > 0xffff) {
|
|
35
|
+
throw new Error('programIdx must be 0-65535');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function buildInstructionData(call: MulticallCall): Uint8Array {
|
|
40
|
+
assertProgramIdx(call.programIdx);
|
|
41
|
+
if (!(call.instructionData instanceof Uint8Array)) {
|
|
42
|
+
throw new Error('instructionData must be a Uint8Array');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const builder = new InstructionDataBuilder();
|
|
46
|
+
builder.set_program_idx(call.programIdx);
|
|
47
|
+
builder.data().write(call.instructionData).finish();
|
|
48
|
+
const buffer = builder.build();
|
|
49
|
+
const view = InstructionData.from_array(buffer);
|
|
50
|
+
if (!view) {
|
|
51
|
+
throw new Error('generated InstructionData failed validation');
|
|
52
|
+
}
|
|
53
|
+
return buffer;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function buildMulticallInstruction(calls: MulticallCall[]): Uint8Array {
|
|
57
|
+
if (!Array.isArray(calls)) throw new Error('calls must be an array');
|
|
58
|
+
if (calls.length > 0xffff) throw new Error('calls length must be 0-65535');
|
|
59
|
+
|
|
60
|
+
const encodedCalls = calls.map(buildInstructionData);
|
|
61
|
+
const totalLength = 2 + encodedCalls.reduce((sum, call) => sum + call.length, 0);
|
|
62
|
+
|
|
63
|
+
const output = new Uint8Array(totalLength);
|
|
64
|
+
let offset = 0;
|
|
65
|
+
writeU16LE(output, offset, calls.length);
|
|
66
|
+
offset += 2;
|
|
67
|
+
|
|
68
|
+
for (const call of encodedCalls) {
|
|
69
|
+
output.set(call, offset);
|
|
70
|
+
offset += call.length;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const validation = MulticallArgs.validate(output);
|
|
74
|
+
if (!validation.ok || validation.consumed !== output.length) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
`generated MulticallArgs failed validation (code=${validation.code ?? 'unknown'})`
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return output;
|
|
81
|
+
}
|
|
@@ -32,6 +32,12 @@ type __TnIrNode =
|
|
|
32
32
|
readonly op: "call";
|
|
33
33
|
readonly typeName: string;
|
|
34
34
|
readonly args: readonly { readonly name: string; readonly source: string }[];
|
|
35
|
+
}
|
|
36
|
+
| {
|
|
37
|
+
readonly op: "sumOverArray";
|
|
38
|
+
readonly count: __TnIrNode;
|
|
39
|
+
readonly elementTypeName: string;
|
|
40
|
+
readonly fieldName: string;
|
|
35
41
|
};
|
|
36
42
|
|
|
37
43
|
type __TnIrContext = {
|
|
@@ -517,6 +523,10 @@ const __tnValidateRegistry: Record<
|
|
|
517
523
|
string,
|
|
518
524
|
(buffer: Uint8Array, params: Record<string, bigint>) => __TnValidateResult
|
|
519
525
|
> = {};
|
|
526
|
+
const __tnDynamicValidateRegistry: Record<
|
|
527
|
+
string,
|
|
528
|
+
(buffer: Uint8Array) => __TnValidateResult
|
|
529
|
+
> = {};
|
|
520
530
|
|
|
521
531
|
function __tnRegisterFootprint(
|
|
522
532
|
typeName: string,
|
|
@@ -532,6 +542,13 @@ function __tnRegisterValidate(
|
|
|
532
542
|
__tnValidateRegistry[typeName] = fn;
|
|
533
543
|
}
|
|
534
544
|
|
|
545
|
+
function __tnRegisterDynamicValidate(
|
|
546
|
+
typeName: string,
|
|
547
|
+
fn: (buffer: Uint8Array) => __TnValidateResult
|
|
548
|
+
): void {
|
|
549
|
+
__tnDynamicValidateRegistry[typeName] = fn;
|
|
550
|
+
}
|
|
551
|
+
|
|
535
552
|
function __tnInvokeFootprint(
|
|
536
553
|
typeName: string,
|
|
537
554
|
params: Record<string, bigint>
|
|
@@ -551,8 +568,17 @@ function __tnInvokeValidate(
|
|
|
551
568
|
return fn(buffer, params);
|
|
552
569
|
}
|
|
553
570
|
|
|
571
|
+
function __tnInvokeDynamicValidate(
|
|
572
|
+
typeName: string,
|
|
573
|
+
buffer: Uint8Array
|
|
574
|
+
): __TnValidateResult {
|
|
575
|
+
const fn = __tnDynamicValidateRegistry[typeName];
|
|
576
|
+
if (!fn) throw new Error(`IR runtime missing dynamic validate helper for ${typeName}`);
|
|
577
|
+
return fn(buffer);
|
|
578
|
+
}
|
|
579
|
+
|
|
554
580
|
function __tnEvalFootprint(node: __TnIrNode, ctx: __TnIrContext): bigint {
|
|
555
|
-
return __tnEvalIrNode(node, ctx);
|
|
581
|
+
return __tnEvalIrNode(node, ctx, __tnToBigInt(0));
|
|
556
582
|
}
|
|
557
583
|
|
|
558
584
|
function __tnTryEvalFootprint(
|
|
@@ -567,7 +593,7 @@ function __tnTryEvalIr(
|
|
|
567
593
|
ctx: __TnIrContext
|
|
568
594
|
): __TnEvalResult {
|
|
569
595
|
try {
|
|
570
|
-
return { ok: true, value: __tnEvalIrNode(node, ctx) };
|
|
596
|
+
return { ok: true, value: __tnEvalIrNode(node, ctx, __tnToBigInt(0)) };
|
|
571
597
|
} catch (err) {
|
|
572
598
|
return { ok: false, code: __tnNormalizeIrError(err) };
|
|
573
599
|
}
|
|
@@ -598,7 +624,11 @@ function __tnValidateIrTree(
|
|
|
598
624
|
return { ok: true, consumed: required };
|
|
599
625
|
}
|
|
600
626
|
|
|
601
|
-
function __tnEvalIrNode(
|
|
627
|
+
function __tnEvalIrNode(
|
|
628
|
+
node: __TnIrNode,
|
|
629
|
+
ctx: __TnIrContext,
|
|
630
|
+
baseOffset: bigint
|
|
631
|
+
): bigint {
|
|
602
632
|
switch (node.op) {
|
|
603
633
|
case "zero":
|
|
604
634
|
return __tnToBigInt(0);
|
|
@@ -616,17 +646,22 @@ function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
|
|
|
616
646
|
return val;
|
|
617
647
|
}
|
|
618
648
|
case "add":
|
|
619
|
-
|
|
620
|
-
__tnEvalIrNode(node.left, ctx)
|
|
621
|
-
__tnEvalIrNode(
|
|
622
|
-
|
|
649
|
+
{
|
|
650
|
+
const left = __tnEvalIrNode(node.left, ctx, baseOffset);
|
|
651
|
+
const right = __tnEvalIrNode(
|
|
652
|
+
node.right,
|
|
653
|
+
ctx,
|
|
654
|
+
__tnCheckedAdd(baseOffset, left)
|
|
655
|
+
);
|
|
656
|
+
return __tnCheckedAdd(left, right);
|
|
657
|
+
}
|
|
623
658
|
case "mul":
|
|
624
659
|
return __tnCheckedMul(
|
|
625
|
-
__tnEvalIrNode(node.left, ctx),
|
|
626
|
-
__tnEvalIrNode(node.right, ctx)
|
|
660
|
+
__tnEvalIrNode(node.left, ctx, baseOffset),
|
|
661
|
+
__tnEvalIrNode(node.right, ctx, baseOffset)
|
|
627
662
|
);
|
|
628
663
|
case "align":
|
|
629
|
-
return __tnAlign(__tnEvalIrNode(node.node, ctx), node.alignment);
|
|
664
|
+
return __tnAlign(__tnEvalIrNode(node.node, ctx, baseOffset), node.alignment);
|
|
630
665
|
case "switch": {
|
|
631
666
|
const tagVal = ctx.params[node.tag];
|
|
632
667
|
if (tagVal === undefined) {
|
|
@@ -639,10 +674,10 @@ function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
|
|
|
639
674
|
const tagNumber = Number(tagVal);
|
|
640
675
|
for (const caseNode of node.cases) {
|
|
641
676
|
if (caseNode.value === tagNumber) {
|
|
642
|
-
return __tnEvalIrNode(caseNode.node, ctx);
|
|
677
|
+
return __tnEvalIrNode(caseNode.node, ctx, baseOffset);
|
|
643
678
|
}
|
|
644
679
|
}
|
|
645
|
-
if (node.default) return __tnEvalIrNode(node.default, ctx);
|
|
680
|
+
if (node.default) return __tnEvalIrNode(node.default, ctx, baseOffset);
|
|
646
681
|
__tnRaiseIrError(
|
|
647
682
|
"tn.ir.invalid_tag",
|
|
648
683
|
`Unhandled IR switch value ${tagNumber} for '${node.tag}'`
|
|
@@ -662,9 +697,10 @@ function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
|
|
|
662
697
|
nestedParams[arg.name] = val;
|
|
663
698
|
}
|
|
664
699
|
if (ctx.buffer) {
|
|
700
|
+
const nestedOffset = __tnBigIntToNumber(baseOffset, "IR nested offset");
|
|
665
701
|
const nestedResult = __tnInvokeValidate(
|
|
666
702
|
node.typeName,
|
|
667
|
-
ctx.buffer,
|
|
703
|
+
ctx.buffer.subarray(nestedOffset),
|
|
668
704
|
nestedParams
|
|
669
705
|
);
|
|
670
706
|
if (!nestedResult.ok) {
|
|
@@ -684,6 +720,36 @@ function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
|
|
|
684
720
|
}
|
|
685
721
|
return __tnInvokeFootprint(node.typeName, nestedParams);
|
|
686
722
|
}
|
|
723
|
+
case "sumOverArray": {
|
|
724
|
+
if (!ctx.buffer) {
|
|
725
|
+
__tnRaiseIrError(
|
|
726
|
+
"tn.ir.missing_buffer",
|
|
727
|
+
`Jagged array '${node.fieldName}' requires buffer-backed validation`
|
|
728
|
+
);
|
|
729
|
+
}
|
|
730
|
+
const count = __tnBigIntToNumber(
|
|
731
|
+
__tnEvalIrNode(node.count, ctx, baseOffset),
|
|
732
|
+
`Jagged array '${node.fieldName}' count`
|
|
733
|
+
);
|
|
734
|
+
let cursor = __tnBigIntToNumber(baseOffset, "IR jagged array offset");
|
|
735
|
+
let total = __tnToBigInt(0);
|
|
736
|
+
for (let i = 0; i < count; i++) {
|
|
737
|
+
const result = __tnInvokeDynamicValidate(
|
|
738
|
+
node.elementTypeName,
|
|
739
|
+
ctx.buffer.subarray(cursor)
|
|
740
|
+
);
|
|
741
|
+
if (!result.ok || result.consumed === undefined) {
|
|
742
|
+
const code = result.code ?? "tn.ir.runtime_error";
|
|
743
|
+
__tnRaiseIrError(
|
|
744
|
+
code,
|
|
745
|
+
`Jagged array '${node.fieldName}' element ${i} failed validation`
|
|
746
|
+
);
|
|
747
|
+
}
|
|
748
|
+
cursor += __tnBigIntToNumber(result.consumed, "IR jagged element size");
|
|
749
|
+
total = __tnCheckedAdd(total, result.consumed);
|
|
750
|
+
}
|
|
751
|
+
return total;
|
|
752
|
+
}
|
|
687
753
|
default:
|
|
688
754
|
__tnRaiseIrError(
|
|
689
755
|
"tn.ir.runtime_error",
|
|
@@ -718,6 +784,14 @@ function __tnNormalizeIrError(err: unknown): string {
|
|
|
718
784
|
return "tn.ir.runtime_error";
|
|
719
785
|
}
|
|
720
786
|
|
|
787
|
+
__tnRegisterFootprint("Hash", (params) => Hash.__tnInvokeFootprint(params));
|
|
788
|
+
__tnRegisterValidate("Hash", (buffer, params) => Hash.__tnInvokeValidate(buffer, params));
|
|
789
|
+
__tnRegisterDynamicValidate("Hash", (buffer) => { const result = Hash.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
|
|
790
|
+
|
|
791
|
+
__tnRegisterFootprint("Pubkey", (params) => Pubkey.__tnInvokeFootprint(params));
|
|
792
|
+
__tnRegisterValidate("Pubkey", (buffer, params) => Pubkey.__tnInvokeValidate(buffer, params));
|
|
793
|
+
__tnRegisterDynamicValidate("Pubkey", (buffer) => { const result = Pubkey.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
|
|
794
|
+
|
|
721
795
|
/* ----- TYPE DEFINITION FOR StateProofHeader ----- */
|
|
722
796
|
|
|
723
797
|
const __tn_ir_StateProofHeader = {
|
|
@@ -833,9 +907,6 @@ export class StateProofHeader {
|
|
|
833
907
|
|
|
834
908
|
}
|
|
835
909
|
|
|
836
|
-
__tnRegisterFootprint("StateProofHeader", (params) => StateProofHeader.__tnInvokeFootprint(params));
|
|
837
|
-
__tnRegisterValidate("StateProofHeader", (buffer, params) => StateProofHeader.__tnInvokeValidate(buffer, params));
|
|
838
|
-
|
|
839
910
|
export class StateProofHeaderBuilder {
|
|
840
911
|
private buffer: Uint8Array;
|
|
841
912
|
private view: DataView;
|
|
@@ -874,6 +945,10 @@ export class StateProofHeaderBuilder {
|
|
|
874
945
|
}
|
|
875
946
|
}
|
|
876
947
|
|
|
948
|
+
__tnRegisterFootprint("StateProofHeader", (params) => StateProofHeader.__tnInvokeFootprint(params));
|
|
949
|
+
__tnRegisterValidate("StateProofHeader", (buffer, params) => StateProofHeader.__tnInvokeValidate(buffer, params));
|
|
950
|
+
__tnRegisterDynamicValidate("StateProofHeader", (buffer) => { const result = StateProofHeader.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
|
|
951
|
+
|
|
877
952
|
/* ----- TYPE DEFINITION FOR StateProof ----- */
|
|
878
953
|
|
|
879
954
|
const __tn_ir_StateProof = {
|
|
@@ -1548,9 +1623,6 @@ export namespace StateProof {
|
|
|
1548
1623
|
}
|
|
1549
1624
|
}
|
|
1550
1625
|
|
|
1551
|
-
__tnRegisterFootprint("StateProof", (params) => StateProof.__tnInvokeFootprint(params));
|
|
1552
|
-
__tnRegisterValidate("StateProof", (buffer, params) => StateProof.__tnInvokeValidate(buffer, params));
|
|
1553
|
-
|
|
1554
1626
|
export class StateProofBuilder {
|
|
1555
1627
|
private __tnPrefixBuffer: Uint8Array;
|
|
1556
1628
|
private __tnPrefixView: DataView;
|
|
@@ -1665,3 +1737,7 @@ export class StateProofBuilder {
|
|
|
1665
1737
|
}
|
|
1666
1738
|
}
|
|
1667
1739
|
|
|
1740
|
+
__tnRegisterFootprint("StateProof", (params) => StateProof.__tnInvokeFootprint(params));
|
|
1741
|
+
__tnRegisterValidate("StateProof", (buffer, params) => StateProof.__tnInvokeValidate(buffer, params));
|
|
1742
|
+
__tnRegisterDynamicValidate("StateProof", (buffer) => { const result = StateProof.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
|
|
1743
|
+
|
|
@@ -30,6 +30,12 @@ type __TnIrNode =
|
|
|
30
30
|
readonly op: "call";
|
|
31
31
|
readonly typeName: string;
|
|
32
32
|
readonly args: readonly { readonly name: string; readonly source: string }[];
|
|
33
|
+
}
|
|
34
|
+
| {
|
|
35
|
+
readonly op: "sumOverArray";
|
|
36
|
+
readonly count: __TnIrNode;
|
|
37
|
+
readonly elementTypeName: string;
|
|
38
|
+
readonly fieldName: string;
|
|
33
39
|
};
|
|
34
40
|
|
|
35
41
|
type __TnIrContext = {
|
|
@@ -515,6 +521,10 @@ const __tnValidateRegistry: Record<
|
|
|
515
521
|
string,
|
|
516
522
|
(buffer: Uint8Array, params: Record<string, bigint>) => __TnValidateResult
|
|
517
523
|
> = {};
|
|
524
|
+
const __tnDynamicValidateRegistry: Record<
|
|
525
|
+
string,
|
|
526
|
+
(buffer: Uint8Array) => __TnValidateResult
|
|
527
|
+
> = {};
|
|
518
528
|
|
|
519
529
|
function __tnRegisterFootprint(
|
|
520
530
|
typeName: string,
|
|
@@ -530,6 +540,13 @@ function __tnRegisterValidate(
|
|
|
530
540
|
__tnValidateRegistry[typeName] = fn;
|
|
531
541
|
}
|
|
532
542
|
|
|
543
|
+
function __tnRegisterDynamicValidate(
|
|
544
|
+
typeName: string,
|
|
545
|
+
fn: (buffer: Uint8Array) => __TnValidateResult
|
|
546
|
+
): void {
|
|
547
|
+
__tnDynamicValidateRegistry[typeName] = fn;
|
|
548
|
+
}
|
|
549
|
+
|
|
533
550
|
function __tnInvokeFootprint(
|
|
534
551
|
typeName: string,
|
|
535
552
|
params: Record<string, bigint>
|
|
@@ -549,8 +566,17 @@ function __tnInvokeValidate(
|
|
|
549
566
|
return fn(buffer, params);
|
|
550
567
|
}
|
|
551
568
|
|
|
569
|
+
function __tnInvokeDynamicValidate(
|
|
570
|
+
typeName: string,
|
|
571
|
+
buffer: Uint8Array
|
|
572
|
+
): __TnValidateResult {
|
|
573
|
+
const fn = __tnDynamicValidateRegistry[typeName];
|
|
574
|
+
if (!fn) throw new Error(`IR runtime missing dynamic validate helper for ${typeName}`);
|
|
575
|
+
return fn(buffer);
|
|
576
|
+
}
|
|
577
|
+
|
|
552
578
|
function __tnEvalFootprint(node: __TnIrNode, ctx: __TnIrContext): bigint {
|
|
553
|
-
return __tnEvalIrNode(node, ctx);
|
|
579
|
+
return __tnEvalIrNode(node, ctx, __tnToBigInt(0));
|
|
554
580
|
}
|
|
555
581
|
|
|
556
582
|
function __tnTryEvalFootprint(
|
|
@@ -565,7 +591,7 @@ function __tnTryEvalIr(
|
|
|
565
591
|
ctx: __TnIrContext
|
|
566
592
|
): __TnEvalResult {
|
|
567
593
|
try {
|
|
568
|
-
return { ok: true, value: __tnEvalIrNode(node, ctx) };
|
|
594
|
+
return { ok: true, value: __tnEvalIrNode(node, ctx, __tnToBigInt(0)) };
|
|
569
595
|
} catch (err) {
|
|
570
596
|
return { ok: false, code: __tnNormalizeIrError(err) };
|
|
571
597
|
}
|
|
@@ -596,7 +622,11 @@ function __tnValidateIrTree(
|
|
|
596
622
|
return { ok: true, consumed: required };
|
|
597
623
|
}
|
|
598
624
|
|
|
599
|
-
function __tnEvalIrNode(
|
|
625
|
+
function __tnEvalIrNode(
|
|
626
|
+
node: __TnIrNode,
|
|
627
|
+
ctx: __TnIrContext,
|
|
628
|
+
baseOffset: bigint
|
|
629
|
+
): bigint {
|
|
600
630
|
switch (node.op) {
|
|
601
631
|
case "zero":
|
|
602
632
|
return __tnToBigInt(0);
|
|
@@ -614,17 +644,22 @@ function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
|
|
|
614
644
|
return val;
|
|
615
645
|
}
|
|
616
646
|
case "add":
|
|
617
|
-
|
|
618
|
-
__tnEvalIrNode(node.left, ctx)
|
|
619
|
-
__tnEvalIrNode(
|
|
620
|
-
|
|
647
|
+
{
|
|
648
|
+
const left = __tnEvalIrNode(node.left, ctx, baseOffset);
|
|
649
|
+
const right = __tnEvalIrNode(
|
|
650
|
+
node.right,
|
|
651
|
+
ctx,
|
|
652
|
+
__tnCheckedAdd(baseOffset, left)
|
|
653
|
+
);
|
|
654
|
+
return __tnCheckedAdd(left, right);
|
|
655
|
+
}
|
|
621
656
|
case "mul":
|
|
622
657
|
return __tnCheckedMul(
|
|
623
|
-
__tnEvalIrNode(node.left, ctx),
|
|
624
|
-
__tnEvalIrNode(node.right, ctx)
|
|
658
|
+
__tnEvalIrNode(node.left, ctx, baseOffset),
|
|
659
|
+
__tnEvalIrNode(node.right, ctx, baseOffset)
|
|
625
660
|
);
|
|
626
661
|
case "align":
|
|
627
|
-
return __tnAlign(__tnEvalIrNode(node.node, ctx), node.alignment);
|
|
662
|
+
return __tnAlign(__tnEvalIrNode(node.node, ctx, baseOffset), node.alignment);
|
|
628
663
|
case "switch": {
|
|
629
664
|
const tagVal = ctx.params[node.tag];
|
|
630
665
|
if (tagVal === undefined) {
|
|
@@ -637,10 +672,10 @@ function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
|
|
|
637
672
|
const tagNumber = Number(tagVal);
|
|
638
673
|
for (const caseNode of node.cases) {
|
|
639
674
|
if (caseNode.value === tagNumber) {
|
|
640
|
-
return __tnEvalIrNode(caseNode.node, ctx);
|
|
675
|
+
return __tnEvalIrNode(caseNode.node, ctx, baseOffset);
|
|
641
676
|
}
|
|
642
677
|
}
|
|
643
|
-
if (node.default) return __tnEvalIrNode(node.default, ctx);
|
|
678
|
+
if (node.default) return __tnEvalIrNode(node.default, ctx, baseOffset);
|
|
644
679
|
__tnRaiseIrError(
|
|
645
680
|
"tn.ir.invalid_tag",
|
|
646
681
|
`Unhandled IR switch value ${tagNumber} for '${node.tag}'`
|
|
@@ -660,9 +695,10 @@ function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
|
|
|
660
695
|
nestedParams[arg.name] = val;
|
|
661
696
|
}
|
|
662
697
|
if (ctx.buffer) {
|
|
698
|
+
const nestedOffset = __tnBigIntToNumber(baseOffset, "IR nested offset");
|
|
663
699
|
const nestedResult = __tnInvokeValidate(
|
|
664
700
|
node.typeName,
|
|
665
|
-
ctx.buffer,
|
|
701
|
+
ctx.buffer.subarray(nestedOffset),
|
|
666
702
|
nestedParams
|
|
667
703
|
);
|
|
668
704
|
if (!nestedResult.ok) {
|
|
@@ -682,6 +718,36 @@ function __tnEvalIrNode(node: __TnIrNode, ctx: __TnIrContext): bigint {
|
|
|
682
718
|
}
|
|
683
719
|
return __tnInvokeFootprint(node.typeName, nestedParams);
|
|
684
720
|
}
|
|
721
|
+
case "sumOverArray": {
|
|
722
|
+
if (!ctx.buffer) {
|
|
723
|
+
__tnRaiseIrError(
|
|
724
|
+
"tn.ir.missing_buffer",
|
|
725
|
+
`Jagged array '${node.fieldName}' requires buffer-backed validation`
|
|
726
|
+
);
|
|
727
|
+
}
|
|
728
|
+
const count = __tnBigIntToNumber(
|
|
729
|
+
__tnEvalIrNode(node.count, ctx, baseOffset),
|
|
730
|
+
`Jagged array '${node.fieldName}' count`
|
|
731
|
+
);
|
|
732
|
+
let cursor = __tnBigIntToNumber(baseOffset, "IR jagged array offset");
|
|
733
|
+
let total = __tnToBigInt(0);
|
|
734
|
+
for (let i = 0; i < count; i++) {
|
|
735
|
+
const result = __tnInvokeDynamicValidate(
|
|
736
|
+
node.elementTypeName,
|
|
737
|
+
ctx.buffer.subarray(cursor)
|
|
738
|
+
);
|
|
739
|
+
if (!result.ok || result.consumed === undefined) {
|
|
740
|
+
const code = result.code ?? "tn.ir.runtime_error";
|
|
741
|
+
__tnRaiseIrError(
|
|
742
|
+
code,
|
|
743
|
+
`Jagged array '${node.fieldName}' element ${i} failed validation`
|
|
744
|
+
);
|
|
745
|
+
}
|
|
746
|
+
cursor += __tnBigIntToNumber(result.consumed, "IR jagged element size");
|
|
747
|
+
total = __tnCheckedAdd(total, result.consumed);
|
|
748
|
+
}
|
|
749
|
+
return total;
|
|
750
|
+
}
|
|
685
751
|
default:
|
|
686
752
|
__tnRaiseIrError(
|
|
687
753
|
"tn.ir.runtime_error",
|
|
@@ -858,9 +924,6 @@ export class Date {
|
|
|
858
924
|
|
|
859
925
|
}
|
|
860
926
|
|
|
861
|
-
__tnRegisterFootprint("Date", (params) => Date.__tnInvokeFootprint(params));
|
|
862
|
-
__tnRegisterValidate("Date", (buffer, params) => Date.__tnInvokeValidate(buffer, params));
|
|
863
|
-
|
|
864
927
|
export class DateBuilder {
|
|
865
928
|
private buffer: Uint8Array;
|
|
866
929
|
private view: DataView;
|
|
@@ -902,6 +965,10 @@ export class DateBuilder {
|
|
|
902
965
|
}
|
|
903
966
|
}
|
|
904
967
|
|
|
968
|
+
__tnRegisterFootprint("Date", (params) => Date.__tnInvokeFootprint(params));
|
|
969
|
+
__tnRegisterValidate("Date", (buffer, params) => Date.__tnInvokeValidate(buffer, params));
|
|
970
|
+
__tnRegisterDynamicValidate("Date", (buffer) => { const result = Date.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
|
|
971
|
+
|
|
905
972
|
/* ----- TYPE DEFINITION FOR Duration ----- */
|
|
906
973
|
|
|
907
974
|
const __tn_ir_Duration = {
|
|
@@ -1025,9 +1092,6 @@ export class Duration {
|
|
|
1025
1092
|
|
|
1026
1093
|
}
|
|
1027
1094
|
|
|
1028
|
-
__tnRegisterFootprint("Duration", (params) => Duration.__tnInvokeFootprint(params));
|
|
1029
|
-
__tnRegisterValidate("Duration", (buffer, params) => Duration.__tnInvokeValidate(buffer, params));
|
|
1030
|
-
|
|
1031
1095
|
export class DurationBuilder {
|
|
1032
1096
|
private buffer: Uint8Array;
|
|
1033
1097
|
private view: DataView;
|
|
@@ -1065,6 +1129,10 @@ export class DurationBuilder {
|
|
|
1065
1129
|
}
|
|
1066
1130
|
}
|
|
1067
1131
|
|
|
1132
|
+
__tnRegisterFootprint("Duration", (params) => Duration.__tnInvokeFootprint(params));
|
|
1133
|
+
__tnRegisterValidate("Duration", (buffer, params) => Duration.__tnInvokeValidate(buffer, params));
|
|
1134
|
+
__tnRegisterDynamicValidate("Duration", (buffer) => { const result = Duration.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
|
|
1135
|
+
|
|
1068
1136
|
/* ----- TYPE DEFINITION FOR FixedPoint ----- */
|
|
1069
1137
|
|
|
1070
1138
|
const __tn_ir_FixedPoint = {
|
|
@@ -1188,9 +1256,6 @@ export class FixedPoint {
|
|
|
1188
1256
|
|
|
1189
1257
|
}
|
|
1190
1258
|
|
|
1191
|
-
__tnRegisterFootprint("FixedPoint", (params) => FixedPoint.__tnInvokeFootprint(params));
|
|
1192
|
-
__tnRegisterValidate("FixedPoint", (buffer, params) => FixedPoint.__tnInvokeValidate(buffer, params));
|
|
1193
|
-
|
|
1194
1259
|
export class FixedPointBuilder {
|
|
1195
1260
|
private buffer: Uint8Array;
|
|
1196
1261
|
private view: DataView;
|
|
@@ -1228,6 +1293,10 @@ export class FixedPointBuilder {
|
|
|
1228
1293
|
}
|
|
1229
1294
|
}
|
|
1230
1295
|
|
|
1296
|
+
__tnRegisterFootprint("FixedPoint", (params) => FixedPoint.__tnInvokeFootprint(params));
|
|
1297
|
+
__tnRegisterValidate("FixedPoint", (buffer, params) => FixedPoint.__tnInvokeValidate(buffer, params));
|
|
1298
|
+
__tnRegisterDynamicValidate("FixedPoint", (buffer) => { const result = FixedPoint.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
|
|
1299
|
+
|
|
1231
1300
|
/* ----- TYPE DEFINITION FOR Hash ----- */
|
|
1232
1301
|
|
|
1233
1302
|
const __tn_ir_Hash = {
|
|
@@ -1331,9 +1400,6 @@ export class Hash {
|
|
|
1331
1400
|
|
|
1332
1401
|
}
|
|
1333
1402
|
|
|
1334
|
-
__tnRegisterFootprint("Hash", (params) => Hash.__tnInvokeFootprint(params));
|
|
1335
|
-
__tnRegisterValidate("Hash", (buffer, params) => Hash.__tnInvokeValidate(buffer, params));
|
|
1336
|
-
|
|
1337
1403
|
export class HashBuilder {
|
|
1338
1404
|
private buffer: Uint8Array;
|
|
1339
1405
|
private view: DataView;
|
|
@@ -1369,6 +1435,10 @@ export class HashBuilder {
|
|
|
1369
1435
|
}
|
|
1370
1436
|
}
|
|
1371
1437
|
|
|
1438
|
+
__tnRegisterFootprint("Hash", (params) => Hash.__tnInvokeFootprint(params));
|
|
1439
|
+
__tnRegisterValidate("Hash", (buffer, params) => Hash.__tnInvokeValidate(buffer, params));
|
|
1440
|
+
__tnRegisterDynamicValidate("Hash", (buffer) => { const result = Hash.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
|
|
1441
|
+
|
|
1372
1442
|
/* ----- TYPE DEFINITION FOR InstructionData ----- */
|
|
1373
1443
|
|
|
1374
1444
|
const __tn_ir_InstructionData = {
|
|
@@ -1654,9 +1724,6 @@ export namespace InstructionData {
|
|
|
1654
1724
|
}
|
|
1655
1725
|
}
|
|
1656
1726
|
|
|
1657
|
-
__tnRegisterFootprint("InstructionData", (params) => InstructionData.__tnInvokeFootprint(params));
|
|
1658
|
-
__tnRegisterValidate("InstructionData", (buffer, params) => InstructionData.__tnInvokeValidate(buffer, params));
|
|
1659
|
-
|
|
1660
1727
|
export class InstructionDataBuilder {
|
|
1661
1728
|
private buffer: Uint8Array;
|
|
1662
1729
|
private view: DataView;
|
|
@@ -1768,6 +1835,10 @@ export class InstructionDataBuilder {
|
|
|
1768
1835
|
}
|
|
1769
1836
|
}
|
|
1770
1837
|
|
|
1838
|
+
__tnRegisterFootprint("InstructionData", (params) => InstructionData.__tnInvokeFootprint(params));
|
|
1839
|
+
__tnRegisterValidate("InstructionData", (buffer, params) => InstructionData.__tnInvokeValidate(buffer, params));
|
|
1840
|
+
__tnRegisterDynamicValidate("InstructionData", (buffer) => { const result = InstructionData.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
|
|
1841
|
+
|
|
1771
1842
|
/* ----- TYPE DEFINITION FOR Pubkey ----- */
|
|
1772
1843
|
|
|
1773
1844
|
const __tn_ir_Pubkey = {
|
|
@@ -1871,9 +1942,6 @@ export class Pubkey {
|
|
|
1871
1942
|
|
|
1872
1943
|
}
|
|
1873
1944
|
|
|
1874
|
-
__tnRegisterFootprint("Pubkey", (params) => Pubkey.__tnInvokeFootprint(params));
|
|
1875
|
-
__tnRegisterValidate("Pubkey", (buffer, params) => Pubkey.__tnInvokeValidate(buffer, params));
|
|
1876
|
-
|
|
1877
1945
|
export class PubkeyBuilder {
|
|
1878
1946
|
private buffer: Uint8Array;
|
|
1879
1947
|
private view: DataView;
|
|
@@ -1909,6 +1977,10 @@ export class PubkeyBuilder {
|
|
|
1909
1977
|
}
|
|
1910
1978
|
}
|
|
1911
1979
|
|
|
1980
|
+
__tnRegisterFootprint("Pubkey", (params) => Pubkey.__tnInvokeFootprint(params));
|
|
1981
|
+
__tnRegisterValidate("Pubkey", (buffer, params) => Pubkey.__tnInvokeValidate(buffer, params));
|
|
1982
|
+
__tnRegisterDynamicValidate("Pubkey", (buffer) => { const result = Pubkey.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
|
|
1983
|
+
|
|
1912
1984
|
/* ----- TYPE DEFINITION FOR Signature ----- */
|
|
1913
1985
|
|
|
1914
1986
|
const __tn_ir_Signature = {
|
|
@@ -2012,9 +2084,6 @@ export class Signature {
|
|
|
2012
2084
|
|
|
2013
2085
|
}
|
|
2014
2086
|
|
|
2015
|
-
__tnRegisterFootprint("Signature", (params) => Signature.__tnInvokeFootprint(params));
|
|
2016
|
-
__tnRegisterValidate("Signature", (buffer, params) => Signature.__tnInvokeValidate(buffer, params));
|
|
2017
|
-
|
|
2018
2087
|
export class SignatureBuilder {
|
|
2019
2088
|
private buffer: Uint8Array;
|
|
2020
2089
|
private view: DataView;
|
|
@@ -2050,6 +2119,10 @@ export class SignatureBuilder {
|
|
|
2050
2119
|
}
|
|
2051
2120
|
}
|
|
2052
2121
|
|
|
2122
|
+
__tnRegisterFootprint("Signature", (params) => Signature.__tnInvokeFootprint(params));
|
|
2123
|
+
__tnRegisterValidate("Signature", (buffer, params) => Signature.__tnInvokeValidate(buffer, params));
|
|
2124
|
+
__tnRegisterDynamicValidate("Signature", (buffer) => { const result = Signature.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
|
|
2125
|
+
|
|
2053
2126
|
/* ----- TYPE DEFINITION FOR Timestamp ----- */
|
|
2054
2127
|
|
|
2055
2128
|
const __tn_ir_Timestamp = {
|
|
@@ -2154,9 +2227,6 @@ export class Timestamp {
|
|
|
2154
2227
|
|
|
2155
2228
|
}
|
|
2156
2229
|
|
|
2157
|
-
__tnRegisterFootprint("Timestamp", (params) => Timestamp.__tnInvokeFootprint(params));
|
|
2158
|
-
__tnRegisterValidate("Timestamp", (buffer, params) => Timestamp.__tnInvokeValidate(buffer, params));
|
|
2159
|
-
|
|
2160
2230
|
export class TimestampBuilder {
|
|
2161
2231
|
private buffer: Uint8Array;
|
|
2162
2232
|
private view: DataView;
|
|
@@ -2189,3 +2259,7 @@ export class TimestampBuilder {
|
|
|
2189
2259
|
}
|
|
2190
2260
|
}
|
|
2191
2261
|
|
|
2262
|
+
__tnRegisterFootprint("Timestamp", (params) => Timestamp.__tnInvokeFootprint(params));
|
|
2263
|
+
__tnRegisterValidate("Timestamp", (buffer, params) => Timestamp.__tnInvokeValidate(buffer, params));
|
|
2264
|
+
__tnRegisterDynamicValidate("Timestamp", (buffer) => { const result = Timestamp.validate(buffer); return { ok: result.ok, code: result.code, consumed: result.consumed === undefined ? undefined : __tnToBigInt(result.consumed) }; });
|
|
2265
|
+
|