Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
address_derivation.cpp
Go to the documentation of this file.
2
3#include <cassert>
4
8
9namespace bb::avm2::simulation {
10
33{
34 // Check if we've already derived this address.
35 if (cached_derivations.contains(address)) {
36 // Note: it is likely safe to skip this recalculation, but if we do, then a mismatch will throw in the
37 // non-cache case and return in the cache case for the same input. No events are emitted either way, so
38 // circuit and tracegen behave the same. The below exists just to unify simulation behaviour (#21374).
39 BB_ASSERT_EQ(address, simulation::compute_contract_address(instance), "Address derivation mismatch");
40 // Already processed this address - cache hit, don't emit event.
41 return;
42 }
43
44 // First time seeing this address - do the actual derivation.
45 // Emits Poseidon2HashEvents and Poseidon2PermutationEvents, see #[SALTED_INITIALIZATION_HASH_POSEIDON2_i] in
46 // address_derivation.pil.
47 FF salted_initialization_hash = poseidon2.hash(
48 { DOM_SEP__SALTED_INITIALIZATION_HASH, instance.salt, instance.initialization_hash, instance.deployer });
49 // Emits Poseidon2HashEvents and Poseidon2PermutationEvents, see #[PARTIAL_ADDRESS_POSEIDON2] in
50 // address_derivation.pil.
51 FF partial_address =
52 poseidon2.hash({ DOM_SEP__PARTIAL_ADDRESS, instance.original_contract_class_id, salted_initialization_hash });
53
54 std::vector<FF> public_keys_hash_fields = instance.public_keys.to_fields();
55 std::vector<FF> public_key_hash_vec{ DOM_SEP__PUBLIC_KEYS_HASH };
56 for (size_t i = 0; i < public_keys_hash_fields.size(); i += 2) {
57 // Public key x coordinate.
58 public_key_hash_vec.push_back(public_keys_hash_fields[i]);
59 // Public key y coordinate.
60 public_key_hash_vec.push_back(public_keys_hash_fields[i + 1]);
61 // TODO(#7529): Public key is_infinity will be removed from address preimage, assuming false.
62 public_key_hash_vec.push_back(FF::zero());
63 }
64 // Emits Poseidon2HashEvents and Poseidon2PermutationEvents, see #[PUBLIC_KEYS_HASH_POSEIDON2_i] in
65 // address_derivation.pil.
66 FF public_keys_hash = poseidon2.hash(public_key_hash_vec);
67 // Emits Poseidon2HashEvents and Poseidon2PermutationEvents, see #[PREADDRESS_POSEIDON2] in address_derivation.pil.
68 FF preaddress = poseidon2.hash({ DOM_SEP__CONTRACT_ADDRESS_V1, public_keys_hash, partial_address });
69
70 // Note: the below ecc calls assume points are on the curve. We know preaddress_public_key is (by definition),
71 // but it may be possible that incoming_viewing_key is not.
72 // The circuit enforces that the point is on the curve to meet ecc's precondition and we replicate this here.
73 BB_ASSERT(instance.public_keys.incoming_viewing_key.on_curve(),
74 "Incoming viewing key is not on the curve when asserting contract address derivation");
75
76 // Emits ScalarMulEvent and EccAddEvents, see #[PREADDRESS_SCALAR_MUL] in address_derivation.pil.
77 EmbeddedCurvePoint preaddress_public_key = ecc.scalar_mul(EmbeddedCurvePoint::one(), preaddress);
78 // Emits EccAddEvent, see #[ADDRESS_ECADD] in address_derivation.pil.
79 EmbeddedCurvePoint address_point = ecc.add(preaddress_public_key, instance.public_keys.incoming_viewing_key);
80
81 // This will throw an unexpected exception if it fails. If we have reached this point,
82 // the contract instance retrieval should have enforced this.
83 BB_ASSERT_EQ(address, address_point.x(), "Address derivation mismatch");
84
85 // Cache this derivation so we don't repeat it
87
88 // Emits AddressDerivationEvent.
89 events.emit({
90 .address = address,
91 .instance = instance,
92 .salted_initialization_hash = salted_initialization_hash,
93 .partial_address = partial_address,
94 .public_keys_hash = public_keys_hash,
95 .preaddress = preaddress,
96 .preaddress_public_key = preaddress_public_key,
97 .address_point = address_point,
98 });
99}
100
101} // namespace bb::avm2::simulation
#define BB_ASSERT(expression,...)
Definition assert.hpp:70
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:83
std::shared_ptr< Napi::ThreadSafeFunction > instance
#define DOM_SEP__SALTED_INITIALIZATION_HASH
#define DOM_SEP__PARTIAL_ADDRESS
#define DOM_SEP__PUBLIC_KEYS_HASH
#define DOM_SEP__CONTRACT_ADDRESS_V1
constexpr const BaseField & x() const noexcept
unordered_flat_set< AztecAddress > cached_derivations
void assert_derivation(const AztecAddress &address, const ContractInstance &instance) override
Verifies a contract instance's address derivation and emits an AddressDerivationEvent....
EventEmitterInterface< AddressDerivationEvent > & events
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
AVM range check gadget for witness generation.
FF compute_contract_address(const ContractInstance &contract_instance)
AvmFlavorSettings::FF FF
Definition field.hpp:10