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 _ws = std::make_unique<WorldState>(thread_pool_size,
173 data_dir,
174 map_size,
175 tree_height,
176 tree_prefill,
177 prefilled_public_data,
178 initial_header_generator_point,
179 genesis_timestamp);
180
183 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return get_tree_info(obj, buffer); });
184
187 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return get_state_reference(obj, buffer); });
188
191 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return get_initial_state_reference(obj, buffer); });
192
195 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return get_leaf_value(obj, buffer); });
196
199 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return get_leaf_preimage(obj, buffer); });
200
203 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return get_sibling_path(obj, buffer); });
204
206 [this](msgpack::object& obj, msgpack::sbuffer& buffer) {
208 });
209
212 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return find_leaf_indices(obj, buffer); });
213
216 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return find_sibling_paths(obj, buffer); });
217
220 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return find_low_leaf(obj, buffer); });
221
224 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return append_leaves(obj, buffer); });
225
228 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return batch_insert(obj, buffer); });
229
232 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return sequential_insert(obj, buffer); });
233
236 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return update_archive(obj, buffer); });
237
239 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return commit(obj, buffer); });
240
243 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return rollback(obj, buffer); });
244
247 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return sync_block(obj, buffer); });
248
251 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return create_fork(obj, buffer); });
252
255 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return delete_fork(obj, buffer); });
256
259 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return set_finalized(obj, buffer); });
260
262 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return unwind(obj, buffer); });
263
266 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return remove_historical(obj, buffer); });
267
270 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return get_status(obj, buffer); });
271
273 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return close(obj, buffer); });
274
277 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return checkpoint(obj, buffer); });
278
281 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return commit_checkpoint(obj, buffer); });
282
285 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return revert_checkpoint(obj, buffer); });
286
289 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return commit_all_checkpoints_to(obj, buffer); });
290
293 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return revert_all_checkpoints_to(obj, buffer); });
294
297 [this](msgpack::object& obj, msgpack::sbuffer& buffer) { return copy_stores(obj, buffer); });
298}
299
300Napi::Value WorldStateWrapper::call(const Napi::CallbackInfo& info)
301{
302 Napi::Env env = info.Env();
303 // keep this in a shared pointer so that AsyncOperation can resolve/reject the promise once the execution is
304 // complete on an separate thread
306
307 if (info.Length() < 1) {
308 deferred->Reject(Napi::TypeError::New(env, "Wrong number of arguments").Value());
309 } else if (!info[0].IsBuffer()) {
310 deferred->Reject(Napi::TypeError::New(env, "Argument must be a buffer").Value());
311 } else if (!_ws) {
312 deferred->Reject(Napi::TypeError::New(env, "World state has been closed").Value());
313 } else {
314 auto buffer = info[0].As<Napi::Buffer<char>>();
315 size_t length = buffer.Length();
316 // we mustn't access the Napi::Env outside of this top-level function
317 // so copy the data to a variable we own
318 // and make it a shared pointer so that it doesn't get destroyed as soon as we exit this code block
320 std::copy_n(buffer.Data(), length, data->data());
321
322 auto* op = new AsyncOperation(env, deferred, [=, this](msgpack::sbuffer& buf) {
323 msgpack::object_handle obj_handle = msgpack::unpack(data->data(), length);
324 msgpack::object obj = obj_handle.get();
325 _dispatcher.on_new_data(obj, buf);
326 });
327
328 // Napi is now responsible for destroying this object
329 op->Queue();
330 }
331
332 return deferred->Promise();
333}
334
335Napi::Value WorldStateWrapper::getHandle(const Napi::CallbackInfo& info)
336{
337 Napi::Env env = info.Env();
338
339 if (!_ws) {
340 throw Napi::Error::New(env, "World state has been closed");
341 }
342
343 // Return a NAPI External that wraps the raw WorldState pointer
344 // This allows other NAPI functions to access the WorldState instance
345 return Napi::External<WorldState>::New(env, _ws.get());
346}
347
348bool WorldStateWrapper::get_tree_info(msgpack::object& obj, msgpack::sbuffer& buffer) const
349{
351 obj.convert(request);
352 auto info = _ws->get_tree_info(request.value.revision, request.value.treeId);
353
354 MsgHeader header(request.header.messageId);
357 header,
358 { request.value.treeId, info.meta.root, info.meta.size, info.meta.depth });
359
360 msgpack::pack(buffer, resp_msg);
361
362 return true;
363}
364
365bool WorldStateWrapper::get_state_reference(msgpack::object& obj, msgpack::sbuffer& buffer) const
366{
368 obj.convert(request);
369 auto state = _ws->get_state_reference(request.value.revision);
370
371 MsgHeader header(request.header.messageId);
374
375 msgpack::pack(buffer, resp_msg);
376
377 return true;
378}
379
380bool WorldStateWrapper::get_initial_state_reference(msgpack::object& obj, msgpack::sbuffer& buffer) const
381{
382 HeaderOnlyMessage request;
383 obj.convert(request);
384 auto state = _ws->get_initial_state_reference();
385
386 MsgHeader header(request.header.messageId);
389
390 msgpack::pack(buffer, resp_msg);
391
392 return true;
393}
394
395bool WorldStateWrapper::get_leaf_value(msgpack::object& obj, msgpack::sbuffer& buffer) const
396{
398 obj.convert(request);
399
400 switch (request.value.treeId) {
401 case MerkleTreeId::NOTE_HASH_TREE:
402 case MerkleTreeId::L1_TO_L2_MESSAGE_TREE:
403 case MerkleTreeId::ARCHIVE: {
404 auto leaf = _ws->get_leaf<bb::fr>(request.value.revision, request.value.treeId, request.value.leafIndex);
405
406 MsgHeader header(request.header.messageId);
408 msgpack::pack(buffer, resp_msg);
409 break;
410 }
411
412 case MerkleTreeId::PUBLIC_DATA_TREE: {
413 auto leaf = _ws->get_leaf<crypto::merkle_tree::PublicDataLeafValue>(
414 request.value.revision, request.value.treeId, request.value.leafIndex);
415 MsgHeader header(request.header.messageId);
418 msgpack::pack(buffer, resp_msg);
419 break;
420 }
421
422 case MerkleTreeId::NULLIFIER_TREE: {
423 auto leaf = _ws->get_leaf<crypto::merkle_tree::NullifierLeafValue>(
424 request.value.revision, request.value.treeId, request.value.leafIndex);
425 MsgHeader header(request.header.messageId);
428 msgpack::pack(buffer, resp_msg);
429 break;
430 }
431
432 default:
433 throw std::runtime_error("Unsupported tree type");
434 }
435
436 return true;
437}
438
439bool WorldStateWrapper::get_leaf_preimage(msgpack::object& obj, msgpack::sbuffer& buffer) const
440{
442 obj.convert(request);
443
444 MsgHeader header(request.header.messageId);
445
446 switch (request.value.treeId) {
447 case MerkleTreeId::NULLIFIER_TREE: {
448 auto leaf = _ws->get_indexed_leaf<NullifierLeafValue>(
449 request.value.revision, request.value.treeId, request.value.leafIndex);
452 msgpack::pack(buffer, resp_msg);
453 break;
454 }
455
456 case MerkleTreeId::PUBLIC_DATA_TREE: {
457 auto leaf = _ws->get_indexed_leaf<PublicDataLeafValue>(
458 request.value.revision, request.value.treeId, request.value.leafIndex);
459
462 msgpack::pack(buffer, resp_msg);
463 break;
464 }
465
466 default:
467 throw std::runtime_error("Unsupported tree type");
468 }
469
470 return true;
471}
472
473bool WorldStateWrapper::get_sibling_path(msgpack::object& obj, msgpack::sbuffer& buffer) const
474{
476 obj.convert(request);
477
478 fr_sibling_path path = _ws->get_sibling_path(request.value.revision, request.value.treeId, request.value.leafIndex);
479
480 MsgHeader header(request.header.messageId);
482
483 msgpack::pack(buffer, resp_msg);
484
485 return true;
486}
487
488bool WorldStateWrapper::get_block_numbers_for_leaf_indices(msgpack::object& obj, msgpack::sbuffer& buffer) const
489{
491 obj.convert(request);
492
494 _ws->get_block_numbers_for_leaf_indices(
495 request.value.revision, request.value.treeId, request.value.leafIndices, response.blockNumbers);
496
497 MsgHeader header(request.header.messageId);
500
501 msgpack::pack(buffer, resp_msg);
502
503 return true;
504}
505
506bool WorldStateWrapper::find_leaf_indices(msgpack::object& obj, msgpack::sbuffer& buffer) const
507{
509 obj.convert(request);
510
512
513 switch (request.value.treeId) {
514 case MerkleTreeId::NOTE_HASH_TREE:
515 case MerkleTreeId::L1_TO_L2_MESSAGE_TREE:
516 case MerkleTreeId::ARCHIVE: {
518 obj.convert(r1);
519 _ws->find_leaf_indices<bb::fr>(
520 request.value.revision, request.value.treeId, r1.value.leaves, response.indices, r1.value.startIndex);
521 break;
522 }
523
524 case MerkleTreeId::PUBLIC_DATA_TREE: {
526 obj.convert(r2);
527 _ws->find_leaf_indices<PublicDataLeafValue>(
528 request.value.revision, request.value.treeId, r2.value.leaves, response.indices, r2.value.startIndex);
529 break;
530 }
531 case MerkleTreeId::NULLIFIER_TREE: {
533 obj.convert(r3);
534 _ws->find_leaf_indices<NullifierLeafValue>(
535 request.value.revision, request.value.treeId, r3.value.leaves, response.indices, r3.value.startIndex);
536 break;
537 }
538 default:
539 throw std::runtime_error("Unsupported tree type");
540 }
541
542 MsgHeader header(request.header.messageId);
545 msgpack::pack(buffer, resp_msg);
546
547 return true;
548}
549
550bool WorldStateWrapper::find_sibling_paths(msgpack::object& obj, msgpack::sbuffer& buffer) const
551{
553 obj.convert(request);
554
555 FindLeafPathsResponse response;
556
557 switch (request.value.treeId) {
558 case MerkleTreeId::NOTE_HASH_TREE:
559 case MerkleTreeId::L1_TO_L2_MESSAGE_TREE:
560 case MerkleTreeId::ARCHIVE: {
562 obj.convert(r1);
563 _ws->find_sibling_paths<bb::fr>(request.value.revision, request.value.treeId, r1.value.leaves, response.paths);
564 break;
565 }
566
567 case MerkleTreeId::PUBLIC_DATA_TREE: {
569 obj.convert(r2);
570 _ws->find_sibling_paths<PublicDataLeafValue>(
571 request.value.revision, request.value.treeId, r2.value.leaves, response.paths);
572 break;
573 }
574 case MerkleTreeId::NULLIFIER_TREE: {
576 obj.convert(r3);
577 _ws->find_sibling_paths<NullifierLeafValue>(
578 request.value.revision, request.value.treeId, r3.value.leaves, response.paths);
579 break;
580 }
581 default:
582 throw std::runtime_error("Unsupported tree type");
583 }
584
585 MsgHeader header(request.header.messageId);
588 msgpack::pack(buffer, resp_msg);
589
590 return true;
591}
592
593bool WorldStateWrapper::find_low_leaf(msgpack::object& obj, msgpack::sbuffer& buffer) const
594{
596 obj.convert(request);
597
598 GetLowIndexedLeafResponse low_leaf_info =
599 _ws->find_low_leaf_index(request.value.revision, request.value.treeId, request.value.key);
600
601 MsgHeader header(request.header.messageId);
603 WorldStateMessageType::FIND_LOW_LEAF, header, { low_leaf_info.is_already_present, low_leaf_info.index });
604 msgpack::pack(buffer, response);
605
606 return true;
607}
608
609bool WorldStateWrapper::append_leaves(msgpack::object& obj, msgpack::sbuffer& buf)
610{
612 obj.convert(request);
613
614 switch (request.value.treeId) {
615 case MerkleTreeId::NOTE_HASH_TREE:
616 case MerkleTreeId::L1_TO_L2_MESSAGE_TREE:
617 case MerkleTreeId::ARCHIVE: {
619 obj.convert(r1);
620 _ws->append_leaves<bb::fr>(r1.value.treeId, r1.value.leaves, r1.value.forkId);
621 break;
622 }
623 case MerkleTreeId::PUBLIC_DATA_TREE: {
625 obj.convert(r2);
626 _ws->append_leaves<crypto::merkle_tree::PublicDataLeafValue>(r2.value.treeId, r2.value.leaves, r2.value.forkId);
627 break;
628 }
629 case MerkleTreeId::NULLIFIER_TREE: {
631 obj.convert(r3);
632 _ws->append_leaves<crypto::merkle_tree::NullifierLeafValue>(r3.value.treeId, r3.value.leaves, r3.value.forkId);
633 break;
634 }
635 default:
636 throw std::runtime_error("Unsupported tree type");
637 }
638
639 MsgHeader header(request.header.messageId);
641 msgpack::pack(buf, resp_msg);
642
643 return true;
644}
645
646bool WorldStateWrapper::batch_insert(msgpack::object& obj, msgpack::sbuffer& buffer)
647{
649 obj.convert(request);
650
651 switch (request.value.treeId) {
652 case MerkleTreeId::PUBLIC_DATA_TREE: {
654 obj.convert(r1);
655 auto result = _ws->batch_insert_indexed_leaves<crypto::merkle_tree::PublicDataLeafValue>(
656 request.value.treeId, r1.value.leaves, r1.value.subtreeDepth, r1.value.forkId);
657 MsgHeader header(request.header.messageId);
660 msgpack::pack(buffer, resp_msg);
661
662 break;
663 }
664 case MerkleTreeId::NULLIFIER_TREE: {
666 obj.convert(r2);
667 auto result = _ws->batch_insert_indexed_leaves<crypto::merkle_tree::NullifierLeafValue>(
668 request.value.treeId, r2.value.leaves, r2.value.subtreeDepth, r2.value.forkId);
669 MsgHeader header(request.header.messageId);
672 msgpack::pack(buffer, resp_msg);
673 break;
674 }
675 default:
676 throw std::runtime_error("Unsupported tree type");
677 }
678
679 return true;
680}
681
682bool WorldStateWrapper::sequential_insert(msgpack::object& obj, msgpack::sbuffer& buffer)
683{
685 obj.convert(request);
686
687 switch (request.value.treeId) {
688 case MerkleTreeId::PUBLIC_DATA_TREE: {
690 obj.convert(r1);
691 auto result = _ws->insert_indexed_leaves<crypto::merkle_tree::PublicDataLeafValue>(
692 request.value.treeId, r1.value.leaves, r1.value.forkId);
693 MsgHeader header(request.header.messageId);
696 msgpack::pack(buffer, resp_msg);
697
698 break;
699 }
700 case MerkleTreeId::NULLIFIER_TREE: {
702 obj.convert(r2);
703 auto result = _ws->insert_indexed_leaves<crypto::merkle_tree::NullifierLeafValue>(
704 request.value.treeId, r2.value.leaves, r2.value.forkId);
705 MsgHeader header(request.header.messageId);
708 msgpack::pack(buffer, resp_msg);
709 break;
710 }
711 default:
712 throw std::runtime_error("Unsupported tree type");
713 }
714
715 return true;
716}
717
718bool WorldStateWrapper::update_archive(msgpack::object& obj, msgpack::sbuffer& buf)
719{
721 obj.convert(request);
722
723 _ws->update_archive(request.value.blockStateRef, request.value.blockHeaderHash, request.value.forkId);
724
725 MsgHeader header(request.header.messageId);
727 msgpack::pack(buf, resp_msg);
728
729 return true;
730}
731
732bool WorldStateWrapper::commit(msgpack::object& obj, msgpack::sbuffer& buf)
733{
734 HeaderOnlyMessage request;
735 obj.convert(request);
736
738 _ws->commit(status);
739
740 MsgHeader header(request.header.messageId);
742 msgpack::pack(buf, resp_msg);
743
744 return true;
745}
746
747bool WorldStateWrapper::rollback(msgpack::object& obj, msgpack::sbuffer& buf)
748{
749 HeaderOnlyMessage request;
750 obj.convert(request);
751
752 _ws->rollback();
753
754 MsgHeader header(request.header.messageId);
756 msgpack::pack(buf, resp_msg);
757
758 return true;
759}
760
761bool WorldStateWrapper::sync_block(msgpack::object& obj, msgpack::sbuffer& buf)
762{
764 obj.convert(request);
765
766 WorldStateStatusFull status = _ws->sync_block(request.value.blockStateRef,
767 request.value.blockHeaderHash,
768 request.value.paddedNoteHashes,
769 request.value.paddedL1ToL2Messages,
770 request.value.paddedNullifiers,
771 request.value.publicDataWrites);
772
773 MsgHeader header(request.header.messageId);
775 msgpack::pack(buf, resp_msg);
776
777 return true;
778}
779
780bool WorldStateWrapper::create_fork(msgpack::object& obj, msgpack::sbuffer& buf)
781{
783 obj.convert(request);
784
786 request.value.latest ? std::nullopt : std::optional<block_number_t>(request.value.blockNumber);
787
788 uint64_t forkId = _ws->create_fork(blockNumber);
789
790 MsgHeader header(request.header.messageId);
792 msgpack::pack(buf, resp_msg);
793
794 return true;
795}
796
797bool WorldStateWrapper::delete_fork(msgpack::object& obj, msgpack::sbuffer& buf)
798{
800 obj.convert(request);
801
802 _ws->delete_fork(request.value.forkId);
803
804 MsgHeader header(request.header.messageId);
806 msgpack::pack(buf, resp_msg);
807
808 return true;
809}
810
811bool WorldStateWrapper::close(msgpack::object& obj, msgpack::sbuffer& buf)
812{
813 HeaderOnlyMessage request;
814 obj.convert(request);
815
816 // The only reason this API exists is for testing purposes in TS (e.g. close db, open new db instance to test
817 // persistence)
818 _ws.reset(nullptr);
819
820 MsgHeader header(request.header.messageId);
822 msgpack::pack(buf, resp_msg);
823
824 return true;
825}
826
827bool WorldStateWrapper::set_finalized(msgpack::object& obj, msgpack::sbuffer& buf) const
828{
830 obj.convert(request);
831 WorldStateStatusSummary status = _ws->set_finalized_blocks(request.value.toBlockNumber);
832 MsgHeader header(request.header.messageId);
834 WorldStateMessageType::FINALIZE_BLOCKS, header, { status });
835 msgpack::pack(buf, resp_msg);
836
837 return true;
838}
839
840bool WorldStateWrapper::unwind(msgpack::object& obj, msgpack::sbuffer& buf) const
841{
843 obj.convert(request);
844
845 WorldStateStatusFull status = _ws->unwind_blocks(request.value.toBlockNumber);
846
847 MsgHeader header(request.header.messageId);
849 msgpack::pack(buf, resp_msg);
850
851 return true;
852}
853
854bool WorldStateWrapper::remove_historical(msgpack::object& obj, msgpack::sbuffer& buf) const
855{
857 obj.convert(request);
858 WorldStateStatusFull status = _ws->remove_historical_blocks(request.value.toBlockNumber);
859
860 MsgHeader header(request.header.messageId);
863 msgpack::pack(buf, resp_msg);
864
865 return true;
866}
867
868bool WorldStateWrapper::checkpoint(msgpack::object& obj, msgpack::sbuffer& buffer)
869{
871 obj.convert(request);
872
873 uint32_t depth = _ws->checkpoint(request.value.forkId);
874
875 MsgHeader header(request.header.messageId);
876 CheckpointDepthResponse resp_value{ depth };
878 WorldStateMessageType::CREATE_CHECKPOINT, header, resp_value);
879 msgpack::pack(buffer, resp_msg);
880
881 return true;
882}
883
884bool WorldStateWrapper::commit_checkpoint(msgpack::object& obj, msgpack::sbuffer& buffer)
885{
887 obj.convert(request);
888
889 _ws->commit_checkpoint(request.value.forkId);
890
891 MsgHeader header(request.header.messageId);
893 msgpack::pack(buffer, resp_msg);
894
895 return true;
896}
897
898bool WorldStateWrapper::revert_checkpoint(msgpack::object& obj, msgpack::sbuffer& buffer)
899{
901 obj.convert(request);
902
903 _ws->revert_checkpoint(request.value.forkId);
904
905 MsgHeader header(request.header.messageId);
907 msgpack::pack(buffer, resp_msg);
908
909 return true;
910}
911
912bool WorldStateWrapper::commit_all_checkpoints_to(msgpack::object& obj, msgpack::sbuffer& buffer)
913{
915 obj.convert(request);
916
917 _ws->commit_all_checkpoints_to(request.value.forkId, request.value.depth);
918
919 MsgHeader header(request.header.messageId);
921 msgpack::pack(buffer, resp_msg);
922
923 return true;
924}
925
926bool WorldStateWrapper::revert_all_checkpoints_to(msgpack::object& obj, msgpack::sbuffer& buffer)
927{
929 obj.convert(request);
930
931 _ws->revert_all_checkpoints_to(request.value.forkId, request.value.depth);
932
933 MsgHeader header(request.header.messageId);
935 msgpack::pack(buffer, resp_msg);
936
937 return true;
938}
939
940bool WorldStateWrapper::get_status(msgpack::object& obj, msgpack::sbuffer& buf) const
941{
942 HeaderOnlyMessage request;
943 obj.convert(request);
944
946 _ws->get_status_summary(status);
947
948 MsgHeader header(request.header.messageId);
950 msgpack::pack(buf, resp_msg);
951
952 return true;
953}
954
955bool WorldStateWrapper::copy_stores(msgpack::object& obj, msgpack::sbuffer& buffer)
956{
958 obj.convert(request);
959
960 _ws->copy_stores(request.value.dstPath, request.value.compact.value_or(false));
961
962 MsgHeader header(request.header.messageId);
964 msgpack::pack(buffer, resp_msg);
965
966 return true;
967}
968
969Napi::Function WorldStateWrapper::get_class(Napi::Env env)
970{
971 return DefineClass(env,
972 "WorldState",
973 {
974 WorldStateWrapper::InstanceMethod("call", &WorldStateWrapper::call),
975 WorldStateWrapper::InstanceMethod("getHandle", &WorldStateWrapper::getHandle),
976 });
977}
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:28
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
const std::vector< MemoryValue > data
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::vector< std::optional< index_t > > indices
std::vector< std::optional< SiblingPathAndIndex > > paths
std::vector< std::optional< block_number_t > > blockNumbers