Skip to content

Commit af9d8be

Browse files
authored
fix: salted initialization hash separator (#22632)
Copied from #20969 ------------------------- When writing an address spec I noticed the same domain separator is being used in two places when deriving an address. This PR introduces DOM_SEP__SALTED_INITIALIZATION_HASH to replace the incorrect usage of DOM_SEP__PARTIAL_ADDRESS.
2 parents 831e809 + 4ff0904 commit af9d8be

38 files changed

Lines changed: 266 additions & 248 deletions

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

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ include "../scalar_mul.pil";
99
* during contract instance retrieval (contract_instance_retrieval.pil) in our execution flow.
1010
* The address is defined by the following flow, where the hash function H() is Poseidon2, and G1
1111
* is the Grumpkin curve's generator point:
12-
* 1. salted_init_hash = H(DOM_SEP__PARTIAL_ADDRESS, salt, init_hash, deployer_addr)
12+
* 1. salted_init_hash = H(DOM_SEP__SALTED_INITIALIZATION_HASH, salt, init_hash, deployer_addr)
1313
* 2. partial_address = H(DOM_SEP__PARTIAL_ADDRESS, class_id, salted_init_hash)
1414
* 3. public_keys_hash = H(DOM_SEP__PUBLIC_KEYS_HASH,
1515
* nullifier_key_x, nullifier_key_y, nullifier_key_is_infinity,
@@ -24,10 +24,6 @@ include "../scalar_mul.pil";
2424
* curve. See the 'Hash Computations', 'Elliptic Curve Operations', and 'INTERACTIONS' sections
2525
* for details on how we enforce each step. This process follows Noir's AztecAddress::compute().
2626
*
27-
* Note: DOM_SEP__PARTIAL_ADDRESS is reused for both the salted initialization hash and the partial
28-
* address computations (steps 1 and 2). This cannot lead to a collision since the preimages are of
29-
* different lengths, hence will have different IV values. Unfortunately, why this is the case is not
30-
* documented in the protocol.
3127
*
3228
* PRECONDITIONS: The correctness of the preimage members is not constrained here and must be
3329
* enforced by the calling circuits. Like class_id_derivation, this trace can be seen
@@ -121,7 +117,7 @@ namespace address_derivation;
121117
///////////////////////////////
122118
//
123119
// This trace constrains the result of four Poseidon2 hashes:
124-
// 1. salted_init_hash = H(DOM_SEP__PARTIAL_ADDRESS, salt, init_hash, deployer_addr)
120+
// 1. salted_init_hash = H(DOM_SEP__SALTED_INITIALIZATION_HASH, salt, init_hash, deployer_addr)
125121
// 2. partial_address = H(DOM_SEP__PARTIAL_ADDRESS, class_id, salted_init_hash)
126122
// 3. public_keys_hash = H(DOM_SEP__PUBLIC_KEYS_HASH,
127123
// nullifier_key_x, nullifier_key_y, 0,
@@ -140,6 +136,8 @@ namespace address_derivation;
140136
sel * (const_four - 4) = 0;
141137
pol commit const_thirteen;
142138
sel * (const_thirteen - 13) = 0;
139+
pol commit salted_init_hash_domain_separator;
140+
sel * (salted_init_hash_domain_separator - constants.DOM_SEP__SALTED_INITIALIZATION_HASH) = 0;
143141
pol commit partial_address_domain_separator;
144142
sel * (partial_address_domain_separator - constants.DOM_SEP__PARTIAL_ADDRESS) = 0;
145143
pol commit public_keys_hash_domain_separator;
@@ -151,14 +149,14 @@ namespace address_derivation;
151149
pol commit salted_init_hash;
152150

153151
// Since Poseidon2 processes inputs in chunks of 3, we need 2 permutation rounds to cover our 4 inputs:
154-
// salted_init_hash = H(DOM_SEP__PARTIAL_ADDRESS, salt, init_hash, deployer_addr)
155-
// Round 1 (start, input_len=4): (DOM_SEP__PARTIAL_ADDRESS, salt, init_hash)
152+
// salted_init_hash = H(DOM_SEP__SALTED_INITIALIZATION_HASH, salt, init_hash, deployer_addr)
153+
// Round 1 (start, input_len=4): (DOM_SEP__SALTED_INITIALIZATION_HASH, salt, init_hash)
156154
// Round 2 (end): (deployer_addr, 0, 0)
157155

158156
// Enforces the first round of salted_init_hash. Note that we must lookup poseidon2_hash.input_len == 4
159157
// here since it is constrained in the poseidon trace on the start row.
160158
#[SALTED_INITIALIZATION_HASH_POSEIDON2_0]
161-
sel { partial_address_domain_separator, salt, init_hash, salted_init_hash, const_four }
159+
sel { salted_init_hash_domain_separator, salt, init_hash, salted_init_hash, const_four }
162160
in poseidon2_hash.start { poseidon2_hash.input_0, poseidon2_hash.input_1, poseidon2_hash.input_2, poseidon2_hash.output, poseidon2_hash.input_len };
163161

164162
// Enforces the second and final round of salted_init_hash. Note that we must enforce the padded values are zero here.

barretenberg/cpp/pil/vm2/constants_gen.pil

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ namespace constants;
178178
pol DOM_SEP__RETRIEVED_BYTECODES_MERKLE = 2789215184;
179179
pol DOM_SEP__PUBLIC_BYTECODE = 260313585;
180180
pol DOM_SEP__CONTRACT_CLASS_ID = 3923495515;
181+
pol DOM_SEP__SALTED_INITIALIZATION_HASH = 2763052992;
181182
pol DOM_SEP__PUBLIC_KEYS_HASH = 777457226;
182183
pol DOM_SEP__PARTIAL_ADDRESS = 2103633018;
183184
pol DOM_SEP__CONTRACT_ADDRESS_V1 = 1788365517;

barretenberg/cpp/src/barretenberg/aztec/aztec_constants.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@
270270
#define DOM_SEP__RETRIEVED_BYTECODES_MERKLE 2789215184UL
271271
#define DOM_SEP__PUBLIC_BYTECODE 260313585UL
272272
#define DOM_SEP__CONTRACT_CLASS_ID 3923495515UL
273+
#define DOM_SEP__SALTED_INITIALIZATION_HASH 2763052992UL
273274
#define DOM_SEP__PUBLIC_KEYS_HASH 777457226UL
274275
#define DOM_SEP__PARTIAL_ADDRESS 2103633018UL
275276
#define DOM_SEP__CONTRACT_ADDRESS_V1 1788365517UL

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ TEST(AddressDerivationConstrainingTest, Basic)
7272

7373
auto instance = testing::random_contract_instance();
7474

75-
FF salted_initialization_hash =
76-
poseidon2::hash({ DOM_SEP__PARTIAL_ADDRESS, instance.salt, instance.initialization_hash, instance.deployer });
75+
FF salted_initialization_hash = poseidon2::hash(
76+
{ DOM_SEP__SALTED_INITIALIZATION_HASH, instance.salt, instance.initialization_hash, instance.deployer });
7777

7878
FF partial_address =
7979
poseidon2::hash({ DOM_SEP__PARTIAL_ADDRESS, instance.original_contract_class_id, salted_initialization_hash });
@@ -225,8 +225,8 @@ TEST(AddressDerivationConstrainingTest, NegativeIVKNotOnCurve)
225225
// Mutate ivk to a point not on the curve.
226226
instance.public_keys.incoming_viewing_key = AffinePoint(1, 2);
227227

228-
FF salted_initialization_hash =
229-
poseidon2::hash({ DOM_SEP__PARTIAL_ADDRESS, instance.salt, instance.initialization_hash, instance.deployer });
228+
FF salted_initialization_hash = poseidon2::hash(
229+
{ DOM_SEP__SALTED_INITIALIZATION_HASH, instance.salt, instance.initialization_hash, instance.deployer });
230230

231231
FF partial_address =
232232
poseidon2::hash({ DOM_SEP__PARTIAL_ADDRESS, instance.original_contract_class_id, salted_initialization_hash });

barretenberg/cpp/src/barretenberg/vm2/generated/columns.hpp

Lines changed: 5 additions & 5 deletions
Large diffs are not rendered by default.

barretenberg/cpp/src/barretenberg/vm2/generated/flavor_variables.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,10 @@ namespace bb::avm2 {
141141

142142
struct AvmFlavorVariables {
143143
static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 122;
144-
static constexpr size_t NUM_WITNESS_ENTITIES = 2957;
144+
static constexpr size_t NUM_WITNESS_ENTITIES = 2958;
145145
static constexpr size_t NUM_SHIFTED_ENTITIES = 364;
146-
static constexpr size_t NUM_WIRES = 2513;
147-
static constexpr size_t NUM_ALL_ENTITIES = 3443;
146+
static constexpr size_t NUM_WIRES = 2514;
147+
static constexpr size_t NUM_ALL_ENTITIES = 3444;
148148

149149
// Need to be templated for recursive verifier
150150
template <typename FF_>

barretenberg/cpp/src/barretenberg/vm2/generated/relations/address_derivation.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ template <typename FF_> class address_derivationImpl {
1414
public:
1515
using FF = FF_;
1616

17-
static constexpr std::array<size_t, 11> SUBRELATION_PARTIAL_LENGTHS = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5 };
17+
static constexpr std::array<size_t, 12> SUBRELATION_PARTIAL_LENGTHS = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5 };
1818

1919
template <typename AllEntities> inline static bool skip(const AllEntities& in)
2020
{
@@ -35,7 +35,7 @@ template <typename FF> class address_derivation : public Relation<address_deriva
3535
static constexpr const std::string_view NAME = "address_derivation";
3636

3737
// Subrelation indices constants, to be used in tests.
38-
static constexpr size_t SR_IVK_ON_CURVE_CHECK = 10;
38+
static constexpr size_t SR_IVK_ON_CURVE_CHECK = 11;
3939

4040
static std::string get_subrelation_label(size_t index)
4141
{

barretenberg/cpp/src/barretenberg/vm2/generated/relations/address_derivation_impl.hpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ void address_derivationImpl<FF_>::accumulate(ContainerOverSubrelations& evals,
1818
const auto constants_GRUMPKIN_ONE_X = FF(1);
1919
const auto constants_GRUMPKIN_ONE_Y =
2020
FF(uint256_t{ 9457493854555940652UL, 3253583849847263892UL, 14921373847124204899UL, 2UL });
21+
const auto constants_DOM_SEP__SALTED_INITIALIZATION_HASH = FF(2763052992UL);
2122
const auto constants_DOM_SEP__PUBLIC_KEYS_HASH = FF(777457226);
2223
const auto constants_DOM_SEP__PARTIAL_ADDRESS = FF(2103633018);
2324
const auto constants_DOM_SEP__CONTRACT_ADDRESS_V1 = FF(1788365517);
@@ -60,42 +61,49 @@ void address_derivationImpl<FF_>::accumulate(ContainerOverSubrelations& evals,
6061
{
6162
using View = typename std::tuple_element_t<5, ContainerOverSubrelations>::View;
6263
auto tmp = static_cast<View>(in.get(C::address_derivation_sel)) *
63-
(static_cast<View>(in.get(C::address_derivation_partial_address_domain_separator)) -
64-
CView(constants_DOM_SEP__PARTIAL_ADDRESS));
64+
(static_cast<View>(in.get(C::address_derivation_salted_init_hash_domain_separator)) -
65+
CView(constants_DOM_SEP__SALTED_INITIALIZATION_HASH));
6566
std::get<5>(evals) += (tmp * scaling_factor);
6667
}
6768
{
6869
using View = typename std::tuple_element_t<6, ContainerOverSubrelations>::View;
6970
auto tmp = static_cast<View>(in.get(C::address_derivation_sel)) *
70-
(static_cast<View>(in.get(C::address_derivation_public_keys_hash_domain_separator)) -
71-
CView(constants_DOM_SEP__PUBLIC_KEYS_HASH));
71+
(static_cast<View>(in.get(C::address_derivation_partial_address_domain_separator)) -
72+
CView(constants_DOM_SEP__PARTIAL_ADDRESS));
7273
std::get<6>(evals) += (tmp * scaling_factor);
7374
}
7475
{
7576
using View = typename std::tuple_element_t<7, ContainerOverSubrelations>::View;
7677
auto tmp = static_cast<View>(in.get(C::address_derivation_sel)) *
77-
(static_cast<View>(in.get(C::address_derivation_preaddress_domain_separator)) -
78-
CView(constants_DOM_SEP__CONTRACT_ADDRESS_V1));
78+
(static_cast<View>(in.get(C::address_derivation_public_keys_hash_domain_separator)) -
79+
CView(constants_DOM_SEP__PUBLIC_KEYS_HASH));
7980
std::get<7>(evals) += (tmp * scaling_factor);
8081
}
8182
{
8283
using View = typename std::tuple_element_t<8, ContainerOverSubrelations>::View;
8384
auto tmp = static_cast<View>(in.get(C::address_derivation_sel)) *
84-
(static_cast<View>(in.get(C::address_derivation_g1_x)) - CView(constants_GRUMPKIN_ONE_X));
85+
(static_cast<View>(in.get(C::address_derivation_preaddress_domain_separator)) -
86+
CView(constants_DOM_SEP__CONTRACT_ADDRESS_V1));
8587
std::get<8>(evals) += (tmp * scaling_factor);
8688
}
8789
{
8890
using View = typename std::tuple_element_t<9, ContainerOverSubrelations>::View;
8991
auto tmp = static_cast<View>(in.get(C::address_derivation_sel)) *
90-
(static_cast<View>(in.get(C::address_derivation_g1_y)) - CView(constants_GRUMPKIN_ONE_Y));
92+
(static_cast<View>(in.get(C::address_derivation_g1_x)) - CView(constants_GRUMPKIN_ONE_X));
9193
std::get<9>(evals) += (tmp * scaling_factor);
9294
}
93-
{ // IVK_ON_CURVE_CHECK
95+
{
9496
using View = typename std::tuple_element_t<10, ContainerOverSubrelations>::View;
9597
auto tmp = static_cast<View>(in.get(C::address_derivation_sel)) *
96-
(CView(address_derivation_Y2) - (CView(address_derivation_X3) - FF(17)));
98+
(static_cast<View>(in.get(C::address_derivation_g1_y)) - CView(constants_GRUMPKIN_ONE_Y));
9799
std::get<10>(evals) += (tmp * scaling_factor);
98100
}
101+
{ // IVK_ON_CURVE_CHECK
102+
using View = typename std::tuple_element_t<11, ContainerOverSubrelations>::View;
103+
auto tmp = static_cast<View>(in.get(C::address_derivation_sel)) *
104+
(CView(address_derivation_Y2) - (CView(address_derivation_X3) - FF(17)));
105+
std::get<11>(evals) += (tmp * scaling_factor);
106+
}
99107
}
100108

101109
} // namespace bb::avm2

barretenberg/cpp/src/barretenberg/vm2/generated/relations/lookups_address_derivation.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct lookup_address_derivation_salted_initialization_hash_poseidon2_0_settings
2222
static constexpr Column COUNTS = Column::lookup_address_derivation_salted_initialization_hash_poseidon2_0_counts;
2323
static constexpr Column INVERSES = Column::lookup_address_derivation_salted_initialization_hash_poseidon2_0_inv;
2424
static constexpr std::array<ColumnAndShifts, LOOKUP_TUPLE_SIZE> SRC_COLUMNS = {
25-
ColumnAndShifts::address_derivation_partial_address_domain_separator,
25+
ColumnAndShifts::address_derivation_salted_init_hash_domain_separator,
2626
ColumnAndShifts::address_derivation_salt,
2727
ColumnAndShifts::address_derivation_init_hash,
2828
ColumnAndShifts::address_derivation_salted_init_hash,

barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/address_derivation.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace bb::avm2::simulation {
1515
* If the address has already been derived, an event has already been emitted and we skip
1616
* repeating the computation and emission. Otherwise, we compute the address from the instance
1717
* members using the poseidon2, scalar_mul, and ecc traces, which is given as:
18-
* 1. salted_init_hash = Poseidon2(DOM_SEP__PARTIAL_ADDRESS, salt, init_hash, deployer_addr)
18+
* 1. salted_init_hash = Poseidon2(DOM_SEP__SALTED_INITIALIZATION_HASH, salt, init_hash, deployer_addr)
1919
* 2. partial_address = Poseidon2(DOM_SEP__PARTIAL_ADDRESS, class_id, salted_init_hash)
2020
* 3. public_keys_hash = Poseidon2(DOM_SEP__PUBLIC_KEYS_HASH, [...public_keys.to_fields()])
2121
* 4. preaddress = Poseidon2(DOM_SEP__CONTRACT_ADDRESS_V1, public_keys_hash, partial_address)
@@ -44,8 +44,8 @@ void AddressDerivation::assert_derivation(const AztecAddress& address, const Con
4444
// First time seeing this address - do the actual derivation.
4545
// Emits Poseidon2HashEvents and Poseidon2PermutationEvents, see #[SALTED_INITIALIZATION_HASH_POSEIDON2_i] in
4646
// address_derivation.pil.
47-
FF salted_initialization_hash =
48-
poseidon2.hash({ DOM_SEP__PARTIAL_ADDRESS, instance.salt, instance.initialization_hash, instance.deployer });
47+
FF salted_initialization_hash = poseidon2.hash(
48+
{ DOM_SEP__SALTED_INITIALIZATION_HASH, instance.salt, instance.initialization_hash, instance.deployer });
4949
// Emits Poseidon2HashEvents and Poseidon2PermutationEvents, see #[PARTIAL_ADDRESS_POSEIDON2] in
5050
// address_derivation.pil.
5151
FF partial_address =

0 commit comments

Comments
 (0)