Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions barretenberg/cpp/src/barretenberg/aztec/aztec_constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
#define MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX 64
#define MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX 63
#define MAX_L2_TO_L1_MSGS_PER_TX 8
#define GENESIS_BLOCK_HEADER_HASH "0x0e7bf88e8833c27b0fca6be614ecc2c63def7bffa35b3ccfa1caff3e39e0c0d2"
#define GENESIS_ARCHIVE_ROOT "0x177a4955b31ecaafad999753938a44e526b54c5ba5d536688227f85f15cfbdf5"
#define GENESIS_BLOCK_HEADER_HASH "0x1302a9e6f643ec596522764c20e5d08d60d33988f11c1559ee13bcd2e2bd8e5d"
#define GENESIS_ARCHIVE_ROOT "0x063786f95f1ae8ebd17b22cb07d7ba122cefae9b0ecb975f5dc3e6e576a5bddc"
#define MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS 3000
#define MAX_PROTOCOL_CONTRACTS 11
#define CONTRACT_CLASS_REGISTRY_CONTRACT_ADDRESS 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ WorldStateWrapper::WorldStateWrapper(const Napi::CallbackInfo& info)
std::unordered_map<MerkleTreeId, uint32_t> tree_height;
std::unordered_map<MerkleTreeId, index_t> tree_prefill;
std::vector<PublicDataLeafValue> prefilled_public_data;
std::vector<bb::fr> prefilled_nullifiers;
std::vector<MerkleTreeId> tree_ids{
MerkleTreeId::NULLIFIER_TREE, MerkleTreeId::NOTE_HASH_TREE, MerkleTreeId::PUBLIC_DATA_TREE,
MerkleTreeId::L1_TO_L2_MESSAGE_TREE, MerkleTreeId::ARCHIVE,
Expand Down Expand Up @@ -112,15 +113,36 @@ WorldStateWrapper::WorldStateWrapper(const Napi::CallbackInfo& info)
throw Napi::TypeError::New(env, "Prefilled public data must be an array");
}

size_t initial_header_generator_point_index = 4;
size_t prefilled_nullifiers_index = 4;
if (info.Length() > prefilled_nullifiers_index && info[prefilled_nullifiers_index].IsArray()) {
Napi::Array arr = info[prefilled_nullifiers_index].As<Napi::Array>();
for (uint32_t i = 0; i < arr.Length(); ++i) {
if (!arr.Get(i).IsBuffer()) {
throw Napi::TypeError::New(env, "Prefilled nullifier value must be a buffer");
}
Napi::Buffer<uint8_t> nullifier_buf = arr.Get(i).As<Napi::Buffer<uint8_t>>();
if (nullifier_buf.Length() != 32) {
throw Napi::TypeError::New(env, "Prefilled nullifier value must be a 32-byte buffer");
}
uint256_t nullifier = 0;
for (size_t j = 0; j < 32; ++j) {
nullifier = (nullifier << 8) | nullifier_buf[j];
}
prefilled_nullifiers.emplace_back(nullifier);
}
} else {
throw Napi::TypeError::New(env, "Prefilled nullifiers must be an array");
}

size_t initial_header_generator_point_index = 5;
if (info.Length() > initial_header_generator_point_index && info[initial_header_generator_point_index].IsNumber()) {
initial_header_generator_point = info[initial_header_generator_point_index].As<Napi::Number>().Uint32Value();
} else {
throw Napi::TypeError::New(env, "Header generator point needs to be a number");
}

