Skip to content

Commit 8181149

Browse files
sklppy88benesjan
andauthored
fix: make block number in txe make sense (#11807)
Right now `env.block_number()` returns the block number that is currently being built, as per an arbitrary choice when creating the TXe. But this has a strange side effect of the current block (from the header) and `env.block_number()` not matching up. The current header has `env.block_number() - 1` because the current header reflects the state of the last committed block. Before this mattered less because we couldn't do historical proofs, and because we had less of a notion of "correctness" in blocks but now due to the changes this makes sense to change. --------- Co-authored-by: benesjan <janbenes1234@gmail.com>
1 parent 393a2df commit 8181149

File tree

4 files changed

+62
-10
lines changed

4 files changed

+62
-10
lines changed

docs/docs/migration_notes.md

+9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@ Aztec is in full-speed development. Literally every version breaks compatibility
88

99
## TBD
1010

11+
### [aztec-nr] `TestEnvironment::block_number()` refactored
12+
13+
The `block_number` function from `TestEnvironment` has been expanded upon with two extra functions, the first being `pending_block_number`, and the second being `committed_block_number`. `pending_block_number` now returns what `block_number` does. In other words, it returns the block number of the block we are currently building. `committed_block_number` returns the block number of the last committed block, i.e. the block number that gets used to execute the private part of transactions when your PXE is successfully synced to the tip of the chain.
14+
15+
```diff
16+
+ `TestEnvironment::pending_block_number()`
17+
+ `TestEnvironment::committed_block_number()`
18+
```
19+
1120
### [aztec-nr] `compute_nullifier_without_context` renamed
1221

1322
The `compute_nullifier_without_context` function from `NoteHash` (ex `NoteInterface`) is now called `compute_nullifier_unconstrained`, and instead of taking storage slot, contract address and nonce it takes a note hash for nullification (same as `compute_note_hash`). This makes writing this

noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr

+11-4
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,18 @@ unconstrained fn test_get_scheduled_value_in_public() {
5050
let mut env = setup();
5151
let state_var = in_public(env);
5252

53+
// Schedule a value change that will activate at `public_context.block_number() + current_delay`.
54+
// Since we haven't modified the delay, it remains at the initial value of TEST_INITIAL_DELAY.
5355
state_var.schedule_value_change(new_value);
5456

5557
let (scheduled, block_of_change) = state_var.get_scheduled_value();
5658
assert_eq(scheduled, new_value);
57-
assert_eq(block_of_change, env.block_number() + TEST_INITIAL_DELAY);
59+
60+
// The block of change should equal the pending block number plus TEST_INITIAL_DELAY because:
61+
// 1. The value change is scheduled using the block number from the public context
62+
// 2. The public context's block number corresponds to the pending block
63+
// 3. The current delay is TEST_INITIAL_DELAY since it hasn't been modified
64+
assert_eq(block_of_change, env.pending_block_number() + TEST_INITIAL_DELAY);
5865
}
5966

6067
#[test]
@@ -120,7 +127,7 @@ unconstrained fn test_get_scheduled_delay_in_public() {
120127
let (scheduled, block_of_change) = state_var.get_scheduled_delay();
121128
assert_eq(scheduled, new_delay);
122129
// The new delay is smaller, therefore we need to wait for the difference between current and new
123-
assert_eq(block_of_change, env.block_number() + TEST_INITIAL_DELAY - new_delay);
130+
assert_eq(block_of_change, env.pending_block_number() + TEST_INITIAL_DELAY - new_delay);
124131
}
125132

126133
#[test]
@@ -172,7 +179,7 @@ unconstrained fn test_get_current_delay_in_public_after_scheduled_change() {
172179
unconstrained fn test_get_current_value_in_private_initial() {
173180
let mut env = setup();
174181

175-
let historical_block_number = env.block_number();
182+
let historical_block_number = env.pending_block_number();
176183
let state_var = in_private(&mut env, historical_block_number);
177184

178185
assert_eq(state_var.get_current_value(), zeroed());
@@ -191,7 +198,7 @@ unconstrained fn test_get_current_value_in_private_before_change() {
191198

192199
let (_, block_of_change) = public_state_var.get_scheduled_value();
193200

194-
let schedule_block_number = env.block_number();
201+
let schedule_block_number = env.pending_block_number();
195202

196203
let private_state_var = in_private(&mut env, schedule_block_number);
197204
assert_eq(private_state_var.get_current_value(), MockStruct::empty());

noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr

+39-3
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,60 @@ impl TestEnvironment {
2222
Self {}
2323
}
2424

25-
pub unconstrained fn block_number(_self: Self) -> u32 {
25+
/// Returns the block number of the block currently being built. Since sequencer is executing the public part
26+
/// of transactions when building blocks, this block number is also returned by public_context.block_number().
27+
pub unconstrained fn pending_block_number(_self: Self) -> u32 {
2628
get_block_number()
2729
}
2830

31+
/// This does what the above does but should be considered deprecated as the naming is subpar.
32+
pub unconstrained fn block_number(self: Self) -> u32 {
33+
self.pending_block_number()
34+
}
35+
36+
/// Returns the block number of the last committed block - this is the block number that gets used in production
37+
/// to execute the private part of transactions when your PXE managed to successfully sync to the tip of the chain.
38+
pub unconstrained fn committed_block_number(self: Self) -> u32 {
39+
self.pending_block_number() - 1
40+
}
41+
42+
/// With TXe tests, every test is run in a mock "contract". This facilitates the ability to write to and read from storage,
43+
/// emit and retrieve nullifiers (because they are hashed with a contract address), and formulate notes in a canonical way.
44+
/// The contract_address also represents the "msg_sender" when we call a contract with a private or public context; and when
45+
/// we call top-level unconstrained functions, we must set this contract address to the contract being called.
46+
/// The contract address can be manipulated to do the above at any particular address, and not simply the one provided at
47+
/// the instantiation of the test.
48+
/// Returns the currently set contract address.
2949
pub unconstrained fn contract_address(_self: Self) -> AztecAddress {
3050
get_contract_address()
3151
}
3252

53+
/// Modifies the currently set contract address. As per above, it sets the "msg_sender" address on our subsequent calls.
54+
/// This is useful when we have multiple "accounts" that need to interact with an arbitrary contract. This also allows
55+
/// us to change the "contract" we emit side effects from, and is required when we want to run a top-level unconstrained function on another contract.
3356
pub unconstrained fn impersonate(_self: Self, address: AztecAddress) {
3457
cheatcodes::set_contract_address(address)
3558
}
3659

60+
/// Advances the internal TXe state to specified block number.
61+
/// Note that this block number describes the block being built. i.e. If you advance the block to 5 from 1,
62+
/// the pending block number will be 5, and your last committed block number will be 4.
3763
pub unconstrained fn advance_block_to(&mut self, block_number: u32) {
38-
let difference = block_number - get_block_number();
64+
let pending_block_number = self.pending_block_number();
65+
assert(pending_block_number <= block_number, "Cannot advance block to a previous block.");
66+
67+
let difference = block_number - pending_block_number;
3968
self.advance_block_by(difference);
4069
}
4170

71+
/// Advances the internal TXe state by the amount of blocks specified. The TXe produces a valid block for every
72+
/// block advanced, and we are able to fetch historical data from warped over blocks.
4273
pub unconstrained fn advance_block_by(_self: &mut Self, blocks: u32) {
4374
cheatcodes::advance_blocks_by(blocks);
4475
}
4576

77+
/// Instantiates a public context. The block number returned from public_context.block_number() will be the
78+
/// block number of the block currently being built (same as the one returned by self.pending_block_number()).
4679
pub unconstrained fn public(_self: Self) -> PublicContext {
4780
PublicContext::new(|| 0)
4881
}
@@ -53,15 +86,18 @@ impl TestEnvironment {
5386
context
5487
}
5588

89+
/// Instantiates a private context at the latest committed block number - this is the block number that gets used
90+
/// in production to build transactions when your PXE managed to successfully sync to the tip of the chain.
5691
pub unconstrained fn private(&mut self) -> PrivateContext {
57-
self.private_at(get_block_number() - 1)
92+
self.private_at(self.committed_block_number())
5893
}
5994

6095
// unconstrained is a key word, so we mis-spell purposefully here, like we do with contrakt
6196
pub unconstrained fn unkonstrained(_self: Self) -> UnconstrainedContext {
6297
UnconstrainedContext::new()
6398
}
6499

100+
/// Instantiates a private context at a specific historical block number.
65101
pub unconstrained fn private_at(&mut self, historical_block_number: u32) -> PrivateContext {
66102
if historical_block_number >= get_block_number() {
67103
self.advance_block_to(historical_block_number + 1);

noir-projects/noir-contracts/contracts/router_contract/src/test.nr

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ unconstrained fn test_check_block_number() {
1313
env.advance_block_by(8);
1414

1515
// First we sanity-check that current block number is as expected
16-
let current_block_number = env.block_number();
17-
assert(current_block_number == 10, "Expected block number to be 10");
16+
let current_block_number = env.pending_block_number();
17+
assert(current_block_number == 10, "Expected pending block number to be 10");
1818

1919
// We test just one success case and 1 failure case in this test as the rest is tested in the comparator unit tests
2020
router.check_block_number(Comparator.LT, 11).call(&mut env.private());
@@ -31,7 +31,7 @@ unconstrained fn test_fail_check_block_number() {
3131
env.advance_block_by(8);
3232

3333
// First we sanity-check that current block number is as expected
34-
let current_block_number = env.block_number();
34+
let current_block_number = env.pending_block_number();
3535
assert(current_block_number == 10, "Expected block number to be 10");
3636

3737
router.check_block_number(Comparator.LT, 5).call(&mut env.private());

0 commit comments

Comments
 (0)