Skip to content

Commit

Permalink
fix: verify start state of a block (#11290)
Browse files Browse the repository at this point in the history
Check the start state of the first tx in a block, in block root rollup
circuit, to make sure that it matches the state in the previous block
header, whose hash is the last leaf in the last archive. Otherwise, it
could be whatever and that allows adding fake data by changing the tree
roots in the start state.
  • Loading branch information
LeilaWang authored Jan 17, 2025
1 parent 232c34e commit 5eb3e8f
Show file tree
Hide file tree
Showing 60 changed files with 15,754 additions and 15,516 deletions.
7 changes: 4 additions & 3 deletions barretenberg/cpp/src/barretenberg/world_state/world_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ void WorldState::create_canonical_fork(const std::string& dataDir,
}
{
uint32_t levels = _tree_heights.at(MerkleTreeId::ARCHIVE);
std::vector<bb::fr> initial_values{ compute_initial_archive(
std::vector<bb::fr> initial_values{ compute_initial_block_header_hash(
get_state_reference(WorldStateRevision::committed(), fork, true), _initial_header_generator_point) };
auto store = std::make_unique<FrStore>(
getMerkleTreeName(MerkleTreeId::ARCHIVE), levels, _persistentStores->archiveStore);
Expand Down Expand Up @@ -876,9 +876,10 @@ bool WorldState::remove_historical_block(const block_number_t& blockNumber, Worl
return true;
}

bb::fr WorldState::compute_initial_archive(const StateReference& initial_state_ref, uint32_t generator_point)
bb::fr WorldState::compute_initial_block_header_hash(const StateReference& initial_state_ref, uint32_t generator_point)
{
// NOTE: this hash operations needs to match the one in yarn-project/circuits.js/src/structs/header.ts
// NOTE: this hash operations needs to match the one in
// noir-project/noir-protocol-circuits/crates/types/src/block_header.nr
return HashPolicy::hash({ generator_point,
// last archive - which, at genesis, is all 0s
0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ class WorldState {
bool is_archive_tip(const WorldStateRevision& revision, const bb::fr& block_header_hash) const;

bool is_same_state_reference(const WorldStateRevision& revision, const StateReference& state_ref) const;
static bb::fr compute_initial_archive(const StateReference& initial_state_ref, uint32_t generator_point);
static bb::fr compute_initial_block_header_hash(const StateReference& initial_state_ref, uint32_t generator_point);

static StateReference get_state_reference(const WorldStateRevision& revision,
Fork::SharedPtr fork,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,13 @@ TEST_F(WorldStateTest, GetInitialTreeInfoForAllTrees)
EXPECT_EQ(info.meta.depth, tree_heights.at(MerkleTreeId::ARCHIVE));
// this is the expected archive tree root at genesis
EXPECT_EQ(info.meta.root, bb::fr("0x0237797d6a2c04d20d4fa06b74482bd970ccd51a43d9b05b57e9b91fa1ae1cae"));

// The leaf at index 0 is the genesis block hash.
assert_leaf_value(ws,
WorldStateRevision::committed(),
MerkleTreeId::ARCHIVE,
0,
fr("0x2da55666630fdf8594065c377958c827dc1c130dac91f17c6699b53dce60ef75"));
}
}

Expand Down
2 changes: 1 addition & 1 deletion l1-contracts/src/core/Rollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Ownable, Leonidas, IRollup, ITes
congestionCost: 0
}),
archive: bytes32(Constants.GENESIS_ARCHIVE_ROOT),
blockHash: bytes32(0), // TODO(palla/prover): The first block does not have hash zero
blockHash: bytes32(Constants.GENESIS_BLOCK_HASH),
slotNumber: Slot.wrap(0)
});
rollupStore.l1GasOracleValues = L1GasOracleValues({
Expand Down
2 changes: 2 additions & 0 deletions l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ library Constants {
uint256 internal constant BLOBS_PER_BLOCK = 3;
uint256 internal constant PRIVATE_LOG_SIZE_IN_FIELDS = 18;
uint256 internal constant AZTEC_MAX_EPOCH_DURATION = 48;
uint256 internal constant GENESIS_BLOCK_HASH =
20646204262468251631976884937192820660867507115079672078981654411421834866549;
uint256 internal constant GENESIS_ARCHIVE_ROOT =
1002640778211850180189505934749257244705296832326768971348723156503780793518;
uint256 internal constant FEE_JUICE_INITIAL_MINT = 200000000000000000000;
Expand Down
3 changes: 1 addition & 2 deletions l1-contracts/src/core/libraries/RollupLibs/EpochProofLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,8 @@ library EpochProofLib {
);

bytes32 expectedPreviousBlockHash = _rollupStore.blocks[previousBlockNumber].blockHash;
// TODO: Remove 0 check once we inject the proper genesis block hash
require(
expectedPreviousBlockHash == 0 || expectedPreviousBlockHash == _args[2],
expectedPreviousBlockHash == _args[2],
Errors.Rollup__InvalidPreviousBlockHash(expectedPreviousBlockHash, _args[2])
);

Expand Down
2 changes: 1 addition & 1 deletion l1-contracts/test/fees/FeeRollup.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ contract FeeRollupTest is FeeModelTestPoints, DecoderBase {
// We will be using the genesis for both before and after. This will be impossible
// to prove, but we don't need to prove anything here.
bytes32 archiveRoot = bytes32(Constants.GENESIS_ARCHIVE_ROOT);
bytes32 blockHash = 0x267f79fe7e757b20e924fac9f78264a0d1c8c4b481fea21d0bbe74650d87a1f1;
bytes32 blockHash = bytes32(Constants.GENESIS_BLOCK_HASH);

bytes32[] memory txHashes = new bytes32[](0);
Signature[] memory signatures = new Signature[](0);
Expand Down
Loading

0 comments on commit 5eb3e8f

Please sign in to comment.