Skip to content

Commit d6d968b

Browse files
authored
feat: merge-train/avm (#23618)
See [merge-train-readme.md](https://github.com/AztecProtocol/aztec-packages/blob/next/.github/workflows/merge-train-readme.md). This is a merge-train.
2 parents f278b8b + 17cf1e9 commit d6d968b

83 files changed

Lines changed: 4940 additions & 4584 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

barretenberg/cpp/pil/vm2/bytecode/address_derivation.pil

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ include "../scalar_mul.pil";
1313
* 2. partial_address = H(DOM_SEP__PARTIAL_ADDRESS, class_id, salted_init_hash)
1414
* 3. incoming_viewing_key_hash = H(DOM_SEP__SINGLE_PUBLIC_KEY_HASH, incoming_viewing_key_x, incoming_viewing_key_y)
1515
* 4. public_keys_hash = H(DOM_SEP__PUBLIC_KEYS_HASH,
16-
* nullifier_key_hash, incoming_viewing_key_hash, outgoing_viewing_key_hash, tagging_key_hash)
16+
* nullifier_key_hash, incoming_viewing_key_hash, outgoing_viewing_key_hash, tagging_key_hash,
17+
* message_signing_key_hash, fallback_key_hash)
1718
* 5. preaddress = H(DOM_SEP__CONTRACT_ADDRESS_V2, public_keys_hash, partial_address)
1819
* 6. preaddress_public_key = preaddress * G1
1920
* 7. address = (preaddress_public_key + incoming_viewing_key).x
@@ -22,10 +23,10 @@ include "../scalar_mul.pil";
2223
* curve. See the 'Hash Computations', 'Elliptic Curve Operations', and 'INTERACTIONS' sections
2324
* for details on how we enforce each step. This process follows Noir's AztecAddress::compute().
2425
*
25-
* Per AZIP-8: only `incoming_viewing_key` is exposed to the circuit as a Grumpkin point (since
26-
* address derivation needs the curve point). The other three master public keys (nullifier,
27-
* outgoing viewing, tagging) are exposed only as their hash digests under
28-
* DOM_SEP__SINGLE_PUBLIC_KEY_HASH; the PXE computes those hashes off-circuit and the circuit
26+
* Only `incoming_viewing_key` is exposed to the circuit as a Grumpkin point (since
27+
* address derivation needs the curve point). The other five master public keys (nullifier,
28+
* outgoing viewing, tagging, message-signing, fallback) are exposed only as their hash digests
29+
* under DOM_SEP__SINGLE_PUBLIC_KEY_HASH; the PXE computes those hashes off-circuit and the circuit
2930
* trusts them.
3031
*
3132
* PRECONDITIONS: The correctness of the preimage members is not constrained here and must be
@@ -43,14 +44,18 @@ include "../scalar_mul.pil";
4344
* nullifier_key_hash,
4445
* incoming_viewing_key_x, incoming_viewing_key_y,
4546
* outgoing_viewing_key_hash,
46-
* tagging_key_hash
47+
* tagging_key_hash,
48+
* message_signing_key_hash,
49+
* fallback_key_hash
4750
* } in address_derivation.sel {
4851
* address_derivation.address, address_derivation.salt, address_derivation.deployer_addr,
4952
* address_derivation.class_id, address_derivation.init_hash,
5053
* address_derivation.nullifier_key_hash,
5154
* address_derivation.incoming_viewing_key_x, address_derivation.incoming_viewing_key_y,
5255
* address_derivation.outgoing_viewing_key_hash,
53-
* address_derivation.tagging_key_hash
56+
* address_derivation.tagging_key_hash,
57+
* address_derivation.message_signing_key_hash,
58+
* address_derivation.fallback_key_hash
5459
* };
5560
*
5661
* TRACE SHAPE: 1 row per address derivation computation. Note that simulation deduplicates addresses
@@ -67,11 +72,11 @@ include "../scalar_mul.pil";
6772
* the retrieved contract instance and public keys (#[ADDRESS_DERIVATION]).
6873
*
6974
* This subtrace looks up:
70-
* - poseidon2_hash.pil: To constrain five Poseidon2 hashes across a total of 7 lookups/rounds:
75+
* - poseidon2_hash.pil: To constrain five Poseidon2 hashes across a total of 8 lookups/rounds:
7176
* - salted_init_hash: #[SALTED_INITIALIZATION_HASH_POSEIDON2_0..1]
7277
* - partial_address: #[PARTIAL_ADDRESS_POSEIDON2]
7378
* - incoming_viewing_key_hash: #[IVPK_M_HASH_POSEIDON2]
74-
* - public_keys_hash: #[PUBLIC_KEYS_HASH_POSEIDON2_0..1]
79+
* - public_keys_hash: #[PUBLIC_KEYS_HASH_POSEIDON2_0..2]
7580
* - preaddress: #[PREADDRESS_POSEIDON2]
7681
* - scalar_mul.pil: To constrain that preaddress_public_key = preaddress * G1 on Grumpkin: #[PREADDRESS_SCALAR_MUL]
7782
* - ecc.pil: To constrain that address = (preaddress_public_key + incoming_viewing_key).x on Grumpkin: #[ADDRESS_ECADD]
@@ -100,13 +105,15 @@ namespace address_derivation;
100105
pol commit immutables_hash;
101106

102107
// Public keys (see PublicKeys in barretenberg/cpp/src/barretenberg/vm2/common/aztec_types.hpp).
103-
// Per AZIP-8, only incoming_viewing_key is held as a Grumpkin point; the other three keys
108+
// Only incoming_viewing_key is held as a Grumpkin point; the other five keys
104109
// are held as their (off-circuit) hashes.
105110
pol commit nullifier_key_hash;
106111
pol commit incoming_viewing_key_x;
107112
pol commit incoming_viewing_key_y;
108113
pol commit outgoing_viewing_key_hash;
109114
pol commit tagging_key_hash;
115+
pol commit message_signing_key_hash;
116+
pol commit fallback_key_hash;
110117

111118

112119
///////////////////////////////
@@ -118,15 +125,20 @@ namespace address_derivation;
118125
// 2. partial_address = H(DOM_SEP__PARTIAL_ADDRESS, class_id, salted_init_hash)
119126
// 3. incoming_viewing_key_hash = H(DOM_SEP__SINGLE_PUBLIC_KEY_HASH, incoming_viewing_key_x, incoming_viewing_key_y)
120127
// 4. public_keys_hash = H(DOM_SEP__PUBLIC_KEYS_HASH,
121-
// nullifier_key_hash, incoming_viewing_key_hash, outgoing_viewing_key_hash, tagging_key_hash)
128+
// nullifier_key_hash, incoming_viewing_key_hash, outgoing_viewing_key_hash,
129+
// tagging_key_hash, message_signing_key_hash, fallback_key_hash)
122130
// 5. preaddress = H(DOM_SEP__CONTRACT_ADDRESS_V2, public_keys_hash, partial_address)
123131
//
124132

125133
// Lookup constant support: Can be removed when we support constants in lookups.
134+
pol commit const_two;
135+
sel * (const_two - 2) = 0;
126136
pol commit const_three;
127137
sel * (const_three - 3) = 0;
128138
pol commit const_five;
129139
sel * (const_five - 5) = 0;
140+
pol commit const_seven;
141+
sel * (const_seven - 7) = 0;
130142
pol commit salted_init_hash_domain_separator;
131143
sel * (salted_init_hash_domain_separator - constants.DOM_SEP__SALTED_INITIALIZATION_HASH) = 0;
132144
pol commit partial_address_domain_separator;
@@ -184,23 +196,30 @@ namespace address_derivation;
184196
sel { single_public_key_hash_domain_separator, incoming_viewing_key_x, incoming_viewing_key_y, incoming_viewing_key_hash, const_three }
185197
in poseidon2_hash.start { poseidon2_hash.input_0, poseidon2_hash.input_1, poseidon2_hash.input_2, poseidon2_hash.output, poseidon2_hash.input_len };
186198

187-
// 4. Computation of public keys hash from the four single-key hashes.
199+
// 4. Computation of public keys hash from the six single-key hashes.
188200
pol commit public_keys_hash;
189201

190-
// We have 5 inputs (DOM_SEP + 4 hashes), hence 2 permutation rounds:
191-
// public_keys_hash = H(DOM_SEP__PUBLIC_KEYS_HASH, npk_m_hash, incoming_viewing_key_hash, ovpk_m_hash, tpk_m_hash)
192-
// Round 1 (start, input_len=5): (DOM_SEP__PUBLIC_KEYS_HASH, npk_m_hash, incoming_viewing_key_hash)
193-
// Round 2 (end): (ovpk_m_hash, tpk_m_hash, 0)
202+
// We have 7 inputs (DOM_SEP + 6 hashes), hence 3 permutation rounds:
203+
// public_keys_hash = H(DOM_SEP__PUBLIC_KEYS_HASH, npk_m_hash, incoming_viewing_key_hash,
204+
// ovpk_m_hash, tpk_m_hash, mspk_m_hash, fbpk_m_hash)
205+
// Round 1 (start, input_len=7): (DOM_SEP__PUBLIC_KEYS_HASH, npk_m_hash, incoming_viewing_key_hash)
206+
// Round 2 (middle, num_perm_rounds_rem=2): (ovpk_m_hash, tpk_m_hash, mspk_m_hash)
207+
// Round 3 (end, num_perm_rounds_rem=1): (fbpk_m_hash, 0, 0)
194208

195-
// Enforces the first poseidon round of public_keys_hash. Note that we must lookup poseidon2_hash.input_len == 5
209+
// Enforces the first poseidon round of public_keys_hash. Note that we must lookup poseidon2_hash.input_len == 7
196210
// here since it is constrained in the poseidon trace on the start row.
197211
#[PUBLIC_KEYS_HASH_POSEIDON2_0]
198-
sel { public_keys_hash_domain_separator, nullifier_key_hash, incoming_viewing_key_hash, public_keys_hash, const_five }
212+
sel { public_keys_hash_domain_separator, nullifier_key_hash, incoming_viewing_key_hash, public_keys_hash, const_seven }
199213
in poseidon2_hash.start { poseidon2_hash.input_0, poseidon2_hash.input_1, poseidon2_hash.input_2, poseidon2_hash.output, poseidon2_hash.input_len };
200214

201-
// Enforces the second and final round of public_keys_hash. Note that we must enforce the padded value is zero here.
215+
// Enforces the middle (second) round of public_keys_hash via the multi-row recipe.
202216
#[PUBLIC_KEYS_HASH_POSEIDON2_1]
203-
sel { outgoing_viewing_key_hash, tagging_key_hash, precomputed.zero, public_keys_hash }
217+
sel { outgoing_viewing_key_hash, tagging_key_hash, message_signing_key_hash, public_keys_hash, const_two }
218+
in poseidon2_hash.sel { poseidon2_hash.input_0, poseidon2_hash.input_1, poseidon2_hash.input_2, poseidon2_hash.output, poseidon2_hash.num_perm_rounds_rem };
219+
220+
// Enforces the third and final round of public_keys_hash. Note that we must enforce the padded values are zero here.
221+
#[PUBLIC_KEYS_HASH_POSEIDON2_2]
222+
sel { fallback_key_hash, precomputed.zero, precomputed.zero, public_keys_hash }
204223
in poseidon2_hash.end { poseidon2_hash.input_0, poseidon2_hash.input_1, poseidon2_hash.input_2, poseidon2_hash.output };
205224

206225
// 5. Computation of preaddress

barretenberg/cpp/pil/vm2/bytecode/contract_instance_retrieval.pil

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,14 +118,16 @@ namespace contract_instance_retrieval;
118118
// or is just assigned "address" (from input) for non-protocol contracts.
119119
pol commit derived_address;
120120

121-
// Public keys (all hinted). Per AZIP-8, only the incoming viewing key is exchanged with the
122-
// address derivation circuit as a Grumpkin point; the other three are hashes computed
121+
// Public keys (all hinted). Only the incoming viewing key is exchanged with the
122+
// address derivation circuit as a Grumpkin point; the other five are hashes computed
123123
// off-circuit by the PXE.
124124
pol commit nullifier_key_hash;
125125
pol commit incoming_viewing_key_x;
126126
pol commit incoming_viewing_key_y;
127127
pol commit outgoing_viewing_key_hash;
128128
pol commit tagging_key_hash;
129+
pol commit message_signing_key_hash;
130+
pol commit fallback_key_hash;
129131

130132
// ==== Determine if It Is a Protocol Contract (<= max) ====
131133

@@ -260,7 +262,9 @@ namespace contract_instance_retrieval;
260262
incoming_viewing_key_x,
261263
incoming_viewing_key_y,
262264
outgoing_viewing_key_hash,
263-
tagging_key_hash
265+
tagging_key_hash,
266+
message_signing_key_hash,
267+
fallback_key_hash
264268
} in address_derivation.sel {
265269
address_derivation.address,
266270
address_derivation.salt,
@@ -272,7 +276,9 @@ namespace contract_instance_retrieval;
272276
address_derivation.incoming_viewing_key_x,
273277
address_derivation.incoming_viewing_key_y,
274278
address_derivation.outgoing_viewing_key_hash,
275-
address_derivation.tagging_key_hash
279+
address_derivation.tagging_key_hash,
280+
address_derivation.message_signing_key_hash,
281+
address_derivation.fallback_key_hash
276282
};
277283

