mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-02 13:23:10 +00:00
Merge pull request #99 from vacp2p/Pravdyvy/node-wallet-rewrite
Data storage removal and node refactor.
This commit is contained in:
commit
4581dcc1d1
309
Cargo.lock
generated
309
Cargo.lock
generated
@ -365,6 +365,56 @@ version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"
|
||||
dependencies = [
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.98"
|
||||
@ -627,17 +677,6 @@ dependencies = [
|
||||
"critical-section",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi 0.1.19",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "auto_ops"
|
||||
version = "0.3.0"
|
||||
@ -961,42 +1000,43 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.2.25"
|
||||
version = "4.5.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
|
||||
checksum = "ed87a9d530bb41a67537289bafcac159cb3ee28460e0a4571123d2a778a6a882"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags 1.3.2",
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64f4f3f3c77c94aff3c7e9aac9a2ca1974a5adf392a8bb751e827d6d127ab966"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"indexmap 1.9.3",
|
||||
"once_cell",
|
||||
"strsim 0.10.0",
|
||||
"termcolor",
|
||||
"textwrap",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.2.25"
|
||||
version = "4.5.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008"
|
||||
checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
|
||||
dependencies = [
|
||||
"heck 0.4.1",
|
||||
"proc-macro-error",
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.2.4"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
|
||||
|
||||
[[package]]
|
||||
name = "cobs"
|
||||
@ -1007,6 +1047,12 @@ dependencies = [
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
|
||||
[[package]]
|
||||
name = "common"
|
||||
version = "0.1.0"
|
||||
@ -1016,6 +1062,7 @@ dependencies = [
|
||||
"hex",
|
||||
"k256",
|
||||
"log",
|
||||
"rand 0.8.5",
|
||||
"reqwest 0.11.27",
|
||||
"risc0-zkvm",
|
||||
"rs_merkle",
|
||||
@ -1026,19 +1073,6 @@ dependencies = [
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "consensus"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"env_logger",
|
||||
"log",
|
||||
"networking",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.9.6"
|
||||
@ -1249,7 +1283,7 @@ dependencies = [
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim 0.11.1",
|
||||
"strsim",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
@ -1939,7 +1973,7 @@ dependencies = [
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"http 0.2.12",
|
||||
"indexmap 2.10.0",
|
||||
"indexmap",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
@ -2017,15 +2051,6 @@ version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.5.2"
|
||||
@ -2352,16 +2377,6 @@ version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ee796ad498c8d9a1d68e477df8f754ed784ef875de1414ebdaf169f70a6a784"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.10.0"
|
||||
@ -2394,9 +2409,6 @@ dependencies = [
|
||||
"env_logger",
|
||||
"hex",
|
||||
"log",
|
||||
"node_core",
|
||||
"node_rpc",
|
||||
"node_runner",
|
||||
"sequencer_core",
|
||||
"sequencer_rpc",
|
||||
"sequencer_runner",
|
||||
@ -2405,6 +2417,7 @@ dependencies = [
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"toml 0.7.8",
|
||||
"wallet",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2449,11 +2462,17 @@ version = "0.4.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
|
||||
dependencies = [
|
||||
"hermit-abi 0.5.2",
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
@ -2943,105 +2962,12 @@ dependencies = [
|
||||
"rayon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "networking"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"env_logger",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "no_std_strings"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5b0c77c1b780822bc749a33e39aeb2c07584ab93332303babeabb645298a76e"
|
||||
|
||||
[[package]]
|
||||
name = "node_core"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"accounts",
|
||||
"actix-rt",
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"common",
|
||||
"elliptic-curve",
|
||||
"env_logger",
|
||||
"hex",
|
||||
"k256",
|
||||
"log",
|
||||
"rand 0.8.5",
|
||||
"reqwest 0.11.27",
|
||||
"risc0-zkvm",
|
||||
"sc_core",
|
||||
"secp256k1-zkp",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"storage",
|
||||
"tempfile",
|
||||
"thiserror 1.0.69",
|
||||
"tokio",
|
||||
"utxo",
|
||||
"zkvm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "node_rpc"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"accounts",
|
||||
"actix",
|
||||
"actix-cors",
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
"common",
|
||||
"consensus",
|
||||
"env_logger",
|
||||
"futures",
|
||||
"hex",
|
||||
"log",
|
||||
"networking",
|
||||
"node_core",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"storage",
|
||||
"tokio",
|
||||
"utxo",
|
||||
"vm",
|
||||
"zkvm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "node_runner"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"accounts",
|
||||
"actix",
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
"clap",
|
||||
"common",
|
||||
"consensus",
|
||||
"env_logger",
|
||||
"hex",
|
||||
"log",
|
||||
"networking",
|
||||
"node_core",
|
||||
"node_rpc",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"storage",
|
||||
"tokio",
|
||||
"utxo",
|
||||
"vm",
|
||||
"zkvm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
@ -3162,6 +3088,12 @@ version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.3.1"
|
||||
@ -3218,12 +3150,6 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.4"
|
||||
@ -4429,13 +4355,11 @@ dependencies = [
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
"common",
|
||||
"consensus",
|
||||
"env_logger",
|
||||
"futures",
|
||||
"hex",
|
||||
"log",
|
||||
"mempool",
|
||||
"networking",
|
||||
"sequencer_core",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -4453,11 +4377,9 @@ dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"common",
|
||||
"consensus",
|
||||
"env_logger",
|
||||
"log",
|
||||
"mempool",
|
||||
"networking",
|
||||
"sequencer_core",
|
||||
"sequencer_rpc",
|
||||
"serde",
|
||||
@ -4691,12 +4613,6 @@ dependencies = [
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
@ -4835,12 +4751,6 @@ dependencies = [
|
||||
"risc0-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.16.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
@ -5037,7 +4947,7 @@ version = "0.19.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
||||
dependencies = [
|
||||
"indexmap 2.10.0",
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
@ -5050,7 +4960,7 @@ version = "0.22.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
|
||||
dependencies = [
|
||||
"indexmap 2.10.0",
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
@ -5248,6 +5158,12 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "utxo"
|
||||
version = "0.1.0"
|
||||
@ -5294,14 +5210,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "vm"
|
||||
name = "wallet"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"accounts",
|
||||
"actix-rt",
|
||||
"anyhow",
|
||||
"bincode",
|
||||
"clap",
|
||||
"common",
|
||||
"elliptic-curve",
|
||||
"env_logger",
|
||||
"hex",
|
||||
"k256",
|
||||
"log",
|
||||
"rand 0.8.5",
|
||||
"reqwest 0.11.27",
|
||||
"risc0-zkvm",
|
||||
"sc_core",
|
||||
"secp256k1-zkp",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"tempfile",
|
||||
"thiserror 1.0.69",
|
||||
"tokio",
|
||||
"utxo",
|
||||
"zkvm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5913,7 +5848,7 @@ dependencies = [
|
||||
"crossbeam-utils",
|
||||
"displaydoc",
|
||||
"flate2",
|
||||
"indexmap 2.10.0",
|
||||
"indexmap",
|
||||
"memchr",
|
||||
"thiserror 2.0.12",
|
||||
"zopfli",
|
||||
|
||||
@ -1,19 +1,14 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = [
|
||||
"node_runner",
|
||||
"sequencer_runner",
|
||||
"storage",
|
||||
"accounts",
|
||||
"utxo",
|
||||
"vm",
|
||||
"networking",
|
||||
"consensus",
|
||||
"node_rpc",
|
||||
"sequencer_rpc",
|
||||
"mempool",
|
||||
"zkvm",
|
||||
"node_core",
|
||||
"wallet",
|
||||
"sequencer_core",
|
||||
"common",
|
||||
"sc_core",
|
||||
@ -75,7 +70,7 @@ version = "=4.1.0"
|
||||
|
||||
[workspace.dependencies.clap]
|
||||
features = ["derive", "env"]
|
||||
version = "3.1.6"
|
||||
version = "4.5.42"
|
||||
|
||||
[workspace.dependencies.tokio-retry]
|
||||
version = "0.3.0"
|
||||
|
||||
@ -6,4 +6,5 @@ source env.sh
|
||||
|
||||
cargo test --release
|
||||
cd integration_tests
|
||||
export NSSA_WALLET_HOME_DIR=$(pwd)/configs/debug/wallet/
|
||||
cargo run $(pwd)/configs/debug all
|
||||
@ -11,6 +11,7 @@ serde.workspace = true
|
||||
reqwest.workspace = true
|
||||
risc0-zkvm = { git = "https://github.com/risc0/risc0.git", branch = "release-2.3" }
|
||||
k256.workspace = true
|
||||
rand.workspace = true
|
||||
|
||||
rs_merkle.workspace = true
|
||||
sha2.workspace = true
|
||||
|
||||
@ -26,19 +26,19 @@ pub struct HashableBlockData {
|
||||
pub data: Data,
|
||||
}
|
||||
|
||||
impl Block {
|
||||
pub fn produce_block_from_hashable_data(hashable_data: HashableBlockData) -> Self {
|
||||
let data = serde_json::to_vec(&hashable_data).unwrap();
|
||||
impl From<HashableBlockData> for Block {
|
||||
fn from(value: HashableBlockData) -> Self {
|
||||
let data = serde_json::to_vec(&value).unwrap();
|
||||
|
||||
let hash = OwnHasher::hash(&data);
|
||||
|
||||
Self {
|
||||
block_id: hashable_data.block_id,
|
||||
prev_block_id: hashable_data.prev_block_id,
|
||||
block_id: value.block_id,
|
||||
prev_block_id: value.prev_block_id,
|
||||
hash,
|
||||
transactions: hashable_data.transactions,
|
||||
data: hashable_data.data,
|
||||
prev_block_hash: hashable_data.prev_block_hash,
|
||||
transactions: value.transactions,
|
||||
data: value.data,
|
||||
prev_block_hash: value.prev_block_hash,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,9 +7,13 @@ pub mod execution_input;
|
||||
pub mod merkle_tree_public;
|
||||
pub mod nullifier;
|
||||
pub mod rpc_primitives;
|
||||
pub mod sequencer_client;
|
||||
pub mod transaction;
|
||||
pub mod utxo_commitment;
|
||||
|
||||
//Module for tests utility functions
|
||||
pub mod test_utils;
|
||||
|
||||
use rpc_primitives::errors::RpcError;
|
||||
|
||||
///Account id on blockchain
|
||||
|
||||
@ -19,8 +19,6 @@ pub struct RegisterAccountRequest {
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct SendTxRequest {
|
||||
pub transaction: Transaction,
|
||||
///UTXO Commitment Root, Pub Tx Root
|
||||
pub tx_roots: [[u8; 32]; 2],
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
use common::transaction::Transaction;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::transaction::Transaction;
|
||||
|
||||
//Requests
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct SendTxRequest {
|
||||
pub transaction: Transaction,
|
||||
///UTXO Commitment Root, Pub Tx Root
|
||||
pub tx_roots: [[u8; 32]; 2],
|
||||
}
|
||||
|
||||
//Responses
|
||||
@ -1,35 +1,32 @@
|
||||
use accounts::account_core::Account;
|
||||
use anyhow::Result;
|
||||
use common::rpc_primitives::requests::{
|
||||
use super::rpc_primitives::requests::{
|
||||
GetAccountBalanceRequest, GetAccountBalanceResponse, GetBlockDataRequest, GetBlockDataResponse,
|
||||
GetGenesisIdRequest, GetGenesisIdResponse, GetInitialTestnetAccountsRequest,
|
||||
RegisterAccountRequest, RegisterAccountResponse,
|
||||
};
|
||||
use common::transaction::Transaction;
|
||||
use common::{SequencerClientError, SequencerRpcError};
|
||||
use anyhow::Result;
|
||||
use json::{SendTxRequest, SendTxResponse, SequencerRpcRequest, SequencerRpcResponse};
|
||||
use reqwest::Client;
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::config::NodeConfig;
|
||||
use crate::sequencer_client::json::AccountInitialData;
|
||||
use crate::transaction::Transaction;
|
||||
use crate::{SequencerClientError, SequencerRpcError};
|
||||
|
||||
pub mod json;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SequencerClient {
|
||||
pub client: reqwest::Client,
|
||||
pub config: NodeConfig,
|
||||
pub sequencer_addr: String,
|
||||
}
|
||||
|
||||
impl SequencerClient {
|
||||
pub fn new(config: NodeConfig) -> Result<Self> {
|
||||
pub fn new(sequencer_addr: String) -> Result<Self> {
|
||||
Ok(Self {
|
||||
client: Client::builder()
|
||||
//Add more fiedls if needed
|
||||
.timeout(std::time::Duration::from_secs(60))
|
||||
.build()?,
|
||||
config,
|
||||
sequencer_addr,
|
||||
})
|
||||
}
|
||||
|
||||
@ -40,7 +37,7 @@ impl SequencerClient {
|
||||
) -> Result<Value, SequencerClientError> {
|
||||
let request = SequencerRpcRequest::from_payload_version_2_0(method.to_string(), payload);
|
||||
|
||||
let call_builder = self.client.post(&self.config.sequencer_addr);
|
||||
let call_builder = self.client.post(&self.sequencer_addr);
|
||||
|
||||
let call_res = call_builder.json(&request).send().await?;
|
||||
|
||||
@ -56,6 +53,7 @@ impl SequencerClient {
|
||||
}
|
||||
}
|
||||
|
||||
///Get block data at `block_id` from sequencer
|
||||
pub async fn get_block(
|
||||
&self,
|
||||
block_id: u64,
|
||||
@ -71,6 +69,7 @@ impl SequencerClient {
|
||||
Ok(resp_deser)
|
||||
}
|
||||
|
||||
///Get account public balance for `address`. `address` must be a valid hex-string for 32 bytes.
|
||||
pub async fn get_account_balance(
|
||||
&self,
|
||||
address: String,
|
||||
@ -88,15 +87,12 @@ impl SequencerClient {
|
||||
Ok(resp_deser)
|
||||
}
|
||||
|
||||
///Send transaction to sequencer
|
||||
pub async fn send_tx(
|
||||
&self,
|
||||
transaction: Transaction,
|
||||
tx_roots: [[u8; 32]; 2],
|
||||
) -> Result<SendTxResponse, SequencerClientError> {
|
||||
let tx_req = SendTxRequest {
|
||||
transaction,
|
||||
tx_roots,
|
||||
};
|
||||
let tx_req = SendTxRequest { transaction };
|
||||
|
||||
let req = serde_json::to_value(tx_req)?;
|
||||
|
||||
@ -107,25 +103,7 @@ impl SequencerClient {
|
||||
Ok(resp_deser)
|
||||
}
|
||||
|
||||
pub async fn register_account(
|
||||
&self,
|
||||
account: &Account,
|
||||
) -> Result<RegisterAccountResponse, SequencerClientError> {
|
||||
let acc_req = RegisterAccountRequest {
|
||||
address: account.address,
|
||||
};
|
||||
|
||||
let req = serde_json::to_value(acc_req)?;
|
||||
|
||||
let resp = self
|
||||
.call_method_with_payload("register_account", req)
|
||||
.await?;
|
||||
|
||||
let resp_deser = serde_json::from_value(resp)?;
|
||||
|
||||
Ok(resp_deser)
|
||||
}
|
||||
|
||||
///Get genesis id from sequencer
|
||||
pub async fn get_genesis_id(&self) -> Result<GetGenesisIdResponse, SequencerClientError> {
|
||||
let genesis_req = GetGenesisIdRequest {};
|
||||
|
||||
@ -141,6 +119,7 @@ impl SequencerClient {
|
||||
Ok(resp_deser)
|
||||
}
|
||||
|
||||
///Get initial testnet accounts from sequencer
|
||||
pub async fn get_initial_testnet_accounts(
|
||||
&self,
|
||||
) -> Result<Vec<AccountInitialData>, SequencerClientError> {
|
||||
115
common/src/test_utils.rs
Normal file
115
common/src/test_utils.rs
Normal file
@ -0,0 +1,115 @@
|
||||
use k256::ecdsa::SigningKey;
|
||||
use secp256k1_zkp::Tweak;
|
||||
|
||||
use crate::{
|
||||
block::{Block, HashableBlockData},
|
||||
execution_input::PublicNativeTokenSend,
|
||||
transaction::{SignaturePrivateKey, Transaction, TransactionBody, TxKind},
|
||||
};
|
||||
|
||||
//Dummy producers
|
||||
|
||||
///Produce dummy block with
|
||||
///
|
||||
/// `id` - block id, provide zero for genesis
|
||||
///
|
||||
/// `prev_hash` - hash of previous block, provide None for genesis
|
||||
///
|
||||
/// `transactions` - vector of `Transaction` objects
|
||||
///
|
||||
/// `additional_data` - vector with additional data
|
||||
pub fn produce_dummy_block(
|
||||
id: u64,
|
||||
prev_hash: Option<[u8; 32]>,
|
||||
transactions: Vec<Transaction>,
|
||||
additional_data: Vec<u8>,
|
||||
) -> Block {
|
||||
let block_data = HashableBlockData {
|
||||
block_id: id,
|
||||
prev_block_id: id.saturating_sub(1),
|
||||
prev_block_hash: prev_hash.unwrap_or_default(),
|
||||
transactions,
|
||||
data: additional_data,
|
||||
};
|
||||
|
||||
block_data.into()
|
||||
}
|
||||
|
||||
pub fn produce_dummy_empty_transaction() -> Transaction {
|
||||
let body = TransactionBody {
|
||||
tx_kind: TxKind::Public,
|
||||
execution_input: Default::default(),
|
||||
execution_output: Default::default(),
|
||||
utxo_commitments_spent_hashes: Default::default(),
|
||||
utxo_commitments_created_hashes: Default::default(),
|
||||
nullifier_created_hashes: Default::default(),
|
||||
execution_proof_private: Default::default(),
|
||||
encoded_data: Default::default(),
|
||||
ephemeral_pub_key: Default::default(),
|
||||
commitment: Default::default(),
|
||||
tweak: Default::default(),
|
||||
secret_r: Default::default(),
|
||||
sc_addr: Default::default(),
|
||||
};
|
||||
|
||||
Transaction::new(body, SignaturePrivateKey::from_slice(&[1; 32]).unwrap())
|
||||
}
|
||||
|
||||
pub fn create_dummy_private_transaction_random_signer(
|
||||
nullifier_created_hashes: Vec<[u8; 32]>,
|
||||
utxo_commitments_spent_hashes: Vec<[u8; 32]>,
|
||||
utxo_commitments_created_hashes: Vec<[u8; 32]>,
|
||||
) -> Transaction {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let body = TransactionBody {
|
||||
tx_kind: TxKind::Private,
|
||||
execution_input: vec![],
|
||||
execution_output: vec![],
|
||||
utxo_commitments_spent_hashes,
|
||||
utxo_commitments_created_hashes,
|
||||
nullifier_created_hashes,
|
||||
execution_proof_private: "dummy_proof".to_string(),
|
||||
encoded_data: vec![],
|
||||
ephemeral_pub_key: vec![10, 11, 12],
|
||||
commitment: vec![],
|
||||
tweak: Tweak::new(&mut rng),
|
||||
secret_r: [0; 32],
|
||||
sc_addr: "sc_addr".to_string(),
|
||||
};
|
||||
Transaction::new(body, SignaturePrivateKey::random(&mut rng))
|
||||
}
|
||||
|
||||
pub fn create_dummy_transaction_native_token_transfer(
|
||||
from: [u8; 32],
|
||||
nonce: u64,
|
||||
to: [u8; 32],
|
||||
balance_to_move: u64,
|
||||
signing_key: SigningKey,
|
||||
) -> Transaction {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let native_token_transfer = PublicNativeTokenSend {
|
||||
from,
|
||||
nonce,
|
||||
to,
|
||||
balance_to_move,
|
||||
};
|
||||
|
||||
let body = TransactionBody {
|
||||
tx_kind: TxKind::Public,
|
||||
execution_input: serde_json::to_vec(&native_token_transfer).unwrap(),
|
||||
execution_output: vec![],
|
||||
utxo_commitments_spent_hashes: vec![],
|
||||
utxo_commitments_created_hashes: vec![],
|
||||
nullifier_created_hashes: vec![],
|
||||
execution_proof_private: "".to_string(),
|
||||
encoded_data: vec![],
|
||||
ephemeral_pub_key: vec![10, 11, 12],
|
||||
commitment: vec![],
|
||||
tweak: Tweak::new(&mut rng),
|
||||
secret_r: [0; 32],
|
||||
sc_addr: "sc_addr".to_string(),
|
||||
};
|
||||
Transaction::new(body, signing_key)
|
||||
}
|
||||
@ -58,10 +58,6 @@ pub struct TransactionBody {
|
||||
pub secret_r: [u8; 32],
|
||||
///Hex-encoded address of a smart contract account called
|
||||
pub sc_addr: String,
|
||||
///Recorded changes in state of smart contract
|
||||
///
|
||||
/// First value represents vector of changes, second is new length of a state
|
||||
pub state_changes: (serde_json::Value, usize),
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
@ -325,7 +321,6 @@ mod tests {
|
||||
tweak: Tweak::from_slice(&[7; SECRET_KEY_SIZE]).unwrap(),
|
||||
secret_r: [8; 32],
|
||||
sc_addr: "someAddress".to_string(),
|
||||
state_changes: (serde_json::Value::Null, 10),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
[package]
|
||||
name = "consensus"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
serde_json.workspace = true
|
||||
env_logger.workspace = true
|
||||
log.workspace = true
|
||||
serde.workspace = true
|
||||
tokio.workspace = true
|
||||
|
||||
[dependencies.networking]
|
||||
path = "../networking"
|
||||
@ -1,22 +0,0 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use networking::peer_manager::PeerManager;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
#[derive(Debug)]
|
||||
///Entrypoint to consensus.
|
||||
/// Manages consensus protocol.
|
||||
pub struct ConsensusManager {
|
||||
pub peer_manager: Arc<Mutex<PeerManager>>,
|
||||
}
|
||||
|
||||
impl ConsensusManager {
|
||||
pub fn new(peer_manager: Arc<Mutex<PeerManager>>) -> Self {
|
||||
Self { peer_manager }
|
||||
}
|
||||
|
||||
//ToDo: change block from generic value into struct, when data block will be defined
|
||||
pub fn vote(&self, _block: serde_json::Value) -> bool {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@ -30,14 +30,8 @@ path = "../sequencer_core"
|
||||
[dependencies.sequencer_runner]
|
||||
path = "../sequencer_runner"
|
||||
|
||||
[dependencies.node_rpc]
|
||||
path = "../node_rpc"
|
||||
|
||||
[dependencies.node_core]
|
||||
path = "../node_core"
|
||||
|
||||
[dependencies.node_runner]
|
||||
path = "../node_runner"
|
||||
[dependencies.wallet]
|
||||
path = "../wallet"
|
||||
|
||||
[dependencies.common]
|
||||
path = "../common"
|
||||
|
||||
@ -1,253 +0,0 @@
|
||||
{
|
||||
"home": "./node",
|
||||
"override_rust_log": null,
|
||||
"sequencer_addr": "http://127.0.0.1:3040",
|
||||
"seq_poll_timeout_secs": 10,
|
||||
"port": 3041,
|
||||
"gas_config": {
|
||||
"gas_fee_per_byte_deploy": 100,
|
||||
"gas_fee_per_input_buffer_runtime": 1000,
|
||||
"gas_fee_per_byte_runtime": 10,
|
||||
"gas_cost_runtime": 100,
|
||||
"gas_cost_deploy": 1000,
|
||||
"gas_limit_deploy": 30000000,
|
||||
"gas_limit_runtime": 30000000
|
||||
},
|
||||
"shapshot_frequency_in_blocks": 10,
|
||||
"initial_accounts": [
|
||||
{
|
||||
"address": [
|
||||
13,
|
||||
150,
|
||||
223,
|
||||
204,
|
||||
65,
|
||||
64,
|
||||
25,
|
||||
56,
|
||||
12,
|
||||
157,
|
||||
222,
|
||||
12,
|
||||
211,
|
||||
220,
|
||||
229,
|
||||
170,
|
||||
201,
|
||||
15,
|
||||
181,
|
||||
68,
|
||||
59,
|
||||
248,
|
||||
113,
|
||||
16,
|
||||
135,
|
||||
65,
|
||||
174,
|
||||
175,
|
||||
222,
|
||||
85,
|
||||
42,
|
||||
215
|
||||
],
|
||||
"balance": 10000,
|
||||
"key_holder": {
|
||||
"address": [
|
||||
13,
|
||||
150,
|
||||
223,
|
||||
204,
|
||||
65,
|
||||
64,
|
||||
25,
|
||||
56,
|
||||
12,
|
||||
157,
|
||||
222,
|
||||
12,
|
||||
211,
|
||||
220,
|
||||
229,
|
||||
170,
|
||||
201,
|
||||
15,
|
||||
181,
|
||||
68,
|
||||
59,
|
||||
248,
|
||||
113,
|
||||
16,
|
||||
135,
|
||||
65,
|
||||
174,
|
||||
175,
|
||||
222,
|
||||
85,
|
||||
42,
|
||||
215
|
||||
],
|
||||
"nullifer_public_key": "03A340BECA9FAAB444CED0140681D72EA1318B5C611704FEE017DA9836B17DB718",
|
||||
"pub_account_signing_key": [
|
||||
133,
|
||||
143,
|
||||
177,
|
||||
187,
|
||||
252,
|
||||
66,
|
||||
237,
|
||||
236,
|
||||
234,
|
||||
252,
|
||||
244,
|
||||
138,
|
||||
5,
|
||||
151,
|
||||
3,
|
||||
99,
|
||||
217,
|
||||
231,
|
||||
112,
|
||||
217,
|
||||
77,
|
||||
211,
|
||||
58,
|
||||
218,
|
||||
176,
|
||||
68,
|
||||
99,
|
||||
53,
|
||||
152,
|
||||
228,
|
||||
198,
|
||||
190
|
||||
],
|
||||
"top_secret_key_holder": {
|
||||
"secret_spending_key": "7BC46784DB1BC67825D8F029436846712BFDF9B5D79EA3AB11D39A52B9B229D4"
|
||||
},
|
||||
"utxo_secret_key_holder": {
|
||||
"nullifier_secret_key": "BB54A8D3C9C51B82C431082D1845A74677B0EF829A11B517E1D9885DE3139506",
|
||||
"viewing_secret_key": "AD923E92F6A5683E30140CEAB2702AFB665330C1EE4EFA70FAF29767B6B52BAF"
|
||||
},
|
||||
"viewing_public_key": "0361220C5D277E7A1709340FD31A52600C1432B9C45B9BCF88A43581D58824A8B6"
|
||||
},
|
||||
"utxos": {}
|
||||
},
|
||||
{
|
||||
"address": [
|
||||
151,
|
||||
72,
|
||||
112,
|
||||
233,
|
||||
190,
|
||||
141,
|
||||
10,
|
||||
192,
|
||||
138,
|
||||
168,
|
||||
59,
|
||||
63,
|
||||
199,
|
||||
167,
|
||||
166,
|
||||
134,
|
||||
41,
|
||||
29,
|
||||
135,
|
||||
50,
|
||||
80,
|
||||
138,
|
||||
186,
|
||||
152,
|
||||
179,
|
||||
96,
|
||||
128,
|
||||
243,
|
||||
156,
|
||||
44,
|
||||
243,
|
||||
100
|
||||
],
|
||||
"balance": 20000,
|
||||
"key_holder": {
|
||||
"address": [
|
||||
151,
|
||||
72,
|
||||
112,
|
||||
233,
|
||||
190,
|
||||
141,
|
||||
10,
|
||||
192,
|
||||
138,
|
||||
168,
|
||||
59,
|
||||
63,
|
||||
199,
|
||||
167,
|
||||
166,
|
||||
134,
|
||||
41,
|
||||
29,
|
||||
135,
|
||||
50,
|
||||
80,
|
||||
138,
|
||||
186,
|
||||
152,
|
||||
179,
|
||||
96,
|
||||
128,
|
||||
243,
|
||||
156,
|
||||
44,
|
||||
243,
|
||||
100
|
||||
],
|
||||
"nullifer_public_key": "02172F50274DE67C4087C344F5D58E11DF761D90285B095060E0994FAA6BCDE271",
|
||||
"pub_account_signing_key": [
|
||||
54,
|
||||
90,
|
||||
62,
|
||||
225,
|
||||
71,
|
||||
225,
|
||||
228,
|
||||
148,
|
||||
143,
|
||||
53,
|
||||
210,
|
||||
23,
|
||||
137,
|
||||
158,
|
||||
171,
|
||||
156,
|
||||
48,
|
||||
7,
|
||||
139,
|
||||
52,
|
||||
117,
|
||||
242,
|
||||
214,
|
||||
7,
|
||||
99,
|
||||
29,
|
||||
122,
|
||||
184,
|
||||
59,
|
||||
116,
|
||||
144,
|
||||
107
|
||||
],
|
||||
"top_secret_key_holder": {
|
||||
"secret_spending_key": "80A186737C8D38B4288A03F0F589957D9C040D79C19F3E0CC4BA80F8494E5179"
|
||||
},
|
||||
"utxo_secret_key_holder": {
|
||||
"nullifier_secret_key": "746928E63F0984F6F4818933493CE9C067562D9CB932FDC06D82C86CDF6D7122",
|
||||
"viewing_secret_key": "89176CF4BC9E673807643FD52110EF99D4894335AFB10D881AC0B5041FE1FCB7"
|
||||
},
|
||||
"viewing_public_key": "026072A8F83FEC3472E30CDD4767683F30B91661D25B1040AD9A5FC2E01D659F99"
|
||||
},
|
||||
"utxos": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,19 +1,8 @@
|
||||
{
|
||||
"home": ".",
|
||||
"home": "./wallet",
|
||||
"override_rust_log": null,
|
||||
"sequencer_addr": "http://127.0.0.1:3040",
|
||||
"seq_poll_timeout_secs": 10,
|
||||
"port": 3041,
|
||||
"gas_config": {
|
||||
"gas_fee_per_byte_deploy": 100,
|
||||
"gas_fee_per_input_buffer_runtime": 1000,
|
||||
"gas_fee_per_byte_runtime": 10,
|
||||
"gas_cost_runtime": 100,
|
||||
"gas_cost_deploy": 1000,
|
||||
"gas_limit_deploy": 30000000,
|
||||
"gas_limit_runtime": 30000000
|
||||
},
|
||||
"shapshot_frequency_in_blocks": 10,
|
||||
"initial_accounts": [
|
||||
{
|
||||
"address": [
|
||||
@ -1,15 +1,15 @@
|
||||
use std::{path::PathBuf, sync::Arc, time::Duration};
|
||||
use std::{path::PathBuf, time::Duration};
|
||||
|
||||
use actix_web::dev::ServerHandle;
|
||||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use common::rpc_primitives::RpcConfig;
|
||||
use common::sequencer_client::SequencerClient;
|
||||
use log::info;
|
||||
use node_core::{NodeCore, config::NodeConfig};
|
||||
use sequencer_core::config::SequencerConfig;
|
||||
use sequencer_runner::startup_sequencer;
|
||||
use tempfile::TempDir;
|
||||
use tokio::{sync::Mutex, task::JoinHandle};
|
||||
use tokio::task::JoinHandle;
|
||||
use wallet::{Command, helperfunctions::fetch_config};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(version)]
|
||||
@ -28,113 +28,71 @@ pub const TIME_TO_WAIT_FOR_BLOCK_SECONDS: u64 = 12;
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub async fn pre_test(
|
||||
home_dir: PathBuf,
|
||||
) -> Result<(
|
||||
ServerHandle,
|
||||
JoinHandle<Result<()>>,
|
||||
ServerHandle,
|
||||
TempDir,
|
||||
TempDir,
|
||||
Arc<Mutex<NodeCore>>,
|
||||
)> {
|
||||
) -> Result<(ServerHandle, JoinHandle<Result<()>>, TempDir)> {
|
||||
let home_dir_sequencer = home_dir.join("sequencer");
|
||||
let home_dir_node = home_dir.join("node");
|
||||
|
||||
let mut sequencer_config =
|
||||
sequencer_runner::config::from_file(home_dir_sequencer.join("sequencer_config.json"))
|
||||
.unwrap();
|
||||
let mut node_config =
|
||||
node_runner::config::from_file(home_dir_node.join("node_config.json")).unwrap();
|
||||
|
||||
let (temp_dir_node, temp_dir_sequencer) =
|
||||
replace_home_dir_with_temp_dir_in_configs(&mut node_config, &mut sequencer_config);
|
||||
let temp_dir_sequencer = replace_home_dir_with_temp_dir_in_configs(&mut sequencer_config);
|
||||
|
||||
let (seq_http_server_handle, sequencer_loop_handle) =
|
||||
startup_sequencer(sequencer_config).await?;
|
||||
|
||||
let node_port = node_config.port;
|
||||
|
||||
let node_core = NodeCore::start_from_config_update_chain(node_config.clone()).await?;
|
||||
|
||||
let wrapped_node_core = Arc::new(Mutex::new(node_core));
|
||||
|
||||
let http_server = node_rpc::new_http_server(
|
||||
RpcConfig::with_port(node_port),
|
||||
node_config.clone(),
|
||||
wrapped_node_core.clone(),
|
||||
)?;
|
||||
info!("HTTP server started");
|
||||
let node_http_server_handle = http_server.handle();
|
||||
tokio::spawn(http_server);
|
||||
|
||||
Ok((
|
||||
seq_http_server_handle,
|
||||
sequencer_loop_handle,
|
||||
node_http_server_handle,
|
||||
temp_dir_node,
|
||||
temp_dir_sequencer,
|
||||
wrapped_node_core,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn replace_home_dir_with_temp_dir_in_configs(
|
||||
node_config: &mut NodeConfig,
|
||||
sequencer_config: &mut SequencerConfig,
|
||||
) -> (TempDir, TempDir) {
|
||||
let temp_dir_node = tempfile::tempdir().unwrap();
|
||||
) -> TempDir {
|
||||
let temp_dir_sequencer = tempfile::tempdir().unwrap();
|
||||
|
||||
node_config.home = temp_dir_node.path().to_path_buf();
|
||||
sequencer_config.home = temp_dir_sequencer.path().to_path_buf();
|
||||
|
||||
(temp_dir_node, temp_dir_sequencer)
|
||||
temp_dir_sequencer
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub async fn post_test(
|
||||
residual: (
|
||||
ServerHandle,
|
||||
JoinHandle<Result<()>>,
|
||||
ServerHandle,
|
||||
TempDir,
|
||||
TempDir,
|
||||
Arc<Mutex<NodeCore>>,
|
||||
),
|
||||
) {
|
||||
let (seq_http_server_handle, sequencer_loop_handle, node_http_server_handle, _, _, _) =
|
||||
residual;
|
||||
pub async fn post_test(residual: (ServerHandle, JoinHandle<Result<()>>, TempDir)) {
|
||||
let (seq_http_server_handle, sequencer_loop_handle, _) = residual;
|
||||
|
||||
info!("Cleanup");
|
||||
|
||||
node_http_server_handle.stop(true).await;
|
||||
sequencer_loop_handle.abort();
|
||||
seq_http_server_handle.stop(true).await;
|
||||
|
||||
//At this point all of the references to node_core and sequencer_core must be lost.
|
||||
//At this point all of the references to sequencer_core must be lost.
|
||||
//So they are dropped and tempdirs will be dropped too,
|
||||
}
|
||||
|
||||
pub async fn test_success(wrapped_node_core: Arc<Mutex<NodeCore>>) {
|
||||
let acc_sender = hex::decode(ACC_SENDER).unwrap().try_into().unwrap();
|
||||
let acc_receiver = hex::decode(ACC_RECEIVER).unwrap().try_into().unwrap();
|
||||
pub async fn test_success() {
|
||||
let command = Command::SendNativeTokenTransfer {
|
||||
from: ACC_SENDER.to_string(),
|
||||
nonce: 0,
|
||||
to: ACC_RECEIVER.to_string(),
|
||||
amount: 100,
|
||||
};
|
||||
|
||||
let guard = wrapped_node_core.lock().await;
|
||||
let wallet_config = fetch_config().unwrap();
|
||||
|
||||
let _res = guard
|
||||
.send_public_native_token_transfer(acc_sender, 0, acc_receiver, 100)
|
||||
.await
|
||||
.unwrap();
|
||||
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
|
||||
|
||||
wallet::execute_subcommand(command).await.unwrap();
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
|
||||
info!("Checking correct balance move");
|
||||
let acc_1_balance = guard
|
||||
.sequencer_client
|
||||
let acc_1_balance = seq_client
|
||||
.get_account_balance(ACC_SENDER.to_string())
|
||||
.await
|
||||
.unwrap();
|
||||
let acc_2_balance = guard
|
||||
.sequencer_client
|
||||
let acc_2_balance = seq_client
|
||||
.get_account_balance(ACC_RECEIVER.to_string())
|
||||
.await
|
||||
.unwrap();
|
||||
@ -148,30 +106,31 @@ pub async fn test_success(wrapped_node_core: Arc<Mutex<NodeCore>>) {
|
||||
info!("Success!");
|
||||
}
|
||||
|
||||
pub async fn test_success_move_to_another_account(wrapped_node_core: Arc<Mutex<NodeCore>>) {
|
||||
let acc_sender = hex::decode(ACC_SENDER).unwrap().try_into().unwrap();
|
||||
let acc_receiver_new_acc = [42; 32];
|
||||
pub async fn test_success_move_to_another_account() {
|
||||
let hex_acc_receiver_new_acc = hex::encode([42; 32]);
|
||||
|
||||
let hex_acc_receiver_new_acc = hex::encode(acc_receiver_new_acc);
|
||||
let command = Command::SendNativeTokenTransfer {
|
||||
from: ACC_SENDER.to_string(),
|
||||
nonce: 0,
|
||||
to: hex_acc_receiver_new_acc.clone(),
|
||||
amount: 100,
|
||||
};
|
||||
|
||||
let guard = wrapped_node_core.lock().await;
|
||||
let wallet_config = fetch_config().unwrap();
|
||||
|
||||
let _res = guard
|
||||
.send_public_native_token_transfer(acc_sender, 0, acc_receiver_new_acc, 100)
|
||||
.await
|
||||
.unwrap();
|
||||
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
|
||||
|
||||
wallet::execute_subcommand(command).await.unwrap();
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
|
||||
info!("Checking correct balance move");
|
||||
let acc_1_balance = guard
|
||||
.sequencer_client
|
||||
let acc_1_balance = seq_client
|
||||
.get_account_balance(ACC_SENDER.to_string())
|
||||
.await
|
||||
.unwrap();
|
||||
let acc_2_balance = guard
|
||||
.sequencer_client
|
||||
let acc_2_balance = seq_client
|
||||
.get_account_balance(hex_acc_receiver_new_acc)
|
||||
.await
|
||||
.unwrap();
|
||||
@ -185,28 +144,29 @@ pub async fn test_success_move_to_another_account(wrapped_node_core: Arc<Mutex<N
|
||||
info!("Success!");
|
||||
}
|
||||
|
||||
pub async fn test_failure(wrapped_node_core: Arc<Mutex<NodeCore>>) {
|
||||
let acc_sender = hex::decode(ACC_SENDER).unwrap().try_into().unwrap();
|
||||
let acc_receiver = hex::decode(ACC_RECEIVER).unwrap().try_into().unwrap();
|
||||
pub async fn test_failure() {
|
||||
let command = Command::SendNativeTokenTransfer {
|
||||
from: ACC_SENDER.to_string(),
|
||||
nonce: 0,
|
||||
to: ACC_RECEIVER.to_string(),
|
||||
amount: 1000000,
|
||||
};
|
||||
|
||||
let guard = wrapped_node_core.lock().await;
|
||||
let wallet_config = fetch_config().unwrap();
|
||||
|
||||
let _res = guard
|
||||
.send_public_native_token_transfer(acc_sender, 0, acc_receiver, 100000)
|
||||
.await
|
||||
.unwrap();
|
||||
let seq_client = SequencerClient::new(wallet_config.sequencer_addr.clone()).unwrap();
|
||||
|
||||
wallet::execute_subcommand(command).await.unwrap();
|
||||
|
||||
info!("Waiting for next block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
|
||||
info!("Checking correct balance move");
|
||||
let acc_1_balance = guard
|
||||
.sequencer_client
|
||||
let acc_1_balance = seq_client
|
||||
.get_account_balance(ACC_SENDER.to_string())
|
||||
.await
|
||||
.unwrap();
|
||||
let acc_2_balance = guard
|
||||
.sequencer_client
|
||||
let acc_2_balance = seq_client
|
||||
.get_account_balance(ACC_RECEIVER.to_string())
|
||||
.await
|
||||
.unwrap();
|
||||
@ -224,12 +184,10 @@ macro_rules! test_cleanup_wrap {
|
||||
($home_dir:ident, $test_func:ident) => {{
|
||||
let res = pre_test($home_dir.clone()).await.unwrap();
|
||||
|
||||
let wrapped_node_core = res.5.clone();
|
||||
|
||||
info!("Waiting for first block creation");
|
||||
tokio::time::sleep(Duration::from_secs(TIME_TO_WAIT_FOR_BLOCK_SECONDS)).await;
|
||||
|
||||
$test_func(wrapped_node_core.clone()).await;
|
||||
$test_func().await;
|
||||
|
||||
post_test(res).await;
|
||||
}};
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
[package]
|
||||
name = "networking"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
serde_json.workspace = true
|
||||
env_logger.workspace = true
|
||||
log.workspace = true
|
||||
serde.workspace = true
|
||||
@ -1,5 +0,0 @@
|
||||
pub mod network_protocol;
|
||||
pub mod peer;
|
||||
pub mod peer_manager;
|
||||
pub mod rate_limiter;
|
||||
pub mod tcp;
|
||||
@ -1,19 +0,0 @@
|
||||
#[derive(Debug)]
|
||||
pub enum MessageKind {}
|
||||
|
||||
pub type PeerId = u64;
|
||||
pub type PeerDistance = u32;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PeerAddr {
|
||||
pub id: PeerId,
|
||||
//Probably will be socket address in the future
|
||||
pub addr: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
///Structure, which contains all necessary fields for handshake
|
||||
pub struct Handshake {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum HandshakeFailedReason {}
|
||||
@ -1,18 +0,0 @@
|
||||
use crate::{
|
||||
network_protocol::{HandshakeFailedReason, PeerAddr},
|
||||
tcp::Connection,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Structure, which stores all of the peer interaction data.
|
||||
/// Created at per-peer connection basis at `PeerManager`
|
||||
pub struct Peer {
|
||||
pub connection: Connection,
|
||||
pub peer_addr: PeerAddr,
|
||||
}
|
||||
|
||||
impl Peer {
|
||||
pub fn handshake(&mut self) -> Result<(), HandshakeFailedReason> {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::{network_protocol::PeerId, peer::Peer};
|
||||
|
||||
#[derive(Debug)]
|
||||
///Entrypoint to network module.
|
||||
/// Manages connections with peers in network
|
||||
pub struct PeerManager {
|
||||
pub my_peer_id: PeerId,
|
||||
}
|
||||
|
||||
impl PeerManager {
|
||||
pub async fn start_peer_manager(_num_threads: u8, my_peer_id: PeerId) -> Result<Self> {
|
||||
Ok(Self { my_peer_id })
|
||||
}
|
||||
|
||||
pub async fn connect(&self, _peer_id: PeerId) -> Peer {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::network_protocol::MessageKind;
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Object responsible to manage the rate limits of all network messages
|
||||
/// for a single connection/peer.
|
||||
pub struct RateLimiter {
|
||||
pub limits: HashMap<MessageKind, u64>,
|
||||
}
|
||||
|
||||
impl RateLimiter {
|
||||
pub fn is_allowed(&self, _message: MessageKind) -> bool {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
use crate::network_protocol::PeerAddr;
|
||||
|
||||
#[derive(Debug)]
|
||||
///Structure, representing peer connection
|
||||
pub struct Connection {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ConnectionType {
|
||||
Inbound { conn: Connection },
|
||||
Outbound { conn: Connection, peer: PeerAddr },
|
||||
}
|
||||
@ -1,269 +0,0 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::path::Path;
|
||||
|
||||
use accounts::account_core::Account;
|
||||
use anyhow::{anyhow, Result};
|
||||
use common::block::Block;
|
||||
use common::merkle_tree_public::merkle_tree::HashStorageMerkleTree;
|
||||
use common::nullifier::UTXONullifier;
|
||||
use common::transaction::Transaction;
|
||||
use common::utxo_commitment::UTXOCommitment;
|
||||
use log::error;
|
||||
use storage::sc_db_utils::{DataBlob, DataBlobChangeVariant};
|
||||
use storage::RocksDBIO;
|
||||
|
||||
use crate::chain_storage::AccMap;
|
||||
|
||||
pub struct NodeBlockStore {
|
||||
dbio: RocksDBIO,
|
||||
}
|
||||
|
||||
impl NodeBlockStore {
|
||||
///Starting database at the start of new chain.
|
||||
/// Creates files if necessary.
|
||||
///
|
||||
/// ATTENTION: Will overwrite genesis block.
|
||||
pub fn open_db_with_genesis(location: &Path, genesis_block: Option<Block>) -> Result<Self> {
|
||||
Ok(Self {
|
||||
dbio: RocksDBIO::new(location, genesis_block)?,
|
||||
})
|
||||
}
|
||||
|
||||
///Reopening existing database
|
||||
pub fn open_db_restart(location: &Path, genesis_block: Block) -> Result<Self> {
|
||||
NodeBlockStore::db_destroy(location)?;
|
||||
NodeBlockStore::open_db_with_genesis(location, Some(genesis_block))
|
||||
}
|
||||
|
||||
///Reloading existing database
|
||||
pub fn open_db_reload(location: &Path) -> Result<Self> {
|
||||
NodeBlockStore::open_db_with_genesis(location, None)
|
||||
}
|
||||
|
||||
///Destroying existing database
|
||||
fn db_destroy(location: &Path) -> Result<()> {
|
||||
RocksDBIO::destroy(location).map_err(|err| anyhow!("RocksDBIO error: {}", err))
|
||||
}
|
||||
|
||||
pub fn get_block_at_id(&self, id: u64) -> Result<Block> {
|
||||
Ok(self.dbio.get_block(id)?)
|
||||
}
|
||||
|
||||
pub fn put_block_at_id(&self, block: Block) -> Result<()> {
|
||||
Ok(self.dbio.put_block(block, false)?)
|
||||
}
|
||||
|
||||
pub fn put_sc_sc_state(
|
||||
&self,
|
||||
sc_addr: &str,
|
||||
length: usize,
|
||||
modifications: Vec<DataBlobChangeVariant>,
|
||||
) -> Result<()> {
|
||||
Ok(self.dbio.put_sc_sc_state(sc_addr, length, modifications)?)
|
||||
}
|
||||
|
||||
pub fn get_sc_sc_state(&self, sc_addr: &str) -> Result<Vec<DataBlob>> {
|
||||
Ok(self.dbio.get_sc_sc_state(sc_addr)?)
|
||||
}
|
||||
|
||||
pub fn get_snapshot_block_id(&self) -> Result<u64> {
|
||||
Ok(self.dbio.get_snapshot_block_id()?)
|
||||
}
|
||||
|
||||
pub fn get_snapshot_account(&self) -> Result<HashMap<[u8; 32], Account>> {
|
||||
let temp: AccMap = serde_json::from_slice(&self.dbio.get_snapshot_account()?)?;
|
||||
Ok(temp.into())
|
||||
}
|
||||
|
||||
pub fn get_snapshot_commitment(&self) -> Result<HashStorageMerkleTree<UTXOCommitment>> {
|
||||
Ok(serde_json::from_slice(
|
||||
&self.dbio.get_snapshot_commitment()?,
|
||||
)?)
|
||||
}
|
||||
|
||||
pub fn get_snapshot_nullifier(&self) -> Result<HashSet<UTXONullifier>> {
|
||||
Ok(serde_json::from_slice(
|
||||
&self.dbio.get_snapshot_nullifier()?,
|
||||
)?)
|
||||
}
|
||||
|
||||
pub fn get_snapshot_transaction(&self) -> Result<HashStorageMerkleTree<Transaction>> {
|
||||
Ok(serde_json::from_slice(
|
||||
&self.dbio.get_snapshot_transaction()?,
|
||||
)?)
|
||||
}
|
||||
|
||||
pub fn put_snapshot_at_block_id(
|
||||
&self,
|
||||
id: u64,
|
||||
accounts_ser: Vec<u8>,
|
||||
comm_ser: Vec<u8>,
|
||||
txs_ser: Vec<u8>,
|
||||
nullifiers_ser: Vec<u8>,
|
||||
) -> Result<()> {
|
||||
//Error notification for writing into DB error
|
||||
self.dbio
|
||||
.put_snapshot_block_id_db(id)
|
||||
.inspect_err(|err| error!("Failed to store snapshot block id with error {err:#?}"))?;
|
||||
self.dbio
|
||||
.put_snapshot_account_db(accounts_ser)
|
||||
.inspect_err(|err| error!("Failed to store snapshot accounts with error {err:#?}"))?;
|
||||
self.dbio
|
||||
.put_snapshot_commitement_db(comm_ser)
|
||||
.inspect_err(|err| {
|
||||
error!("Failed to store snapshot commitments with error {err:#?}")
|
||||
})?;
|
||||
self.dbio
|
||||
.put_snapshot_transaction_db(txs_ser)
|
||||
.inspect_err(|err| {
|
||||
error!("Failed to store snapshot transactions with error {err:#?}")
|
||||
})?;
|
||||
self.dbio
|
||||
.put_snapshot_nullifier_db(nullifiers_ser)
|
||||
.inspect_err(|err| error!("Failed to store snapshot nullifiers with error {err:#?}"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use common::block::Data;
|
||||
use tempfile::tempdir;
|
||||
|
||||
fn create_genesis_block() -> Block {
|
||||
Block {
|
||||
block_id: 0,
|
||||
prev_block_id: 0,
|
||||
prev_block_hash: [0; 32],
|
||||
hash: [1; 32],
|
||||
transactions: vec![],
|
||||
data: Data::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn create_sample_block(block_id: u64, prev_block_id: u64) -> Block {
|
||||
Block {
|
||||
block_id,
|
||||
prev_block_id,
|
||||
prev_block_hash: [0; 32],
|
||||
hash: [1; 32],
|
||||
transactions: vec![],
|
||||
data: Data::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_open_db_with_genesis() {
|
||||
let temp_dir = tempdir().unwrap();
|
||||
let path = temp_dir.path();
|
||||
|
||||
let genesis_block = create_genesis_block();
|
||||
let node_store =
|
||||
NodeBlockStore::open_db_with_genesis(path, Some(genesis_block.clone())).unwrap();
|
||||
|
||||
// Verify the genesis block is stored
|
||||
let stored_block = node_store.get_block_at_id(0).unwrap();
|
||||
assert_eq!(stored_block.block_id, genesis_block.block_id);
|
||||
assert_eq!(stored_block.hash, genesis_block.hash);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_open_db_restart() {
|
||||
let temp_dir = tempdir().unwrap();
|
||||
let path = temp_dir.path();
|
||||
|
||||
let genesis_block = create_genesis_block();
|
||||
{
|
||||
let node_store_old =
|
||||
NodeBlockStore::open_db_with_genesis(path, Some(genesis_block.clone())).unwrap();
|
||||
|
||||
let block = create_sample_block(1, 0);
|
||||
node_store_old.put_block_at_id(block.clone()).unwrap();
|
||||
}
|
||||
|
||||
// Check that the first block is still in the old database
|
||||
{
|
||||
let node_store_old = NodeBlockStore::open_db_reload(path).unwrap();
|
||||
let result = node_store_old.get_block_at_id(1);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
// Restart the database
|
||||
let node_store = NodeBlockStore::open_db_restart(path, genesis_block).unwrap();
|
||||
|
||||
// The block should no longer be available since no first block is set on restart
|
||||
let result = node_store.get_block_at_id(1);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_open_db_reload() {
|
||||
let temp_dir = tempdir().unwrap();
|
||||
let path = temp_dir.path();
|
||||
|
||||
let genesis_block = create_genesis_block();
|
||||
let _ = NodeBlockStore::open_db_with_genesis(path, Some(genesis_block)).unwrap();
|
||||
|
||||
// Reload the database
|
||||
let node_store = NodeBlockStore::open_db_reload(path).unwrap();
|
||||
|
||||
// The genesis block should be available on reload
|
||||
let result = node_store.get_block_at_id(0);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_put_and_get_block() {
|
||||
let temp_dir = tempdir().unwrap();
|
||||
let path = temp_dir.path();
|
||||
|
||||
let genesis_block = create_genesis_block();
|
||||
let node_store = NodeBlockStore::open_db_with_genesis(path, Some(genesis_block)).unwrap();
|
||||
|
||||
let block = create_sample_block(1, 0);
|
||||
node_store.put_block_at_id(block.clone()).unwrap();
|
||||
|
||||
let retrieved_block = node_store.get_block_at_id(1).unwrap();
|
||||
assert_eq!(retrieved_block.block_id, block.block_id);
|
||||
assert_eq!(retrieved_block.hash, block.hash);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_put_snapshot_at_block_id() {
|
||||
let temp_dir = tempdir().unwrap();
|
||||
let path = temp_dir.path();
|
||||
|
||||
let genesis_block = create_genesis_block();
|
||||
let node_store = NodeBlockStore::open_db_with_genesis(path, Some(genesis_block)).unwrap();
|
||||
|
||||
let id = 3;
|
||||
let accounts_ser = vec![1, 2, 3, 4];
|
||||
let comm_ser = vec![5, 6, 7, 8];
|
||||
let txs_ser = vec![9, 10, 11, 12];
|
||||
let nullifiers_ser = vec![13, 14, 15, 16];
|
||||
|
||||
node_store
|
||||
.put_snapshot_at_block_id(
|
||||
id,
|
||||
accounts_ser.clone(),
|
||||
comm_ser.clone(),
|
||||
txs_ser.clone(),
|
||||
nullifiers_ser.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(node_store.dbio.get_snapshot_block_id().unwrap(), id);
|
||||
assert_eq!(
|
||||
node_store.dbio.get_snapshot_account().unwrap(),
|
||||
accounts_ser
|
||||
);
|
||||
assert_eq!(node_store.dbio.get_snapshot_commitment().unwrap(), comm_ser);
|
||||
assert_eq!(node_store.dbio.get_snapshot_transaction().unwrap(), txs_ser);
|
||||
assert_eq!(
|
||||
node_store.dbio.get_snapshot_nullifier().unwrap(),
|
||||
nullifiers_ser
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,632 +0,0 @@
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
|
||||
use accounts::account_core::{address::AccountAddress, Account};
|
||||
use anyhow::Result;
|
||||
use block_store::NodeBlockStore;
|
||||
use common::{
|
||||
block::Block,
|
||||
execution_input::PublicNativeTokenSend,
|
||||
merkle_tree_public::merkle_tree::{PublicTransactionMerkleTree, UTXOCommitmentsMerkleTree},
|
||||
nullifier::UTXONullifier,
|
||||
utxo_commitment::UTXOCommitment,
|
||||
};
|
||||
use k256::AffinePoint;
|
||||
use log::{info, warn};
|
||||
use sc_core::public_context::PublicSCContext;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use utxo::utxo_core::UTXO;
|
||||
|
||||
use crate::{config::NodeConfig, ActionData};
|
||||
|
||||
pub mod accounts_store;
|
||||
pub mod block_store;
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct AccMap {
|
||||
pub acc_map: HashMap<String, Account>,
|
||||
}
|
||||
|
||||
impl From<HashMap<[u8; 32], Account>> for AccMap {
|
||||
fn from(value: HashMap<[u8; 32], Account>) -> Self {
|
||||
AccMap {
|
||||
acc_map: value
|
||||
.into_iter()
|
||||
.map(|(key, val)| (hex::encode(key), val))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AccMap> for HashMap<[u8; 32], Account> {
|
||||
fn from(value: AccMap) -> Self {
|
||||
value
|
||||
.acc_map
|
||||
.into_iter()
|
||||
.map(|(key, val)| (hex::decode(key).unwrap().try_into().unwrap(), val))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NodeChainStore {
|
||||
pub acc_map: HashMap<AccountAddress, Account>,
|
||||
pub block_store: NodeBlockStore,
|
||||
pub nullifier_store: HashSet<UTXONullifier>,
|
||||
pub utxo_commitments_store: UTXOCommitmentsMerkleTree,
|
||||
pub pub_tx_store: PublicTransactionMerkleTree,
|
||||
pub node_config: NodeConfig,
|
||||
}
|
||||
|
||||
impl NodeChainStore {
|
||||
pub fn new(config: NodeConfig, genesis_block: Block) -> Result<(Self, u64)> {
|
||||
let mut acc_map = HashMap::new();
|
||||
let mut nullifier_store = HashSet::new();
|
||||
let mut utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]);
|
||||
let mut pub_tx_store = PublicTransactionMerkleTree::new(vec![]);
|
||||
let mut block_id = genesis_block.block_id;
|
||||
|
||||
//Sequencer should panic if unable to open db,
|
||||
//as fixing this issue may require actions non-native to program scope
|
||||
let block_store =
|
||||
NodeBlockStore::open_db_with_genesis(&config.home.join("rocksdb"), Some(genesis_block))
|
||||
.unwrap();
|
||||
|
||||
if let Ok(temp_block_id) = block_store.get_snapshot_block_id() {
|
||||
utxo_commitments_store = block_store.get_snapshot_commitment()?;
|
||||
nullifier_store = block_store.get_snapshot_nullifier()?;
|
||||
acc_map = block_store.get_snapshot_account()?;
|
||||
pub_tx_store = block_store.get_snapshot_transaction()?;
|
||||
block_id = temp_block_id;
|
||||
}
|
||||
|
||||
Ok((
|
||||
Self {
|
||||
acc_map,
|
||||
block_store,
|
||||
nullifier_store,
|
||||
utxo_commitments_store,
|
||||
pub_tx_store,
|
||||
node_config: config,
|
||||
},
|
||||
block_id,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn new_after_restart(config: NodeConfig, genesis_block: Block) -> Result<(Self, u64)> {
|
||||
let mut acc_map = HashMap::new();
|
||||
let mut nullifier_store = HashSet::new();
|
||||
let mut utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]);
|
||||
let mut pub_tx_store = PublicTransactionMerkleTree::new(vec![]);
|
||||
let mut block_id = genesis_block.block_id;
|
||||
|
||||
//Sequencer should panic if unable to open db,
|
||||
//as fixing this issue may require actions non-native to program scope
|
||||
let block_store = NodeBlockStore::open_db_reload(&config.home.join("rocksdb")).unwrap();
|
||||
|
||||
if let Ok(temp_block_id) = block_store.get_snapshot_block_id() {
|
||||
utxo_commitments_store = block_store.get_snapshot_commitment()?;
|
||||
nullifier_store = block_store.get_snapshot_nullifier()?;
|
||||
acc_map = block_store.get_snapshot_account()?;
|
||||
pub_tx_store = block_store.get_snapshot_transaction()?;
|
||||
block_id = temp_block_id;
|
||||
}
|
||||
|
||||
Ok((
|
||||
Self {
|
||||
acc_map,
|
||||
block_store,
|
||||
nullifier_store,
|
||||
utxo_commitments_store,
|
||||
pub_tx_store,
|
||||
node_config: config,
|
||||
},
|
||||
block_id,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn dissect_insert_block(&mut self, block: Block) -> Result<()> {
|
||||
let block_id = block.block_id;
|
||||
|
||||
for tx in &block.transactions {
|
||||
if !tx.body().execution_input.is_empty() {
|
||||
let public_action =
|
||||
serde_json::from_slice::<ActionData>(&tx.body().execution_input);
|
||||
|
||||
if let Ok(public_action) = public_action {
|
||||
match public_action {
|
||||
ActionData::MintMoneyPublicTx(action) => {
|
||||
let acc_mut = self.acc_map.get_mut(&action.acc);
|
||||
|
||||
if let Some(acc_mut) = acc_mut {
|
||||
acc_mut.balance += action.amount as u64;
|
||||
}
|
||||
}
|
||||
ActionData::SendMoneyDeshieldedTx(action) => {
|
||||
for (balance, acc_addr) in action.receiver_data {
|
||||
let acc_mut = self.acc_map.get_mut(&acc_addr);
|
||||
|
||||
if let Some(acc_mut) = acc_mut {
|
||||
acc_mut.balance += balance as u64;
|
||||
}
|
||||
}
|
||||
}
|
||||
ActionData::SendMoneyShieldedTx(action) => {
|
||||
let acc_mut = self.acc_map.get_mut(&action.acc_sender);
|
||||
|
||||
if let Some(acc_mut) = acc_mut {
|
||||
acc_mut.balance =
|
||||
acc_mut.balance.saturating_sub(action.amount as u64);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
let native_transfer =
|
||||
serde_json::from_slice::<PublicNativeTokenSend>(&tx.body().execution_input);
|
||||
|
||||
if let Ok(transfer) = native_transfer {
|
||||
if let Some(acc_sender) = self.acc_map.get_mut(&transfer.from) {
|
||||
//Can panic, we depend on sequencer maintaining chain consistency here
|
||||
acc_sender.balance -= transfer.balance_to_move;
|
||||
|
||||
if let Some(acc_rec) = self.acc_map.get_mut(&transfer.to) {
|
||||
acc_rec.balance += transfer.balance_to_move;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.utxo_commitments_store.add_tx_multiple(
|
||||
tx.body()
|
||||
.utxo_commitments_created_hashes
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|hash| UTXOCommitment { hash })
|
||||
.collect(),
|
||||
);
|
||||
|
||||
for nullifier in tx.body().nullifier_created_hashes.iter() {
|
||||
self.nullifier_store.insert(UTXONullifier {
|
||||
utxo_hash: *nullifier,
|
||||
});
|
||||
}
|
||||
|
||||
if !tx.body().encoded_data.is_empty() {
|
||||
let ephemeral_public_key_sender =
|
||||
serde_json::from_slice::<AffinePoint>(&tx.body().ephemeral_pub_key)?;
|
||||
|
||||
for (ciphertext, nonce, tag) in tx.body().encoded_data.clone() {
|
||||
let slice = nonce.as_slice();
|
||||
let nonce =
|
||||
accounts::key_management::constants_types::Nonce::clone_from_slice(slice);
|
||||
for (acc_id, acc) in self.acc_map.iter_mut() {
|
||||
if hex::decode(acc_id).unwrap()[0] == tag {
|
||||
let decoded_data_curr_acc = acc.decrypt_data(
|
||||
ephemeral_public_key_sender,
|
||||
ciphertext.clone(),
|
||||
nonce,
|
||||
);
|
||||
if let Ok(decoded_data_curr_acc) = decoded_data_curr_acc {
|
||||
let decoded_utxo_try =
|
||||
serde_json::from_slice::<UTXO>(&decoded_data_curr_acc);
|
||||
if let Ok(utxo) = decoded_utxo_try {
|
||||
if &utxo.owner == acc_id {
|
||||
acc.utxos.insert(utxo.hash, utxo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.pub_tx_store.add_tx(tx);
|
||||
}
|
||||
|
||||
self.block_store.put_block_at_id(block)?;
|
||||
|
||||
//Snapshot
|
||||
if block_id.is_multiple_of(self.node_config.shapshot_frequency_in_blocks) {
|
||||
//Serializing all important data structures
|
||||
|
||||
//If we fail serialization, it is not the reason to stop running
|
||||
//Logging on warn level in this cases
|
||||
let acc_map: AccMap = self.acc_map.clone().into();
|
||||
|
||||
if let Ok(accounts_ser) = serde_json::to_vec(&acc_map).inspect_err(|err| {
|
||||
warn!("Failed to serialize accounts data {err:#?}");
|
||||
}) {
|
||||
if let Ok(comm_ser) =
|
||||
serde_json::to_vec(&self.utxo_commitments_store).inspect_err(|err| {
|
||||
warn!("Failed to serialize commitments {err:#?}");
|
||||
})
|
||||
{
|
||||
if let Ok(txs_ser) = serde_json::to_vec(&self.pub_tx_store).inspect_err(|err| {
|
||||
warn!("Failed to serialize transactions {err:#?}");
|
||||
}) {
|
||||
if let Ok(nullifiers_ser) = serde_json::to_vec(&self.nullifier_store)
|
||||
.inspect_err(|err| {
|
||||
warn!("Failed to serialize nullifiers {err:#?}");
|
||||
})
|
||||
{
|
||||
let snapshot_trace = self.block_store.put_snapshot_at_block_id(
|
||||
block_id,
|
||||
accounts_ser,
|
||||
comm_ser,
|
||||
txs_ser,
|
||||
nullifiers_ser,
|
||||
);
|
||||
|
||||
info!(
|
||||
"Snapshot executed at {block_id:?} with results {snapshot_trace:#?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn produce_context(&self, caller: AccountAddress) -> PublicSCContext {
|
||||
let mut account_masks = BTreeMap::new();
|
||||
|
||||
for (acc_addr, acc) in &self.acc_map {
|
||||
account_masks.insert(*acc_addr, acc.make_account_public_mask());
|
||||
}
|
||||
|
||||
PublicSCContext {
|
||||
caller_address: caller,
|
||||
caller_balance: self.acc_map.get(&caller).unwrap().balance,
|
||||
account_masks,
|
||||
comitment_store_root: self.utxo_commitments_store.get_root().unwrap_or([0; 32]),
|
||||
pub_tx_store_root: self.pub_tx_store.get_root().unwrap_or([0; 32]),
|
||||
nullifiers_set: self
|
||||
.nullifier_store
|
||||
.iter()
|
||||
.map(|item| item.utxo_hash)
|
||||
.collect(),
|
||||
commitments_tree: self.utxo_commitments_store.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::config::GasConfig;
|
||||
use accounts::account_core::Account;
|
||||
use common::block::{Block, Data};
|
||||
use common::merkle_tree_public::TreeHashType;
|
||||
use common::transaction::{SignaturePrivateKey, Transaction, TransactionBody, TxKind};
|
||||
use secp256k1_zkp::Tweak;
|
||||
use std::path::PathBuf;
|
||||
use tempfile::tempdir;
|
||||
|
||||
fn create_initial_accounts() -> Vec<Account> {
|
||||
let initial_acc1 = serde_json::from_str(r#"{
|
||||
"address": [
|
||||
244,
|
||||
55,
|
||||
238,
|
||||
205,
|
||||
74,
|
||||
115,
|
||||
179,
|
||||
192,
|
||||
65,
|
||||
186,
|
||||
166,
|
||||
169,
|
||||
221,
|
||||
45,
|
||||
6,
|
||||
57,
|
||||
200,
|
||||
65,
|
||||
195,
|
||||
70,
|
||||
118,
|
||||
252,
|
||||
206,
|
||||
100,
|
||||
215,
|
||||
250,
|
||||
72,
|
||||
230,
|
||||
19,
|
||||
71,
|
||||
217,
|
||||
249
|
||||
],
|
||||
"balance": 100,
|
||||
"key_holder": {
|
||||
"nullifer_public_key": "03A340BECA9FAAB444CED0140681D72EA1318B5C611704FEE017DA9836B17DB718",
|
||||
"pub_account_signing_key": [
|
||||
244,
|
||||
88,
|
||||
134,
|
||||
61,
|
||||
35,
|
||||
209,
|
||||
229,
|
||||
101,
|
||||
85,
|
||||
35,
|
||||
140,
|
||||
140,
|
||||
192,
|
||||
226,
|
||||
83,
|
||||
83,
|
||||
190,
|
||||
189,
|
||||
110,
|
||||
8,
|
||||
89,
|
||||
127,
|
||||
147,
|
||||
142,
|
||||
157,
|
||||
204,
|
||||
51,
|
||||
109,
|
||||
189,
|
||||
92,
|
||||
144,
|
||||
68
|
||||
],
|
||||
"top_secret_key_holder": {
|
||||
"secret_spending_key": "7BC46784DB1BC67825D8F029436846712BFDF9B5D79EA3AB11D39A52B9B229D4"
|
||||
},
|
||||
"utxo_secret_key_holder": {
|
||||
"nullifier_secret_key": "BB54A8D3C9C51B82C431082D1845A74677B0EF829A11B517E1D9885DE3139506",
|
||||
"viewing_secret_key": "AD923E92F6A5683E30140CEAB2702AFB665330C1EE4EFA70FAF29767B6B52BAF"
|
||||
},
|
||||
"viewing_public_key": "0361220C5D277E7A1709340FD31A52600C1432B9C45B9BCF88A43581D58824A8B6"
|
||||
},
|
||||
"utxos": {}
|
||||
}"#).unwrap();
|
||||
|
||||
let initial_acc2 = serde_json::from_str(r#"{
|
||||
"address": [
|
||||
72,
|
||||
169,
|
||||
70,
|
||||
237,
|
||||
1,
|
||||
96,
|
||||
35,
|
||||
157,
|
||||
25,
|
||||
15,
|
||||
83,
|
||||
18,
|
||||
52,
|
||||
206,
|
||||
202,
|
||||
63,
|
||||
48,
|
||||
59,
|
||||
173,
|
||||
76,
|
||||
78,
|
||||
7,
|
||||
254,
|
||||
229,
|
||||
28,
|
||||
45,
|
||||
194,
|
||||
79,
|
||||
6,
|
||||
89,
|
||||
58,
|
||||
85
|
||||
],
|
||||
"balance": 200,
|
||||
"key_holder": {
|
||||
"nullifer_public_key": "02172F50274DE67C4087C344F5D58E11DF761D90285B095060E0994FAA6BCDE271",
|
||||
"pub_account_signing_key": [
|
||||
136,
|
||||
105,
|
||||
9,
|
||||
53,
|
||||
180,
|
||||
145,
|
||||
64,
|
||||
5,
|
||||
235,
|
||||
174,
|
||||
62,
|
||||
211,
|
||||
206,
|
||||
116,
|
||||
185,
|
||||
24,
|
||||
214,
|
||||
62,
|
||||
244,
|
||||
64,
|
||||
224,
|
||||
59,
|
||||
120,
|
||||
150,
|
||||
30,
|
||||
249,
|
||||
160,
|
||||
46,
|
||||
189,
|
||||
254,
|
||||
47,
|
||||
244
|
||||
],
|
||||
"top_secret_key_holder": {
|
||||
"secret_spending_key": "80A186737C8D38B4288A03F0F589957D9C040D79C19F3E0CC4BA80F8494E5179"
|
||||
},
|
||||
"utxo_secret_key_holder": {
|
||||
"nullifier_secret_key": "746928E63F0984F6F4818933493CE9C067562D9CB932FDC06D82C86CDF6D7122",
|
||||
"viewing_secret_key": "89176CF4BC9E673807643FD52110EF99D4894335AFB10D881AC0B5041FE1FCB7"
|
||||
},
|
||||
"viewing_public_key": "026072A8F83FEC3472E30CDD4767683F30B91661D25B1040AD9A5FC2E01D659F99"
|
||||
},
|
||||
"utxos": {}
|
||||
}"#).unwrap();
|
||||
|
||||
let initial_accounts = vec![initial_acc1, initial_acc2];
|
||||
|
||||
initial_accounts
|
||||
}
|
||||
|
||||
fn create_genesis_block() -> Block {
|
||||
Block {
|
||||
block_id: 0,
|
||||
prev_block_id: 0,
|
||||
prev_block_hash: [0; 32],
|
||||
hash: [1; 32],
|
||||
transactions: vec![],
|
||||
data: Data::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn create_dummy_transaction(
|
||||
nullifier_created_hashes: Vec<[u8; 32]>,
|
||||
utxo_commitments_spent_hashes: Vec<[u8; 32]>,
|
||||
utxo_commitments_created_hashes: Vec<[u8; 32]>,
|
||||
) -> Transaction {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let body = TransactionBody {
|
||||
tx_kind: TxKind::Private,
|
||||
execution_input: vec![],
|
||||
execution_output: vec![],
|
||||
utxo_commitments_spent_hashes,
|
||||
utxo_commitments_created_hashes,
|
||||
nullifier_created_hashes,
|
||||
execution_proof_private: "dummy_proof".to_string(),
|
||||
encoded_data: vec![],
|
||||
ephemeral_pub_key: vec![10, 11, 12],
|
||||
commitment: vec![],
|
||||
tweak: Tweak::new(&mut rng),
|
||||
secret_r: [0; 32],
|
||||
sc_addr: "sc_addr".to_string(),
|
||||
state_changes: (serde_json::Value::Null, 0),
|
||||
};
|
||||
Transaction::new(body, SignaturePrivateKey::random(&mut rng))
|
||||
}
|
||||
|
||||
fn create_sample_block(block_id: u64, prev_block_id: u64) -> Block {
|
||||
Block {
|
||||
block_id,
|
||||
prev_block_id,
|
||||
prev_block_hash: [0; 32],
|
||||
hash: [1; 32],
|
||||
transactions: vec![],
|
||||
data: Data::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn create_sample_node_config(home: PathBuf) -> NodeConfig {
|
||||
NodeConfig {
|
||||
home,
|
||||
override_rust_log: None,
|
||||
sequencer_addr: "http://127.0.0.1".to_string(),
|
||||
seq_poll_timeout_secs: 1,
|
||||
port: 8000,
|
||||
gas_config: create_sample_gas_config(),
|
||||
shapshot_frequency_in_blocks: 1,
|
||||
initial_accounts: create_initial_accounts(),
|
||||
}
|
||||
}
|
||||
|
||||
fn create_sample_gas_config() -> GasConfig {
|
||||
GasConfig {
|
||||
gas_fee_per_byte_deploy: 0,
|
||||
gas_fee_per_input_buffer_runtime: 0,
|
||||
gas_fee_per_byte_runtime: 0,
|
||||
gas_cost_runtime: 0,
|
||||
gas_cost_deploy: 0,
|
||||
gas_limit_deploy: 0,
|
||||
gas_limit_runtime: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_dummy_utxo(address: TreeHashType, amount: u128) -> UTXO {
|
||||
UTXO::new(address, vec![], amount, false)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_initializes_correctly() {
|
||||
let temp_dir = tempdir().unwrap();
|
||||
let path = temp_dir.path();
|
||||
|
||||
let config = create_sample_node_config(path.to_path_buf());
|
||||
|
||||
let genesis_block = create_genesis_block();
|
||||
|
||||
let (store, block_id) = NodeChainStore::new(config.clone(), genesis_block.clone()).unwrap();
|
||||
|
||||
assert_eq!(block_id, 0);
|
||||
assert!(store.acc_map.is_empty());
|
||||
assert!(store.nullifier_store.is_empty());
|
||||
assert_eq!(
|
||||
store.utxo_commitments_store.get_root().unwrap_or([0; 32]),
|
||||
[0; 32]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_recovers_from_snapshot() {
|
||||
let temp_dir = tempdir().unwrap();
|
||||
let path = temp_dir.path().to_path_buf();
|
||||
|
||||
let config = create_sample_node_config(path);
|
||||
|
||||
let nullifier_secret_const =
|
||||
"261d61d294ac4bdc24f91b6f490efa263757a4a95f65871cd4f16b2ea23c3b5d";
|
||||
std::env::set_var("NULLIFIER_SECRET_CONST", nullifier_secret_const);
|
||||
|
||||
let viewing_secret_const =
|
||||
"6117af750b30d7a296672ec3b3b25d3489beca3cfe5770fa39f275cec395d5ce";
|
||||
std::env::set_var("VIEWING_SECRET_CONST", viewing_secret_const);
|
||||
|
||||
let genesis_block = create_genesis_block();
|
||||
|
||||
// Initialize once to create DB and store fake snapshot
|
||||
{
|
||||
let (mut store, _) =
|
||||
NodeChainStore::new(config.clone(), genesis_block.clone()).unwrap();
|
||||
|
||||
// Insert state
|
||||
let mut account = Account::new();
|
||||
account
|
||||
.add_new_utxo_outputs(vec![generate_dummy_utxo(account.address, 100)])
|
||||
.unwrap();
|
||||
store.acc_map.insert(account.address, account);
|
||||
store.nullifier_store.insert(UTXONullifier {
|
||||
utxo_hash: [2u8; 32],
|
||||
});
|
||||
store
|
||||
.utxo_commitments_store
|
||||
.add_tx_multiple(vec![UTXOCommitment { hash: [3u8; 32] }]);
|
||||
store.pub_tx_store.add_tx(&create_dummy_transaction(
|
||||
vec![[9; 32]],
|
||||
vec![[7; 32]],
|
||||
vec![[8; 32]],
|
||||
));
|
||||
|
||||
// Put block snapshot to trigger snapshot recovery on next load
|
||||
let dummy_block = create_sample_block(1, 0);
|
||||
|
||||
store.dissect_insert_block(dummy_block).unwrap();
|
||||
}
|
||||
|
||||
// Now reload and verify snapshot is used
|
||||
let (recovered_store, block_id) =
|
||||
NodeChainStore::new_after_restart(config.clone(), genesis_block).unwrap();
|
||||
|
||||
assert_eq!(block_id, 1);
|
||||
assert_eq!(recovered_store.acc_map.len(), 1);
|
||||
assert!(recovered_store.utxo_commitments_store.get_root().is_some());
|
||||
}
|
||||
}
|
||||
1746
node_core/src/lib.rs
1746
node_core/src/lib.rs
File diff suppressed because it is too large
Load Diff
@ -1,71 +0,0 @@
|
||||
use anyhow::Result;
|
||||
use log::info;
|
||||
|
||||
use crate::chain_storage::NodeChainStore;
|
||||
|
||||
///Addres of public fund transfer account, as no such binary exists for zkVM
|
||||
pub const PUBLIC_DEPOSIT_ID: [u8; 32] = [0; 32];
|
||||
|
||||
///Setups public states of default smart conracts as empty
|
||||
pub async fn setup_empty_sc_states(node: &NodeChainStore) -> Result<()> {
|
||||
info!("Filling up public states of default smart contracts");
|
||||
|
||||
let empty_state = vec![];
|
||||
|
||||
let public_deposit_addr = hex::encode(PUBLIC_DEPOSIT_ID);
|
||||
node.block_store.put_sc_sc_state(
|
||||
&public_deposit_addr,
|
||||
empty_state.len(),
|
||||
empty_state.clone(),
|
||||
)?;
|
||||
info!("Public transfer state set");
|
||||
|
||||
let mint_utxo_addr_bytes: Vec<u8> = zkvm::test_methods::MINT_UTXO_ID
|
||||
.iter()
|
||||
.flat_map(|num| num.to_le_bytes())
|
||||
.collect();
|
||||
let mint_utxo_addr = hex::encode(mint_utxo_addr_bytes);
|
||||
node.block_store
|
||||
.put_sc_sc_state(&mint_utxo_addr, empty_state.len(), empty_state.clone())?;
|
||||
info!("Mint UTXO state set");
|
||||
|
||||
let single_utxo_transfer_addr_bytes: Vec<u8> = zkvm::test_methods::SEND_UTXO_ID
|
||||
.iter()
|
||||
.flat_map(|num| num.to_le_bytes())
|
||||
.collect();
|
||||
let single_utxo_transfer_addr = hex::encode(single_utxo_transfer_addr_bytes);
|
||||
node.block_store.put_sc_sc_state(
|
||||
&single_utxo_transfer_addr,
|
||||
empty_state.len(),
|
||||
empty_state.clone(),
|
||||
)?;
|
||||
info!("Single UTXO transfer state set");
|
||||
|
||||
let mint_utxo_multiple_assets_addr_bytes: Vec<u8> =
|
||||
zkvm::test_methods::MINT_UTXO_MULTIPLE_ASSETS_ID
|
||||
.iter()
|
||||
.flat_map(|num| num.to_le_bytes())
|
||||
.collect();
|
||||
let mint_utxo_multiple_assets_addr = hex::encode(mint_utxo_multiple_assets_addr_bytes);
|
||||
node.block_store.put_sc_sc_state(
|
||||
&mint_utxo_multiple_assets_addr,
|
||||
empty_state.len(),
|
||||
empty_state.clone(),
|
||||
)?;
|
||||
info!("Mint UTXO multiple assets state set");
|
||||
|
||||
let multiple_assets_utxo_transfer_addr_bytes: Vec<u8> =
|
||||
zkvm::test_methods::SEND_UTXO_MULTIPLE_ASSETS_ID
|
||||
.iter()
|
||||
.flat_map(|num| num.to_le_bytes())
|
||||
.collect();
|
||||
let multiple_assets_utxo_transfer_addr = hex::encode(multiple_assets_utxo_transfer_addr_bytes);
|
||||
node.block_store.put_sc_sc_state(
|
||||
&multiple_assets_utxo_transfer_addr,
|
||||
empty_state.len(),
|
||||
empty_state.clone(),
|
||||
)?;
|
||||
info!("Multiple_assets UTXO transfer state set");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
[package]
|
||||
name = "node_rpc"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
serde_json.workspace = true
|
||||
env_logger.workspace = true
|
||||
log.workspace = true
|
||||
serde.workspace = true
|
||||
actix.workspace = true
|
||||
actix-cors.workspace = true
|
||||
futures.workspace = true
|
||||
tokio.workspace = true
|
||||
hex.workspace = true
|
||||
|
||||
actix-web.workspace = true
|
||||
|
||||
[dependencies.accounts]
|
||||
path = "../accounts"
|
||||
|
||||
[dependencies.consensus]
|
||||
path = "../consensus"
|
||||
|
||||
[dependencies.networking]
|
||||
path = "../networking"
|
||||
|
||||
[dependencies.storage]
|
||||
path = "../storage"
|
||||
|
||||
[dependencies.utxo]
|
||||
path = "../utxo"
|
||||
|
||||
[dependencies.vm]
|
||||
path = "../vm"
|
||||
|
||||
[dependencies.zkvm]
|
||||
path = "../zkvm"
|
||||
|
||||
[dependencies.node_core]
|
||||
path = "../node_core"
|
||||
|
||||
[dependencies.common]
|
||||
path = "../common"
|
||||
@ -1,45 +0,0 @@
|
||||
pub mod net_utils;
|
||||
pub mod process;
|
||||
pub mod types;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use common::rpc_primitives::{
|
||||
errors::{RpcError, RpcErrorKind},
|
||||
RpcPollingConfig,
|
||||
};
|
||||
use node_core::{config::NodeConfig, NodeCore};
|
||||
use serde::Serialize;
|
||||
use serde_json::Value;
|
||||
|
||||
pub use net_utils::*;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use self::types::err_rpc::RpcErr;
|
||||
|
||||
//ToDo: Add necessary fields
|
||||
pub struct JsonHandler {
|
||||
pub polling_config: RpcPollingConfig,
|
||||
pub node_core_config: NodeConfig,
|
||||
pub node_chain_store: Arc<Mutex<NodeCore>>,
|
||||
}
|
||||
|
||||
fn respond<T: Serialize>(val: T) -> Result<Value, RpcErr> {
|
||||
Ok(serde_json::to_value(val)?)
|
||||
}
|
||||
|
||||
pub fn rpc_error_responce_inverter(err: RpcError) -> RpcError {
|
||||
let mut content: Option<Value> = None;
|
||||
if err.error_struct.is_some() {
|
||||
content = match err.error_struct.clone().unwrap() {
|
||||
RpcErrorKind::HandlerError(val) | RpcErrorKind::InternalError(val) => Some(val),
|
||||
RpcErrorKind::RequestValidationError(vall) => Some(serde_json::to_value(vall).unwrap()),
|
||||
};
|
||||
}
|
||||
RpcError {
|
||||
error_struct: None,
|
||||
code: err.code,
|
||||
message: err.message,
|
||||
data: content,
|
||||
}
|
||||
}
|
||||
@ -1,76 +0,0 @@
|
||||
use std::io;
|
||||
use std::sync::Arc;
|
||||
|
||||
use actix_cors::Cors;
|
||||
use actix_web::{http, middleware, web, App, Error as HttpError, HttpResponse, HttpServer};
|
||||
use futures::Future;
|
||||
use futures::FutureExt;
|
||||
use log::info;
|
||||
|
||||
use common::rpc_primitives::message::Message;
|
||||
use common::rpc_primitives::RpcConfig;
|
||||
use node_core::config::NodeConfig;
|
||||
use node_core::NodeCore;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use super::JsonHandler;
|
||||
|
||||
pub const SHUTDOWN_TIMEOUT_SECS: u64 = 10;
|
||||
|
||||
fn rpc_handler(
|
||||
message: web::Json<Message>,
|
||||
handler: web::Data<JsonHandler>,
|
||||
) -> impl Future<Output = Result<HttpResponse, HttpError>> {
|
||||
let response = async move {
|
||||
let message = handler.process(message.0).await?;
|
||||
Ok(HttpResponse::Ok().json(&message))
|
||||
};
|
||||
response.boxed()
|
||||
}
|
||||
|
||||
fn get_cors(cors_allowed_origins: &[String]) -> Cors {
|
||||
let mut cors = Cors::permissive();
|
||||
if cors_allowed_origins != ["*".to_string()] {
|
||||
for origin in cors_allowed_origins {
|
||||
cors = cors.allowed_origin(origin);
|
||||
}
|
||||
}
|
||||
cors.allowed_methods(vec!["GET", "POST"])
|
||||
.allowed_headers(vec![http::header::AUTHORIZATION, http::header::ACCEPT])
|
||||
.allowed_header(http::header::CONTENT_TYPE)
|
||||
.max_age(3600)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new_http_server(
|
||||
config: RpcConfig,
|
||||
node_config: NodeConfig,
|
||||
node_chain_store: Arc<Mutex<NodeCore>>,
|
||||
) -> io::Result<actix_web::dev::Server> {
|
||||
let RpcConfig {
|
||||
addr,
|
||||
cors_allowed_origins,
|
||||
polling_config,
|
||||
limits_config,
|
||||
} = config;
|
||||
info!(target:"network", "Starting http server at {addr}");
|
||||
let handler = web::Data::new(JsonHandler {
|
||||
polling_config,
|
||||
node_core_config: node_config,
|
||||
node_chain_store,
|
||||
});
|
||||
|
||||
// HTTP server
|
||||
Ok(HttpServer::new(move || {
|
||||
App::new()
|
||||
.wrap(get_cors(&cors_allowed_origins))
|
||||
.app_data(handler.clone())
|
||||
.app_data(web::JsonConfig::default().limit(limits_config.json_payload_max_size))
|
||||
.wrap(middleware::Logger::default())
|
||||
.service(web::resource("/").route(web::post().to(rpc_handler)))
|
||||
})
|
||||
.bind(addr)?
|
||||
.shutdown_timeout(SHUTDOWN_TIMEOUT_SECS)
|
||||
.disable_signals()
|
||||
.run())
|
||||
}
|
||||
@ -1,755 +0,0 @@
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use actix_web::Error as HttpError;
|
||||
use node_core::generate_commitments_helper;
|
||||
use serde_json::Value;
|
||||
|
||||
use common::rpc_primitives::{
|
||||
errors::RpcError,
|
||||
message::{Message, Request},
|
||||
parser::RpcRequest,
|
||||
};
|
||||
use common::transaction::ActionData;
|
||||
|
||||
use common::rpc_primitives::requests::{
|
||||
GetBlockDataRequest, GetBlockDataResponse, GetLastBlockRequest, GetLastBlockResponse,
|
||||
};
|
||||
|
||||
use crate::types::{
|
||||
err_rpc::cast_common_execution_error_into_rpc_error,
|
||||
rpc_structs::{
|
||||
CreateAccountRequest, CreateAccountResponse, ExecuteScenarioMultipleSendRequest,
|
||||
ExecuteScenarioMultipleSendResponse, ExecuteScenarioSplitRequest,
|
||||
ExecuteScenarioSplitResponse, ExecuteSubscenarioRequest, ExecuteSubscenarioResponse,
|
||||
ShowAccountPublicBalanceRequest, ShowAccountPublicBalanceResponse, ShowAccountUTXORequest,
|
||||
ShowAccountUTXOResponse, ShowTransactionRequest, ShowTransactionResponse,
|
||||
UTXOShortEssentialStruct, WriteMintPrivateUTXOMultipleAssetsRequest,
|
||||
WriteMintPrivateUTXOMultipleAssetsResponse, WriteMintPrivateUTXORequest,
|
||||
WriteMintPrivateUTXOResponse, WriteSendDeshieldedBalanceRequest,
|
||||
WriteSendDeshieldedUTXOResponse, WriteSendPrivateUTXORequest, WriteSendPrivateUTXOResponse,
|
||||
WriteSendShieldedUTXORequest, WriteSendShieldedUTXOResponse, WriteSendSplitUTXOResponse,
|
||||
WriteSplitUTXORequest,
|
||||
},
|
||||
};
|
||||
|
||||
pub const CREATE_ACCOUNT: &str = "create_account";
|
||||
pub const EXECUTE_SUBSCENARIO: &str = "execute_subscenario";
|
||||
pub const GET_BLOCK: &str = "get_block";
|
||||
pub const GET_LAST_BLOCK: &str = "get_last_block";
|
||||
pub const EXECUTE_SCENARIO_SPLIT: &str = "execute_scenario_split";
|
||||
pub const EXECUTE_SCENARIO_MULTIPLE_SEND: &str = "execute_scenario_multiple_send";
|
||||
pub const SHOW_ACCOUNT_PUBLIC_BALANCE: &str = "show_account_public_balance";
|
||||
pub const SHOW_ACCOUNT_UTXO: &str = "show_account_utxo";
|
||||
pub const SHOW_TRANSACTION: &str = "show_transaction";
|
||||
pub const WRITE_MINT_UTXO: &str = "write_mint_utxo";
|
||||
pub const WRITE_MINT_UTXO_MULTIPLE_ASSETS: &str = "write_mint_utxo_multiple_assets";
|
||||
pub const WRITE_SEND_UTXO_PRIVATE: &str = "write_send_utxo_private";
|
||||
pub const WRITE_SEND_UTXO_SHIELDED: &str = "write_send_utxo_shielded";
|
||||
pub const WRITE_SEND_UTXO_DESHIELDED: &str = "write_send_utxo_deshielded";
|
||||
pub const WRITE_SPLIT_UTXO: &str = "write_split_utxo";
|
||||
|
||||
pub const SUCCESS: &str = "success";
|
||||
|
||||
pub const ACCOUNT_NOT_FOUND: &str = "Account not found";
|
||||
pub const TRANSACTION_NOT_FOUND: &str = "Transaction not found";
|
||||
|
||||
use super::{respond, types::err_rpc::RpcErr, JsonHandler};
|
||||
|
||||
impl JsonHandler {
|
||||
pub async fn process(&self, message: Message) -> Result<Message, HttpError> {
|
||||
let id = message.id();
|
||||
if let Message::Request(request) = message {
|
||||
let message_inner = self
|
||||
.process_request_internal(request)
|
||||
.await
|
||||
.map_err(|e| e.0);
|
||||
Ok(Message::response(id, message_inner))
|
||||
} else {
|
||||
Ok(Message::error(RpcError::parse_error(
|
||||
"JSON RPC Request format was expected".to_owned(),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
async fn process_request_execute_subscenario(&self, request: Request) -> Result<Value, RpcErr> {
|
||||
let req = ExecuteSubscenarioRequest::parse(Some(request.params))?;
|
||||
|
||||
{
|
||||
let mut store = self.node_chain_store.lock().await;
|
||||
|
||||
match req.scenario_id {
|
||||
1 => store
|
||||
.subscenario_1()
|
||||
.await
|
||||
.map_err(cast_common_execution_error_into_rpc_error)?,
|
||||
2 => store
|
||||
.subscenario_2()
|
||||
.await
|
||||
.map_err(cast_common_execution_error_into_rpc_error)?,
|
||||
3 => store
|
||||
.subscenario_3()
|
||||
.await
|
||||
.map_err(cast_common_execution_error_into_rpc_error)?,
|
||||
_ => return Err(RpcErr(RpcError::invalid_params("Scenario id not found"))),
|
||||
}
|
||||
}
|
||||
|
||||
let helperstruct = ExecuteSubscenarioResponse {
|
||||
scenario_result: SUCCESS.to_string(),
|
||||
};
|
||||
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
async fn process_request_execute_scenario_split(
|
||||
&self,
|
||||
request: Request,
|
||||
) -> Result<Value, RpcErr> {
|
||||
let req = ExecuteScenarioSplitRequest::parse(Some(request.params))?;
|
||||
|
||||
{
|
||||
let mut store = self.node_chain_store.lock().await;
|
||||
|
||||
store
|
||||
.scenario_1(req.visibility_list, req.publication_index)
|
||||
.await
|
||||
.map_err(cast_common_execution_error_into_rpc_error)?;
|
||||
}
|
||||
|
||||
let helperstruct = ExecuteScenarioSplitResponse {
|
||||
scenario_result: SUCCESS.to_string(),
|
||||
};
|
||||
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
async fn process_request_execute_scenario_multiple_send(
|
||||
&self,
|
||||
request: Request,
|
||||
) -> Result<Value, RpcErr> {
|
||||
let req = ExecuteScenarioMultipleSendRequest::parse(Some(request.params))?;
|
||||
|
||||
{
|
||||
let mut store = self.node_chain_store.lock().await;
|
||||
|
||||
store
|
||||
.scenario_2(req.number_of_assets, req.number_to_send)
|
||||
.await
|
||||
.map_err(cast_common_execution_error_into_rpc_error)?;
|
||||
}
|
||||
|
||||
let helperstruct = ExecuteScenarioMultipleSendResponse {
|
||||
scenario_result: SUCCESS.to_string(),
|
||||
};
|
||||
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
async fn process_create_account(&self, request: Request) -> Result<Value, RpcErr> {
|
||||
let _req = CreateAccountRequest::parse(Some(request.params))?;
|
||||
|
||||
let acc_addr = {
|
||||
let mut guard = self.node_chain_store.lock().await;
|
||||
|
||||
guard.create_new_account().await
|
||||
};
|
||||
|
||||
let helperstruct = CreateAccountResponse {
|
||||
status: hex::encode(acc_addr),
|
||||
};
|
||||
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
async fn process_get_block_data(&self, request: Request) -> Result<Value, RpcErr> {
|
||||
let req = GetBlockDataRequest::parse(Some(request.params))?;
|
||||
|
||||
let block = {
|
||||
let guard = self.node_chain_store.lock().await;
|
||||
|
||||
{
|
||||
let read_guard = guard.storage.read().await;
|
||||
|
||||
read_guard.block_store.get_block_at_id(req.block_id)?
|
||||
}
|
||||
};
|
||||
|
||||
let helperstruct = GetBlockDataResponse { block };
|
||||
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
async fn process_get_last_block(&self, request: Request) -> Result<Value, RpcErr> {
|
||||
let _req = GetLastBlockRequest::parse(Some(request.params))?;
|
||||
|
||||
let last_block = {
|
||||
let guard = self.node_chain_store.lock().await;
|
||||
|
||||
guard.curr_height.load(Ordering::Relaxed)
|
||||
};
|
||||
|
||||
let helperstruct = GetLastBlockResponse { last_block };
|
||||
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
async fn process_show_account_public_balance(&self, request: Request) -> Result<Value, RpcErr> {
|
||||
let req = ShowAccountPublicBalanceRequest::parse(Some(request.params))?;
|
||||
|
||||
let acc_addr_hex_dec = hex::decode(req.account_addr.clone()).map_err(|_| {
|
||||
RpcError::parse_error("Failed to decode account address from hex string".to_string())
|
||||
})?;
|
||||
|
||||
let acc_addr: [u8; 32] = acc_addr_hex_dec.try_into().map_err(|_| {
|
||||
RpcError::parse_error("Failed to parse account address from bytes".to_string())
|
||||
})?;
|
||||
|
||||
let balance = {
|
||||
let cover_guard = self.node_chain_store.lock().await;
|
||||
|
||||
{
|
||||
let under_guard = cover_guard.storage.read().await;
|
||||
|
||||
let acc = under_guard
|
||||
.acc_map
|
||||
.get(&acc_addr)
|
||||
.ok_or(RpcError::new_internal_error(None, ACCOUNT_NOT_FOUND))?;
|
||||
|
||||
acc.balance
|
||||
}
|
||||
};
|
||||
|
||||
let helperstruct = ShowAccountPublicBalanceResponse {
|
||||
addr: req.account_addr,
|
||||
balance,
|
||||
};
|
||||
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
async fn process_show_account_utxo_request(&self, request: Request) -> Result<Value, RpcErr> {
|
||||
let req = ShowAccountUTXORequest::parse(Some(request.params))?;
|
||||
|
||||
let acc_addr_hex_dec = hex::decode(req.account_addr.clone()).map_err(|_| {
|
||||
RpcError::parse_error("Failed to decode account address from hex string".to_string())
|
||||
})?;
|
||||
|
||||
let acc_addr: [u8; 32] = acc_addr_hex_dec.try_into().map_err(|_| {
|
||||
RpcError::parse_error("Failed to parse account address from bytes".to_string())
|
||||
})?;
|
||||
|
||||
let utxo_hash_hex_dec = hex::decode(req.utxo_hash.clone()).map_err(|_| {
|
||||
RpcError::parse_error("Failed to decode hash from hex string".to_string())
|
||||
})?;
|
||||
|
||||
let utxo_hash: [u8; 32] = utxo_hash_hex_dec
|
||||
.try_into()
|
||||
.map_err(|_| RpcError::parse_error("Failed to parse hash from bytes".to_string()))?;
|
||||
|
||||
let (asset, amount) = {
|
||||
let cover_guard = self.node_chain_store.lock().await;
|
||||
|
||||
{
|
||||
let mut under_guard = cover_guard.storage.write().await;
|
||||
|
||||
let acc = under_guard
|
||||
.acc_map
|
||||
.get_mut(&acc_addr)
|
||||
.ok_or(RpcError::new_internal_error(None, ACCOUNT_NOT_FOUND))?;
|
||||
|
||||
let utxo = acc
|
||||
.utxos
|
||||
.get(&utxo_hash)
|
||||
.ok_or(RpcError::new_internal_error(
|
||||
None,
|
||||
"UTXO does not exist in the tree",
|
||||
))?;
|
||||
|
||||
(utxo.asset.clone(), utxo.amount)
|
||||
}
|
||||
};
|
||||
|
||||
let helperstruct = ShowAccountUTXOResponse {
|
||||
hash: req.utxo_hash,
|
||||
asset,
|
||||
amount,
|
||||
};
|
||||
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
async fn process_show_transaction(&self, request: Request) -> Result<Value, RpcErr> {
|
||||
let req = ShowTransactionRequest::parse(Some(request.params))?;
|
||||
|
||||
let tx_hash_hex_dec = hex::decode(req.tx_hash.clone()).map_err(|_| {
|
||||
RpcError::parse_error("Failed to decode hash from hex string".to_string())
|
||||
})?;
|
||||
|
||||
let tx_hash: [u8; 32] = tx_hash_hex_dec
|
||||
.try_into()
|
||||
.map_err(|_| RpcError::parse_error("Failed to parse hash from bytes".to_string()))?;
|
||||
|
||||
let helperstruct = {
|
||||
let cover_guard = self.node_chain_store.lock().await;
|
||||
|
||||
{
|
||||
let under_guard = cover_guard.storage.read().await;
|
||||
|
||||
let tx = under_guard
|
||||
.pub_tx_store
|
||||
.get_tx(tx_hash)
|
||||
.ok_or(RpcError::new_internal_error(None, TRANSACTION_NOT_FOUND))?;
|
||||
|
||||
ShowTransactionResponse {
|
||||
hash: req.tx_hash,
|
||||
tx_kind: tx.body().tx_kind,
|
||||
public_input: if let Ok(action) =
|
||||
serde_json::from_slice::<ActionData>(&tx.body().execution_input)
|
||||
{
|
||||
action.into_hexed_print()
|
||||
} else {
|
||||
"".to_string()
|
||||
},
|
||||
public_output: if let Ok(action) =
|
||||
serde_json::from_slice::<ActionData>(&tx.body().execution_output)
|
||||
{
|
||||
action.into_hexed_print()
|
||||
} else {
|
||||
"".to_string()
|
||||
},
|
||||
utxo_commitments_created_hashes: tx
|
||||
.body()
|
||||
.utxo_commitments_created_hashes
|
||||
.iter()
|
||||
.map(hex::encode)
|
||||
.collect::<Vec<_>>(),
|
||||
utxo_commitments_spent_hashes: tx
|
||||
.body()
|
||||
.utxo_commitments_spent_hashes
|
||||
.iter()
|
||||
.map(hex::encode)
|
||||
.collect::<Vec<_>>(),
|
||||
utxo_nullifiers_created_hashes: tx
|
||||
.body()
|
||||
.nullifier_created_hashes
|
||||
.iter()
|
||||
.map(hex::encode)
|
||||
.collect::<Vec<_>>(),
|
||||
encoded_data: tx
|
||||
.body()
|
||||
.encoded_data
|
||||
.iter()
|
||||
.map(|val| (hex::encode(val.0.clone()), hex::encode(val.1.clone())))
|
||||
.collect::<Vec<_>>(),
|
||||
ephemeral_pub_key: hex::encode(tx.body().ephemeral_pub_key.clone()),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
pub async fn process_write_mint_utxo(&self, request: Request) -> Result<Value, RpcErr> {
|
||||
let req = WriteMintPrivateUTXORequest::parse(Some(request.params))?;
|
||||
|
||||
let acc_addr_hex_dec = hex::decode(req.account_addr.clone()).map_err(|_| {
|
||||
RpcError::parse_error("Failed to decode account address from hex string".to_string())
|
||||
})?;
|
||||
|
||||
let acc_addr: [u8; 32] = acc_addr_hex_dec.try_into().map_err(|_| {
|
||||
RpcError::parse_error("Failed to parse account address from bytes".to_string())
|
||||
})?;
|
||||
|
||||
let (utxo, commitment_hash) = {
|
||||
let mut cover_guard = self.node_chain_store.lock().await;
|
||||
|
||||
cover_guard
|
||||
.operate_account_mint_private(acc_addr, req.amount as u128)
|
||||
.await
|
||||
.map_err(cast_common_execution_error_into_rpc_error)?
|
||||
};
|
||||
|
||||
let helperstruct = WriteMintPrivateUTXOResponse {
|
||||
status: SUCCESS.to_string(),
|
||||
utxo: UTXOShortEssentialStruct {
|
||||
hash: hex::encode(utxo.hash),
|
||||
commitment_hash: hex::encode(commitment_hash),
|
||||
asset: utxo.asset,
|
||||
},
|
||||
};
|
||||
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
pub async fn process_write_mint_utxo_multiple_assets(
|
||||
&self,
|
||||
request: Request,
|
||||
) -> Result<Value, RpcErr> {
|
||||
let req = WriteMintPrivateUTXOMultipleAssetsRequest::parse(Some(request.params))?;
|
||||
|
||||
let acc_addr_hex_dec = hex::decode(req.account_addr.clone()).map_err(|_| {
|
||||
RpcError::parse_error("Failed to decode account address from hex string".to_string())
|
||||
})?;
|
||||
|
||||
let acc_addr: [u8; 32] = acc_addr_hex_dec.try_into().map_err(|_| {
|
||||
RpcError::parse_error("Failed to parse account address from bytes".to_string())
|
||||
})?;
|
||||
|
||||
let (utxos, commitment_hashes) = {
|
||||
let mut cover_guard = self.node_chain_store.lock().await;
|
||||
|
||||
cover_guard
|
||||
.operate_account_mint_multiple_assets_private(
|
||||
acc_addr,
|
||||
req.amount as u128,
|
||||
req.num_of_assets,
|
||||
)
|
||||
.await
|
||||
.map_err(cast_common_execution_error_into_rpc_error)?
|
||||
};
|
||||
|
||||
let helperstruct = WriteMintPrivateUTXOMultipleAssetsResponse {
|
||||
status: SUCCESS.to_string(),
|
||||
utxos: utxos
|
||||
.into_iter()
|
||||
.zip(commitment_hashes)
|
||||
.map(|(utxo, comm_hash)| UTXOShortEssentialStruct {
|
||||
hash: hex::encode(utxo.hash),
|
||||
commitment_hash: hex::encode(comm_hash),
|
||||
asset: utxo.asset,
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
pub async fn process_write_send_private_utxo(&self, request: Request) -> Result<Value, RpcErr> {
|
||||
let req = WriteSendPrivateUTXORequest::parse(Some(request.params))?;
|
||||
|
||||
let acc_addr_hex_dec_sender =
|
||||
hex::decode(req.account_addr_sender.clone()).map_err(|_| {
|
||||
RpcError::parse_error(
|
||||
"Failed to decode account address from hex string".to_string(),
|
||||
)
|
||||
})?;
|
||||
|
||||
let acc_addr_sender: [u8; 32] = acc_addr_hex_dec_sender.try_into().map_err(|_| {
|
||||
RpcError::parse_error("Failed to parse account address from bytes".to_string())
|
||||
})?;
|
||||
|
||||
let acc_addr_hex_dec = hex::decode(req.account_addr_receiver.clone()).map_err(|_| {
|
||||
RpcError::parse_error("Failed to decode account address from hex string".to_string())
|
||||
})?;
|
||||
|
||||
let acc_addr: [u8; 32] = acc_addr_hex_dec.try_into().map_err(|_| {
|
||||
RpcError::parse_error("Failed to parse account address from bytes".to_string())
|
||||
})?;
|
||||
|
||||
let utxo_hash_hex_dec = hex::decode(req.utxo_hash.clone()).map_err(|_| {
|
||||
RpcError::parse_error("Failed to decode utxo hash from hex string".to_string())
|
||||
})?;
|
||||
|
||||
let utxo_hash: [u8; 32] = utxo_hash_hex_dec.try_into().map_err(|_| {
|
||||
RpcError::parse_error("Failed to parse utxo hash from bytes".to_string())
|
||||
})?;
|
||||
|
||||
let comm_hash_hex_dec = hex::decode(req.utxo_commitment.clone()).map_err(|_| {
|
||||
RpcError::parse_error("Failed to decode commitment hash from hex string".to_string())
|
||||
})?;
|
||||
|
||||
let comm_hash: [u8; 32] = comm_hash_hex_dec.try_into().map_err(|_| {
|
||||
RpcError::parse_error("Failed to parse commitment hash from bytes".to_string())
|
||||
})?;
|
||||
|
||||
let new_utxo_rec = {
|
||||
let mut cover_guard = self.node_chain_store.lock().await;
|
||||
|
||||
let utxo_to_send = {
|
||||
let mut under_guard = cover_guard.storage.write().await;
|
||||
|
||||
let acc = under_guard
|
||||
.acc_map
|
||||
.get_mut(&acc_addr_sender)
|
||||
.ok_or(RpcError::new_internal_error(None, ACCOUNT_NOT_FOUND))?;
|
||||
|
||||
acc.utxos
|
||||
.get(&utxo_hash)
|
||||
.ok_or(RpcError::new_internal_error(
|
||||
None,
|
||||
"UTXO does not exist in tree",
|
||||
))?
|
||||
.clone()
|
||||
};
|
||||
|
||||
cover_guard
|
||||
.operate_account_send_private_one_receiver(acc_addr, utxo_to_send, comm_hash)
|
||||
.await
|
||||
.map_err(cast_common_execution_error_into_rpc_error)?
|
||||
};
|
||||
|
||||
let helperstruct = WriteSendPrivateUTXOResponse {
|
||||
status: SUCCESS.to_string(),
|
||||
utxo_result: UTXOShortEssentialStruct {
|
||||
hash: hex::encode(new_utxo_rec.hash),
|
||||
asset: new_utxo_rec.asset.clone(),
|
||||
commitment_hash: hex::encode(generate_commitments_helper(&[new_utxo_rec])[0]),
|
||||
},
|
||||
};
|
||||
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
pub async fn process_write_send_shielded_utxo(
|
||||
&self,
|
||||
request: Request,
|
||||
) -> Result<Value, RpcErr> {
|
||||
let req = WriteSendShieldedUTXORequest::parse(Some(request.params))?;
|
||||
|
||||
let acc_addr_hex_dec_sender =
|
||||
hex::decode(req.account_addr_sender.clone()).map_err(|_| {
|
||||
RpcError::parse_error(
|
||||
"Failed to decode account address sender from hex string".to_string(),
|
||||
)
|
||||
})?;
|
||||
|
||||
let acc_addr_sender: [u8; 32] = acc_addr_hex_dec_sender.try_into().map_err(|_| {
|
||||
RpcError::parse_error("Failed to parse account address sender from bytes".to_string())
|
||||
})?;
|
||||
|
||||
let acc_addr_hex_dec_rec =
|
||||
hex::decode(req.account_addr_receiver.clone()).map_err(|_| {
|
||||
RpcError::parse_error(
|
||||
"Failed to decode account address receiver from hex string".to_string(),
|
||||
)
|
||||
})?;
|
||||
|
||||
let acc_addr_rec: [u8; 32] = acc_addr_hex_dec_rec.try_into().map_err(|_| {
|
||||
RpcError::parse_error("Failed to parse account address receiver from bytes".to_string())
|
||||
})?;
|
||||
|
||||
let new_utxo_rec = {
|
||||
let mut cover_guard = self.node_chain_store.lock().await;
|
||||
|
||||
cover_guard
|
||||
.operate_account_send_shielded_one_receiver(
|
||||
acc_addr_sender,
|
||||
acc_addr_rec,
|
||||
req.amount as u128,
|
||||
)
|
||||
.await
|
||||
.map_err(cast_common_execution_error_into_rpc_error)?
|
||||
};
|
||||
|
||||
let helperstruct = WriteSendShieldedUTXOResponse {
|
||||
status: SUCCESS.to_string(),
|
||||
utxo_result: UTXOShortEssentialStruct {
|
||||
hash: hex::encode(new_utxo_rec.hash),
|
||||
asset: new_utxo_rec.asset.clone(),
|
||||
commitment_hash: hex::encode(generate_commitments_helper(&[new_utxo_rec])[0]),
|
||||
},
|
||||
};
|
||||
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
pub async fn process_write_send_deshielded_utxo(
|
||||
&self,
|
||||
request: Request,
|
||||
) -> Result<Value, RpcErr> {
|
||||
let req = WriteSendDeshieldedBalanceRequest::parse(Some(request.params))?;
|
||||
|
||||
let acc_addr_hex_dec_sender =
|
||||
hex::decode(req.account_addr_sender.clone()).map_err(|_| {
|
||||
RpcError::parse_error(
|
||||
"Failed to decode account address from hex string".to_string(),
|
||||
)
|
||||
})?;
|
||||
|
||||
let acc_addr_sender: [u8; 32] = acc_addr_hex_dec_sender.try_into().map_err(|_| {
|
||||
RpcError::parse_error("Failed to parse account address from bytes".to_string())
|
||||
})?;
|
||||
|
||||
let acc_addr_hex_dec = hex::decode(req.account_addr_receiver.clone()).map_err(|_| {
|
||||
RpcError::parse_error("Failed to decode account address from hex string".to_string())
|
||||
})?;
|
||||
|
||||
let acc_addr: [u8; 32] = acc_addr_hex_dec.try_into().map_err(|_| {
|
||||
RpcError::parse_error("Failed to parse account address from bytes".to_string())
|
||||
})?;
|
||||
|
||||
let utxo_hash_hex_dec = hex::decode(req.utxo_hash.clone()).map_err(|_| {
|
||||
RpcError::parse_error("Failed to decode utxo hash from hex string".to_string())
|
||||
})?;
|
||||
|
||||
let utxo_hash: [u8; 32] = utxo_hash_hex_dec.try_into().map_err(|_| {
|
||||
RpcError::parse_error("Failed to parse utxo hash from bytes".to_string())
|
||||
})?;
|
||||
|
||||
let comm_hash_hex_dec = hex::decode(req.utxo_commitment.clone()).map_err(|_| {
|
||||
RpcError::parse_error("Failed to decode commitment hash from hex string".to_string())
|
||||
})?;
|
||||
|
||||
let comm_hash: [u8; 32] = comm_hash_hex_dec.try_into().map_err(|_| {
|
||||
RpcError::parse_error("Failed to parse commitment hash from bytes".to_string())
|
||||
})?;
|
||||
|
||||
{
|
||||
let mut cover_guard = self.node_chain_store.lock().await;
|
||||
|
||||
let utxo_to_send = {
|
||||
let mut under_guard = cover_guard.storage.write().await;
|
||||
|
||||
let acc = under_guard
|
||||
.acc_map
|
||||
.get_mut(&acc_addr_sender)
|
||||
.ok_or(RpcError::new_internal_error(None, ACCOUNT_NOT_FOUND))?;
|
||||
|
||||
acc.utxos
|
||||
.get(&utxo_hash)
|
||||
.ok_or(RpcError::new_internal_error(
|
||||
None,
|
||||
"UTXO does not exist in tree",
|
||||
))?
|
||||
.clone()
|
||||
};
|
||||
|
||||
cover_guard
|
||||
.operate_account_send_deshielded_one_receiver(acc_addr, utxo_to_send, comm_hash)
|
||||
.await
|
||||
.map_err(cast_common_execution_error_into_rpc_error)?
|
||||
};
|
||||
|
||||
let helperstruct = WriteSendDeshieldedUTXOResponse {
|
||||
status: SUCCESS.to_string(),
|
||||
};
|
||||
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
pub async fn process_write_send_split_utxo(&self, request: Request) -> Result<Value, RpcErr> {
|
||||
let req = WriteSplitUTXORequest::parse(Some(request.params))?;
|
||||
|
||||
let acc_addr_hex_dec_sender =
|
||||
hex::decode(req.account_addr_sender.clone()).map_err(|_| {
|
||||
RpcError::parse_error(
|
||||
"Failed to decode account address from hex string".to_string(),
|
||||
)
|
||||
})?;
|
||||
|
||||
let acc_addr_sender: [u8; 32] = acc_addr_hex_dec_sender.try_into().map_err(|_| {
|
||||
RpcError::parse_error("Failed to parse account address from bytes".to_string())
|
||||
})?;
|
||||
|
||||
let acc_addresses = {
|
||||
let mut res_addrs = vec![];
|
||||
|
||||
for item in req.account_addr_receivers {
|
||||
let hex_dec_item = hex::decode(item).map_err(|_| {
|
||||
RpcError::parse_error(
|
||||
"Failed to decode account address from hex string".to_string(),
|
||||
)
|
||||
})?;
|
||||
|
||||
let dec_item = hex_dec_item.try_into().map_err(|_| {
|
||||
RpcError::parse_error(
|
||||
"Failed to decode account address from hex string".to_string(),
|
||||
)
|
||||
})?;
|
||||
|
||||
res_addrs.push(dec_item);
|
||||
}
|
||||
|
||||
res_addrs.try_into().unwrap()
|
||||
};
|
||||
|
||||
let utxo_hash_hex_dec = hex::decode(req.utxo_hash.clone()).map_err(|_| {
|
||||
RpcError::parse_error("Failed to decode utxo hash from hex string".to_string())
|
||||
})?;
|
||||
|
||||
let utxo_hash: [u8; 32] = utxo_hash_hex_dec.try_into().map_err(|_| {
|
||||
RpcError::parse_error("Failed to parse utxo hash from bytes".to_string())
|
||||
})?;
|
||||
|
||||
let comm_hash_hex_dec = hex::decode(req.utxo_commitment.clone()).map_err(|_| {
|
||||
RpcError::parse_error("Failed to decode commitment hash from hex string".to_string())
|
||||
})?;
|
||||
|
||||
let comm_hash: [u8; 32] = comm_hash_hex_dec.try_into().map_err(|_| {
|
||||
RpcError::parse_error("Failed to parse commitment hash from bytes".to_string())
|
||||
})?;
|
||||
|
||||
let (new_utxos, commitment_hashes) = {
|
||||
let mut cover_guard = self.node_chain_store.lock().await;
|
||||
|
||||
let utxo_to_send = {
|
||||
let mut under_guard = cover_guard.storage.write().await;
|
||||
|
||||
let acc = under_guard
|
||||
.acc_map
|
||||
.get_mut(&acc_addr_sender)
|
||||
.ok_or(RpcError::new_internal_error(None, ACCOUNT_NOT_FOUND))?;
|
||||
|
||||
acc.utxos
|
||||
.get(&utxo_hash)
|
||||
.ok_or(RpcError::new_internal_error(
|
||||
None,
|
||||
"UTXO does not exist in tree",
|
||||
))?
|
||||
.clone()
|
||||
};
|
||||
|
||||
cover_guard
|
||||
.operate_account_send_split_utxo(
|
||||
acc_addresses,
|
||||
utxo_to_send,
|
||||
comm_hash,
|
||||
req.visibility_list,
|
||||
)
|
||||
.await
|
||||
.map_err(cast_common_execution_error_into_rpc_error)?
|
||||
};
|
||||
|
||||
let helperstruct = WriteSendSplitUTXOResponse {
|
||||
status: SUCCESS.to_string(),
|
||||
utxo_results: new_utxos
|
||||
.into_iter()
|
||||
.zip(commitment_hashes)
|
||||
.map(|(utxo, comm_hash)| UTXOShortEssentialStruct {
|
||||
hash: hex::encode(utxo.hash),
|
||||
commitment_hash: hex::encode(comm_hash),
|
||||
asset: utxo.asset,
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
|
||||
respond(helperstruct)
|
||||
}
|
||||
|
||||
pub async fn process_request_internal(&self, request: Request) -> Result<Value, RpcErr> {
|
||||
match request.method.as_ref() {
|
||||
//Todo : Add handling of more JSON RPC methods
|
||||
CREATE_ACCOUNT => self.process_create_account(request).await,
|
||||
EXECUTE_SUBSCENARIO => self.process_request_execute_subscenario(request).await,
|
||||
GET_BLOCK => self.process_get_block_data(request).await,
|
||||
GET_LAST_BLOCK => self.process_get_last_block(request).await,
|
||||
EXECUTE_SCENARIO_SPLIT => self.process_request_execute_scenario_split(request).await,
|
||||
EXECUTE_SCENARIO_MULTIPLE_SEND => {
|
||||
self.process_request_execute_scenario_multiple_send(request)
|
||||
.await
|
||||
}
|
||||
SHOW_ACCOUNT_PUBLIC_BALANCE => self.process_show_account_public_balance(request).await,
|
||||
SHOW_ACCOUNT_UTXO => self.process_show_account_utxo_request(request).await,
|
||||
SHOW_TRANSACTION => self.process_show_transaction(request).await,
|
||||
WRITE_MINT_UTXO => self.process_write_mint_utxo(request).await,
|
||||
WRITE_MINT_UTXO_MULTIPLE_ASSETS => {
|
||||
self.process_write_mint_utxo_multiple_assets(request).await
|
||||
}
|
||||
WRITE_SEND_UTXO_PRIVATE => self.process_write_send_private_utxo(request).await,
|
||||
WRITE_SEND_UTXO_SHIELDED => self.process_write_send_shielded_utxo(request).await,
|
||||
WRITE_SEND_UTXO_DESHIELDED => self.process_write_send_deshielded_utxo(request).await,
|
||||
WRITE_SPLIT_UTXO => self.process_write_send_split_utxo(request).await,
|
||||
_ => Err(RpcErr(RpcError::method_not_found(request.method))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,85 +0,0 @@
|
||||
use common::{ExecutionFailureKind, SequencerClientError};
|
||||
use log::debug;
|
||||
|
||||
use common::rpc_primitives::errors::{RpcError, RpcParseError};
|
||||
|
||||
pub struct RpcErr(pub RpcError);
|
||||
|
||||
pub type RpcErrInternal = anyhow::Error;
|
||||
|
||||
pub trait RpcErrKind: 'static {
|
||||
fn into_rpc_err(self) -> RpcError;
|
||||
}
|
||||
|
||||
impl<T: RpcErrKind> From<T> for RpcErr {
|
||||
fn from(e: T) -> Self {
|
||||
Self(e.into_rpc_err())
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! standard_rpc_err_kind {
|
||||
($type_name:path) => {
|
||||
impl RpcErrKind for $type_name {
|
||||
fn into_rpc_err(self) -> RpcError {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
standard_rpc_err_kind!(RpcError);
|
||||
standard_rpc_err_kind!(RpcParseError);
|
||||
|
||||
impl RpcErrKind for serde_json::Error {
|
||||
fn into_rpc_err(self) -> RpcError {
|
||||
RpcError::serialization_error(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl RpcErrKind for RpcErrInternal {
|
||||
fn into_rpc_err(self) -> RpcError {
|
||||
RpcError::new_internal_error(None, &format!("{self:#?}"))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn from_rpc_err_into_anyhow_err(rpc_err: RpcError) -> anyhow::Error {
|
||||
debug!("Rpc error cast to anyhow error : err {rpc_err:?}");
|
||||
anyhow::anyhow!(format!("{rpc_err:#?}"))
|
||||
}
|
||||
|
||||
pub fn cast_seq_client_error_into_rpc_error(seq_cli_err: SequencerClientError) -> RpcError {
|
||||
let error_string = seq_cli_err.to_string();
|
||||
|
||||
match seq_cli_err {
|
||||
SequencerClientError::SerdeError(_) => RpcError::serialization_error(&error_string),
|
||||
SequencerClientError::HTTPError(_) => RpcError::new_internal_error(None, &error_string),
|
||||
SequencerClientError::InternalError(err) => RpcError::new_internal_error(
|
||||
err.error.data,
|
||||
&serde_json::to_string(&err.error.error_struct).unwrap_or(String::default()),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cast_common_execution_error_into_rpc_error(comm_exec_err: ExecutionFailureKind) -> RpcError {
|
||||
let error_string = comm_exec_err.to_string();
|
||||
|
||||
match comm_exec_err {
|
||||
ExecutionFailureKind::BuilderError(_) => RpcError::new_internal_error(None, &error_string),
|
||||
ExecutionFailureKind::WriteError(_) => RpcError::new_internal_error(None, &error_string),
|
||||
ExecutionFailureKind::DBError(_) => RpcError::new_internal_error(None, &error_string),
|
||||
ExecutionFailureKind::DecodeError(_) => RpcError::new_internal_error(None, &error_string),
|
||||
ExecutionFailureKind::ProveError(_) => RpcError::new_internal_error(None, &error_string),
|
||||
ExecutionFailureKind::AmountMismatchError => {
|
||||
RpcError::new_internal_error(None, &error_string)
|
||||
}
|
||||
ExecutionFailureKind::InsufficientGasError => {
|
||||
RpcError::new_internal_error(None, &error_string)
|
||||
}
|
||||
ExecutionFailureKind::InsufficientFundsError => {
|
||||
RpcError::new_internal_error(None, &error_string)
|
||||
}
|
||||
ExecutionFailureKind::SequencerClientError(seq_cli_err) => {
|
||||
cast_seq_client_error_into_rpc_error(seq_cli_err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,2 +0,0 @@
|
||||
pub mod err_rpc;
|
||||
pub mod rpc_structs;
|
||||
@ -1,206 +0,0 @@
|
||||
use common::parse_request;
|
||||
use common::rpc_primitives::errors::RpcParseError;
|
||||
use common::rpc_primitives::parser::parse_params;
|
||||
use common::rpc_primitives::parser::RpcRequest;
|
||||
use common::transaction::TxKind;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ExecuteSubscenarioRequest {
|
||||
pub scenario_id: u64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ExecuteScenarioSplitRequest {
|
||||
pub visibility_list: [bool; 3],
|
||||
pub publication_index: usize,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ExecuteScenarioMultipleSendRequest {
|
||||
pub number_of_assets: usize,
|
||||
pub number_to_send: usize,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ShowAccountPublicBalanceRequest {
|
||||
pub account_addr: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ShowAccountUTXORequest {
|
||||
pub account_addr: String,
|
||||
pub utxo_hash: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ShowTransactionRequest {
|
||||
pub tx_hash: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct WriteDepositPublicBalanceRequest {
|
||||
pub account_addr: String,
|
||||
pub amount: u64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct WriteMintPrivateUTXORequest {
|
||||
pub account_addr: String,
|
||||
pub amount: u64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct WriteMintPrivateUTXOMultipleAssetsRequest {
|
||||
pub account_addr: String,
|
||||
pub num_of_assets: usize,
|
||||
pub amount: u64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct WriteSendPrivateUTXORequest {
|
||||
pub account_addr_sender: String,
|
||||
pub account_addr_receiver: String,
|
||||
pub utxo_hash: String,
|
||||
pub utxo_commitment: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct WriteSendShieldedUTXORequest {
|
||||
pub account_addr_sender: String,
|
||||
pub account_addr_receiver: String,
|
||||
pub amount: u64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct WriteSendDeshieldedBalanceRequest {
|
||||
pub account_addr_sender: String,
|
||||
pub account_addr_receiver: String,
|
||||
pub utxo_hash: String,
|
||||
pub utxo_commitment: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct WriteSplitUTXORequest {
|
||||
pub account_addr_sender: String,
|
||||
pub account_addr_receivers: [String; 3],
|
||||
pub visibility_list: [bool; 3],
|
||||
pub utxo_hash: String,
|
||||
pub utxo_commitment: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct CreateAccountRequest {}
|
||||
|
||||
// parse_request!(GetGenesisIdRequest);
|
||||
parse_request!(ExecuteSubscenarioRequest);
|
||||
parse_request!(ExecuteScenarioSplitRequest);
|
||||
parse_request!(ExecuteScenarioMultipleSendRequest);
|
||||
// parse_request!(GetLastBlockRequest);
|
||||
|
||||
parse_request!(ShowAccountPublicBalanceRequest);
|
||||
parse_request!(ShowAccountUTXORequest);
|
||||
parse_request!(ShowTransactionRequest);
|
||||
|
||||
parse_request!(WriteDepositPublicBalanceRequest);
|
||||
parse_request!(WriteMintPrivateUTXORequest);
|
||||
parse_request!(WriteMintPrivateUTXOMultipleAssetsRequest);
|
||||
parse_request!(WriteSendPrivateUTXORequest);
|
||||
parse_request!(WriteSendShieldedUTXORequest);
|
||||
parse_request!(WriteSendDeshieldedBalanceRequest);
|
||||
parse_request!(WriteSplitUTXORequest);
|
||||
parse_request!(CreateAccountRequest);
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ExecuteSubscenarioResponse {
|
||||
pub scenario_result: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ExecuteScenarioSplitResponse {
|
||||
pub scenario_result: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ExecuteScenarioMultipleSendResponse {
|
||||
pub scenario_result: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ShowAccountPublicBalanceResponse {
|
||||
pub addr: String,
|
||||
pub balance: u64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ShowAccountUTXOResponse {
|
||||
pub hash: String,
|
||||
pub asset: Vec<u8>,
|
||||
pub amount: u128,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct ShowTransactionResponse {
|
||||
pub hash: String,
|
||||
pub tx_kind: TxKind,
|
||||
pub public_input: String,
|
||||
pub public_output: String,
|
||||
pub utxo_commitments_created_hashes: Vec<String>,
|
||||
pub utxo_commitments_spent_hashes: Vec<String>,
|
||||
pub utxo_nullifiers_created_hashes: Vec<String>,
|
||||
pub encoded_data: Vec<(String, String)>,
|
||||
pub ephemeral_pub_key: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct WriteDepositPublicBalanceResponse {
|
||||
pub status: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct UTXOShortEssentialStruct {
|
||||
pub hash: String,
|
||||
pub commitment_hash: String,
|
||||
pub asset: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct WriteMintPrivateUTXOResponse {
|
||||
pub status: String,
|
||||
pub utxo: UTXOShortEssentialStruct,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct WriteMintPrivateUTXOMultipleAssetsResponse {
|
||||
pub status: String,
|
||||
pub utxos: Vec<UTXOShortEssentialStruct>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct WriteSendPrivateUTXOResponse {
|
||||
pub status: String,
|
||||
pub utxo_result: UTXOShortEssentialStruct,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct WriteSendShieldedUTXOResponse {
|
||||
pub status: String,
|
||||
pub utxo_result: UTXOShortEssentialStruct,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct WriteSendDeshieldedUTXOResponse {
|
||||
pub status: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct WriteSendSplitUTXOResponse {
|
||||
pub status: String,
|
||||
pub utxo_results: Vec<UTXOShortEssentialStruct>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct CreateAccountResponse {
|
||||
pub status: String,
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
[package]
|
||||
name = "node_runner"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
hex.workspace = true
|
||||
anyhow.workspace = true
|
||||
serde_json.workspace = true
|
||||
env_logger.workspace = true
|
||||
log.workspace = true
|
||||
serde.workspace = true
|
||||
actix.workspace = true
|
||||
|
||||
actix-web.workspace = true
|
||||
tokio.workspace = true
|
||||
|
||||
[dependencies.clap]
|
||||
features = ["derive", "env"]
|
||||
workspace = true
|
||||
|
||||
[dependencies.accounts]
|
||||
path = "../accounts"
|
||||
|
||||
[dependencies.consensus]
|
||||
path = "../consensus"
|
||||
|
||||
[dependencies.networking]
|
||||
path = "../networking"
|
||||
|
||||
[dependencies.storage]
|
||||
path = "../storage"
|
||||
|
||||
[dependencies.utxo]
|
||||
path = "../utxo"
|
||||
|
||||
[dependencies.vm]
|
||||
path = "../vm"
|
||||
|
||||
[dependencies.zkvm]
|
||||
path = "../zkvm"
|
||||
|
||||
[dependencies.node_rpc]
|
||||
path = "../node_rpc"
|
||||
|
||||
[dependencies.node_core]
|
||||
path = "../node_core"
|
||||
|
||||
[dependencies.common]
|
||||
path = "../common"
|
||||
@ -1,14 +0,0 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::Result;
|
||||
use node_core::config::NodeConfig;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
|
||||
pub fn from_file(config_home: PathBuf) -> Result<NodeConfig> {
|
||||
let file = File::open(config_home)?;
|
||||
let reader = BufReader::new(file);
|
||||
|
||||
Ok(serde_json::from_reader(reader)?)
|
||||
}
|
||||
@ -1,56 +0,0 @@
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use common::rpc_primitives::RpcConfig;
|
||||
use consensus::ConsensusManager;
|
||||
use log::info;
|
||||
use networking::peer_manager::PeerManager;
|
||||
use node_core::NodeCore;
|
||||
use node_rpc::new_http_server;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
pub mod config;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(version)]
|
||||
struct Args {
|
||||
/// Path to configs
|
||||
home_dir: PathBuf,
|
||||
}
|
||||
|
||||
pub async fn main_runner() -> Result<()> {
|
||||
env_logger::init();
|
||||
|
||||
let args = Args::parse();
|
||||
let Args { home_dir } = args;
|
||||
|
||||
let app_config = config::from_file(home_dir.join("node_config.json"))?;
|
||||
|
||||
let port = app_config.port;
|
||||
|
||||
let node_core = NodeCore::start_from_config_update_chain(app_config.clone()).await?;
|
||||
let wrapped_node_core = Arc::new(Mutex::new(node_core));
|
||||
|
||||
let http_server = new_http_server(
|
||||
RpcConfig::with_port(port),
|
||||
app_config.clone(),
|
||||
wrapped_node_core.clone(),
|
||||
)?;
|
||||
info!("HTTP server started");
|
||||
let _http_server_handle = http_server.handle();
|
||||
tokio::spawn(http_server);
|
||||
|
||||
let peer_manager = PeerManager::start_peer_manager(4, 0).await?;
|
||||
info!("Peer manager mock started");
|
||||
|
||||
let peer_manager_shared = Arc::new(Mutex::new(peer_manager));
|
||||
|
||||
let _consensus_manager = ConsensusManager::new(peer_manager_shared.clone());
|
||||
info!("Consensus manger mock started");
|
||||
|
||||
#[allow(clippy::empty_loop)]
|
||||
loop {
|
||||
//ToDo: Insert activity into main loop
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
use anyhow::Result;
|
||||
|
||||
use node_runner::main_runner;
|
||||
|
||||
pub const NUM_THREADS: usize = 4;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
actix::System::with_tokio_rt(|| {
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.worker_threads(NUM_THREADS)
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap()
|
||||
})
|
||||
.block_on(main_runner())
|
||||
}
|
||||
@ -98,12 +98,6 @@ pub fn private_circuit(
|
||||
));
|
||||
}
|
||||
|
||||
for nullifier in in_nullifiers.iter() {
|
||||
let nullifier: [u8; 32] = nullifier.clone().try_into().unwrap();
|
||||
|
||||
assert!(!public_context.nullifiers_set.contains(&nullifier));
|
||||
}
|
||||
|
||||
(in_nullifiers, generate_commitments(output_utxos))
|
||||
}
|
||||
|
||||
@ -147,12 +141,6 @@ pub fn deshielded_circuit(
|
||||
));
|
||||
}
|
||||
|
||||
for nullifier in in_nullifiers.iter() {
|
||||
let nullifier: [u8; 32] = nullifier.clone().try_into().unwrap();
|
||||
|
||||
assert!(!public_context.nullifiers_set.contains(&nullifier));
|
||||
}
|
||||
|
||||
in_nullifiers
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use accounts::account_core::{address::AccountAddress, AccountPublicMask};
|
||||
use common::merkle_tree_public::{merkle_tree::UTXOCommitmentsMerkleTree, TreeHashType};
|
||||
@ -20,9 +20,7 @@ pub struct PublicSCContext {
|
||||
pub caller_balance: u64,
|
||||
pub account_masks: BTreeMap<AccountAddress, AccountPublicMask>,
|
||||
pub comitment_store_root: TreeHashType,
|
||||
pub pub_tx_store_root: TreeHashType,
|
||||
pub commitments_tree: UTXOCommitmentsMerkleTree,
|
||||
pub nullifiers_set: HashSet<[u8; 32]>,
|
||||
}
|
||||
|
||||
impl Serialize for PublicSCContext {
|
||||
@ -44,9 +42,7 @@ impl Serialize for PublicSCContext {
|
||||
s.serialize_field(ACCOUNT_MASKS_KEYS_SORTED, &account_masks_keys)?;
|
||||
s.serialize_field(ACCOUNT_MASKS_VALUES_SORTED, &account_mask_values)?;
|
||||
s.serialize_field(COMMITMENT_STORE_ROOT, &self.comitment_store_root)?;
|
||||
s.serialize_field(PUT_TX_STORE_ROOT, &self.pub_tx_store_root)?;
|
||||
s.serialize_field(COMMITMENT_TREE, &self.commitments_tree)?;
|
||||
s.serialize_field(NULLIFIERS_SET, &self.nullifiers_set)?;
|
||||
|
||||
s.end()
|
||||
}
|
||||
@ -100,12 +96,9 @@ mod tests {
|
||||
fn create_test_context() -> PublicSCContext {
|
||||
let caller_address = [1; 32];
|
||||
let comitment_store_root = [3; 32];
|
||||
let pub_tx_store_root = [4; 32];
|
||||
|
||||
let commitments_tree =
|
||||
UTXOCommitmentsMerkleTree::new(vec![UTXOCommitment { hash: [5; 32] }]);
|
||||
let mut nullifiers_set = HashSet::new();
|
||||
nullifiers_set.insert([6; 32]);
|
||||
|
||||
let mut account_masks = BTreeMap::new();
|
||||
|
||||
@ -122,9 +115,7 @@ mod tests {
|
||||
caller_balance: 100,
|
||||
account_masks,
|
||||
comitment_store_root,
|
||||
pub_tx_store_root,
|
||||
commitments_tree,
|
||||
nullifiers_set,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,6 @@ pub fn create_public_transaction_payload(
|
||||
tweak: Tweak,
|
||||
secret_r: [u8; 32],
|
||||
sc_addr: String,
|
||||
state_changes: (serde_json::Value, usize),
|
||||
) -> TransactionBody {
|
||||
TransactionBody {
|
||||
tx_kind: TxKind::Public,
|
||||
@ -30,7 +29,6 @@ pub fn create_public_transaction_payload(
|
||||
tweak,
|
||||
secret_r,
|
||||
sc_addr,
|
||||
state_changes,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ use std::fmt::Display;
|
||||
use accounts::account_core::address::{self, AccountAddress};
|
||||
use anyhow::Result;
|
||||
use common::{
|
||||
block::{Block, HashableBlockData},
|
||||
block::HashableBlockData,
|
||||
execution_input::PublicNativeTokenSend,
|
||||
merkle_tree_public::TreeHashType,
|
||||
nullifier::UTXONullifier,
|
||||
@ -80,7 +80,6 @@ impl SequencerCore {
|
||||
pub fn transaction_pre_check(
|
||||
&mut self,
|
||||
tx: Transaction,
|
||||
tx_roots: [[u8; 32]; 2],
|
||||
) -> Result<AuthenticatedTransaction, TransactionMalformationErrorKind> {
|
||||
let tx = tx
|
||||
.into_authenticated()
|
||||
@ -103,16 +102,6 @@ impl SequencerCore {
|
||||
return Err(TransactionMalformationErrorKind::MempoolFullForRound { tx: tx_hash });
|
||||
}
|
||||
|
||||
let curr_sequencer_roots = self.get_tree_roots();
|
||||
|
||||
if tx_roots != curr_sequencer_roots {
|
||||
return Err(
|
||||
TransactionMalformationErrorKind::ChainStateFurtherThanTransactionState {
|
||||
tx: tx_hash,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
//Sanity check
|
||||
match tx_kind {
|
||||
TxKind::Public => {
|
||||
@ -197,7 +186,6 @@ impl SequencerCore {
|
||||
pub fn push_tx_into_mempool_pre_check(
|
||||
&mut self,
|
||||
transaction: Transaction,
|
||||
tx_roots: [[u8; 32]; 2],
|
||||
) -> Result<(), TransactionMalformationErrorKind> {
|
||||
let mempool_size = self.mempool.len();
|
||||
if mempool_size >= self.sequencer_config.max_num_tx_in_block {
|
||||
@ -206,7 +194,7 @@ impl SequencerCore {
|
||||
});
|
||||
}
|
||||
|
||||
let authenticated_tx = self.transaction_pre_check(transaction, tx_roots)?;
|
||||
let authenticated_tx = self.transaction_pre_check(transaction)?;
|
||||
|
||||
self.mempool.push_item(authenticated_tx.into());
|
||||
|
||||
@ -321,7 +309,7 @@ impl SequencerCore {
|
||||
prev_block_hash,
|
||||
};
|
||||
|
||||
let block = Block::produce_block_from_hashable_data(hashable_data);
|
||||
let block = hashable_data.into();
|
||||
|
||||
self.store.block_store.put_block_at_id(block)?;
|
||||
|
||||
@ -336,11 +324,8 @@ mod tests {
|
||||
use crate::config::AccountInitialData;
|
||||
|
||||
use super::*;
|
||||
|
||||
use common::transaction::{SignaturePrivateKey, Transaction, TransactionBody, TxKind};
|
||||
use k256::{ecdsa::SigningKey, FieldBytes};
|
||||
use mempool_transaction::MempoolTransaction;
|
||||
use secp256k1_zkp::Tweak;
|
||||
|
||||
fn setup_sequencer_config_variable_initial_accounts(
|
||||
initial_accounts: Vec<AccountInitialData>,
|
||||
@ -386,67 +371,6 @@ mod tests {
|
||||
setup_sequencer_config_variable_initial_accounts(initial_accounts)
|
||||
}
|
||||
|
||||
fn create_dummy_transaction(
|
||||
nullifier_created_hashes: Vec<[u8; 32]>,
|
||||
utxo_commitments_spent_hashes: Vec<[u8; 32]>,
|
||||
utxo_commitments_created_hashes: Vec<[u8; 32]>,
|
||||
) -> Transaction {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let body = TransactionBody {
|
||||
tx_kind: TxKind::Private,
|
||||
execution_input: vec![],
|
||||
execution_output: vec![],
|
||||
utxo_commitments_spent_hashes,
|
||||
utxo_commitments_created_hashes,
|
||||
nullifier_created_hashes,
|
||||
execution_proof_private: "dummy_proof".to_string(),
|
||||
encoded_data: vec![],
|
||||
ephemeral_pub_key: vec![10, 11, 12],
|
||||
commitment: vec![],
|
||||
tweak: Tweak::new(&mut rng),
|
||||
secret_r: [0; 32],
|
||||
sc_addr: "sc_addr".to_string(),
|
||||
state_changes: (serde_json::Value::Null, 0),
|
||||
};
|
||||
Transaction::new(body, SignaturePrivateKey::random(&mut rng))
|
||||
}
|
||||
|
||||
fn create_dummy_transaction_native_token_transfer(
|
||||
from: [u8; 32],
|
||||
nonce: u64,
|
||||
to: [u8; 32],
|
||||
balance_to_move: u64,
|
||||
signing_key: SigningKey,
|
||||
) -> Transaction {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let native_token_transfer = PublicNativeTokenSend {
|
||||
from,
|
||||
nonce,
|
||||
to,
|
||||
balance_to_move,
|
||||
};
|
||||
|
||||
let body = TransactionBody {
|
||||
tx_kind: TxKind::Public,
|
||||
execution_input: serde_json::to_vec(&native_token_transfer).unwrap(),
|
||||
execution_output: vec![],
|
||||
utxo_commitments_spent_hashes: vec![],
|
||||
utxo_commitments_created_hashes: vec![],
|
||||
nullifier_created_hashes: vec![],
|
||||
execution_proof_private: "".to_string(),
|
||||
encoded_data: vec![],
|
||||
ephemeral_pub_key: vec![10, 11, 12],
|
||||
commitment: vec![],
|
||||
tweak: Tweak::new(&mut rng),
|
||||
secret_r: [0; 32],
|
||||
sc_addr: "sc_addr".to_string(),
|
||||
state_changes: (serde_json::Value::Null, 0),
|
||||
};
|
||||
Transaction::new(body, signing_key)
|
||||
}
|
||||
|
||||
fn create_signing_key_for_account1() -> SigningKey {
|
||||
let pub_sign_key_acc1 = [
|
||||
133, 143, 177, 187, 252, 66, 237, 236, 234, 252, 244, 138, 5, 151, 3, 99, 217, 231,
|
||||
@ -468,7 +392,11 @@ mod tests {
|
||||
}
|
||||
|
||||
fn common_setup(sequencer: &mut SequencerCore) {
|
||||
let tx = create_dummy_transaction(vec![[9; 32]], vec![[7; 32]], vec![[8; 32]]);
|
||||
let tx = common::test_utils::create_dummy_private_transaction_random_signer(
|
||||
vec![[9; 32]],
|
||||
vec![[7; 32]],
|
||||
vec![[8; 32]],
|
||||
);
|
||||
let mempool_tx = MempoolTransaction {
|
||||
auth_tx: tx.into_authenticated().unwrap(),
|
||||
};
|
||||
@ -581,9 +509,13 @@ mod tests {
|
||||
|
||||
common_setup(&mut sequencer);
|
||||
|
||||
let tx = create_dummy_transaction(vec![[91; 32]], vec![[71; 32]], vec![[81; 32]]);
|
||||
let tx_roots = sequencer.get_tree_roots();
|
||||
let result = sequencer.transaction_pre_check(tx, tx_roots);
|
||||
let tx = common::test_utils::create_dummy_private_transaction_random_signer(
|
||||
vec![[91; 32]],
|
||||
vec![[71; 32]],
|
||||
vec![[81; 32]],
|
||||
);
|
||||
|
||||
let result = sequencer.transaction_pre_check(tx);
|
||||
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
@ -606,9 +538,11 @@ mod tests {
|
||||
|
||||
let sign_key1 = create_signing_key_for_account1();
|
||||
|
||||
let tx = create_dummy_transaction_native_token_transfer(acc1, 0, acc2, 10, sign_key1);
|
||||
let tx_roots = sequencer.get_tree_roots();
|
||||
let result = sequencer.transaction_pre_check(tx, tx_roots);
|
||||
let tx = common::test_utils::create_dummy_transaction_native_token_transfer(
|
||||
acc1, 0, acc2, 10, sign_key1,
|
||||
);
|
||||
|
||||
let result = sequencer.transaction_pre_check(tx);
|
||||
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
@ -631,9 +565,11 @@ mod tests {
|
||||
|
||||
let sign_key2 = create_signing_key_for_account2();
|
||||
|
||||
let tx = create_dummy_transaction_native_token_transfer(acc1, 0, acc2, 10, sign_key2);
|
||||
let tx_roots = sequencer.get_tree_roots();
|
||||
let result = sequencer.transaction_pre_check(tx, tx_roots);
|
||||
let tx = common::test_utils::create_dummy_transaction_native_token_transfer(
|
||||
acc1, 0, acc2, 10, sign_key2,
|
||||
);
|
||||
|
||||
let result = sequencer.transaction_pre_check(tx);
|
||||
|
||||
assert_eq!(
|
||||
result.err().unwrap(),
|
||||
@ -659,9 +595,11 @@ mod tests {
|
||||
|
||||
let sign_key1 = create_signing_key_for_account1();
|
||||
|
||||
let tx = create_dummy_transaction_native_token_transfer(acc1, 0, acc2, 10000000, sign_key1);
|
||||
let tx_roots = sequencer.get_tree_roots();
|
||||
let result = sequencer.transaction_pre_check(tx, tx_roots);
|
||||
let tx = common::test_utils::create_dummy_transaction_native_token_transfer(
|
||||
acc1, 0, acc2, 10000000, sign_key1,
|
||||
);
|
||||
|
||||
let result = sequencer.transaction_pre_check(tx);
|
||||
|
||||
//Passed pre-check
|
||||
assert!(result.is_ok());
|
||||
@ -693,7 +631,9 @@ mod tests {
|
||||
|
||||
let sign_key1 = create_signing_key_for_account1();
|
||||
|
||||
let tx = create_dummy_transaction_native_token_transfer(acc1, 0, acc2, 100, sign_key1);
|
||||
let tx = common::test_utils::create_dummy_transaction_native_token_transfer(
|
||||
acc1, 0, acc2, 100, sign_key1,
|
||||
);
|
||||
|
||||
sequencer
|
||||
.execute_check_transaction_on_state(&tx.into_authenticated().unwrap().into())
|
||||
@ -716,8 +656,11 @@ mod tests {
|
||||
|
||||
common_setup(&mut sequencer);
|
||||
|
||||
let tx = create_dummy_transaction(vec![[92; 32]], vec![[72; 32]], vec![[82; 32]]);
|
||||
let tx_roots = sequencer.get_tree_roots();
|
||||
let tx = common::test_utils::create_dummy_private_transaction_random_signer(
|
||||
vec![[92; 32]],
|
||||
vec![[72; 32]],
|
||||
vec![[82; 32]],
|
||||
);
|
||||
|
||||
// Fill the mempool
|
||||
let dummy_tx = MempoolTransaction {
|
||||
@ -725,7 +668,7 @@ mod tests {
|
||||
};
|
||||
sequencer.mempool.push_item(dummy_tx);
|
||||
|
||||
let result = sequencer.push_tx_into_mempool_pre_check(tx, tx_roots);
|
||||
let result = sequencer.push_tx_into_mempool_pre_check(tx);
|
||||
|
||||
assert!(matches!(
|
||||
result,
|
||||
@ -740,10 +683,13 @@ mod tests {
|
||||
|
||||
common_setup(&mut sequencer);
|
||||
|
||||
let tx = create_dummy_transaction(vec![[93; 32]], vec![[73; 32]], vec![[83; 32]]);
|
||||
let tx_roots = sequencer.get_tree_roots();
|
||||
let tx = common::test_utils::create_dummy_private_transaction_random_signer(
|
||||
vec![[93; 32]],
|
||||
vec![[73; 32]],
|
||||
vec![[83; 32]],
|
||||
);
|
||||
|
||||
let result = sequencer.push_tx_into_mempool_pre_check(tx, tx_roots);
|
||||
let result = sequencer.push_tx_into_mempool_pre_check(tx);
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(sequencer.mempool.len(), 1);
|
||||
}
|
||||
@ -754,7 +700,11 @@ mod tests {
|
||||
let mut sequencer = SequencerCore::start_from_config(config);
|
||||
let genesis_height = sequencer.chain_height;
|
||||
|
||||
let tx = create_dummy_transaction(vec![[94; 32]], vec![[7; 32]], vec![[8; 32]]);
|
||||
let tx = common::test_utils::create_dummy_private_transaction_random_signer(
|
||||
vec![[94; 32]],
|
||||
vec![[7; 32]],
|
||||
vec![[8; 32]],
|
||||
);
|
||||
let tx_mempool = MempoolTransaction {
|
||||
auth_tx: tx.into_authenticated().unwrap(),
|
||||
};
|
||||
@ -783,7 +733,9 @@ mod tests {
|
||||
|
||||
let sign_key1 = create_signing_key_for_account1();
|
||||
|
||||
let tx = create_dummy_transaction_native_token_transfer(acc1, 0, acc2, 100, sign_key1);
|
||||
let tx = common::test_utils::create_dummy_transaction_native_token_transfer(
|
||||
acc1, 0, acc2, 100, sign_key1,
|
||||
);
|
||||
|
||||
let tx_mempool_original = MempoolTransaction {
|
||||
auth_tx: tx.clone().into_authenticated().unwrap(),
|
||||
@ -828,7 +780,9 @@ mod tests {
|
||||
|
||||
let sign_key1 = create_signing_key_for_account1();
|
||||
|
||||
let tx = create_dummy_transaction_native_token_transfer(acc1, 0, acc2, 100, sign_key1);
|
||||
let tx = common::test_utils::create_dummy_transaction_native_token_transfer(
|
||||
acc1, 0, acc2, 100, sign_key1,
|
||||
);
|
||||
|
||||
// The transaction should be included the first time
|
||||
let tx_mempool_original = MempoolTransaction {
|
||||
|
||||
@ -76,40 +76,8 @@ fn block_to_transactions_map(block: &Block) -> HashMap<TreeHashType, u64> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use common::transaction::{SignaturePrivateKey, TransactionBody};
|
||||
use tempfile::tempdir;
|
||||
|
||||
fn create_dummy_block_with_transaction(block_id: u64) -> (Block, Transaction) {
|
||||
let body = TransactionBody {
|
||||
tx_kind: common::transaction::TxKind::Public,
|
||||
execution_input: Default::default(),
|
||||
execution_output: Default::default(),
|
||||
utxo_commitments_spent_hashes: Default::default(),
|
||||
utxo_commitments_created_hashes: Default::default(),
|
||||
nullifier_created_hashes: Default::default(),
|
||||
execution_proof_private: Default::default(),
|
||||
encoded_data: Default::default(),
|
||||
ephemeral_pub_key: Default::default(),
|
||||
commitment: Default::default(),
|
||||
tweak: Default::default(),
|
||||
secret_r: Default::default(),
|
||||
sc_addr: Default::default(),
|
||||
state_changes: Default::default(),
|
||||
};
|
||||
let tx = Transaction::new(body, SignaturePrivateKey::from_slice(&[1; 32]).unwrap());
|
||||
(
|
||||
Block {
|
||||
block_id,
|
||||
prev_block_id: block_id - 1,
|
||||
prev_block_hash: [0; 32],
|
||||
hash: [1; 32],
|
||||
transactions: vec![tx.clone()],
|
||||
data: vec![],
|
||||
},
|
||||
tx,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_transaction_by_hash() {
|
||||
let temp_dir = tempdir().unwrap();
|
||||
@ -125,7 +93,10 @@ mod tests {
|
||||
// Start an empty node store
|
||||
let mut node_store =
|
||||
SequecerBlockStore::open_db_with_genesis(path, Some(genesis_block)).unwrap();
|
||||
let (block, tx) = create_dummy_block_with_transaction(1);
|
||||
|
||||
let tx = common::test_utils::produce_dummy_empty_transaction();
|
||||
let block = common::test_utils::produce_dummy_block(1, None, vec![tx.clone()], vec![]);
|
||||
|
||||
// Try retrieve a tx that's not in the chain yet.
|
||||
let retrieved_tx = node_store.get_transaction_by_hash(tx.body().hash());
|
||||
assert_eq!(None, retrieved_tx);
|
||||
|
||||
@ -3,7 +3,7 @@ use std::{collections::HashSet, path::Path};
|
||||
use accounts_store::SequencerAccountsStore;
|
||||
use block_store::SequecerBlockStore;
|
||||
use common::{
|
||||
block::{Block, HashableBlockData},
|
||||
block::HashableBlockData,
|
||||
merkle_tree_public::merkle_tree::{PublicTransactionMerkleTree, UTXOCommitmentsMerkleTree},
|
||||
nullifier::UTXONullifier,
|
||||
};
|
||||
@ -63,7 +63,7 @@ impl SequecerChainStore {
|
||||
prev_block_hash,
|
||||
};
|
||||
|
||||
let genesis_block = Block::produce_block_from_hashable_data(hashable_data);
|
||||
let genesis_block = hashable_data.into();
|
||||
|
||||
//Sequencer should panic if unable to open db,
|
||||
//as fixing this issue may require actions non-native to program scope
|
||||
|
||||
@ -24,12 +24,6 @@ path = "../mempool"
|
||||
[dependencies.accounts]
|
||||
path = "../accounts"
|
||||
|
||||
[dependencies.consensus]
|
||||
path = "../consensus"
|
||||
|
||||
[dependencies.networking]
|
||||
path = "../networking"
|
||||
|
||||
[dependencies.sequencer_core]
|
||||
path = "../sequencer_core"
|
||||
|
||||
|
||||
@ -88,7 +88,7 @@ impl JsonHandler {
|
||||
{
|
||||
let mut state = self.sequencer_state.lock().await;
|
||||
|
||||
state.push_tx_into_mempool_pre_check(send_tx_req.transaction, send_tx_req.tx_roots)?;
|
||||
state.push_tx_into_mempool_pre_check(send_tx_req.transaction)?;
|
||||
}
|
||||
|
||||
let helperstruct = SendTxResponse {
|
||||
@ -287,13 +287,10 @@ mod tests {
|
||||
tweak: Default::default(),
|
||||
secret_r: Default::default(),
|
||||
sc_addr: Default::default(),
|
||||
state_changes: Default::default(),
|
||||
};
|
||||
let tx = Transaction::new(tx_body, SignaturePrivateKey::from_slice(&[1; 32]).unwrap());
|
||||
|
||||
sequencer_core
|
||||
.push_tx_into_mempool_pre_check(tx, [[0; 32]; 2])
|
||||
.unwrap();
|
||||
sequencer_core.push_tx_into_mempool_pre_check(tx).unwrap();
|
||||
sequencer_core
|
||||
.produce_new_block_with_mempool_transactions()
|
||||
.unwrap();
|
||||
@ -499,7 +496,7 @@ mod tests {
|
||||
let request = serde_json::json!({
|
||||
"jsonrpc": "2.0",
|
||||
"method": "get_transaction_by_hash",
|
||||
"params": { "hash": "a5210ef33912a448cfe6eda43878c144df81f7bdf51d19b5ddf97be11806a6ed"},
|
||||
"params": { "hash": "2c69b9639bcf8d58509204e18f1d5962029bf26840915f2bf2bb434501ad3c38"},
|
||||
"id": 1
|
||||
});
|
||||
|
||||
@ -518,14 +515,13 @@ mod tests {
|
||||
"nullifier_created_hashes": [],
|
||||
"sc_addr": "",
|
||||
"secret_r": vec![0; 32],
|
||||
"state_changes": [null, 0],
|
||||
"tweak": "0".repeat(64),
|
||||
"tx_kind": "Shielded",
|
||||
"utxo_commitments_created_hashes": [],
|
||||
"utxo_commitments_spent_hashes": [],
|
||||
},
|
||||
"public_key": "3056301006072A8648CE3D020106052B8104000A034200041B84C5567B126440995D3ED5AABA0565D71E1834604819FF9C17F5E9D5DD078F70BEAF8F588B541507FED6A642C5AB42DFDF8120A7F639DE5122D47A69A8E8D1",
|
||||
"signature": "A4E0D6A25BE829B006124F0DFD766427967AA3BEA96C29219E79BB2CC871891F384748C27E28718A4450AA78709FBF1A57DB33BCD575A2C819D2A439C2D878E6"
|
||||
"signature": "D75783642EA6E7D5E13AE8CCD3C2D3F82728C0A778A80C9F2976C739CD9F7F3F240B0532954D87761DE299A6CB9E6606295786BA5D0F5CACAB3F3626724528B1"
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -22,12 +22,6 @@ workspace = true
|
||||
[dependencies.mempool]
|
||||
path = "../mempool"
|
||||
|
||||
[dependencies.consensus]
|
||||
path = "../consensus"
|
||||
|
||||
[dependencies.networking]
|
||||
path = "../networking"
|
||||
|
||||
[dependencies.sequencer_rpc]
|
||||
path = "../sequencer_rpc"
|
||||
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
[package]
|
||||
name = "vm"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
serde_json.workspace = true
|
||||
env_logger.workspace = true
|
||||
log.workspace = true
|
||||
serde.workspace = true
|
||||
@ -1 +0,0 @@
|
||||
//ToDo: Add vm module
|
||||
@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "node_core"
|
||||
name = "wallet"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
@ -21,6 +21,7 @@ tempfile.workspace = true
|
||||
risc0-zkvm = { git = "https://github.com/risc0/risc0.git", branch = "release-2.3" }
|
||||
hex.workspace = true
|
||||
actix-rt.workspace = true
|
||||
clap.workspace = true
|
||||
|
||||
[dependencies.sc_core]
|
||||
path = "../sc_core"
|
||||
@ -28,9 +29,6 @@ path = "../sc_core"
|
||||
[dependencies.accounts]
|
||||
path = "../accounts"
|
||||
|
||||
[dependencies.storage]
|
||||
path = "../storage"
|
||||
|
||||
[dependencies.utxo]
|
||||
path = "../utxo"
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
use accounts::account_core::{address::AccountAddress, Account};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct NodeAccountsStore {
|
||||
pub struct WalletAccountsStore {
|
||||
pub accounts: HashMap<AccountAddress, Account>,
|
||||
}
|
||||
|
||||
impl NodeAccountsStore {
|
||||
impl WalletAccountsStore {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
accounts: HashMap::new(),
|
||||
@ -21,7 +21,7 @@ impl NodeAccountsStore {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for NodeAccountsStore {
|
||||
impl Default for WalletAccountsStore {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
@ -45,13 +45,13 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_create_empty_store() {
|
||||
let store = NodeAccountsStore::new();
|
||||
let store = WalletAccountsStore::new();
|
||||
assert!(store.accounts.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_register_account() {
|
||||
let mut store = NodeAccountsStore::new();
|
||||
let mut store = WalletAccountsStore::new();
|
||||
|
||||
let account = create_sample_account(100);
|
||||
let account_addr = account.address;
|
||||
@ -65,7 +65,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_unregister_account() {
|
||||
let mut store = NodeAccountsStore::new();
|
||||
let mut store = WalletAccountsStore::new();
|
||||
|
||||
let account = create_sample_account(100);
|
||||
let account_addr = account.address;
|
||||
@ -79,7 +79,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_unregister_nonexistent_account() {
|
||||
let mut store = NodeAccountsStore::new();
|
||||
let mut store = WalletAccountsStore::new();
|
||||
|
||||
let account_addr: [u8; 32] = pad_to_32("nonexistent".to_string().as_bytes());
|
||||
store.unregister_account(account_addr);
|
||||
@ -89,7 +89,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_register_multiple_accounts() {
|
||||
let mut store = NodeAccountsStore::new();
|
||||
let mut store = WalletAccountsStore::new();
|
||||
|
||||
let account1 = create_sample_account(100);
|
||||
let account2 = create_sample_account(200);
|
||||
280
wallet/src/chain_storage/mod.rs
Normal file
280
wallet/src/chain_storage/mod.rs
Normal file
@ -0,0 +1,280 @@
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
use accounts::account_core::{address::AccountAddress, Account};
|
||||
use anyhow::Result;
|
||||
use common::merkle_tree_public::merkle_tree::UTXOCommitmentsMerkleTree;
|
||||
use sc_core::public_context::PublicSCContext;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::config::WalletConfig;
|
||||
|
||||
pub mod accounts_store;
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct AccMap {
|
||||
pub acc_map: HashMap<String, Account>,
|
||||
}
|
||||
|
||||
impl From<HashMap<[u8; 32], Account>> for AccMap {
|
||||
fn from(value: HashMap<[u8; 32], Account>) -> Self {
|
||||
AccMap {
|
||||
acc_map: value
|
||||
.into_iter()
|
||||
.map(|(key, val)| (hex::encode(key), val))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AccMap> for HashMap<[u8; 32], Account> {
|
||||
fn from(value: AccMap) -> Self {
|
||||
value
|
||||
.acc_map
|
||||
.into_iter()
|
||||
.map(|(key, val)| (hex::decode(key).unwrap().try_into().unwrap(), val))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WalletChainStore {
|
||||
pub acc_map: HashMap<AccountAddress, Account>,
|
||||
pub utxo_commitments_store: UTXOCommitmentsMerkleTree,
|
||||
pub wallet_config: WalletConfig,
|
||||
}
|
||||
|
||||
impl WalletChainStore {
|
||||
pub fn new(config: WalletConfig) -> Result<Self> {
|
||||
let acc_map = HashMap::new();
|
||||
let utxo_commitments_store = UTXOCommitmentsMerkleTree::new(vec![]);
|
||||
|
||||
Ok(Self {
|
||||
acc_map,
|
||||
utxo_commitments_store,
|
||||
wallet_config: config,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn produce_context(&self, caller: AccountAddress) -> PublicSCContext {
|
||||
let mut account_masks = BTreeMap::new();
|
||||
|
||||
for (acc_addr, acc) in &self.acc_map {
|
||||
account_masks.insert(*acc_addr, acc.make_account_public_mask());
|
||||
}
|
||||
|
||||
PublicSCContext {
|
||||
caller_address: caller,
|
||||
caller_balance: self.acc_map.get(&caller).unwrap().balance,
|
||||
account_masks,
|
||||
comitment_store_root: self.utxo_commitments_store.get_root().unwrap_or([0; 32]),
|
||||
commitments_tree: self.utxo_commitments_store.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use accounts::account_core::Account;
|
||||
use std::path::PathBuf;
|
||||
use tempfile::tempdir;
|
||||
|
||||
fn create_initial_accounts() -> Vec<Account> {
|
||||
let initial_acc1 = serde_json::from_str(r#"{
|
||||
"address": [
|
||||
244,
|
||||
55,
|
||||
238,
|
||||
205,
|
||||
74,
|
||||
115,
|
||||
179,
|
||||
192,
|
||||
65,
|
||||
186,
|
||||
166,
|
||||
169,
|
||||
221,
|
||||
45,
|
||||
6,
|
||||
57,
|
||||
200,
|
||||
65,
|
||||
195,
|
||||
70,
|
||||
118,
|
||||
252,
|
||||
206,
|
||||
100,
|
||||
215,
|
||||
250,
|
||||
72,
|
||||
230,
|
||||
19,
|
||||
71,
|
||||
217,
|
||||
249
|
||||
],
|
||||
"balance": 100,
|
||||
"key_holder": {
|
||||
"nullifer_public_key": "03A340BECA9FAAB444CED0140681D72EA1318B5C611704FEE017DA9836B17DB718",
|
||||
"pub_account_signing_key": [
|
||||
244,
|
||||
88,
|
||||
134,
|
||||
61,
|
||||
35,
|
||||
209,
|
||||
229,
|
||||
101,
|
||||
85,
|
||||
35,
|
||||
140,
|
||||
140,
|
||||
192,
|
||||
226,
|
||||
83,
|
||||
83,
|
||||
190,
|
||||
189,
|
||||
110,
|
||||
8,
|
||||
89,
|
||||
127,
|
||||
147,
|
||||
142,
|
||||
157,
|
||||
204,
|
||||
51,
|
||||
109,
|
||||
189,
|
||||
92,
|
||||
144,
|
||||
68
|
||||
],
|
||||
"top_secret_key_holder": {
|
||||
"secret_spending_key": "7BC46784DB1BC67825D8F029436846712BFDF9B5D79EA3AB11D39A52B9B229D4"
|
||||
},
|
||||
"utxo_secret_key_holder": {
|
||||
"nullifier_secret_key": "BB54A8D3C9C51B82C431082D1845A74677B0EF829A11B517E1D9885DE3139506",
|
||||
"viewing_secret_key": "AD923E92F6A5683E30140CEAB2702AFB665330C1EE4EFA70FAF29767B6B52BAF"
|
||||
},
|
||||
"viewing_public_key": "0361220C5D277E7A1709340FD31A52600C1432B9C45B9BCF88A43581D58824A8B6"
|
||||
},
|
||||
"utxos": {}
|
||||
}"#).unwrap();
|
||||
|
||||
let initial_acc2 = serde_json::from_str(r#"{
|
||||
"address": [
|
||||
72,
|
||||
169,
|
||||
70,
|
||||
237,
|
||||
1,
|
||||
96,
|
||||
35,
|
||||
157,
|
||||
25,
|
||||
15,
|
||||
83,
|
||||
18,
|
||||
52,
|
||||
206,
|
||||
202,
|
||||
63,
|
||||
48,
|
||||
59,
|
||||
173,
|
||||
76,
|
||||
78,
|
||||
7,
|
||||
254,
|
||||
229,
|
||||
28,
|
||||
45,
|
||||
194,
|
||||
79,
|
||||
6,
|
||||
89,
|
||||
58,
|
||||
85
|
||||
],
|
||||
"balance": 200,
|
||||
"key_holder": {
|
||||
"nullifer_public_key": "02172F50274DE67C4087C344F5D58E11DF761D90285B095060E0994FAA6BCDE271",
|
||||
"pub_account_signing_key": [
|
||||
136,
|
||||
105,
|
||||
9,
|
||||
53,
|
||||
180,
|
||||
145,
|
||||
64,
|
||||
5,
|
||||
235,
|
||||
174,
|
||||
62,
|
||||
211,
|
||||
206,
|
||||
116,
|
||||
185,
|
||||
24,
|
||||
214,
|
||||
62,
|
||||
244,
|
||||
64,
|
||||
224,
|
||||
59,
|
||||
120,
|
||||
150,
|
||||
30,
|
||||
249,
|
||||
160,
|
||||
46,
|
||||
189,
|
||||
254,
|
||||
47,
|
||||
244
|
||||
],
|
||||
"top_secret_key_holder": {
|
||||
"secret_spending_key": "80A186737C8D38B4288A03F0F589957D9C040D79C19F3E0CC4BA80F8494E5179"
|
||||
},
|
||||
"utxo_secret_key_holder": {
|
||||
"nullifier_secret_key": "746928E63F0984F6F4818933493CE9C067562D9CB932FDC06D82C86CDF6D7122",
|
||||
"viewing_secret_key": "89176CF4BC9E673807643FD52110EF99D4894335AFB10D881AC0B5041FE1FCB7"
|
||||
},
|
||||
"viewing_public_key": "026072A8F83FEC3472E30CDD4767683F30B91661D25B1040AD9A5FC2E01D659F99"
|
||||
},
|
||||
"utxos": {}
|
||||
}"#).unwrap();
|
||||
|
||||
let initial_accounts = vec![initial_acc1, initial_acc2];
|
||||
|
||||
initial_accounts
|
||||
}
|
||||
|
||||
fn create_sample_wallet_config(home: PathBuf) -> WalletConfig {
|
||||
WalletConfig {
|
||||
home,
|
||||
override_rust_log: None,
|
||||
sequencer_addr: "http://127.0.0.1".to_string(),
|
||||
seq_poll_timeout_secs: 1,
|
||||
initial_accounts: create_initial_accounts(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_initializes_correctly() {
|
||||
let temp_dir = tempdir().unwrap();
|
||||
let path = temp_dir.path();
|
||||
|
||||
let config = create_sample_wallet_config(path.to_path_buf());
|
||||
|
||||
let store = WalletChainStore::new(config.clone()).unwrap();
|
||||
|
||||
assert!(store.acc_map.is_empty());
|
||||
assert_eq!(
|
||||
store.utxo_commitments_store.get_root().unwrap_or([0; 32]),
|
||||
[0; 32]
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -37,7 +37,7 @@ impl From<GasConfig> for zkvm::gas_calculator::GasCalculator {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct NodeConfig {
|
||||
pub struct WalletConfig {
|
||||
///Home dir of sequencer storage
|
||||
pub home: PathBuf,
|
||||
///Override rust log (env var logging level)
|
||||
@ -46,12 +46,6 @@ pub struct NodeConfig {
|
||||
pub sequencer_addr: String,
|
||||
///Sequencer polling duration for new blocks in seconds
|
||||
pub seq_poll_timeout_secs: u64,
|
||||
///Port to listen
|
||||
pub port: u16,
|
||||
///Gas config
|
||||
pub gas_config: GasConfig,
|
||||
///Frequency of snapshots
|
||||
pub shapshot_frequency_in_blocks: u64,
|
||||
///Initial accounts for wallet
|
||||
pub initial_accounts: Vec<Account>,
|
||||
}
|
||||
26
wallet/src/helperfunctions.rs
Normal file
26
wallet/src/helperfunctions.rs
Normal file
@ -0,0 +1,26 @@
|
||||
use std::{fs::File, io::BufReader, path::PathBuf, str::FromStr};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
|
||||
use crate::{config::WalletConfig, HOME_DIR_ENV_VAR};
|
||||
|
||||
///Get home dir for wallet. Env var `NSSA_WALLET_HOME_DIR` must be set before execution to succeed.
|
||||
pub fn get_home() -> Result<PathBuf> {
|
||||
Ok(PathBuf::from_str(&std::env::var(HOME_DIR_ENV_VAR)?)?)
|
||||
}
|
||||
|
||||
///Fetch config from `NSSA_WALLET_HOME_DIR`
|
||||
pub fn fetch_config() -> Result<WalletConfig> {
|
||||
let config_home = get_home()?;
|
||||
let file = File::open(config_home.join("wallet_config.json"))?;
|
||||
let reader = BufReader::new(file);
|
||||
|
||||
Ok(serde_json::from_reader(reader)?)
|
||||
}
|
||||
|
||||
//ToDo: Replace with structures conversion in future
|
||||
pub fn produce_account_addr_from_hex(hex_str: String) -> Result<[u8; 32]> {
|
||||
hex::decode(hex_str)?
|
||||
.try_into()
|
||||
.map_err(|_| anyhow!("Failed conversion to 32 bytes"))
|
||||
}
|
||||
176
wallet/src/lib.rs
Normal file
176
wallet/src/lib.rs
Normal file
@ -0,0 +1,176 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use common::{
|
||||
execution_input::PublicNativeTokenSend,
|
||||
sequencer_client::{json::SendTxResponse, SequencerClient},
|
||||
transaction::Transaction,
|
||||
ExecutionFailureKind,
|
||||
};
|
||||
|
||||
use accounts::account_core::{address::AccountAddress, Account};
|
||||
use anyhow::Result;
|
||||
use chain_storage::WalletChainStore;
|
||||
use common::transaction::TransactionBody;
|
||||
use config::WalletConfig;
|
||||
use log::info;
|
||||
use sc_core::proofs_circuits::pedersen_commitment_vec;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
use crate::helperfunctions::{fetch_config, produce_account_addr_from_hex};
|
||||
|
||||
pub const HOME_DIR_ENV_VAR: &str = "NSSA_WALLET_HOME_DIR";
|
||||
pub const BLOCK_GEN_DELAY_SECS: u64 = 20;
|
||||
|
||||
pub mod chain_storage;
|
||||
pub mod config;
|
||||
pub mod helperfunctions;
|
||||
|
||||
pub struct WalletCore {
|
||||
pub storage: Arc<RwLock<WalletChainStore>>,
|
||||
pub wallet_config: WalletConfig,
|
||||
pub sequencer_client: Arc<SequencerClient>,
|
||||
}
|
||||
|
||||
impl WalletCore {
|
||||
pub async fn start_from_config_update_chain(config: WalletConfig) -> Result<Self> {
|
||||
let client = Arc::new(SequencerClient::new(config.sequencer_addr.clone())?);
|
||||
|
||||
let mut storage = WalletChainStore::new(config.clone())?;
|
||||
for acc in config.clone().initial_accounts {
|
||||
storage.acc_map.insert(acc.address, acc);
|
||||
}
|
||||
|
||||
let wrapped_storage = Arc::new(RwLock::new(storage));
|
||||
|
||||
Ok(Self {
|
||||
storage: wrapped_storage,
|
||||
wallet_config: config.clone(),
|
||||
sequencer_client: client.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn create_new_account(&mut self) -> AccountAddress {
|
||||
let account = Account::new();
|
||||
account.log();
|
||||
|
||||
let addr = account.address;
|
||||
|
||||
{
|
||||
let mut write_guard = self.storage.write().await;
|
||||
|
||||
write_guard.acc_map.insert(account.address, account);
|
||||
}
|
||||
|
||||
addr
|
||||
}
|
||||
|
||||
pub async fn send_public_native_token_transfer(
|
||||
&self,
|
||||
from: AccountAddress,
|
||||
nonce: u64,
|
||||
to: AccountAddress,
|
||||
balance_to_move: u64,
|
||||
) -> Result<SendTxResponse, ExecutionFailureKind> {
|
||||
let public_context = {
|
||||
let read_guard = self.storage.read().await;
|
||||
|
||||
read_guard.produce_context(from)
|
||||
};
|
||||
|
||||
let (tweak, secret_r, commitment) = pedersen_commitment_vec(
|
||||
//Will not panic, as public context is serializable
|
||||
public_context.produce_u64_list_from_context().unwrap(),
|
||||
);
|
||||
|
||||
let sc_addr = hex::encode([0; 32]);
|
||||
|
||||
let tx: TransactionBody =
|
||||
sc_core::transaction_payloads_tools::create_public_transaction_payload(
|
||||
serde_json::to_vec(&PublicNativeTokenSend {
|
||||
from,
|
||||
nonce,
|
||||
to,
|
||||
balance_to_move,
|
||||
})
|
||||
.unwrap(),
|
||||
commitment,
|
||||
tweak,
|
||||
secret_r,
|
||||
sc_addr,
|
||||
);
|
||||
tx.log();
|
||||
|
||||
{
|
||||
let read_guard = self.storage.read().await;
|
||||
|
||||
let account = read_guard.acc_map.get(&from);
|
||||
|
||||
if let Some(account) = account {
|
||||
let key_to_sign_transaction = account.key_holder.get_pub_account_signing_key();
|
||||
|
||||
let signed_transaction = Transaction::new(tx, key_to_sign_transaction);
|
||||
|
||||
Ok(self.sequencer_client.send_tx(signed_transaction).await?)
|
||||
} else {
|
||||
Err(ExecutionFailureKind::AmountMismatchError)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///Represents CLI command for a wallet
|
||||
#[derive(Subcommand, Debug, Clone)]
|
||||
#[clap(about)]
|
||||
pub enum Command {
|
||||
SendNativeTokenTransfer {
|
||||
///from - valid 32 byte hex string
|
||||
#[arg(long)]
|
||||
from: String,
|
||||
///nonce - u64 integer
|
||||
#[arg(long)]
|
||||
nonce: u64,
|
||||
///to - valid 32 byte hex string
|
||||
#[arg(long)]
|
||||
to: String,
|
||||
///amount - amount of balance to move
|
||||
#[arg(long)]
|
||||
amount: u64,
|
||||
},
|
||||
}
|
||||
|
||||
///To execute commands, env var NSSA_WALLET_HOME_DIR must be set into directory with config
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(version, about)]
|
||||
pub struct Args {
|
||||
/// Wallet command
|
||||
#[command(subcommand)]
|
||||
pub command: Command,
|
||||
}
|
||||
|
||||
pub async fn execute_subcommand(command: Command) -> Result<()> {
|
||||
match command {
|
||||
Command::SendNativeTokenTransfer {
|
||||
from,
|
||||
nonce,
|
||||
to,
|
||||
amount,
|
||||
} => {
|
||||
let wallet_config = fetch_config()?;
|
||||
|
||||
let from = produce_account_addr_from_hex(from)?;
|
||||
let to = produce_account_addr_from_hex(to)?;
|
||||
|
||||
let wallet_core = WalletCore::start_from_config_update_chain(wallet_config).await?;
|
||||
|
||||
let res = wallet_core
|
||||
.send_public_native_token_transfer(from, nonce, to, amount)
|
||||
.await?;
|
||||
|
||||
info!("Results of tx send is {res:#?}");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
24
wallet/src/main.rs
Normal file
24
wallet/src/main.rs
Normal file
@ -0,0 +1,24 @@
|
||||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use tokio::runtime::Builder;
|
||||
use wallet::{execute_subcommand, Args};
|
||||
|
||||
pub const NUM_THREADS: usize = 2;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let runtime = Builder::new_multi_thread()
|
||||
.worker_threads(NUM_THREADS)
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let args = Args::parse();
|
||||
|
||||
env_logger::init();
|
||||
|
||||
runtime.block_on(async move {
|
||||
execute_subcommand(args.command).await.unwrap();
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user