uint64_t genesis_timestamp = 0;
size_t genesis_timestamp_index = 5;
size_t genesis_timestamp_index = 6;
if (info.Length() > genesis_timestamp_index) {
if (info[genesis_timestamp_index].IsNumber()) {
genesis_timestamp = static_cast<uint64_t>(info[genesis_timestamp_index].As<Napi::Number>().Int64Value());
Expand All @@ -130,7 +152,7 @@ WorldStateWrapper::WorldStateWrapper(const Napi::CallbackInfo& info)
}

// optional parameters
size_t map_size_index = 6;
size_t map_size_index = 7;
if (info.Length() > map_size_index) {
if (info[map_size_index].IsObject()) {
Napi::Object obj = info[map_size_index].As<Napi::Object>();
Expand Down Expand Up @@ -160,7 +182,7 @@ WorldStateWrapper::WorldStateWrapper(const Napi::CallbackInfo& info)
}
}

size_t thread_pool_size_index = 7;
size_t thread_pool_size_index = 8;
if (info.Length() > thread_pool_size_index) {
if (!info[thread_pool_size_index].IsNumber()) {
throw Napi::TypeError::New(env, "Thread pool size must be a number");
Expand All @@ -173,7 +195,7 @@ WorldStateWrapper::WorldStateWrapper(const Napi::CallbackInfo& info)
// commits never block on fsync, files stay sparse, and a crash mid-write yields an
// unrecoverable env. Intended for throwaway scratch state (TXE test sessions).
bool ephemeral = false;
size_t ephemeral_index = 8;
size_t ephemeral_index = 9;
if (info.Length() > ephemeral_index) {
if (!info[ephemeral_index].IsBoolean()) {
throw Napi::TypeError::New(env, "Ephemeral flag must be a boolean");
Expand All @@ -187,6 +209,7 @@ WorldStateWrapper::WorldStateWrapper(const Napi::CallbackInfo& info)
tree_height,
tree_prefill,
prefilled_public_data,
prefilled_nullifiers,
initial_header_generator_point,
genesis_timestamp,
ephemeral);
Expand Down
Binary file not shown.
16 changes: 14 additions & 2 deletions barretenberg/cpp/src/barretenberg/world_state/world_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ WorldState::WorldState(uint64_t thread_pool_size,
const std::unordered_map<MerkleTreeId, uint32_t>& tree_heights,
const std::unordered_map<MerkleTreeId, index_t>& tree_prefill,
const std::vector<PublicDataLeafValue>& prefilled_public_data,
const std::vector<bb::fr>& prefilled_nullifiers,
uint32_t initial_header_generator_point,
uint64_t genesis_timestamp,
bool ephemeral)
Expand All @@ -51,7 +52,7 @@ WorldState::WorldState(uint64_t thread_pool_size,
{
// We set the max readers to be high, at least the number of given threads or the default if higher
uint64_t maxReaders = std::max(thread_pool_size, DEFAULT_MIN_NUMBER_OF_READERS);
create_canonical_fork(data_dir, map_size, prefilled_public_data, maxReaders, ephemeral);
create_canonical_fork(data_dir, map_size, prefilled_public_data, prefilled_nullifiers, maxReaders, ephemeral);
try {
attempt_tree_resync();
} catch (std::exception& e) {
Expand All @@ -73,6 +74,7 @@ WorldState::WorldState(uint64_t thread_pool_size,
tree_heights,
tree_prefill,
std::vector<PublicDataLeafValue>(),
std::vector<bb::fr>(),
initial_header_generator_point,
genesis_timestamp,
ephemeral)
Expand All @@ -84,6 +86,7 @@ WorldState::WorldState(uint64_t thread_pool_size,
const std::unordered_map<MerkleTreeId, uint32_t>& tree_heights,
const std::unordered_map<MerkleTreeId, index_t>& tree_prefill,
const std::vector<PublicDataLeafValue>& prefilled_public_data,
const std::vector<bb::fr>& prefilled_nullifiers,
uint32_t initial_header_generator_point,
uint64_t genesis_timestamp,
bool ephemeral)
Expand All @@ -99,6 +102,7 @@ WorldState::WorldState(uint64_t thread_pool_size,
tree_heights,
tree_prefill,
prefilled_public_data,
prefilled_nullifiers,
initial_header_generator_point,
genesis_timestamp,
ephemeral)
Expand All @@ -118,6 +122,7 @@ WorldState::WorldState(uint64_t thread_pool_size,
tree_heights,
tree_prefill,
std::vector<PublicDataLeafValue>(),
std::vector<bb::fr>(),
initial_header_generator_point,
genesis_timestamp,
ephemeral)
Expand All @@ -126,6 +131,7 @@ WorldState::WorldState(uint64_t thread_pool_size,
void WorldState::create_canonical_fork(const std::string& dataDir,
const std::unordered_map<MerkleTreeId, uint64_t>& dbSize,
const std::vector<PublicDataLeafValue>& prefilled_public_data,
const std::vector<bb::fr>& prefilled_nullifiers,
uint64_t maxReaders,
bool ephemeral)
{
Expand All @@ -148,9 +154,15 @@ void WorldState::create_canonical_fork(const std::string& dataDir,
{
uint32_t levels = _tree_heights.at(MerkleTreeId::NULLIFIER_TREE);
index_t initial_size = _initial_tree_size.at(MerkleTreeId::NULLIFIER_TREE);
std::vector<NullifierLeafValue> prefilled_nullifier_leaves;
prefilled_nullifier_leaves.reserve(prefilled_nullifiers.size());
for (const auto& nullifier : prefilled_nullifiers) {
prefilled_nullifier_leaves.emplace_back(nullifier);
}
auto store = std::make_unique<NullifierStore>(
getMerkleTreeName(MerkleTreeId::NULLIFIER_TREE), levels, _persistentStores->nullifierStore);
auto tree = std::make_unique<NullifierTree>(std::move(store), _workers, initial_size);
auto tree =
std::make_unique<NullifierTree>(std::move(store), _workers, initial_size, prefilled_nullifier_leaves);
fork->_trees.insert({ MerkleTreeId::NULLIFIER_TREE, TreeWithStore(std::move(tree)) });
}
{
Expand Down
6 changes: 6 additions & 0 deletions barretenberg/cpp/src/barretenberg/world_state/world_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,15 @@ class WorldState {
const std::unordered_map<MerkleTreeId, uint32_t>& tree_heights,
const std::unordered_map<MerkleTreeId, index_t>& tree_prefill,
const std::vector<PublicDataLeafValue>& prefilled_public_data,
const std::vector<bb::fr>& prefilled_nullifiers,
uint32_t initial_header_generator_point,
uint64_t genesis_timestamp = 0,
bool ephemeral = false);

/**
* @param prefilled_nullifiers Nullifier leaves to pre-insert into the genesis nullifier tree (e.g. the protocol
* contract registration nullifiers). Must be unique and strictly increasing in field value, and
* distinct from the padding leaves implied by the nullifier tree prefill size.
* @param ephemeral When true, every underlying LMDB env opens with `MDB_NOSYNC |
* MDB_NOMETASYNC`. Commits return without waiting for fsync; the kernel
* flushes lazily, files stay sparse. Intended for throwaway scratch
Expand All @@ -99,6 +103,7 @@ class WorldState {
const std::unordered_map<MerkleTreeId, uint32_t>& tree_heights,
const std::unordered_map<MerkleTreeId, index_t>& tree_prefill,
const std::vector<PublicDataLeafValue>& prefilled_public_data,
const std::vector<bb::fr>& prefilled_nullifiers,
uint32_t initial_header_generator_point,
uint64_t genesis_timestamp = 0,
bool ephemeral = false);
Expand Down Expand Up @@ -326,6 +331,7 @@ class WorldState {
void create_canonical_fork(const std::string& dataDir,
const std::unordered_map<MerkleTreeId, uint64_t>& dbSize,
const std::vector<PublicDataLeafValue>& prefilled_public_data,
const std::vector<bb::fr>& prefilled_nullifiers,
uint64_t maxReaders,
bool ephemeral);

Expand Down
27 changes: 25 additions & 2 deletions barretenberg/cpp/src/barretenberg/world_state/world_state.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,13 +168,35 @@ void assert_fork_state_unchanged(const WorldState& ws,

TEST_F(WorldStateTest, GetInitialTreeInfoForAllTrees)
{
WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
// The canonical protocol contract registration nullifiers seeded into the genesis nullifier tree in production.
// These must stay in sync with `ProtocolContractGenesisNullifiers` in
// yarn-project/protocol-contracts/src/protocol_contract_data.ts (regenerated from the noir artifacts). They are
// sorted ascending because the indexed nullifier tree requires its prefilled leaves to be unique and strictly
// increasing. The genesis archive root and block header hash below depend on these values.
std::vector<bb::fr> prefilled_nullifiers = {
bb::fr("0x005c0a9bddf634b60b266dddcd84552e9b7845b43d5d1a938d996e6709793839"),
bb::fr("0x0d99507b7ecac720c73bf197a0e7366a5ed80c1c1b0afe8ff8c6ecc7b5a7aefe"),
bb::fr("0x0eb50b367fb754d3a7d1238bfc105cc9b391a02e187be69038876ae9a502e877"),
bb::fr("0x0eef0cc0fb564969f5f28dfb46ec3c271dd4cf4af1d355abf8d89ff9f6265000"),
bb::fr("0x1cea539e01abaa5db980e7ff52ef0d2a7772310306ac625783ae435756ee326d"),
bb::fr("0x237d1818f0030cf4062b26f367a2c8ba0faa6dfaa7349d8df1b6c237d0985568"),
};
WorldState ws(thread_pool_size,
data_dir,
map_size,
tree_heights,
tree_prefill,
std::vector<PublicDataLeafValue>(),
prefilled_nullifiers,
initial_header_generator_point);

{
auto info = ws.get_tree_info(WorldStateRevision::committed(), MerkleTreeId::NULLIFIER_TREE);
// The prefilled nullifiers occupy the last slots of the 128-leaf initial prefill region (they replace padding
// leaves rather than being appended), so the tree size stays 128 but the root reflects the seeded values.
EXPECT_EQ(info.meta.size, 128);
EXPECT_EQ(info.meta.depth, tree_heights.at(MerkleTreeId::NULLIFIER_TREE));
EXPECT_EQ(info.meta.root, bb::fr("0x18935581a8ed73d08ffd00386fba55ba6c89f3ab848a76b8fedfa9034cee0454"));
EXPECT_EQ(info.meta.root, bb::fr("0x1bcda34f33b87d40db8bb8ee1378ef7123c16c197da1ded6ea47659230559f42"));
}

{
Expand Down Expand Up @@ -225,6 +247,7 @@ TEST_F(WorldStateTest, GetInitialTreeInfoWithPrefilledPublicData)
tree_heights,
tree_prefill,
prefilled_values,
std::vector<bb::fr>(),
initial_header_generator_point);

WorldState ws(thread_pool_size, data_dir, map_size, tree_heights, tree_prefill, initial_header_generator_point);
Expand Down
6 changes: 6 additions & 0 deletions barretenberg/cpp/src/barretenberg/wsdb/wsdb_ipc_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,18 @@ int execute_wsdb_server(const std::string& input_path,

// Create WorldState
std::cerr << "Creating WorldState at " << data_dir << " with " << threads << " threads" << '\n';
// This standalone IPC server is non-production tooling and does not accept prefilled genesis nullifiers over the
// wire (the production node path is the napi nodejs_module, which seeds the canonical protocol contract
// registration nullifiers). It must NOT be used to initialize canonical/consensus genesis: an empty nullifier set
// here yields a different genesis root than production and would diverge from consensus.
std::vector<bb::fr> prefilled_nullifiers;
auto ws = std::make_unique<WorldState>(threads,
data_dir,
map_size,
tree_height,
tree_prefill,
prefilled_public_data,
prefilled_nullifiers,
initial_header_generator_point,
genesis_timestamp);

Expand Down
2 changes: 1 addition & 1 deletion l1-contracts/script/deploy/DeployRollupForUpgradeV5.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ contract DeployRollupForUpgradeV5 is Script, StdAssertions {
bytes32 internal constant EXPECTED_PROTOCOL_CONTRACTS_HASH =
0x016d8ee101b952bcb395235a0ab89707008374dda24f70c1f3911f1b0539d6c4;
bytes32 internal constant EXPECTED_GENESIS_ARCHIVE_ROOT =
0x177a4955b31ecaafad999753938a44e526b54c5ba5d536688227f85f15cfbdf5;
0x063786f95f1ae8ebd17b22cb07d7ba122cefae9b0ecb975f5dc3e6e576a5bddc;

uint256 internal constant ENTRY_QUEUE_BOOTSTRAP_VALIDATOR_SET_SIZE = 500;
uint256 internal constant ENTRY_QUEUE_BOOTSTRAP_FLUSH_SIZE = 4;
Expand Down
2 changes: 1 addition & 1 deletion l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ library Constants {
uint256 internal constant INITIAL_CHECKPOINT_NUMBER = 1;
uint256 internal constant MAX_CHECKPOINTS_PER_EPOCH = 32;
uint256 internal constant GENESIS_ARCHIVE_ROOT =
10_619_256_997_260_439_436_842_531_499_967_995_403_253_967_496_480_475_679_746_178_797_053_672_406_517;
2_811_985_237_115_337_302_441_007_096_010_206_688_216_126_612_881_585_569_089_559_449_761_808_235_996;
uint256 internal constant EMPTY_EPOCH_OUT_HASH =
355_785_372_471_781_095_838_790_036_702_437_931_769_306_153_278_986_832_745_847_530_947_941_691_539;
uint256 internal constant FEE_JUICE_ADDRESS = 3;
Expand Down
22 changes: 11 additions & 11 deletions l1-contracts/test/fixtures/empty_checkpoint_1.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,29 @@
"l2ToL1Messages": []
},
"checkpoint": {
"archive": "0x09d45c1e01b8596153838a068ddb470ead95e6e1e151f40b4d48664c1e311af6",
"blobCommitments": "0x01b5ee84e13509320e7da39921b53268c6e918a8981cc76cea986944ee28cebf6f6792d882657deafbc05c8acae3e0e3c0",
"batchedBlobInputs": "0x01851e02ace4d00c5648b2c63e082a6b23bbb7409c4b56f593b30ffd179f37482294e64217fe3e55d50b62a2d8de4b8cebe8b27dcbb32271b1c2745551eb4e5636f3a36a62e42bada7d17029a10c09583af4da2dca90062ca5c55a7478ebae8db5ee84e13509320e7da39921b53268c6e918a8981cc76cea986944ee28cebf6f6792d882657deafbc05c8acae3e0e3c084d838af4d5c73b08f0150f8415f80949e980ef4efa679cc47a07b1683cc8158fabf688dc0fbddd0179b955abb08f841",
"archive": "0x037adb6c2d8b6b4af5b940805ba653f5580ab595734d59362dd58a82cefc5468",
"blobCommitments": "0x01b2305b8b54df6babd7d41c8618a6e445dfc259d4fbb5e6c65fa3e80fbb87e32dd49133ad76a2e51f244e24e60499f78f",
"batchedBlobInputs": "0x01bf03ab3a8048a603a9eda955c955ca82625c2761ee470f75b9a5ddb3ac1dc509926f4782ae4df8bd8a61a241db305699049c8eea2d58e2910e27503b3156bd22947826081782f28266e2d5fc9eee40e3768766dab90f672e0751d250539d51b2305b8b54df6babd7d41c8618a6e445dfc259d4fbb5e6c65fa3e80fbb87e32dd49133ad76a2e51f244e24e60499f78fb9ceb843f67810e2459dda50512d0e5cee2338439c2948095fa3689b237bf265aa8b26106cf87459b358c132df9204f6",
"checkpointNumber": 1,
"body": "0x00000000",
"header": {
"lastArchiveRoot": "0x177a4955b31ecaafad999753938a44e526b54c5ba5d536688227f85f15cfbdf5",
"blockHeadersHash": "0x2e3e0911389bc48fa8126a93273d016cc7dc08019f8ffc5f1f5ae7d90745eaa2",
"blobsHash": "0x00e5b752fe6bc2154155ff3a979c4c5fa91d3ac0d716169ac521e1560fd83b2b",
"lastArchiveRoot": "0x063786f95f1ae8ebd17b22cb07d7ba122cefae9b0ecb975f5dc3e6e576a5bddc",
"blockHeadersHash": "0x07a738639dc7a01808721838e58ce8329afc306411f38e392e6c278839f4301f",
"blobsHash": "0x00a36a05d6711c5939c6f7ba2bf25be30f6c74b2f625d90d32873189f8622dc0",
"inHash": "0x00de7b349d2306334734e4f58b1302a6ed5a6c796a706f6597a5641b6d468223",
"outHash": "0x00c95e0ceb41951039e1592745ec2faea9866f6eaf01bf189a4463b4143af093",
"slotNumber": 99,
"timestamp": 1776857814,
"coinbase": "0x35b8c86ef5942f43d1541967cb19102a2d993b31",
"feeRecipient": "0x1e23fb62f5dd64886d92830820df4ee59bb32fe60838439a13dfb209f4d89b15",
"timestamp": 1782246833,
"coinbase": "0x3c57acde85c7551ccf764e90d413ce5fe2910f51",
"feeRecipient": "0x22aa2abc106d2738fab022606ef6ef3e07435f6a15a37011bd573d06b9ee2f51",
"gasFees": {
"feePerDaGas": 0,
"feePerL2Gas": 292838000000
"feePerL2Gas": 291266000000
},
"totalManaUsed": 0,
"accumulatedFees": 0
},
"headerHash": "0x0069eb49ccf7b0dd2902a19712dd167fd3b5d890df7f0711fdcfe4d2987838ad",
"headerHash": "0x00222d56bf1a4050b91aa02962597be293dbf893f796503818949bbc5be1c552",
"numTxs": 0
}
}
Loading
Loading