278284
// ==== Constrain That "current" Class ID Truly Is Current (Non-protocol Contracts That Exist) ====

barretenberg/cpp/src/barretenberg/avm_fuzzer/fuzz_lib/fuzzer_context.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ ContractInstance create_default_instance(const ContractClassId& class_id)
4444
.incoming_viewing_key = affine_one,
4545
.outgoing_viewing_key_hash = 0,
4646
.tagging_key_hash = 0,
47+
.message_signing_key_hash = 0,
48+
.fallback_key_hash = 0,
4749
},
4850
};
4951
}

barretenberg/cpp/src/barretenberg/vm2/common/avm_io.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,12 @@ struct PublicKeysHint {
119119
AffinePoint ivpk_m;
120120
FF ovpk_m_hash;
121121
FF tpk_m_hash;
122+
FF mspk_m_hash;
123+
FF fbpk_m_hash;
122124

123125
bool operator==(const PublicKeysHint& other) const = default;
124126

125-
MSGPACK_CAMEL_CASE_FIELDS(npk_m_hash, ivpk_m, ovpk_m_hash, tpk_m_hash);
127+
MSGPACK_CAMEL_CASE_FIELDS(npk_m_hash, ivpk_m, ovpk_m_hash, tpk_m_hash, mspk_m_hash, fbpk_m_hash);
126128
};
127129

