Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
world_state.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4#include <any>
5#include <array>
6#include <cstdint>
7#include <iostream>
8#include <memory>
9#include <optional>
10#include <sstream>
11#include <stdexcept>
12#include <sys/types.h>
13#include <unordered_map>
14
27#include "napi.h"
28
29using namespace bb::nodejs;
30using namespace bb::world_state;
31using namespace bb::crypto::merkle_tree;
32using namespace bb::messaging;
33
34const uint64_t DEFAULT_MAP_SIZE = 1024UL * 1024;
35
37 : ObjectWrap(info)
38{
39 uint64_t thread_pool_size = 16;
40 std::string data_dir;
42 { MerkleTreeId::ARCHIVE, DEFAULT_MAP_SIZE },
43 { MerkleTreeId::NULLIFIER_TREE, DEFAULT_MAP_SIZE },
44 { MerkleTreeId::NOTE_HASH_TREE, DEFAULT_MAP_SIZE },
45 { MerkleTreeId::PUBLIC_DATA_TREE, DEFAULT_MAP_SIZE },
46 { MerkleTreeId::L1_TO_L2_MESSAGE_TREE, DEFAULT_MAP_SIZE },
47 };
48 std::unordered_map<MerkleTreeId, uint32_t> tree_height;
49 std::unordered_map<MerkleTreeId, index_t> tree_prefill;
50 std::vector<PublicDataLeafValue> prefilled_public_data;
52 MerkleTreeId::NULLIFIER_TREE, MerkleTreeId::NOTE_HASH_TREE, MerkleTreeId::PUBLIC_DATA_TREE,
53 MerkleTreeId::L1_TO_L2_MESSAGE_TREE, MerkleTreeId::ARCHIVE,
54 };
55 uint32_t initial_header_generator_point = 0;
56
57 Napi::Env env = info.Env();
58
59 size_t data_dir_index = 0;
60 if (info.Length() > data_dir_index && info[data_dir_index].IsString()) {
61 data_dir = info[data_dir_index].As<Napi::String>();
62 } else {
63 throw Napi::TypeError::New(env, "Directory needs to be a string");
64 }
65
66 size_t tree_height_index = 1;
67 if (info.Length() > tree_height_index && info[tree_height_index].IsObject()) {
68 Napi::Object obj = info[tree_height_index].As<Napi::Object>();
69
70 for (auto tree_id : tree_ids) {
71 if (obj.Has(tree_id)) {
72 tree_height[tree_id] = obj.Get(tree_id).As<Napi::Number>().Uint32Value();
73 }
74 }
75 } else {
76 throw Napi::TypeError::New(env, "Tree heights must be a map");
77 }
78
79 size_t tree_prefill_index = 2;
80 if (info.Length() > tree_prefill_index && info[tree_prefill_index].IsObject()) {
81 Napi::Object obj = info[tree_prefill_index].As<Napi::Object>();
82
83 for (auto tree_id : tree_ids) {
84 if (obj.Has(tree_id)) {
85 tree_prefill[tree_id] = obj.Get(tree_id).As<Napi::Number>().Uint32Value();
86 }
87 }
88 } else {
89 throw Napi::TypeError::New(env, "Tree prefill must be a map");
90 }
91
92 size_t prefilled_public_data_index = 3;
93 if (info.Length() > prefilled_public_data_index && info[prefilled_public_data_index].IsArray()) {
94 Napi::Array arr = info[prefilled_public_data_index].As<Napi::Array>();
95 for (uint32_t i = 0; i < arr.Length(); ++i) {
96 Napi::Array deserialized = arr.Get(i).As<Napi::Array>();
97 if (deserialized.Length() != 2 || !deserialized.Get(uint32_t(0)).IsBuffer() ||
98 !deserialized.Get(uint32_t(1)).IsBuffer()) {
99 throw Napi::TypeError::New(env, "Prefilled public data value must be a buffer array of size 2");
100 }
101 Napi::Buffer<uint8_t> slot_buf = deserialized.Get(uint32_t(0)).As<Napi::Buffer<uint8_t>>();
102 Napi::Buffer<uint8_t> value_buf = deserialized.Get(uint32_t(1)).As<Napi::Buffer<uint8_t>>();
103 uint256_t slot = 0;
104 uint256_t value = 0;
105 for (size_t j = 0; j < 32; ++j) {
106 slot = (slot << 8) | slot_buf[j];
107 value = (value << 8) | value_buf[j];
108 }
109 prefilled_public_data.push_back(PublicDataLeafValue(slot, value));
110 }
111 } else {
112 throw Napi::TypeError::New(env, "Prefilled public data must be an array");
113 }
114
115 size_t initial_header_generator_point_index = 4;
116 if (info.Length() > initial_header_generator_point_index && info[initial_header_generator_point_index].IsNumber()) {
117 initial_header_generator_point = info[initial_header_generator_point_index].As<Napi::Number>().Uint32Value();
118 } else {
119 throw Napi::TypeError::New(env, "Header generator point needs to be a number");
120 }
121
122 uint64_t genesis_timestamp = 0;
123 size_t genesis_timestamp_index = 5;
124 if (info.Length() > genesis_timestamp_index) {
125 if (info[genesis_timestamp_index].IsNumber()) {
126 genesis_timestamp = static_cast<uint64_t>(info[genesis_timestamp_index].As<Napi::Number>().Int64Value());
127 } else {
128 throw Napi::TypeError::New(env, "Genesis timestamp needs to be a number");
129 }
130 }
131
132 // optional parameters
133 size_t map_size_index = 6;
134 if (info.Length() > map_size_index) {
135 if (info[map_size_index].IsObject()) {
136 Napi::Object obj = info[map_size_index].As<Napi::Object>();
137
138 for (auto tree_id : tree_ids) {
139 if (obj.Has(tree_id)) {
140 // Int64Value is the widest integer accessor in N-API (no Uint64Value exists)
141 int64_t val = obj.Get(tree_id).As<Napi::Number>().Int64Value();
142 if (val <= 0) {
143 throw Napi::TypeError::New(env, "Map size must be a positive number");
144 }
145 map_size[tree_id] = static_cast<uint64_t>(val);
146 }
147 }
148 } else if (info[map_size_index].IsNumber()) {
149 // Int64Value is the widest integer accessor in N-API (no Uint64Value exists)
150 int64_t val = info[map_size_index].As<Napi::Number>().Int64Value();
151 if (val <= 0) {
152 throw Napi::TypeError::New(env, "Map size must be a positive number");
153 }
154 uint64_t size = static_cast<uint64_t>(val);
155 for (auto tree_id : tree_ids) {
156 map_size[tree_id] = size;
157 }
158 } else {
159 throw Napi::TypeError::New(env, "Map size must be a number or an object");
160 }
161 }
162
163 size_t thread_pool_size_index = 7;
164 if (info.Length() > thread_pool_size_index) {
165 if (!info[thread_pool_size_index].IsNumber()) {
166 throw Napi::TypeError::New(env, "Thread pool size must be a number");
167 }
168
169 thread_pool_size = info[thread_pool_size_index].As<Napi::Number>().Uint32Value();
170 }
171
172 // `ephemeral` opens each underlying LMDB env with `MDB_NOSYNC | MDB_NOMETASYNC` —
173 // commits never block on fsync, files stay sparse, and a crash mid-write yields an
174 // unrecoverable env. Intended for throwaway scratch state (TXE test sessions).
175 bool ephemeral = false;
176 size_t ephemeral_index = 8;
177 if (info.Length() > ephemeral_index) {
178 if (!info[ephemeral_index].IsBoolean()) {
179 throw Napi::TypeError::New(env, "Ephemeral flag must be a boolean");
180 }
181 ephemeral = info[ephemeral_index].As<Napi::Boolean>().Value();
182 }
183
184 _ws = std::make_unique<WorldState>(thread_pool_size,
185 data_dir,
186 map_size,
187 tree_height,
188 tree_prefill,
189 prefilled_public_data,
190 initial_header_generator_point,
191 genesis_timestamp,
192 ephemeral);
193
196 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return get_tree_info(obj, buffer); });
197
200 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return get_state_reference(obj, buffer); });
201
204 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return get_initial_state_reference(obj, buffer); });
205
208 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return get_leaf_value(obj, buffer); });
209
212 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return get_leaf_preimage(obj, buffer); });
213
216 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return get_sibling_path(obj, buffer); });
217
219 [this](msgpack::object& obj, msgpack::sbuffer& buffer) {
221 });
222
225 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return find_leaf_indices(obj, buffer); });
226
229 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return find_sibling_paths(obj, buffer); });
230
233 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return find_low_leaf(obj, buffer); });
234
237 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return append_leaves(obj, buffer); });
238
241 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return batch_insert(obj, buffer); });
242
245 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return sequential_insert(obj, buffer); });
246
249 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return update_archive(obj, buffer); });
250
252 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return commit(obj, buffer); });
253
256 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return rollback(obj, buffer); });
257
260 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return sync_block(obj, buffer); });
261
264 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return create_fork(obj, buffer); });
265
268 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return delete_fork(obj, buffer); });
269
272 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return set_finalized(obj, buffer); });
273
275 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return unwind(obj, buffer); });
276
279 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return remove_historical(obj, buffer); });
280
283 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return get_status(obj, buffer); });
284
286 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return close(obj, buffer); });
287
290 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return checkpoint(obj, buffer); });
291
294 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return commit_checkpoint(obj, buffer); });
295
298 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return revert_checkpoint(obj, buffer); });
299
302 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return commit_all_checkpoints_to(obj, buffer); });
303
306 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return revert_all_checkpoints_to(obj, buffer); });
307
310 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return copy_stores(obj, buffer); });
311}
312
313Napi::Value WorldStateWrapper::call(const Napi::CallbackInfo& info)
314{
315 Napi::Env env = info.Env();
316 // keep this in a shared pointer so that AsyncOperation can resolve/reject the promise once the execution is
317 // complete on an separate thread
319
320 if (info.Length() < 1) {
321 deferred->Reject(Napi::TypeError::New(env, "Wrong number of arguments").Value());
322 } else if (!info[0].IsBuffer()) {
323 deferred->Reject(Napi::TypeError::New(env, "Argument must be a buffer").Value());
324 } else if (!_ws) {
325 deferred->Reject(Napi::TypeError::New(env, "World state has been closed").Value());
326 } else {
327 auto buffer = info[0].As<Napi::Buffer<char>>();
328 size_t length = buffer.Length();
329 // we mustn't access the Napi::Env outside of this top-level function
330 // so copy the data to a variable we own
331 // and make it a shared pointer so that it doesn't get destroyed as soon as we exit this code block
333 std::copy_n(buffer.Data(), length, data->data());
334
335 auto* op = new AsyncOperation(env, deferred, [=, this](msgpack::sbuffer& buf) {
336 msgpack::object_handle obj_handle = msgpack::unpack(data->data(), length);
337 msgpack::object obj = obj_handle.get();
338 _dispatcher.on_new_data(obj, buf);
339 });
340
341 // Napi is now responsible for destroying this object
342 op->Queue();
343 }
344
345 return deferred->Promise();
346}
347
348Napi::Value WorldStateWrapper::getHandle(const Napi::CallbackInfo& info)
349{
350 Napi::Env env = info.Env();
351
352 if (!_ws) {
353 throw Napi::Error::New(env, "World state has been closed");
354 }
355
356 // Return a NAPI External that wraps the raw WorldState pointer
357 // This allows other NAPI functions to access the WorldState instance
358 return Napi::External<WorldState>::New(env, _ws.get());
359}
360
361bool WorldStateWrapper::get_tree_info(msgpack::object& obj, msgpack::sbuffer& buffer) const
362{
364 obj.convert(request);
365 auto info = _ws->get_tree_info(request.value.revision, request.value.treeId);
366
367 MsgHeader header(request.header.messageId);
370 header,
371 { request.value.treeId, info.meta.root, info.meta.size, info.meta.depth });
372
373 msgpack::pack(buffer, resp_msg);
374
375 return true;
376}
377
378bool WorldStateWrapper::get_state_reference(msgpack::object& obj, msgpack::sbuffer& buffer) const
379{
381 obj.convert(request);
382 auto state = _ws->get_state_reference(request.value.revision);
383
384 MsgHeader header(request.header.messageId);
387
388 msgpack::pack(buffer, resp_msg);
389
390 return true;
391}
392
393bool WorldStateWrapper::get_initial_state_reference(msgpack::object& obj, msgpack::sbuffer& buffer) const
394{
395 HeaderOnlyMessage request;
396 obj.convert(request);
397 auto state = _ws->get_initial_state_reference();
398
399 MsgHeader header(request.header.messageId);
402
403 msgpack::pack(buffer, resp_msg);
404
405 return true;
406}
407
408bool WorldStateWrapper::get_leaf_value(msgpack::object& obj, msgpack::sbuffer& buffer) const
409{
411 obj.convert(request);
412
413 switch (request.value.treeId) {
414 case MerkleTreeId::NOTE_HASH_TREE:
415 case MerkleTreeId::L1_TO_L2_MESSAGE_TREE:
416 case MerkleTreeId::ARCHIVE: {
417 auto leaf = _ws->get_leaf<bb::fr>(request.value.revision, request.value.treeId, request.value.leafIndex);
418
419 MsgHeader header(request.header.messageId);
421 msgpack::pack(buffer, resp_msg);
422 break;
423 }
424
425 case MerkleTreeId::PUBLIC_DATA_TREE: {
426 auto leaf = _ws->get_leaf<crypto::merkle_tree::PublicDataLeafValue>(
427 request.value.revision, request.value.treeId, request.value.leafIndex);
428 MsgHeader header(request.header.messageId);
431 msgpack::pack(buffer, resp_msg);
432 break;
433 }
434
435 case MerkleTreeId::NULLIFIER_TREE: {
436 auto leaf = _ws->get_leaf<crypto::merkle_tree::NullifierLeafValue>(
437 request.value.revision, request.value.treeId, request.value.leafIndex);
438 MsgHeader header(request.header.messageId);
441 msgpack::pack(buffer, resp_msg);
442 break;
443 }
444
445 default:
446 throw std::runtime_error("Unsupported tree type");
447 }
448
449 return true;
450}
451
452bool WorldStateWrapper::get_leaf_preimage(msgpack::object& obj, msgpack::sbuffer& buffer) const
453{
455 obj.convert(request);
456
457 MsgHeader header(request.header.messageId);
458
459 switch (request.value.treeId) {
460 case MerkleTreeId::NULLIFIER_TREE: {
461 auto leaf = _ws->get_indexed_leaf<NullifierLeafValue>(
462 request.value.revision, request.value.treeId, request.value.leafIndex);
465 msgpack::pack(buffer, resp_msg);
466 break;
467 }
468
469 case MerkleTreeId::PUBLIC_DATA_TREE: {
470 auto leaf = _ws->get_indexed_leaf<PublicDataLeafValue>(
471 request.value.revision, request.value.treeId, request.value.leafIndex);
472
475 msgpack::pack(buffer, resp_msg);
476 break;
477 }
478
479 default:
480 throw std::runtime_error("Unsupported tree type");
481 }
482
483 return true;
484}
485
486bool WorldStateWrapper::get_sibling_path(msgpack::object& obj, msgpack::sbuffer& buffer) const
487{
489 obj.convert(request);
490
491 fr_sibling_path path = _ws->get_sibling_path(request.value.revision, request.value.treeId, request.value.leafIndex);
492
493 MsgHeader header(request.header.messageId);
495
496 msgpack::pack(buffer, resp_msg);
497
498 return true;
499}
500
501bool WorldStateWrapper::get_block_numbers_for_leaf_indices(msgpack::object& obj, msgpack::sbuffer& buffer) const
502{
504 obj.convert(request);
505
507 _ws->get_block_numbers_for_leaf_indices(
508 request.value.revision, request.value.treeId, request.value.leafIndices, response.blockNumbers);
509
510 MsgHeader header(request.header.messageId);
513
514 msgpack::pack(buffer, resp_msg);
515
516 return true;
517}
518
519bool WorldStateWrapper::find_leaf_indices(msgpack::object& obj, msgpack::sbuffer& buffer) const
520{
522 obj.convert(request);
523
525
526 switch (request.value.treeId) {
527 case MerkleTreeId::NOTE_HASH_TREE:
528 case MerkleTreeId::L1_TO_L2_MESSAGE_TREE:
529 case MerkleTreeId::ARCHIVE: {
531 obj.convert(r1);
532 _ws->find_leaf_indices<bb::fr>(
533 request.value.revision, request.value.treeId, r1.value.leaves, response.indices, r1.value.startIndex);
534 break;
535 }
536
537 case MerkleTreeId::PUBLIC_DATA_TREE: {
539 obj.convert(r2);
540 _ws->find_leaf_indices<PublicDataLeafValue>(
541 request.value.revision, request.value.treeId, r2.value.leaves, response.indices, r2.value.startIndex);
542 break;
543 }
544 case MerkleTreeId::NULLIFIER_TREE: {
546 obj.convert(r3);
547 _ws->find_leaf_indices<NullifierLeafValue>(
548 request.value.revision, request.value.treeId, r3.value.leaves, response.indices, r3.value.startIndex);
549 break;
550 }
551 default:
552 throw std::runtime_error("Unsupported tree type");
553 }
554
555 MsgHeader header(request.header.messageId);
558 msgpack::pack(buffer, resp_msg);
559
560 return true;
561}
562
563bool WorldStateWrapper::find_sibling_paths(msgpack::object& obj, msgpack::sbuffer& buffer) const
564{
566 obj.convert(request);
567
568 FindLeafPathsResponse response;
569
570 switch (request.value.treeId) {
571 case MerkleTreeId::NOTE_HASH_TREE:
572 case MerkleTreeId::L1_TO_L2_MESSAGE_TREE:
573 case MerkleTreeId::ARCHIVE: {
575 obj.convert(r1);
576 _ws->find_sibling_paths<bb::fr>(request.value.revision, request.value.treeId, r1.value.leaves, response.paths);
577 break;
578 }
579
580 case MerkleTreeId::PUBLIC_DATA_TREE: {
582 obj.convert(r2);
583 _ws->find_sibling_paths<PublicDataLeafValue>(
584 request.value.revision, request.value.treeId, r2.value.leaves, response.paths);
585 break;
586 }
587 case MerkleTreeId::NULLIFIER_TREE: {
589 obj.convert(r3);
590 _ws->find_sibling_paths<NullifierLeafValue>(
591 request.value.revision, request.value.treeId, r3.value.leaves, response.paths);
592 break;
593 }
594 default:
595 throw std::runtime_error("Unsupported tree type");
596 }
597
598 MsgHeader header(request.header.messageId);
601 msgpack::pack(buffer, resp_msg);
602
603 return true;
604}
605
606bool WorldStateWrapper::find_low_leaf(msgpack::object& obj, msgpack::sbuffer& buffer) const
607{
609 obj.convert(request);
610
611 GetLowIndexedLeafResponse low_leaf_info =
612 _ws->find_low_leaf_index(request.value.revision, request.value.treeId, request.value.key);
613
614 MsgHeader header(request.header.messageId);
616 WorldStateMessageType::FIND_LOW_LEAF, header, { low_leaf_info.is_already_present, low_leaf_info.index });
617 msgpack::pack(buffer, response);
618
619 return true;
620}
621
622bool WorldStateWrapper::append_leaves(msgpack::object& obj, msgpack::sbuffer& buf)
623{
625 obj.convert(request);
626
627 switch (request.value.treeId) {
628 case MerkleTreeId::NOTE_HASH_TREE:
629 case MerkleTreeId::L1_TO_L2_MESSAGE_TREE:
630 case MerkleTreeId::ARCHIVE: {
632 obj.convert(r1);
633 _ws->append_leaves<bb::fr>(r1.value.treeId, r1.value.leaves, r1.value.forkId);
634 break;
635 }
636 case MerkleTreeId::PUBLIC_DATA_TREE: {
638 obj.convert(r2);
639 _ws->append_leaves<crypto::merkle_tree::PublicDataLeafValue>(r2.value.treeId, r2.value.leaves, r2.value.forkId);
640 break;
641 }
642 case MerkleTreeId::NULLIFIER_TREE: {
644 obj.convert(r3);
645 _ws->append_leaves<crypto::merkle_tree::NullifierLeafValue>(r3.value.treeId, r3.value.leaves, r3.value.forkId);
646 break;
647 }
648 default:
649 throw std::runtime_error("Unsupported tree type");
650 }
651
652 MsgHeader header(request.header.messageId);
654 msgpack::pack(buf, resp_msg);
655
656 return true;
657}
658
659bool WorldStateWrapper::batch_insert(msgpack::object& obj, msgpack::sbuffer& buffer)
660{
662 obj.convert(request);
663
664 switch (request.value.treeId) {
665 case MerkleTreeId::PUBLIC_DATA_TREE: {
667 obj.convert(r1);
668 auto result = _ws->batch_insert_indexed_leaves<crypto::merkle_tree::PublicDataLeafValue>(
669 request.value.treeId, r1.value.leaves, r1.value.subtreeDepth, r1.value.forkId);
670 MsgHeader header(request.header.messageId);
673 msgpack::pack(buffer, resp_msg);
674
675 break;
676 }
677 case MerkleTreeId::NULLIFIER_TREE: {
679 obj.convert(r2);
680 auto result = _ws->batch_insert_indexed_leaves<crypto::merkle_tree::NullifierLeafValue>(
681 request.value.treeId, r2.value.leaves, r2.value.subtreeDepth, r2.value.forkId);
682 MsgHeader header(request.header.messageId);
685 msgpack::pack(buffer, resp_msg);
686 break;
687 }
688 default:
689 throw std::runtime_error("Unsupported tree type");
690 }
691
692 return true;
693}
694
695bool WorldStateWrapper::sequential_insert(msgpack::object& obj, msgpack::sbuffer& buffer)
696{
698 obj.convert(request);
699
700 switch (request.value.treeId) {
701 case MerkleTreeId::PUBLIC_DATA_TREE: {
703 obj.convert(r1);
704 auto result = _ws->insert_indexed_leaves<crypto::merkle_tree::PublicDataLeafValue>(
705 request.value.treeId, r1.value.leaves, r1.value.forkId);
706 MsgHeader header(request.header.messageId);
709 msgpack::pack(buffer, resp_msg);
710
711 break;
712 }
713 case MerkleTreeId::NULLIFIER_TREE: {
715 obj.convert(r2);
716 auto result = _ws->insert_indexed_leaves<crypto::merkle_tree::NullifierLeafValue>(
717 request.value.treeId, r2.value.leaves, r2.value.forkId);
718 MsgHeader header(request.header.messageId);
721 msgpack::pack(buffer, resp_msg);
722 break;
723 }
724 default:
725 throw std::runtime_error("Unsupported tree type");
726 }
727
728 return true;
729}
730
731bool WorldStateWrapper::update_archive(msgpack::object& obj, msgpack::sbuffer& buf)
732{
734 obj.convert(request);
735
736 _ws->update_archive(request.value.blockStateRef, request.value.blockHeaderHash, request.value.forkId);
737
738 MsgHeader header(request.header.messageId);
740 msgpack::pack(buf, resp_msg);
741
742 return true;
743}
744
745bool WorldStateWrapper::commit(msgpack::object& obj, msgpack::sbuffer& buf)
746{
747 HeaderOnlyMessage request;
748 obj.convert(request);
749
751 _ws->commit(status);
752
753 MsgHeader header(request.header.messageId);
755 msgpack::pack(buf, resp_msg);
756
757 return true;
758}
759
760bool WorldStateWrapper::rollback(msgpack::object& obj, msgpack::sbuffer& buf)
761{
762 HeaderOnlyMessage request;
763 obj.convert(request);
764
765 _ws->rollback();
766
767 MsgHeader header(request.header.messageId);
769 msgpack::pack(buf, resp_msg);
770
771 return true;
772}
773
774bool WorldStateWrapper::sync_block(msgpack::object& obj, msgpack::sbuffer& buf)
775{
777 obj.convert(request);
778
779 WorldStateStatusFull status = _ws->sync_block(request.value.blockStateRef,
780 request.value.blockHeaderHash,
781 request.value.paddedNoteHashes,
782 request.value.paddedL1ToL2Messages,
783 request.value.paddedNullifiers,
784 request.value.publicDataWrites);
785
786 MsgHeader header(request.header.messageId);
788 msgpack::pack(buf, resp_msg);
789
790 return true;
791}
792
793bool WorldStateWrapper::create_fork(msgpack::object& obj, msgpack::sbuffer& buf)
794{
796 obj.convert(request);
797
799 request.value.latest ? std::nullopt : std::optional<block_number_t>(request.value.blockNumber);
800
801 uint64_t forkId = _ws->create_fork(blockNumber);
802
803 MsgHeader header(request.header.messageId);
805 msgpack::pack(buf, resp_msg);
806
807 return true;
808}
809
810bool WorldStateWrapper::delete_fork(msgpack::object& obj, msgpack::sbuffer& buf)
811{
813 obj.convert(request);
814
815 _ws->delete_fork(request.value.forkId);
816
817 MsgHeader header(request.header.messageId);
819 msgpack::pack(buf, resp_msg);
820
821 return true;
822}
823
824bool WorldStateWrapper::close(msgpack::object& obj, msgpack::sbuffer& buf)
825{
826 HeaderOnlyMessage request;
827 obj.convert(request);
828
829 // The only reason this API exists is for testing purposes in TS (e.g. close db, open new db instance to test
830 // persistence)
831 _ws.reset(nullptr);
832
833 MsgHeader header(request.header.messageId);
835 msgpack::pack(buf, resp_msg);
836
837 return true;
838}
839
840bool WorldStateWrapper::set_finalized(msgpack::object& obj, msgpack::sbuffer& buf) const
841{
843 obj.convert(request);
844 WorldStateStatusSummary status = _ws->set_finalized_blocks(request.value.toBlockNumber);
845 MsgHeader header(request.header.messageId);
847 WorldStateMessageType::FINALIZE_BLOCKS, header, { status });
848 msgpack::pack(buf, resp_msg);
849
850 return true;
851}
852
853bool WorldStateWrapper::unwind(msgpack::object& obj, msgpack::sbuffer& buf) const
854{
856 obj.convert(request);
857
858 WorldStateStatusFull status = _ws->unwind_blocks(request.value.toBlockNumber);
859
860 MsgHeader header(request.header.messageId);
862 msgpack::pack(buf, resp_msg);
863
864 return true;
865}
866
867bool WorldStateWrapper::remove_historical(msgpack::object& obj, msgpack::sbuffer& buf) const
868{
870 obj.convert(request);
871 WorldStateStatusFull status = _ws->remove_historical_blocks(request.value.toBlockNumber);
872
873 MsgHeader header(request.header.messageId);
876 msgpack::pack(buf, resp_msg);
877
878 return true;
879}
880
881bool WorldStateWrapper::checkpoint(msgpack::object& obj, msgpack::sbuffer& buffer)
882{
884 obj.convert(request);
885
886 uint32_t depth = _ws->checkpoint(request.value.forkId);
887
888 MsgHeader header(request.header.messageId);
889 CheckpointDepthResponse resp_value{ depth };
891 WorldStateMessageType::CREATE_CHECKPOINT, header, resp_value);
892 msgpack::pack(buffer, resp_msg);
893
894 return true;
895}
896
897bool WorldStateWrapper::commit_checkpoint(msgpack::object& obj, msgpack::sbuffer& buffer)
898{
900 obj.convert(request);
901
902 _ws->commit_checkpoint(request.value.forkId);
903
904 MsgHeader header(request.header.messageId);
906 msgpack::pack(buffer, resp_msg);
907
908 return true;
909}
910
911bool WorldStateWrapper::revert_checkpoint(msgpack::object& obj, msgpack::sbuffer& buffer)
912{
914 obj.convert(request);
915
916 _ws->revert_checkpoint(request.value.forkId);
917
918 MsgHeader header(request.header.messageId);
920 msgpack::pack(buffer, resp_msg);
921
922 return true;
923}
924
925bool WorldStateWrapper::commit_all_checkpoints_to(msgpack::object& obj, msgpack::sbuffer& buffer)
926{
928 obj.convert(request);
929
930 _ws->commit_all_checkpoints_to(request.value.forkId, request.value.depth);
931
932 MsgHeader header(request.header.messageId);
934 msgpack::pack(buffer, resp_msg);
935
936 return true;
937}
938
939bool WorldStateWrapper::revert_all_checkpoints_to(msgpack::object& obj, msgpack::sbuffer& buffer)
940{
942 obj.convert(request);
943
944 _ws->revert_all_checkpoints_to(request.value.forkId, request.value.depth);
945
946 MsgHeader header(request.header.messageId);
948 msgpack::pack(buffer, resp_msg);
949
950 return true;
951}
952
953bool WorldStateWrapper::get_status(msgpack::object& obj, msgpack::sbuffer& buf) const
954{
955 HeaderOnlyMessage request;
956 obj.convert(request);
957
959 _ws->get_status_summary(status);
960
961 MsgHeader header(request.header.messageId);
963 msgpack::pack(buf, resp_msg);
964
965 return true;
966}
967
968bool WorldStateWrapper::copy_stores(msgpack::object& obj, msgpack::sbuffer& buffer)
969{
971 obj.convert(request);
972
973 _ws->copy_stores(request.value.dstPath, request.value.compact.value_or(false));
974
975 MsgHeader header(request.header.messageId);
977 msgpack::pack(buffer, resp_msg);
978
979 return true;
980}
981
982Napi::Function WorldStateWrapper::get_class(Napi::Env env)
983{
984 return DefineClass(env,
985 "WorldState",
986 {
987 WorldStateWrapper::InstanceMethod("call", &WorldStateWrapper::call),
988 WorldStateWrapper::InstanceMethod("getHandle", &WorldStateWrapper::getHandle),
989 });
990}
std::shared_ptr< Napi::ThreadSafeFunction > revert_checkpoint
std::shared_ptr< Napi::ThreadSafeFunction > commit_checkpoint
bool on_new_data(msgpack::object &obj, msgpack::sbuffer &buffer) const
void register_target(uint32_t msgType, const message_handler &handler, bool unique=false)
Encapsulatest some work that can be done off the JavaScript main thread.
Definition async_op.hpp:33
bool get_tree_info(msgpack::object &obj, msgpack::sbuffer &buffer) const
WorldStateWrapper(const Napi::CallbackInfo &)
bool get_initial_state_reference(msgpack::object &obj, msgpack::sbuffer &buffer) const
std::unique_ptr< bb::world_state::WorldState > _ws
bool find_low_leaf(msgpack::object &obj, msgpack::sbuffer &buffer) const
bool get_leaf_value(msgpack::object &obj, msgpack::sbuffer &buffer) const
bool update_archive(msgpack::object &obj, msgpack::sbuffer &buffer)
bool rollback(msgpack::object &obj, msgpack::sbuffer &buffer)
bool set_finalized(msgpack::object &obj, msgpack::sbuffer &buffer) const
bool get_state_reference(msgpack::object &obj, msgpack::sbuffer &buffer) const
bb::messaging::MessageDispatcher _dispatcher
bool remove_historical(msgpack::object &obj, msgpack::sbuffer &buffer) const
bool get_leaf_preimage(msgpack::object &obj, msgpack::sbuffer &buffer) const
bool sequential_insert(msgpack::object &obj, msgpack::sbuffer &buffer)
bool get_block_numbers_for_leaf_indices(msgpack::object &obj, msgpack::sbuffer &buffer) const
bool delete_fork(msgpack::object &obj, msgpack::sbuffer &buffer)
bool revert_checkpoint(msgpack::object &obj, msgpack::sbuffer &buffer)
bool find_sibling_paths(msgpack::object &obj, msgpack::sbuffer &buffer) const
bool sync_block(msgpack::object &obj, msgpack::sbuffer &buffer)
Napi::Value getHandle(const Napi::CallbackInfo &)
Get a NAPI External handle to the underlying WorldState pointer. This allows other NAPI functions to ...
bool close(msgpack::object &obj, msgpack::sbuffer &buffer)
bool create_fork(msgpack::object &obj, msgpack::sbuffer &buffer)
static Napi::Function get_class(Napi::Env)
Register the WorldStateAddon class with the JavaScript runtime.
bool append_leaves(msgpack::object &obj, msgpack::sbuffer &buffer)
bool copy_stores(msgpack::object &obj, msgpack::sbuffer &buffer)
bool find_leaf_indices(msgpack::object &obj, msgpack::sbuffer &buffer) const
bool get_status(msgpack::object &obj, msgpack::sbuffer &buffer) const
bool unwind(msgpack::object &obj, msgpack::sbuffer &buffer) const
bool commit_checkpoint(msgpack::object &obj, msgpack::sbuffer &buffer)
bool commit_all_checkpoints_to(msgpack::object &obj, msgpack::sbuffer &buffer)
bool checkpoint(msgpack::object &obj, msgpack::sbuffer &buffer)
bool batch_insert(msgpack::object &obj, msgpack::sbuffer &buffer)
bool get_sibling_path(msgpack::object &obj, msgpack::sbuffer &buffer) const
Napi::Value call(const Napi::CallbackInfo &)
The only instance method exposed to JavaScript. Takes a msgpack Message and returns a Promise.
bool commit(msgpack::object &obj, msgpack::sbuffer &buffer)
bool revert_all_checkpoints_to(msgpack::object &obj, msgpack::sbuffer &buffer)
#define info(...)
Definition log.hpp:93
std::unique_ptr< uint8_t[]> buffer
Definition engine.cpp:60
const uint64_t DEFAULT_MAP_SIZE
std::vector< fr > fr_sibling_path
Definition hash_path.hpp:14
std::vector< uint8_t > Value
Definition types.hpp:12
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
const uint64_t DEFAULT_MAP_SIZE
std::byte * data
std::vector< std::optional< index_t > > indices
std::vector< std::optional< SiblingPathAndIndex > > paths
std::vector< std::optional< block_number_t > > blockNumbers