@aztec/stdlib 3.0.0-nightly.20251005 → 3.0.0-nightly.20251008
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/dest/avm/avm.d.ts +62 -78
- package/dest/avm/avm.d.ts.map +1 -1
- package/dest/avm/avm.js +8 -22
- package/dest/avm/avm_circuit_public_inputs.d.ts +19 -6
- package/dest/avm/avm_circuit_public_inputs.d.ts.map +1 -1
- package/dest/avm/avm_circuit_public_inputs.js +12 -11
- package/dest/avm/avm_proving_request.d.ts +49 -40
- package/dest/avm/avm_proving_request.d.ts.map +1 -1
- package/dest/file-store/interface.d.ts +8 -2
- package/dest/file-store/interface.d.ts.map +1 -1
- package/dest/file-store/s3.d.ts +1 -0
- package/dest/file-store/s3.d.ts.map +1 -1
- package/dest/file-store/s3.js +81 -16
- package/dest/interfaces/aztec-node-admin.d.ts +3 -0
- package/dest/interfaces/aztec-node-admin.d.ts.map +1 -1
- package/dest/interfaces/configs.d.ts +5 -0
- package/dest/interfaces/configs.d.ts.map +1 -1
- package/dest/interfaces/configs.js +2 -1
- package/dest/interfaces/proving-job.d.ts +49 -40
- package/dest/interfaces/proving-job.d.ts.map +1 -1
- package/dest/interfaces/validator.d.ts +1 -1
- package/dest/interfaces/validator.d.ts.map +1 -1
- package/dest/kernel/hints/build_nullifier_read_request_hints.d.ts +3 -2
- package/dest/kernel/hints/build_nullifier_read_request_hints.d.ts.map +1 -1
- package/dest/kernel/hints/nullifier_read_request_hints.d.ts +4 -3
- package/dest/kernel/hints/nullifier_read_request_hints.d.ts.map +1 -1
- package/dest/kernel/private_call_data.d.ts +4 -24
- package/dest/kernel/private_call_data.d.ts.map +1 -1
- package/dest/kernel/private_call_data.js +4 -16
- package/dest/kernel/private_kernel_circuit_public_inputs.d.ts +3 -3
- package/dest/kernel/private_kernel_circuit_public_inputs.d.ts.map +1 -1
- package/dest/kernel/private_kernel_circuit_public_inputs.js +3 -3
- package/dest/kernel/private_kernel_init_circuit_private_inputs.d.ts +5 -4
- package/dest/kernel/private_kernel_init_circuit_private_inputs.d.ts.map +1 -1
- package/dest/kernel/private_kernel_init_circuit_private_inputs.js +7 -6
- package/dest/kernel/private_kernel_tail_circuit_public_inputs.js +1 -1
- package/dest/p2p/block_proposal.d.ts +2 -0
- package/dest/p2p/block_proposal.d.ts.map +1 -1
- package/dest/rollup/block_constant_data.d.ts +4 -4
- package/dest/rollup/block_constant_data.d.ts.map +1 -1
- package/dest/rollup/block_constant_data.js +4 -4
- package/dest/rollup/checkpoint_constant_data.d.ts +4 -4
- package/dest/rollup/checkpoint_constant_data.d.ts.map +1 -1
- package/dest/rollup/checkpoint_constant_data.js +4 -4
- package/dest/rollup/epoch_constant_data.d.ts +4 -4
- package/dest/rollup/epoch_constant_data.d.ts.map +1 -1
- package/dest/rollup/epoch_constant_data.js +5 -5
- package/dest/snapshots/download.d.ts.map +1 -1
- package/dest/snapshots/download.js +58 -2
- package/dest/snapshots/upload.d.ts.map +1 -1
- package/dest/snapshots/upload.js +1 -0
- package/dest/tests/factories.d.ts +5 -4
- package/dest/tests/factories.d.ts.map +1 -1
- package/dest/tests/factories.js +11 -10
- package/dest/tests/mocks.d.ts +2 -2
- package/dest/tests/mocks.d.ts.map +1 -1
- package/dest/tests/mocks.js +2 -2
- package/dest/trees/index.d.ts +0 -1
- package/dest/trees/index.d.ts.map +1 -1
- package/dest/trees/index.js +0 -1
- package/dest/tx/index.d.ts +2 -0
- package/dest/tx/index.d.ts.map +1 -1
- package/dest/tx/index.js +2 -0
- package/dest/tx/private_tx_constant_data.d.ts +60 -0
- package/dest/tx/private_tx_constant_data.d.ts.map +1 -0
- package/dest/tx/private_tx_constant_data.js +69 -0
- package/dest/tx/protocol_contracts.d.ts +29 -0
- package/dest/tx/protocol_contracts.d.ts.map +1 -0
- package/dest/tx/protocol_contracts.js +49 -0
- package/dest/tx/tx_constant_data.d.ts +5 -37
- package/dest/tx/tx_constant_data.d.ts.map +1 -1
- package/dest/tx/tx_constant_data.js +8 -17
- package/dest/tx/validator/error_texts.d.ts +1 -1
- package/dest/tx/validator/error_texts.d.ts.map +1 -1
- package/dest/tx/validator/error_texts.js +1 -1
- package/dest/versioning/versioning.d.ts +2 -2
- package/dest/versioning/versioning.d.ts.map +1 -1
- package/dest/versioning/versioning.js +8 -8
- package/package.json +8 -8
- package/src/avm/avm.ts +13 -24
- package/src/avm/avm_circuit_public_inputs.ts +11 -10
- package/src/file-store/interface.ts +8 -2
- package/src/file-store/s3.ts +83 -15
- package/src/interfaces/configs.ts +3 -0
- package/src/interfaces/validator.ts +1 -1
- package/src/kernel/hints/build_nullifier_read_request_hints.ts +3 -2
- package/src/kernel/hints/nullifier_read_request_hints.ts +3 -3
- package/src/kernel/private_call_data.ts +2 -21
- package/src/kernel/private_kernel_circuit_public_inputs.ts +4 -4
- package/src/kernel/private_kernel_init_circuit_private_inputs.ts +5 -4
- package/src/kernel/private_kernel_tail_circuit_public_inputs.ts +1 -1
- package/src/p2p/block_proposal.ts +2 -0
- package/src/rollup/block_constant_data.ts +3 -3
- package/src/rollup/checkpoint_constant_data.ts +3 -3
- package/src/rollup/epoch_constant_data.ts +3 -9
- package/src/snapshots/download.ts +66 -2
- package/src/snapshots/upload.ts +1 -0
- package/src/tests/factories.ts +12 -19
- package/src/tests/mocks.ts +3 -3
- package/src/trees/index.ts +0 -1
- package/src/tx/index.ts +2 -0
- package/src/tx/private_tx_constant_data.ts +94 -0
- package/src/tx/protocol_contracts.ts +70 -0
- package/src/tx/tx_constant_data.ts +6 -19
- package/src/tx/validator/error_texts.ts +1 -1
- package/src/versioning/versioning.ts +10 -10
- package/dest/trees/protocol_contract_leaf.d.ts +0 -84
- package/dest/trees/protocol_contract_leaf.d.ts.map +0 -1
- package/dest/trees/protocol_contract_leaf.js +0 -100
- package/src/trees/protocol_contract_leaf.ts +0 -128
package/src/tests/factories.ts
CHANGED
|
@@ -68,7 +68,6 @@ import {
|
|
|
68
68
|
AvmGetLeafValueHint,
|
|
69
69
|
AvmGetPreviousValueIndexHint,
|
|
70
70
|
AvmGetSiblingPathHint,
|
|
71
|
-
AvmProtocolContractAddressHint,
|
|
72
71
|
AvmRevertCheckpointHint,
|
|
73
72
|
AvmSequentialInsertHintNullifierTree,
|
|
74
73
|
AvmSequentialInsertHintPublicDataTree,
|
|
@@ -160,6 +159,7 @@ import { FunctionData } from '../tx/function_data.js';
|
|
|
160
159
|
import { GlobalVariables } from '../tx/global_variables.js';
|
|
161
160
|
import { PartialStateReference } from '../tx/partial_state_reference.js';
|
|
162
161
|
import { makeProcessedTxFromPrivateOnlyTx, makeProcessedTxFromTxWithPublicCalls } from '../tx/processed_tx.js';
|
|
162
|
+
import { ProtocolContracts } from '../tx/protocol_contracts.js';
|
|
163
163
|
import { PublicCallRequestWithCalldata } from '../tx/public_call_request_with_calldata.js';
|
|
164
164
|
import { StateReference } from '../tx/state_reference.js';
|
|
165
165
|
import { TreeSnapshots } from '../tx/tree_snapshots.js';
|
|
@@ -420,6 +420,10 @@ export function makePublicTubePublicInputs(seed = 1) {
|
|
|
420
420
|
return new PublicTubePublicInputs(makePrivateToPublicKernelCircuitPublicInputs(seed), fr(seed + 0x1000));
|
|
421
421
|
}
|
|
422
422
|
|
|
423
|
+
export function makeProtocolContracts(seed = 1) {
|
|
424
|
+
return new ProtocolContracts(makeTuple(MAX_PROTOCOL_CONTRACTS, makeAztecAddress, seed));
|
|
425
|
+
}
|
|
426
|
+
|
|
423
427
|
/**
|
|
424
428
|
* Creates arbitrary public kernel circuit public inputs.
|
|
425
429
|
* @param seed - The seed to use for generating the kernel circuit public inputs.
|
|
@@ -441,7 +445,7 @@ export function makePrivateToRollupKernelCircuitPublicInputs(
|
|
|
441
445
|
function makeAvmCircuitPublicInputs(seed = 1) {
|
|
442
446
|
return new AvmCircuitPublicInputs(
|
|
443
447
|
makeGlobalVariables(seed),
|
|
444
|
-
|
|
448
|
+
makeProtocolContracts(seed + 0x100),
|
|
445
449
|
makeTreeSnapshots(seed + 0x10),
|
|
446
450
|
makeGas(seed + 0x20),
|
|
447
451
|
makeGasSettings(),
|
|
@@ -1429,13 +1433,6 @@ export async function makeAvmTxHint(seed = 0): Promise<AvmTxHint> {
|
|
|
1429
1433
|
);
|
|
1430
1434
|
}
|
|
1431
1435
|
|
|
1432
|
-
export function makeAvmProtocolContractDerivedAddressesHint(seed = 0): AvmProtocolContractAddressHint {
|
|
1433
|
-
return new AvmProtocolContractAddressHint(
|
|
1434
|
-
/*canonicalAddress=*/ new AztecAddress(new Fr(seed + 1)),
|
|
1435
|
-
/*derivedAddress=*/ new AztecAddress(new Fr(seed + 0x1001)),
|
|
1436
|
-
);
|
|
1437
|
-
}
|
|
1438
|
-
|
|
1439
1436
|
/**
|
|
1440
1437
|
* Creates arbitrary AvmExecutionHints.
|
|
1441
1438
|
* @param seed - The seed to use for generating the hints.
|
|
@@ -1452,11 +1449,7 @@ export async function makeAvmExecutionHints(
|
|
|
1452
1449
|
const fields = {
|
|
1453
1450
|
globalVariables: makeGlobalVariables(seed + 0x4000),
|
|
1454
1451
|
tx: await makeAvmTxHint(seed + 0x4100),
|
|
1455
|
-
|
|
1456
|
-
MAX_PROTOCOL_CONTRACTS,
|
|
1457
|
-
makeAvmProtocolContractDerivedAddressesHint,
|
|
1458
|
-
seed + 0x4600,
|
|
1459
|
-
),
|
|
1452
|
+
protocolContracts: new ProtocolContracts(makeTuple(MAX_PROTOCOL_CONTRACTS, makeAztecAddress, seed + 0x4600)),
|
|
1460
1453
|
contractInstances: makeArray(baseLength + 2, makeAvmContractInstanceHint, seed + 0x4700),
|
|
1461
1454
|
contractClasses: makeArray(baseLength + 5, makeAvmContractClassHint, seed + 0x4900),
|
|
1462
1455
|
bytecodeCommitments: await makeArrayAsync(baseLength + 5, makeAvmBytecodeCommitmentHint, seed + 0x4900),
|
|
@@ -1490,7 +1483,7 @@ export async function makeAvmExecutionHints(
|
|
|
1490
1483
|
return new AvmExecutionHints(
|
|
1491
1484
|
fields.globalVariables,
|
|
1492
1485
|
fields.tx,
|
|
1493
|
-
fields.
|
|
1486
|
+
fields.protocolContracts,
|
|
1494
1487
|
fields.contractInstances,
|
|
1495
1488
|
fields.contractClasses,
|
|
1496
1489
|
fields.bytecodeCommitments,
|
|
@@ -1546,7 +1539,7 @@ export async function makeBloatedProcessedTx({
|
|
|
1546
1539
|
version = Fr.ZERO,
|
|
1547
1540
|
gasSettings = GasSettings.default({ maxFeesPerGas: new GasFees(10, 10) }),
|
|
1548
1541
|
vkTreeRoot = Fr.ZERO,
|
|
1549
|
-
|
|
1542
|
+
protocolContracts = makeProtocolContracts(seed + 0x100),
|
|
1550
1543
|
globalVariables = GlobalVariables.empty(),
|
|
1551
1544
|
newL1ToL2Snapshot = AppendOnlyTreeSnapshot.empty(),
|
|
1552
1545
|
feePayer,
|
|
@@ -1562,7 +1555,7 @@ export async function makeBloatedProcessedTx({
|
|
|
1562
1555
|
vkTreeRoot?: Fr;
|
|
1563
1556
|
globalVariables?: GlobalVariables;
|
|
1564
1557
|
newL1ToL2Snapshot?: AppendOnlyTreeSnapshot;
|
|
1565
|
-
|
|
1558
|
+
protocolContracts?: ProtocolContracts;
|
|
1566
1559
|
feePayer?: AztecAddress;
|
|
1567
1560
|
feePaymentPublicDataWrite?: PublicDataWrite;
|
|
1568
1561
|
privateOnly?: boolean;
|
|
@@ -1577,7 +1570,7 @@ export async function makeBloatedProcessedTx({
|
|
|
1577
1570
|
txConstantData.txContext.version = version;
|
|
1578
1571
|
txConstantData.txContext.gasSettings = gasSettings;
|
|
1579
1572
|
txConstantData.vkTreeRoot = vkTreeRoot;
|
|
1580
|
-
txConstantData.
|
|
1573
|
+
txConstantData.protocolContractsHash = await protocolContracts.hash();
|
|
1581
1574
|
|
|
1582
1575
|
const tx = !privateOnly
|
|
1583
1576
|
? await mockTx(seed, { feePayer })
|
|
@@ -1616,7 +1609,7 @@ export async function makeBloatedProcessedTx({
|
|
|
1616
1609
|
// Create avm output.
|
|
1617
1610
|
const avmOutput = AvmCircuitPublicInputs.empty();
|
|
1618
1611
|
// Assign data from hints.
|
|
1619
|
-
avmOutput.
|
|
1612
|
+
avmOutput.protocolContracts = protocolContracts;
|
|
1620
1613
|
avmOutput.startTreeSnapshots.l1ToL2MessageTree = newL1ToL2Snapshot;
|
|
1621
1614
|
avmOutput.endTreeSnapshots.l1ToL2MessageTree = newL1ToL2Snapshot;
|
|
1622
1615
|
// Assign data from private.
|
package/src/tests/mocks.ts
CHANGED
|
@@ -87,7 +87,7 @@ export const mockTx = async (
|
|
|
87
87
|
chainId = Fr.ZERO,
|
|
88
88
|
version = Fr.ZERO,
|
|
89
89
|
vkTreeRoot = Fr.ZERO,
|
|
90
|
-
|
|
90
|
+
protocolContractsHash = Fr.ZERO,
|
|
91
91
|
}: {
|
|
92
92
|
numberOfNonRevertiblePublicCallRequests?: number;
|
|
93
93
|
numberOfRevertiblePublicCallRequests?: number;
|
|
@@ -100,7 +100,7 @@ export const mockTx = async (
|
|
|
100
100
|
chainId?: Fr;
|
|
101
101
|
version?: Fr;
|
|
102
102
|
vkTreeRoot?: Fr;
|
|
103
|
-
|
|
103
|
+
protocolContractsHash?: Fr;
|
|
104
104
|
} = {},
|
|
105
105
|
) => {
|
|
106
106
|
const totalPublicCallRequests =
|
|
@@ -118,7 +118,7 @@ export const mockTx = async (
|
|
|
118
118
|
data.constants.txContext.chainId = chainId;
|
|
119
119
|
data.constants.txContext.version = version;
|
|
120
120
|
data.constants.vkTreeRoot = vkTreeRoot;
|
|
121
|
-
data.constants.
|
|
121
|
+
data.constants.protocolContractsHash = protocolContractsHash;
|
|
122
122
|
|
|
123
123
|
// Set includeByTimestamp to the maximum allowed duration from the current time.
|
|
124
124
|
data.includeByTimestamp = BigInt(Math.floor(Date.now() / 1000) + MAX_INCLUDE_BY_TIMESTAMP_DURATION);
|
package/src/trees/index.ts
CHANGED
package/src/tx/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ export * from './state_reference.js';
|
|
|
6
6
|
export * from './partial_state_reference.js';
|
|
7
7
|
export * from './function_data.js';
|
|
8
8
|
export * from './tree_snapshots.js';
|
|
9
|
+
export * from './private_tx_constant_data.js';
|
|
9
10
|
export * from './tx_constant_data.js';
|
|
10
11
|
export * from './tx_context.js';
|
|
11
12
|
export * from './tx_request.js';
|
|
@@ -29,3 +30,4 @@ export * from './hashed_values.js';
|
|
|
29
30
|
export * from './indexed_tx_effect.js';
|
|
30
31
|
export * from './offchain_effect.js';
|
|
31
32
|
export * from './profiling.js';
|
|
33
|
+
export * from './protocol_contracts.js';
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { TX_CONSTANT_DATA_LENGTH } from '@aztec/constants';
|
|
2
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
3
|
+
import { BufferReader, FieldReader, serializeToBuffer, serializeToFields } from '@aztec/foundation/serialize';
|
|
4
|
+
import type { FieldsOf } from '@aztec/foundation/types';
|
|
5
|
+
|
|
6
|
+
import { BlockHeader } from './block_header.js';
|
|
7
|
+
import { ProtocolContracts } from './protocol_contracts.js';
|
|
8
|
+
import { TxContext } from './tx_context.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Data that is constant/not modified by neither of the kernels.
|
|
12
|
+
*/
|
|
13
|
+
export class PrivateTxConstantData {
|
|
14
|
+
constructor(
|
|
15
|
+
/** Header of a block whose state is used during execution (not the block the transaction is included in). */
|
|
16
|
+
public anchorBlockHeader: BlockHeader,
|
|
17
|
+
/**
|
|
18
|
+
* Context of the transaction.
|
|
19
|
+
*
|
|
20
|
+
* Note: `chainId` and `version` in txContext are not redundant to the values in
|
|
21
|
+
* self.anchor_block_header.global_variables because they can be different in case of a protocol upgrade. In such
|
|
22
|
+
* a situation we could be using header from a block before the upgrade took place but be using the updated
|
|
23
|
+
* protocol to execute and prove the transaction.
|
|
24
|
+
*/
|
|
25
|
+
public txContext: TxContext,
|
|
26
|
+
/**
|
|
27
|
+
* Root of the vk tree for the protocol circuits.
|
|
28
|
+
*/
|
|
29
|
+
public vkTreeRoot: Fr,
|
|
30
|
+
/**
|
|
31
|
+
* List of protocol contracts.
|
|
32
|
+
*/
|
|
33
|
+
public protocolContracts: ProtocolContracts,
|
|
34
|
+
) {}
|
|
35
|
+
|
|
36
|
+
static from(fields: FieldsOf<PrivateTxConstantData>) {
|
|
37
|
+
return new PrivateTxConstantData(...PrivateTxConstantData.getFields(fields));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static getFields(fields: FieldsOf<PrivateTxConstantData>) {
|
|
41
|
+
return [fields.anchorBlockHeader, fields.txContext, fields.vkTreeRoot, fields.protocolContracts] as const;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static fromFields(fields: Fr[] | FieldReader): PrivateTxConstantData {
|
|
45
|
+
const reader = FieldReader.asReader(fields);
|
|
46
|
+
return new PrivateTxConstantData(
|
|
47
|
+
reader.readObject(BlockHeader),
|
|
48
|
+
reader.readObject(TxContext),
|
|
49
|
+
reader.readField(),
|
|
50
|
+
reader.readObject(ProtocolContracts),
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
toFields(): Fr[] {
|
|
55
|
+
const fields = serializeToFields(...PrivateTxConstantData.getFields(this));
|
|
56
|
+
if (fields.length !== TX_CONSTANT_DATA_LENGTH) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
`Invalid number of fields for PrivateTxConstantData. Expected ${TX_CONSTANT_DATA_LENGTH}, got ${fields.length}`,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
return fields;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static fromBuffer(buffer: Buffer | BufferReader): PrivateTxConstantData {
|
|
65
|
+
const reader = BufferReader.asReader(buffer);
|
|
66
|
+
return new PrivateTxConstantData(
|
|
67
|
+
reader.readObject(BlockHeader),
|
|
68
|
+
reader.readObject(TxContext),
|
|
69
|
+
Fr.fromBuffer(reader),
|
|
70
|
+
reader.readObject(ProtocolContracts),
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
toBuffer() {
|
|
75
|
+
return serializeToBuffer(...PrivateTxConstantData.getFields(this));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static empty() {
|
|
79
|
+
return new PrivateTxConstantData(BlockHeader.empty(), TxContext.empty(), Fr.ZERO, ProtocolContracts.empty());
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
getSize() {
|
|
83
|
+
return (
|
|
84
|
+
this.anchorBlockHeader.getSize() +
|
|
85
|
+
this.txContext.getSize() +
|
|
86
|
+
this.vkTreeRoot.size +
|
|
87
|
+
this.protocolContracts.getSize()
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
clone(): PrivateTxConstantData {
|
|
92
|
+
return PrivateTxConstantData.fromBuffer(this.toBuffer());
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { GeneratorIndex, MAX_PROTOCOL_CONTRACTS } from '@aztec/constants';
|
|
2
|
+
import { makeTuple } from '@aztec/foundation/array';
|
|
3
|
+
import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection';
|
|
4
|
+
import { poseidon2HashWithSeparator } from '@aztec/foundation/crypto';
|
|
5
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
6
|
+
import {
|
|
7
|
+
BufferReader,
|
|
8
|
+
FieldReader,
|
|
9
|
+
type Tuple,
|
|
10
|
+
assertLength,
|
|
11
|
+
serializeToBuffer,
|
|
12
|
+
serializeToFields,
|
|
13
|
+
} from '@aztec/foundation/serialize';
|
|
14
|
+
import type { FieldsOf } from '@aztec/foundation/types';
|
|
15
|
+
|
|
16
|
+
import { z } from 'zod';
|
|
17
|
+
|
|
18
|
+
import { AztecAddress } from '../aztec-address/index.js';
|
|
19
|
+
|
|
20
|
+
export class ProtocolContracts {
|
|
21
|
+
constructor(public derivedAddresses: Tuple<AztecAddress, typeof MAX_PROTOCOL_CONTRACTS>) {}
|
|
22
|
+
|
|
23
|
+
static from(fields: FieldsOf<ProtocolContracts>) {
|
|
24
|
+
return new ProtocolContracts(...ProtocolContracts.getFields(fields));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static getFields(fields: FieldsOf<ProtocolContracts>) {
|
|
28
|
+
return [fields.derivedAddresses] as const;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static fromFields(fields: Fr[] | FieldReader): ProtocolContracts {
|
|
32
|
+
const reader = FieldReader.asReader(fields);
|
|
33
|
+
return new ProtocolContracts(reader.readArray(MAX_PROTOCOL_CONTRACTS, AztecAddress));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
toFields(): Fr[] {
|
|
37
|
+
return serializeToFields(...ProtocolContracts.getFields(this));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static fromBuffer(buffer: Buffer | BufferReader): ProtocolContracts {
|
|
41
|
+
const reader = BufferReader.asReader(buffer);
|
|
42
|
+
return new ProtocolContracts(reader.readArray(MAX_PROTOCOL_CONTRACTS, AztecAddress));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
toBuffer() {
|
|
46
|
+
return serializeToBuffer(...ProtocolContracts.getFields(this));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static empty() {
|
|
50
|
+
return new ProtocolContracts(makeTuple(MAX_PROTOCOL_CONTRACTS, () => AztecAddress.zero()));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
getSize() {
|
|
54
|
+
return arraySerializedSizeOfNonEmpty(this.derivedAddresses);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
hash() {
|
|
58
|
+
return poseidon2HashWithSeparator(this.derivedAddresses, GeneratorIndex.PROTOCOL_CONTRACTS);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static get schema() {
|
|
62
|
+
return z
|
|
63
|
+
.object({
|
|
64
|
+
derivedAddresses: AztecAddress.schema.array().min(MAX_PROTOCOL_CONTRACTS).max(MAX_PROTOCOL_CONTRACTS),
|
|
65
|
+
})
|
|
66
|
+
.transform(
|
|
67
|
+
({ derivedAddresses }) => new ProtocolContracts(assertLength(derivedAddresses, MAX_PROTOCOL_CONTRACTS)),
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -7,29 +7,16 @@ import { BlockHeader } from './block_header.js';
|
|
|
7
7
|
import { TxContext } from './tx_context.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Version of `PrivateTxConstantData` exposed by the tail circuits
|
|
11
|
+
* It compresses the protocol contracts list to a hash to minimize the number of public inputs.
|
|
12
|
+
* Refer to `PrivateTxConstantData` for more details.
|
|
11
13
|
*/
|
|
12
14
|
export class TxConstantData {
|
|
13
15
|
constructor(
|
|
14
|
-
/** Header of a block whose state is used during execution (not the block the transaction is included in). */
|
|
15
16
|
public anchorBlockHeader: BlockHeader,
|
|
16
|
-
/**
|
|
17
|
-
* Context of the transaction.
|
|
18
|
-
*
|
|
19
|
-
* Note: `chainId` and `version` in txContext are not redundant to the values in
|
|
20
|
-
* self.anchor_block_header.global_variables because they can be different in case of a protocol upgrade. In such
|
|
21
|
-
* a situation we could be using header from a block before the upgrade took place but be using the updated
|
|
22
|
-
* protocol to execute and prove the transaction.
|
|
23
|
-
*/
|
|
24
17
|
public txContext: TxContext,
|
|
25
|
-
/**
|
|
26
|
-
* Root of the vk tree for the protocol circuits.
|
|
27
|
-
*/
|
|
28
18
|
public vkTreeRoot: Fr,
|
|
29
|
-
|
|
30
|
-
* Root of the tree for the protocol contracts.
|
|
31
|
-
*/
|
|
32
|
-
public protocolContractTreeRoot: Fr,
|
|
19
|
+
public protocolContractsHash: Fr,
|
|
33
20
|
) {}
|
|
34
21
|
|
|
35
22
|
static from(fields: FieldsOf<TxConstantData>) {
|
|
@@ -37,7 +24,7 @@ export class TxConstantData {
|
|
|
37
24
|
}
|
|
38
25
|
|
|
39
26
|
static getFields(fields: FieldsOf<TxConstantData>) {
|
|
40
|
-
return [fields.anchorBlockHeader, fields.txContext, fields.vkTreeRoot, fields.
|
|
27
|
+
return [fields.anchorBlockHeader, fields.txContext, fields.vkTreeRoot, fields.protocolContractsHash] as const;
|
|
41
28
|
}
|
|
42
29
|
|
|
43
30
|
static fromFields(fields: Fr[] | FieldReader): TxConstantData {
|
|
@@ -83,7 +70,7 @@ export class TxConstantData {
|
|
|
83
70
|
this.anchorBlockHeader.getSize() +
|
|
84
71
|
this.txContext.getSize() +
|
|
85
72
|
this.vkTreeRoot.size +
|
|
86
|
-
this.
|
|
73
|
+
this.protocolContractsHash.size
|
|
87
74
|
);
|
|
88
75
|
}
|
|
89
76
|
|
|
@@ -16,7 +16,7 @@ export const TX_ERROR_INVALID_INCLUDE_BY_TIMESTAMP = 'Invalid expiration timesta
|
|
|
16
16
|
export const TX_ERROR_INCORRECT_L1_CHAIN_ID = 'Incorrect L1 chain id';
|
|
17
17
|
export const TX_ERROR_INCORRECT_ROLLUP_VERSION = 'Incorrect rollup version';
|
|
18
18
|
export const TX_ERROR_INCORRECT_VK_TREE_ROOT = 'Incorrect verification keys tree root';
|
|
19
|
-
export const
|
|
19
|
+
export const TX_ERROR_INCORRECT_PROTOCOL_CONTRACTS_HASH = 'Incorrect protocol contracts hash';
|
|
20
20
|
|
|
21
21
|
// Proof
|
|
22
22
|
export const TX_ERROR_INVALID_PROOF = 'Invalid proof';
|
|
@@ -14,21 +14,21 @@ export type ComponentsVersions = {
|
|
|
14
14
|
// such as the keystore, we need to change it so we can handle updates.
|
|
15
15
|
l1RollupAddress: EthAddress;
|
|
16
16
|
rollupVersion: number;
|
|
17
|
-
|
|
17
|
+
l2ProtocolContractsHash: string;
|
|
18
18
|
l2CircuitsVkTreeRoot: string;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
/** Returns components versions from chain config. */
|
|
22
22
|
export function getComponentsVersionsFromConfig(
|
|
23
23
|
config: ChainConfig,
|
|
24
|
-
|
|
24
|
+
l2ProtocolContractsHash: string | Fr,
|
|
25
25
|
l2CircuitsVkTreeRoot: string | Fr,
|
|
26
26
|
): ComponentsVersions {
|
|
27
27
|
return {
|
|
28
28
|
l1ChainId: config.l1ChainId,
|
|
29
29
|
l1RollupAddress: config.l1Contracts?.rollupAddress, // This should not be undefined, but sometimes the config lies to us and it is...
|
|
30
30
|
rollupVersion: config.rollupVersion,
|
|
31
|
-
|
|
31
|
+
l2ProtocolContractsHash: l2ProtocolContractsHash.toString(),
|
|
32
32
|
l2CircuitsVkTreeRoot: l2CircuitsVkTreeRoot.toString(),
|
|
33
33
|
};
|
|
34
34
|
}
|
|
@@ -37,7 +37,7 @@ export function getComponentsVersionsFromConfig(
|
|
|
37
37
|
export function compressComponentVersions(versions: ComponentsVersions): string {
|
|
38
38
|
if (
|
|
39
39
|
versions.l1RollupAddress === undefined ||
|
|
40
|
-
versions.
|
|
40
|
+
versions.l2ProtocolContractsHash === undefined ||
|
|
41
41
|
versions.l2CircuitsVkTreeRoot === undefined
|
|
42
42
|
) {
|
|
43
43
|
throw new Error(`Component versions are not set: ${jsonStringify(versions)}`);
|
|
@@ -48,7 +48,7 @@ export function compressComponentVersions(versions: ComponentsVersions): string
|
|
|
48
48
|
versions.l1ChainId,
|
|
49
49
|
versions.l1RollupAddress.toString().slice(2, 10),
|
|
50
50
|
versions.rollupVersion,
|
|
51
|
-
versions.
|
|
51
|
+
versions.l2ProtocolContractsHash.toString().slice(2, 10),
|
|
52
52
|
versions.l2CircuitsVkTreeRoot.toString().slice(2, 10),
|
|
53
53
|
].join('-');
|
|
54
54
|
}
|
|
@@ -62,7 +62,7 @@ export class ComponentsVersionsError extends Error {
|
|
|
62
62
|
|
|
63
63
|
/** Checks if the compressed string matches against the expected versions. Throws on mismatch. */
|
|
64
64
|
export function checkCompressedComponentVersion(compressed: string, expected: ComponentsVersions) {
|
|
65
|
-
const [versionVersion, l1ChainId, l1RollupAddress, rollupVersion,
|
|
65
|
+
const [versionVersion, l1ChainId, l1RollupAddress, rollupVersion, l2ProtocolContractsHash, l2CircuitsVkTreeRoot] =
|
|
66
66
|
compressed.split('-');
|
|
67
67
|
if (versionVersion !== '00') {
|
|
68
68
|
throw new ComponentsVersionsError('version', '00', versionVersion);
|
|
@@ -76,11 +76,11 @@ export function checkCompressedComponentVersion(compressed: string, expected: Co
|
|
|
76
76
|
if (rollupVersion !== expected.rollupVersion.toString()) {
|
|
77
77
|
throw new ComponentsVersionsError('L2 chain version', expected.rollupVersion.toString(), rollupVersion);
|
|
78
78
|
}
|
|
79
|
-
if (
|
|
79
|
+
if (l2ProtocolContractsHash !== expected.l2ProtocolContractsHash.toString().slice(2, 10)) {
|
|
80
80
|
throw new ComponentsVersionsError(
|
|
81
81
|
`L2 protocol contracts vk tree root`,
|
|
82
|
-
expected.
|
|
83
|
-
|
|
82
|
+
expected.l2ProtocolContractsHash.toString(),
|
|
83
|
+
l2ProtocolContractsHash,
|
|
84
84
|
);
|
|
85
85
|
}
|
|
86
86
|
if (l2CircuitsVkTreeRoot !== expected.l2CircuitsVkTreeRoot.toString().slice(2, 10)) {
|
|
@@ -99,7 +99,7 @@ export function validatePartialComponentVersionsMatch(
|
|
|
99
99
|
) {
|
|
100
100
|
for (const key of [
|
|
101
101
|
'l1RollupAddress',
|
|
102
|
-
'
|
|
102
|
+
'l2ProtocolContractsHash',
|
|
103
103
|
'l2CircuitsVkTreeRoot',
|
|
104
104
|
'l1ChainId',
|
|
105
105
|
'rollupVersion',
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
2
|
-
import { BufferReader } from '@aztec/foundation/serialize';
|
|
3
|
-
import type { IndexedTreeLeaf, IndexedTreeLeafPreimage } from '@aztec/foundation/trees';
|
|
4
|
-
import { z } from 'zod';
|
|
5
|
-
/**
|
|
6
|
-
* Class containing the data of a preimage of a single leaf in the protocol contract tree.
|
|
7
|
-
* Note: It's called preimage because this data gets hashed before being inserted as a node into the `IndexedTree`.
|
|
8
|
-
* Note: Though this tree contains addresses, they are converted to fields to avoid unnecessary conversions in the tree.
|
|
9
|
-
*/
|
|
10
|
-
export declare class ProtocolContractLeafPreimage implements IndexedTreeLeafPreimage {
|
|
11
|
-
/**
|
|
12
|
-
* Leaf value inside the indexed tree's linked list.
|
|
13
|
-
*/
|
|
14
|
-
address: Fr;
|
|
15
|
-
/**
|
|
16
|
-
* Next value inside the indexed tree's linked list.
|
|
17
|
-
*/
|
|
18
|
-
nextAddress: Fr;
|
|
19
|
-
/**
|
|
20
|
-
* Index of the next leaf in the indexed tree's linked list.
|
|
21
|
-
*/
|
|
22
|
-
nextIndex: bigint;
|
|
23
|
-
constructor(
|
|
24
|
-
/**
|
|
25
|
-
* Leaf value inside the indexed tree's linked list.
|
|
26
|
-
*/
|
|
27
|
-
address: Fr,
|
|
28
|
-
/**
|
|
29
|
-
* Next value inside the indexed tree's linked list.
|
|
30
|
-
*/
|
|
31
|
-
nextAddress: Fr,
|
|
32
|
-
/**
|
|
33
|
-
* Index of the next leaf in the indexed tree's linked list.
|
|
34
|
-
*/
|
|
35
|
-
nextIndex: bigint);
|
|
36
|
-
static get schema(): z.ZodEffects<z.ZodObject<{
|
|
37
|
-
address: z.ZodType<Fr, any, string>;
|
|
38
|
-
nextAddress: z.ZodType<Fr, any, string>;
|
|
39
|
-
nextIndex: z.ZodPipeline<z.ZodUnion<[z.ZodBigInt, z.ZodNumber, z.ZodString]>, z.ZodBigInt>;
|
|
40
|
-
}, "strip", z.ZodTypeAny, {
|
|
41
|
-
nextIndex: bigint;
|
|
42
|
-
address: Fr;
|
|
43
|
-
nextAddress: Fr;
|
|
44
|
-
}, {
|
|
45
|
-
nextIndex: string | number | bigint;
|
|
46
|
-
address: string;
|
|
47
|
-
nextAddress: string;
|
|
48
|
-
}>, ProtocolContractLeafPreimage, {
|
|
49
|
-
nextIndex: string | number | bigint;
|
|
50
|
-
address: string;
|
|
51
|
-
nextAddress: string;
|
|
52
|
-
}>;
|
|
53
|
-
getKey(): bigint;
|
|
54
|
-
getNextKey(): bigint;
|
|
55
|
-
getNextIndex(): bigint;
|
|
56
|
-
asLeaf(): ProtocolContractLeaf;
|
|
57
|
-
toBuffer(): Buffer;
|
|
58
|
-
toHashInputs(): Buffer[];
|
|
59
|
-
toFields(): Fr[];
|
|
60
|
-
static random(): ProtocolContractLeafPreimage;
|
|
61
|
-
static empty(): ProtocolContractLeafPreimage;
|
|
62
|
-
static fromBuffer(buffer: Buffer | BufferReader): ProtocolContractLeafPreimage;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* An address to be inserted or checked in the protocol contract tree.
|
|
66
|
-
*/
|
|
67
|
-
export declare class ProtocolContractLeaf implements IndexedTreeLeaf {
|
|
68
|
-
/**
|
|
69
|
-
* Address value.
|
|
70
|
-
*/
|
|
71
|
-
address: Fr;
|
|
72
|
-
constructor(
|
|
73
|
-
/**
|
|
74
|
-
* Address value.
|
|
75
|
-
*/
|
|
76
|
-
address: Fr);
|
|
77
|
-
getKey(): bigint;
|
|
78
|
-
toBuffer(): Buffer;
|
|
79
|
-
isEmpty(): boolean;
|
|
80
|
-
updateTo(_another: ProtocolContractLeaf): ProtocolContractLeaf;
|
|
81
|
-
static buildDummy(key: bigint): ProtocolContractLeaf;
|
|
82
|
-
static fromBuffer(buf: Buffer): ProtocolContractLeaf;
|
|
83
|
-
}
|
|
84
|
-
//# sourceMappingURL=protocol_contract_leaf.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"protocol_contract_leaf.d.ts","sourceRoot":"","sources":["../../src/trees/protocol_contract_leaf.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAExF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,qBAAa,4BAA6B,YAAW,uBAAuB;IAExE;;OAEG;IACI,OAAO,EAAE,EAAE;IAClB;;OAEG;IACI,WAAW,EAAE,EAAE;IACtB;;OAEG;IACI,SAAS,EAAE,MAAM;;IAXxB;;OAEG;IACI,OAAO,EAAE,EAAE;IAClB;;OAEG;IACI,WAAW,EAAE,EAAE;IACtB;;OAEG;IACI,SAAS,EAAE,MAAM;IAG1B,MAAM,KAAK,MAAM;;;;;;;;;;;;;;;;OAUhB;IAED,MAAM,IAAI,MAAM;IAIhB,UAAU,IAAI,MAAM;IAIpB,YAAY,IAAI,MAAM;IAItB,MAAM,IAAI,oBAAoB;IAI9B,QAAQ,IAAI,MAAM;IAIlB,YAAY,IAAI,MAAM,EAAE;IAKxB,QAAQ,IAAI,EAAE,EAAE;IAIhB,MAAM,CAAC,MAAM;IAQb,MAAM,CAAC,KAAK,IAAI,4BAA4B;IAI5C,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,4BAA4B;CAQ/E;AAED;;GAEG;AACH,qBAAa,oBAAqB,YAAW,eAAe;IAExD;;OAEG;IACI,OAAO,EAAE,EAAE;;IAHlB;;OAEG;IACI,OAAO,EAAE,EAAE;IAGpB,MAAM,IAAI,MAAM;IAIhB,QAAQ,IAAI,MAAM;IAIlB,OAAO,IAAI,OAAO;IAIlB,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,GAAG,oBAAoB;IAI9D,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB;IAIpD,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB;CAGrD"}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { MAX_PROTOCOL_CONTRACTS } from '@aztec/constants';
|
|
2
|
-
import { toBigIntBE } from '@aztec/foundation/bigint-buffer';
|
|
3
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
4
|
-
import { schemas } from '@aztec/foundation/schemas';
|
|
5
|
-
import { BufferReader } from '@aztec/foundation/serialize';
|
|
6
|
-
import { z } from 'zod';
|
|
7
|
-
/**
|
|
8
|
-
* Class containing the data of a preimage of a single leaf in the protocol contract tree.
|
|
9
|
-
* Note: It's called preimage because this data gets hashed before being inserted as a node into the `IndexedTree`.
|
|
10
|
-
* Note: Though this tree contains addresses, they are converted to fields to avoid unnecessary conversions in the tree.
|
|
11
|
-
*/ export class ProtocolContractLeafPreimage {
|
|
12
|
-
address;
|
|
13
|
-
nextAddress;
|
|
14
|
-
nextIndex;
|
|
15
|
-
constructor(/**
|
|
16
|
-
* Leaf value inside the indexed tree's linked list.
|
|
17
|
-
*/ address, /**
|
|
18
|
-
* Next value inside the indexed tree's linked list.
|
|
19
|
-
*/ nextAddress, /**
|
|
20
|
-
* Index of the next leaf in the indexed tree's linked list.
|
|
21
|
-
*/ nextIndex){
|
|
22
|
-
this.address = address;
|
|
23
|
-
this.nextAddress = nextAddress;
|
|
24
|
-
this.nextIndex = nextIndex;
|
|
25
|
-
}
|
|
26
|
-
static get schema() {
|
|
27
|
-
return z.object({
|
|
28
|
-
address: schemas.Fr,
|
|
29
|
-
nextAddress: schemas.Fr,
|
|
30
|
-
nextIndex: schemas.BigInt
|
|
31
|
-
}).transform(({ address, nextAddress, nextIndex })=>new ProtocolContractLeafPreimage(address, nextAddress, nextIndex));
|
|
32
|
-
}
|
|
33
|
-
getKey() {
|
|
34
|
-
return this.address.toBigInt();
|
|
35
|
-
}
|
|
36
|
-
getNextKey() {
|
|
37
|
-
return this.nextAddress.toBigInt();
|
|
38
|
-
}
|
|
39
|
-
getNextIndex() {
|
|
40
|
-
return this.nextIndex;
|
|
41
|
-
}
|
|
42
|
-
asLeaf() {
|
|
43
|
-
return new ProtocolContractLeaf(this.address);
|
|
44
|
-
}
|
|
45
|
-
toBuffer() {
|
|
46
|
-
return Buffer.concat(this.toHashInputs());
|
|
47
|
-
}
|
|
48
|
-
toHashInputs() {
|
|
49
|
-
// Note: the protocol contract leaves only hash the value and next value.
|
|
50
|
-
return [
|
|
51
|
-
Buffer.from(this.address.toBuffer()),
|
|
52
|
-
Buffer.from(this.nextAddress.toBuffer())
|
|
53
|
-
];
|
|
54
|
-
}
|
|
55
|
-
toFields() {
|
|
56
|
-
return [
|
|
57
|
-
this.address,
|
|
58
|
-
this.nextAddress,
|
|
59
|
-
new Fr(this.nextIndex)
|
|
60
|
-
];
|
|
61
|
-
}
|
|
62
|
-
static random() {
|
|
63
|
-
return new ProtocolContractLeafPreimage(Fr.random(), Fr.random(), BigInt(Math.floor(Math.random() * 1000) % MAX_PROTOCOL_CONTRACTS));
|
|
64
|
-
}
|
|
65
|
-
static empty() {
|
|
66
|
-
return new ProtocolContractLeafPreimage(Fr.ZERO, Fr.ZERO, 0n);
|
|
67
|
-
}
|
|
68
|
-
static fromBuffer(buffer) {
|
|
69
|
-
const reader = BufferReader.asReader(buffer);
|
|
70
|
-
return new ProtocolContractLeafPreimage(reader.readObject(Fr), reader.readObject(Fr), toBigIntBE(reader.readBytes(32)));
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* An address to be inserted or checked in the protocol contract tree.
|
|
75
|
-
*/ export class ProtocolContractLeaf {
|
|
76
|
-
address;
|
|
77
|
-
constructor(/**
|
|
78
|
-
* Address value.
|
|
79
|
-
*/ address){
|
|
80
|
-
this.address = address;
|
|
81
|
-
}
|
|
82
|
-
getKey() {
|
|
83
|
-
return this.address.toBigInt();
|
|
84
|
-
}
|
|
85
|
-
toBuffer() {
|
|
86
|
-
return this.address.toBuffer();
|
|
87
|
-
}
|
|
88
|
-
isEmpty() {
|
|
89
|
-
return this.address.isZero();
|
|
90
|
-
}
|
|
91
|
-
updateTo(_another) {
|
|
92
|
-
throw new Error('Protocol contract tree is insert only');
|
|
93
|
-
}
|
|
94
|
-
static buildDummy(key) {
|
|
95
|
-
return new ProtocolContractLeaf(new Fr(key));
|
|
96
|
-
}
|
|
97
|
-
static fromBuffer(buf) {
|
|
98
|
-
return new ProtocolContractLeaf(Fr.fromBuffer(buf));
|
|
99
|
-
}
|
|
100
|
-
}
|