128130
struct ContractInstanceHint {

barretenberg/cpp/src/barretenberg/vm2/common/aztec_types.hpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,20 +86,19 @@ enum class ContractInstanceMember : uint8_t {
8686
////////////////////////////////////////////////////////////////////////////
8787

8888
// Only `incoming_viewing_key` is exposed as a point (since address derivation
89-
// needs the curve point in-circuit); the other three keys are exposed as their hashes.
89+
// needs the curve point in-circuit); the other five keys are exposed as their hashes.
9090
struct PublicKeys {
9191
FF nullifier_key_hash;
9292
AffinePoint incoming_viewing_key;
9393
FF outgoing_viewing_key_hash;
9494
FF tagging_key_hash;
95+
FF message_signing_key_hash;
96+
FF fallback_key_hash;
9597

9698
std::vector<FF> to_fields() const
9799
{
98-
return { nullifier_key_hash,
99-
incoming_viewing_key.x,
100-
incoming_viewing_key.y,
101-
outgoing_viewing_key_hash,
102-
tagging_key_hash };
100+
return { nullifier_key_hash, incoming_viewing_key.x, incoming_viewing_key.y, outgoing_viewing_key_hash,
101+
tagging_key_hash, message_signing_key_hash, fallback_key_hash };
103102
}
104103

105104
bool operator==(const PublicKeys& other) const = default;
@@ -115,7 +114,11 @@ struct PublicKeys {
115114
"ovpkMHash",
116115
outgoing_viewing_key_hash,
117116
"tpkMHash",
118-
tagging_key_hash);
117+
tagging_key_hash,
118+
"mspkMHash",
119+
message_signing_key_hash,
120+
"fbpkMHash",
121+
fallback_key_hash);
119122
}
120123
};
121124

