Skip to content

Commit eb6053f

Browse files
author
sklppy88
committed
init
1 parent 9d3b351 commit eb6053f

File tree

2 files changed

+54
-26
lines changed

2 files changed

+54
-26
lines changed

yarn-project/circuits.js/src/contract/artifact_hash.ts

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -58,28 +58,56 @@ export function computeArtifactHashPreimage(artifact: ContractArtifact) {
5858
return { privateFunctionRoot, unconstrainedFunctionRoot, metadataHash };
5959
}
6060

61-
export function computeArtifactMetadataHash(artifact: ContractArtifact) {
62-
// TODO: #6021 We need to make sure the artifact is deterministic from any specific compiler run. This relates to selectors not being sorted and being
63-
// apparently random in the order they appear after compiled w/ nargo. We can try to sort this upon loading an artifact.
64-
// TODO: #6021: Should we use the sorted event selectors instead? They'd need to be unique for that.
65-
// Response - The output selectors need to be sorted, because if not noir makes no guarantees on the order of outputs for some reason
61+
const sortAndHashArtifactMetadata = (metadata: Record<string | number, NonNullable<any>>) => {
62+
const obj = structuredClone(metadata);
6663

67-
const metadata = { name: artifact.name, outputs: artifact.outputs };
64+
const sortAndHashNestedObject = (obj: Record<string | number, NonNullable<any>>) => {
65+
if (Array.isArray(obj)) {
66+
for (let i = 0; i < obj.length; i++) {
67+
if (Array.isArray(obj[i]) || (typeof obj[i] === 'object' && obj[i] !== null)) {
68+
obj[i] = sortAndHashNestedObject(obj[i]);
69+
}
70+
}
6871

69-
const exceptions: string[] = [
70-
'AuthRegistry',
71-
'FeeJuice',
72-
'ContractInstanceDeployer',
73-
'ContractClassRegisterer',
74-
'Router',
75-
];
76-
77-
// This is a temporary workaround for the canonical contracts to have deterministic deployments.
78-
if (exceptions.includes(artifact.name)) {
79-
return sha256Fr(Buffer.from(JSON.stringify({ name: artifact.name }), 'utf-8'));
80-
}
72+
const sorted = obj.sort();
73+
74+
const hashed = sha256Fr(Buffer.from(JSON.stringify(sorted), 'utf-8'));
75+
76+
return hashed;
77+
}
78+
79+
if (typeof obj === 'object') {
80+
for (const [key, value] of Object.entries(obj)) {
81+
if (Array.isArray(value) || (typeof value === 'object' && value !== null)) {
82+
obj[key] = sortAndHashNestedObject(value);
83+
}
84+
}
85+
86+
const sorted = Object.keys(obj)
87+
.sort()
88+
.reduce(
89+
(acc, key) => ({
90+
...acc,
91+
[key]: obj[key],
92+
}),
93+
{},
94+
);
95+
96+
const hashed = sha256Fr(Buffer.from(JSON.stringify(sorted), 'utf-8'));
97+
98+
return hashed;
99+
}
100+
101+
throw new Error('Can only be called on an object or array');
102+
};
103+
104+
return sortAndHashNestedObject(obj);
105+
};
106+
107+
export function computeArtifactMetadataHash(artifact: ContractArtifact) {
108+
const metadata = { name: artifact.name, outputs: artifact.outputs };
81109

82-
return sha256Fr(Buffer.from(JSON.stringify(metadata), 'utf-8'));
110+
return sortAndHashArtifactMetadata(metadata);
83111
}
84112

85113
export function computeArtifactFunctionTreeRoot(artifact: ContractArtifact, fnType: FunctionType) {

yarn-project/protocol-contracts/src/protocol_contract_data.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,14 @@ export const ProtocolContractAddress: Record<ProtocolContractName, AztecAddress>
5050
};
5151

5252
export const ProtocolContractLeaf = {
53-
AuthRegistry: Fr.fromString('0x04d70cb3d8222ae04cfa59e8bfed4f804832aaaef4f485d1debb004d1b9d6362'),
54-
ContractInstanceDeployer: Fr.fromString('0x04a661c9d4d295fc485a7e0f3de40c09b35366343bce8ad229106a8ef4076fe5'),
55-
ContractClassRegisterer: Fr.fromString('0x147ba3294403576dbad10f86d3ffd4eb83fb230ffbcd5c8b153dd02942d0611f'),
56-
MultiCallEntrypoint: Fr.fromString('0x154b701b41d6cf6da7204fef36b2ee9578b449d21b3792a9287bf45eba48fd26'),
57-
FeeJuice: Fr.fromString('0x1067e9dc15d3046b6d21aaa8eafcfec88216217242cee3f9d722165ffc03c767'),
58-
Router: Fr.fromString('0x16ab75e4efc0964c0ee3d715ac645d7972b722bfe60eea730a60b527c0681973'),
53+
AuthRegistry: Fr.fromString('0x1f8bfccaf4965336c66ffb52c7b39b9637105f019ac5f4d795e7ba3b3398a34a'),
54+
ContractInstanceDeployer: Fr.fromString('0x08b46b68aea276ffcf07c6b46d9bf4397d51a589a63b8b25f364fea25e2071e9'),
55+
ContractClassRegisterer: Fr.fromString('0x18a38fb40d939fa5e6d452918f6c3955a3bda92088579634fb4d36392048516f'),
56+
MultiCallEntrypoint: Fr.fromString('0x1bace4b543ec90410c8427b13c9d6609f649ab878c9d50c615ec821c77571e3e'),
57+
FeeJuice: Fr.fromString('0x1de6b0dace07dabe41559101f328fe3ab628b67439fccf8d3921199de6da0c50'),
58+
Router: Fr.fromString('0x1bfe36b062c01de3567f477c9ee7d9e1306edfe3296123906506b8d7ab7cd9d9'),
5959
};
6060

6161
export const protocolContractTreeRoot = Fr.fromString(
62-
'0x2673f1d0618d2c98ccb3a11282073002f73335c4791eac16f67bf522e24151d1',
62+
'0x2cb2aa3df6e2339c2ad3c20a8279e24eaf1bbb3e341c1af6296ea587c248ce72',
6363
);

0 commit comments

Comments
 (0)