From 470bd6ab460c266a64dd77d086f261814be2f87c Mon Sep 17 00:00:00 2001 From: stringhandler Date: Tue, 28 Jun 2022 12:24:45 +0200 Subject: [PATCH] feat: add tari engine for flow and wasm functions --- Cargo.lock | 667 +++++++++++++++++- applications/tari_validator_node/Cargo.toml | 1 + .../src/contract_worker_manager.rs | 3 + .../src/grpc/services/wallet_client.rs | 3 +- .../src/grpc/validator_node_grpc_server.rs | 2 +- .../src/p2p/proto/conversions.rs | 42 +- .../src/p2p/rpc/service_impl.rs | 6 +- .../src/p2p/services/rpc_client.rs | 4 +- dan_layer/common_types/src/lib.rs | 4 + dan_layer/common_types/src/storage/mod.rs | 6 + .../src/storage/unit_of_work_tracker.rs | 47 ++ dan_layer/common_types/src/template_id.rs | 70 ++ dan_layer/core/Cargo.toml | 4 +- dan_layer/core/src/digital_assets_error.rs | 3 + dan_layer/core/src/models/asset_definition.rs | 34 +- .../core/src/models/hot_stuff_tree_node.rs | 3 +- dan_layer/core/src/models/instruction_set.rs | 3 +- dan_layer/core/src/models/mod.rs | 78 +- dan_layer/core/src/models/op_log.rs | 69 -- dan_layer/core/src/models/state_root.rs | 44 -- dan_layer/core/src/models/tari_dan_payload.rs | 3 +- .../core/src/services/asset_processor.rs | 58 +- dan_layer/core/src/services/asset_proxy.rs | 3 +- .../core/src/services/checkpoint_manager.rs | 7 +- .../core/src/services/mempool_service.rs | 6 +- dan_layer/core/src/services/mocks/mod.rs | 25 +- .../core/src/services/payload_processor.rs | 4 +- .../src/services/service_specification.rs | 10 +- .../src/services/validator_node_rpc_client.rs | 4 +- dan_layer/core/src/services/wallet_client.rs | 3 +- .../storage/chain/chain_db_unit_of_work.rs | 5 +- .../core/src/storage/chain/db_instruction.rs | 4 +- dan_layer/core/src/storage/db_factory.rs | 2 +- dan_layer/core/src/storage/error.rs | 6 +- dan_layer/core/src/storage/lmdb/asset_db.rs | 24 - dan_layer/core/src/storage/lmdb/helpers.rs | 46 -- .../src/storage/lmdb/lmdb_asset_backend.rs | 74 -- .../core/src/storage/lmdb/lmdb_asset_store.rs | 130 ---- dan_layer/core/src/storage/lmdb/mod.rs | 35 - dan_layer/core/src/storage/lmdb/test.rs | 59 -- dan_layer/core/src/storage/mocks/mod.rs | 9 +- dan_layer/core/src/storage/mocks/state_db.rs | 106 --- dan_layer/core/src/storage/mod.rs | 5 - .../core/src/storage/state/db_key_value.rs | 28 - dan_layer/core/src/storage/state/mod.rs | 35 - dan_layer/core/src/storage/state/state_db.rs | 58 -- .../storage/state/state_db_backend_adapter.rs | 66 -- .../core/src/storage/state/state_op_log.rs | 77 -- .../core/src/storage/unit_of_work_tracker.rs | 66 -- dan_layer/core/src/template_command.rs | 4 +- .../core/src/templates/tip002_template.rs | 12 +- .../core/src/templates/tip004_template.rs | 7 +- .../core/src/templates/tip721_template.rs | 7 +- .../core/src/workers/consensus_worker.rs | 2 +- .../core/src/workers/state_sync/error.rs | 4 + dan_layer/core/src/workers/state_sync/mod.rs | 15 +- .../core/src/workers/states/next_view.rs | 3 +- dan_layer/core/src/workers/states/prepare.rs | 3 +- .../core/src/workers/states/synchronizing.rs | 3 +- dan_layer/engine/Cargo.toml | 22 + dan_layer/engine/src/flow/error.rs | 9 + dan_layer/engine/src/flow/flow_factory.rs | 45 ++ dan_layer/engine/src/flow/flow_instance.rs | 127 ++++ dan_layer/engine/src/flow/mod.rs | 33 + .../engine/src/flow/workers/arg_worker.rs | 53 ++ .../src/flow/workers/create_bucket_worker.rs | 110 +++ .../src/flow/workers/has_role_worker.rs | 42 ++ .../src/flow/workers/mint_bucket_worker.rs | 61 ++ dan_layer/engine/src/flow/workers/mod.rs | 19 + .../engine/src/flow/workers/sender_worker.rs | 33 + .../engine/src/flow/workers/start_worker.rs | 22 + .../src/flow/workers/store_bucket_worker.rs | 84 +++ .../engine/src/flow/workers/text_worker.rs | 24 + .../flow_function_definition.rs | 13 + .../function_arg_definition.rs | 20 + .../engine/src/function_definitions/mod.rs | 11 + .../wasm_function_definition.rs | 13 + .../src/instructions}/instruction.rs | 26 +- dan_layer/engine/src/instructions/mod.rs | 6 + dan_layer/engine/src/lib.rs | 9 + dan_layer/engine/src/models/bucket.rs | 33 + dan_layer/engine/src/models/mod.rs | 6 + dan_layer/engine/src/state/db_key_value.rs | 9 + dan_layer/engine/src/state/error.rs | 28 + dan_layer/engine/src/state/mocks/mod.rs | 4 + dan_layer/engine/src/state/mocks/state_db.rs | 70 ++ dan_layer/engine/src/state/mod.rs | 22 + .../engine/src/state/models/key_value.rs | 10 + dan_layer/engine/src/state/models/mod.rs | 14 + dan_layer/engine/src/state/models/op_log.rs | 50 ++ .../engine/src/state/models/schema_state.rs | 23 + .../engine/src/state/models/state_root.rs | 25 + dan_layer/engine/src/state/state_db.rs | 39 + .../src/state/state_db_backend_adapter.rs | 35 + .../src}/state/state_db_unit_of_work.rs | 75 +- dan_layer/engine/src/state/state_op_log.rs | 60 ++ dan_layer/engine/src/wasm/error.rs | 10 + dan_layer/engine/src/wasm/mod.rs | 10 + .../engine/src/wasm/wasm_module_definition.rs | 12 + .../engine/src/wasm/wasm_module_factory.rs | 148 ++++ dan_layer/storage_sqlite/Cargo.toml | 4 +- dan_layer/storage_sqlite/src/error.rs | 25 +- .../storage_sqlite/src/models/instruction.rs | 7 +- dan_layer/storage_sqlite/src/models/mod.rs | 1 - .../storage_sqlite/src/models/state_op_log.rs | 14 +- .../storage_sqlite/src/models/state_tree.rs | 38 - .../storage_sqlite/src/sqlite_db_factory.rs | 3 +- .../src/sqlite_state_db_backend_adapter.rs | 76 +- 108 files changed, 2405 insertions(+), 1339 deletions(-) create mode 100644 dan_layer/common_types/src/storage/mod.rs create mode 100644 dan_layer/common_types/src/storage/unit_of_work_tracker.rs create mode 100644 dan_layer/common_types/src/template_id.rs delete mode 100644 dan_layer/core/src/models/op_log.rs delete mode 100644 dan_layer/core/src/models/state_root.rs delete mode 100644 dan_layer/core/src/storage/lmdb/asset_db.rs delete mode 100644 dan_layer/core/src/storage/lmdb/helpers.rs delete mode 100644 dan_layer/core/src/storage/lmdb/lmdb_asset_backend.rs delete mode 100644 dan_layer/core/src/storage/lmdb/lmdb_asset_store.rs delete mode 100644 dan_layer/core/src/storage/lmdb/mod.rs delete mode 100644 dan_layer/core/src/storage/lmdb/test.rs delete mode 100644 dan_layer/core/src/storage/mocks/state_db.rs delete mode 100644 dan_layer/core/src/storage/state/db_key_value.rs delete mode 100644 dan_layer/core/src/storage/state/mod.rs delete mode 100644 dan_layer/core/src/storage/state/state_db.rs delete mode 100644 dan_layer/core/src/storage/state/state_db_backend_adapter.rs delete mode 100644 dan_layer/core/src/storage/state/state_op_log.rs delete mode 100644 dan_layer/core/src/storage/unit_of_work_tracker.rs create mode 100644 dan_layer/engine/Cargo.toml create mode 100644 dan_layer/engine/src/flow/error.rs create mode 100644 dan_layer/engine/src/flow/flow_factory.rs create mode 100644 dan_layer/engine/src/flow/flow_instance.rs create mode 100644 dan_layer/engine/src/flow/mod.rs create mode 100644 dan_layer/engine/src/flow/workers/arg_worker.rs create mode 100644 dan_layer/engine/src/flow/workers/create_bucket_worker.rs create mode 100644 dan_layer/engine/src/flow/workers/has_role_worker.rs create mode 100644 dan_layer/engine/src/flow/workers/mint_bucket_worker.rs create mode 100644 dan_layer/engine/src/flow/workers/mod.rs create mode 100644 dan_layer/engine/src/flow/workers/sender_worker.rs create mode 100644 dan_layer/engine/src/flow/workers/start_worker.rs create mode 100644 dan_layer/engine/src/flow/workers/store_bucket_worker.rs create mode 100644 dan_layer/engine/src/flow/workers/text_worker.rs create mode 100644 dan_layer/engine/src/function_definitions/flow_function_definition.rs create mode 100644 dan_layer/engine/src/function_definitions/function_arg_definition.rs create mode 100644 dan_layer/engine/src/function_definitions/mod.rs create mode 100644 dan_layer/engine/src/function_definitions/wasm_function_definition.rs rename dan_layer/{core/src/models => engine/src/instructions}/instruction.rs (58%) create mode 100644 dan_layer/engine/src/instructions/mod.rs create mode 100644 dan_layer/engine/src/lib.rs create mode 100644 dan_layer/engine/src/models/bucket.rs create mode 100644 dan_layer/engine/src/models/mod.rs create mode 100644 dan_layer/engine/src/state/db_key_value.rs create mode 100644 dan_layer/engine/src/state/error.rs create mode 100644 dan_layer/engine/src/state/mocks/mod.rs create mode 100644 dan_layer/engine/src/state/mocks/state_db.rs create mode 100644 dan_layer/engine/src/state/mod.rs create mode 100644 dan_layer/engine/src/state/models/key_value.rs create mode 100644 dan_layer/engine/src/state/models/mod.rs create mode 100644 dan_layer/engine/src/state/models/op_log.rs create mode 100644 dan_layer/engine/src/state/models/schema_state.rs create mode 100644 dan_layer/engine/src/state/models/state_root.rs create mode 100644 dan_layer/engine/src/state/state_db.rs create mode 100644 dan_layer/engine/src/state/state_db_backend_adapter.rs rename dan_layer/{core/src/storage => engine/src}/state/state_db_unit_of_work.rs (79%) create mode 100644 dan_layer/engine/src/state/state_op_log.rs create mode 100644 dan_layer/engine/src/wasm/error.rs create mode 100644 dan_layer/engine/src/wasm/mod.rs create mode 100644 dan_layer/engine/src/wasm/wasm_module_definition.rs create mode 100644 dan_layer/engine/src/wasm/wasm_module_factory.rs delete mode 100644 dan_layer/storage_sqlite/src/models/state_tree.rs diff --git a/Cargo.lock b/Cargo.lock index 3111f69c49..8d753a3902 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +dependencies = [ + "gimli", +] + [[package]] name = "adler" version = "1.0.2" @@ -371,6 +380,21 @@ dependencies = [ "cc", ] +[[package]] +name = "backtrace" +version = "0.3.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61" +dependencies = [ + "addr2line", + "cc", + "cfg-if 1.0.0", + "libc", + "miniz_oxide 0.5.1", + "object", + "rustc-demangle", +] + [[package]] name = "base58-monero" version = "0.3.2" @@ -674,6 +698,27 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +[[package]] +name = "bytecheck" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a31f923c2db9513e4298b72df143e6e655a759b3d6a0966df18f81223fff54f" +dependencies = [ + "bytecheck_derive", + "ptr_meta", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb17c862a905d912174daa27ae002326fff56dc8b8ada50a0a5f0976cb174f0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "bytecodec" version = "0.4.15" @@ -1223,6 +1268,19 @@ dependencies = [ "memchr", ] +[[package]] +name = "corosensei" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab4b310cff9117ec16d05970743c20df3eaddafd461829f2758e76a8de2863a9" +dependencies = [ + "autocfg", + "cfg-if 1.0.0", + "libc", + "scopeguard", + "windows-sys 0.33.0", +] + [[package]] name = "cpufeatures" version = "0.1.5" @@ -1247,6 +1305,65 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" +[[package]] +name = "cranelift-bforest" +version = "0.82.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38faa2a16616c8e78a18d37b4726b98bfd2de192f2fdc8a39ddf568a408a0f75" +dependencies = [ + "cranelift-entity", +] + +[[package]] +name = "cranelift-codegen" +version = "0.82.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26f192472a3ba23860afd07d2b0217dc628f21fcc72617aa1336d98e1671f33b" +dependencies = [ + "cranelift-bforest", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-entity", + "gimli", + "log", + "regalloc", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.82.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f32ddb89e9b89d3d9b36a5b7d7ea3261c98235a76ac95ba46826b8ec40b1a24" +dependencies = [ + "cranelift-codegen-shared", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.82.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01fd0d9f288cc1b42d9333b7a776b17e278fc888c28e6a0f09b5573d45a150bc" + +[[package]] +name = "cranelift-entity" +version = "0.82.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3bfe172b83167604601faf9dc60453e0d0a93415b57a9c4d1a7ae6849185cf" + +[[package]] +name = "cranelift-frontend" +version = "0.82.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a006e3e32d80ce0e4ba7f1f9ddf66066d052a8c884a110b91d05404d6ce26dce" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + [[package]] name = "crc24" version = "0.1.6" @@ -1666,6 +1783,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "d3ne" +version = "0.7.4" +source = "git+https://github.com/stringhandler/d3ne-rs.git?branch=st-fixes2#ad2b0dfca267c9466251780aecb78bab139846e5" +dependencies = [ + "anyhow", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "darling" version = "0.10.2" @@ -2045,6 +2173,26 @@ dependencies = [ "syn", ] +[[package]] +name = "enum-iterator" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "enumflags2" version = "0.7.4" @@ -2066,6 +2214,27 @@ dependencies = [ "syn", ] +[[package]] +name = "enumset" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4799cdb24d48f1f8a7a98d06b7fde65a85a2d1e42b25a889f5406aa1fbefe074" +dependencies = [ + "enumset_derive", +] + +[[package]] +name = "enumset_derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea83a3fbdc1d999ccfbcbee717eab36f8edf2d71693a23ce0d7cca19e085304c" +dependencies = [ + "darling 0.13.1", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "env_logger" version = "0.7.1" @@ -2141,6 +2310,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + [[package]] name = "fast-float" version = "0.2.0" @@ -2600,6 +2775,17 @@ dependencies = [ "polyval 0.5.3", ] +[[package]] +name = "gimli" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +dependencies = [ + "fallible-iterator", + "indexmap", + "stable_deref_trait", +] + [[package]] name = "gio" version = "0.15.10" @@ -2839,6 +3025,9 @@ name = "hashbrown" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] [[package]] name = "hashbrown" @@ -3133,6 +3322,7 @@ checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" dependencies = [ "autocfg", "hashbrown 0.11.2", + "serde", ] [[package]] @@ -3365,6 +3555,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + [[package]] name = "libc" version = "0.2.121" @@ -3591,6 +3787,27 @@ dependencies = [ "tracing-subscriber 0.3.9", ] +[[package]] +name = "loupe" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6a72dfa44fe15b5e76b94307eeb2ff995a8c5b283b55008940c02e0c5b634d" +dependencies = [ + "indexmap", + "loupe-derive", + "rustversion", +] + +[[package]] +name = "loupe-derive" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fbfc88337168279f2e9ae06e157cfed4efd3316e14dc96ed074d4f2e6c5952" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "mac" version = "0.1.1" @@ -3610,6 +3827,15 @@ dependencies = [ "time 0.3.9", ] +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + [[package]] name = "malloc_buf" version = "0.0.6" @@ -3680,6 +3906,15 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +[[package]] +name = "memmap2" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5172b50c23043ff43dd53e51392f36519d9b35a8f3a410d30ece5d1aedd58ae" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.6.5" @@ -3847,6 +4082,12 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "more-asserts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" + [[package]] name = "multiaddr" version = "0.14.0" @@ -4248,6 +4489,18 @@ dependencies = [ "objc", ] +[[package]] +name = "object" +version = "0.28.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" +dependencies = [ + "crc32fast", + "hashbrown 0.11.2", + "indexmap", + "memchr", +] + [[package]] name = "once_cell" version = "1.12.0" @@ -5163,6 +5416,26 @@ version = "2.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf7e6d18738ecd0902d30d1ad232c9125985a3422929b16c65517b38adc14f96" +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "qrcode" version = "0.12.0" @@ -5408,6 +5681,17 @@ dependencies = [ "thiserror", ] +[[package]] +name = "regalloc" +version = "0.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62446b1d3ebf980bdc68837700af1d77b37bc430e524bf95319c6eada2a4cc02" +dependencies = [ + "log", + "rustc-hash", + "smallvec", +] + [[package]] name = "regex" version = "1.5.5" @@ -5434,6 +5718,18 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +[[package]] +name = "region" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" +dependencies = [ + "bitflags 1.3.2", + "libc", + "mach", + "winapi 0.3.9", +] + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -5443,6 +5739,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "rend" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79af64b4b6362ffba04eef3a4e10829718a4896dac19daa741851c86781edf95" +dependencies = [ + "bytecheck", +] + [[package]] name = "reqwest" version = "0.11.10" @@ -5529,6 +5834,31 @@ dependencies = [ "opaque-debug 0.3.0", ] +[[package]] +name = "rkyv" +version = "0.7.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15" +dependencies = [ + "bytecheck", + "hashbrown 0.12.0", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "ron" version = "0.7.0" @@ -5579,6 +5909,12 @@ dependencies = [ "ordered-multimap", ] +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + [[package]] name = "rustc-hash" version = "1.1.0" @@ -5746,6 +6082,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + [[package]] name = "security-framework" version = "2.6.1" @@ -5841,6 +6183,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_bytes" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212e73464ebcde48d723aa02eb270ba62eff38a9b732df31f33f1b4e145f3a54" +dependencies = [ + "serde", +] + [[package]] name = "serde_cbor" version = "0.11.2" @@ -5864,9 +6215,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.79" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" dependencies = [ "itoa 1.0.1", "ryu", @@ -6496,6 +6847,12 @@ dependencies = [ "xattr", ] +[[package]] +name = "target-lexicon" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1" + [[package]] name = "tari_app_grpc" version = "0.32.5" @@ -6975,13 +7332,11 @@ dependencies = [ "anyhow", "async-trait", "blake2 0.9.2", - "bytecodec", "clap 3.2.6", "digest 0.9.0", "futures 0.3.21", "lmdb-zero", "log", - "patricia_tree", "prost", "prost-types", "rand 0.8.5", @@ -6995,6 +7350,7 @@ dependencies = [ "tari_core", "tari_crypto", "tari_dan_common_types", + "tari_dan_engine", "tari_mmr", "tari_p2p", "tari_service_framework", @@ -7008,19 +7364,37 @@ dependencies = [ "tonic", ] +[[package]] +name = "tari_dan_engine" +version = "0.1.0" +dependencies = [ + "anyhow", + "d3ne", + "digest 0.9.0", + "log", + "serde", + "serde_json", + "tari_common_types", + "tari_crypto", + "tari_dan_common_types", + "tari_mmr", + "tari_utilities", + "thiserror", + "wasmer", +] + [[package]] name = "tari_dan_storage_sqlite" version = "0.1.0" dependencies = [ "async-trait", - "bytecodec", "diesel", "diesel_migrations", "log", - "patricia_tree", "tari_common", "tari_common_types", "tari_dan_core", + "tari_dan_engine", "tari_utilities", "thiserror", "tokio 1.17.0", @@ -7391,6 +7765,7 @@ dependencies = [ "tari_crypto", "tari_dan_common_types", "tari_dan_core", + "tari_dan_engine", "tari_dan_storage_sqlite", "tari_mmr", "tari_p2p", @@ -8655,6 +9030,273 @@ dependencies = [ "quote", ] +[[package]] +name = "wasm-encoder" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f0c17267a5ffd6ae3d897589460e21db1673c84fb7016b909c9691369a75ea" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasmer" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea8d8361c9d006ea3d7797de7bd6b1492ffd0f91a22430cfda6c1658ad57bedf" +dependencies = [ + "cfg-if 1.0.0", + "indexmap", + "js-sys", + "loupe", + "more-asserts", + "target-lexicon", + "thiserror", + "wasm-bindgen", + "wasmer-artifact", + "wasmer-compiler", + "wasmer-compiler-cranelift", + "wasmer-derive", + "wasmer-engine", + "wasmer-engine-dylib", + "wasmer-engine-universal", + "wasmer-types", + "wasmer-vm", + "wat", + "winapi 0.3.9", +] + +[[package]] +name = "wasmer-artifact" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aaf9428c29c1d8ad2ac0e45889ba8a568a835e33fd058964e5e500f2f7ce325" +dependencies = [ + "enumset", + "loupe", + "thiserror", + "wasmer-compiler", + "wasmer-types", +] + +[[package]] +name = "wasmer-compiler" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67a6cd866aed456656db2cfea96c18baabbd33f676578482b85c51e1ee19d2c" +dependencies = [ + "enumset", + "loupe", + "rkyv", + "serde", + "serde_bytes", + "smallvec", + "target-lexicon", + "thiserror", + "wasmer-types", + "wasmparser", +] + +[[package]] +name = "wasmer-compiler-cranelift" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48be2f9f6495f08649e4f8b946a2cbbe119faf5a654aa1457f9504a99d23dae0" +dependencies = [ + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "gimli", + "loupe", + "more-asserts", + "rayon", + "smallvec", + "target-lexicon", + "tracing", + "wasmer-compiler", + "wasmer-types", +] + +[[package]] +name = "wasmer-derive" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00e50405cc2a2f74ff574584710a5f2c1d5c93744acce2ca0866084739284b51" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "wasmer-engine" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f98f010978c244db431b392aeab0661df7ea0822343334f8f2a920763548e45" +dependencies = [ + "backtrace", + "enumset", + "lazy_static", + "loupe", + "memmap2", + "more-asserts", + "rustc-demangle", + "serde", + "serde_bytes", + "target-lexicon", + "thiserror", + "wasmer-artifact", + "wasmer-compiler", + "wasmer-types", + "wasmer-vm", +] + +[[package]] +name = "wasmer-engine-dylib" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0358af9c154724587731175553805648d9acb8f6657880d165e378672b7e53" +dependencies = [ + "cfg-if 1.0.0", + "enum-iterator", + "enumset", + "leb128", + "libloading", + "loupe", + "object", + "rkyv", + "serde", + "tempfile", + "tracing", + "wasmer-artifact", + "wasmer-compiler", + "wasmer-engine", + "wasmer-object", + "wasmer-types", + "wasmer-vm", + "which", +] + +[[package]] +name = "wasmer-engine-universal" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "440dc3d93c9ca47865a4f4edd037ea81bf983b5796b59b3d712d844b32dbef15" +dependencies = [ + "cfg-if 1.0.0", + "enumset", + "leb128", + "loupe", + "region", + "rkyv", + "wasmer-compiler", + "wasmer-engine", + "wasmer-engine-universal-artifact", + "wasmer-types", + "wasmer-vm", + "winapi 0.3.9", +] + +[[package]] +name = "wasmer-engine-universal-artifact" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f1db3f54152657eb6e86c44b66525ff7801dad8328fe677da48dd06af9ad41" +dependencies = [ + "enum-iterator", + "enumset", + "loupe", + "rkyv", + "thiserror", + "wasmer-artifact", + "wasmer-compiler", + "wasmer-types", +] + +[[package]] +name = "wasmer-object" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d831335ff3a44ecf451303f6f891175c642488036b92ceceb24ac8623a8fa8b" +dependencies = [ + "object", + "thiserror", + "wasmer-compiler", + "wasmer-types", +] + +[[package]] +name = "wasmer-types" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39df01ea05dc0a9bab67e054c7cb01521e53b35a7bb90bd02eca564ed0b2667f" +dependencies = [ + "backtrace", + "enum-iterator", + "indexmap", + "loupe", + "more-asserts", + "rkyv", + "serde", + "thiserror", +] + +[[package]] +name = "wasmer-vm" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d965fa61f4dc4cdb35a54daaf7ecec3563fbb94154a6c35433f879466247dd" +dependencies = [ + "backtrace", + "cc", + "cfg-if 1.0.0", + "corosensei", + "enum-iterator", + "indexmap", + "lazy_static", + "libc", + "loupe", + "mach", + "memoffset", + "more-asserts", + "region", + "rkyv", + "scopeguard", + "serde", + "thiserror", + "wasmer-artifact", + "wasmer-types", + "winapi 0.3.9", +] + +[[package]] +name = "wasmparser" +version = "0.83.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a" + +[[package]] +name = "wast" +version = "42.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "badcb03f976f983ff0daf294da9697be659442f61e6b0942bb37a2b6cbfe9dd4" +dependencies = [ + "leb128", + "memchr", + "unicode-width", + "wasm-encoder", +] + +[[package]] +name = "wat" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b92f20b742ac527066c8414bc0637352661b68cab07ef42586cefaba71c965cf" +dependencies = [ + "wast", +] + [[package]] name = "web-sys" version = "0.3.56" @@ -8911,6 +9553,19 @@ dependencies = [ "windows_x86_64_msvc 0.32.0", ] +[[package]] +name = "windows-sys" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43dbb096663629518eb1dfa72d80243ca5a6aca764cae62a2df70af760a9be75" +dependencies = [ + "windows_aarch64_msvc 0.33.0", + "windows_i686_gnu 0.33.0", + "windows_i686_msvc 0.33.0", + "windows_x86_64_gnu 0.33.0", + "windows_x86_64_msvc 0.33.0", +] + [[package]] name = "windows_aarch64_msvc" version = "0.30.0" diff --git a/applications/tari_validator_node/Cargo.toml b/applications/tari_validator_node/Cargo.toml index b235d72bc1..daf582e97a 100644 --- a/applications/tari_validator_node/Cargo.toml +++ b/applications/tari_validator_node/Cargo.toml @@ -25,6 +25,7 @@ tari_dan_core = { path = "../../dan_layer/core" } tari_dan_storage_sqlite = { path = "../../dan_layer/storage_sqlite" } tari_dan_common_types = { path = "../../dan_layer/common_types" } tari_common_types = { path = "../../base_layer/common_types" } +tari_dan_engine = { path = "../../dan_layer/engine"} anyhow = "1.0.53" async-trait = "0.1.50" diff --git a/applications/tari_validator_node/src/contract_worker_manager.rs b/applications/tari_validator_node/src/contract_worker_manager.rs index 7dcedab425..124d37e13f 100644 --- a/applications/tari_validator_node/src/contract_worker_manager.rs +++ b/applications/tari_validator_node/src/contract_worker_manager.rs @@ -294,6 +294,9 @@ impl ContractWorkerManager { checkpoint_unique_id: vec![], initial_state: Default::default(), template_parameters: vec![], + wasm_modules: vec![], + wasm_functions: vec![], + flow_functions: vec![], }, node_identity, mempool, diff --git a/applications/tari_validator_node/src/grpc/services/wallet_client.rs b/applications/tari_validator_node/src/grpc/services/wallet_client.rs index dac42263bb..a1363a5123 100644 --- a/applications/tari_validator_node/src/grpc/services/wallet_client.rs +++ b/applications/tari_validator_node/src/grpc/services/wallet_client.rs @@ -33,7 +33,8 @@ use tari_app_grpc::{ }; use tari_common_types::types::{FixedHash, PublicKey, Signature}; use tari_crypto::tari_utilities::ByteArray; -use tari_dan_core::{models::StateRoot, services::WalletClient, DigitalAssetError}; +use tari_dan_core::{services::WalletClient, DigitalAssetError}; +use tari_dan_engine::state::models::StateRoot; type Inner = grpc::wallet_client::WalletClient; diff --git a/applications/tari_validator_node/src/grpc/validator_node_grpc_server.rs b/applications/tari_validator_node/src/grpc/validator_node_grpc_server.rs index bf4c9eb7dc..8db5bd6e46 100644 --- a/applications/tari_validator_node/src/grpc/validator_node_grpc_server.rs +++ b/applications/tari_validator_node/src/grpc/validator_node_grpc_server.rs @@ -30,10 +30,10 @@ use tari_common_types::types::{FixedHash, PublicKey, Signature}; use tari_comms::NodeIdentity; use tari_crypto::tari_utilities::ByteArray; use tari_dan_core::{ - models::Instruction, services::{AssetProcessor, AssetProxy, ServiceSpecification, WalletClient}, storage::DbFactory, }; +use tari_dan_engine::instructions::Instruction; use tokio::{task, time}; use tonic::{Request, Response, Status}; diff --git a/applications/tari_validator_node/src/p2p/proto/conversions.rs b/applications/tari_validator_node/src/p2p/proto/conversions.rs index ec4b3f29db..cd54cdc858 100644 --- a/applications/tari_validator_node/src/p2p/proto/conversions.rs +++ b/applications/tari_validator_node/src/p2p/proto/conversions.rs @@ -24,27 +24,27 @@ use std::convert::{TryFrom, TryInto}; use tari_common_types::types::PublicKey; use tari_crypto::tari_utilities::ByteArray; -use tari_dan_core::{ - models::{ - CheckpointData, - HotStuffMessage, - HotStuffMessageType, - HotStuffTreeNode, - Instruction, - InstructionSet, - KeyValue, - Node, - QuorumCertificate, - SideChainBlock, - Signature, - StateOpLogEntry, - StateRoot, - TariDanPayload, - TemplateId, - TreeNodeHash, - ViewId, +use tari_dan_common_types::TemplateId; +use tari_dan_core::models::{ + CheckpointData, + HotStuffMessage, + HotStuffMessageType, + HotStuffTreeNode, + InstructionSet, + Node, + QuorumCertificate, + SideChainBlock, + Signature, + TariDanPayload, + TreeNodeHash, + ViewId, +}; +use tari_dan_engine::{ + instructions::Instruction, + state::{ + models::{KeyValue, StateOpLogEntry, StateRoot}, + DbStateOpLogEntry, }, - storage::state::DbStateOpLogEntry, }; use crate::p2p::proto; @@ -218,7 +218,7 @@ impl TryFrom for Instruction { type Error = String; fn try_from(value: proto::common::Instruction) -> Result { - let template_id = TemplateId::try_from(value.template_id).map_err(|err| err.to_string())?; + let template_id = TemplateId::try_from(value.template_id)?; Ok(Self::new( template_id, value.method, diff --git a/applications/tari_validator_node/src/p2p/rpc/service_impl.rs b/applications/tari_validator_node/src/p2p/rpc/service_impl.rs index 681a77f371..4eb0561fad 100644 --- a/applications/tari_validator_node/src/p2p/rpc/service_impl.rs +++ b/applications/tari_validator_node/src/p2p/rpc/service_impl.rs @@ -28,16 +28,18 @@ use tari_comms::{ utils, }; use tari_dan_core::{ - models::{Instruction, TreeNodeHash}, + models::TreeNodeHash, services::{AssetProcessor, MempoolService}, - storage::{state::StateDbUnitOfWorkReader, DbFactory}, + storage::DbFactory, }; +use tari_dan_engine::state::StateDbUnitOfWorkReader; use tokio::{sync::mpsc, task}; const LOG_TARGET: &str = "vn::p2p::rpc"; use tari_common_types::types::PublicKey; use tari_crypto::tari_utilities::ByteArray; +use tari_dan_engine::instructions::Instruction; use crate::p2p::{proto::validator_node as proto, rpc::ValidatorNodeRpcService}; diff --git a/applications/tari_validator_node/src/p2p/services/rpc_client.rs b/applications/tari_validator_node/src/p2p/services/rpc_client.rs index 4e1a0121dd..ca99d05873 100644 --- a/applications/tari_validator_node/src/p2p/services/rpc_client.rs +++ b/applications/tari_validator_node/src/p2p/services/rpc_client.rs @@ -28,10 +28,12 @@ use tari_common_types::types::{FixedHash, PublicKey}; use tari_comms::PeerConnection; use tari_comms_dht::DhtRequester; use tari_crypto::tari_utilities::ByteArray; +use tari_dan_common_types::TemplateId; use tari_dan_core::{ - models::{Node, SchemaState, SideChainBlock, StateOpLogEntry, TemplateId, TreeNodeHash}, + models::{Node, SideChainBlock, TreeNodeHash}, services::{ValidatorNodeClientError, ValidatorNodeClientFactory, ValidatorNodeRpcClient}, }; +use tari_dan_engine::state::models::{SchemaState, StateOpLogEntry}; use tokio_stream::StreamExt; use crate::p2p::{proto::validator_node as proto, rpc}; diff --git a/dan_layer/common_types/src/lib.rs b/dan_layer/common_types/src/lib.rs index ff76c528c5..7772dd98c9 100644 --- a/dan_layer/common_types/src/lib.rs +++ b/dan_layer/common_types/src/lib.rs @@ -2,3 +2,7 @@ // SPDX-License-Identifier: BSD-3-Clause pub mod proto; +pub mod storage; + +mod template_id; +pub use template_id::TemplateId; diff --git a/dan_layer/common_types/src/storage/mod.rs b/dan_layer/common_types/src/storage/mod.rs new file mode 100644 index 0000000000..4d542cd250 --- /dev/null +++ b/dan_layer/common_types/src/storage/mod.rs @@ -0,0 +1,6 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +mod unit_of_work_tracker; + +pub use unit_of_work_tracker::UnitOfWorkTracker; diff --git a/dan_layer/common_types/src/storage/unit_of_work_tracker.rs b/dan_layer/common_types/src/storage/unit_of_work_tracker.rs new file mode 100644 index 0000000000..acdd3238db --- /dev/null +++ b/dan_layer/common_types/src/storage/unit_of_work_tracker.rs @@ -0,0 +1,47 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + RwLock, + RwLockReadGuard, + RwLockWriteGuard, +}; + +#[derive(Debug)] +pub struct UnitOfWorkTracker { + item: Arc>, + is_dirty: Arc, +} + +impl Clone for UnitOfWorkTracker { + fn clone(&self) -> Self { + Self { + item: self.item.clone(), + is_dirty: self.is_dirty.clone(), + } + } +} + +impl UnitOfWorkTracker { + pub fn new(item: TItem, is_dirty: bool) -> Self { + Self { + item: Arc::new(RwLock::new(item)), + is_dirty: Arc::new(AtomicBool::new(is_dirty)), + } + } + + pub fn get(&self) -> RwLockReadGuard { + self.item.read().unwrap() + } + + pub fn get_mut(&self) -> RwLockWriteGuard { + self.is_dirty.store(true, Ordering::SeqCst); + self.item.write().unwrap() + } + + pub fn is_dirty(&self) -> bool { + self.is_dirty.load(Ordering::SeqCst) + } +} diff --git a/dan_layer/common_types/src/template_id.rs b/dan_layer/common_types/src/template_id.rs new file mode 100644 index 0000000000..8c2aedab86 --- /dev/null +++ b/dan_layer/common_types/src/template_id.rs @@ -0,0 +1,70 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use std::{ + convert::TryFrom, + fmt::{Display, Formatter}, + str::FromStr, +}; + +#[derive(Copy, Clone, Debug)] +pub enum TemplateId { + Tip002 = 2, + Tip003 = 3, + Tip004 = 4, + Tip721 = 721, + EditableMetadata = 20, +} + +impl FromStr for TemplateId { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "Tip002" => Ok(TemplateId::Tip002), + "Tip003" => Ok(TemplateId::Tip003), + "Tip004" => Ok(TemplateId::Tip004), + "Tip721" => Ok(TemplateId::Tip721), + "EditableMetadata" => Ok(TemplateId::EditableMetadata), + _ => { + println!("Unrecognised template"); + Err(format!("Unrecognised template ID '{}'", s)) + }, + } + } +} + +impl TryFrom for TemplateId { + type Error = String; + + fn try_from(value: u32) -> Result { + match value { + 2 => Ok(TemplateId::Tip002), + 3 => Ok(TemplateId::Tip003), + 4 => Ok(TemplateId::Tip004), + 721 => Ok(TemplateId::Tip721), + _ => Err(format!("Unknown value: {}", value)), + } + } +} + +impl TryFrom for TemplateId { + type Error = String; + + fn try_from(value: i32) -> Result { + u32::try_from(value) + .map_err(|_| { + format!( + "Could not convert to TemplateId because it was not a valid u32:{}", + value + ) + })? + .try_into() + } +} + +impl Display for TemplateId { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self) + } +} diff --git a/dan_layer/core/Cargo.toml b/dan_layer/core/Cargo.toml index 83d4b45dc2..22731d3ab0 100644 --- a/dan_layer/core/Cargo.toml +++ b/dan_layer/core/Cargo.toml @@ -21,6 +21,7 @@ tari_core = {path = "../../base_layer/core"} tari_dan_common_types = {path = "../common_types"} tari_common_types = {path = "../../base_layer/common_types"} tari_utilities = { git = "https://github.com/tari-project/tari_utilities.git", tag = "v0.4.4" } +tari_dan_engine = { path = "../engine"} anyhow = "1.0.53" async-trait = "0.1.50" @@ -39,9 +40,6 @@ tokio = { version="1.10", features = ["macros", "time"]} tokio-stream = { version = "0.1.7", features = ["sync"] } tonic = "0.6.2" -# saving of patricia tree -patricia_tree = { version = "0.3.0", features = ["binary-format"] } -bytecodec = { version = "0.4.14", features = ["bincode_codec"] } serde_json = "1.0.64" [dev-dependencies] diff --git a/dan_layer/core/src/digital_assets_error.rs b/dan_layer/core/src/digital_assets_error.rs index 5afe2b8ab2..bdd9bb435d 100644 --- a/dan_layer/core/src/digital_assets_error.rs +++ b/dan_layer/core/src/digital_assets_error.rs @@ -23,6 +23,7 @@ use prost::DecodeError; use tari_comms_dht::outbound::DhtOutboundError; use tari_crypto::ristretto::RistrettoPublicKey; +use tari_dan_engine::state::error::StateStorageError; use thiserror::Error; use tokio::sync::mpsc::error::SendError; @@ -105,6 +106,8 @@ pub enum DigitalAssetError { SendError(#[from] Box)>>), #[error("Invalid committee public key hex")] InvalidCommitteePublicKeyHex, + #[error("State storage error:{0}")] + StateStorageError(#[from] StateStorageError), } impl From for DigitalAssetError { diff --git a/dan_layer/core/src/models/asset_definition.rs b/dan_layer/core/src/models/asset_definition.rs index 97d89bc414..990668b6cd 100644 --- a/dan_layer/core/src/models/asset_definition.rs +++ b/dan_layer/core/src/models/asset_definition.rs @@ -23,6 +23,11 @@ use serde::{self, Deserialize, Serialize}; use tari_common_types::types::FixedHash; use tari_core::transactions::transaction_components::TemplateParameter; +use tari_dan_engine::{ + function_definitions::{FlowFunctionDefinition, WasmFunctionDefinition}, + state::models::SchemaState, + wasm::WasmModuleDefinition, +}; use crate::helpers::deserialize_from_hex; @@ -40,6 +45,9 @@ pub struct AssetDefinition { pub checkpoint_unique_id: Vec, pub initial_state: InitialState, pub template_parameters: Vec, + pub wasm_modules: Vec, + pub wasm_functions: Vec, + pub flow_functions: Vec, } impl Default for AssetDefinition { @@ -52,6 +60,9 @@ impl Default for AssetDefinition { phase_timeout: 30, initial_state: Default::default(), template_parameters: vec![], + wasm_modules: vec![], + wasm_functions: vec![], + flow_functions: vec![], } } } @@ -66,26 +77,3 @@ impl AssetDefinition { pub struct InitialState { pub schemas: Vec, } - -#[derive(Serialize, Deserialize, Default, Clone, Debug)] -pub struct SchemaState { - pub name: String, - pub items: Vec, -} - -impl SchemaState { - pub fn new(name: String, items: Vec) -> Self { - Self { name, items } - } - - pub fn push_key_value(&mut self, key_value: KeyValue) -> &mut Self { - self.items.push(key_value); - self - } -} - -#[derive(Serialize, Deserialize, Default, Clone, Debug)] -pub struct KeyValue { - pub key: Vec, - pub value: Vec, -} diff --git a/dan_layer/core/src/models/hot_stuff_tree_node.rs b/dan_layer/core/src/models/hot_stuff_tree_node.rs index 9478168c22..aec285709f 100644 --- a/dan_layer/core/src/models/hot_stuff_tree_node.rs +++ b/dan_layer/core/src/models/hot_stuff_tree_node.rs @@ -22,8 +22,9 @@ use digest::{Digest, FixedOutput}; use tari_crypto::common::Blake256; +use tari_dan_engine::state::models::StateRoot; -use crate::models::{Payload, StateRoot, TreeNodeHash}; +use crate::models::{Payload, TreeNodeHash}; #[derive(Debug, Clone)] pub struct HotStuffTreeNode { diff --git a/dan_layer/core/src/models/instruction_set.rs b/dan_layer/core/src/models/instruction_set.rs index b082b0dbaf..595943f61b 100644 --- a/dan_layer/core/src/models/instruction_set.rs +++ b/dan_layer/core/src/models/instruction_set.rs @@ -24,9 +24,10 @@ use std::{convert::TryFrom, hash::Hash, iter::FromIterator}; use tari_common_types::types::FixedHash; use tari_crypto::common::Blake256; +use tari_dan_engine::instructions::Instruction; use tari_mmr::MerkleMountainRange; -use crate::models::{ConsensusHash, Instruction}; +use crate::models::ConsensusHash; #[derive(PartialEq, Eq, Clone, Debug, Hash)] pub struct InstructionSetHash(FixedHash); diff --git a/dan_layer/core/src/models/mod.rs b/dan_layer/core/src/models/mod.rs index 2349e3c465..a39acc8c2f 100644 --- a/dan_layer/core/src/models/mod.rs +++ b/dan_layer/core/src/models/mod.rs @@ -20,12 +20,7 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use std::{ - convert::{TryFrom, TryInto}, - fmt::{Debug, Display, Formatter}, - hash::Hash, - str::FromStr, -}; +use std::{convert::TryFrom, fmt::Debug, hash::Hash}; mod asset_definition; mod base_layer_metadata; @@ -35,36 +30,30 @@ pub mod domain_events; mod error; mod hot_stuff_message; mod hot_stuff_tree_node; -mod instruction; mod instruction_set; mod node; -mod op_log; mod payload; mod quorum_certificate; mod sidechain_block; mod sidechain_metadata; -mod state_root; mod tari_dan_payload; mod tree_node_hash; mod view; mod view_id; -pub use asset_definition::{AssetDefinition, InitialState, KeyValue, SchemaState}; +pub use asset_definition::{AssetDefinition, InitialState}; pub use base_layer_metadata::BaseLayerMetadata; pub use base_layer_output::{BaseLayerOutput, CheckpointOutput, CommitteeOutput}; pub use committee::Committee; pub use error::ModelError; pub use hot_stuff_message::HotStuffMessage; pub use hot_stuff_tree_node::HotStuffTreeNode; -pub use instruction::Instruction; pub use instruction_set::InstructionSet; pub use node::Node; -pub use op_log::{StateOpLogEntry, StateOperation}; pub use payload::Payload; pub use quorum_certificate::QuorumCertificate; pub use sidechain_block::SideChainBlock; pub use sidechain_metadata::SidechainMetadata; -pub use state_root::StateRoot; pub use tari_dan_payload::{CheckpointData, TariDanPayload}; pub use tree_node_hash::TreeNodeHash; pub use view::View; @@ -81,69 +70,6 @@ impl InstructionCaller { } } -#[derive(Copy, Clone, Debug)] -pub enum TemplateId { - Tip002 = 2, - Tip003 = 3, - Tip004 = 4, - Tip721 = 721, - EditableMetadata = 20, -} - -impl FromStr for TemplateId { - type Err = ModelError; - - fn from_str(s: &str) -> Result { - match s { - "Tip002" => Ok(TemplateId::Tip002), - "Tip003" => Ok(TemplateId::Tip003), - "Tip004" => Ok(TemplateId::Tip004), - "Tip721" => Ok(TemplateId::Tip721), - "EditableMetadata" => Ok(TemplateId::EditableMetadata), - _ => { - println!("Unrecognised template"); - Err(ModelError::StringParseError { - details: format!("Unrecognised template ID '{}'", s), - }) - }, - } - } -} - -impl TryFrom for TemplateId { - type Error = ModelError; - - fn try_from(value: u32) -> Result { - match value { - 2 => Ok(TemplateId::Tip002), - 3 => Ok(TemplateId::Tip003), - 4 => Ok(TemplateId::Tip004), - 721 => Ok(TemplateId::Tip721), - _ => Err(ModelError::InvalidTemplateIdNumber { - value: i64::from(value), - }), - } - } -} - -impl TryFrom for TemplateId { - type Error = ModelError; - - fn try_from(value: i32) -> Result { - u32::try_from(value) - .map_err(|_| ModelError::InvalidTemplateIdNumber { - value: i64::from(value), - })? - .try_into() - } -} - -impl Display for TemplateId { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self) - } -} - #[derive(Clone, Debug, Hash)] pub struct TokenId(pub Vec); diff --git a/dan_layer/core/src/models/op_log.rs b/dan_layer/core/src/models/op_log.rs deleted file mode 100644 index be3b2e9e97..0000000000 --- a/dan_layer/core/src/models/op_log.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2022, The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -use crate::storage::state::{DbStateOpLogEntry, DbStateOperation}; - -#[derive(Debug)] -pub struct StateOpLogEntry { - inner: DbStateOpLogEntry, -} - -impl StateOpLogEntry { - pub fn operation(&self) -> StateOperation { - self.inner.operation.into() - } - - pub fn into_inner(self) -> DbStateOpLogEntry { - self.inner - } -} - -impl From for StateOpLogEntry { - fn from(inner: DbStateOpLogEntry) -> Self { - Self { inner } - } -} - -#[derive(Debug, Clone, Copy)] -pub enum StateOperation { - Set, - Delete, -} - -impl StateOperation { - pub fn as_op_str(&self) -> &str { - use StateOperation::{Delete, Set}; - match self { - Set => "S", - Delete => "D", - } - } -} - -impl From for StateOperation { - fn from(op: DbStateOperation) -> Self { - match op { - DbStateOperation::Set => StateOperation::Set, - DbStateOperation::Delete => StateOperation::Delete, - } - } -} diff --git a/dan_layer/core/src/models/state_root.rs b/dan_layer/core/src/models/state_root.rs deleted file mode 100644 index 75b539e663..0000000000 --- a/dan_layer/core/src/models/state_root.rs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2021. The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -use tari_common_types::types::FixedHash; - -#[derive(PartialEq, Eq, Debug, Clone)] -pub struct StateRoot { - root: FixedHash, -} - -impl StateRoot { - pub fn new(root: FixedHash) -> Self { - Self { root } - } - - pub fn as_bytes(&self) -> &[u8] { - self.root.as_slice() - } - - pub fn initial() -> Self { - Self { - root: FixedHash::zero(), - } - } -} diff --git a/dan_layer/core/src/models/tari_dan_payload.rs b/dan_layer/core/src/models/tari_dan_payload.rs index 427b19a064..0693f2b3f5 100644 --- a/dan_layer/core/src/models/tari_dan_payload.rs +++ b/dan_layer/core/src/models/tari_dan_payload.rs @@ -25,8 +25,9 @@ use std::fmt::Debug; use digest::Digest; use tari_common_types::types::FixedHash; use tari_crypto::common::Blake256; +use tari_dan_engine::instructions::Instruction; -use crate::models::{ConsensusHash, Instruction, InstructionSet, Payload}; +use crate::models::{ConsensusHash, InstructionSet, Payload}; #[derive(Debug, Clone)] pub struct TariDanPayload { diff --git a/dan_layer/core/src/services/asset_processor.rs b/dan_layer/core/src/services/asset_processor.rs index 2d4287098f..918c7e28a1 100644 --- a/dan_layer/core/src/services/asset_processor.rs +++ b/dan_layer/core/src/services/asset_processor.rs @@ -23,11 +23,16 @@ use std::convert::TryInto; use tari_core::transactions::transaction_components::TemplateParameter; +use tari_dan_engine::{ + flow::FlowFactory, + instructions::Instruction, + state::{StateDbUnitOfWork, StateDbUnitOfWorkReader}, + wasm::WasmModuleFactory, +}; use crate::{ digital_assets_error::DigitalAssetError, - models::{Instruction, InstructionSet, TemplateId}, - storage::state::{StateDbUnitOfWork, StateDbUnitOfWorkReader}, + models::{AssetDefinition, InstructionSet}, template_command::ExecutionResult, templates::{tip002_template, tip004_template, tip721_template}, }; @@ -50,7 +55,23 @@ pub trait AssetProcessor: Sync + Send + 'static { #[derive(Default, Clone)] pub struct ConcreteAssetProcessor { + _asset_definition: AssetDefinition, template_factory: TemplateFactory, + _wasm_factory: WasmModuleFactory, + _function_interface: FunctionInterface, + _flow_factory: FlowFactory, +} + +impl ConcreteAssetProcessor { + pub fn new(asset_definition: AssetDefinition) -> Self { + Self { + _wasm_factory: WasmModuleFactory::new(&asset_definition.wasm_modules, &asset_definition.wasm_functions), + _flow_factory: FlowFactory::new(&asset_definition.flow_functions), + _asset_definition: asset_definition, + template_factory: Default::default(), + _function_interface: FunctionInterface {}, + } + } } impl AssetProcessor for ConcreteAssetProcessor { @@ -71,12 +92,39 @@ impl AssetProcessor for ConcreteAssetProcessor { } } +#[derive(Clone, Default)] +pub struct FunctionInterface {} + +// impl FunctionInterface { +// #[allow(dead_code)] +// fn find_executor(&self, instruction: &Instruction) -> Result { +// match instruction.template_id() { +// // TODO: Put these back +// // TemplateId::Tip6000 => Ok(InstructionExecutor::WasmModule { +// // name: instruction.method().to_string(), +// // }), +// // TemplateId::Tip7000 => Ok(InstructionExecutor::Flow { +// // name: instruction.method().to_string(), +// // }), +// _ => Ok(InstructionExecutor::Template { +// template_id: instruction.template_id(), +// }), +// } +// } +// } +// +// pub enum InstructionExecutor { +// WasmModule { name: String }, +// Template { template_id: TemplateId }, +// Flow { name: String }, +// } + #[derive(Default, Clone)] pub struct TemplateFactory {} impl TemplateFactory { pub fn initial_instructions(&self, template_param: &TemplateParameter) -> InstructionSet { - use TemplateId::{EditableMetadata, Tip002, Tip003, Tip004, Tip721}; + use tari_dan_common_types::TemplateId::{EditableMetadata, Tip002, Tip003, Tip004, Tip721}; // TODO: We may want to use the TemplateId type, so that we know it is known/valid let template_id = template_param.template_id.try_into().unwrap(); match template_id { @@ -95,7 +143,7 @@ impl TemplateFactory { instruction: &Instruction, state_db: &TUnitOfWork, ) -> Result>, DigitalAssetError> { - use TemplateId::{EditableMetadata, Tip002, Tip003, Tip004, Tip721}; + use tari_dan_common_types::TemplateId::{EditableMetadata, Tip002, Tip003, Tip004, Tip721}; match instruction.template_id() { Tip002 => tip002_template::invoke_read_method(instruction.method(), instruction.args(), state_db), Tip003 => todo!(), @@ -112,7 +160,7 @@ impl TemplateFactory { instruction: &Instruction, state_db: &mut TUnitOfWork, ) -> Result<(), DigitalAssetError> { - use TemplateId::{EditableMetadata, Tip002, Tip003, Tip004, Tip721}; + use tari_dan_common_types::TemplateId::{EditableMetadata, Tip002, Tip003, Tip004, Tip721}; match instruction.template_id() { Tip002 => tip002_template::invoke_write_method(instruction.method(), instruction.args(), state_db), Tip003 => todo!(), diff --git a/dan_layer/core/src/services/asset_proxy.rs b/dan_layer/core/src/services/asset_proxy.rs index 079affdf95..0c0babd1e1 100644 --- a/dan_layer/core/src/services/asset_proxy.rs +++ b/dan_layer/core/src/services/asset_proxy.rs @@ -25,11 +25,12 @@ use futures::stream::FuturesUnordered; use log::*; use tari_common_types::types::{FixedHash, PublicKey}; use tari_core::transactions::transaction_components::OutputType; +use tari_dan_common_types::TemplateId; +use tari_dan_engine::instructions::Instruction; use tari_utilities::hex::Hex; use tokio_stream::StreamExt; use crate::{ - models::{Instruction, TemplateId}, services::{ validator_node_rpc_client::ValidatorNodeRpcClient, BaseNodeClient, diff --git a/dan_layer/core/src/services/checkpoint_manager.rs b/dan_layer/core/src/services/checkpoint_manager.rs index a1ae232c8e..5987d370a0 100644 --- a/dan_layer/core/src/services/checkpoint_manager.rs +++ b/dan_layer/core/src/services/checkpoint_manager.rs @@ -22,12 +22,9 @@ use async_trait::async_trait; use log::*; +use tari_dan_engine::state::models::StateRoot; -use crate::{ - models::{AssetDefinition, StateRoot}, - services::wallet_client::WalletClient, - DigitalAssetError, -}; +use crate::{models::AssetDefinition, services::wallet_client::WalletClient, DigitalAssetError}; const LOG_TARGET: &str = "tari::dan::checkpoint_manager"; diff --git a/dan_layer/core/src/services/mempool_service.rs b/dan_layer/core/src/services/mempool_service.rs index 090f29a562..dfa1376d8f 100644 --- a/dan_layer/core/src/services/mempool_service.rs +++ b/dan_layer/core/src/services/mempool_service.rs @@ -24,12 +24,10 @@ use std::sync::Arc; use async_trait::async_trait; use tari_common_types::types::FixedHash; +use tari_dan_engine::instructions::Instruction; use tokio::sync::Mutex; -use crate::{ - digital_assets_error::DigitalAssetError, - models::{Instruction, TreeNodeHash}, -}; +use crate::{digital_assets_error::DigitalAssetError, models::TreeNodeHash}; #[async_trait] pub trait MempoolService: Sync + Send + 'static { diff --git a/dan_layer/core/src/services/mocks/mod.rs b/dan_layer/core/src/services/mocks/mod.rs index fbed3ea1c4..5597e575c7 100644 --- a/dan_layer/core/src/services/mocks/mod.rs +++ b/dan_layer/core/src/services/mocks/mod.rs @@ -30,6 +30,17 @@ use async_trait::async_trait; use tari_common_types::types::{FixedHash, PublicKey}; use tari_core::{chain_storage::UtxoMinedInfo, transactions::transaction_components::OutputType}; use tari_crypto::ristretto::RistrettoPublicKey; +use tari_dan_common_types::TemplateId; +#[cfg(test)] +use tari_dan_engine::state::mocks::state_db::MockStateDbBackupAdapter; +use tari_dan_engine::{ + instructions::Instruction, + state::{ + models::{SchemaState, StateOpLogEntry, StateRoot}, + StateDbUnitOfWork, + StateDbUnitOfWorkReader, + }, +}; use crate::{ digital_assets_error::DigitalAssetError, @@ -40,18 +51,13 @@ use crate::{ Committee, Event, HotStuffTreeNode, - Instruction, InstructionSet, Node, Payload, - SchemaState, SideChainBlock, SidechainMetadata, Signature, - StateOpLogEntry, - StateRoot, TariDanPayload, - TemplateId, TreeNodeHash, }, services::{ @@ -70,19 +76,14 @@ use crate::{ ValidatorNodeRpcClient, WalletClient, }, - storage::{ - chain::ChainDbUnitOfWork, - state::{StateDbUnitOfWork, StateDbUnitOfWorkReader}, - ChainStorageService, - StorageError, - }, + storage::{chain::ChainDbUnitOfWork, ChainStorageService, StorageError}, }; #[cfg(test)] use crate::{ models::domain_events::ConsensusWorkerDomainEvent, services::infrastructure_services::mocks::{MockInboundConnectionService, MockOutboundService}, services::{ConcreteAssetProxy, ServiceSpecification}, - storage::mocks::{chain_db::MockChainDbBackupAdapter, state_db::MockStateDbBackupAdapter, MockDbFactory}, + storage::mocks::{chain_db::MockChainDbBackupAdapter, MockDbFactory}, }; #[derive(Debug, Clone)] diff --git a/dan_layer/core/src/services/payload_processor.rs b/dan_layer/core/src/services/payload_processor.rs index 1c11d0a630..448d2ca2ba 100644 --- a/dan_layer/core/src/services/payload_processor.rs +++ b/dan_layer/core/src/services/payload_processor.rs @@ -21,12 +21,12 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use async_trait::async_trait; +use tari_dan_engine::state::{models::StateRoot, StateDbUnitOfWork}; use crate::{ digital_assets_error::DigitalAssetError, - models::{Payload, StateRoot, TariDanPayload}, + models::{Payload, TariDanPayload}, services::AssetProcessor, - storage::state::StateDbUnitOfWork, }; #[async_trait] diff --git a/dan_layer/core/src/services/service_specification.rs b/dan_layer/core/src/services/service_specification.rs index 04d8dad095..5c073ebbc8 100644 --- a/dan_layer/core/src/services/service_specification.rs +++ b/dan_layer/core/src/services/service_specification.rs @@ -20,6 +20,8 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +use tari_dan_engine::state::StateDbBackendAdapter; + use crate::{ models::{domain_events::ConsensusWorkerDomainEvent, Payload}, services::{ @@ -37,13 +39,7 @@ use crate::{ SigningService, ValidatorNodeClientFactory, }, - storage::{ - chain::ChainDbBackendAdapter, - global::GlobalDbBackendAdapter, - state::StateDbBackendAdapter, - ChainStorageService, - DbFactory, - }, + storage::{chain::ChainDbBackendAdapter, global::GlobalDbBackendAdapter, ChainStorageService, DbFactory}, }; /// A trait to describe a specific configuration of services. This type allows other services to diff --git a/dan_layer/core/src/services/validator_node_rpc_client.rs b/dan_layer/core/src/services/validator_node_rpc_client.rs index b5f88c39f2..5fbcd7360c 100644 --- a/dan_layer/core/src/services/validator_node_rpc_client.rs +++ b/dan_layer/core/src/services/validator_node_rpc_client.rs @@ -28,9 +28,11 @@ use tari_comms::{ types::CommsPublicKey, }; use tari_comms_dht::DhtActorError; +use tari_dan_common_types::TemplateId; +use tari_dan_engine::state::models::{SchemaState, StateOpLogEntry}; use crate::{ - models::{Node, SchemaState, SideChainBlock, StateOpLogEntry, TemplateId, TreeNodeHash}, + models::{Node, SideChainBlock, TreeNodeHash}, services::infrastructure_services::NodeAddressable, }; diff --git a/dan_layer/core/src/services/wallet_client.rs b/dan_layer/core/src/services/wallet_client.rs index f2aeb55915..ed10fbf275 100644 --- a/dan_layer/core/src/services/wallet_client.rs +++ b/dan_layer/core/src/services/wallet_client.rs @@ -22,8 +22,9 @@ use async_trait::async_trait; use tari_common_types::types::{FixedHash, PublicKey, Signature}; +use tari_dan_engine::state::models::StateRoot; -use crate::{models::StateRoot, DigitalAssetError}; +use crate::DigitalAssetError; #[async_trait] pub trait WalletClient: Send + Sync { diff --git a/dan_layer/core/src/storage/chain/chain_db_unit_of_work.rs b/dan_layer/core/src/storage/chain/chain_db_unit_of_work.rs index 78b28c3666..81deb6e1dc 100644 --- a/dan_layer/core/src/storage/chain/chain_db_unit_of_work.rs +++ b/dan_layer/core/src/storage/chain/chain_db_unit_of_work.rs @@ -27,12 +27,13 @@ use std::{ }; use log::*; +use tari_dan_common_types::storage::UnitOfWorkTracker; +use tari_dan_engine::instructions::Instruction; use crate::{ - models::{Instruction, Node, QuorumCertificate, TreeNodeHash}, + models::{Node, QuorumCertificate, TreeNodeHash}, storage::{ chain::{db_node::DbNode, ChainDbBackendAdapter, DbInstruction, DbQc}, - unit_of_work_tracker::UnitOfWorkTracker, StorageError, }, }; diff --git a/dan_layer/core/src/storage/chain/db_instruction.rs b/dan_layer/core/src/storage/chain/db_instruction.rs index 2cad7357d8..d8756cb2e2 100644 --- a/dan_layer/core/src/storage/chain/db_instruction.rs +++ b/dan_layer/core/src/storage/chain/db_instruction.rs @@ -20,7 +20,9 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use crate::models::{Instruction, TreeNodeHash}; +use tari_dan_engine::instructions::Instruction; + +use crate::models::TreeNodeHash; #[derive(Debug, Clone)] pub struct DbInstruction { diff --git a/dan_layer/core/src/storage/db_factory.rs b/dan_layer/core/src/storage/db_factory.rs index c4458e18dc..543ae4c892 100644 --- a/dan_layer/core/src/storage/db_factory.rs +++ b/dan_layer/core/src/storage/db_factory.rs @@ -21,11 +21,11 @@ // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use tari_common_types::types::FixedHash; +use tari_dan_engine::state::{StateDb, StateDbBackendAdapter}; use crate::storage::{ chain::{ChainDb, ChainDbBackendAdapter}, global::{GlobalDb, GlobalDbBackendAdapter}, - state::{StateDb, StateDbBackendAdapter}, StorageError, }; diff --git a/dan_layer/core/src/storage/error.rs b/dan_layer/core/src/storage/error.rs index 8fc2705705..8733a78a36 100644 --- a/dan_layer/core/src/storage/error.rs +++ b/dan_layer/core/src/storage/error.rs @@ -23,7 +23,6 @@ use std::{io, sync::PoisonError}; use lmdb_zero as lmdb; -use tari_mmr::error::MerkleMountainRangeError; use tari_storage::lmdb_store::LMDBError; #[derive(Debug, thiserror::Error)] @@ -36,8 +35,6 @@ pub enum StorageError { LmdbError(#[from] lmdb::Error), #[error("LMDB Error: {0}")] LMDBError(#[from] LMDBError), - #[error("Decode Error: {0}")] - DecodeError(#[from] bytecodec::Error), #[error("Query error:{reason}")] QueryError { reason: String }, #[error("Migration error: {reason}")] @@ -48,8 +45,7 @@ pub enum StorageError { NotFound, #[error("File system path does not exist")] FileSystemPathDoesNotExist, - #[error("Merkle error:{0}")] - MerkleMountainRangeError(#[from] MerkleMountainRangeError), + #[error("General storage error: {details}")] General { details: String }, #[error("Lock error")] diff --git a/dan_layer/core/src/storage/lmdb/asset_db.rs b/dan_layer/core/src/storage/lmdb/asset_db.rs deleted file mode 100644 index d7b79bfe50..0000000000 --- a/dan_layer/core/src/storage/lmdb/asset_db.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2021. The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -/// A database for each asset (per network) -pub struct AssetDb {} diff --git a/dan_layer/core/src/storage/lmdb/helpers.rs b/dan_layer/core/src/storage/lmdb/helpers.rs deleted file mode 100644 index 940425470a..0000000000 --- a/dan_layer/core/src/storage/lmdb/helpers.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2021, The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -use std::path::Path; - -use lmdb_zero::db; -use tari_storage::lmdb_store::{LMDBBuilder, LMDBConfig, LMDBStore}; - -use crate::storage::StorageError; - -const DATABASES: &[(&str, db::Flags)] = &[("metadata", db::INTEGERKEY)]; - -pub fn create_lmdb_store>(path: P, config: LMDBConfig) -> Result { - const CREATE_FLAG: db::Flags = db::CREATE; - - let mut lmdb_store = LMDBBuilder::new() - .set_path(path) - .set_env_config(config) - .set_max_number_of_databases(10); - - for (db_name, flags) in DATABASES { - lmdb_store = lmdb_store.add_database(db_name, CREATE_FLAG | *flags); - } - - let lmdb_store = lmdb_store.build()?; - Ok(lmdb_store) -} diff --git a/dan_layer/core/src/storage/lmdb/lmdb_asset_backend.rs b/dan_layer/core/src/storage/lmdb/lmdb_asset_backend.rs deleted file mode 100644 index 8e1eb3282f..0000000000 --- a/dan_layer/core/src/storage/lmdb/lmdb_asset_backend.rs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2021. The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -use std::{fs, fs::File, path::Path, sync::Arc}; - -use lmdb_zero as lmdb; -use lmdb_zero::{put, ConstAccessor, LmdbResultExt, ReadTransaction, WriteAccessor, WriteTransaction}; -use tari_common::file_lock; -use tari_storage::lmdb_store::{DatabaseRef, LMDBConfig}; - -use crate::storage::{lmdb::helpers::create_lmdb_store, StorageError}; - -#[derive(Clone)] -pub struct LmdbAssetBackend { - _file_lock: Arc, - env: Arc, - metadata_db: DatabaseRef, -} - -impl LmdbAssetBackend { - pub(crate) fn initialize>(path: P, config: LMDBConfig) -> Result { - fs::create_dir_all(&path)?; - let file_lock = file_lock::try_lock_exclusive(path.as_ref())?; - let store = create_lmdb_store(path, config)?; - - Ok(Self { - _file_lock: Arc::new(file_lock), - env: store.env(), - metadata_db: store.get_handle("metadata").unwrap().db(), - }) - } - - pub fn read_transaction(&self) -> Result, StorageError> { - Ok(ReadTransaction::new(&*self.env)?) - } - - pub fn write_transaction(&self) -> Result, StorageError> { - Ok(WriteTransaction::new(&*self.env)?) - } - - pub fn get_metadata<'a>(&self, access: &'a ConstAccessor<'_>, key: u64) -> Result, StorageError> { - let val = access.get::<_, [u8]>(&*self.metadata_db, &key).to_opt()?; - Ok(val) - } - - pub fn replace_metadata( - &self, - access: &mut WriteAccessor<'_>, - key: u64, - metadata: &[u8], - ) -> Result<(), StorageError> { - access.put(&self.metadata_db, &key, metadata, put::Flags::empty())?; - Ok(()) - } -} diff --git a/dan_layer/core/src/storage/lmdb/lmdb_asset_store.rs b/dan_layer/core/src/storage/lmdb/lmdb_asset_store.rs deleted file mode 100644 index fab1bc9842..0000000000 --- a/dan_layer/core/src/storage/lmdb/lmdb_asset_store.rs +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2021. The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -use std::path::Path; - -use bytecodec::{ - bincode_codec::{BincodeDecoder, BincodeEncoder}, - DecodeExt, - EncodeExt, -}; -use lmdb_zero::ConstAccessor; -use patricia_tree::{ - node::{Node, NodeDecoder, NodeEncoder}, - PatriciaMap, -}; -use tari_storage::lmdb_store::LMDBConfig; - -use crate::{ - digital_assets_error::DigitalAssetError, - models::TokenId, - storage::{ - lmdb::{lmdb_asset_backend::LmdbAssetBackend, PATRICIA_MAP_KEY}, - AssetStore, - StorageError, - }, -}; - -pub struct LmdbAssetStore { - db: LmdbAssetBackend, - cached: Option>>, -} - -impl LmdbAssetStore { - pub fn initialize>(path: P, config: LMDBConfig) -> Result { - Ok(Self { - db: LmdbAssetBackend::initialize(path, config)?, - cached: None, - }) - } - - /// Returns the full persisted ParticiaMap of the metadata state. - fn load_map(&self, access: &ConstAccessor<'_>) -> Result>, StorageError> { - let map = self - .db - .get_metadata(access, PATRICIA_MAP_KEY)? - .map(decode_patricia_nodes) - .transpose()? - .unwrap_or_else(Node::root); - Ok(map.into()) - } -} - -impl AssetStore for LmdbAssetStore { - fn get_metadata(&mut self, token_id: &TokenId) -> Result>, DigitalAssetError> { - match &self.cached { - Some(cached) => { - let val = cached.get(token_id); - Ok(val.cloned()) - }, - None => { - let txn = self.db.read_transaction()?; - let map = self.load_map(&txn.access())?; - let val = map.get(token_id).cloned(); - self.cached = Some(map); - Ok(val) - }, - } - } - - fn replace_metadata(&mut self, token_id: &TokenId, value: &[u8]) -> Result<(), DigitalAssetError> { - let mut cached = self.cached.take(); - let txn = self.db.write_transaction()?; - { - let mut access = txn.access(); - if cached.is_none() { - cached = Some(self.load_map(&*access)?); - }; - let cached_ref = cached.as_mut().unwrap(); - cached_ref.insert(token_id, value.to_vec()); - let encoded = encode_patricia_map(cached_ref.clone()) - .map_err(|_| DigitalAssetError::MalformedMetadata("Failed to encode Patricia map".to_string()))?; - self.db.replace_metadata(&mut access, PATRICIA_MAP_KEY, &encoded)?; - } - txn.commit()?; - self.cached = cached; - - Ok(()) - } -} - -impl Clone for LmdbAssetStore { - fn clone(&self) -> Self { - Self { - db: self.db.clone(), - cached: None, - } - } -} -fn decode_patricia_nodes(bytes: &[u8]) -> Result, bytecodec::Error> -where for<'de> T: serde::Deserialize<'de> { - let mut decoder = NodeDecoder::new(BincodeDecoder::new()); - let nodes = decoder.decode_from_bytes(bytes)?; - Ok(nodes) -} - -fn encode_patricia_map(map: PatriciaMap) -> Result, bytecodec::Error> -where T: serde::Serialize { - let mut encoder = NodeEncoder::new(BincodeEncoder::new()); - let encoded = encoder.encode_into_bytes(map.into())?; - Ok(encoded) -} diff --git a/dan_layer/core/src/storage/lmdb/mod.rs b/dan_layer/core/src/storage/lmdb/mod.rs deleted file mode 100644 index 2f0e34e07e..0000000000 --- a/dan_layer/core/src/storage/lmdb/mod.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2021, The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#[cfg(test)] -mod test; - -mod asset_db; -mod helpers; -mod lmdb_asset_backend; -mod lmdb_asset_store; - -pub use asset_db::AssetDb; -pub use lmdb_asset_backend::LmdbAssetBackend; -pub use lmdb_asset_store::LmdbAssetStore; - -const PATRICIA_MAP_KEY: u64 = 1u64; diff --git a/dan_layer/core/src/storage/lmdb/test.rs b/dan_layer/core/src/storage/lmdb/test.rs deleted file mode 100644 index fb6548cd5e..0000000000 --- a/dan_layer/core/src/storage/lmdb/test.rs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2021, The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -use std::fs; - -use tari_test_utils::paths; - -use crate::{ - models::TokenId, - storage::{lmdb::lmdb_asset_store::LmdbAssetStore, AssetStore}, -}; - -fn with_store(f: F) { - let path = paths::create_temporary_data_path(); - let store = LmdbAssetStore::initialize(&path, Default::default()).unwrap(); - f(store); - // TODO: This will not happen on panic - fs::remove_dir_all(path).unwrap(); -} - -#[test] -fn it_replaces_the_metadata() { - with_store(|mut store| { - store.replace_metadata(&TokenId(b"123".to_vec()), &[4, 5, 6]).unwrap(); - let metadata = store.get_metadata(&TokenId(b"123".to_vec())).unwrap().unwrap(); - assert_eq!(metadata, vec![4, 5, 6]); - - store.replace_metadata(&TokenId(b"123".to_vec()), &[5, 6, 7]).unwrap(); - let metadata = store.get_metadata(&TokenId(b"123".to_vec())).unwrap().unwrap(); - assert_eq!(metadata, vec![5, 6, 7]); - }); -} - -#[test] -fn it_returns_none_if_key_does_not_exist() { - with_store(|mut store| { - let metadata = store.get_metadata(&TokenId(b"123".to_vec())).unwrap(); - assert!(metadata.is_none()); - }); -} diff --git a/dan_layer/core/src/storage/mocks/mod.rs b/dan_layer/core/src/storage/mocks/mod.rs index 7c5fc12496..e8f7ce4a19 100644 --- a/dan_layer/core/src/storage/mocks/mod.rs +++ b/dan_layer/core/src/storage/mocks/mod.rs @@ -22,7 +22,6 @@ pub mod chain_db; pub mod global_db; -pub mod state_db; use std::{ collections::HashMap, @@ -30,16 +29,12 @@ use std::{ }; use tari_common_types::types::FixedHash; +use tari_dan_engine::state::{mocks::state_db::MockStateDbBackupAdapter, StateDb}; use crate::storage::{ chain::{ChainDb, DbInstruction, DbNode, DbQc}, global::GlobalDb, - mocks::{ - chain_db::MockChainDbBackupAdapter, - global_db::MockGlobalDbBackupAdapter, - state_db::MockStateDbBackupAdapter, - }, - state::StateDb, + mocks::{chain_db::MockChainDbBackupAdapter, global_db::MockGlobalDbBackupAdapter}, DbFactory, StorageError, }; diff --git a/dan_layer/core/src/storage/mocks/state_db.rs b/dan_layer/core/src/storage/mocks/state_db.rs deleted file mode 100644 index 2ca153cec0..0000000000 --- a/dan_layer/core/src/storage/mocks/state_db.rs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2022, The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -use patricia_tree::PatriciaMap; - -use crate::storage::{ - state::{DbKeyValue, DbStateOpLogEntry, StateDbBackendAdapter}, - StorageError, -}; - -#[derive(Debug, Clone, Default)] -pub struct MockStateDbBackupAdapter; - -impl StateDbBackendAdapter for MockStateDbBackupAdapter { - type BackendTransaction = (); - type Error = StorageError; - - fn create_transaction(&self) -> Result { - todo!() - } - - fn update_key_value( - &self, - _schema: &str, - _key: &[u8], - _value: &[u8], - _tx: &Self::BackendTransaction, - ) -> Result<(), Self::Error> { - todo!() - } - - fn get(&self, _schema: &str, _key: &[u8]) -> Result>, Self::Error> { - todo!() - } - - fn find_keys_by_value(&self, _schema: &str, _value: &[u8]) -> Result>, Self::Error> { - todo!() - } - - fn commit(&self, _tx: &Self::BackendTransaction) -> Result<(), Self::Error> { - todo!() - } - - fn get_current_state_tree(&self, _tx: &Self::BackendTransaction) -> Result>, Self::Error> { - todo!() - } - - fn set_current_state_tree( - &self, - _tree: PatriciaMap>, - _tx: &Self::BackendTransaction, - ) -> Result<(), Self::Error> { - todo!() - } - - fn get_all_schemas(&self, _tx: &Self::BackendTransaction) -> Result, Self::Error> { - todo!() - } - - fn get_all_values_for_schema( - &self, - _schema: &str, - _tx: &Self::BackendTransaction, - ) -> Result, Self::Error> { - todo!() - } - - fn get_state_op_logs_by_height( - &self, - _height: u64, - _tx: &Self::BackendTransaction, - ) -> Result, Self::Error> { - todo!() - } - - fn add_state_oplog_entry( - &self, - _entry: DbStateOpLogEntry, - _tx: &Self::BackendTransaction, - ) -> Result<(), Self::Error> { - todo!() - } - - fn clear_all_state(&self, _tx: &Self::BackendTransaction) -> Result<(), Self::Error> { - todo!() - } -} diff --git a/dan_layer/core/src/storage/mod.rs b/dan_layer/core/src/storage/mod.rs index 03a87e3cf7..5f085f3f03 100644 --- a/dan_layer/core/src/storage/mod.rs +++ b/dan_layer/core/src/storage/mod.rs @@ -22,19 +22,14 @@ pub use chain_storage_service::ChainStorageService; pub use error::StorageError; -pub use lmdb::{LmdbAssetBackend, LmdbAssetStore}; pub use store::{AssetDataStore, AssetStore}; pub mod chain; mod chain_storage_service; mod db_factory; mod error; pub mod global; -pub mod lmdb; -pub mod state; mod store; -mod unit_of_work_tracker; pub use db_factory::DbFactory; -pub use unit_of_work_tracker::UnitOfWorkTracker; pub mod mocks; diff --git a/dan_layer/core/src/storage/state/db_key_value.rs b/dan_layer/core/src/storage/state/db_key_value.rs deleted file mode 100644 index 496b53554b..0000000000 --- a/dan_layer/core/src/storage/state/db_key_value.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2021. The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#[derive(Debug, Clone)] -pub struct DbKeyValue { - pub schema: String, - pub key: Vec, - pub value: Vec, -} diff --git a/dan_layer/core/src/storage/state/mod.rs b/dan_layer/core/src/storage/state/mod.rs deleted file mode 100644 index 00eaeb630a..0000000000 --- a/dan_layer/core/src/storage/state/mod.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2021. The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -mod state_db_unit_of_work; -pub use state_db_unit_of_work::{StateDbUnitOfWork, StateDbUnitOfWorkImpl, StateDbUnitOfWorkReader, UnitOfWorkContext}; - -mod db_key_value; -pub use db_key_value::DbKeyValue; - -mod state_db; -pub use state_db::StateDb; - -mod state_db_backend_adapter; -pub use state_db_backend_adapter::StateDbBackendAdapter; - -mod state_op_log; -pub use state_op_log::{DbStateOpLogEntry, DbStateOperation}; diff --git a/dan_layer/core/src/storage/state/state_db.rs b/dan_layer/core/src/storage/state/state_db.rs deleted file mode 100644 index 68fd97051e..0000000000 --- a/dan_layer/core/src/storage/state/state_db.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2021. The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -use tari_common_types::types::FixedHash; - -use crate::storage::state::{ - state_db_unit_of_work::{StateDbUnitOfWorkImpl, StateDbUnitOfWorkReader, UnitOfWorkContext}, - StateDbBackendAdapter, -}; - -pub struct StateDb { - backend_adapter: TStateDbBackendAdapter, - contract_id: FixedHash, -} - -impl StateDb { - pub fn new(contract_id: FixedHash, backend_adapter: TStateDbBackendAdapter) -> Self { - Self { - backend_adapter, - contract_id, - } - } - - pub fn new_unit_of_work(&self, height: u64) -> StateDbUnitOfWorkImpl { - StateDbUnitOfWorkImpl::new( - UnitOfWorkContext::new(height, self.contract_id), - self.backend_adapter.clone(), - ) - } - - pub fn reader(&self) -> impl StateDbUnitOfWorkReader { - // TODO: A reader doesnt need the current context, should perhaps make a read-only implementation that the - // writable implementation also uses - StateDbUnitOfWorkImpl::new( - UnitOfWorkContext::new(0, self.contract_id), - self.backend_adapter.clone(), - ) - } -} diff --git a/dan_layer/core/src/storage/state/state_db_backend_adapter.rs b/dan_layer/core/src/storage/state/state_db_backend_adapter.rs deleted file mode 100644 index df8b0080aa..0000000000 --- a/dan_layer/core/src/storage/state/state_db_backend_adapter.rs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2021. The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -use patricia_tree::PatriciaMap; - -use crate::storage::{ - state::{db_key_value::DbKeyValue, DbStateOpLogEntry}, - StorageError, -}; - -pub trait StateDbBackendAdapter: Send + Sync + Clone { - type BackendTransaction; - type Error: Into; - - fn create_transaction(&self) -> Result; - fn update_key_value( - &self, - schema: &str, - key: &[u8], - value: &[u8], - tx: &Self::BackendTransaction, - ) -> Result<(), Self::Error>; - fn get(&self, schema: &str, key: &[u8]) -> Result>, Self::Error>; - fn find_keys_by_value(&self, schema: &str, value: &[u8]) -> Result>, Self::Error>; - fn commit(&self, tx: &Self::BackendTransaction) -> Result<(), Self::Error>; - fn get_current_state_tree(&self, tx: &Self::BackendTransaction) -> Result>, Self::Error>; - fn set_current_state_tree( - &self, - tree: PatriciaMap>, - tx: &Self::BackendTransaction, - ) -> Result<(), Self::Error>; - - fn get_all_schemas(&self, tx: &Self::BackendTransaction) -> Result, Self::Error>; - fn get_all_values_for_schema( - &self, - schema: &str, - tx: &Self::BackendTransaction, - ) -> Result, Self::Error>; - fn get_state_op_logs_by_height( - &self, - height: u64, - tx: &Self::BackendTransaction, - ) -> Result, Self::Error>; - fn add_state_oplog_entry(&self, entry: DbStateOpLogEntry, tx: &Self::BackendTransaction) - -> Result<(), Self::Error>; - fn clear_all_state(&self, tx: &Self::BackendTransaction) -> Result<(), Self::Error>; -} diff --git a/dan_layer/core/src/storage/state/state_op_log.rs b/dan_layer/core/src/storage/state/state_op_log.rs deleted file mode 100644 index 76c7a9b982..0000000000 --- a/dan_layer/core/src/storage/state/state_op_log.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2022, The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -use std::str::FromStr; - -use crate::{models::TreeNodeHash, storage::state::DbKeyValue}; - -#[derive(Debug)] -pub struct DbStateOpLogEntry { - pub height: u64, - pub merkle_root: Option, - pub operation: DbStateOperation, - pub schema: String, - pub key: Vec, - pub value: Option>, -} - -impl DbStateOpLogEntry { - pub fn set_operation(height: u64, key_value: DbKeyValue) -> Self { - Self { - height, - merkle_root: None, - operation: DbStateOperation::Set, - schema: key_value.schema, - key: key_value.key, - value: Some(key_value.value), - } - } -} - -#[derive(Debug, Clone, Copy)] -pub enum DbStateOperation { - Set, - Delete, -} - -impl DbStateOperation { - pub fn as_op_str(&self) -> &str { - use DbStateOperation::{Delete, Set}; - match self { - Set => "S", - Delete => "D", - } - } -} - -impl FromStr for DbStateOperation { - type Err = (); - - fn from_str(s: &str) -> Result { - use DbStateOperation::{Delete, Set}; - match s { - "S" => Ok(Set), - "D" => Ok(Delete), - _ => Err(()), - } - } -} diff --git a/dan_layer/core/src/storage/unit_of_work_tracker.rs b/dan_layer/core/src/storage/unit_of_work_tracker.rs deleted file mode 100644 index 6431d97307..0000000000 --- a/dan_layer/core/src/storage/unit_of_work_tracker.rs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2021. The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -use std::sync::{ - atomic::{AtomicBool, Ordering}, - Arc, - RwLock, - RwLockReadGuard, - RwLockWriteGuard, -}; - -#[derive(Debug)] -pub struct UnitOfWorkTracker { - item: Arc>, - is_dirty: Arc, -} - -impl Clone for UnitOfWorkTracker { - fn clone(&self) -> Self { - Self { - item: self.item.clone(), - is_dirty: self.is_dirty.clone(), - } - } -} - -impl UnitOfWorkTracker { - pub fn new(item: TItem, is_dirty: bool) -> Self { - Self { - item: Arc::new(RwLock::new(item)), - is_dirty: Arc::new(AtomicBool::new(is_dirty)), - } - } - - pub fn get(&self) -> RwLockReadGuard { - self.item.read().unwrap() - } - - pub fn get_mut(&self) -> RwLockWriteGuard { - self.is_dirty.store(true, Ordering::SeqCst); - self.item.write().unwrap() - } - - pub fn is_dirty(&self) -> bool { - self.is_dirty.load(Ordering::SeqCst) - } -} diff --git a/dan_layer/core/src/template_command.rs b/dan_layer/core/src/template_command.rs index 0264b304a3..2f1b1431d3 100644 --- a/dan_layer/core/src/template_command.rs +++ b/dan_layer/core/src/template_command.rs @@ -20,7 +20,9 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use crate::{digital_assets_error::DigitalAssetError, storage::state::StateDbUnitOfWork}; +use tari_dan_engine::state::StateDbUnitOfWork; + +use crate::digital_assets_error::DigitalAssetError; pub trait TemplateCommand { fn try_execute( diff --git a/dan_layer/core/src/templates/tip002_template.rs b/dan_layer/core/src/templates/tip002_template.rs index 0c54aeb3ab..26146720da 100644 --- a/dan_layer/core/src/templates/tip002_template.rs +++ b/dan_layer/core/src/templates/tip002_template.rs @@ -23,14 +23,14 @@ use prost::Message; use tari_common_types::types::PublicKey; use tari_core::transactions::transaction_components::TemplateParameter; -use tari_dan_common_types::proto::tips::tip002; +use tari_dan_common_types::{proto::tips::tip002, TemplateId}; +use tari_dan_engine::{ + instructions::Instruction, + state::{StateDbUnitOfWork, StateDbUnitOfWorkReader}, +}; use tari_utilities::{hex::Hex, ByteArray}; -use crate::{ - models::{Instruction, InstructionSet, TemplateId}, - storage::state::{StateDbUnitOfWork, StateDbUnitOfWorkReader}, - DigitalAssetError, -}; +use crate::{models::InstructionSet, DigitalAssetError}; pub fn initial_instructions(template_param: &TemplateParameter) -> InstructionSet { InstructionSet::from_vec(vec![Instruction::new( diff --git a/dan_layer/core/src/templates/tip004_template.rs b/dan_layer/core/src/templates/tip004_template.rs index 22a484b8dc..028c23fc84 100644 --- a/dan_layer/core/src/templates/tip004_template.rs +++ b/dan_layer/core/src/templates/tip004_template.rs @@ -26,13 +26,10 @@ use prost::Message; use tari_core::transactions::transaction_components::TemplateParameter; use tari_crypto::common::Blake256; use tari_dan_common_types::proto::tips::tip004; +use tari_dan_engine::state::{StateDbUnitOfWork, StateDbUnitOfWorkReader}; use tari_utilities::hex::Hex; -use crate::{ - models::InstructionSet, - storage::state::{StateDbUnitOfWork, StateDbUnitOfWorkReader}, - DigitalAssetError, -}; +use crate::{models::InstructionSet, DigitalAssetError}; const LOG_TARGET: &str = "tari::dan_layer::core::templates::tip004_template"; diff --git a/dan_layer/core/src/templates/tip721_template.rs b/dan_layer/core/src/templates/tip721_template.rs index c35312dd94..8ab09bf29e 100644 --- a/dan_layer/core/src/templates/tip721_template.rs +++ b/dan_layer/core/src/templates/tip721_template.rs @@ -24,13 +24,10 @@ use log::*; use prost::Message; use tari_core::transactions::transaction_components::TemplateParameter; use tari_dan_common_types::proto::tips::tip721; +use tari_dan_engine::state::{StateDbUnitOfWork, StateDbUnitOfWorkReader}; use tari_utilities::{hex::Hex, ByteArray}; -use crate::{ - models::InstructionSet, - storage::state::{StateDbUnitOfWork, StateDbUnitOfWorkReader}, - DigitalAssetError, -}; +use crate::{models::InstructionSet, DigitalAssetError}; const LOG_TARGET: &str = "tari::dan_layer::core::templates::tip721_template"; diff --git a/dan_layer/core/src/workers/consensus_worker.rs b/dan_layer/core/src/workers/consensus_worker.rs index 260420afbd..37927a4201 100644 --- a/dan_layer/core/src/workers/consensus_worker.rs +++ b/dan_layer/core/src/workers/consensus_worker.rs @@ -27,6 +27,7 @@ use std::sync::{ use log::*; use tari_common_types::types::PublicKey; +use tari_dan_engine::state::{StateDbUnitOfWork, StateDbUnitOfWorkImpl, StateDbUnitOfWorkReader}; use tari_shutdown::ShutdownSignal; use tokio::time::Duration; @@ -36,7 +37,6 @@ use crate::{ services::{CheckpointManager, CommitteeManager, EventsPublisher, PayloadProvider, ServiceSpecification}, storage::{ chain::{ChainDb, ChainDbUnitOfWork}, - state::{StateDbUnitOfWork, StateDbUnitOfWorkImpl, StateDbUnitOfWorkReader}, DbFactory, }, workers::{states, states::ConsensusWorkerStateEvent}, diff --git a/dan_layer/core/src/workers/state_sync/error.rs b/dan_layer/core/src/workers/state_sync/error.rs index 6a68292dba..c336e17fe1 100644 --- a/dan_layer/core/src/workers/state_sync/error.rs +++ b/dan_layer/core/src/workers/state_sync/error.rs @@ -20,6 +20,8 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +use tari_dan_engine::state::error::StateStorageError; + use crate::{services::ValidatorNodeClientError, storage::StorageError}; #[derive(Debug, thiserror::Error)] @@ -30,6 +32,8 @@ pub enum StateSyncError { NoOtherCommitteeMembersToSync, #[error("Storage error: {0}")] StorageError(#[from] StorageError), + #[error("State storage error: {0}")] + StateStorageError(#[from] StateStorageError), #[error("Invalid state Merkle root")] InvalidStateMerkleRoot, #[error("Remote peer does not have tip node")] diff --git a/dan_layer/core/src/workers/state_sync/mod.rs b/dan_layer/core/src/workers/state_sync/mod.rs index e9feea43ee..9aba7e7b54 100644 --- a/dan_layer/core/src/workers/state_sync/mod.rs +++ b/dan_layer/core/src/workers/state_sync/mod.rs @@ -25,15 +25,18 @@ pub use error::StateSyncError; use log::*; use rand::{rngs::OsRng, seq::SliceRandom}; use tari_common_types::types::PublicKey; +use tari_dan_engine::state::{ + error::StateStorageError, + StateDb, + StateDbBackendAdapter, + StateDbUnitOfWork, + StateDbUnitOfWorkReader, +}; use tari_utilities::hex::Hex; use crate::{ models::CheckpointOutput, services::{ValidatorNodeClientFactory, ValidatorNodeRpcClient}, - storage::{ - state::{StateDb, StateDbBackendAdapter, StateDbUnitOfWork, StateDbUnitOfWorkReader}, - StorageError, - }, }; const LOG_TARGET: &str = "tari::dan::workers::state_sync"; @@ -128,8 +131,8 @@ where } // TODO: Check merkle root before commit - uow.clear_all_state().map_err(StorageError::from)?; - uow.commit().map_err(StorageError::from)?; + uow.clear_all_state().map_err(StateStorageError::from)?; + uow.commit().map_err(StateStorageError::from)?; let merkle_root = uow.calculate_root()?; if self.last_checkpoint.merkle_root.as_slice() != merkle_root.as_bytes() { diff --git a/dan_layer/core/src/workers/states/next_view.rs b/dan_layer/core/src/workers/states/next_view.rs index 25c94fd677..6f07ab3bee 100644 --- a/dan_layer/core/src/workers/states/next_view.rs +++ b/dan_layer/core/src/workers/states/next_view.rs @@ -23,11 +23,12 @@ use std::marker::PhantomData; use log::*; +use tari_dan_engine::state::models::StateRoot; use tari_shutdown::ShutdownSignal; use crate::{ digital_assets_error::DigitalAssetError, - models::{AssetDefinition, Committee, HotStuffMessage, HotStuffTreeNode, QuorumCertificate, StateRoot, View}, + models::{AssetDefinition, Committee, HotStuffMessage, HotStuffTreeNode, QuorumCertificate, View}, services::{infrastructure_services::OutboundService, PayloadProvider, ServiceSpecification}, storage::DbFactory, workers::states::ConsensusWorkerStateEvent, diff --git a/dan_layer/core/src/workers/states/prepare.rs b/dan_layer/core/src/workers/states/prepare.rs index 7d3f51fc04..24aba6c7e1 100644 --- a/dan_layer/core/src/workers/states/prepare.rs +++ b/dan_layer/core/src/workers/states/prepare.rs @@ -24,6 +24,7 @@ use std::{collections::HashMap, time::Duration}; use log::*; use tari_common_types::types::FixedHash; +use tari_dan_engine::state::StateDbUnitOfWork; use tokio::time::sleep; use crate::{ @@ -46,7 +47,7 @@ use crate::{ ServiceSpecification, SigningService, }, - storage::{chain::ChainDbUnitOfWork, state::StateDbUnitOfWork, ChainStorageService, DbFactory, StorageError}, + storage::{chain::ChainDbUnitOfWork, ChainStorageService, DbFactory, StorageError}, workers::states::ConsensusWorkerStateEvent, }; diff --git a/dan_layer/core/src/workers/states/synchronizing.rs b/dan_layer/core/src/workers/states/synchronizing.rs index 7852adacf7..d94f12553a 100644 --- a/dan_layer/core/src/workers/states/synchronizing.rs +++ b/dan_layer/core/src/workers/states/synchronizing.rs @@ -25,11 +25,12 @@ use std::{convert::TryFrom, marker::PhantomData}; use log::*; use tari_comms::types::CommsPublicKey; use tari_core::transactions::transaction_components::OutputType; +use tari_dan_engine::state::StateDbUnitOfWorkReader; use crate::{ models::{AssetDefinition, CheckpointOutput}, services::{BaseNodeClient, ServiceSpecification}, - storage::{state::StateDbUnitOfWorkReader, DbFactory}, + storage::DbFactory, workers::{state_sync::StateSynchronizer, states::ConsensusWorkerStateEvent}, DigitalAssetError, }; diff --git a/dan_layer/engine/Cargo.toml b/dan_layer/engine/Cargo.toml new file mode 100644 index 0000000000..c7ecbe91a4 --- /dev/null +++ b/dan_layer/engine/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "tari_dan_engine" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +tari_common_types = {path = "../../base_layer/common_types"} +tari_dan_common_types = {path = "../common_types"} +tari_mmr = { path = "../../base_layer/mmr" } +tari_utilities = { git = "https://github.com/tari-project/tari_utilities.git", tag = "v0.4.4" } +tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.14.0" } + +wasmer = "2.2.1" +digest = "0.9.0" +d3ne = { git="https://github.com/stringhandler/d3ne-rs.git", branch="st-fixes2"} +anyhow = "1.0.53" +serde = "1.0.126" +log = { version = "0.4.8", features = ["std"] } +serde_json ="1.0.81" +thiserror = "^1.0.20" diff --git a/dan_layer/engine/src/flow/error.rs b/dan_layer/engine/src/flow/error.rs new file mode 100644 index 0000000000..60d9eec06e --- /dev/null +++ b/dan_layer/engine/src/flow/error.rs @@ -0,0 +1,9 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use thiserror::Error; +#[derive(Debug, Error)] +pub enum FlowEngineError { + #[error("The instruction execution failed: Inner error:{inner}")] + InstructionFailed { inner: String }, +} diff --git a/dan_layer/engine/src/flow/flow_factory.rs b/dan_layer/engine/src/flow/flow_factory.rs new file mode 100644 index 0000000000..7f75d4eb47 --- /dev/null +++ b/dan_layer/engine/src/flow/flow_factory.rs @@ -0,0 +1,45 @@ +use std::collections::HashMap; + +use d3ne::WorkersBuilder; + +use crate::{ + flow::{FlowEngineError, FlowInstance}, + function_definitions::{FlowFunctionDefinition, FunctionArgDefinition}, + instructions::Instruction, + state::StateDbUnitOfWork, +}; + +#[derive(Clone, Default)] +pub struct FlowFactory { + flows: HashMap, FlowInstance)>, +} +impl FlowFactory { + pub fn new(flow_functions: &[FlowFunctionDefinition]) -> Self { + let mut flows = HashMap::new(); + for func_def in flow_functions { + // build_instance(&mut instance, &func_def); + flows.insert( + func_def.name.clone(), + ( + func_def.args.clone(), + FlowInstance::try_build(func_def.flow.clone(), WorkersBuilder::new().build()) + .expect("Could not build flow"), + ), + ); + } + Self { flows } + } + + pub fn invoke_write_method( + &self, + name: String, + instruction: &Instruction, + state_db: TUnitOfWork, + ) -> Result { + if let Some((args, engine)) = self.flows.get(&name) { + engine.process(instruction.args(), args, instruction.sender(), state_db) + } else { + todo!("could not find engine") + } + } +} diff --git a/dan_layer/engine/src/flow/flow_instance.rs b/dan_layer/engine/src/flow/flow_instance.rs new file mode 100644 index 0000000000..8c89ebbae8 --- /dev/null +++ b/dan_layer/engine/src/flow/flow_instance.rs @@ -0,0 +1,127 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use std::{ + collections::HashMap, + ops::Deref, + sync::{Arc, RwLock}, +}; + +use d3ne::{Engine, Node, Workers, WorkersBuilder}; +use serde_json::Value as JsValue; +use tari_common_types::types::PublicKey; +use tari_utilities::ByteArray; + +use crate::{ + flow::{ + workers::{ + ArgWorker, + CreateBucketWorker, + HasRoleWorker, + MintBucketWorker, + SenderWorker, + StartWorker, + StoreBucketWorker, + TextWorker, + }, + ArgValue, + FlowEngineError, + }, + function_definitions::{ArgType, FunctionArgDefinition}, + state::StateDbUnitOfWork, +}; + +#[derive(Clone, Debug)] +pub struct FlowInstance { + // engine: Engine, + // TODO: engine is not Send so can't be added here + // process: JsValue, + start_node: i64, + nodes: HashMap, +} + +impl FlowInstance { + pub fn try_build(value: JsValue, workers: Workers) -> Result { + let engine = Engine::new("tari@0.1.0", workers); + // dbg!(&value); + let nodes = engine.parse_value(value).expect("could not create engine"); + Ok(FlowInstance { + // process: value, + nodes, + start_node: 1, + }) + } + + pub fn process( + &self, + args: &[u8], + arg_defs: &[FunctionArgDefinition], + sender: PublicKey, + state_db: TUnitOfWork, + ) -> Result { + let mut engine_args = HashMap::new(); + + let mut remaining_args = Vec::from(args); + for ad in arg_defs { + let value = match ad.arg_type { + ArgType::String => { + let length = remaining_args.pop().expect("no more args: len") as usize; + let s_bytes: Vec = remaining_args.drain(0..length).collect(); + let s = String::from_utf8(s_bytes).expect("could not convert string"); + ArgValue::String(s) + }, + ArgType::Byte => ArgValue::Byte(remaining_args.pop().expect("No byte to read")), + ArgType::PublicKey => { + let bytes: Vec = remaining_args.drain(0..32).collect(); + let pk = PublicKey::from_bytes(&bytes).expect("Not a valid public key"); + ArgValue::PublicKey(pk) + }, + ArgType::Uint => { + let bytes: Vec = remaining_args.drain(0..8).collect(); + let mut fixed: [u8; 8] = [0u8; 8]; + fixed.copy_from_slice(&bytes); + let value = u64::from_le_bytes(fixed); + ArgValue::Uint(value) + }, + }; + engine_args.insert(ad.name.clone(), value); + } + + let state_db = Arc::new(RwLock::new(state_db)); + let engine = Engine::new("tari@0.1.0", load_workers(engine_args, sender, state_db.clone())); + let output = engine.process(&self.nodes, self.start_node); + let _od = output.expect("engine process failed"); + // if let Some(err) = od.get("error") { + // match err { + // Ok(_) => todo!("Unexpected Ok result returned from error"), + // Err(e) => { + // return Err(FlowEngineError::InstructionFailed { inner: e.to_string() }); + // }, + // } + // } + let inner = state_db.read().map(|s| s.deref().clone()).unwrap(); + Ok(inner) + } +} + +fn load_workers( + args: HashMap, + sender: PublicKey, + state_db: Arc>, +) -> Workers { + let mut workers = WorkersBuilder::new(); + workers.add(StartWorker {}); + workers.add(CreateBucketWorker { + state_db: state_db.clone(), + }); + workers.add(StoreBucketWorker { + state_db: state_db.clone(), + }); + workers.add(ArgWorker { args: args.clone() }); + workers.add(ArgWorker { args }); + workers.add(SenderWorker { sender }); + workers.add(TextWorker {}); + workers.add(HasRoleWorker { state_db }); + workers.add(MintBucketWorker {}); + workers.build() +} diff --git a/dan_layer/engine/src/flow/mod.rs b/dan_layer/engine/src/flow/mod.rs new file mode 100644 index 0000000000..96a826171a --- /dev/null +++ b/dan_layer/engine/src/flow/mod.rs @@ -0,0 +1,33 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +pub mod error; +mod flow_factory; +mod flow_instance; +pub mod workers; + +use std::any::Any; + +pub use error::FlowEngineError; +pub use flow_factory::FlowFactory; +pub use flow_instance::FlowInstance; +use tari_common_types::types::PublicKey; + +#[derive(Clone, Debug)] +pub enum ArgValue { + String(String), + Byte(u8), + PublicKey(PublicKey), + Uint(u64), +} + +impl ArgValue { + pub fn into_any(self) -> Box { + match self { + ArgValue::String(s) => Box::new(s), + ArgValue::Byte(b) => Box::new(b), + ArgValue::PublicKey(k) => Box::new(k), + ArgValue::Uint(u) => Box::new(u), + } + } +} diff --git a/dan_layer/engine/src/flow/workers/arg_worker.rs b/dan_layer/engine/src/flow/workers/arg_worker.rs new file mode 100644 index 0000000000..2d9e896493 --- /dev/null +++ b/dan_layer/engine/src/flow/workers/arg_worker.rs @@ -0,0 +1,53 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use std::collections::HashMap; + +use d3ne::{InputData, Node, OutputData, OutputDataBuilder, Worker}; +use tari_utilities::hex::Hex; + +use crate::flow::ArgValue; + +pub struct ArgWorker { + pub args: HashMap, +} + +impl Worker for ArgWorker { + // fn call(&self, node: Node, inputs: InputData) -> OutputData { + // let name = node.get_string_field("name", &inputs).unwrap(); + // let mut map = HashMap::new(); + // let value = self.args.get(&name).cloned().expect("could not find arg"); + // match value { + // ArgValue::Uint(x) => map.insert( + // "default".to_string(), + // Ok(IOData { + // data: Box::new(x as i64), + // }), + // ), + // ArgValue::PublicKey(pk) => map.insert( + // "default".to_string(), + // Ok(IOData { + // data: Box::new(pk.to_hex()), + // }), + // ), + // _ => todo!(), + // }; + // + // Rc::new(map) + // } + + fn name(&self) -> &str { + "tari::arg" + } + + fn work(&self, node: &Node, input_data: InputData) -> anyhow::Result { + let name = node.get_string_field("name", &input_data)?; + let value = self.args.get(&name).cloned().expect("could not find arg"); + let output = match value { + ArgValue::Uint(x) => OutputDataBuilder::new().data("default", Box::new(x as i64)), + ArgValue::PublicKey(pk) => OutputDataBuilder::new().data("default", Box::new(pk.to_hex())), + _ => todo!(), + }; + Ok(output.build()) + } +} diff --git a/dan_layer/engine/src/flow/workers/create_bucket_worker.rs b/dan_layer/engine/src/flow/workers/create_bucket_worker.rs new file mode 100644 index 0000000000..0b543ecacd --- /dev/null +++ b/dan_layer/engine/src/flow/workers/create_bucket_worker.rs @@ -0,0 +1,110 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use std::{ + convert::TryFrom, + sync::{Arc, RwLock}, +}; + +use d3ne::{InputData, Node, OutputData, OutputDataBuilder, Worker}; +use tari_common_types::types::PublicKey; +use tari_utilities::{hex::Hex, ByteArray}; + +use crate::{models::Bucket, state::StateDbUnitOfWork}; + +pub struct CreateBucketWorker { + pub state_db: Arc>, +} + +impl Worker for CreateBucketWorker { + fn name(&self) -> &str { + "tari::create_bucket" + } + + fn work(&self, node: &Node, input_data: InputData) -> anyhow::Result { + // TODO: return proper errors.... + let amount = u64::try_from(node.get_number_field("amount", &input_data)?)?; + let token_id = u64::try_from(node.get_number_field("token_id", &input_data)?)?; + let asset_id = u64::try_from(node.get_number_field("asset_id", &input_data)?)?; + let from = PublicKey::from_hex(&node.get_string_field("from", &input_data)?).expect("Not a valid pub key"); + let mut state = self.state_db.write().unwrap(); + let balance_key = format!("token_id-{}-{}", asset_id, token_id); + let balance = state.get_u64(&balance_key, from.as_bytes())?.unwrap_or(0); + let new_balance = balance.checked_sub(amount).expect("Not enough funds to create bucket"); + state + .set_u64(&balance_key, from.as_bytes(), new_balance) + .expect("Could not save state"); + let output = OutputDataBuilder::new() + .data("default", Box::new(())) + .data("bucket", Box::new(Bucket::new(amount, token_id, asset_id))) + .build(); + Ok(output) + } + // let mut map = HashMap::new(); + // let amount = match node.get_number_field("amount", &inputs) { + // Ok(a) => a as u64, + // Err(err) => { + // let mut err_map = HashMap::new(); + // err_map.insert("error".to_string(), Err(err)); + // return Rc::new(err_map); + // }, + // }; + // let token_id = match node.get_number_field("token_id", &inputs) { + // Ok(a) => a as u64, + // Err(err) => { + // let mut err_map = HashMap::new(); + // err_map.insert("error".to_string(), Err(err)); + // return Rc::new(err_map); + // }, + // }; + // let asset_id = match node.get_number_field("asset_id", &inputs) { + // Ok(a) => a as u64, + // Err(err) => { + // let mut err_map = HashMap::new(); + // err_map.insert("error".to_string(), Err(err)); + // return Rc::new(err_map); + // }, + // }; + // let from = match node.get_string_field("from", &inputs) { + // Ok(a) => PublicKey::from_hex(&a).expect("Not a valid pub key"), + // Err(err) => { + // let mut err_map = HashMap::new(); + // err_map.insert("error".to_string(), Err(err)); + // return Rc::new(err_map); + // }, + // }; + // + // let mut state = self.state_db.write().unwrap(); + // let balance_key = format!("token_id-{}-{}", asset_id, token_id); + // let balance = match state.get_u64(&balance_key, from.as_bytes()) { + // Ok(b) => b.unwrap_or(0), + // Err(err) => { + // let mut err_map = HashMap::new(); + // err_map.insert("error".to_string(), Err(err.into())); + // return Rc::new(err_map); + // }, + // }; + // + // let new_balance = match balance.checked_sub(amount) { + // Some(x) => x, + // None => { + // let mut err_map = HashMap::new(); + // err_map.insert("error".to_string(), Err(anyhow!("Not enough funds to create bucket"))); + // return Rc::new(err_map); + // }, + // }; + // match state.set_u64(&balance_key, from.as_bytes(), new_balance) { + // Ok(_) => (), + // Err(err) => { + // let mut err_map = HashMap::new(); + // err_map.insert("error".to_string(), Err(err.into())); + // return Rc::new(err_map); + // }, + // } + // + // let bucket = Bucket::new(amount, token_id, asset_id); + // map.insert("default".to_string(), Ok(IOData { data: Box::new(()) })); + // map.insert("bucket".to_string(), Ok(IOData { data: Box::new(bucket) })); + // Rc::new(map) + // } +} diff --git a/dan_layer/engine/src/flow/workers/has_role_worker.rs b/dan_layer/engine/src/flow/workers/has_role_worker.rs new file mode 100644 index 0000000000..df9bc9641e --- /dev/null +++ b/dan_layer/engine/src/flow/workers/has_role_worker.rs @@ -0,0 +1,42 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use std::sync::{Arc, RwLock}; + +use d3ne::{InputData, Node, OutputData, OutputDataBuilder, Worker}; + +use crate::state::StateDbUnitOfWork; + +pub struct HasRoleWorker { + pub state_db: Arc>, +} +impl Worker for HasRoleWorker { + // fn call(&self, node: Node, inputs: InputData) -> OutputData { + // let _role = node.get_string_field("role", &inputs).unwrap(); + // + // let _pubkey = match node.get_string_field("pubkey", &inputs) { + // Ok(a) => PublicKey::from_hex(&a).expect("Not a valid pub key"), + // Err(err) => { + // let mut err_map = HashMap::new(); + // err_map.insert("error".to_string(), Err(err)); + // return Rc::new(err_map); + // }, + // }; + // + // // let state = self.state_db.read().expect("Could not get lock on data"); + // // state.get_value() + // // TODO: read roles from db + // let mut map = HashMap::new(); + // map.insert("default".to_string(), Ok(IOData { data: Box::new(()) })); + // Rc::new(map) + // } + + fn name(&self) -> &str { + "tari::has_role" + } + + fn work(&self, node: &Node, input_data: InputData) -> anyhow::Result { + let _role = node.get_string_field("role", &input_data)?; + Ok(OutputDataBuilder::new().data("default", Box::new(())).build()) + } +} diff --git a/dan_layer/engine/src/flow/workers/mint_bucket_worker.rs b/dan_layer/engine/src/flow/workers/mint_bucket_worker.rs new file mode 100644 index 0000000000..001f329f12 --- /dev/null +++ b/dan_layer/engine/src/flow/workers/mint_bucket_worker.rs @@ -0,0 +1,61 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use std::convert::TryFrom; + +use d3ne::{InputData, Node, OutputData, OutputDataBuilder, Worker}; + +use crate::models::Bucket; + +pub struct MintBucketWorker {} + +impl Worker for MintBucketWorker { + // fn call(&self, node: Node, inputs: InputData) -> OutputData { + // let mut map = HashMap::new(); + // let amount = match node.get_number_field("amount", &inputs) { + // Ok(a) => a as u64, + // Err(err) => { + // let mut err_map = HashMap::new(); + // err_map.insert("error".to_string(), Err(err)); + // return Rc::new(err_map); + // }, + // }; + // let token_id = match node.get_number_field("token_id", &inputs) { + // Ok(a) => a as u64, + // Err(err) => { + // let mut err_map = HashMap::new(); + // err_map.insert("error".to_string(), Err(err)); + // return Rc::new(err_map); + // }, + // }; + // + // let asset_id = match node.get_number_field("asset_id", &inputs) { + // Ok(a) => a as u64, + // Err(err) => { + // let mut err_map = HashMap::new(); + // err_map.insert("error".to_string(), Err(err)); + // return Rc::new(err_map); + // }, + // }; + // let bucket = Bucket::new(amount, token_id, asset_id); + // map.insert("default".to_string(), Ok(IOData { data: Box::new(()) })); + // map.insert("bucket".to_string(), Ok(IOData { data: Box::new(bucket) })); + // Rc::new(map) + // } + + fn name(&self) -> &str { + "tari::mint_bucket" + } + + fn work(&self, node: &Node, inputs: InputData) -> anyhow::Result { + let amount = u64::try_from(node.get_number_field("amount", &inputs)?)?; + let token_id = u64::try_from(node.get_number_field("token_id", &inputs)?)?; + let asset_id = u64::try_from(node.get_number_field("asset_id", &inputs)?)?; + let bucket = Bucket::new(amount, token_id, asset_id); + let output = OutputDataBuilder::new() + .data("default", Box::new(())) + .data("bucket", Box::new(bucket)) + .build(); + Ok(output) + } +} diff --git a/dan_layer/engine/src/flow/workers/mod.rs b/dan_layer/engine/src/flow/workers/mod.rs new file mode 100644 index 0000000000..c44e88c458 --- /dev/null +++ b/dan_layer/engine/src/flow/workers/mod.rs @@ -0,0 +1,19 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause +mod arg_worker; +mod create_bucket_worker; +mod has_role_worker; +mod mint_bucket_worker; +mod sender_worker; +mod start_worker; +mod store_bucket_worker; +mod text_worker; + +pub use arg_worker::ArgWorker; +pub use create_bucket_worker::CreateBucketWorker; +pub use has_role_worker::HasRoleWorker; +pub use mint_bucket_worker::MintBucketWorker; +pub use sender_worker::SenderWorker; +pub use start_worker::StartWorker; +pub use store_bucket_worker::StoreBucketWorker; +pub use text_worker::TextWorker; diff --git a/dan_layer/engine/src/flow/workers/sender_worker.rs b/dan_layer/engine/src/flow/workers/sender_worker.rs new file mode 100644 index 0000000000..16f47b2745 --- /dev/null +++ b/dan_layer/engine/src/flow/workers/sender_worker.rs @@ -0,0 +1,33 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use d3ne::{InputData, Node, OutputData, OutputDataBuilder, Worker}; +use tari_common_types::types::PublicKey; +use tari_utilities::hex::Hex; + +pub struct SenderWorker { + pub sender: PublicKey, +} + +impl Worker for SenderWorker { + // fn call(&self, _node: Node, _input: InputData) -> OutputData { + // let mut map = HashMap::new(); + // map.insert( + // "default".to_string(), + // Ok(IOData { + // data: Box::new(self.sender.to_hex()), + // }), + // ); + // Rc::new(map) + // } + + fn name(&self) -> &str { + "core::sender" + } + + fn work(&self, _node: &Node, _input_data: InputData) -> anyhow::Result { + Ok(OutputDataBuilder::new() + .data("default", Box::new(self.sender.to_hex())) + .build()) + } +} diff --git a/dan_layer/engine/src/flow/workers/start_worker.rs b/dan_layer/engine/src/flow/workers/start_worker.rs new file mode 100644 index 0000000000..3bb2fd2d93 --- /dev/null +++ b/dan_layer/engine/src/flow/workers/start_worker.rs @@ -0,0 +1,22 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use d3ne::{InputData, Node, OutputData, OutputDataBuilder, Worker}; + +pub struct StartWorker {} + +impl Worker for StartWorker { + // fn call(&self, _node: Node, _inputs: InputData) -> OutputData { + // let mut map = HashMap::new(); + // map.insert("default".to_string(), Ok(IOData { data: Box::new(()) })); + // Rc::new(map) + // } + + fn name(&self) -> &str { + "core::start" + } + + fn work(&self, _node: &Node, _input_data: InputData) -> anyhow::Result { + Ok(OutputDataBuilder::new().data("default", Box::new(())).build()) + } +} diff --git a/dan_layer/engine/src/flow/workers/store_bucket_worker.rs b/dan_layer/engine/src/flow/workers/store_bucket_worker.rs new file mode 100644 index 0000000000..a625a6a0d9 --- /dev/null +++ b/dan_layer/engine/src/flow/workers/store_bucket_worker.rs @@ -0,0 +1,84 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use std::sync::{Arc, RwLock}; + +use d3ne::{InputData, Node, OutputData, OutputDataBuilder, Worker}; +use tari_common_types::types::PublicKey; +use tari_utilities::{hex::Hex, ByteArray}; + +use crate::{models::Bucket, state::StateDbUnitOfWork}; + +pub struct StoreBucketWorker { + pub state_db: Arc>, +} + +impl Worker for StoreBucketWorker { + // fn call(&self, node: Node, inputs: InputData) -> OutputData { + // let mut map = HashMap::new(); + // let bucket: Bucket = match node.get_field_t("bucket", &inputs) { + // Ok(a) => a, + // Err(err) => { + // let mut err_map = HashMap::new(); + // err_map.insert("error".to_string(), Err(err)); + // return Rc::new(err_map); + // }, + // }; + // + // let to = match node.get_string_field("to", &inputs) { + // Ok(a) => PublicKey::from_hex(&a).expect("Not a valid pub key"), + // Err(err) => { + // let mut err_map = HashMap::new(); + // err_map.insert("error".to_string(), Err(err)); + // return Rc::new(err_map); + // }, + // }; + // + // let mut state = self.state_db.write().unwrap(); + // let balance_key = format!("token_id-{}-{}", bucket.asset_id(), bucket.token_id()); + // let balance = match state.get_u64(&balance_key, to.as_bytes()) { + // Ok(b) => b.unwrap_or(0), + // Err(err) => { + // let mut err_map = HashMap::new(); + // err_map.insert("error".to_string(), Err(err.into())); + // return Rc::new(err_map); + // }, + // }; + // match state.set_u64( + // &balance_key, + // to.as_bytes(), + // bucket.amount().checked_add(balance).expect("overflowed"), + // ) { + // Ok(_) => (), + // Err(err) => { + // let mut err_map = HashMap::new(); + // err_map.insert("error".to_string(), Err(err.into())); + // return Rc::new(err_map); + // }, + // } + // + // map.insert("default".to_string(), Ok(IOData { data: Box::new(()) })); + // // map.insert("bucket".to_string(), Ok(IOData { data: Box::new(bucket) })); + // Rc::new(map) + // } + + fn name(&self) -> &str { + "tari::store_bucket" + } + + fn work(&self, node: &Node, inputs: InputData) -> anyhow::Result { + let bucket: Bucket = serde_json::from_str(&node.get_string_field("bucket", &inputs)?)?; + let to = PublicKey::from_hex(&node.get_string_field("to", &inputs)?)?; + let mut state = self.state_db.write().unwrap(); + let balance_key = format!("token_id-{}-{}", bucket.asset_id(), bucket.token_id()); + let balance = state.get_u64(&balance_key, to.as_bytes())?.unwrap_or(0); + state.set_u64( + &balance_key, + to.as_bytes(), + bucket.amount().checked_add(balance).expect("overflowed"), + )?; + + let output = OutputDataBuilder::new().data("default", Box::new(())).build(); + Ok(output) + } +} diff --git a/dan_layer/engine/src/flow/workers/text_worker.rs b/dan_layer/engine/src/flow/workers/text_worker.rs new file mode 100644 index 0000000000..24e90379d0 --- /dev/null +++ b/dan_layer/engine/src/flow/workers/text_worker.rs @@ -0,0 +1,24 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use d3ne::{InputData, Node, OutputData, OutputDataBuilder, Worker}; + +pub struct TextWorker {} + +impl Worker for TextWorker { + // fn call(&self, node: Node, inputs: InputData) -> OutputData { + // let txt = node.get_string_field("txt", &inputs).unwrap(); + // let mut map = HashMap::new(); + // map.insert("txt".to_string(), Ok(IOData { data: Box::new(txt) })); + // Rc::new(map) + // } + + fn name(&self) -> &str { + "core::text" + } + + fn work(&self, node: &Node, input_data: InputData) -> anyhow::Result { + let txt = node.get_string_field("txt", &input_data)?; + Ok(OutputDataBuilder::new().data("txt", Box::new(txt)).build()) + } +} diff --git a/dan_layer/engine/src/function_definitions/flow_function_definition.rs b/dan_layer/engine/src/function_definitions/flow_function_definition.rs new file mode 100644 index 0000000000..0ac03e7fa9 --- /dev/null +++ b/dan_layer/engine/src/function_definitions/flow_function_definition.rs @@ -0,0 +1,13 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause +use serde::{Deserialize, Serialize}; +use serde_json::Value as JsValue; + +use crate::function_definitions::FunctionArgDefinition; + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct FlowFunctionDefinition { + pub name: String, + pub args: Vec, + pub flow: JsValue, +} diff --git a/dan_layer/engine/src/function_definitions/function_arg_definition.rs b/dan_layer/engine/src/function_definitions/function_arg_definition.rs new file mode 100644 index 0000000000..5d55835c01 --- /dev/null +++ b/dan_layer/engine/src/function_definitions/function_arg_definition.rs @@ -0,0 +1,20 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct FunctionArgDefinition { + pub name: String, + #[serde(rename = "type")] + pub arg_type: ArgType, +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +#[serde(rename_all = "snake_case")] +pub enum ArgType { + String, + Byte, + PublicKey, + Uint, +} diff --git a/dan_layer/engine/src/function_definitions/mod.rs b/dan_layer/engine/src/function_definitions/mod.rs new file mode 100644 index 0000000000..d0998b0528 --- /dev/null +++ b/dan_layer/engine/src/function_definitions/mod.rs @@ -0,0 +1,11 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +mod function_arg_definition; + +mod flow_function_definition; +mod wasm_function_definition; + +pub use flow_function_definition::FlowFunctionDefinition; +pub use function_arg_definition::{ArgType, FunctionArgDefinition}; +pub use wasm_function_definition::WasmFunctionDefinition; diff --git a/dan_layer/engine/src/function_definitions/wasm_function_definition.rs b/dan_layer/engine/src/function_definitions/wasm_function_definition.rs new file mode 100644 index 0000000000..c68f44a003 --- /dev/null +++ b/dan_layer/engine/src/function_definitions/wasm_function_definition.rs @@ -0,0 +1,13 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use serde::{Deserialize, Serialize}; + +use crate::function_definitions::FunctionArgDefinition; + +#[derive(Serialize, Deserialize, Default, Clone, Debug)] +pub struct WasmFunctionDefinition { + pub name: String, + pub args: Vec, + pub in_module: String, +} diff --git a/dan_layer/core/src/models/instruction.rs b/dan_layer/engine/src/instructions/instruction.rs similarity index 58% rename from dan_layer/core/src/models/instruction.rs rename to dan_layer/engine/src/instructions/instruction.rs index 3830fe7ca5..bda812423a 100644 --- a/dan_layer/core/src/models/instruction.rs +++ b/dan_layer/engine/src/instructions/instruction.rs @@ -1,34 +1,14 @@ -// Copyright 2021. The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause use std::fmt::{Display, Formatter}; use digest::Digest; use tari_common_types::types::{FixedHash, PublicKey}; use tari_crypto::common::Blake256; +use tari_dan_common_types::TemplateId; use tari_utilities::hex::Hex; -use crate::models::TemplateId; - #[derive(Clone, Debug)] pub struct Instruction { template_id: TemplateId, diff --git a/dan_layer/engine/src/instructions/mod.rs b/dan_layer/engine/src/instructions/mod.rs new file mode 100644 index 0000000000..e7dc0b50e9 --- /dev/null +++ b/dan_layer/engine/src/instructions/mod.rs @@ -0,0 +1,6 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +mod instruction; + +pub use instruction::Instruction; diff --git a/dan_layer/engine/src/lib.rs b/dan_layer/engine/src/lib.rs new file mode 100644 index 0000000000..a543eb9be5 --- /dev/null +++ b/dan_layer/engine/src/lib.rs @@ -0,0 +1,9 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +pub mod flow; +pub mod function_definitions; +pub mod instructions; +pub mod models; +pub mod state; +pub mod wasm; diff --git a/dan_layer/engine/src/models/bucket.rs b/dan_layer/engine/src/models/bucket.rs new file mode 100644 index 0000000000..d9f43d7cfc --- /dev/null +++ b/dan_layer/engine/src/models/bucket.rs @@ -0,0 +1,33 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use serde::Deserialize; + +#[derive(Debug, Default, Clone, Deserialize)] +pub struct Bucket { + amount: u64, + token_id: u64, + asset_id: u64, +} + +impl Bucket { + pub fn new(amount: u64, token_id: u64, asset_id: u64) -> Self { + Self { + amount, + token_id, + asset_id, + } + } + + pub fn amount(&self) -> u64 { + self.amount + } + + pub fn token_id(&self) -> u64 { + self.token_id + } + + pub fn asset_id(&self) -> u64 { + self.asset_id + } +} diff --git a/dan_layer/engine/src/models/mod.rs b/dan_layer/engine/src/models/mod.rs new file mode 100644 index 0000000000..020c508d6d --- /dev/null +++ b/dan_layer/engine/src/models/mod.rs @@ -0,0 +1,6 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +mod bucket; + +pub use bucket::Bucket; diff --git a/dan_layer/engine/src/state/db_key_value.rs b/dan_layer/engine/src/state/db_key_value.rs new file mode 100644 index 0000000000..7e639270ca --- /dev/null +++ b/dan_layer/engine/src/state/db_key_value.rs @@ -0,0 +1,9 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +#[derive(Debug, Clone)] +pub struct DbKeyValue { + pub schema: String, + pub key: Vec, + pub value: Vec, +} diff --git a/dan_layer/engine/src/state/error.rs b/dan_layer/engine/src/state/error.rs new file mode 100644 index 0000000000..e6e840d0fc --- /dev/null +++ b/dan_layer/engine/src/state/error.rs @@ -0,0 +1,28 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause +use std::sync::PoisonError; + +use tari_mmr::error::MerkleMountainRangeError; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum StateStorageError { + #[error("Lock error")] + LockError, + #[error("Merkle error:{0}")] + MerkleMountainRangeError(#[from] MerkleMountainRangeError), + #[error("Could not connect to storage:{reason}")] + ConnectionError { reason: String }, + #[error("Query error:{reason}")] + QueryError { reason: String }, + #[error("Migration error: {reason}")] + MigrationError { reason: String }, + #[error("General storage error: {details}")] + General { details: String }, +} + +impl From> for StateStorageError { + fn from(_err: PoisonError) -> Self { + Self::LockError + } +} diff --git a/dan_layer/engine/src/state/mocks/mod.rs b/dan_layer/engine/src/state/mocks/mod.rs new file mode 100644 index 0000000000..06eb2c9285 --- /dev/null +++ b/dan_layer/engine/src/state/mocks/mod.rs @@ -0,0 +1,4 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +pub mod state_db; diff --git a/dan_layer/engine/src/state/mocks/state_db.rs b/dan_layer/engine/src/state/mocks/state_db.rs new file mode 100644 index 0000000000..db968a6899 --- /dev/null +++ b/dan_layer/engine/src/state/mocks/state_db.rs @@ -0,0 +1,70 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use crate::state::{error::StateStorageError, DbKeyValue, DbStateOpLogEntry, StateDbBackendAdapter}; + +#[derive(Debug, Clone, Default)] +pub struct MockStateDbBackupAdapter; + +impl StateDbBackendAdapter for MockStateDbBackupAdapter { + type BackendTransaction = (); + type Error = StateStorageError; + + fn create_transaction(&self) -> Result { + todo!() + } + + fn update_key_value( + &self, + _schema: &str, + _key: &[u8], + _value: &[u8], + _tx: &Self::BackendTransaction, + ) -> Result<(), Self::Error> { + todo!() + } + + fn get(&self, _schema: &str, _key: &[u8]) -> Result>, Self::Error> { + todo!() + } + + fn find_keys_by_value(&self, _schema: &str, _value: &[u8]) -> Result>, Self::Error> { + todo!() + } + + fn commit(&self, _tx: &Self::BackendTransaction) -> Result<(), Self::Error> { + todo!() + } + + fn get_all_schemas(&self, _tx: &Self::BackendTransaction) -> Result, Self::Error> { + todo!() + } + + fn get_all_values_for_schema( + &self, + _schema: &str, + _tx: &Self::BackendTransaction, + ) -> Result, Self::Error> { + todo!() + } + + fn get_state_op_logs_by_height( + &self, + _height: u64, + _tx: &Self::BackendTransaction, + ) -> Result, Self::Error> { + todo!() + } + + fn add_state_oplog_entry( + &self, + _entry: DbStateOpLogEntry, + _tx: &Self::BackendTransaction, + ) -> Result<(), Self::Error> { + todo!() + } + + fn clear_all_state(&self, _tx: &Self::BackendTransaction) -> Result<(), Self::Error> { + todo!() + } +} diff --git a/dan_layer/engine/src/state/mod.rs b/dan_layer/engine/src/state/mod.rs new file mode 100644 index 0000000000..f182357543 --- /dev/null +++ b/dan_layer/engine/src/state/mod.rs @@ -0,0 +1,22 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +mod state_db_unit_of_work; +pub use state_db_unit_of_work::{StateDbUnitOfWork, StateDbUnitOfWorkImpl, StateDbUnitOfWorkReader, UnitOfWorkContext}; + +mod db_key_value; +pub use db_key_value::DbKeyValue; + +mod state_db; +pub use state_db::StateDb; + +mod state_db_backend_adapter; +pub use state_db_backend_adapter::StateDbBackendAdapter; + +mod state_op_log; +pub use state_op_log::{DbStateOpLogEntry, DbStateOperation}; + +pub mod models; + +pub mod error; +pub mod mocks; diff --git a/dan_layer/engine/src/state/models/key_value.rs b/dan_layer/engine/src/state/models/key_value.rs new file mode 100644 index 0000000000..98271aa6c9 --- /dev/null +++ b/dan_layer/engine/src/state/models/key_value.rs @@ -0,0 +1,10 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Default, Clone, Debug)] +pub struct KeyValue { + pub key: Vec, + pub value: Vec, +} diff --git a/dan_layer/engine/src/state/models/mod.rs b/dan_layer/engine/src/state/models/mod.rs new file mode 100644 index 0000000000..72e01e6142 --- /dev/null +++ b/dan_layer/engine/src/state/models/mod.rs @@ -0,0 +1,14 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +mod key_value; +pub use key_value::KeyValue; + +mod schema_state; +pub use schema_state::SchemaState; + +mod state_root; +pub use state_root::StateRoot; + +mod op_log; +pub use op_log::{StateOpLogEntry, StateOperation}; diff --git a/dan_layer/engine/src/state/models/op_log.rs b/dan_layer/engine/src/state/models/op_log.rs new file mode 100644 index 0000000000..8ccea65eb7 --- /dev/null +++ b/dan_layer/engine/src/state/models/op_log.rs @@ -0,0 +1,50 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use crate::state::{DbStateOpLogEntry, DbStateOperation}; + +#[derive(Debug)] +pub struct StateOpLogEntry { + inner: DbStateOpLogEntry, +} + +impl StateOpLogEntry { + pub fn operation(&self) -> StateOperation { + self.inner.operation.into() + } + + pub fn into_inner(self) -> DbStateOpLogEntry { + self.inner + } +} + +impl From for StateOpLogEntry { + fn from(inner: DbStateOpLogEntry) -> Self { + Self { inner } + } +} + +#[derive(Debug, Clone, Copy)] +pub enum StateOperation { + Set, + Delete, +} + +impl StateOperation { + pub fn as_op_str(&self) -> &str { + use StateOperation::{Delete, Set}; + match self { + Set => "S", + Delete => "D", + } + } +} + +impl From for StateOperation { + fn from(op: DbStateOperation) -> Self { + match op { + DbStateOperation::Set => StateOperation::Set, + DbStateOperation::Delete => StateOperation::Delete, + } + } +} diff --git a/dan_layer/engine/src/state/models/schema_state.rs b/dan_layer/engine/src/state/models/schema_state.rs new file mode 100644 index 0000000000..b5ed83d11c --- /dev/null +++ b/dan_layer/engine/src/state/models/schema_state.rs @@ -0,0 +1,23 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use serde::{Deserialize, Serialize}; + +use crate::state::models::KeyValue; + +#[derive(Serialize, Deserialize, Default, Clone, Debug)] +pub struct SchemaState { + pub name: String, + pub items: Vec, +} + +impl SchemaState { + pub fn new(name: String, items: Vec) -> Self { + Self { name, items } + } + + pub fn push_key_value(&mut self, key_value: KeyValue) -> &mut Self { + self.items.push(key_value); + self + } +} diff --git a/dan_layer/engine/src/state/models/state_root.rs b/dan_layer/engine/src/state/models/state_root.rs new file mode 100644 index 0000000000..fb1d1efff7 --- /dev/null +++ b/dan_layer/engine/src/state/models/state_root.rs @@ -0,0 +1,25 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use tari_common_types::types::FixedHash; + +#[derive(PartialEq, Eq, Debug, Clone)] +pub struct StateRoot { + root: FixedHash, +} + +impl StateRoot { + pub fn new(root: FixedHash) -> Self { + Self { root } + } + + pub fn as_bytes(&self) -> &[u8] { + self.root.as_slice() + } + + pub fn initial() -> Self { + Self { + root: FixedHash::zero(), + } + } +} diff --git a/dan_layer/engine/src/state/state_db.rs b/dan_layer/engine/src/state/state_db.rs new file mode 100644 index 0000000000..7fa683888a --- /dev/null +++ b/dan_layer/engine/src/state/state_db.rs @@ -0,0 +1,39 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use tari_common_types::types::FixedHash; + +use crate::state::{ + state_db_unit_of_work::{StateDbUnitOfWorkImpl, StateDbUnitOfWorkReader, UnitOfWorkContext}, + StateDbBackendAdapter, +}; + +pub struct StateDb { + backend_adapter: TStateDbBackendAdapter, + contract_id: FixedHash, +} + +impl StateDb { + pub fn new(contract_id: FixedHash, backend_adapter: TStateDbBackendAdapter) -> Self { + Self { + backend_adapter, + contract_id, + } + } + + pub fn new_unit_of_work(&self, height: u64) -> StateDbUnitOfWorkImpl { + StateDbUnitOfWorkImpl::new( + UnitOfWorkContext::new(height, self.contract_id), + self.backend_adapter.clone(), + ) + } + + pub fn reader(&self) -> impl StateDbUnitOfWorkReader { + // TODO: A reader doesnt need the current context, should perhaps make a read-only implementation that the + // writable implementation also uses + StateDbUnitOfWorkImpl::new( + UnitOfWorkContext::new(0, self.contract_id), + self.backend_adapter.clone(), + ) + } +} diff --git a/dan_layer/engine/src/state/state_db_backend_adapter.rs b/dan_layer/engine/src/state/state_db_backend_adapter.rs new file mode 100644 index 0000000000..c25eea837d --- /dev/null +++ b/dan_layer/engine/src/state/state_db_backend_adapter.rs @@ -0,0 +1,35 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use crate::state::{db_key_value::DbKeyValue, error::StateStorageError, DbStateOpLogEntry}; + +pub trait StateDbBackendAdapter: Send + Sync + Clone { + type BackendTransaction; + type Error: Into; + + fn create_transaction(&self) -> Result; + fn update_key_value( + &self, + schema: &str, + key: &[u8], + value: &[u8], + tx: &Self::BackendTransaction, + ) -> Result<(), Self::Error>; + fn get(&self, schema: &str, key: &[u8]) -> Result>, Self::Error>; + fn find_keys_by_value(&self, schema: &str, value: &[u8]) -> Result>, Self::Error>; + fn commit(&self, tx: &Self::BackendTransaction) -> Result<(), Self::Error>; + fn get_all_schemas(&self, tx: &Self::BackendTransaction) -> Result, Self::Error>; + fn get_all_values_for_schema( + &self, + schema: &str, + tx: &Self::BackendTransaction, + ) -> Result, Self::Error>; + fn get_state_op_logs_by_height( + &self, + height: u64, + tx: &Self::BackendTransaction, + ) -> Result, Self::Error>; + fn add_state_oplog_entry(&self, entry: DbStateOpLogEntry, tx: &Self::BackendTransaction) + -> Result<(), Self::Error>; + fn clear_all_state(&self, tx: &Self::BackendTransaction) -> Result<(), Self::Error>; +} diff --git a/dan_layer/core/src/storage/state/state_db_unit_of_work.rs b/dan_layer/engine/src/state/state_db_unit_of_work.rs similarity index 79% rename from dan_layer/core/src/storage/state/state_db_unit_of_work.rs rename to dan_layer/engine/src/state/state_db_unit_of_work.rs index 408d24ccea..c4f0c4a86a 100644 --- a/dan_layer/core/src/storage/state/state_db_unit_of_work.rs +++ b/dan_layer/engine/src/state/state_db_unit_of_work.rs @@ -1,24 +1,5 @@ -// Copyright 2021. The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause use std::{ convert::TryInto, @@ -30,35 +11,35 @@ use digest::Digest; use log::*; use tari_common_types::types::{FixedHash, HashDigest}; use tari_crypto::common::Blake256; +use tari_dan_common_types::storage::UnitOfWorkTracker; use tari_mmr::{MemBackendVec, MerkleMountainRange}; use tari_utilities::hex::Hex; -use crate::{ +use crate::state::{ + db_key_value::DbKeyValue, + error::StateStorageError, models::{KeyValue, SchemaState, StateOpLogEntry, StateRoot}, - storage::{ - state::{db_key_value::DbKeyValue, DbStateOpLogEntry, StateDbBackendAdapter}, - StorageError, - UnitOfWorkTracker, - }, + DbStateOpLogEntry, + StateDbBackendAdapter, }; const LOG_TARGET: &str = "tari::dan::state_db"; pub trait StateDbUnitOfWork: StateDbUnitOfWorkReader { - fn set_value(&mut self, schema: String, key: Vec, value: Vec) -> Result<(), StorageError>; - fn set_u64(&mut self, schema: &str, key: &[u8], value: u64) -> Result<(), StorageError>; - fn commit(&mut self) -> Result<(), StorageError>; - fn clear_all_state(&self) -> Result<(), StorageError>; + fn set_value(&mut self, schema: String, key: Vec, value: Vec) -> Result<(), StateStorageError>; + fn set_u64(&mut self, schema: &str, key: &[u8], value: u64) -> Result<(), StateStorageError>; + fn commit(&mut self) -> Result<(), StateStorageError>; + fn clear_all_state(&self) -> Result<(), StateStorageError>; } pub trait StateDbUnitOfWorkReader: Clone + Send + Sync { fn context(&self) -> &UnitOfWorkContext; - fn get_value(&self, schema: &str, key: &[u8]) -> Result>, StorageError>; - fn get_u64(&self, schema: &str, key: &[u8]) -> Result, StorageError>; - fn find_keys_by_value(&self, schema: &str, value: &[u8]) -> Result>, StorageError>; - fn calculate_root(&self) -> Result; - fn get_all_state(&self) -> Result, StorageError>; - fn get_op_logs_for_height(&self, height: u64) -> Result, StorageError>; + fn get_value(&self, schema: &str, key: &[u8]) -> Result>, StateStorageError>; + fn get_u64(&self, schema: &str, key: &[u8]) -> Result, StateStorageError>; + fn find_keys_by_value(&self, schema: &str, value: &[u8]) -> Result>, StateStorageError>; + fn calculate_root(&self) -> Result; + fn get_all_state(&self) -> Result, StateStorageError>; + fn get_op_logs_for_height(&self, height: u64) -> Result, StateStorageError>; } #[derive(Debug, Clone)] @@ -105,7 +86,7 @@ impl Clone for StateDbUnitOfWorkImpl StateDbUnitOfWork for StateDbUnitOfWorkImpl { - fn set_value(&mut self, schema: String, key: Vec, value: Vec) -> Result<(), StorageError> { + fn set_value(&mut self, schema: String, key: Vec, value: Vec) -> Result<(), StateStorageError> { let mut inner = self.inner.write()?; inner .updates @@ -114,11 +95,11 @@ impl StateDbUnitOfWork for StateDbUnitOf Ok(()) } - fn set_u64(&mut self, schema: &str, key: &[u8], value: u64) -> Result<(), StorageError> { + fn set_u64(&mut self, schema: &str, key: &[u8], value: u64) -> Result<(), StateStorageError> { self.set_value(schema.to_string(), Vec::from(key), Vec::from(value.to_le_bytes())) } - fn commit(&mut self) -> Result<(), StorageError> { + fn commit(&mut self) -> Result<(), StateStorageError> { let mut inner = self.inner.write()?; let tx = inner .backend_adapter @@ -163,7 +144,7 @@ impl StateDbUnitOfWork for StateDbUnitOf /// Clears the state db immediately (before commit) - this will not be needed in future when build up the state from /// instructions/op logs - fn clear_all_state(&self) -> Result<(), StorageError> { + fn clear_all_state(&self) -> Result<(), StateStorageError> { let inner = self.inner.write()?; let tx = inner .backend_adapter @@ -181,7 +162,7 @@ impl StateDbUnitOfWorkReader for StateDb &self.context } - fn get_value(&self, schema: &str, key: &[u8]) -> Result>, StorageError> { + fn get_value(&self, schema: &str, key: &[u8]) -> Result>, StateStorageError> { let inner = self.inner.read()?; // Hit the DB. inner @@ -190,7 +171,7 @@ impl StateDbUnitOfWorkReader for StateDb .map_err(TBackendAdapter::Error::into) } - fn get_u64(&self, schema: &str, key: &[u8]) -> Result, StorageError> { + fn get_u64(&self, schema: &str, key: &[u8]) -> Result, StateStorageError> { let data = self.get_value(schema, key)?; match data { Some(data) => { @@ -202,7 +183,7 @@ impl StateDbUnitOfWorkReader for StateDb } } - fn find_keys_by_value(&self, schema: &str, value: &[u8]) -> Result>, StorageError> { + fn find_keys_by_value(&self, schema: &str, value: &[u8]) -> Result>, StateStorageError> { let inner = self.inner.read()?; inner .backend_adapter @@ -210,7 +191,7 @@ impl StateDbUnitOfWorkReader for StateDb .map_err(TBackendAdapter::Error::into) } - fn calculate_root(&self) -> Result { + fn calculate_root(&self) -> Result { let inner = self.inner.read()?; let tx = inner .backend_adapter @@ -263,7 +244,7 @@ impl StateDbUnitOfWorkReader for StateDb )) } - fn get_all_state(&self) -> Result, StorageError> { + fn get_all_state(&self) -> Result, StateStorageError> { let inner = self.inner.read()?; let tx = inner .backend_adapter @@ -294,7 +275,7 @@ impl StateDbUnitOfWorkReader for StateDb Ok(schema_state) } - fn get_op_logs_for_height(&self, height: u64) -> Result, StorageError> { + fn get_op_logs_for_height(&self, height: u64) -> Result, StateStorageError> { let inner = self.inner.read()?; let tx = inner .backend_adapter diff --git a/dan_layer/engine/src/state/state_op_log.rs b/dan_layer/engine/src/state/state_op_log.rs new file mode 100644 index 0000000000..764fba8f41 --- /dev/null +++ b/dan_layer/engine/src/state/state_op_log.rs @@ -0,0 +1,60 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use std::str::FromStr; + +use tari_common_types::types::FixedHash; + +use crate::state::DbKeyValue; + +#[derive(Debug)] +pub struct DbStateOpLogEntry { + pub height: u64, + pub merkle_root: Option, + pub operation: DbStateOperation, + pub schema: String, + pub key: Vec, + pub value: Option>, +} + +impl DbStateOpLogEntry { + pub fn set_operation(height: u64, key_value: DbKeyValue) -> Self { + Self { + height, + merkle_root: None, + operation: DbStateOperation::Set, + schema: key_value.schema, + key: key_value.key, + value: Some(key_value.value), + } + } +} + +#[derive(Debug, Clone, Copy)] +pub enum DbStateOperation { + Set, + Delete, +} + +impl DbStateOperation { + pub fn as_op_str(&self) -> &str { + use DbStateOperation::{Delete, Set}; + match self { + Set => "S", + Delete => "D", + } + } +} + +impl FromStr for DbStateOperation { + type Err = (); + + fn from_str(s: &str) -> Result { + use DbStateOperation::{Delete, Set}; + match s { + "S" => Ok(Set), + "D" => Ok(Delete), + _ => Err(()), + } + } +} diff --git a/dan_layer/engine/src/wasm/error.rs b/dan_layer/engine/src/wasm/error.rs new file mode 100644 index 0000000000..b7f3cd3cb7 --- /dev/null +++ b/dan_layer/engine/src/wasm/error.rs @@ -0,0 +1,10 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum WasmError { + #[error("Missing argument at position {position} (name: {argument_name}")] + MissingArgument { argument_name: String, position: usize }, +} diff --git a/dan_layer/engine/src/wasm/mod.rs b/dan_layer/engine/src/wasm/mod.rs new file mode 100644 index 0000000000..d884d88abc --- /dev/null +++ b/dan_layer/engine/src/wasm/mod.rs @@ -0,0 +1,10 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +mod error; +mod wasm_module_definition; +mod wasm_module_factory; + +pub use error::WasmError; +pub use wasm_module_definition::WasmModuleDefinition; +pub use wasm_module_factory::WasmModuleFactory; diff --git a/dan_layer/engine/src/wasm/wasm_module_definition.rs b/dan_layer/engine/src/wasm/wasm_module_definition.rs new file mode 100644 index 0000000000..1750e88dd0 --- /dev/null +++ b/dan_layer/engine/src/wasm/wasm_module_definition.rs @@ -0,0 +1,12 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use std::path::PathBuf; + +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Default, Clone, Debug)] +pub struct WasmModuleDefinition { + pub name: String, + pub path: PathBuf, +} diff --git a/dan_layer/engine/src/wasm/wasm_module_factory.rs b/dan_layer/engine/src/wasm/wasm_module_factory.rs new file mode 100644 index 0000000000..92d17745d2 --- /dev/null +++ b/dan_layer/engine/src/wasm/wasm_module_factory.rs @@ -0,0 +1,148 @@ +// Copyright 2022 The Tari Project +// SPDX-License-Identifier: BSD-3-Clause + +use std::{collections::HashMap, fs}; + +use wasmer::{imports, Instance, Module, Store, Val, Value}; + +use crate::{ + function_definitions::{ArgType, WasmFunctionDefinition}, + instructions::Instruction, + state::StateDbUnitOfWork, + wasm::{WasmError, WasmModuleDefinition}, +}; + +#[derive(Clone, Default)] +pub struct WasmModuleFactory { + modules: HashMap, + functions: HashMap, String)>, +} + +impl WasmModuleFactory { + pub fn new(wasm_modules: &[WasmModuleDefinition], wasm_functions: &[WasmFunctionDefinition]) -> Self { + let mut modules = HashMap::new(); + for mod_def in wasm_modules { + let store = Store::default(); + let file = fs::read(&mod_def.path).expect("could not read all bytes"); + let module = Module::new(&store, file).expect("Did not compile"); + let import_object = imports! {}; // <- SDK for interacting with block chain + let _declared_imps: Vec<_> = module.imports().functions().collect(); + // TODO: Does wasm code auto run at this point + let instance = Instance::new(&module, &import_object).expect("Could not create instance"); + modules.insert(mod_def.name.clone(), instance); + } + let mut functions = HashMap::new(); + for func_def in wasm_functions { + if let Some(instance) = modules.get(&func_def.in_module) { + // check that imported function is actually present in wasm + let _function = instance.exports.get_function(&func_def.name).unwrap(); + + functions.insert( + func_def.name.clone(), + ( + func_def.args.iter().map(|at| at.arg_type.clone()).collect(), + func_def.in_module.clone(), + ), + ); + } else { + panic!("module {} does not exist", func_def.in_module) + } + } + Self { modules, functions } + } + + pub fn invoke_write_method( + &self, + name: String, + instruction: &Instruction, + state_db: TUnitOfWork, + ) -> Result { + // TODO: We should probably create a new instance each time, so that + // there's no stale memory + if let Some((arg_types, module_name)) = self.functions.get(&name) { + if let Some(instance) = self.modules.get(module_name) { + let func_pointer = instance.exports.get_function(&name).expect("Could not find function"); + let _type_params = func_pointer.ty().params(); + let _remaining_args = Vec::from(instruction.args()); + // dbg!(&remaining_args); + // let memory = instance.get_memory("mem"); + let _offset = 0; + // TODO: better iteration + let mut remaining_instruction_args = Vec::from(instruction.args()); + let args: Vec> = arg_types + .iter() + .enumerate() + .map(|(position, param)| { + match param { + ArgType::String => { + // if remaining_args.len() < 3 { + // return Err(DigitalAssetError::MissingArgument { + // position, + // argument_name: "Wasm string".to_string(), + // }); + // } + // + // let len = remaining_instruction_args.pop().expect("can't take length") as usize; + // let instruction_arg = + // String::from_utf8(remaining_instruction_args.drain(len)).expect("invalid utf8"); + // let ptr = WasmPtr::::new(offset); + // let derefed = ptr.deref(&memory).expect("could not get derefed pointer"); + // derefed.set(instruction_arg); + // + // Ok(vec![Value::I32()]) + todo!() + }, + ArgType::Byte => { + if remaining_instruction_args.is_empty() { + return Err(WasmError::MissingArgument { + position, + argument_name: "Wasm byte".to_string(), + }); + } + let byte = remaining_instruction_args.pop().expect("not enough length"); + Ok(vec![Value::I32(i32::from(byte))]) + }, + ArgType::PublicKey => { + if remaining_instruction_args.len() < 32 { + return Err(WasmError::MissingArgument { + position, + argument_name: "Wasm public key".to_string(), + }); + } + let bytes: Vec = remaining_instruction_args.drain(..32).collect(); + let mut result = Vec::with_capacity(8); + for i in 0..8 { + let mut data = [0u8; 4]; + data.copy_from_slice(&bytes[i * 4..i * 4 + 4]); + result.push(Value::I32(i32::from_le_bytes(data))); + } + // write as 8 * bytes + Ok(result) + }, + // F32, + // F64, + // V128, + // ExternRef, + // FuncRef, + _ => { + todo!() + }, + } + }) + .collect::>()?; + + let args: Vec = args.into_iter().flatten().collect(); + let _result = func_pointer.call(args.as_slice()).expect("invokation error"); + Ok(state_db) + } else { + todo!("No module found") + } + } else { + todo!("function not found") + } + // let store = Store::default(); + // let module = Module::new(&store, wat_file.as_str()); + // let import_object = imports! {}; + // let instance = Instance::new(&module, &import_object)?; + } +} diff --git a/dan_layer/storage_sqlite/Cargo.toml b/dan_layer/storage_sqlite/Cargo.toml index adeeefa6e2..0eb363fc10 100644 --- a/dan_layer/storage_sqlite/Cargo.toml +++ b/dan_layer/storage_sqlite/Cargo.toml @@ -9,7 +9,7 @@ tari_dan_core = {path="../core"} tari_common = { path = "../../common"} tari_common_types = {path = "../../base_layer/common_types"} tari_utilities = { git = "https://github.com/tari-project/tari_utilities.git", tag = "v0.4.4" } - +tari_dan_engine = { path = "../engine"} diesel = { version = "1.4.8", features = ["sqlite"] } diesel_migrations = "1.4.0" @@ -18,5 +18,3 @@ async-trait = "0.1.50" tokio = { version="1.10", features = ["macros", "time"]} tokio-stream = { version = "0.1.7", features = ["sync"] } log = { version = "0.4.8", features = ["std"] } -patricia_tree = { version = "0.3.0", features = ["binary-format"] } -bytecodec = { version = "0.4.14", features = ["bincode_codec"] } diff --git a/dan_layer/storage_sqlite/src/error.rs b/dan_layer/storage_sqlite/src/error.rs index 42c864c458..fc07993ddd 100644 --- a/dan_layer/storage_sqlite/src/error.rs +++ b/dan_layer/storage_sqlite/src/error.rs @@ -22,6 +22,7 @@ use diesel; use tari_common_types::types::FixedHashSizeError; use tari_dan_core::{models::ModelError, storage::StorageError}; +use tari_dan_engine::state::error::StateStorageError; use thiserror::Error; #[derive(Debug, Error)] @@ -41,14 +42,14 @@ pub enum SqliteStorageError { #[from] source: diesel_migrations::RunMigrationsError, }, - #[error("Error decoding bytes:{0}")] - DecodeError(#[from] bytecodec::Error), #[error("Encountered malformed hash data")] MalformedHashData, #[error("Malformed DB data: {0}")] MalformedDbData(String), #[error(transparent)] ModelError(#[from] ModelError), + #[error("Conversion error:{reason}")] + ConversionError { reason: String }, } impl From for StorageError { @@ -63,7 +64,6 @@ impl From for StorageError { SqliteStorageError::MigrationError { .. } => StorageError::MigrationError { reason: source.to_string(), }, - SqliteStorageError::DecodeError(e) => StorageError::DecodeError(e), other => StorageError::General { details: other.to_string(), }, @@ -71,6 +71,25 @@ impl From for StorageError { } } +impl From for StateStorageError { + fn from(source: SqliteStorageError) -> Self { + match source { + SqliteStorageError::ConnectionError { .. } => StateStorageError::ConnectionError { + reason: source.to_string(), + }, + SqliteStorageError::DieselError { .. } => StateStorageError::QueryError { + reason: source.to_string(), + }, + SqliteStorageError::MigrationError { .. } => StateStorageError::MigrationError { + reason: source.to_string(), + }, + other => StateStorageError::General { + details: other.to_string(), + }, + } + } +} + impl From for SqliteStorageError { fn from(_: FixedHashSizeError) -> Self { SqliteStorageError::MalformedHashData diff --git a/dan_layer/storage_sqlite/src/models/instruction.rs b/dan_layer/storage_sqlite/src/models/instruction.rs index d9909b8c1f..173688e001 100644 --- a/dan_layer/storage_sqlite/src/models/instruction.rs +++ b/dan_layer/storage_sqlite/src/models/instruction.rs @@ -39,11 +39,14 @@ pub struct Instruction { pub sender: Vec, } -impl TryFrom for tari_dan_core::models::Instruction { +impl TryFrom for tari_dan_engine::instructions::Instruction { type Error = SqliteStorageError; fn try_from(instruction: Instruction) -> Result { - let template_id = instruction.template_id.try_into()?; + let template_id = instruction + .template_id + .try_into() + .map_err(|s| SqliteStorageError::ConversionError { reason: s })?; Ok(Self::new( template_id, instruction.method, diff --git a/dan_layer/storage_sqlite/src/models/mod.rs b/dan_layer/storage_sqlite/src/models/mod.rs index 00613a6de0..bc30cc1599 100644 --- a/dan_layer/storage_sqlite/src/models/mod.rs +++ b/dan_layer/storage_sqlite/src/models/mod.rs @@ -26,4 +26,3 @@ pub mod node; pub mod prepare_qc; pub mod state_key; pub mod state_op_log; -pub mod state_tree; diff --git a/dan_layer/storage_sqlite/src/models/state_op_log.rs b/dan_layer/storage_sqlite/src/models/state_op_log.rs index 5d21f3670e..4ebbb358ff 100644 --- a/dan_layer/storage_sqlite/src/models/state_op_log.rs +++ b/dan_layer/storage_sqlite/src/models/state_op_log.rs @@ -1,6 +1,8 @@ use std::convert::TryFrom; -use tari_dan_core::models::TreeNodeHash; +use tari_common_types::types::FixedHash; +use tari_dan_engine::state::DbStateOpLogEntry; + // Copyright 2022, The Tari Project // // Redistribution and use in source and binary forms, with or without modification, are permitted provided that @@ -23,8 +25,6 @@ use tari_dan_core::models::TreeNodeHash; // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. -use tari_dan_core::storage::state::DbStateOpLogEntry; - use crate::{error::SqliteStorageError, schema::*}; #[derive(Debug, Clone, Identifiable, Queryable)] @@ -55,7 +55,7 @@ impl From for NewStateOpLogEntry { fn from(entry: DbStateOpLogEntry) -> Self { Self { height: entry.height as i64, - merkle_root: entry.merkle_root.map(|r| r.as_bytes().to_vec()), + merkle_root: entry.merkle_root.map(|r| r.to_vec()), operation: entry.operation.as_op_str().to_string(), schema: entry.schema, key: entry.key, @@ -73,13 +73,15 @@ impl TryFrom for DbStateOpLogEntry { height: entry.height as u64, merkle_root: entry .merkle_root - .map(TreeNodeHash::try_from) + .map(FixedHash::try_from) .transpose() .map_err(|_| SqliteStorageError::MalformedHashData)?, operation: entry .operation .parse() - .map_err(|_| SqliteStorageError::MalformedDbData("Invalid OpLog operation".to_string()))?, + .map_err(|_| SqliteStorageError::ConversionError { + reason: "Invalid OpLog operation".to_string(), + })?, schema: entry.schema, key: entry.key, value: entry.value, diff --git a/dan_layer/storage_sqlite/src/models/state_tree.rs b/dan_layer/storage_sqlite/src/models/state_tree.rs deleted file mode 100644 index 3654df2ca5..0000000000 --- a/dan_layer/storage_sqlite/src/models/state_tree.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2021. The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -use crate::schema::*; -#[derive(Queryable)] -pub(crate) struct StateTree { - pub _id: i32, - pub version: i32, - pub _is_current: bool, - pub data: Vec, -} - -#[derive(Insertable)] -#[table_name = "state_tree"] -pub(crate) struct NewStateTree { - pub version: i32, - pub is_current: bool, - pub data: Vec, -} diff --git a/dan_layer/storage_sqlite/src/sqlite_db_factory.rs b/dan_layer/storage_sqlite/src/sqlite_db_factory.rs index 6c1c823eb6..7ede7674a6 100644 --- a/dan_layer/storage_sqlite/src/sqlite_db_factory.rs +++ b/dan_layer/storage_sqlite/src/sqlite_db_factory.rs @@ -26,7 +26,8 @@ use diesel::{Connection, ConnectionError, SqliteConnection}; use diesel_migrations::embed_migrations; use log::*; use tari_common_types::types::FixedHash; -use tari_dan_core::storage::{chain::ChainDb, global::GlobalDb, state::StateDb, DbFactory, StorageError}; +use tari_dan_core::storage::{chain::ChainDb, global::GlobalDb, DbFactory, StorageError}; +use tari_dan_engine::state::StateDb; use tari_utilities::hex::Hex; use crate::{ diff --git a/dan_layer/storage_sqlite/src/sqlite_state_db_backend_adapter.rs b/dan_layer/storage_sqlite/src/sqlite_state_db_backend_adapter.rs index bd4db62c84..879fc499cb 100644 --- a/dan_layer/storage_sqlite/src/sqlite_state_db_backend_adapter.rs +++ b/dan_layer/storage_sqlite/src/sqlite_state_db_backend_adapter.rs @@ -22,25 +22,15 @@ use std::convert::TryInto; -use bytecodec::{ - bincode_codec::{BincodeDecoder, BincodeEncoder}, - DecodeExt, - EncodeExt, -}; use diesel::{prelude::*, Connection, SqliteConnection}; use log::*; -use patricia_tree::{ - node::{Node, NodeDecoder, NodeEncoder}, - PatriciaMap, -}; -use tari_dan_core::storage::state::{DbKeyValue, DbStateOpLogEntry, StateDbBackendAdapter}; +use tari_dan_engine::state::{DbKeyValue, DbStateOpLogEntry, StateDbBackendAdapter}; use crate::{ error::SqliteStorageError, models::{ state_key::StateKey, state_op_log::{NewStateOpLogEntry, StateOpLogEntry}, - state_tree::{NewStateTree, StateTree}, }, schema::*, SqliteTransaction, @@ -161,70 +151,6 @@ impl StateDbBackendAdapter for SqliteStateDbBackendAdapter { Ok(()) } - fn get_current_state_tree(&self, tx: &Self::BackendTransaction) -> Result>, Self::Error> { - use crate::schema::state_tree::dsl; - let row: Option = dsl::state_tree - .filter(state_tree::is_current.eq(true)) - .order_by(state_tree::version.desc()) - .first(tx.connection()) - .optional() - .map_err(|source| SqliteStorageError::DieselError { - source, - operation: "get_current_state_tree".to_string(), - })?; - if let Some(row) = row { - let mut decoder = NodeDecoder::new(BincodeDecoder::new()); - let nodes: Node> = decoder.decode_from_bytes(&row.data)?; - Ok(nodes.into()) - } else { - Ok(PatriciaMap::new()) - } - } - - fn set_current_state_tree( - &self, - tree: patricia_tree::map::PatriciaMap>, - tx: &Self::BackendTransaction, - ) -> Result<(), Self::Error> { - let mut encoder = NodeEncoder::new(BincodeEncoder::new()); - let encoded = encoder.encode_into_bytes(tree.into())?; - - use crate::schema::state_tree::dsl; - let existing_row: Option = dsl::state_tree - .filter(state_tree::is_current.eq(true)) - .order_by(state_tree::version.desc()) - .first(tx.connection()) - .optional() - .map_err(|source| SqliteStorageError::DieselError { - source, - operation: "set_current_state_tree::fetch".to_string(), - })?; - - diesel::update(dsl::state_tree.filter(state_tree::is_current.eq(true))) - .set(state_tree::is_current.eq(false)) - .execute(tx.connection()) - .map_err(|source| SqliteStorageError::DieselError { - source, - operation: "set_current_state_tree:update".to_string(), - })?; - - let row = NewStateTree { - version: existing_row.map(|r| r.version).unwrap_or_default() + 1, - is_current: true, - data: encoded, - }; - - diesel::insert_into(dsl::state_tree) - .values(row) - .execute(tx.connection()) - .map_err(|source| SqliteStorageError::DieselError { - source, - operation: "set_current_state_tree::insert".to_string(), - })?; - - Ok(()) - } - fn get_all_schemas(&self, tx: &Self::BackendTransaction) -> Result, Self::Error> { use crate::schema::state_keys::dsl; let schemas: Vec = dsl::state_keys