barretenberg/cpp/src/barretenberg/vm2/constraining/relations/contract_instance_retrieval.test.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ ContractInstance create_test_contract_instance(uint32_t salt_value = 123)
5252
.incoming_viewing_key = { FF(0x200), FF(0x201) },
5353
.outgoing_viewing_key_hash = FF(0x300),
5454
.tagging_key_hash = FF(0x400),
55+
.message_signing_key_hash = FF(0x500),
56+
.fallback_key_hash = FF(0x600),
5557
},
5658
};
5759
}
@@ -79,6 +81,8 @@ TEST(ContractInstanceRetrievalConstrainingTest, CompleteValidTrace)
7981
const auto incoming_viewing_key_y = FF(0x201);
8082
const auto outgoing_viewing_key_hash = FF(0x300);
8183
const auto tagging_key_hash = FF(0x400);
84+
const auto message_signing_key_hash = FF(0x500);
85+
const auto fallback_key_hash = FF(0x600);
8286

8387
// Test complete valid trace with all constraints
8488
TestTraceContainer trace({
@@ -102,6 +106,8 @@ TEST(ContractInstanceRetrievalConstrainingTest, CompleteValidTrace)
102106
{ C::contract_instance_retrieval_incoming_viewing_key_y, incoming_viewing_key_y },
103107
{ C::contract_instance_retrieval_outgoing_viewing_key_hash, outgoing_viewing_key_hash },
104108
{ C::contract_instance_retrieval_tagging_key_hash, tagging_key_hash },
109+
{ C::contract_instance_retrieval_message_signing_key_hash, message_signing_key_hash },
110+
{ C::contract_instance_retrieval_fallback_key_hash, fallback_key_hash },
105111
{ C::contract_instance_retrieval_deployer_protocol_contract_address,
106112
CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
107113
// Protocol Contract conditionals
@@ -158,6 +164,9 @@ TEST(ContractInstanceRetrievalConstrainingTest, MultipleInstancesTrace)
158164
{ C::contract_instance_retrieval_outgoing_viewing_key_hash,
159165
contract_instance.public_keys.outgoing_viewing_key_hash },
160166
{ C::contract_instance_retrieval_tagging_key_hash, contract_instance.public_keys.tagging_key_hash },
167+
{ C::contract_instance_retrieval_message_signing_key_hash,
168+
contract_instance.public_keys.message_signing_key_hash },
169+
{ C::contract_instance_retrieval_fallback_key_hash, contract_instance.public_keys.fallback_key_hash },
161170
{ C::contract_instance_retrieval_deployer_protocol_contract_address,
162171
CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
163172
// Protocol Contract conditionals
@@ -272,6 +281,8 @@ TEST(ContractInstanceRetrievalConstrainingTest, MaximumFieldValuesTrace)
272281
{ C::contract_instance_retrieval_incoming_viewing_key_y, max_field },
273282
{ C::contract_instance_retrieval_outgoing_viewing_key_hash, max_field },
274283
{ C::contract_instance_retrieval_tagging_key_hash, max_field },
284+
{ C::contract_instance_retrieval_message_signing_key_hash, max_field },
285+
{ C::contract_instance_retrieval_fallback_key_hash, max_field },
275286
{ C::contract_instance_retrieval_deployer_protocol_contract_address,
276287
CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS },
277288
// Protocol Contract conditionals
@@ -466,6 +477,9 @@ TEST(ContractInstanceRetrievalConstrainingTest, IntegrationTracegenValidInstance
466477
{ C::address_derivation_outgoing_viewing_key_hash,
467478
contract_instance_data.public_keys.outgoing_viewing_key_hash },
468479
{ C::address_derivation_tagging_key_hash, contract_instance_data.public_keys.tagging_key_hash },
480+
{ C::address_derivation_message_signing_key_hash,
481+
contract_instance_data.public_keys.message_signing_key_hash },
482+
{ C::address_derivation_fallback_key_hash, contract_instance_data.public_keys.fallback_key_hash },
469483
// For update check lookup
470484
{ C::update_check_sel, 1 },
471485
{ C::update_check_address, contract_address },
@@ -543,6 +557,8 @@ TEST(ContractInstanceRetrievalConstrainingTest, IntegrationTracegenNonExistentIn
543557
{ C::address_derivation_incoming_viewing_key_y, 0 },
544558
{ C::address_derivation_outgoing_viewing_key_hash, 0 },
545559
{ C::address_derivation_tagging_key_hash, 0 },
560+
{ C::address_derivation_message_signing_key_hash, 0 },
561+
{ C::address_derivation_fallback_key_hash, 0 },
546562
// For update check lookup (only populated when nullifier exists)
547563
{ C::update_check_sel, 0 }, // Not selected since nullifier doesn't exist
548564
{ C::update_check_address, contract_address },
@@ -622,6 +638,8 @@ TEST(ContractInstanceRetrievalConstrainingTest, IntegrationTracegenAddressZero)
622638
{ C::address_derivation_incoming_viewing_key_y, 0 },
623639
{ C::address_derivation_outgoing_viewing_key_hash, 0 },
624640
{ C::address_derivation_tagging_key_hash, 0 },
641+
{ C::address_derivation_message_signing_key_hash, 0 },
642+
{ C::address_derivation_fallback_key_hash, 0 },
625643
// For update check lookup (only populated when nullifier exists)
626644
{ C::update_check_sel, 0 }, // Not selected since nullifier doesn't exist
627645
{ C::update_check_address, contract_address },
@@ -713,6 +731,9 @@ TEST(ContractInstanceRetrievalConstrainingTest, IntegrationTracegenMultipleInsta
713731
{ C::address_derivation_outgoing_viewing_key_hash,
714732
contract_instance_data.public_keys.outgoing_viewing_key_hash },
715733
{ C::address_derivation_tagging_key_hash, contract_instance_data.public_keys.tagging_key_hash },
734+
{ C::address_derivation_message_signing_key_hash,
735+
contract_instance_data.public_keys.message_signing_key_hash },
736+
{ C::address_derivation_fallback_key_hash, contract_instance_data.public_keys.fallback_key_hash },
716737
// For update check lookup (only when nullifier exists)
717738
{ C::update_check_sel, 1 },
718739
{ C::update_check_address, FF(base_address + i) },

0 commit comments

Comments
 (0)