prividium 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +8 -1
- package/dist/cli/base-cli.d.ts +5 -0
- package/dist/cli/base-cli.js +11 -0
- package/dist/cli/commands/config.d.ts +2 -0
- package/dist/cli/commands/doctor/clients/browser-auth.d.ts +1 -0
- package/dist/cli/commands/doctor/clients/http.d.ts +3 -0
- package/dist/cli/commands/doctor/clients/rpc.d.ts +19 -0
- package/dist/cli/commands/doctor/clients/wallet-api.d.ts +7 -0
- package/dist/cli/commands/doctor/constants.d.ts +1 -0
- package/dist/cli/commands/doctor/probes/authentication/authentication.d.ts +4 -0
- package/dist/cli/commands/doctor/probes/authentication/wallet-preconditions.d.ts +2 -0
- package/dist/cli/commands/doctor/probes/authentication.d.ts +2 -0
- package/dist/cli/commands/doctor/probes/bridging/bridging.d.ts +5 -0
- package/dist/cli/commands/doctor/probes/bridging.d.ts +2 -0
- package/dist/cli/commands/doctor/probes/global/input-validation.d.ts +3 -0
- package/dist/cli/commands/doctor/probes/global/reachability.d.ts +5 -0
- package/dist/cli/commands/doctor/probes/global.d.ts +2 -0
- package/dist/cli/commands/doctor/probes/wallet/authenticated-rpc.d.ts +3 -0
- package/dist/cli/commands/doctor/probes/wallet/authorization-and-wallet-rpc.d.ts +5 -0
- package/dist/cli/commands/doctor/probes/wallet-api.d.ts +2 -0
- package/dist/cli/commands/doctor/probes/wallet.d.ts +2 -0
- package/dist/cli/commands/doctor/profile.d.ts +12 -0
- package/dist/cli/commands/doctor/report/build.d.ts +2 -0
- package/dist/cli/commands/doctor/report/render.d.ts +2 -0
- package/dist/cli/commands/doctor/stages.d.ts +2 -0
- package/dist/cli/commands/doctor/types.d.ts +90 -0
- package/dist/cli/commands/doctor/utils.d.ts +18 -0
- package/dist/cli/commands/doctor.d.ts +2 -0
- package/dist/cli/commands/proxy.d.ts +2 -0
- package/dist/cli/{cli/commands → commands}/proxy.js +1 -3
- package/dist/cli/commands/utils/schemas.d.ts +3 -0
- package/dist/cli/commands/utils/schemas.js +3 -0
- package/dist/cli/commands/utils/show-prividium-header.d.ts +2 -0
- package/dist/cli/commands/utils/url-config.d.ts +18 -0
- package/dist/cli/commands/verify/account-data-cmd.d.ts +14 -0
- package/dist/cli/commands/verify/account-data-cmd.js +102 -0
- package/dist/cli/commands/verify/erc20-balance-cmd.d.ts +17 -0
- package/dist/cli/commands/verify/erc20-balance-cmd.js +111 -0
- package/dist/cli/commands/verify/erc20-supply-cmd.d.ts +16 -0
- package/dist/cli/commands/verify/erc20-supply-cmd.js +102 -0
- package/dist/cli/commands/verify/utils.d.ts +5 -0
- package/dist/cli/commands/verify/utils.js +38 -0
- package/dist/cli/commands/verify/verify-workflow.d.ts +8 -0
- package/dist/cli/commands/verify/verify-workflow.js +41 -0
- package/dist/cli/commands/verify.d.ts +18 -0
- package/dist/cli/commands/verify.js +43 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +11 -0
- package/dist/cli/server/config-file.d.ts +62 -0
- package/dist/cli/server/config-file.js +167 -0
- package/dist/cli/server/connection-workflow.d.ts +12 -0
- package/dist/cli/server/server.d.ts +28 -0
- package/dist/sdk/create-prividium-client.d.ts +1 -1
- package/dist/sdk/create-prividium-client.js +1 -1
- package/dist/sdk/selective-disclosure/account-properties.d.ts +7 -1
- package/dist/sdk/selective-disclosure/account-properties.js +22 -10
- package/dist/sdk/selective-disclosure/utils.d.ts +2 -0
- package/dist/sdk/selective-disclosure/utils.js +3 -0
- package/dist/sdk/selective-disclosure/verify-disclosure.d.ts +35 -12
- package/dist/sdk/selective-disclosure/verify-disclosure.js +60 -25
- package/dist/tsconfig.cli.tsbuildinfo +1 -0
- package/dist/tsconfig.sdk.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/dist/cli/cli/base-cli.js +0 -9
- package/dist/cli/cli/index.js +0 -13
- package/dist/cli/cli/server/config-file.js +0 -78
- package/dist/cli/src/error-utils.js +0 -73
- package/dist/cli/src/memory-storage.js +0 -12
- package/dist/cli/src/rpc-error-codes.js +0 -28
- package/dist/cli/src/siwe-auth.js +0 -70
- package/dist/cli/src/storage.js +0 -142
- package/dist/cli/src/types.js +0 -46
- package/dist/cli/tsconfig.cli.tsbuildinfo +0 -1
- /package/dist/cli/cli/{static/callback.html → callback.html} +0 -0
- /package/dist/cli/cli/{static/start.html → start.html} +0 -0
- /package/dist/cli/{cli/commands → commands}/config.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/clients/browser-auth.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/clients/http.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/clients/rpc.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/clients/wallet-api.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/constants.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/probes/authentication/authentication.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/probes/authentication/wallet-preconditions.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/probes/authentication.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/probes/bridging/bridging.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/probes/bridging.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/probes/global/input-validation.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/probes/global/reachability.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/probes/global.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/probes/wallet/authenticated-rpc.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/probes/wallet/authorization-and-wallet-rpc.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/probes/wallet-api.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/probes/wallet.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/profile.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/report/build.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/report/render.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/stages.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/types.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor/utils.js +0 -0
- /package/dist/cli/{cli/commands → commands}/doctor.js +0 -0
- /package/dist/cli/{cli/commands → commands}/utils/show-prividium-header.js +0 -0
- /package/dist/cli/{cli/commands → commands}/utils/url-config.js +0 -0
- /package/dist/cli/{cli/server → server}/connection-workflow.js +0 -0
- /package/dist/cli/{cli/server → server}/server.js +0 -0
|
@@ -12,29 +12,52 @@ export declare const DIAMOND_ABI: {
|
|
|
12
12
|
readonly type: "bytes32";
|
|
13
13
|
}];
|
|
14
14
|
}[];
|
|
15
|
+
export type CallDisclosureResult = {
|
|
16
|
+
success: true;
|
|
17
|
+
} | {
|
|
18
|
+
success: false;
|
|
19
|
+
errorMsg: string;
|
|
20
|
+
};
|
|
21
|
+
type VerifyEthCallDisclosureParams = {
|
|
22
|
+
disclosure: EthCallDisclosureResult;
|
|
23
|
+
l1Client: PublicClient;
|
|
24
|
+
l2Client: PublicClient;
|
|
25
|
+
diamondAddress: Address;
|
|
26
|
+
contractBytecodes: Record<Address, Hex>;
|
|
27
|
+
batchNumber: number;
|
|
28
|
+
expectedTo?: Address;
|
|
29
|
+
expectedCallData?: Hex;
|
|
30
|
+
};
|
|
15
31
|
/**
|
|
16
32
|
* Verifies an ethCall disclosure response end-to-end.
|
|
17
33
|
*
|
|
18
34
|
* Verification steps:
|
|
19
|
-
* 1.
|
|
20
|
-
* 2.
|
|
21
|
-
* 3.
|
|
22
|
-
* 4.
|
|
35
|
+
* 1. Checks the disclosure's `to` and `callData` match `expectedTo` / `expectedCallData` when provided.
|
|
36
|
+
* 2. Extracts Merkle roots from all storage proofs and checks they are consistent.
|
|
37
|
+
* 3. Computes the state commitment from the tree root and preimage data.
|
|
38
|
+
* 4. Encodes the batch info, hashes it, and compares against the L1 diamond proxy's `storedBatchHash`.
|
|
39
|
+
* 5. Replays the original call on `l2Client` with state overrides (proven storage + bytecodes)
|
|
23
40
|
* and checks the result matches the disclosed value.
|
|
24
41
|
*
|
|
25
42
|
* Throws if the disclosure data is internally inconsistent (e.g. no proofs, divergent roots,
|
|
26
43
|
* or missing bytecode for a contract referenced in the proofs).
|
|
27
44
|
*
|
|
28
|
-
* Returns `true` if every check passes, `false
|
|
45
|
+
* Returns `{ success: true }` if every check passes, otherwise `{ success: false, errorMsg }`.
|
|
29
46
|
*
|
|
30
|
-
* @param
|
|
31
|
-
* @param
|
|
32
|
-
* @param
|
|
47
|
+
* @param params - A single object holding all verification inputs:
|
|
48
|
+
* @param params.disclosure - The response from `prividium_tokenSupplyDisclosure` or `prividium_tokenBalanceDisclosure`.
|
|
49
|
+
* @param params.l1Client - A viem PublicClient connected to L1, used to read `storedBatchHash` from the diamond proxy.
|
|
50
|
+
* @param params.l2Client - A viem PublicClient connected to a local L2 node trusted by the caller. Used to
|
|
33
51
|
* replay the disclosed call with state overrides. This must be a node the caller trusts, not the
|
|
34
52
|
* Prividium proxy, so the replay cannot be manipulated.
|
|
35
|
-
* @param diamondAddress - The address of the L1 diamond proxy contract that stores batch commitments.
|
|
36
|
-
* @param contractBytecodes - A mapping from contract address to deployed bytecode (hex) for every
|
|
53
|
+
* @param params.diamondAddress - The address of the L1 diamond proxy contract that stores batch commitments.
|
|
54
|
+
* @param params.contractBytecodes - A mapping from contract address to deployed bytecode (hex) for every
|
|
37
55
|
* contract referenced in the disclosure proofs. Used for the call replay with state overrides.
|
|
38
|
-
* @param batchNumber - The L1 batch number the disclosure was computed against.
|
|
56
|
+
* @param params.batchNumber - The L1 batch number the disclosure was computed against.
|
|
57
|
+
* @param params.expectedTo - Optional. The address the disclosed call was expected to target; when set,
|
|
58
|
+
* verification fails if it does not match `disclosure.to` (case-insensitive).
|
|
59
|
+
* @param params.expectedCallData - Optional. The calldata the disclosed call was expected to use; when
|
|
60
|
+
* set, verification fails if it does not match `disclosure.callData` (case-insensitive).
|
|
39
61
|
*/
|
|
40
|
-
export declare function verifyEthCallDisclosure(disclosure
|
|
62
|
+
export declare function verifyEthCallDisclosure({ disclosure, l1Client, l2Client, diamondAddress, contractBytecodes, batchNumber, expectedTo, expectedCallData }: VerifyEthCallDisclosureParams): Promise<CallDisclosureResult>;
|
|
63
|
+
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { keccak256, pad, parseAbiItem } from 'viem';
|
|
2
2
|
import { encodeBatchInfo } from './batch-info.js';
|
|
3
3
|
import { computeStateCommitment } from './state-commitment.js';
|
|
4
|
+
import { areHexEqual } from './utils.js';
|
|
4
5
|
import { calculateStateMerkleRoot } from './verifiy-proofs.js';
|
|
5
6
|
export const DIAMOND_ABI = [
|
|
6
7
|
parseAbiItem('function storedBatchHash(uint256 _batchNumber) external view returns (bytes32)')
|
|
@@ -35,29 +36,46 @@ const tracerStr = `{
|
|
|
35
36
|
* Verifies an ethCall disclosure response end-to-end.
|
|
36
37
|
*
|
|
37
38
|
* Verification steps:
|
|
38
|
-
* 1.
|
|
39
|
-
* 2.
|
|
40
|
-
* 3.
|
|
41
|
-
* 4.
|
|
39
|
+
* 1. Checks the disclosure's `to` and `callData` match `expectedTo` / `expectedCallData` when provided.
|
|
40
|
+
* 2. Extracts Merkle roots from all storage proofs and checks they are consistent.
|
|
41
|
+
* 3. Computes the state commitment from the tree root and preimage data.
|
|
42
|
+
* 4. Encodes the batch info, hashes it, and compares against the L1 diamond proxy's `storedBatchHash`.
|
|
43
|
+
* 5. Replays the original call on `l2Client` with state overrides (proven storage + bytecodes)
|
|
42
44
|
* and checks the result matches the disclosed value.
|
|
43
45
|
*
|
|
44
46
|
* Throws if the disclosure data is internally inconsistent (e.g. no proofs, divergent roots,
|
|
45
47
|
* or missing bytecode for a contract referenced in the proofs).
|
|
46
48
|
*
|
|
47
|
-
* Returns `true` if every check passes, `false
|
|
49
|
+
* Returns `{ success: true }` if every check passes, otherwise `{ success: false, errorMsg }`.
|
|
48
50
|
*
|
|
49
|
-
* @param
|
|
50
|
-
* @param
|
|
51
|
-
* @param
|
|
51
|
+
* @param params - A single object holding all verification inputs:
|
|
52
|
+
* @param params.disclosure - The response from `prividium_tokenSupplyDisclosure` or `prividium_tokenBalanceDisclosure`.
|
|
53
|
+
* @param params.l1Client - A viem PublicClient connected to L1, used to read `storedBatchHash` from the diamond proxy.
|
|
54
|
+
* @param params.l2Client - A viem PublicClient connected to a local L2 node trusted by the caller. Used to
|
|
52
55
|
* replay the disclosed call with state overrides. This must be a node the caller trusts, not the
|
|
53
56
|
* Prividium proxy, so the replay cannot be manipulated.
|
|
54
|
-
* @param diamondAddress - The address of the L1 diamond proxy contract that stores batch commitments.
|
|
55
|
-
* @param contractBytecodes - A mapping from contract address to deployed bytecode (hex) for every
|
|
57
|
+
* @param params.diamondAddress - The address of the L1 diamond proxy contract that stores batch commitments.
|
|
58
|
+
* @param params.contractBytecodes - A mapping from contract address to deployed bytecode (hex) for every
|
|
56
59
|
* contract referenced in the disclosure proofs. Used for the call replay with state overrides.
|
|
57
|
-
* @param batchNumber - The L1 batch number the disclosure was computed against.
|
|
60
|
+
* @param params.batchNumber - The L1 batch number the disclosure was computed against.
|
|
61
|
+
* @param params.expectedTo - Optional. The address the disclosed call was expected to target; when set,
|
|
62
|
+
* verification fails if it does not match `disclosure.to` (case-insensitive).
|
|
63
|
+
* @param params.expectedCallData - Optional. The calldata the disclosed call was expected to use; when
|
|
64
|
+
* set, verification fails if it does not match `disclosure.callData` (case-insensitive).
|
|
58
65
|
*/
|
|
59
|
-
export async function verifyEthCallDisclosure(disclosure, l1Client, l2Client, diamondAddress, contractBytecodes, batchNumber) {
|
|
60
|
-
|
|
66
|
+
export async function verifyEthCallDisclosure({ disclosure, l1Client, l2Client, diamondAddress, contractBytecodes, batchNumber, expectedTo, expectedCallData }) {
|
|
67
|
+
const normalizedBytecodes = Object.entries(contractBytecodes).reduce((obj, [key, value]) => {
|
|
68
|
+
obj[key.toLowerCase()] = value;
|
|
69
|
+
return obj;
|
|
70
|
+
}, {});
|
|
71
|
+
// Step 1: Verify expected data match
|
|
72
|
+
if (expectedTo !== undefined && !areHexEqual(expectedTo, disclosure.to)) {
|
|
73
|
+
return { success: false, errorMsg: '"to" field doesn\'t match with expected value' };
|
|
74
|
+
}
|
|
75
|
+
if (expectedCallData !== undefined && !areHexEqual(expectedCallData, disclosure.callData)) {
|
|
76
|
+
return { success: false, errorMsg: '"callData" field doesn\'t match with expected value' };
|
|
77
|
+
}
|
|
78
|
+
// Step 2: Extract Merkle roots from all storage proofs and verify they're consistent.
|
|
61
79
|
const roots = [];
|
|
62
80
|
for (const proof of disclosure.proofs) {
|
|
63
81
|
for (const storageProof of proof.storageProofs) {
|
|
@@ -71,26 +89,32 @@ export async function verifyEthCallDisclosure(disclosure, l1Client, l2Client, di
|
|
|
71
89
|
if (new Set(roots).size !== 1) {
|
|
72
90
|
throw new Error('Inconsistent data: multiple roots for same batch');
|
|
73
91
|
}
|
|
74
|
-
// Step
|
|
92
|
+
// Step 3: Compute state commitment from the tree root + preimage data.
|
|
75
93
|
const stateCommitment = computeStateCommitment(roots[0], BigInt(disclosure.stateCommitmentPreimage.nextFreeSlot), BigInt(disclosure.stateCommitmentPreimage.blockNumber), disclosure.stateCommitmentPreimage.last256BlockHashesBlake, BigInt(disclosure.stateCommitmentPreimage.lastBlockTimestamp));
|
|
76
|
-
// Step
|
|
94
|
+
// Step 4: Encode batch info and keccak256 hash it.
|
|
77
95
|
const batchInfoHex = encodeBatchInfo(BigInt(batchNumber), stateCommitment, BigInt(disclosure.l1VerificationData.numberOfLayer1Txs), disclosure.l1VerificationData.priorityOperationsHash, disclosure.l1VerificationData.l2ToL1LogsRootHash, disclosure.l1VerificationData.commitment);
|
|
78
96
|
const batchInfoHash = keccak256(batchInfoHex);
|
|
79
|
-
// Step
|
|
80
|
-
const storedBatchHash = await l1Client
|
|
97
|
+
// Step 5: Verify against L1 diamond proxy.
|
|
98
|
+
const storedBatchHash = await l1Client
|
|
99
|
+
.readContract({
|
|
81
100
|
address: diamondAddress,
|
|
82
101
|
abi: DIAMOND_ABI,
|
|
83
102
|
functionName: 'storedBatchHash',
|
|
84
103
|
args: [BigInt(batchNumber)]
|
|
104
|
+
})
|
|
105
|
+
.catch((e) => {
|
|
106
|
+
throw new Error('Error reading l1 diamond', { cause: e });
|
|
85
107
|
});
|
|
86
|
-
if (batchInfoHash
|
|
87
|
-
return false;
|
|
108
|
+
if (!areHexEqual(batchInfoHash, storedBatchHash)) {
|
|
109
|
+
return { success: false, errorMsg: 'L1 batch commitment does not match the proof data' };
|
|
88
110
|
}
|
|
111
|
+
// Step 6: Replay the call on L2 with state overrides to verify the proven
|
|
112
|
+
// and debug capabilities storage values produce the expected result using the same slots.
|
|
89
113
|
const contractAddress = disclosure.to;
|
|
90
114
|
const stateOverride = {};
|
|
91
115
|
for (const proof of disclosure.proofs) {
|
|
92
116
|
const address = proof.address.toLowerCase();
|
|
93
|
-
const code =
|
|
117
|
+
const code = normalizedBytecodes[address];
|
|
94
118
|
if (!code) {
|
|
95
119
|
throw new Error(`Missing bytecode for contract ${address}`);
|
|
96
120
|
}
|
|
@@ -119,18 +143,29 @@ export async function verifyEthCallDisclosure(disclosure, l1Client, l2Client, di
|
|
|
119
143
|
]
|
|
120
144
|
});
|
|
121
145
|
if (!debugResult.success) {
|
|
122
|
-
return false;
|
|
146
|
+
return { success: false, errorMsg: 'Error during simulated call' };
|
|
123
147
|
}
|
|
148
|
+
// 7. Check that no slot reads were outside the expected proven slots.
|
|
124
149
|
for (const address in debugResult.reads) {
|
|
125
150
|
for (const slot of debugResult.reads[address]) {
|
|
126
151
|
const realSlot = `0x${slot}`;
|
|
127
|
-
const exists = disclosure.proofs.find((p) => p.address
|
|
152
|
+
const exists = disclosure.proofs.find((p) => areHexEqual(p.address, address) &&
|
|
128
153
|
p.storageProofs.some((sp) => BigInt(sp.key) === BigInt(realSlot)));
|
|
129
154
|
if (!exists) {
|
|
130
|
-
return
|
|
155
|
+
return {
|
|
156
|
+
success: false,
|
|
157
|
+
errorMsg: `Missing slot in provided proofs: ${realSlot}`
|
|
158
|
+
};
|
|
131
159
|
}
|
|
132
160
|
}
|
|
133
161
|
}
|
|
134
|
-
|
|
135
|
-
|
|
162
|
+
if (BigInt(debugResult.value) === BigInt(disclosure.result)) {
|
|
163
|
+
return { success: true };
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
return {
|
|
167
|
+
success: false,
|
|
168
|
+
errorMsg: `Simulated call did not match with expected value. Expected: ${disclosure.result}, received: ${debugResult.value}`
|
|
169
|
+
};
|
|
170
|
+
}
|
|
136
171
|
}
|