Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
address_derivation.test.cpp
Go to the documentation of this file.
2
3#include <cstdint>
4#include <gmock/gmock.h>
5#include <gtest/gtest.h>
6#include <stdexcept>
7
19
20using ::testing::IsEmpty;
21using ::testing::Return;
22using ::testing::SizeIs;
23using ::testing::StrictMock;
24
26
27namespace bb::avm2::simulation {
28
29namespace {
30
31using simulation::PurePoseidon2;
32
33TEST(AvmSimulationAddressDerivationTest, Positive)
34{
35 EventEmitter<AddressDerivationEvent> address_derivation_event_emitter;
36 PurePoseidon2 poseidon2 = PurePoseidon2();
37 StrictMock<MockEcc> ecc;
38
39 AddressDerivation address_derivation(poseidon2, ecc, address_derivation_event_emitter);
40
42 AztecAddress derived_address = compute_contract_address(instance);
43 std::vector<FF> salted_init_hash_inputs = {
44 DOM_SEP__SALTED_INITIALIZATION_HASH, instance.salt, instance.initialization_hash, instance.deployer
45 };
46 FF salted_init_hash = poseidon2::hash(salted_init_hash_inputs);
47
48 std::vector<FF> partial_address_inputs = { DOM_SEP__PARTIAL_ADDRESS,
49 instance.original_contract_class_id,
50 salted_init_hash };
51 FF partial_address = poseidon2::hash(partial_address_inputs);
52
53 FF public_keys_hash = hash_public_keys(instance.public_keys);
54
55 std::vector<FF> preaddress_inputs = { DOM_SEP__CONTRACT_ADDRESS_V1, public_keys_hash, partial_address };
56 FF preaddress = poseidon2::hash(preaddress_inputs);
57
59 EmbeddedCurvePoint preaddress_public_key = g1 * Fq(preaddress);
60 EXPECT_CALL(ecc, scalar_mul(g1, preaddress)).WillOnce(Return(preaddress_public_key));
61
62 EmbeddedCurvePoint address_point = preaddress_public_key + instance.public_keys.incoming_viewing_key;
63 EXPECT_CALL(ecc, add(preaddress_public_key, EmbeddedCurvePoint(instance.public_keys.incoming_viewing_key)))
64 .WillOnce(Return(address_point));
65
66 address_derivation.assert_derivation(derived_address, instance);
67
68 auto events = address_derivation_event_emitter.dump_events();
69 EXPECT_THAT(events, SizeIs(1));
70 EXPECT_EQ(events[0].instance, instance);
71 EXPECT_EQ(events[0].salted_initialization_hash, salted_init_hash);
72 EXPECT_EQ(events[0].partial_address, partial_address);
73 EXPECT_EQ(events[0].public_keys_hash, public_keys_hash);
74 EXPECT_EQ(events[0].preaddress, preaddress);
75 EXPECT_EQ(events[0].preaddress_public_key, preaddress_public_key);
76 EXPECT_EQ(events[0].address, derived_address);
77 EXPECT_EQ(events[0].address_point.x(), derived_address);
78
79 // Second derivation for the same address should be a cache hit and should not emit an event
80 address_derivation.assert_derivation(derived_address, instance);
81 events = address_derivation_event_emitter.dump_events();
82 EXPECT_THAT(events, IsEmpty());
83}
84
85TEST(AvmSimulationAddressDerivationTest, Negative)
86{
87 EventEmitter<AddressDerivationEvent> address_derivation_event_emitter;
88 PurePoseidon2 poseidon2 = PurePoseidon2();
89 StrictMock<MockEcc> ecc;
90
91 AddressDerivation address_derivation(poseidon2, ecc, address_derivation_event_emitter);
92
94 AztecAddress derived_address = compute_contract_address(instance);
95
96 std::vector<FF> salted_init_hash_inputs = {
97 DOM_SEP__SALTED_INITIALIZATION_HASH, instance.salt, instance.initialization_hash, instance.deployer
98 };
99 FF salted_init_hash = poseidon2::hash(salted_init_hash_inputs);
100
101 std::vector<FF> partial_address_inputs = { DOM_SEP__PARTIAL_ADDRESS,
102 instance.original_contract_class_id,
103 salted_init_hash };
104 FF partial_address = poseidon2::hash(partial_address_inputs);
105
106 FF public_keys_hash = hash_public_keys(instance.public_keys);
107
108 std::vector<FF> preaddress_inputs = { DOM_SEP__CONTRACT_ADDRESS_V1, public_keys_hash, partial_address };
109 FF preaddress = poseidon2::hash(preaddress_inputs);
110
112 EmbeddedCurvePoint preaddress_public_key = g1 * Fq(preaddress);
113 EXPECT_CALL(ecc, scalar_mul(g1, preaddress)).WillOnce(Return(preaddress_public_key));
114
115 EmbeddedCurvePoint address_point = preaddress_public_key + instance.public_keys.incoming_viewing_key;
116 EXPECT_CALL(ecc, add(preaddress_public_key, EmbeddedCurvePoint(instance.public_keys.incoming_viewing_key)))
117 .WillOnce(Return(address_point));
118
119 // Should fail on incorrect derived address.
120 EXPECT_THROW(address_derivation.assert_derivation(derived_address + 1, instance), std::runtime_error);
121
122 // Should fail on mutated instance for unseen address.
123 instance.public_keys.nullifier_key = AffinePoint::one();
124
125 public_keys_hash = hash_public_keys(instance.public_keys);
126 preaddress_inputs = { DOM_SEP__CONTRACT_ADDRESS_V1, public_keys_hash, partial_address };
127 preaddress = poseidon2::hash(preaddress_inputs);
128 preaddress_public_key = g1 * Fq(preaddress);
129 address_point = preaddress_public_key + instance.public_keys.incoming_viewing_key;
130
131 EXPECT_CALL(ecc, scalar_mul(g1, preaddress)).WillOnce(Return(preaddress_public_key));
132 EXPECT_CALL(ecc, add(preaddress_public_key, EmbeddedCurvePoint(instance.public_keys.incoming_viewing_key)))
133 .WillOnce(Return(address_point));
134
135 // The below fails and does not emit an event.
136 EXPECT_THROW(address_derivation.assert_derivation(derived_address, instance), std::runtime_error);
137 EXPECT_THAT(address_derivation_event_emitter.dump_events(), IsEmpty());
138
139 // Perform a successful derivation for the mutated instance above.
140 EXPECT_CALL(ecc, scalar_mul(g1, preaddress)).WillOnce(Return(preaddress_public_key));
141 EXPECT_CALL(ecc, add(preaddress_public_key, EmbeddedCurvePoint(instance.public_keys.incoming_viewing_key)))
142 .WillOnce(Return(address_point));
143 // The below succeeds, emits an event, and stores the address in the cached_derivations cache.
144 address_derivation.assert_derivation(address_point.x(), instance);
145 EXPECT_THAT(address_derivation_event_emitter.dump_events(), SizeIs(1));
146
147 // Should fail on mutated instance for seen address.
148 ContractInstance new_instance = instance;
149 new_instance.deployer += 1;
150 // Note: EXPECT_CALLs not required since the address is cached.
151 EXPECT_THROW(address_derivation.assert_derivation(address_point.x(), new_instance), std::runtime_error);
152 EXPECT_THAT(address_derivation_event_emitter.dump_events(), IsEmpty());
153
154 // The below succeeds and hits the cache, so does not emit an event.
155 address_derivation.assert_derivation(address_point.x(), instance);
156 EXPECT_THAT(address_derivation_event_emitter.dump_events(), IsEmpty());
157}
158
159} // namespace
160} // namespace bb::avm2::simulation
std::shared_ptr< Napi::ThreadSafeFunction > instance
#define DOM_SEP__SALTED_INITIALIZATION_HASH
#define DOM_SEP__PARTIAL_ADDRESS
#define DOM_SEP__CONTRACT_ADDRESS_V1
Native Poseidon2 hash function implementation.
Definition poseidon2.hpp:22
static FF hash(const std::vector< FF > &input)
Hashes a vector of field elements.
static constexpr affine_element one() noexcept
group class. Represents an elliptic curve group element. Group is parametrised by Fq and Fr
Definition group.hpp:38
AVM range check gadget for witness generation.
ContractInstance random_contract_instance()
Definition fixtures.cpp:159
StandardAffinePoint< AvmFlavorSettings::EmbeddedCurve::AffineElement > EmbeddedCurvePoint
Definition field.hpp:12
AvmFlavorSettings::G1::Fq Fq
Definition field.hpp:11
TEST(BoomerangMegaCircuitBuilder, BasicCircuit)