diff --git a/Dockerfile b/Dockerfile index 43e797f91d..8decdb5ed9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -138,7 +138,7 @@ RUN apt-get update \ # We fix the version of Rust here to ensure that we can update it without having # issues with the caching layers containing outdated versions which aren't compatible. RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o rustup.sh \ - && sh rustup.sh -y --target 1.71.1-aarch64-unknown-linux-gnu 1.71.1-x86_64-unknown-linux-gnu --default-toolchain 1.77.2 + && sh rustup.sh -y --target 1.81.0-aarch64-unknown-linux-gnu 1.81.0-x86_64-unknown-linux-gnu --default-toolchain 1.81.0 RUN "$HOME/.cargo/bin/cargo" install sccache --version 0.7.4 diff --git a/core-rust/Cargo.lock b/core-rust/Cargo.lock index 89bfbc8b67..7e941ef058 100644 --- a/core-rust/Cargo.lock +++ b/core-rust/Cargo.lock @@ -17,6 +17,18 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.0.4" @@ -63,6 +75,12 @@ version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "async-trait" version = "0.1.73" @@ -156,6 +174,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bech32" version = "0.9.1" @@ -210,16 +234,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", + "digest", ] [[package]] @@ -395,6 +410,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "const-sha1" version = "0.3.0" @@ -429,7 +450,7 @@ dependencies = [ "radix-common", "radix-engine", "radix-engine-interface", - "radix-engine-toolkit", + "radix-engine-toolkit-common", "radix-rust", "radix-substate-store-impls", "radix-substate-store-interface", @@ -504,17 +525,31 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "3.2.1" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", "subtle", "zeroize", ] +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + [[package]] name = "darling" version = "0.14.4" @@ -599,22 +634,23 @@ dependencies = [ ] [[package]] -name = "deranged" -version = "0.3.11" +name = "der" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ - "powerfmt", - "serde", + "const-oid", + "zeroize", ] [[package]] -name = "digest" -version = "0.9.0" +name = "deranged" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ - "generic-array", + "powerfmt", + "serde", ] [[package]] @@ -623,7 +659,7 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", + "block-buffer", "crypto-common", "subtle", ] @@ -636,24 +672,25 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" [[package]] name = "ed25519" -version = "1.5.3" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ + "pkcs8", "signature", ] [[package]] name = "ed25519-dalek" -version = "1.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", - "rand 0.7.3", "serde", "sha2", + "subtle", "zeroize", ] @@ -690,7 +727,7 @@ dependencies = [ "radix-substate-store-interface", "radix-substate-store-queries", "radix-transactions", - "rand 0.8.5", + "rand", "regex", "sbor", "serde", @@ -745,6 +782,12 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + [[package]] name = "fixedstr" version = "0.2.12" @@ -865,17 +908,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.10" @@ -884,7 +916,7 @@ checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -910,6 +942,9 @@ name = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", +] [[package]] name = "heck" @@ -1031,7 +1066,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" dependencies = [ "bitmaps", - "rand_core 0.6.4", + "rand_core", "rand_xoshiro", "sized-chunks", "typenum", @@ -1202,9 +1237,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "librocksdb-sys" @@ -1320,7 +1355,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys", ] @@ -1346,6 +1381,12 @@ dependencies = [ "uuid", ] +[[package]] +name = "multi-stash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685a9ac4b61f4e728e1d2c6a7844609c16527aeb5e6c865915c08e619c16410f" + [[package]] name = "node-common" version = "0.1.0" @@ -1412,6 +1453,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -1456,12 +1508,6 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - [[package]] name = "opentelemetry" version = "0.18.0" @@ -1530,7 +1576,7 @@ dependencies = [ "once_cell", "opentelemetry_api", "percent-encoding", - "rand 0.8.5", + "rand", "thiserror", "tokio", "tokio-stream", @@ -1634,6 +1680,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.27" @@ -1664,9 +1720,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -1707,8 +1763,8 @@ dependencies = [ [[package]] name = "radix-blueprint-schema-init" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "bitflags 1.3.2", "radix-common", @@ -1718,8 +1774,8 @@ dependencies = [ [[package]] name = "radix-common" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "bech32", "blake2", @@ -1744,8 +1800,8 @@ dependencies = [ [[package]] name = "radix-common-derive" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "paste", "proc-macro2", @@ -1756,8 +1812,8 @@ dependencies = [ [[package]] name = "radix-engine" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "bitflags 1.3.2", "colored", @@ -1777,18 +1833,18 @@ dependencies = [ "radix-substate-store-interface", "radix-transactions", "radix-wasm-instrument", - "radix-wasmi", "sbor", - "serde_json", "strum", "syn 1.0.109", + "tempfile", + "wasmi", "wasmparser 0.107.0", ] [[package]] name = "radix-engine-interface" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "bitflags 1.3.2", "const-sha1", @@ -1808,16 +1864,16 @@ dependencies = [ [[package]] name = "radix-engine-profiling" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "fixedstr", ] [[package]] name = "radix-engine-profiling-derive" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "proc-macro2", "quote", @@ -1826,15 +1882,14 @@ dependencies = [ ] [[package]] -name = "radix-engine-toolkit" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +name = "radix-engine-toolkit-common" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "radix-common", "radix-engine", "radix-engine-interface", "radix-rust", - "radix-substate-store-interface", "sbor", "serde", "serde_with 3.9.0", @@ -1842,8 +1897,8 @@ dependencies = [ [[package]] name = "radix-native-sdk" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "radix-common", "radix-engine-interface", @@ -1853,8 +1908,8 @@ dependencies = [ [[package]] name = "radix-rust" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "indexmap 2.2.6", "serde", @@ -1862,8 +1917,8 @@ dependencies = [ [[package]] name = "radix-sbor-derive" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "proc-macro2", "quote", @@ -1873,8 +1928,8 @@ dependencies = [ [[package]] name = "radix-substate-store-impls" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "hex", "itertools", @@ -1887,8 +1942,8 @@ dependencies = [ [[package]] name = "radix-substate-store-interface" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "hex", "itertools", @@ -1899,8 +1954,8 @@ dependencies = [ [[package]] name = "radix-substate-store-queries" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "hex", "itertools", @@ -1916,8 +1971,8 @@ dependencies = [ [[package]] name = "radix-transaction-scenarios" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "hex", "itertools", @@ -1936,16 +1991,18 @@ dependencies = [ [[package]] name = "radix-transactions" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "annotate-snippets", "bech32", "hex", "lazy_static", + "paste", "radix-common", "radix-engine-interface", "radix-rust", + "radix-substate-store-interface", "sbor", "strum", ] @@ -1963,37 +2020,6 @@ dependencies = [ "wasmprinter", ] -[[package]] -name = "radix-wasmi" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59bf4a0498ed223122e726f9360e9889c2bb6eb6898069f4b6f9960b067a742d" -dependencies = [ - "radix-wasmi-arena", - "spin", - "wasmi_core", - "wasmparser-nostd", -] - -[[package]] -name = "radix-wasmi-arena" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a03d7e7816ade40c6ecedff7515198906d644527771bd8fb5a335094353a15a" - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - [[package]] name = "rand" version = "0.8.5" @@ -2001,18 +2027,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", + "rand_chacha", + "rand_core", ] [[package]] @@ -2022,16 +2038,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", + "rand_core", ] [[package]] @@ -2040,16 +2047,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.10", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", + "getrandom", ] [[package]] @@ -2058,7 +2056,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" dependencies = [ - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -2166,8 +2164,8 @@ dependencies = [ [[package]] name = "sbor" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "const-sha1", "hex", @@ -2180,8 +2178,8 @@ dependencies = [ [[package]] name = "sbor-derive" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "proc-macro2", "sbor-derive-common", @@ -2190,10 +2188,11 @@ dependencies = [ [[package]] name = "sbor-derive-common" -version = "1.2.0" -source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=bottlenose-e1f25ed9#e1f25ed9a1e64f720193477504ec46e9850f4ee3" +version = "1.3.0-dev" +source = "git+https://github.com/radixdlt/radixdlt-scrypto?tag=cuttlefish-96326032#96326032783d8858e9814590a728cd277ca27f6b" dependencies = [ "const-sha1", + "indexmap 2.2.6", "itertools", "proc-macro2", "quote", @@ -2356,15 +2355,13 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.9" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "block-buffer 0.9.0", "cfg-if", "cpufeatures", - "digest 0.9.0", - "opaque-debug", + "digest", ] [[package]] @@ -2373,7 +2370,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest 0.10.7", + "digest", "keccak", ] @@ -2388,9 +2385,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" @@ -2403,9 +2400,12 @@ dependencies = [ [[package]] name = "signature" -version = "1.6.4" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "rand_core", +] [[package]] name = "sized-chunks" @@ -2452,9 +2452,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" @@ -2482,6 +2482,16 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "state-manager" version = "0.1.0" @@ -2505,7 +2515,7 @@ dependencies = [ "radix-substate-store-queries", "radix-transaction-scenarios", "radix-transactions", - "rand 0.8.5", + "rand", "sbor", "slotmap", "tempfile", @@ -2513,6 +2523,17 @@ dependencies = [ "tracing", ] +[[package]] +name = "string-interner" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c6a0d765f5807e98a091107bae0a56ea3799f66a5de47b2c84c94a39c09974e" +dependencies = [ + "cfg-if", + "hashbrown 0.14.3", + "serde", +] + [[package]] name = "strsim" version = "0.10.0" @@ -2908,7 +2929,7 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" dependencies = [ - "getrandom 0.2.10", + "getrandom", ] [[package]] @@ -2948,12 +2969,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -3023,11 +3038,39 @@ dependencies = [ "leb128", ] +[[package]] +name = "wasmi" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbaac6e702fa7b52258e5ac90d6e20a40afb37a1fbe7c645d0903ee42c5f85f4" +dependencies = [ + "arrayvec", + "multi-stash", + "num-derive", + "num-traits", + "smallvec", + "spin", + "wasmi_collections", + "wasmi_core", + "wasmparser-nostd", +] + +[[package]] +name = "wasmi_collections" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ff59e30e550a509cc689ec638e5042be4d78ec9f6dd8a71fd02ee28776a74fd" +dependencies = [ + "ahash", + "hashbrown 0.14.3", + "string-interner", +] + [[package]] name = "wasmi_core" -version = "0.8.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d21fc8d8dafc2df566ebcba7d48a2df7b37386d6afa64237cdf9415c8d7d98ec" +checksum = "13e10c674add0f92f47bf8ad57c55ee3ac1762a0d9baf07535e27e22b758a916" dependencies = [ "downcast-rs", "libm", @@ -3057,9 +3100,9 @@ dependencies = [ [[package]] name = "wasmparser-nostd" -version = "0.91.0" +version = "0.100.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c37f310b5a62bfd5ae7c0f1d8e6f98af16a5d6d84ba764e9c36439ec14e318b" +checksum = "d5a015fe95f3504a94bb1462c717aae75253e39b9dd6c3fb1062c934535c64aa" dependencies = [ "indexmap-nostd", ] @@ -3244,11 +3287,31 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + [[package]] name = "zeroize" -version = "1.3.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] diff --git a/core-rust/Cargo.toml b/core-rust/Cargo.toml index b3ebb62c76..3c8aab5ac2 100644 --- a/core-rust/Cargo.toml +++ b/core-rust/Cargo.toml @@ -23,18 +23,18 @@ resolver = "2" # $ git push origin "release_name-BLAH" # * Then use tag="release_name-BLAH" in the below dependencies. # -sbor = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "bottlenose-e1f25ed9", features = ["serde"] } -radix-transactions = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "bottlenose-e1f25ed9" } -radix-transaction-scenarios = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "bottlenose-e1f25ed9" } -radix-common = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "bottlenose-e1f25ed9", features = ["serde"] } -radix-engine-interface = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "bottlenose-e1f25ed9" } -radix-engine = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "bottlenose-e1f25ed9" } -radix-substate-store-impls = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "bottlenose-e1f25ed9" } -radix-substate-store-interface = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "bottlenose-e1f25ed9" } -radix-substate-store-queries = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "bottlenose-e1f25ed9" } -radix-rust = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "bottlenose-e1f25ed9", features = ["serde"] } -radix-blueprint-schema-init = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "bottlenose-e1f25ed9", features = ["serde"] } -radix-engine-toolkit = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "bottlenose-e1f25ed9" } +sbor = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "cuttlefish-96326032", features = ["serde"] } +radix-transactions = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "cuttlefish-96326032" } +radix-transaction-scenarios = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "cuttlefish-96326032" } +radix-common = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "cuttlefish-96326032", features = ["serde"] } +radix-engine-interface = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "cuttlefish-96326032" } +radix-engine = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "cuttlefish-96326032" } +radix-substate-store-impls = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "cuttlefish-96326032" } +radix-substate-store-interface = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "cuttlefish-96326032" } +radix-substate-store-queries = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "cuttlefish-96326032" } +radix-rust = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "cuttlefish-96326032", features = ["serde"] } +radix-blueprint-schema-init = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "cuttlefish-96326032", features = ["serde"] } +radix-engine-toolkit-common = { git = "https://github.com/radixdlt/radixdlt-scrypto", tag = "cuttlefish-96326032" } itertools = { version = "=0.10.5" } jni = { version = "=0.19.0" } diff --git a/core-rust/core-api-server/Cargo.toml b/core-rust/core-api-server/Cargo.toml index a6ff45abd3..00359f524a 100644 --- a/core-rust/core-api-server/Cargo.toml +++ b/core-rust/core-api-server/Cargo.toml @@ -17,7 +17,7 @@ radix-substate-store-interface = { workspace = true } radix-substate-store-queries = { workspace = true } radix-blueprint-schema-init = { workspace = true } radix-rust = { workspace = true } -radix-engine-toolkit = { workspace = true } +radix-engine-toolkit-common = { workspace = true } # Non-Radix Engine Dependencies: jni = { workspace = true } diff --git a/core-rust/core-api-server/src/core_api/conversions/addressing.rs b/core-rust/core-api-server/src/core_api/conversions/addressing.rs index 6dee4e5034..8268910b9e 100644 --- a/core-rust/core-api-server/src/core_api/conversions/addressing.rs +++ b/core-rust/core-api-server/src/core_api/conversions/addressing.rs @@ -1,6 +1,4 @@ -use crate::core_api::models; -use crate::core_api::*; -use crate::engine_prelude::*; +use crate::prelude::*; use models::SubstateType; pub fn to_api_global_address( @@ -68,14 +66,16 @@ pub fn to_api_entity_type(entity_type: EntityType) -> models::EntityType { EntityType::GlobalAccountLocker => models::EntityType::GlobalAccountLocker, EntityType::GlobalIdentity => models::EntityType::GlobalIdentity, EntityType::GlobalGenericComponent => models::EntityType::GlobalGenericComponent, - EntityType::GlobalVirtualSecp256k1Account => { + EntityType::GlobalPreallocatedSecp256k1Account => { models::EntityType::GlobalVirtualSecp256k1Account } - EntityType::GlobalVirtualEd25519Account => models::EntityType::GlobalVirtualEd25519Account, - EntityType::GlobalVirtualSecp256k1Identity => { + EntityType::GlobalPreallocatedEd25519Account => { + models::EntityType::GlobalVirtualEd25519Account + } + EntityType::GlobalPreallocatedSecp256k1Identity => { models::EntityType::GlobalVirtualSecp256k1Identity } - EntityType::GlobalVirtualEd25519Identity => { + EntityType::GlobalPreallocatedEd25519Identity => { models::EntityType::GlobalVirtualEd25519Identity } EntityType::InternalFungibleVault => models::EntityType::InternalFungibleVault, @@ -140,6 +140,10 @@ pub fn to_api_substate_id( SubstateType::BootLoaderModuleFieldKernelBoot, models::PartitionKind::Field, ), + TypedSubstateKey::BootLoader(TypedBootLoaderSubstateKey::BootLoaderField( + BootLoaderField::TransactionValidationConfiguration, + )) => todo!(), + TypedSubstateKey::ProtocolUpdateStatus(_) => todo!(), TypedSubstateKey::TypeInfo(TypedTypeInfoSubstateKey::TypeInfoField( TypeInfoField::TypeInfo, )) => ( @@ -459,6 +463,7 @@ pub fn to_api_substate_id( let entity_module = match typed_substate_key { TypedSubstateKey::BootLoader(_) => models::EntityModule::BootLoader, + TypedSubstateKey::ProtocolUpdateStatus(_) => todo!(), TypedSubstateKey::TypeInfo(_) => models::EntityModule::TypeInfo, TypedSubstateKey::RoleAssignmentModule(_) => models::EntityModule::RoleAssignment, TypedSubstateKey::RoyaltyModule(_) => models::EntityModule::Royalty, @@ -609,8 +614,8 @@ pub fn to_api_object_module_partition_kind( AccessControllerPartitionOffset::Field => models::PartitionKind::Field, } } - EntityType::GlobalVirtualSecp256k1Account - | EntityType::GlobalVirtualEd25519Account + EntityType::GlobalPreallocatedSecp256k1Account + | EntityType::GlobalPreallocatedEd25519Account | EntityType::GlobalAccount => match AccountPartitionOffset::try_from(partition_offset)? { AccountPartitionOffset::Field => models::PartitionKind::Field, AccountPartitionOffset::ResourceVaultKeyValue => models::PartitionKind::KeyValue, @@ -624,8 +629,8 @@ pub fn to_api_object_module_partition_kind( } } } - EntityType::GlobalVirtualSecp256k1Identity - | EntityType::GlobalVirtualEd25519Identity + EntityType::GlobalPreallocatedSecp256k1Identity + | EntityType::GlobalPreallocatedEd25519Identity | EntityType::GlobalIdentity => Err(())?, // Identity doesn't have any substates EntityType::InternalFungibleVault => { match FungibleVaultPartitionOffset::try_from(partition_offset)? { diff --git a/core-rust/core-api-server/src/core_api/conversions/common.rs b/core-rust/core-api-server/src/core_api/conversions/common.rs index 69e8bcd8ca..b6572c73cc 100644 --- a/core-rust/core-api-server/src/core_api/conversions/common.rs +++ b/core-rust/core-api-server/src/core_api/conversions/common.rs @@ -1,5 +1,4 @@ -use crate::engine_prelude::*; -use state_manager::{LedgerStateSummary, StateVersion}; +use crate::prelude::*; use crate::core_api::handlers::to_api_epoch_round; use crate::core_api::*; diff --git a/core-rust/core-api-server/src/core_api/conversions/context.rs b/core-rust/core-api-server/src/core_api/conversions/context.rs index 8bc600fd25..2378c459ac 100644 --- a/core-rust/core-api-server/src/core_api/conversions/context.rs +++ b/core-rust/core-api-server/src/core_api/conversions/context.rs @@ -1,6 +1,4 @@ -use crate::engine_prelude::*; - -use crate::core_api::models; +use crate::prelude::*; pub struct MappingContext { pub network_definition: NetworkDefinition, diff --git a/core-rust/core-api-server/src/core_api/conversions/errors.rs b/core-rust/core-api-server/src/core_api/conversions/errors.rs index 543c0a242e..437ddfcba1 100644 --- a/core-rust/core-api-server/src/core_api/conversions/errors.rs +++ b/core-rust/core-api-server/src/core_api/conversions/errors.rs @@ -1,11 +1,8 @@ -use crate::engine_prelude::*; -use state_manager::StateVersion; -use tracing::warn; - -use crate::core_api::*; +use crate::prelude::*; /// Should be used when there's an error mapping to an API response #[derive(Debug, Clone)] +#[allow(unused)] // Debug is ignored for dead code analysis, but is used in the error messages pub enum MappingError { PartitionNumber { entity_address: String, @@ -91,6 +88,7 @@ impl From for ResponseError { /// Should be used when extracting values from a client request #[derive(Debug, Clone)] #[allow(clippy::enum_variant_names)] +#[allow(unused)] // Debug is ignored for dead code analysis, but is used in the error messages pub enum ExtractionError { InvalidInteger { message: String, diff --git a/core-rust/core-api-server/src/core_api/conversions/hashes.rs b/core-rust/core-api-server/src/core_api/conversions/hashes.rs index 5aef7f647c..d72ba03ed7 100644 --- a/core-rust/core-api-server/src/core_api/conversions/hashes.rs +++ b/core-rust/core-api-server/src/core_api/conversions/hashes.rs @@ -1,25 +1,26 @@ -use crate::engine_prelude::*; -use state_manager::{transaction::*, ReceiptTreeHash, StateHash, TransactionTreeHash}; +use crate::prelude::*; -use crate::core_api::*; - -pub fn to_api_intent_hash(intent_hash: &IntentHash) -> String { - to_hex(intent_hash) +pub fn to_api_transaction_intent_hash(transaction_intent_hash: &TransactionIntentHash) -> String { + to_hex(transaction_intent_hash) } -pub fn to_api_signed_intent_hash(signed_intent_hash: &SignedIntentHash) -> String { - to_hex(signed_intent_hash) +pub fn to_api_signed_transaction_intent_hash( + signed_transaction_intent_hash: &SignedTransactionIntentHash, +) -> String { + to_hex(signed_transaction_intent_hash) } -pub fn to_api_notarized_transaction_hash(payload_hash: &NotarizedTransactionHash) -> String { - to_hex(payload_hash) +pub fn to_api_notarized_transaction_hash( + notarized_transaction_hash: &NotarizedTransactionHash, +) -> String { + to_hex(notarized_transaction_hash) } pub fn to_api_ledger_hash(ledger_hash: &LedgerTransactionHash) -> String { to_hex(ledger_hash) } -pub fn to_api_hash_bech32m( +pub fn to_api_hash_bech32m( context: &MappingContext, hash: &T, ) -> Result { @@ -49,14 +50,14 @@ pub fn to_api_code_hash(hash: &CodeHash) -> String { to_hex(hash) } -pub fn extract_intent_hash( +pub fn extract_transaction_intent_hash( context: &ExtractionContext, hash_str: String, -) -> Result { +) -> Result { from_hex(&hash_str) .ok() .and_then(|bytes| Hash::try_from(bytes.as_slice()).ok()) - .map(IntentHash::from_hash) + .map(TransactionIntentHash::from_hash) .or_else(|| { context .transaction_hash_decoder diff --git a/core-rust/core-api-server/src/core_api/conversions/keys_and_sigs.rs b/core-rust/core-api-server/src/core_api/conversions/keys_and_sigs.rs index 59ac861942..3562f14c92 100644 --- a/core-rust/core-api-server/src/core_api/conversions/keys_and_sigs.rs +++ b/core-rust/core-api-server/src/core_api/conversions/keys_and_sigs.rs @@ -1,6 +1,4 @@ -use crate::engine_prelude::*; - -use crate::core_api::*; +use crate::prelude::*; pub fn to_api_public_key(public_key: &PublicKey) -> models::PublicKey { match public_key { diff --git a/core-rust/core-api-server/src/core_api/conversions/lts.rs b/core-rust/core-api-server/src/core_api/conversions/lts.rs index 8d3bae4244..84e44cc80e 100644 --- a/core-rust/core-api-server/src/core_api/conversions/lts.rs +++ b/core-rust/core-api-server/src/core_api/conversions/lts.rs @@ -1,13 +1,4 @@ -use crate::engine_prelude::*; -use node_common::store::rocks_db::ReadableRocks; -use state_manager::store::rocks_db::StateManagerDatabase; -use state_manager::store::traits::SubstateNodeAncestryStore; -use state_manager::{ - CommittedTransactionIdentifiers, LedgerTransactionOutcome, LocalTransactionReceipt, - StateVersion, TransactionTreeHash, -}; - -use crate::core_api::*; +use crate::prelude::*; #[tracing::instrument(skip_all)] pub fn to_api_lts_committed_transaction_outcome( @@ -30,24 +21,28 @@ pub fn to_api_lts_committed_transaction_outcome( &identifiers.resultant_ledger_hashes.transaction_root, ), user_transaction_identifiers: identifiers - .payload - .typed - .user() + .transaction_hashes + .as_user() .map(|hashes| { Ok(Box::new(models::TransactionIdentifiers { - intent_hash: to_api_intent_hash(hashes.intent_hash), - intent_hash_bech32m: to_api_hash_bech32m(context, hashes.intent_hash)?, - signed_intent_hash: to_api_signed_intent_hash(hashes.signed_intent_hash), + intent_hash: to_api_transaction_intent_hash(&hashes.transaction_intent_hash), + intent_hash_bech32m: to_api_hash_bech32m( + context, + &hashes.transaction_intent_hash, + )?, + signed_intent_hash: to_api_signed_transaction_intent_hash( + &hashes.signed_transaction_intent_hash, + ), signed_intent_hash_bech32m: to_api_hash_bech32m( context, - hashes.signed_intent_hash, + &hashes.signed_transaction_intent_hash, )?, payload_hash: to_api_notarized_transaction_hash( - hashes.notarized_transaction_hash, + &hashes.notarized_transaction_hash, ), payload_hash_bech32m: to_api_hash_bech32m( context, - hashes.notarized_transaction_hash, + &hashes.notarized_transaction_hash, )?, })) }) diff --git a/core-rust/core-api-server/src/core_api/conversions/numerics.rs b/core-rust/core-api-server/src/core_api/conversions/numerics.rs index 575da7754c..84517369aa 100644 --- a/core-rust/core-api-server/src/core_api/conversions/numerics.rs +++ b/core-rust/core-api-server/src/core_api/conversions/numerics.rs @@ -1,15 +1,10 @@ +use crate::prelude::*; use chrono::prelude::*; use std::any::type_name; use std::ops::RangeInclusive; -use crate::engine_prelude::*; -use state_manager::store::traits::scenario::ScenarioSequenceNumber; -use state_manager::StateVersion; - use crate::core_api::models; -use super::*; - // See the guidance in the top of the core-api-schema.yaml // These should be duplicated in the Open API schema along with the actual types // If mapped to i32, these need to be below 4294967295 = 2^32 - 1 to ensure they fit into an i64 on the OAS. diff --git a/core-rust/core-api-server/src/core_api/conversions/pagination.rs b/core-rust/core-api-server/src/core_api/conversions/pagination.rs index 9b545fb856..9641ba734e 100644 --- a/core-rust/core-api-server/src/core_api/conversions/pagination.rs +++ b/core-rust/core-api-server/src/core_api/conversions/pagination.rs @@ -1,5 +1,4 @@ -use crate::core_api::*; -use crate::engine_prelude::*; +use crate::prelude::*; pub struct SizeRange { pub min: usize, diff --git a/core-rust/core-api-server/src/core_api/conversions/receipt.rs b/core-rust/core-api-server/src/core_api/conversions/receipt.rs index 9703b26bee..4b28aa99d0 100644 --- a/core-rust/core-api-server/src/core_api/conversions/receipt.rs +++ b/core-rust/core-api-server/src/core_api/conversions/receipt.rs @@ -1,16 +1,6 @@ #![allow(clippy::too_many_arguments)] -use super::addressing::*; -use crate::core_api::*; -use crate::engine_prelude::*; - -use node_common::store::rocks_db::ReadableRocks; -use state_manager::store::rocks_db::StateManagerDatabase; -use state_manager::{ - ApplicationEvent, BySubstate, DetailedTransactionOutcome, LedgerStateChanges, - LocalTransactionReceipt, PartitionChangeAction, PartitionReference, SubstateChangeAction, - SubstateReference, -}; +use crate::prelude::*; pub fn to_api_receipt( database: Option<&StateManagerDatabase>, @@ -158,6 +148,8 @@ pub fn to_api_substate_system_structure( SystemFieldKind::VmBoot => models::SystemFieldKind::VmBoot, SystemFieldKind::SystemBoot => models::SystemFieldKind::SystemBoot, SystemFieldKind::KernelBoot => models::SystemFieldKind::KernelBoot, + SystemFieldKind::TransactionValidationConfiguration => todo!(), + SystemFieldKind::ProtocolUpdateStatusSummary => todo!(), }, } } @@ -558,10 +550,10 @@ impl StateMappingLookups { // Step 2 - Create the lookups from the database let mut blueprint_type_lookups = IndexMap::new(); for (package_address, blueprint_name) in blueprints_to_fetch_types { - let definition = database.get_mapped::( - package_address.as_node_id(), + let definition = database.get_substate::( + package_address, PackagePartitionOffset::BlueprintVersionDefinitionKeyValue.as_main_partition(), - &SubstateKey::Map(scrypto_encode(&PackageBlueprintVersionDefinitionKeyPayload::from_content_source( + SubstateKey::Map(scrypto_encode(&PackageBlueprintVersionDefinitionKeyPayload::from_content_source( BlueprintVersionKey::new_default(blueprint_name.clone()) )).unwrap()), ).ok_or_else(|| MappingError::CouldNotResolveRemoteGenericSubstitution { @@ -690,8 +682,9 @@ pub fn to_api_fee_summary( pub fn to_api_costing_parameters( _context: &MappingContext, engine_costing_parameters: &CostingParameters, - transaction_costing_parameters: &TransactionCostingParametersReceipt, + transaction_costing_parameters: &TransactionCostingParametersReceiptV2, ) -> Result { + let tip_percentage_decimal: Decimal = transaction_costing_parameters.tip_proportion * 100; Ok(models::CostingParameters { execution_cost_unit_price: to_api_decimal( &engine_costing_parameters.execution_cost_unit_price, @@ -711,7 +704,7 @@ pub fn to_api_costing_parameters( xrd_usd_price: to_api_decimal(&engine_costing_parameters.usd_price), xrd_storage_price: to_api_decimal(&engine_costing_parameters.state_storage_price), xrd_archive_storage_price: to_api_decimal(&engine_costing_parameters.archive_storage_price), - tip_percentage: to_api_u16_as_i32(transaction_costing_parameters.tip_percentage), + tip_percentage: tip_percentage_decimal.try_into().unwrap_or(i32::MAX), }) } diff --git a/core-rust/core-api-server/src/core_api/conversions/substates/access_rules_module.rs b/core-rust/core-api-server/src/core_api/conversions/substates/access_rules_module.rs index 9ad05d1620..8695d6e6d0 100644 --- a/core-rust/core-api-server/src/core_api/conversions/substates/access_rules_module.rs +++ b/core-rust/core-api-server/src/core_api/conversions/substates/access_rules_module.rs @@ -63,20 +63,22 @@ pub fn to_api_access_rule( pub fn to_api_access_rule_node( context: &MappingContext, - access_rule: &AccessRuleNode, + composite_requirement: &CompositeRequirement, ) -> Result { - Ok(match access_rule { - AccessRuleNode::ProofRule(proof_rule) => models::AccessRuleNode::ProofAccessRuleNode { - proof_rule: Box::new(to_api_proof_rule(context, proof_rule)?), - }, - AccessRuleNode::AnyOf(access_rules) => models::AccessRuleNode::AnyOfAccessRuleNode { - access_rules: access_rules + Ok(match composite_requirement { + CompositeRequirement::BasicRequirement(requirement) => { + models::AccessRuleNode::ProofAccessRuleNode { + proof_rule: Box::new(to_api_proof_rule(context, requirement)?), + } + } + CompositeRequirement::AnyOf(requirements) => models::AccessRuleNode::AnyOfAccessRuleNode { + access_rules: requirements .iter() .map(|ar| to_api_access_rule_node(context, ar)) .collect::>()?, }, - AccessRuleNode::AllOf(access_rules) => models::AccessRuleNode::AllOfAccessRuleNode { - access_rules: access_rules + CompositeRequirement::AllOf(requirements) => models::AccessRuleNode::AllOfAccessRuleNode { + access_rules: requirements .iter() .map(|ar| to_api_access_rule_node(context, ar)) .collect::>()?, @@ -86,23 +88,29 @@ pub fn to_api_access_rule_node( pub fn to_api_proof_rule( context: &MappingContext, - proof_rule: &ProofRule, + requirement: &BasicRequirement, ) -> Result { - Ok(match proof_rule { - ProofRule::Require(resource_or_non_fungible) => models::ProofRule::RequireProofRule { - requirement: Box::new(to_api_requirement(context, resource_or_non_fungible)?), - }, - ProofRule::AmountOf(amount, resource) => models::ProofRule::AmountOfProofRule { + Ok(match requirement { + BasicRequirement::Require(resource_or_non_fungible) => { + models::ProofRule::RequireProofRule { + requirement: Box::new(to_api_requirement(context, resource_or_non_fungible)?), + } + } + BasicRequirement::AmountOf(amount, resource) => models::ProofRule::AmountOfProofRule { amount: to_api_decimal(amount), resource: to_api_resource_address(context, resource)?, }, - ProofRule::AllOf(resource_or_non_fungible_list) => models::ProofRule::AllOfProofRule { - list: to_api_resource_or_non_fungible_list(context, resource_or_non_fungible_list)?, - }, - ProofRule::AnyOf(resource_or_non_fungible_list) => models::ProofRule::AnyOfProofRule { - list: to_api_resource_or_non_fungible_list(context, resource_or_non_fungible_list)?, - }, - ProofRule::CountOf(count, resource_or_non_fungible_list) => { + BasicRequirement::AllOf(resource_or_non_fungible_list) => { + models::ProofRule::AllOfProofRule { + list: to_api_resource_or_non_fungible_list(context, resource_or_non_fungible_list)?, + } + } + BasicRequirement::AnyOf(resource_or_non_fungible_list) => { + models::ProofRule::AnyOfProofRule { + list: to_api_resource_or_non_fungible_list(context, resource_or_non_fungible_list)?, + } + } + BasicRequirement::CountOf(count, resource_or_non_fungible_list) => { models::ProofRule::CountOfProofRule { count: *count as i32, list: to_api_resource_or_non_fungible_list(context, resource_or_non_fungible_list)?, diff --git a/core-rust/core-api-server/src/core_api/conversions/substates/boot_loader_module.rs b/core-rust/core-api-server/src/core_api/conversions/substates/boot_loader_module.rs index 388a134ecc..f3cc3ccfd1 100644 --- a/core-rust/core-api-server/src/core_api/conversions/substates/boot_loader_module.rs +++ b/core-rust/core-api-server/src/core_api/conversions/substates/boot_loader_module.rs @@ -13,6 +13,7 @@ pub fn to_api_system_boot_substate( SystemBoot::V1(system_parameters) => models::BootLoaderModuleFieldSystemBootValue::new( to_api_system_parameters(context, system_parameters)?, ), + SystemBoot::V2(..) => todo!(), }; Ok(models::Substate::BootLoaderModuleFieldSystemBootSubstate { @@ -46,6 +47,7 @@ pub fn to_api_kernel_boot_substate( let value = match substate { // Note: this is how OpenAPI generator represents an empty object type, even when named: KernelBoot::V1 => serde_json::Value::Object(serde_json::Map::default()), + KernelBoot::V2(_) => todo!(), }; Ok(models::Substate::BootLoaderModuleFieldKernelBootSubstate { @@ -105,8 +107,8 @@ fn to_api_network_definition( } = network_definition; Ok(models::NetworkDefinition { id: to_api_u8_as_i32(*id), - logical_name: logical_name.clone(), - hrp_suffix: hrp_suffix.clone(), + logical_name: logical_name.to_string(), + hrp_suffix: hrp_suffix.to_string(), }) } diff --git a/core-rust/core-api-server/src/core_api/conversions/substates/substate.rs b/core-rust/core-api-server/src/core_api/conversions/substates/substate.rs index 16931c2dcd..0bfdb3ee85 100644 --- a/core-rust/core-api-server/src/core_api/conversions/substates/substate.rs +++ b/core-rust/core-api-server/src/core_api/conversions/substates/substate.rs @@ -20,6 +20,10 @@ pub fn to_api_substate( TypedSubstateValue::BootLoader(BootLoaderSubstateValue::Kernel(kernel_boot_substate)) => { to_api_kernel_boot_substate(context, state_mapping_lookups, kernel_boot_substate)? } + TypedSubstateValue::BootLoader(BootLoaderSubstateValue::TransactionValidation(_)) => { + todo!() + } + TypedSubstateValue::ProtocolUpdateStatus(_) => todo!(), TypedSubstateValue::TypeInfoModule(TypedTypeInfoModuleSubstateValue::TypeInfo( type_info_substate, )) => to_api_type_info_substate(context, state_mapping_lookups, type_info_substate)?, diff --git a/core-rust/core-api-server/src/core_api/conversions/substates/transaction_tracker.rs b/core-rust/core-api-server/src/core_api/conversions/substates/transaction_tracker.rs index 71effdc48a..40e7374116 100644 --- a/core-rust/core-api-server/src/core_api/conversions/substates/transaction_tracker.rs +++ b/core-rust/core-api-server/src/core_api/conversions/substates/transaction_tracker.rs @@ -44,7 +44,7 @@ pub fn to_api_transaction_tracker_collection_entry( substate, TransactionTrackerCollectionEntry, models::TransactionIdKey { - intent_hash: to_api_intent_hash(intent_hash), + intent_hash: to_api_transaction_intent_hash(intent_hash), intent_hash_bech32m: to_api_hash_bech32m(context, intent_hash)?, }, value => { diff --git a/core-rust/core-api-server/src/core_api/errors.rs b/core-rust/core-api-server/src/core_api/errors.rs index 5c2f68af5e..59c16c4d4c 100644 --- a/core-rust/core-api-server/src/core_api/errors.rs +++ b/core-rust/core-api-server/src/core_api/errors.rs @@ -1,23 +1,13 @@ -use axum::body::BoxBody; -use axum::{ - response::{IntoResponse, Response}, - Json, -}; -use models::stream_proofs_error_details::StreamProofsErrorDetails; +use crate::prelude::*; use std::any::Any; -use crate::engine_prelude::*; -use hyper::StatusCode; use tower_http::catch_panic::ResponseForPanic; -use super::{models, CoreApiState}; -use crate::core_api::models::StreamTransactionsErrorDetails; use models::{ lts_transaction_submit_error_details::LtsTransactionSubmitErrorDetails, + stream_proofs_error_details::StreamProofsErrorDetails, transaction_submit_error_details::TransactionSubmitErrorDetails, }; -use state_manager::historical_state::StateHistoryError; -use state_manager::transaction::PreviewerError; /// A marker trait for custom error details pub trait ErrorDetails: serde::Serialize + Debug + Sized { @@ -76,7 +66,7 @@ impl ErrorDetails for LtsTransactionSubmitErrorDetails { } } -impl ErrorDetails for StreamTransactionsErrorDetails { +impl ErrorDetails for models::StreamTransactionsErrorDetails { fn to_error_response( details: Option, code: i32, diff --git a/core-rust/core-api-server/src/core_api/handlers/lts/state_account_all_fungible_resource_balances.rs b/core-rust/core-api-server/src/core_api/handlers/lts/state_account_all_fungible_resource_balances.rs index 8c81151be1..fefe80f48a 100644 --- a/core-rust/core-api-server/src/core_api/handlers/lts/state_account_all_fungible_resource_balances.rs +++ b/core-rust/core-api-server/src/core_api/handlers/lts/state_account_all_fungible_resource_balances.rs @@ -1,9 +1,4 @@ -use crate::core_api::*; -use crate::engine_prelude::*; - -use state_manager::query::{dump_component_state, VaultData}; - -use std::ops::Deref; +use crate::prelude::*; #[tracing::instrument(skip(state))] pub(crate) async fn handle_lts_state_account_all_fungible_resource_balances( @@ -43,7 +38,7 @@ pub(crate) async fn handle_lts_state_account_all_fungible_resource_balances( ); if type_info.is_none() { - if component_address.as_node_id().is_global_virtual() { + if component_address.as_node_id().is_global_preallocated() { return Ok(Json( models::LtsStateAccountAllFungibleResourceBalancesResponse { state_version: to_api_state_version(header.state_version)?, diff --git a/core-rust/core-api-server/src/core_api/handlers/lts/state_account_deposit_behaviour.rs b/core-rust/core-api-server/src/core_api/handlers/lts/state_account_deposit_behaviour.rs index f444ae62f4..d80c34424d 100644 --- a/core-rust/core-api-server/src/core_api/handlers/lts/state_account_deposit_behaviour.rs +++ b/core-rust/core-api-server/src/core_api/handlers/lts/state_account_deposit_behaviour.rs @@ -1,10 +1,4 @@ -use crate::core_api::*; -use crate::engine_prelude::*; - -use state_manager::LedgerHeader; -use std::ops::Deref; - -use node_common::utils::IsAccountExt; +use crate::prelude::*; /// Maximum number of resource addresses allowed in the request. /// Must be aligned with the `maxItems` in the API documentation. @@ -66,7 +60,7 @@ pub(crate) async fn handle_lts_state_account_deposit_behaviour( // If it does not exist, then either it is an empty virtual account, or a bad account address: let Some(default_deposit_rule) = default_deposit_rule else { - return if account_address.as_node_id().is_global_virtual() { + return if account_address.as_node_id().is_global_preallocated() { Ok(empty_virtual_account_response( &mapping_context, &header, diff --git a/core-rust/core-api-server/src/core_api/handlers/lts/state_account_resource_balance.rs b/core-rust/core-api-server/src/core_api/handlers/lts/state_account_resource_balance.rs index cfddb3b783..781b3297a4 100644 --- a/core-rust/core-api-server/src/core_api/handlers/lts/state_account_resource_balance.rs +++ b/core-rust/core-api-server/src/core_api/handlers/lts/state_account_resource_balance.rs @@ -1,8 +1,4 @@ -use crate::core_api::*; -use crate::engine_prelude::*; - -use state_manager::LedgerHeader; -use std::ops::Deref; +use crate::prelude::*; #[tracing::instrument(skip(state))] pub(crate) async fn handle_lts_state_account_fungible_resource_balance( @@ -43,7 +39,7 @@ pub(crate) async fn handle_lts_state_account_fungible_resource_balance( let database = state.state_manager.database.snapshot(); - if !account_address.as_node_id().is_global_virtual() { + if !account_address.as_node_id().is_global_preallocated() { read_optional_substate::( database.deref(), account_address.as_node_id(), @@ -63,7 +59,7 @@ pub(crate) async fn handle_lts_state_account_fungible_resource_balance( ); if type_info.is_none() { - if account_address.as_node_id().is_global_virtual() { + if account_address.as_node_id().is_global_preallocated() { return response( &mapping_context, &header, diff --git a/core-rust/core-api-server/src/core_api/handlers/lts/stream_account_transaction_outcomes.rs b/core-rust/core-api-server/src/core_api/handlers/lts/stream_account_transaction_outcomes.rs index 6dbd3eefe8..b4da8fe46c 100644 --- a/core-rust/core-api-server/src/core_api/handlers/lts/stream_account_transaction_outcomes.rs +++ b/core-rust/core-api-server/src/core_api/handlers/lts/stream_account_transaction_outcomes.rs @@ -1,9 +1,4 @@ -use crate::core_api::*; -use state_manager::store::traits::{ - extensions::IterableAccountChangeIndex, ConfigurableDatabase, QueryableProofStore, - QueryableTransactionStore, -}; -use std::ops::Deref; +use crate::prelude::*; #[tracing::instrument(skip(state))] pub(crate) async fn handle_lts_stream_account_transaction_outcomes( diff --git a/core-rust/core-api-server/src/core_api/handlers/lts/stream_transaction_outcomes.rs b/core-rust/core-api-server/src/core_api/handlers/lts/stream_transaction_outcomes.rs index 8a8f717d73..5b69338520 100644 --- a/core-rust/core-api-server/src/core_api/handlers/lts/stream_transaction_outcomes.rs +++ b/core-rust/core-api-server/src/core_api/handlers/lts/stream_transaction_outcomes.rs @@ -1,8 +1,4 @@ -use crate::core_api::*; -use state_manager::store::traits::{ - CommittedTransactionBundle, ConfigurableDatabase, IterableTransactionStore, QueryableProofStore, -}; -use std::ops::Deref; +use crate::prelude::*; #[tracing::instrument(skip(state))] pub(crate) async fn handle_lts_stream_transaction_outcomes( diff --git a/core-rust/core-api-server/src/core_api/handlers/lts/transaction_construction.rs b/core-rust/core-api-server/src/core_api/handlers/lts/transaction_construction.rs index d041f6662d..4374f5bce0 100644 --- a/core-rust/core-api-server/src/core_api/handlers/lts/transaction_construction.rs +++ b/core-rust/core-api-server/src/core_api/handlers/lts/transaction_construction.rs @@ -1,7 +1,4 @@ -use crate::core_api::*; -use crate::engine_prelude::*; - -use std::ops::Deref; +use crate::prelude::*; #[tracing::instrument(skip(state))] pub(crate) async fn handle_lts_transaction_construction( diff --git a/core-rust/core-api-server/src/core_api/handlers/lts/transaction_status.rs b/core-rust/core-api-server/src/core_api/handlers/lts/transaction_status.rs index b24e70e848..b8696cfc3f 100644 --- a/core-rust/core-api-server/src/core_api/handlers/lts/transaction_status.rs +++ b/core-rust/core-api-server/src/core_api/handlers/lts/transaction_status.rs @@ -1,15 +1,4 @@ -use std::collections::{HashMap, HashSet}; - -use crate::core_api::*; -use crate::engine_prelude::*; - -use state_manager::{ - AlreadyCommittedError, DetailedTransactionOutcome, MempoolRejectionReason, StateVersion, -}; - -use state_manager::mempool::pending_transaction_result_cache::PendingTransactionRecord; -use state_manager::query::StateManagerSubstateQueries; -use state_manager::store::traits::*; +use crate::prelude::*; #[tracing::instrument(skip(state))] pub(crate) async fn handle_lts_transaction_status( @@ -21,7 +10,7 @@ pub(crate) async fn handle_lts_transaction_status( let mapping_context = MappingContext::new_for_uncommitted_data(&state.network); let extraction_context = ExtractionContext::new(&state.network); - let intent_hash = extract_intent_hash(&extraction_context, request.intent_hash) + let intent_hash = extract_transaction_intent_hash(&extraction_context, request.intent_hash) .map_err(|err| err.into_response_error("intent_hash"))?; let pending_transaction_result_cache = @@ -57,11 +46,10 @@ pub(crate) async fn handle_lts_transaction_status( }); if let Some(txn_state_version) = txn_state_version_opt { - let identifiers = database + let hashes = database .get_committed_transaction_identifiers(txn_state_version) .expect("Txn identifiers are missing") - .payload - .typed; + .transaction_hashes; let local_detailed_outcome = database .get_committed_local_transaction_execution(txn_state_version) @@ -69,13 +57,13 @@ pub(crate) async fn handle_lts_transaction_status( .outcome; drop(database); - let user_identifiers = identifiers - .user() + let user_hashes = hashes + .as_user() .expect("Only user transactions should be able to be looked up by intent hash"); - let notarized_transaction_hash = user_identifiers.notarized_transaction_hash; + let notarized_transaction_hash = user_hashes.notarized_transaction_hash; // Remove the committed payload from the rejection list if it's present - known_pending_payloads.remove(notarized_transaction_hash); + known_pending_payloads.remove(¬arized_transaction_hash); let (intent_status, payload_status, outcome, error_message) = match local_detailed_outcome { DetailedTransactionOutcome::Success(_) => ( @@ -94,11 +82,11 @@ pub(crate) async fn handle_lts_transaction_status( let committed_payload = models::LtsTransactionPayloadDetails { payload_hash: to_api_notarized_transaction_hash( - user_identifiers.notarized_transaction_hash, + &user_hashes.notarized_transaction_hash, ), payload_hash_bech32m: to_api_hash_bech32m( &mapping_context, - user_identifiers.notarized_transaction_hash, + &user_hashes.notarized_transaction_hash, )?, state_version: Some(to_api_state_version(txn_state_version)?), status: payload_status, @@ -110,7 +98,7 @@ pub(crate) async fn handle_lts_transaction_status( &mapping_context, known_pending_payloads, txn_state_version, - notarized_transaction_hash, + ¬arized_transaction_hash, )?); return Ok(Json(models::LtsTransactionStatusResponse { diff --git a/core-rust/core-api-server/src/core_api/handlers/lts/transaction_submit.rs b/core-rust/core-api-server/src/core_api/handlers/lts/transaction_submit.rs index 03b90089e7..9fa815f502 100644 --- a/core-rust/core-api-server/src/core_api/handlers/lts/transaction_submit.rs +++ b/core-rust/core-api-server/src/core_api/handlers/lts/transaction_submit.rs @@ -1,10 +1,7 @@ -use crate::core_api::*; -use crate::engine_prelude::*; +use crate::prelude::*; use crate::core_api::handlers::to_api_committed_intent_metadata; -use hyper::StatusCode; use models::lts_transaction_submit_error_details::LtsTransactionSubmitErrorDetails; -use state_manager::{MempoolAddError, MempoolAddSource}; #[tracing::instrument(level = "debug", skip(state))] pub(crate) async fn handle_lts_transaction_submit( @@ -24,18 +21,21 @@ pub(crate) async fn handle_lts_transaction_submit( let result = state.state_manager.mempool_manager.add_and_trigger_relay( MempoolAddSource::CoreApi, - RawNotarizedTransaction(transaction_bytes), + RawNotarizedTransaction::from_vec(transaction_bytes), force_recalculate, ); match result { Ok(_) => Ok(models::LtsTransactionSubmitResponse::new(false)), - Err(MempoolAddError::PriorityThresholdNotMet { min_tip_percentage_required, tip_percentage }) => Err(detailed_error( + Err(MempoolAddError::PriorityThresholdNotMet { + min_tip_basis_points_required, + tip_basis_points, + }) => Err(detailed_error( StatusCode::BAD_REQUEST, "The mempool is full and the submitted transaction's priority is not sufficient to replace any existing transactions. Try submitting with a larger tip to increase the transaction's priority.", LtsTransactionSubmitErrorDetails::LtsTransactionSubmitPriorityThresholdNotMetErrorDetails { - tip_percentage: tip_percentage as i32, - min_tip_percentage_required: min_tip_percentage_required.map(|x| x as i32), + tip_percentage: TipSpecifier::BasisPoints(tip_basis_points).truncate_to_percentage_u32() as i32, // Dividing by 100 means this is inbounds + min_tip_percentage_required: min_tip_basis_points_required.map(|x| TipSpecifier::BasisPoints(x).truncate_to_percentage_u32() as i32), }, )), Err(MempoolAddError::Duplicate(_)) => Ok(models::LtsTransactionSubmitResponse::new(true)), @@ -63,19 +63,19 @@ pub(crate) async fn handle_lts_transaction_submit( is_intent_rejection_permanent: rejection.is_permanent_for_intent(), // TODO - Add `result_validity_substate_criteria` once track / mempool is improved retry_from_timestamp: match rejection.retry_from { - state_manager::RetryFrom::Never => None, - state_manager::RetryFrom::FromTime(time) => Some(Box::new( + RetryFrom::Never => None, + RetryFrom::FromTime(time) => Some(Box::new( to_api_clamped_instant_from_epoch_milli(to_unix_timestamp_ms(time)?)?, )), - state_manager::RetryFrom::FromEpoch(_) => None, - state_manager::RetryFrom::Whenever => { + RetryFrom::FromEpoch(_) => None, + RetryFrom::Whenever => { Some(Box::new(to_api_clamped_instant_from_epoch_milli( to_unix_timestamp_ms(std::time::SystemTime::now())?, )?)) } }, retry_from_epoch: match rejection.retry_from { - state_manager::RetryFrom::FromEpoch(epoch) => { + RetryFrom::FromEpoch(epoch) => { Some(to_api_epoch(&mapping_context, epoch)?) } _ => None, diff --git a/core-rust/core-api-server/src/core_api/handlers/mempool_list.rs b/core-rust/core-api-server/src/core_api/handlers/mempool_list.rs index f3906273fa..cac9797976 100644 --- a/core-rust/core-api-server/src/core_api/handlers/mempool_list.rs +++ b/core-rust/core-api-server/src/core_api/handlers/mempool_list.rs @@ -1,4 +1,4 @@ -use crate::core_api::*; +use crate::prelude::*; #[tracing::instrument(level = "debug", skip(state))] pub(crate) async fn handle_mempool_list( @@ -15,7 +15,7 @@ pub(crate) async fn handle_mempool_list( .all_hashes_iter() .map(|(intent_hash, payload_hash)| { Ok(models::MempoolTransactionHashes { - intent_hash: to_api_intent_hash(intent_hash), + intent_hash: to_api_transaction_intent_hash(intent_hash), intent_hash_bech32m: to_api_hash_bech32m(&mapping_context, intent_hash)?, payload_hash: to_api_notarized_transaction_hash(payload_hash), payload_hash_bech32m: to_api_hash_bech32m(&mapping_context, payload_hash)?, diff --git a/core-rust/core-api-server/src/core_api/handlers/mempool_transaction.rs b/core-rust/core-api-server/src/core_api/handlers/mempool_transaction.rs index d792e36c3a..99f88a572e 100644 --- a/core-rust/core-api-server/src/core_api/handlers/mempool_transaction.rs +++ b/core-rust/core-api-server/src/core_api/handlers/mempool_transaction.rs @@ -1,4 +1,4 @@ -use crate::core_api::*; +use crate::prelude::*; pub(crate) async fn handle_mempool_transaction( state: State, @@ -29,7 +29,9 @@ pub(crate) async fn handle_mempool_transaction( .map_err(|err| err.into_response_error("payload_hashes"))?; let (hex, error) = match mempool.get_payload(&payload_hash) { - Some(mempool_transaction) => (Some(hex::encode(&mempool_transaction.raw.0)), None), + Some(mempool_transaction) => { + (Some(hex::encode(mempool_transaction.raw.as_slice())), None) + } None => (None, Some("Payload hash not found in mempool".into())), }; diff --git a/core-rust/core-api-server/src/core_api/handlers/state_access_controller.rs b/core-rust/core-api-server/src/core_api/handlers/state_access_controller.rs index 9578767aca..4e92b42256 100644 --- a/core-rust/core-api-server/src/core_api/handlers/state_access_controller.rs +++ b/core-rust/core-api-server/src/core_api/handlers/state_access_controller.rs @@ -1,10 +1,4 @@ -use crate::core_api::*; - -use crate::engine_prelude::*; - -use state_manager::query::dump_component_state; - -use std::ops::Deref; +use crate::prelude::*; use super::component_dump_to_vaults_and_nodes; diff --git a/core-rust/core-api-server/src/core_api/handlers/state_account.rs b/core-rust/core-api-server/src/core_api/handlers/state_account.rs index 9ae362b687..e19ff39c6a 100644 --- a/core-rust/core-api-server/src/core_api/handlers/state_account.rs +++ b/core-rust/core-api-server/src/core_api/handlers/state_account.rs @@ -1,10 +1,7 @@ -use crate::core_api::*; -use crate::engine_prelude::*; +use crate::prelude::*; use state_manager::query::{dump_component_state, VaultData}; -use std::ops::Deref; - pub(crate) async fn handle_state_account( state: State, Json(request): Json, diff --git a/core-rust/core-api-server/src/core_api/handlers/state_component.rs b/core-rust/core-api-server/src/core_api/handlers/state_component.rs index ac5e98575c..2ee2489a5f 100644 --- a/core-rust/core-api-server/src/core_api/handlers/state_component.rs +++ b/core-rust/core-api-server/src/core_api/handlers/state_component.rs @@ -1,9 +1,4 @@ -use crate::core_api::*; -use crate::engine_prelude::*; - -use state_manager::query::{dump_component_state, ComponentStateDump, DescendantParentOpt}; - -use std::ops::Deref; +use crate::prelude::*; use super::map_to_vault_balance; diff --git a/core-rust/core-api-server/src/core_api/handlers/state_consensus_manager.rs b/core-rust/core-api-server/src/core_api/handlers/state_consensus_manager.rs index e040ea8fde..7fbe698ba6 100644 --- a/core-rust/core-api-server/src/core_api/handlers/state_consensus_manager.rs +++ b/core-rust/core-api-server/src/core_api/handlers/state_consensus_manager.rs @@ -1,10 +1,4 @@ -use crate::core_api::*; -use crate::engine_prelude::*; - -use node_common::store::rocks_db::ReadableRocks; -use state_manager::protocol::ProtocolVersionName; -use state_manager::store::rocks_db::StateManagerDatabase; -use std::ops::Deref; +use crate::prelude::*; #[tracing::instrument(skip(state))] pub(crate) async fn handle_state_consensus_manager( diff --git a/core-rust/core-api-server/src/core_api/handlers/state_non_fungible.rs b/core-rust/core-api-server/src/core_api/handlers/state_non_fungible.rs index 7cbd9d7066..759ca3faaf 100644 --- a/core-rust/core-api-server/src/core_api/handlers/state_non_fungible.rs +++ b/core-rust/core-api-server/src/core_api/handlers/state_non_fungible.rs @@ -1,8 +1,4 @@ -use crate::engine_prelude::*; - -use std::ops::Deref; - -use crate::core_api::*; +use crate::prelude::*; use crate::core_api::models::StateNonFungibleResponse; diff --git a/core-rust/core-api-server/src/core_api/handlers/state_package.rs b/core-rust/core-api-server/src/core_api/handlers/state_package.rs index fca7895ad2..8c8c2dedd1 100644 --- a/core-rust/core-api-server/src/core_api/handlers/state_package.rs +++ b/core-rust/core-api-server/src/core_api/handlers/state_package.rs @@ -1,7 +1,4 @@ -use crate::core_api::*; -use crate::engine_prelude::*; - -use std::ops::Deref; +use crate::prelude::*; pub(crate) async fn handle_state_package( state: State, diff --git a/core-rust/core-api-server/src/core_api/handlers/state_resource.rs b/core-rust/core-api-server/src/core_api/handlers/state_resource.rs index d6a814ce0c..d7dbc19689 100644 --- a/core-rust/core-api-server/src/core_api/handlers/state_resource.rs +++ b/core-rust/core-api-server/src/core_api/handlers/state_resource.rs @@ -1,7 +1,4 @@ -use crate::core_api::*; -use crate::engine_prelude::*; - -use std::ops::Deref; +use crate::prelude::*; enum ManagerByType { Fungible( diff --git a/core-rust/core-api-server/src/core_api/handlers/state_validator.rs b/core-rust/core-api-server/src/core_api/handlers/state_validator.rs index 8159035156..10069658af 100644 --- a/core-rust/core-api-server/src/core_api/handlers/state_validator.rs +++ b/core-rust/core-api-server/src/core_api/handlers/state_validator.rs @@ -1,11 +1,5 @@ -use crate::core_api::*; -use crate::engine_prelude::*; - -use state_manager::query::dump_component_state; - -use std::ops::Deref; - use super::component_dump_to_vaults_and_nodes; +use crate::prelude::*; pub(crate) async fn handle_state_validator( state: State, diff --git a/core-rust/core-api-server/src/core_api/handlers/status_network_configuration.rs b/core-rust/core-api-server/src/core_api/handlers/status_network_configuration.rs index abce3f98fb..234c17f1c7 100644 --- a/core-rust/core-api-server/src/core_api/handlers/status_network_configuration.rs +++ b/core-rust/core-api-server/src/core_api/handlers/status_network_configuration.rs @@ -1,5 +1,4 @@ -use crate::core_api::*; -use crate::engine_prelude::*; +use crate::prelude::*; #[tracing::instrument(skip(state))] pub(crate) async fn handle_status_network_configuration( @@ -20,27 +19,27 @@ pub(crate) async fn handle_status_network_configuration( core_version: env!("CARGO_PKG_VERSION").to_string(), api_version: models::SCHEMA_VERSION.to_string(), }), - network: network.logical_name, + network: network.logical_name.into_owned(), network_id: to_api_u8_as_i32(network.id), - network_hrp_suffix: network.hrp_suffix, + network_hrp_suffix: network.hrp_suffix.into_owned(), usd_price_in_xrd: to_api_decimal(&Decimal::try_from(USD_PRICE_IN_XRD).unwrap()), address_types, well_known_addresses: Box::new(models::NetworkConfigurationResponseWellKnownAddresses { xrd: bech32_encoder.encode(XRD.as_ref()).unwrap(), secp256k1_signature_virtual_badge: bech32_encoder - .encode(SECP256K1_SIGNATURE_VIRTUAL_BADGE.as_ref()) + .encode(SECP256K1_SIGNATURE_RESOURCE.as_ref()) .unwrap(), ed25519_signature_virtual_badge: bech32_encoder - .encode(ED25519_SIGNATURE_VIRTUAL_BADGE.as_ref()) + .encode(ED25519_SIGNATURE_RESOURCE.as_ref()) .unwrap(), package_of_direct_caller_virtual_badge: bech32_encoder - .encode(PACKAGE_OF_DIRECT_CALLER_VIRTUAL_BADGE.as_ref()) + .encode(PACKAGE_OF_DIRECT_CALLER_RESOURCE.as_ref()) .unwrap(), global_caller_virtual_badge: bech32_encoder - .encode(GLOBAL_CALLER_VIRTUAL_BADGE.as_ref()) + .encode(GLOBAL_CALLER_RESOURCE.as_ref()) .unwrap(), system_transaction_badge: bech32_encoder - .encode(SYSTEM_TRANSACTION_BADGE.as_ref()) + .encode(SYSTEM_EXECUTION_RESOURCE.as_ref()) .unwrap(), package_owner_badge: bech32_encoder.encode(PACKAGE_OWNER_BADGE.as_ref()).unwrap(), validator_owner_badge: bech32_encoder diff --git a/core-rust/core-api-server/src/core_api/handlers/status_network_status.rs b/core-rust/core-api-server/src/core_api/handlers/status_network_status.rs index 418f118713..a7ea4fa90a 100644 --- a/core-rust/core-api-server/src/core_api/handlers/status_network_status.rs +++ b/core-rust/core-api-server/src/core_api/handlers/status_network_status.rs @@ -1,10 +1,4 @@ -use crate::core_api::*; - -use crate::engine_prelude::*; - -use state_manager::query::TransactionIdentifierLoader; -use state_manager::store::traits::*; -use state_manager::{LedgerHashes, LedgerProof, LedgerStateSummary, StateVersion}; +use crate::prelude::*; #[tracing::instrument(skip(state))] pub(crate) async fn handle_status_network_status( diff --git a/core-rust/core-api-server/src/core_api/handlers/status_scenarios.rs b/core-rust/core-api-server/src/core_api/handlers/status_scenarios.rs index 7227fabcd9..c3cd32d4f8 100644 --- a/core-rust/core-api-server/src/core_api/handlers/status_scenarios.rs +++ b/core-rust/core-api-server/src/core_api/handlers/status_scenarios.rs @@ -1,10 +1,4 @@ -use crate::core_api::*; - -use crate::engine_prelude::*; - -use state_manager::store::traits::scenario::{ - ExecutedScenario, ExecutedScenarioStore, ExecutedScenarioTransaction, ScenarioSequenceNumber, -}; +use crate::prelude::*; #[tracing::instrument(skip(state))] pub(crate) async fn handle_status_scenarios( @@ -58,7 +52,7 @@ pub fn to_api_scenario_transaction( Ok(models::ExecutedScenarioTransaction { logical_name: transaction.logical_name.clone(), state_version: to_api_state_version(transaction.state_version)?, - intent_hash: to_api_intent_hash(&transaction.intent_hash), - intent_hash_bech32m: to_api_hash_bech32m(context, &transaction.intent_hash)?, + intent_hash: to_api_transaction_intent_hash(&transaction.transaction_intent_hash), + intent_hash_bech32m: to_api_hash_bech32m(context, &transaction.transaction_intent_hash)?, }) } diff --git a/core-rust/core-api-server/src/core_api/handlers/stream_proofs.rs b/core-rust/core-api-server/src/core_api/handlers/stream_proofs.rs index a3565061b3..d1e77d9a61 100644 --- a/core-rust/core-api-server/src/core_api/handlers/stream_proofs.rs +++ b/core-rust/core-api-server/src/core_api/handlers/stream_proofs.rs @@ -1,10 +1,5 @@ -use crate::core_api::*; - -use crate::engine_prelude::*; -use node_common::store::rocks_db::ReadableRocks; -use state_manager::store::rocks_db::StateManagerDatabase; -use state_manager::store::traits::*; -use state_manager::{LedgerProof, LedgerProofOrigin, StateVersion}; +use crate::core_api::handlers::to_api_ledger_proof; +use crate::prelude::*; #[tracing::instrument(skip(state))] pub(crate) async fn handle_stream_proofs( @@ -67,7 +62,7 @@ pub(crate) async fn handle_stream_proofs( let (page, continuation_token) = to_api_page( &mut proofs_iter, page_size, - |proof| handlers::to_api_ledger_proof(&mapping_context, proof), + |proof| to_api_ledger_proof(&mapping_context, proof), |proof| proof.ledger_header.state_version, )?; diff --git a/core-rust/core-api-server/src/core_api/handlers/stream_transactions.rs b/core-rust/core-api-server/src/core_api/handlers/stream_transactions.rs index 8a5caabefa..5dfa06c679 100644 --- a/core-rust/core-api-server/src/core_api/handlers/stream_transactions.rs +++ b/core-rust/core-api-server/src/core_api/handlers/stream_transactions.rs @@ -1,18 +1,4 @@ -use crate::engine_prelude::*; - -use std::iter; -use std::ops::Deref; - -use crate::core_api::*; - -use node_common::store::rocks_db::ReadableRocks; -use state_manager::store::rocks_db::StateManagerDatabase; -use state_manager::store::traits::*; -use state_manager::transaction::*; -use state_manager::{ - CommittedTransactionIdentifiers, LedgerHeader, LedgerProof, LedgerProofOrigin, - LocalTransactionReceipt, StateVersion, -}; +use crate::prelude::*; use super::to_api_committed_state_identifiers; @@ -102,7 +88,7 @@ pub(crate) async fn handle_stream_transactions( let proofs_iter = if request.include_proofs.is_some_and(|value| value) { database.get_proof_iter(from_state_version) } else { - Box::new(iter::empty()) + Box::new(core::iter::empty()) }; let transactions_and_proofs_iter = TransactionAndProofIterator::new(bundles_iter, proofs_iter); for (bundle, maybe_proof) in transactions_and_proofs_iter.take(limit) { @@ -203,10 +189,10 @@ pub fn to_api_ledger_proof( } LedgerProofOrigin::ProtocolUpdate { protocol_version_name, - batch_idx, + batch_index, } => models::LedgerProofOrigin::ProtocolUpdateLedgerProofOrigin { protocol_version_name: protocol_version_name.to_string(), - batch_idx: to_api_u32_as_i64(*batch_idx), + batch_idx: to_api_u32_as_i64(*batch_index), }, }; Ok(models::LedgerProof { @@ -298,7 +284,7 @@ pub fn to_api_committed_transaction( context, &raw_ledger_transaction, &ledger_transaction, - &identifiers.payload, + &identifiers.transaction_hashes, )?), receipt: Box::new(to_api_receipt(Some(database), context, receipt)?), balance_changes, @@ -310,33 +296,33 @@ pub fn to_api_ledger_transaction( context: &MappingContext, raw_ledger_transaction: &RawLedgerTransaction, ledger_transaction: &LedgerTransaction, - payload_identifiers: &PayloadIdentifiers, + hashes: &LedgerTransactionHashes, ) -> Result { let payload_hex = if context.transaction_options.include_raw_ledger { - Some(to_hex(&raw_ledger_transaction.0)) + Some(to_hex(raw_ledger_transaction.as_slice())) } else { None }; Ok(match ledger_transaction { LedgerTransaction::UserV1(tx) => { - let user_identifiers = payload_identifiers.typed.user().ok_or_else(|| { - MappingError::MismatchedTransactionIdentifiers { - message: "Transaction hashes for notarized transaction were not user" - .to_string(), - } - })?; + let user_hashes = + hashes + .as_user() + .ok_or_else(|| MappingError::MismatchedTransactionIdentifiers { + message: "Transaction hashes for notarized transaction were not user" + .to_string(), + })?; models::LedgerTransaction::UserLedgerTransaction { payload_hex, notarized_transaction: Box::new(to_api_notarized_transaction( context, tx, - user_identifiers.intent_hash, - user_identifiers.signed_intent_hash, - user_identifiers.notarized_transaction_hash, + &user_hashes, )?), } } + LedgerTransaction::UserV2(..) => todo!(), LedgerTransaction::RoundUpdateV1(tx) => { models::LedgerTransaction::RoundUpdateLedgerTransaction { payload_hex, @@ -372,30 +358,31 @@ pub fn to_api_ledger_transaction( pub fn to_api_notarized_transaction( context: &MappingContext, notarized: &NotarizedTransactionV1, - intent_hash: &IntentHash, - signed_intent_hash: &SignedIntentHash, - notarized_transaction_hash: &NotarizedTransactionHash, + user_hashes: &UserTransactionHashes, ) -> Result { let payload_hex = if context.transaction_options.include_raw_notarized { - Some(to_hex(notarized.to_payload_bytes().map_err(|err| { - MappingError::SborEncodeError { - encode_error: err, - message: "Error encoding user payload sbor".to_string(), - } - })?)) + Some(to_hex( + notarized + .to_raw() + .map_err(|err| MappingError::SborEncodeError { + encode_error: err, + message: "Error encoding user payload sbor".to_string(), + })? + .as_slice(), + )) } else { None }; Ok(models::NotarizedTransaction { - hash: to_api_notarized_transaction_hash(notarized_transaction_hash), - hash_bech32m: to_api_hash_bech32m(context, notarized_transaction_hash)?, + hash: to_api_notarized_transaction_hash(&user_hashes.notarized_transaction_hash), + hash_bech32m: to_api_hash_bech32m(context, &user_hashes.notarized_transaction_hash)?, payload_hex, signed_intent: Box::new(to_api_signed_intent( context, ¬arized.signed_intent, - intent_hash, - signed_intent_hash, + &user_hashes.transaction_intent_hash, + &user_hashes.signed_transaction_intent_hash, )?), notary_signature: Some(to_api_signature(¬arized.notary_signature.0)), }) @@ -405,13 +392,17 @@ pub fn to_api_notarized_transaction( pub fn to_api_signed_intent( context: &MappingContext, signed_intent: &SignedIntentV1, - intent_hash: &IntentHash, - signed_intent_hash: &SignedIntentHash, + transaction_intent_hash: &TransactionIntentHash, + signed_transaction_intent_hash: &SignedTransactionIntentHash, ) -> Result { Ok(models::SignedTransactionIntent { - hash: to_api_signed_intent_hash(signed_intent_hash), - hash_bech32m: to_api_hash_bech32m(context, signed_intent_hash)?, - intent: Box::new(to_api_intent(context, &signed_intent.intent, intent_hash)?), + hash: to_api_signed_transaction_intent_hash(signed_transaction_intent_hash), + hash_bech32m: to_api_hash_bech32m(context, signed_transaction_intent_hash)?, + intent: Box::new(to_api_intent_v1( + context, + &signed_intent.intent, + transaction_intent_hash, + )?), intent_signatures: signed_intent .intent_signatures .signatures @@ -422,16 +413,29 @@ pub fn to_api_signed_intent( } #[tracing::instrument(skip_all)] -pub fn to_api_intent( +pub fn to_api_intent_v1( context: &MappingContext, intent: &IntentV1, - intent_hash: &IntentHash, + transaction_intent_hash: &TransactionIntentHash, ) -> Result { + let instructions = if context.transaction_options.include_manifest { + let readable_manifest = TransactionManifestV1::from_intent(intent); + Some( + manifest::decompile(&readable_manifest, &context.network_definition).map_err( + |err| MappingError::InvalidManifest { + message: format!("Failed to decompile a transaction manifest: {err:?}"), + }, + )?, + ) + } else { + None + }; + let IntentV1 { header, - instructions, blobs, message, + .. } = intent; let header = Box::new(models::TransactionHeader { @@ -444,21 +448,6 @@ pub fn to_api_intent( tip_percentage: to_api_u16_as_i32(header.tip_percentage), }); - let instructions = if context.transaction_options.include_manifest { - Some( - manifest::decompile(&instructions.0, &context.network_definition).map_err(|err| { - MappingError::InvalidManifest { - message: format!( - "Failed to decompile a transaction manifest: {err:?}, instructions: {:?}", - &instructions - ), - } - })?, - ) - } else { - None - }; - let blobs_hex = if context.transaction_options.include_blobs { Some( blobs @@ -483,8 +472,8 @@ pub fn to_api_intent( }; Ok(models::TransactionIntent { - hash: to_api_intent_hash(intent_hash), - hash_bech32m: to_api_hash_bech32m(context, intent_hash)?, + hash: to_api_transaction_intent_hash(transaction_intent_hash), + hash_bech32m: to_api_hash_bech32m(context, transaction_intent_hash)?, header, instructions, blobs_hex, @@ -608,12 +597,15 @@ pub fn to_api_system_transaction( system_transaction: &SystemTransactionV1, ) -> Result { let payload_hex = if context.transaction_options.include_raw_system { - Some(to_hex(system_transaction.to_payload_bytes().map_err( - |err| MappingError::SborEncodeError { - encode_error: err, - message: "Error encoding system transaction sbor".to_string(), - }, - )?)) + Some(to_hex( + system_transaction + .to_raw() + .map_err(|err| MappingError::SborEncodeError { + encode_error: err, + message: "Error encoding system transaction sbor".to_string(), + })? + .as_slice(), + )) } else { None }; diff --git a/core-rust/core-api-server/src/core_api/handlers/transaction_callpreview.rs b/core-rust/core-api-server/src/core_api/handlers/transaction_callpreview.rs index ee746ddc1e..a8a89f8dba 100644 --- a/core-rust/core-api-server/src/core_api/handlers/transaction_callpreview.rs +++ b/core-rust/core-api-server/src/core_api/handlers/transaction_callpreview.rs @@ -1,7 +1,4 @@ -use crate::core_api::*; -use crate::engine_prelude::*; - -use state_manager::PreviewRequest; +use crate::prelude::*; macro_rules! args_from_bytes_vec { ($args: expr) => {{ @@ -49,12 +46,12 @@ pub(crate) async fn handle_transaction_callpreview( extract_package_address(&extraction_context, package_address.as_str()) .map_err(|err| err.into_response_error("target.package_address"))?; - InstructionV1::CallFunction { + InstructionV1::CallFunction(CallFunction { blueprint_name, function_name, package_address: package_address.into(), args: args_from_bytes_vec!(args), - } + }) } models::TargetIdentifier::ComponentMethodTargetIdentifier { component_address, @@ -64,11 +61,11 @@ pub(crate) async fn handle_transaction_callpreview( extract_component_address(&extraction_context, component_address.as_str()) .map_err(|err| err.into_response_error("target.component_address"))?; - InstructionV1::CallMethod { + InstructionV1::CallMethod(CallMethod { address: component_address.into(), method_name, args: args_from_bytes_vec!(args), - } + }) } }; @@ -77,6 +74,7 @@ pub(crate) async fn handle_transaction_callpreview( manifest: TransactionManifestV1 { instructions: vec![requested_call], blobs: index_map_new(), + object_names: Default::default(), }, start_epoch_inclusive: None, end_epoch_exclusive: None, diff --git a/core-rust/core-api-server/src/core_api/handlers/transaction_parse.rs b/core-rust/core-api-server/src/core_api/handlers/transaction_parse.rs index 6c6d0b599f..23123577d2 100644 --- a/core-rust/core-api-server/src/core_api/handlers/transaction_parse.rs +++ b/core-rust/core-api-server/src/core_api/handlers/transaction_parse.rs @@ -1,25 +1,17 @@ -use crate::core_api::*; -use std::ops::Deref; -use std::time::SystemTime; +use crate::prelude::*; use models::transaction_parse_request::{ParseMode, ResponseMode, ValidationMode}; use models::transaction_parse_response::TransactionParseResponse; -use state_manager::mempool::pending_transaction_result_cache::MempoolRejectionReason; - -use state_manager::transaction::*; - -use crate::engine_prelude::*; - use super::{ - to_api_intent, to_api_ledger_transaction, to_api_notarized_transaction, to_api_signed_intent, + to_api_intent_v1, to_api_ledger_transaction, to_api_notarized_transaction, to_api_signed_intent, }; pub struct ParseContext<'a> { mapping_context: MappingContext, response_mode: ResponseMode, validation_mode: ValidationMode, - user_transaction_validator: NotarizedTransactionValidator, + transaction_validator: TransactionValidator, committability_validator: &'a CommittabilityValidator, } @@ -38,9 +30,7 @@ pub(crate) async fn handle_transaction_parse( .with_transaction_formats(&request.transaction_format_options), response_mode: request.response_mode.unwrap_or(ResponseMode::Full), validation_mode: request.validation_mode.unwrap_or(ValidationMode::_Static), - user_transaction_validator: NotarizedTransactionValidator::new(ValidationConfig::default( - state.network.id, - )), + transaction_validator: *state.state_manager.transaction_validator.read(), committability_validator: read_commitability_validator.deref(), }; @@ -54,17 +44,17 @@ pub(crate) async fn handle_transaction_parse( to_api_parsed_notarized_transaction(&context, parsed)? } ParseMode::Signed => { - let parsed = attempt_parsing_as_signed_intent(&bytes) + let parsed = attempt_parsing_as_signed_intent(&context, &bytes) .ok_or_else(|| client_error("The payload isn't a signed transaction intent"))?; to_api_parsed_signed_intent(&context, parsed)? } ParseMode::Unsigned => { - let parsed = attempt_parsing_as_intent(&bytes) + let parsed = attempt_parsing_as_intent(&context, &bytes) .ok_or_else(|| client_error("The payload isn't an unsigned transaction intent"))?; to_api_parsed_intent(&context, parsed)? } ParseMode::Ledger => { - let parsed = attempt_parsing_as_ledger_transaction(&bytes) + let parsed = attempt_parsing_as_ledger_transaction(&context, &bytes) .ok_or_else(|| client_error("The payload isn't a ledger transaction"))?; to_api_parsed_ledger_transaction(&context, parsed)? } @@ -87,21 +77,21 @@ fn attempt_parsing_as_any_payload_type_and_map_for_api( } // Attempt 2 - Try parsing as SignedTransactionIntent - let signed_intent_parse_option = attempt_parsing_as_signed_intent(bytes); + let signed_intent_parse_option = attempt_parsing_as_signed_intent(context, bytes); if let Some(parsed) = signed_intent_parse_option { return to_api_parsed_signed_intent(context, parsed); } // Attempt 3 - Try parsing as (unsigned) TransactionIntent - let intent_parse_option = attempt_parsing_as_intent(bytes); + let intent_parse_option = attempt_parsing_as_intent(context, bytes); if let Some(parsed) = intent_parse_option { return to_api_parsed_intent(context, parsed); } // Attempt 4 - Try parsing as a ledger transaction payload - let ledger_parse_option = attempt_parsing_as_ledger_transaction(bytes); + let ledger_parse_option = attempt_parsing_as_ledger_transaction(context, bytes); if let Some(parsed) = ledger_parse_option { return to_api_parsed_ledger_transaction(context, parsed); @@ -112,6 +102,7 @@ fn attempt_parsing_as_any_payload_type_and_map_for_api( struct ParsedNotarizedTransactionV1 { model: NotarizedTransactionV1, + hashes: UserTransactionHashes, prepared: PreparedNotarizedTransactionV1, validation: Option>, } @@ -120,48 +111,56 @@ fn attempt_parsing_as_notarized_transaction( context: &ParseContext, bytes: &[u8], ) -> Option { - let prepare_result = context - .user_transaction_validator - .prepare_from_payload_bytes(bytes); - let prepared = match prepare_result { - Ok(prepared) => prepared, - Err(_) => return None, - }; - let model: NotarizedTransactionV1 = match NotarizedTransactionV1::from_payload_bytes(bytes) { - Ok(model) => model, - Err(_) => return None, + let raw = RawNotarizedTransaction::from_slice(bytes); + let prepared = raw + .prepare(context.transaction_validator.preparation_settings()) + .ok()?; + + let hashes = prepared.hashes(); + + let prepared = match prepared { + PreparedUserTransaction::V1(prepared) => prepared, + PreparedUserTransaction::V2(_) => todo!(), }; + let model = NotarizedTransactionV1::from_raw(&raw).ok()?; + Some(match context.validation_mode { ValidationMode::None => ParsedNotarizedTransactionV1 { model, + hashes, prepared, validation: None, }, ValidationMode::_Static => { let validation = Some( - context - .user_transaction_validator - .validate(prepared.clone()) + prepared + .clone() + .validate(&context.transaction_validator) .map(|_| ()) .map_err(MempoolRejectionReason::ValidationError), ); ParsedNotarizedTransactionV1 { model, + hashes, prepared, validation, } } ValidationMode::Full => { let validation = Some({ - context - .user_transaction_validator - .validate(prepared.clone()) + prepared + .clone() + .validate(&context.transaction_validator) .map_err(MempoolRejectionReason::ValidationError) .and_then(|validated| { let rejection = context .committability_validator - .check_for_rejection(&validated, SystemTime::now()) + .check_for_rejection( + &validated.create_executable(), + &hashes, + SystemTime::now(), + ) .rejection; match rejection { Some(rejection) => Err(rejection), @@ -171,6 +170,7 @@ fn attempt_parsing_as_notarized_transaction( }); ParsedNotarizedTransactionV1 { model, + hashes, prepared, validation, } @@ -182,18 +182,12 @@ fn to_api_parsed_notarized_transaction( context: &ParseContext, parsed: ParsedNotarizedTransactionV1, ) -> Result> { - let intent_hash = parsed.prepared.intent_hash(); - let signed_intent_hash = parsed.prepared.signed_intent_hash(); - let notarized_transaction_hash = parsed.prepared.notarized_transaction_hash(); - let model = match context.response_mode { ResponseMode::Basic => None, ResponseMode::Full => Some(Box::new(to_api_notarized_transaction( &context.mapping_context, &parsed.model, - &intent_hash, - &signed_intent_hash, - ¬arized_transaction_hash, + &parsed.hashes, )?)), }; @@ -208,22 +202,30 @@ fn to_api_parsed_notarized_transaction( }); let ledger_hash = - PreparedLedgerTransactionInner::UserV1(Box::new(parsed.prepared)).get_ledger_hash(); + PreparedLedgerTransactionInner::User(PreparedUserTransaction::V1(parsed.prepared)) + .get_ledger_hash(); Ok(models::ParsedTransaction::ParsedNotarizedTransaction { notarized_transaction: model, identifiers: Box::new(models::ParsedNotarizedTransactionIdentifiers { - intent_hash: to_api_intent_hash(&intent_hash), - intent_hash_bech32m: to_api_hash_bech32m(&context.mapping_context, &intent_hash)?, - signed_intent_hash: to_api_signed_intent_hash(&signed_intent_hash), + intent_hash: to_api_transaction_intent_hash(&parsed.hashes.transaction_intent_hash), + intent_hash_bech32m: to_api_hash_bech32m( + &context.mapping_context, + &parsed.hashes.transaction_intent_hash, + )?, + signed_intent_hash: to_api_signed_transaction_intent_hash( + &parsed.hashes.signed_transaction_intent_hash, + ), signed_intent_hash_bech32m: to_api_hash_bech32m( &context.mapping_context, - &signed_intent_hash, + &parsed.hashes.signed_transaction_intent_hash, )?, - payload_hash: to_api_notarized_transaction_hash(¬arized_transaction_hash), + payload_hash: to_api_notarized_transaction_hash( + &parsed.hashes.notarized_transaction_hash, + ), payload_hash_bech32m: to_api_hash_bech32m( &context.mapping_context, - ¬arized_transaction_hash, + &parsed.hashes.notarized_transaction_hash, )?, ledger_hash: to_api_ledger_hash(&ledger_hash), ledger_hash_bech32m: to_api_hash_bech32m(&context.mapping_context, &ledger_hash)?, @@ -233,10 +235,14 @@ fn to_api_parsed_notarized_transaction( } fn attempt_parsing_as_signed_intent( + context: &ParseContext, bytes: &[u8], ) -> Option<(SignedIntentV1, PreparedSignedIntentV1)> { - let signed_intent = SignedIntentV1::from_payload_bytes(bytes).ok()?; - let prepared = PreparedSignedIntentV1::prepare_from_payload(bytes).ok()?; + let raw = RawSignedTransactionIntent::from_slice(bytes); + let signed_intent = SignedIntentV1::from_raw(&raw).ok()?; + let prepared = + PreparedSignedIntentV1::prepare(&raw, context.transaction_validator.preparation_settings()) + .ok()?; Some((signed_intent, prepared)) } @@ -249,30 +255,38 @@ fn to_api_parsed_signed_intent( ResponseMode::Full => Some(Box::new(to_api_signed_intent( &context.mapping_context, &model, - &prepared.intent_hash(), - &prepared.signed_intent_hash(), + &prepared.transaction_intent_hash(), + &prepared.signed_transaction_intent_hash(), )?)), }; Ok(models::ParsedTransaction::ParsedSignedTransactionIntent { signed_intent: model, identifiers: Box::new(models::ParsedSignedTransactionIntentIdentifiers { - intent_hash: to_api_intent_hash(&prepared.intent_hash()), + intent_hash: to_api_transaction_intent_hash(&prepared.transaction_intent_hash()), intent_hash_bech32m: to_api_hash_bech32m( &context.mapping_context, - &prepared.intent_hash(), + &prepared.transaction_intent_hash(), )?, - signed_intent_hash: to_api_signed_intent_hash(&prepared.signed_intent_hash()), + signed_intent_hash: to_api_signed_transaction_intent_hash( + &prepared.signed_transaction_intent_hash(), + ), signed_intent_hash_bech32m: to_api_hash_bech32m( &context.mapping_context, - &prepared.signed_intent_hash(), + &prepared.signed_transaction_intent_hash(), )?, }), }) } -fn attempt_parsing_as_intent(bytes: &[u8]) -> Option<(IntentV1, PreparedIntentV1)> { - let model = IntentV1::from_payload_bytes(bytes).ok()?; - let prepared = PreparedIntentV1::prepare_from_payload(bytes).ok()?; +fn attempt_parsing_as_intent( + context: &ParseContext, + bytes: &[u8], +) -> Option<(IntentV1, PreparedIntentV1)> { + let raw = RawTransactionIntent::from_slice(bytes); + let model = IntentV1::from_raw(&raw).ok()?; + let prepared = + PreparedIntentV1::prepare(&raw, context.transaction_validator.preparation_settings()) + .ok()?; Some((model, prepared)) } @@ -280,10 +294,10 @@ fn to_api_parsed_intent( context: &ParseContext, (model, prepared): (IntentV1, PreparedIntentV1), ) -> Result> { - let intent_hash = &prepared.intent_hash(); + let intent_hash = &prepared.transaction_intent_hash(); let model = match context.response_mode { ResponseMode::Basic => None, - ResponseMode::Full => Some(Box::new(to_api_intent( + ResponseMode::Full => Some(Box::new(to_api_intent_v1( &context.mapping_context, &model, intent_hash, @@ -292,22 +306,27 @@ fn to_api_parsed_intent( Ok(models::ParsedTransaction::ParsedTransactionIntent { intent: model, identifiers: Box::new(models::ParsedTransactionIntentIdentifiers { - intent_hash: to_api_intent_hash(intent_hash), + intent_hash: to_api_transaction_intent_hash(intent_hash), intent_hash_bech32m: to_api_hash_bech32m(&context.mapping_context, intent_hash)?, }), }) } fn attempt_parsing_as_ledger_transaction( + context: &ParseContext, bytes: &[u8], ) -> Option<( LedgerTransaction, PreparedLedgerTransaction, RawLedgerTransaction, )> { - let model = LedgerTransaction::from_payload_bytes(bytes).ok()?; - let prepared = PreparedLedgerTransaction::prepare_from_payload(bytes).ok()?; - let raw = RawLedgerTransaction(bytes.to_vec()); + let raw = RawLedgerTransaction::from_slice(bytes); + let model = LedgerTransaction::from_raw(&raw).ok()?; + let prepared = PreparedLedgerTransaction::prepare( + &raw, + context.transaction_validator.preparation_settings(), + ) + .ok()?; Some((model, prepared, raw)) } @@ -319,45 +338,53 @@ fn to_api_parsed_ledger_transaction( RawLedgerTransaction, ), ) -> Result> { - let identifiers = prepared.create_identifiers(); + let hashes = prepared.create_hashes(); let model = match context.response_mode { ResponseMode::Basic => None, ResponseMode::Full => Some(Box::new(to_api_ledger_transaction( &context.mapping_context, &raw, &model, - &identifiers, + &hashes, )?)), }; - let user_identifiers = identifiers.typed.user(); + let user_identifiers = hashes.as_user(); Ok(models::ParsedTransaction::ParsedLedgerTransaction { ledger_transaction: model, identifiers: Box::new(models::ParsedLedgerTransactionIdentifiers { intent_hash: user_identifiers .as_ref() - .map(|hashes| to_api_intent_hash(hashes.intent_hash)), + .map(|hashes| to_api_transaction_intent_hash(&hashes.transaction_intent_hash)), intent_hash_bech32m: user_identifiers .as_ref() - .map(|hashes| to_api_hash_bech32m(&context.mapping_context, hashes.intent_hash)) + .map(|hashes| { + to_api_hash_bech32m(&context.mapping_context, &hashes.transaction_intent_hash) + }) .transpose()?, - signed_intent_hash: user_identifiers - .as_ref() - .map(|hashes| to_api_signed_intent_hash(hashes.signed_intent_hash)), + signed_intent_hash: user_identifiers.as_ref().map(|hashes| { + to_api_signed_transaction_intent_hash(&hashes.signed_transaction_intent_hash) + }), signed_intent_hash_bech32m: user_identifiers .as_ref() .map(|hashes| { - to_api_hash_bech32m(&context.mapping_context, hashes.signed_intent_hash) + to_api_hash_bech32m( + &context.mapping_context, + &hashes.signed_transaction_intent_hash, + ) }) .transpose()?, - payload_hash: user_identifiers - .as_ref() - .map(|hashes| to_api_notarized_transaction_hash(hashes.notarized_transaction_hash)), + payload_hash: user_identifiers.as_ref().map(|hashes| { + to_api_notarized_transaction_hash(&hashes.notarized_transaction_hash) + }), payload_hash_bech32m: user_identifiers .as_ref() .map(|hashes| { - to_api_hash_bech32m(&context.mapping_context, hashes.notarized_transaction_hash) + to_api_hash_bech32m( + &context.mapping_context, + &hashes.notarized_transaction_hash, + ) }) .transpose()?, ledger_hash: to_api_ledger_hash(&prepared.ledger_transaction_hash()), diff --git a/core-rust/core-api-server/src/core_api/handlers/transaction_preview.rs b/core-rust/core-api-server/src/core_api/handlers/transaction_preview.rs index e6b2e23a19..4282747603 100644 --- a/core-rust/core-api-server/src/core_api/handlers/transaction_preview.rs +++ b/core-rust/core-api-server/src/core_api/handlers/transaction_preview.rs @@ -1,10 +1,5 @@ -use crate::core_api::*; -use crate::engine_prelude::*; - -use radix_engine_toolkit::receipt::RuntimeToolkitTransactionReceipt; -use state_manager::rocks_db::ActualStateManagerDatabase; -use state_manager::transaction::ProcessedPreviewResult; -use state_manager::{ExecutionFeeData, LocalTransactionReceipt, PreviewRequest}; +use crate::prelude::*; +use radix_engine_toolkit_common::receipt::RuntimeToolkitTransactionReceipt; pub(crate) async fn handle_transaction_preview( state: State, @@ -107,17 +102,16 @@ fn to_api_response( should_include_toolkit_receipt: bool, ) -> Result> { let engine_receipt = result.receipt; - let versioned_engine_receipt = engine_receipt.clone().into_versioned(); - // This is interpreted by the toolkit in the wallet. This will be removed with the release of - // the cuttlefish protocol update. - let encoded_receipt = to_hex(scrypto_encode(&versioned_engine_receipt).unwrap()); + // The `encoded_receipt` is removed as of Cuttlefish, but the JSON field is kept for + // structural backwards compatibility, to prevent breaking clients who don't rely on it. + let encoded_receipt = "".to_string(); // Produce a toolkit transaction receipt for the transaction preview if it was requested in the // request opt-ins. let toolkit_receipt = if should_include_toolkit_receipt { Some( - RuntimeToolkitTransactionReceipt::try_from(versioned_engine_receipt.clone()) + RuntimeToolkitTransactionReceipt::try_from(engine_receipt.clone()) .ok() .and_then(|value| { value diff --git a/core-rust/core-api-server/src/core_api/handlers/transaction_receipt.rs b/core-rust/core-api-server/src/core_api/handlers/transaction_receipt.rs index 8ded896fb1..3f69c45b2c 100644 --- a/core-rust/core-api-server/src/core_api/handlers/transaction_receipt.rs +++ b/core-rust/core-api-server/src/core_api/handlers/transaction_receipt.rs @@ -1,8 +1,5 @@ use crate::core_api::handlers::to_api_committed_transaction; -use crate::core_api::*; - -use state_manager::store::traits::*; -use state_manager::transaction::*; +use crate::prelude::*; #[tracing::instrument(skip(state))] pub(crate) async fn handle_transaction_receipt( @@ -15,7 +12,7 @@ pub(crate) async fn handle_transaction_receipt( .with_transaction_formats(&request.transaction_format_options); let extraction_context = ExtractionContext::new(&state.network); - let intent_hash = extract_intent_hash(&extraction_context, request.intent_hash) + let intent_hash = extract_transaction_intent_hash(&extraction_context, request.intent_hash) .map_err(|err| err.into_response_error("intent_hash"))?; let database = state.state_manager.database.snapshot(); diff --git a/core-rust/core-api-server/src/core_api/handlers/transaction_status.rs b/core-rust/core-api-server/src/core_api/handlers/transaction_status.rs index 75e1276df7..2442317d60 100644 --- a/core-rust/core-api-server/src/core_api/handlers/transaction_status.rs +++ b/core-rust/core-api-server/src/core_api/handlers/transaction_status.rs @@ -1,15 +1,4 @@ -use std::collections::{HashMap, HashSet}; - -use crate::core_api::*; -use crate::engine_prelude::*; - -use state_manager::{ - AlreadyCommittedError, DetailedTransactionOutcome, MempoolRejectionReason, StateVersion, -}; - -use state_manager::mempool::pending_transaction_result_cache::PendingTransactionRecord; -use state_manager::query::StateManagerSubstateQueries; -use state_manager::store::traits::*; +use crate::prelude::*; #[tracing::instrument(skip(state))] pub(crate) async fn handle_transaction_status( @@ -21,7 +10,7 @@ pub(crate) async fn handle_transaction_status( let mapping_context = MappingContext::new_for_uncommitted_data(&state.network); let extraction_context = ExtractionContext::new(&state.network); - let intent_hash = extract_intent_hash(&extraction_context, request.intent_hash) + let intent_hash = extract_transaction_intent_hash(&extraction_context, request.intent_hash) .map_err(|err| err.into_response_error("intent_hash"))?; let pending_transaction_result_cache = @@ -57,11 +46,10 @@ pub(crate) async fn handle_transaction_status( }); if let Some(txn_state_version) = txn_state_version_opt { - let identifiers = database + let hashes = database .get_committed_transaction_identifiers(txn_state_version) .expect("Txn identifiers are missing") - .payload - .typed; + .transaction_hashes; let local_detailed_outcome = database .get_committed_local_transaction_execution(txn_state_version) @@ -69,13 +57,13 @@ pub(crate) async fn handle_transaction_status( .outcome; drop(database); - let user_identifiers = identifiers - .user() + let user_hashes = hashes + .as_user() .expect("Only user transactions should be able to be looked up by intent hash"); - let notarized_transaction_hash = user_identifiers.notarized_transaction_hash; + let notarized_transaction_hash = user_hashes.notarized_transaction_hash; // Remove the committed payload from the rejection list if it's present - known_pending_payloads.remove(notarized_transaction_hash); + known_pending_payloads.remove(¬arized_transaction_hash); let (intent_status, payload_status, outcome, error_message) = match local_detailed_outcome { DetailedTransactionOutcome::Success(_) => ( @@ -94,11 +82,11 @@ pub(crate) async fn handle_transaction_status( let committed_payload = models::TransactionPayloadDetails { payload_hash: to_api_notarized_transaction_hash( - user_identifiers.notarized_transaction_hash, + &user_hashes.notarized_transaction_hash, ), payload_hash_bech32m: to_api_hash_bech32m( &mapping_context, - user_identifiers.notarized_transaction_hash, + &user_hashes.notarized_transaction_hash, )?, state_version: Some(to_api_state_version(txn_state_version)?), status: payload_status, @@ -110,7 +98,7 @@ pub(crate) async fn handle_transaction_status( &mapping_context, known_pending_payloads, txn_state_version, - notarized_transaction_hash, + ¬arized_transaction_hash, )?); return Ok(Json(models::TransactionStatusResponse { diff --git a/core-rust/core-api-server/src/core_api/handlers/transaction_submit.rs b/core-rust/core-api-server/src/core_api/handlers/transaction_submit.rs index 2a56d5adca..c6859d0d32 100644 --- a/core-rust/core-api-server/src/core_api/handlers/transaction_submit.rs +++ b/core-rust/core-api-server/src/core_api/handlers/transaction_submit.rs @@ -1,9 +1,5 @@ -use crate::core_api::*; -use crate::engine_prelude::*; - -use hyper::StatusCode; +use crate::prelude::*; use models::transaction_submit_error_details::TransactionSubmitErrorDetails; -use state_manager::{AlreadyCommittedError, MempoolAddError, MempoolAddSource}; #[tracing::instrument(level = "debug", skip(state))] pub(crate) async fn handle_transaction_submit( @@ -20,21 +16,21 @@ pub(crate) async fn handle_transaction_submit( let result = state.state_manager.mempool_manager.add_and_trigger_relay( MempoolAddSource::CoreApi, - RawNotarizedTransaction(transaction_bytes), + RawNotarizedTransaction::from_vec(transaction_bytes), force_recalculate, ); match result { Ok(_) => Ok(models::TransactionSubmitResponse::new(false)), Err(MempoolAddError::PriorityThresholdNotMet { - min_tip_percentage_required, - tip_percentage, + min_tip_basis_points_required, + tip_basis_points, }) => Err(detailed_error( StatusCode::BAD_REQUEST, "The mempool is full and the submitted transaction's priority is not sufficient to replace any existing transactions. Try submitting with a larger tip to increase the transaction's priority.", TransactionSubmitErrorDetails::TransactionSubmitPriorityThresholdNotMetErrorDetails { - tip_percentage: tip_percentage as i32, - min_tip_percentage_required: min_tip_percentage_required.map(|x| x as i32), + tip_percentage: TipSpecifier::BasisPoints(tip_basis_points).truncate_to_percentage_u32() as i32, // Dividing by 100 means this is inbounds + min_tip_percentage_required: min_tip_basis_points_required.map(|x| TipSpecifier::BasisPoints(x).truncate_to_percentage_u32() as i32), }, )), Err(MempoolAddError::Duplicate(_)) => Ok(models::TransactionSubmitResponse::new(true)), @@ -62,19 +58,19 @@ pub(crate) async fn handle_transaction_submit( is_intent_rejection_permanent: rejection.is_permanent_for_intent(), // TODO - Add `result_validity_substate_criteria` once track / mempool is improved retry_from_timestamp: match rejection.retry_from { - state_manager::RetryFrom::Never => None, - state_manager::RetryFrom::FromTime(time) => Some(Box::new( + RetryFrom::Never => None, + RetryFrom::FromTime(time) => Some(Box::new( to_api_clamped_instant_from_epoch_milli(to_unix_timestamp_ms(time)?)?, )), - state_manager::RetryFrom::FromEpoch(_) => None, - state_manager::RetryFrom::Whenever => { + RetryFrom::FromEpoch(_) => None, + RetryFrom::Whenever => { Some(Box::new(to_api_clamped_instant_from_epoch_milli( to_unix_timestamp_ms(std::time::SystemTime::now())?, )?)) } }, retry_from_epoch: match rejection.retry_from { - state_manager::RetryFrom::FromEpoch(epoch) => { + RetryFrom::FromEpoch(epoch) => { Some(to_api_epoch(&mapping_context, epoch)?) } _ => None, diff --git a/core-rust/core-api-server/src/core_api/helpers.rs b/core-rust/core-api-server/src/core_api/helpers.rs index 6d68a4e62a..ad2efbeca4 100644 --- a/core-rust/core-api-server/src/core_api/helpers.rs +++ b/core-rust/core-api-server/src/core_api/helpers.rs @@ -1,13 +1,7 @@ -use crate::engine_prelude::*; -use node_common::store::rocks_db::ReadableRocks; +use crate::prelude::*; use serde::Serialize; -use state_manager::store::rocks_db::StateManagerDatabase; -use state_manager::store::traits::*; -use state_manager::LedgerHeader; use std::io::Write; -use super::*; - #[allow(unused)] pub(crate) fn read_typed_substate( context: &MappingContext, @@ -16,7 +10,7 @@ pub(crate) fn read_typed_substate( partition_number: PartitionNumber, substate_key: &SubstateKey, ) -> Result, MappingError> { - let Some(raw_value) = database.get_substate( + let Some(raw_value) = database.get_raw_substate_by_db_key( &SpreadPrefixKeyMapper::to_db_partition_key(node_id, partition_number), &SpreadPrefixKeyMapper::to_db_sort_key(substate_key), ) else { @@ -120,7 +114,7 @@ pub(crate) fn read_optional_substate( partition_number: PartitionNumber, substate_key: &SubstateKey, ) -> Option { - database.get_mapped::(node_id, partition_number, substate_key) + database.get_substate::(node_id, partition_number, substate_key) } #[tracing::instrument(skip_all)] diff --git a/core-rust/core-api-server/src/core_api/server.rs b/core-rust/core-api-server/src/core_api/server.rs index 17c71e73e6..703d9f8740 100644 --- a/core-rust/core-api-server/src/core_api/server.rs +++ b/core-rust/core-api-server/src/core_api/server.rs @@ -62,8 +62,8 @@ * permissions under this License. */ +use crate::prelude::*; use std::future::Future; -use std::sync::Arc; use super::metrics::CoreApiMetrics; use super::metrics_layer::MetricsLayer; @@ -76,12 +76,8 @@ use axum::{ routing::{get, post}, Router, }; - -use crate::engine_prelude::*; -use prometheus::Registry; -use state_manager::StateManager; +use state_manager::state_manager::StateManager; use tower_http::catch_panic::CatchPanicLayer; -use tracing::{debug, error, info, trace, warn, Level}; use super::{constants::LARGE_REQUEST_MAX_BYTES, handlers::*, not_found_error, ResponseError}; @@ -100,7 +96,7 @@ pub async fn create_server( bind_addr: &str, shutdown_signal: F, core_api_state: CoreApiState, - metric_registry: &Registry, + metric_registry: &MetricRegistry, ) where F: Future, { @@ -233,21 +229,21 @@ async fn emit_error_response_event(uri: Uri, response: Response) -> Response { let level = resolve_level(response.status()); // the `event!(level, ...)` macro does not accept non-constant levels, hence we unroll: match level { - Level::TRACE => trace!(path = uri.path(), error = debug(error_response)), - Level::DEBUG => debug!(path = uri.path(), error = debug(error_response)), - Level::INFO => info!(path = uri.path(), error = debug(error_response)), - Level::WARN => warn!(path = uri.path(), error = debug(error_response)), - Level::ERROR => error!(path = uri.path(), error = debug(error_response)), + LogLevel::TRACE => trace!(path = uri.path(), error = debug(error_response)), + LogLevel::DEBUG => debug!(path = uri.path(), error = debug(error_response)), + LogLevel::INFO => info!(path = uri.path(), error = debug(error_response)), + LogLevel::WARN => warn!(path = uri.path(), error = debug(error_response)), + LogLevel::ERROR => error!(path = uri.path(), error = debug(error_response)), } } response } -fn resolve_level(status_code: StatusCode) -> Level { +fn resolve_level(status_code: StatusCode) -> LogLevel { if status_code.is_server_error() { - Level::WARN + LogLevel::WARN } else { - Level::DEBUG + LogLevel::DEBUG } } diff --git a/core-rust/core-api-server/src/jni/mod.rs b/core-rust/core-api-server/src/jni/mod.rs index 4c83711c89..8b4166e8da 100644 --- a/core-rust/core-api-server/src/jni/mod.rs +++ b/core-rust/core-api-server/src/jni/mod.rs @@ -62,19 +62,13 @@ * permissions under this License. */ +use std::sync::MutexGuard; + use crate::core_api::{create_server, CoreApiServerConfig, CoreApiState}; -use crate::engine_prelude::*; +use crate::jni_prelude::*; use futures::channel::oneshot; use futures::channel::oneshot::Sender; use futures::FutureExt; -use jni::objects::{JClass, JObject}; -use jni::sys::jbyteArray; -use jni::JNIEnv; -use node_common::java::*; -use prometheus::*; -use state_manager::jni::node_rust_environment::JNINodeRustEnvironment; -use std::str; -use std::sync::{Arc, MutexGuard}; use tokio::runtime::Runtime; const POINTER_JNI_FIELD_NAME: &str = "rustCoreApiServerPointer"; @@ -88,7 +82,7 @@ pub struct JNICoreApiServer { pub runtime: Arc, pub state: CoreApiState, pub running_server: Option, - pub metric_registry: Arc, + pub metric_registry: Arc, } #[no_mangle] diff --git a/core-rust/core-api-server/src/lib.rs b/core-rust/core-api-server/src/lib.rs index 70f2442e8b..6e6abaeb27 100644 --- a/core-rust/core-api-server/src/lib.rs +++ b/core-rust/core-api-server/src/lib.rs @@ -68,6 +68,30 @@ extern crate serde_json; mod core_api; pub mod jni; +#[allow(unused_imports)] +pub(crate) mod prelude { + pub(crate) use crate::engine_prelude::*; + pub(crate) use node_common::prelude::*; + pub(crate) use state_manager::prelude::*; + + pub(crate) use crate::core_api::*; + pub(crate) use historical_state::*; + + // Axum imports + pub(crate) use axum::{ + body::BoxBody, + http::Uri, + response::{IntoResponse, Response}, + Json, + }; +} + +pub(crate) mod jni_prelude { + pub(crate) use crate::prelude::*; + pub(crate) use state_manager::jni_prelude::*; +} + +#[allow(unused_imports)] pub(crate) mod engine_prelude { pub use radix_blueprint_schema_init::*; pub use radix_common::prelude::*; diff --git a/core-rust/engine-state-api-server/src/engine_state_api/conversions/access_rules.rs b/core-rust/engine-state-api-server/src/engine_state_api/conversions/access_rules.rs index bdadb89086..c2f74f9259 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/conversions/access_rules.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/conversions/access_rules.rs @@ -1,7 +1,4 @@ -use super::*; -use crate::engine_state_api::models; - -use crate::engine_prelude::*; +use crate::prelude::*; pub fn to_api_access_rule( context: &MappingContext, @@ -18,19 +15,21 @@ pub fn to_api_access_rule( pub fn to_api_access_rule_node( context: &MappingContext, - access_rule: &AccessRuleNode, + requirement: &CompositeRequirement, ) -> Result { - Ok(match access_rule { - AccessRuleNode::ProofRule(proof_rule) => models::AccessRuleNode::ProofAccessRuleNode { - proof_rule: Box::new(to_api_proof_rule(context, proof_rule)?), - }, - AccessRuleNode::AnyOf(access_rules) => models::AccessRuleNode::AnyOfAccessRuleNode { + Ok(match requirement { + CompositeRequirement::BasicRequirement(requirement) => { + models::AccessRuleNode::ProofAccessRuleNode { + proof_rule: Box::new(to_api_proof_rule(context, requirement)?), + } + } + CompositeRequirement::AnyOf(access_rules) => models::AccessRuleNode::AnyOfAccessRuleNode { access_rules: access_rules .iter() .map(|ar| to_api_access_rule_node(context, ar)) .collect::>()?, }, - AccessRuleNode::AllOf(access_rules) => models::AccessRuleNode::AllOfAccessRuleNode { + CompositeRequirement::AllOf(access_rules) => models::AccessRuleNode::AllOfAccessRuleNode { access_rules: access_rules .iter() .map(|ar| to_api_access_rule_node(context, ar)) @@ -41,23 +40,29 @@ pub fn to_api_access_rule_node( pub fn to_api_proof_rule( context: &MappingContext, - proof_rule: &ProofRule, + requirement: &BasicRequirement, ) -> Result { - Ok(match proof_rule { - ProofRule::Require(resource_or_non_fungible) => models::ProofRule::RequireProofRule { - requirement: Box::new(to_api_requirement(context, resource_or_non_fungible)?), - }, - ProofRule::AmountOf(amount, resource) => models::ProofRule::AmountOfProofRule { + Ok(match requirement { + BasicRequirement::Require(resource_or_non_fungible) => { + models::ProofRule::RequireProofRule { + requirement: Box::new(to_api_requirement(context, resource_or_non_fungible)?), + } + } + BasicRequirement::AmountOf(amount, resource) => models::ProofRule::AmountOfProofRule { amount: to_api_decimal(amount), resource: to_api_resource_address(context, resource)?, }, - ProofRule::AllOf(resource_or_non_fungible_list) => models::ProofRule::AllOfProofRule { - list: to_api_resource_or_non_fungible_list(context, resource_or_non_fungible_list)?, - }, - ProofRule::AnyOf(resource_or_non_fungible_list) => models::ProofRule::AnyOfProofRule { - list: to_api_resource_or_non_fungible_list(context, resource_or_non_fungible_list)?, - }, - ProofRule::CountOf(count, resource_or_non_fungible_list) => { + BasicRequirement::AllOf(resource_or_non_fungible_list) => { + models::ProofRule::AllOfProofRule { + list: to_api_resource_or_non_fungible_list(context, resource_or_non_fungible_list)?, + } + } + BasicRequirement::AnyOf(resource_or_non_fungible_list) => { + models::ProofRule::AnyOfProofRule { + list: to_api_resource_or_non_fungible_list(context, resource_or_non_fungible_list)?, + } + } + BasicRequirement::CountOf(count, resource_or_non_fungible_list) => { models::ProofRule::CountOfProofRule { count: *count as i32, list: to_api_resource_or_non_fungible_list(context, resource_or_non_fungible_list)?, diff --git a/core-rust/engine-state-api-server/src/engine_state_api/conversions/addressing.rs b/core-rust/engine-state-api-server/src/engine_state_api/conversions/addressing.rs index ede1d95680..e78fd26964 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/conversions/addressing.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/conversions/addressing.rs @@ -1,7 +1,4 @@ -use crate::engine_state_api::models; -use crate::engine_state_api::*; - -use crate::engine_prelude::*; +use crate::prelude::*; pub fn to_api_global_address( context: &MappingContext, @@ -48,14 +45,16 @@ pub fn to_api_entity_type(entity_type: EntityType) -> models::EntityType { EntityType::GlobalAccountLocker => models::EntityType::GlobalAccountLocker, EntityType::GlobalIdentity => models::EntityType::GlobalIdentity, EntityType::GlobalGenericComponent => models::EntityType::GlobalGenericComponent, - EntityType::GlobalVirtualSecp256k1Account => { + EntityType::GlobalPreallocatedSecp256k1Account => { models::EntityType::GlobalVirtualSecp256k1Account } - EntityType::GlobalVirtualEd25519Account => models::EntityType::GlobalVirtualEd25519Account, - EntityType::GlobalVirtualSecp256k1Identity => { + EntityType::GlobalPreallocatedEd25519Account => { + models::EntityType::GlobalVirtualEd25519Account + } + EntityType::GlobalPreallocatedSecp256k1Identity => { models::EntityType::GlobalVirtualSecp256k1Identity } - EntityType::GlobalVirtualEd25519Identity => { + EntityType::GlobalPreallocatedEd25519Identity => { models::EntityType::GlobalVirtualEd25519Identity } EntityType::InternalFungibleVault => models::EntityType::InternalFungibleVault, @@ -84,14 +83,16 @@ pub fn extract_entity_type(entity_type: models::EntityType) -> EntityType { models::EntityType::GlobalIdentity => EntityType::GlobalIdentity, models::EntityType::GlobalGenericComponent => EntityType::GlobalGenericComponent, models::EntityType::GlobalVirtualSecp256k1Account => { - EntityType::GlobalVirtualSecp256k1Account + EntityType::GlobalPreallocatedSecp256k1Account + } + models::EntityType::GlobalVirtualEd25519Account => { + EntityType::GlobalPreallocatedEd25519Account } - models::EntityType::GlobalVirtualEd25519Account => EntityType::GlobalVirtualEd25519Account, models::EntityType::GlobalVirtualSecp256k1Identity => { - EntityType::GlobalVirtualSecp256k1Identity + EntityType::GlobalPreallocatedSecp256k1Identity } models::EntityType::GlobalVirtualEd25519Identity => { - EntityType::GlobalVirtualEd25519Identity + EntityType::GlobalPreallocatedEd25519Identity } models::EntityType::InternalFungibleVault => EntityType::InternalFungibleVault, models::EntityType::InternalNonFungibleVault => EntityType::InternalNonFungibleVault, diff --git a/core-rust/engine-state-api-server/src/engine_state_api/conversions/common.rs b/core-rust/engine-state-api-server/src/engine_state_api/conversions/common.rs index e9b9b4eede..f1ad3a5134 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/conversions/common.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/conversions/common.rs @@ -1,10 +1,6 @@ -use crate::engine_prelude::*; +use crate::prelude::*; use itertools::Either; -use state_manager::{LedgerStateSummary, StateVersion}; - -use crate::engine_state_api::*; - #[tracing::instrument(skip_all)] pub fn to_hex>(v: T) -> String { hex::encode(v) diff --git a/core-rust/engine-state-api-server/src/engine_state_api/conversions/context.rs b/core-rust/engine-state-api-server/src/engine_state_api/conversions/context.rs index 45f06d88fe..efca1b632d 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/conversions/context.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/conversions/context.rs @@ -46,14 +46,12 @@ impl MappingContext { pub struct ExtractionContext { pub address_decoder: AddressBech32Decoder, - pub transaction_hash_decoder: TransactionHashBech32Decoder, } impl ExtractionContext { pub fn new(network_definition: &NetworkDefinition) -> Self { Self { address_decoder: AddressBech32Decoder::new(network_definition), - transaction_hash_decoder: TransactionHashBech32Decoder::new(network_definition), } } } diff --git a/core-rust/engine-state-api-server/src/engine_state_api/conversions/errors.rs b/core-rust/engine-state-api-server/src/engine_state_api/conversions/errors.rs index a0b2de68f6..d36cbc8a85 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/conversions/errors.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/conversions/errors.rs @@ -34,6 +34,7 @@ impl From for ResponseError { /// Should be used when extracting values from a client request #[derive(Debug, Clone)] #[allow(clippy::enum_variant_names)] +#[allow(unused)] // Fields are used in Debug implementations, but it's not enough to satisfy the lint pub enum ExtractionError { InvalidInteger { message: String, diff --git a/core-rust/engine-state-api-server/src/engine_state_api/conversions/hashes.rs b/core-rust/engine-state-api-server/src/engine_state_api/conversions/hashes.rs index 1bb6043f7c..8b1e22da69 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/conversions/hashes.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/conversions/hashes.rs @@ -1,7 +1,4 @@ -use crate::engine_prelude::*; -use state_manager::{ReceiptTreeHash, StateHash, TransactionTreeHash}; - -use crate::engine_state_api::*; +use crate::prelude::*; pub fn to_api_state_tree_hash(state_tree_hash: &StateHash) -> String { to_hex(state_tree_hash) diff --git a/core-rust/engine-state-api-server/src/engine_state_api/conversions/numerics.rs b/core-rust/engine-state-api-server/src/engine_state_api/conversions/numerics.rs index 910e6eba54..08ffe21d0a 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/conversions/numerics.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/conversions/numerics.rs @@ -1,13 +1,8 @@ -use crate::engine_prelude::*; +use crate::prelude::*; use chrono::prelude::*; use std::ops::RangeInclusive; use regex::Regex; -use state_manager::StateVersion; - -use crate::engine_state_api::models; - -use super::*; const MAX_API_EPOCH: u64 = 10000000000; const MAX_API_ROUND: u64 = 10000000000; diff --git a/core-rust/engine-state-api-server/src/engine_state_api/errors.rs b/core-rust/engine-state-api-server/src/engine_state_api/errors.rs index 8f7ce47c2c..8a8277e140 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/errors.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/errors.rs @@ -1,18 +1,11 @@ -use axum::body::BoxBody; -use axum::http::Uri; -use axum::{ - response::{IntoResponse, Response}, - Json, -}; +use crate::prelude::*; use std::any::Any; use hyper::StatusCode; use rand::distributions::Alphanumeric; use rand::Rng; -use state_manager::historical_state::StateHistoryError; use tower_http::catch_panic::ResponseForPanic; -use tracing::{debug, error, info, trace, warn, Level}; use super::models; @@ -89,7 +82,7 @@ impl TraceId { #[derive(Debug, Clone)] pub struct ErrorResponseEvent { - pub level: Level, + pub level: LogLevel, pub error: models::ErrorResponse, pub internal_message: String, } @@ -117,11 +110,11 @@ impl IntoResponse for ResponseError { } } -fn resolve_level(status_code: StatusCode) -> Level { +fn resolve_level(status_code: StatusCode) -> LogLevel { if status_code.is_server_error() { - Level::WARN + LogLevel::WARN } else { - Level::DEBUG + LogLevel::DEBUG } } @@ -139,11 +132,11 @@ pub async fn emit_error_response_event(uri: Uri, response: Response) -> Response internal_message, } = event; match *level { - Level::TRACE => trace!(path = uri.path(), error = debug(error), internal_message), - Level::DEBUG => debug!(path = uri.path(), error = debug(error), internal_message), - Level::INFO => info!(path = uri.path(), error = debug(error), internal_message), - Level::WARN => warn!(path = uri.path(), error = debug(error), internal_message), - Level::ERROR => error!(path = uri.path(), error = debug(error), internal_message), + LogLevel::TRACE => trace!(path = uri.path(), error = debug(error), internal_message), + LogLevel::DEBUG => debug!(path = uri.path(), error = debug(error), internal_message), + LogLevel::INFO => info!(path = uri.path(), error = debug(error), internal_message), + LogLevel::WARN => warn!(path = uri.path(), error = debug(error), internal_message), + LogLevel::ERROR => error!(path = uri.path(), error = debug(error), internal_message), } } response diff --git a/core-rust/engine-state-api-server/src/engine_state_api/extras.rs b/core-rust/engine-state-api-server/src/engine_state_api/extras.rs index 142932b351..b71c92d34c 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/extras.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/extras.rs @@ -1,10 +1,4 @@ -use crate::engine_prelude::*; - -use itertools::Itertools; - -use state_manager::store::traits::indices::{ - CreationId, EntityBlueprintId, EntityBlueprintIdV1, EntityListingIndex, -}; +use crate::prelude::*; use super::*; diff --git a/core-rust/engine-state-api-server/src/engine_state_api/factories.rs b/core-rust/engine-state-api-server/src/engine_state_api/factories.rs index 57267e8597..cc2445ad05 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/factories.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/factories.rs @@ -1,14 +1,7 @@ -use crate::engine_prelude::*; - -use radix_engine::transaction::{ - execute_and_commit_transaction, CommitResult, ExecutionConfig, StateUpdateSummary, - TransactionResult, -}; -use radix_engine::vm::wasm::DefaultWasmEngine; -use radix_engine::vm::{NoExtension, ScryptoVm, VmInit}; -use radix_substate_store_impls::substate_database_overlay::{ - SubstateDatabaseOverlay, UnmergeableSubstateDatabaseOverlay, -}; +use crate::prelude::*; + +use radix_engine::transaction::*; +use radix_transactions::manifest::*; use super::*; @@ -18,14 +11,16 @@ use super::*; /// instantiation" of an uninstantiated entity - hence most endpoint handlers should interact with /// this factory. pub struct EngineStateLoaderFactory<'s, S> { + network_definition: NetworkDefinition, database: UnmergeableSubstateDatabaseOverlay<'s, S>, staged_node_ids: IndexSet, } impl<'s, S: SubstateDatabase> EngineStateLoaderFactory<'s, S> { /// Creates a factory using the given database. - pub fn new(database: &'s S) -> Self { + pub fn new(network_definition: NetworkDefinition, database: &'s S) -> Self { Self { + network_definition, database: SubstateDatabaseOverlay::new_unmergeable(database), staged_node_ids: index_set_new(), } @@ -107,7 +102,7 @@ impl<'s, S: SubstateDatabase> EngineStateLoaderFactory<'s, S> { /// Checks whether the given entity should be automatically instantiated on access, given the /// current database state. fn requires_instantiation(&self, node_id: &NodeId) -> bool { - if !node_id.is_global_virtual() { + if !node_id.is_global_preallocated() { // No matter if it exists or not, we shouldn't instantiate: return false; } @@ -127,13 +122,13 @@ impl<'s, S: SubstateDatabase> EngineStateLoaderFactory<'s, S> { // the benefits of caching an instance (since we do not use any WASM here). If these // assumptions change in future, then it will make most sense to turn the `Self` into a // long-lived service holding a `ScryptoVm` as its dependency. - let scrypto_vm = ScryptoVm::::default(); + let vm_modules = DefaultVmModules::default(); let receipt = execute_and_commit_transaction( &mut self.database, - VmInit::new(&scrypto_vm, NoExtension), - &ExecutionConfig::default(), - &intent.get_executable(), + &vm_modules, + &ExecutionConfig::for_preview(self.network_definition.clone()), + intent.create_executable(), ); let TransactionResult::Commit(commit) = receipt.result else { panic!("failed to force instantiation: {:?}", receipt); @@ -182,7 +177,7 @@ fn create_intent_forcing_instantiation(node_id: &NodeId) -> ValidatedPreviewInte // Call any basic, non-invasive method, which is enough to force instantiation: // Note: the "get metadata" call below seems universal and future-proof enough, but // a more elegant solution could be based on some hypothetical "ensure exists" method? - InstructionV1::CallMetadataMethod { + InstructionV1::CallMetadataMethod(CallMetadataMethod { address: DynamicGlobalAddress::Static(address), method_name: "get".to_string(), args: ManifestValue::Tuple { @@ -190,14 +185,16 @@ fn create_intent_forcing_instantiation(node_id: &NodeId) -> ValidatedPreviewInte value: "dummy name".to_string(), }], }, - }, + }), ]), blobs: BlobsV1::default(), message: MessageV1::None, }; ValidatedPreviewIntent { - intent: intent.prepare().expect("hardcoded"), + intent: intent + .prepare(&PreparationSettings::latest()) + .expect("hardcoded"), encoded_instructions: manifest_encode(&intent.instructions.0).expect("hardcoded"), signer_public_keys: vec![], flags: PreviewFlags { diff --git a/core-rust/engine-state-api-server/src/engine_state_api/handlers/blueprint_info.rs b/core-rust/engine-state-api-server/src/engine_state_api/handlers/blueprint_info.rs index af039c874d..b58a64c83e 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/handlers/blueprint_info.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/handlers/blueprint_info.rs @@ -1,8 +1,4 @@ -use crate::engine_prelude::*; -use crate::engine_state_api::*; - -use crate::engine_state_api::factories::EngineStateLoaderFactory; -use state_manager::historical_state::VersionScopingSupport; +use crate::prelude::*; pub(crate) async fn handle_blueprint_info( state: State, @@ -34,7 +30,7 @@ pub(crate) async fn handle_blueprint_info( .database .snapshot() .scoped_at(requested_state_version)?; - let loader_factory = EngineStateLoaderFactory::new(&database); + let loader_factory = EngineStateLoaderFactory::new(state.network.clone(), &database); let blueprint_meta = loader_factory .create_meta_loader() diff --git a/core-rust/engine-state-api-server/src/engine_state_api/handlers/entity_info.rs b/core-rust/engine-state-api-server/src/engine_state_api/handlers/entity_info.rs index 6d403ae84f..fda9e99a0b 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/handlers/entity_info.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/handlers/entity_info.rs @@ -1,8 +1,4 @@ -use crate::engine_prelude::*; -use crate::engine_state_api::factories::EngineStateLoaderFactory; -use crate::engine_state_api::*; -use state_manager::historical_state::VersionScopingSupport; -use state_manager::store::traits::{SubstateNodeAncestryRecord, SubstateNodeAncestryStore}; +use crate::prelude::*; pub(crate) async fn handle_entity_info( state: State, @@ -22,7 +18,8 @@ pub(crate) async fn handle_entity_info( .database .snapshot() .scoped_at(requested_state_version)?; - let loader_factory = EngineStateLoaderFactory::new(&database).ensure_instantiated(&node_id); + let loader_factory = EngineStateLoaderFactory::new(state.network.clone(), &database) + .ensure_instantiated(&node_id); let entity_meta = loader_factory .create_meta_loader() diff --git a/core-rust/engine-state-api-server/src/engine_state_api/handlers/entity_schema_entry.rs b/core-rust/engine-state-api-server/src/engine_state_api/handlers/entity_schema_entry.rs index 1bbc6aacd8..65d7768f58 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/handlers/entity_schema_entry.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/handlers/entity_schema_entry.rs @@ -1,9 +1,4 @@ -use crate::engine_state_api::*; - -use crate::engine_prelude::*; - -use crate::engine_state_api::factories::EngineStateLoaderFactory; -use state_manager::historical_state::VersionScopingSupport; +use crate::prelude::*; pub(crate) async fn handle_entity_schema_entry( state: State, @@ -27,7 +22,8 @@ pub(crate) async fn handle_entity_schema_entry( .snapshot() .scoped_at(requested_state_version)?; - let loader_factory = EngineStateLoaderFactory::new(&database).ensure_instantiated(&node_id); + let loader_factory = EngineStateLoaderFactory::new(state.network.clone(), &database) + .ensure_instantiated(&node_id); let data_loader = loader_factory.create_data_loader(); let versioned_schema_data = data_loader.load_schema(&SchemaReference { diff --git a/core-rust/engine-state-api-server/src/engine_state_api/handlers/extra_entity_search.rs b/core-rust/engine-state-api-server/src/engine_state_api/handlers/extra_entity_search.rs index 7b1208f4d6..73064fd4da 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/handlers/extra_entity_search.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/handlers/extra_entity_search.rs @@ -1,16 +1,4 @@ -use crate::engine_state_api::*; - -use crate::engine_prelude::*; - -use state_manager::historical_state::VersionScopingSupport; -use state_manager::store::traits::indices::CreationId; -use state_manager::store::traits::ConfigurableDatabase; - -use crate::engine_state_api::extras::{EngineEntityLister, EntitySummary}; -use state_manager::StateVersion; -use std::ops::Deref; - -use crate::engine_state_api::handlers::HandlerPagingSupport; +use crate::prelude::*; pub(crate) async fn handle_extra_entity_search( state: State, diff --git a/core-rust/engine-state-api-server/src/engine_state_api/handlers/kv_store_entry.rs b/core-rust/engine-state-api-server/src/engine_state_api/handlers/kv_store_entry.rs index e939774418..b886985e66 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/handlers/kv_store_entry.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/handlers/kv_store_entry.rs @@ -1,9 +1,4 @@ -use crate::engine_state_api::*; - -use crate::engine_prelude::*; - -use crate::engine_state_api::factories::EngineStateLoaderFactory; -use state_manager::historical_state::VersionScopingSupport; +use crate::prelude::*; pub(crate) async fn handle_kv_store_entry( state: State, @@ -27,7 +22,8 @@ pub(crate) async fn handle_kv_store_entry( .snapshot() .scoped_at(requested_state_version)?; - let loader_factory = EngineStateLoaderFactory::new(&database).ensure_instantiated(&node_id); + let loader_factory = EngineStateLoaderFactory::new(state.network.clone(), &database) + .ensure_instantiated(&node_id); let meta_loader = loader_factory.create_meta_loader(); let EntityMeta::KeyValueStore(kv_store_meta) = meta_loader.load_entity_meta(&node_id)? else { diff --git a/core-rust/engine-state-api-server/src/engine_state_api/handlers/kv_store_iterator.rs b/core-rust/engine-state-api-server/src/engine_state_api/handlers/kv_store_iterator.rs index 1eafa5e24b..5ca9b50028 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/handlers/kv_store_iterator.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/handlers/kv_store_iterator.rs @@ -1,10 +1,4 @@ -use crate::engine_state_api::*; - -use crate::engine_prelude::*; - -use crate::engine_state_api::factories::EngineStateLoaderFactory; -use crate::engine_state_api::handlers::HandlerPagingSupport; -use state_manager::historical_state::VersionScopingSupport; +use crate::prelude::*; pub(crate) async fn handle_kv_store_iterator( state: State, @@ -31,7 +25,8 @@ pub(crate) async fn handle_kv_store_iterator( .snapshot() .scoped_at(requested_state_version)?; - let loader_factory = EngineStateLoaderFactory::new(&database).ensure_instantiated(&node_id); + let loader_factory = EngineStateLoaderFactory::new(state.network.clone(), &database) + .ensure_instantiated(&node_id); let meta_loader = loader_factory.create_meta_loader(); let EntityMeta::KeyValueStore(kv_store_meta) = meta_loader.load_entity_meta(&node_id)? else { diff --git a/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_collection_entry.rs b/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_collection_entry.rs index 6ea7dfdf01..1aa1d8ff0f 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_collection_entry.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_collection_entry.rs @@ -1,9 +1,4 @@ -use crate::engine_state_api::*; - -use crate::engine_prelude::*; - -use crate::engine_state_api::factories::EngineStateLoaderFactory; -use state_manager::historical_state::VersionScopingSupport; +use crate::prelude::*; pub(crate) async fn handle_object_collection_entry( state: State, @@ -38,7 +33,8 @@ pub(crate) async fn handle_object_collection_entry( .snapshot() .scoped_at(requested_state_version)?; - let loader_factory = EngineStateLoaderFactory::new(&database).ensure_instantiated(&node_id); + let loader_factory = EngineStateLoaderFactory::new(state.network.clone(), &database) + .ensure_instantiated(&node_id); let meta_loader = loader_factory.create_meta_loader(); let module_state_meta = meta_loader.load_object_module_state_meta(&node_id, module_id)?; diff --git a/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_collection_iterator.rs b/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_collection_iterator.rs index 223cd0cb30..4220d06295 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_collection_iterator.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_collection_iterator.rs @@ -1,11 +1,4 @@ -use crate::engine_state_api::*; - -use crate::engine_prelude::*; - -use crate::engine_state_api::handlers::HandlerPagingSupport; - -use crate::engine_state_api::factories::EngineStateLoaderFactory; -use state_manager::historical_state::VersionScopingSupport; +use crate::prelude::*; pub(crate) async fn handle_object_collection_iterator( state: State, @@ -37,7 +30,8 @@ pub(crate) async fn handle_object_collection_iterator( .snapshot() .scoped_at(requested_state_version)?; - let loader_factory = EngineStateLoaderFactory::new(&database).ensure_instantiated(&node_id); + let loader_factory = EngineStateLoaderFactory::new(state.network.clone(), &database) + .ensure_instantiated(&node_id); let meta_loader = loader_factory.create_meta_loader(); let module_state_meta = meta_loader.load_object_module_state_meta(&node_id, module_id)?; diff --git a/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_field.rs b/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_field.rs index 89fc691265..cf5cb900e5 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_field.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_field.rs @@ -1,9 +1,4 @@ -use crate::engine_state_api::*; - -use crate::engine_prelude::*; - -use crate::engine_state_api::factories::EngineStateLoaderFactory; -use state_manager::historical_state::VersionScopingSupport; +use crate::prelude::*; pub(crate) async fn handle_object_field( state: State, @@ -32,7 +27,8 @@ pub(crate) async fn handle_object_field( .snapshot() .scoped_at(requested_state_version)?; - let loader_factory = EngineStateLoaderFactory::new(&database).ensure_instantiated(&node_id); + let loader_factory = EngineStateLoaderFactory::new(state.network.clone(), &database) + .ensure_instantiated(&node_id); let meta_loader = loader_factory.create_meta_loader(); let module_state_meta = meta_loader.load_object_module_state_meta(&node_id, module_id)?; diff --git a/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_metadata_entry.rs b/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_metadata_entry.rs index a165063b3f..6f7b838d08 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_metadata_entry.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_metadata_entry.rs @@ -1,9 +1,4 @@ -use crate::engine_state_api::*; - -use crate::engine_prelude::*; - -use crate::engine_state_api::factories::EngineStateLoaderFactory; -use state_manager::historical_state::VersionScopingSupport; +use crate::prelude::*; pub(crate) async fn handle_object_metadata_entry( state: State, @@ -25,7 +20,8 @@ pub(crate) async fn handle_object_metadata_entry( .snapshot() .scoped_at(requested_state_version)?; - let loader_factory = EngineStateLoaderFactory::new(&database).ensure_instantiated(&node_id); + let loader_factory = EngineStateLoaderFactory::new(state.network.clone(), &database) + .ensure_instantiated(&node_id); let metadata_value = loader_factory .create_object_metadata_loader() diff --git a/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_metadata_iterator.rs b/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_metadata_iterator.rs index f23b24636b..680e382b5e 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_metadata_iterator.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_metadata_iterator.rs @@ -1,11 +1,4 @@ -use crate::engine_state_api::*; - -use crate::engine_prelude::*; - -use crate::engine_state_api::handlers::HandlerPagingSupport; - -use crate::engine_state_api::factories::EngineStateLoaderFactory; -use state_manager::historical_state::VersionScopingSupport; +use crate::prelude::*; pub(crate) async fn handle_object_metadata_iterator( state: State, @@ -29,7 +22,8 @@ pub(crate) async fn handle_object_metadata_iterator( .snapshot() .scoped_at(requested_state_version)?; - let loader_factory = EngineStateLoaderFactory::new(&database).ensure_instantiated(&node_id); + let loader_factory = EngineStateLoaderFactory::new(state.network.clone(), &database) + .ensure_instantiated(&node_id); let loader = loader_factory.create_object_metadata_loader(); let page = paging_support.get_page(|from| loader.iter_keys(&node_id, from))?; diff --git a/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_role_assignment.rs b/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_role_assignment.rs index f149abe8d3..bf7b16ae2c 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_role_assignment.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_role_assignment.rs @@ -1,9 +1,4 @@ -use crate::engine_state_api::*; - -use crate::engine_prelude::*; - -use crate::engine_state_api::factories::EngineStateLoaderFactory; -use state_manager::historical_state::VersionScopingSupport; +use crate::prelude::*; pub(crate) async fn handle_object_role_assignment( state: State, @@ -25,7 +20,8 @@ pub(crate) async fn handle_object_role_assignment( .snapshot() .scoped_at(requested_state_version)?; - let loader_factory = EngineStateLoaderFactory::new(&database).ensure_instantiated(&node_id); + let loader_factory = EngineStateLoaderFactory::new(state.network.clone(), &database) + .ensure_instantiated(&node_id); let ObjectRoleAssignment { owner_role_entry, diff --git a/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_royalty.rs b/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_royalty.rs index 39f8232e61..17543b1ae8 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_royalty.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/handlers/object_royalty.rs @@ -1,9 +1,4 @@ -use crate::engine_state_api::*; - -use crate::engine_prelude::*; - -use crate::engine_state_api::factories::EngineStateLoaderFactory; -use state_manager::historical_state::VersionScopingSupport; +use crate::prelude::*; pub(crate) async fn handle_object_royalty( state: State, @@ -25,7 +20,8 @@ pub(crate) async fn handle_object_royalty( .snapshot() .scoped_at(requested_state_version)?; - let loader_factory = EngineStateLoaderFactory::new(&database).ensure_instantiated(&node_id); + let loader_factory = EngineStateLoaderFactory::new(state.network.clone(), &database) + .ensure_instantiated(&node_id); let method_amounts = loader_factory .create_object_royalty_loader() diff --git a/core-rust/engine-state-api-server/src/engine_state_api/mod.rs b/core-rust/engine-state-api-server/src/engine_state_api/mod.rs index 666abb4501..0e42cd5ce1 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/mod.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/mod.rs @@ -85,6 +85,9 @@ pub(crate) use attached_modules::*; pub(crate) use conversions::*; pub(crate) use errors::*; pub(crate) use extractors::*; +pub(crate) use extras::*; +pub(crate) use factories::*; +pub(crate) use handlers::*; pub(crate) use paging::*; pub(crate) use programmatic_json::*; pub(crate) use readers::*; diff --git a/core-rust/engine-state-api-server/src/engine_state_api/programmatic_json.rs b/core-rust/engine-state-api-server/src/engine_state_api/programmatic_json.rs index 1210fc175a..7783ecc160 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/programmatic_json.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/programmatic_json.rs @@ -1,4 +1,4 @@ -use crate::engine_prelude::*; +use crate::prelude::*; use serde::Deserialize; use serde_with::serde_as; @@ -26,7 +26,7 @@ impl<'a> ProgrammaticJsonEncoder<'a> { schema: &SchemaV1, type_id: LocalTypeId, ) -> Result { - let raw_payload = RawScryptoPayload::new_from_valid_owned(payload_bytes); + let raw_payload = ScryptoRawPayload::new_from_valid_owned(payload_bytes); let serializable = raw_payload.serializable(SerializationParameters::WithSchema { mode: SerializationMode::Programmatic, custom_context: ScryptoValueDisplayContext::with_optional_bech32(Some( diff --git a/core-rust/engine-state-api-server/src/engine_state_api/server.rs b/core-rust/engine-state-api-server/src/engine_state_api/server.rs index 2cf73be9ab..fecf75c6a3 100644 --- a/core-rust/engine-state-api-server/src/engine_state_api/server.rs +++ b/core-rust/engine-state-api-server/src/engine_state_api/server.rs @@ -62,6 +62,7 @@ * permissions under this License. */ +use crate::prelude::*; use std::future::Future; use std::sync::Arc; @@ -76,9 +77,8 @@ use axum::{ Router, }; -use crate::engine_prelude::*; use prometheus::Registry; -use state_manager::StateManager; +use state_manager::state_manager::StateManager; use tower_http::catch_panic::CatchPanicLayer; use super::{handlers::*, ResponseError}; diff --git a/core-rust/engine-state-api-server/src/jni/mod.rs b/core-rust/engine-state-api-server/src/jni/mod.rs index 04bfe87611..29568bd345 100644 --- a/core-rust/engine-state-api-server/src/jni/mod.rs +++ b/core-rust/engine-state-api-server/src/jni/mod.rs @@ -63,15 +63,11 @@ */ use crate::engine_state_api::{create_server, EngineStateApiServerConfig, EngineStateApiState}; +use crate::jni_prelude::*; use futures::channel::oneshot; use futures::channel::oneshot::Sender; use futures::FutureExt; -use jni::objects::{JClass, JObject}; -use jni::sys::jbyteArray; -use jni::JNIEnv; use prometheus::*; -use state_manager::jni::node_rust_environment::JNINodeRustEnvironment; -use std::str; use std::sync::{Arc, MutexGuard}; use tokio::runtime::Runtime; diff --git a/core-rust/engine-state-api-server/src/lib.rs b/core-rust/engine-state-api-server/src/lib.rs index 3747047f48..5dad36667c 100644 --- a/core-rust/engine-state-api-server/src/lib.rs +++ b/core-rust/engine-state-api-server/src/lib.rs @@ -68,12 +68,36 @@ extern crate serde_json; mod engine_state_api; pub mod jni; +#[allow(unused_imports)] +pub(crate) mod prelude { + pub(crate) use crate::engine_prelude::*; + pub(crate) use node_common::prelude::*; + pub(crate) use state_manager::prelude::*; + + pub(crate) use crate::engine_state_api::*; + pub(crate) use historical_state::*; + + // Axum imports + pub(crate) use axum::{ + body::BoxBody, + http::Uri, + response::{IntoResponse, Response}, + Json, + }; +} + +pub(crate) mod jni_prelude { + pub(crate) use crate::prelude::*; + pub(crate) use state_manager::jni_prelude::*; +} + pub(crate) mod engine_prelude { pub use radix_blueprint_schema_init::*; pub use radix_engine::object_modules::metadata::*; pub use radix_engine::system::system_db_reader::*; pub use radix_engine::system::system_type_checker::*; + pub use radix_engine::vm::*; pub use radix_common::prelude::*; @@ -84,6 +108,7 @@ pub(crate) mod engine_prelude { pub use radix_transactions::errors::*; pub use sbor::representations::*; + pub use radix_substate_store_impls::substate_database_overlay::*; pub use radix_substate_store_interface::interface::*; pub use radix_substate_store_queries::typed_substate_layout::*; } diff --git a/core-rust/jni-export/Cargo.toml b/core-rust/jni-export/Cargo.toml index 17f18cfef2..f63fa08e88 100644 --- a/core-rust/jni-export/Cargo.toml +++ b/core-rust/jni-export/Cargo.toml @@ -25,4 +25,4 @@ jni = { workspace = true } [lib] name = "corerust" -crate_type = ["cdylib"] +crate-type = ["cdylib"] diff --git a/core-rust/jni-export/src/constants.rs b/core-rust/jni-export/src/constants.rs index 18b9dc2b26..507e661abe 100644 --- a/core-rust/jni-export/src/constants.rs +++ b/core-rust/jni-export/src/constants.rs @@ -62,23 +62,10 @@ * permissions under this License. */ -use jni::objects::JClass; -use jni::sys::jbyteArray; -use jni::JNIEnv; -use radix_common::prelude::{ - EXECUTION_COST_UNIT_LIMIT, FINALIZATION_COST_UNIT_LIMIT, MAX_TRANSACTION_SIZE, -}; - -use node_common::config::limits::{ - DEFAULT_MAX_TOTAL_VERTEX_EXECUTION_COST_UNITS_CONSUMED, - DEFAULT_MAX_TOTAL_VERTEX_FINALIZATION_COST_UNITS_CONSUMED, - DEFAULT_MAX_TOTAL_VERTEX_TRANSACTIONS_SIZE, DEFAULT_MAX_VERTEX_TRANSACTION_COUNT, -}; -use node_common::config::{ - DEFAULT_MEMPOOL_MAX_TOTAL_TRANSACTIONS_SIZE, DEFAULT_MEMPOOL_MAX_TRANSACTION_COUNT, -}; -use node_common::java::jni_sbor_coded_call; -use state_manager::priority_mempool::MEMPOOL_TRANSACTION_OVERHEAD_FACTOR_PERCENT; +use node_common::prelude::*; +use radix_transactions::model::PreparationSettings; +use state_manager::jni_prelude::*; +use state_manager::prelude::*; #[no_mangle] extern "system" fn Java_com_radixdlt_environment_NodeConstants_getDefaultMaxVertexTransactionCount( @@ -152,7 +139,9 @@ extern "system" fn Java_com_radixdlt_environment_NodeConstants_getDefaultMaxTran _class: JClass, request_payload: jbyteArray, ) -> jbyteArray { - jni_sbor_coded_call(&env, request_payload, |_: ()| MAX_TRANSACTION_SIZE) + jni_sbor_coded_call(&env, request_payload, |_: ()| { + PreparationSettings::latest().max_user_payload_length + }) } #[no_mangle] diff --git a/core-rust/node-common/src/config/limits.rs b/core-rust/node-common/src/config/limits.rs index c53ad5798f..6132817c61 100644 --- a/core-rust/node-common/src/config/limits.rs +++ b/core-rust/node-common/src/config/limits.rs @@ -62,7 +62,7 @@ * permissions under this License. */ -use crate::engine_prelude::*; +use crate::prelude::*; pub const DEFAULT_MAX_VERTEX_TRANSACTION_COUNT: u32 = 100; pub const DEFAULT_MAX_TOTAL_VERTEX_TRANSACTIONS_SIZE: usize = (3.8 * 1024.0 * 1024.0) as usize; diff --git a/core-rust/node-common/src/config/mod.rs b/core-rust/node-common/src/config/mod.rs index a7c74ab577..d1d1ecb164 100644 --- a/core-rust/node-common/src/config/mod.rs +++ b/core-rust/node-common/src/config/mod.rs @@ -62,9 +62,11 @@ * permissions under this License. */ -use crate::engine_prelude::*; +use crate::prelude::*; -pub mod limits; +mod limits; + +pub use limits::*; // Note: this is a hard limit on the raw network size of all transactions represented by the mempool. // However, the implementation may keep extra information (i.e. the same transaction but validated/prepared) @@ -72,7 +74,7 @@ pub mod limits; pub const DEFAULT_MEMPOOL_MAX_TOTAL_TRANSACTIONS_SIZE: u64 = 512 * 1024 * 1024; pub const DEFAULT_MEMPOOL_MAX_TRANSACTION_COUNT: u32 = 10_000; -#[derive(Debug, Categorize, Encode, Decode, Clone)] +#[derive(Debug, Clone, Sbor)] pub struct MempoolConfig { pub max_total_transactions_size: u64, pub max_transaction_count: u32, diff --git a/core-rust/node-common/src/java/mod.rs b/core-rust/node-common/src/java/mod.rs index 28476ed249..ea121c3bbf 100644 --- a/core-rust/node-common/src/java/mod.rs +++ b/core-rust/node-common/src/java/mod.rs @@ -62,12 +62,12 @@ * permissions under this License. */ -pub use self::utils::*; pub use result::*; pub use structure::*; pub use types::*; +pub use utils::*; -pub mod result; -pub mod structure; -pub mod types; -pub mod utils; +mod result; +mod structure; +mod types; +mod utils; diff --git a/core-rust/node-common/src/java/result.rs b/core-rust/node-common/src/java/result.rs index fe44c2ee1d..14da786246 100644 --- a/core-rust/node-common/src/java/result.rs +++ b/core-rust/node-common/src/java/result.rs @@ -62,9 +62,9 @@ * permissions under this License. */ -use crate::engine_prelude::*; +use crate::prelude::*; -#[derive(Debug, ScryptoSbor)] +#[derive(Debug, Sbor)] pub struct JavaError(pub String); impl From for JavaError { diff --git a/core-rust/node-common/src/java/structure.rs b/core-rust/node-common/src/java/structure.rs index 6b19c64bd6..715920a3f1 100644 --- a/core-rust/node-common/src/java/structure.rs +++ b/core-rust/node-common/src/java/structure.rs @@ -62,8 +62,8 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use crate::java::result::JavaResult; +use crate::jni_prelude::*; +use crate::prelude::*; pub trait StructFromJava { fn from_java(data: &[u8]) -> JavaResult diff --git a/core-rust/node-common/src/java/types.rs b/core-rust/node-common/src/java/types.rs index c70b34d836..ca2ac13a0c 100644 --- a/core-rust/node-common/src/java/types.rs +++ b/core-rust/node-common/src/java/types.rs @@ -62,9 +62,9 @@ * permissions under this License. */ -use crate::engine_prelude::*; +use crate::jni_prelude::*; -#[derive(Debug, PartialEq, Eq, Categorize, Encode, Decode)] +#[derive(Debug, PartialEq, Eq, Sbor)] pub struct JavaHashCode(Vec); impl JavaHashCode { diff --git a/core-rust/node-common/src/java/utils.rs b/core-rust/node-common/src/java/utils.rs index 5af40d96c1..39e7a52711 100644 --- a/core-rust/node-common/src/java/utils.rs +++ b/core-rust/node-common/src/java/utils.rs @@ -62,16 +62,10 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use jni::sys::jbyteArray; -use jni::JNIEnv; +use crate::jni_prelude::*; use std::panic; use std::panic::AssertUnwindSafe; -use crate::java::structure::{StructFromJava, StructToJava}; - -use crate::java::result::JavaResult; - pub fn jni_jbytearray_to_vector(env: &JNIEnv, jbytearray: jbyteArray) -> JavaResult> { Ok(env.convert_byte_array(jbytearray)?) } diff --git a/core-rust/node-common/src/jni/addressing.rs b/core-rust/node-common/src/jni/addressing.rs index 33e617b9f6..eee2f5ce54 100644 --- a/core-rust/node-common/src/jni/addressing.rs +++ b/core-rust/node-common/src/jni/addressing.rs @@ -62,12 +62,8 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use crate::java::utils::jni_sbor_coded_call; +use crate::jni_prelude::*; use bech32::{FromBase32, ToBase32, Variant}; -use jni::objects::JClass; -use jni::sys::jbyteArray; -use jni::JNIEnv; #[no_mangle] extern "system" fn Java_com_radixdlt_identifiers_Bech32mCoder_encodeAddress( @@ -153,7 +149,7 @@ extern "system" fn Java_com_radixdlt_identifiers_Address_nativeVirtualAccountAdd // Note: the bytes may represent a non-existent point on a curve (an invalid public key) - // this is okay. We need to support this because there are such accounts on Olympia. let public_key = Secp256k1PublicKey(unchecked_public_key_bytes); - ComponentAddress::virtual_account_from_public_key(&public_key) + ComponentAddress::preallocated_account_from_public_key(&public_key) }, ) } @@ -171,7 +167,7 @@ extern "system" fn Java_com_radixdlt_identifiers_Address_nativeVirtualIdentityAd // Note: the bytes may represent a non-existent point on a curve (an invalid public key) - // this is okay. We need to support this because there are such accounts on Olympia. let public_key = Secp256k1PublicKey(unchecked_public_key_bytes); - ComponentAddress::virtual_identity_from_public_key(&public_key) + ComponentAddress::preallocated_identity_from_public_key(&public_key) }, ) } diff --git a/core-rust/node-common/src/jni/scrypto_constants.rs b/core-rust/node-common/src/jni/scrypto_constants.rs index 81afdd328c..a3359ce46b 100644 --- a/core-rust/node-common/src/jni/scrypto_constants.rs +++ b/core-rust/node-common/src/jni/scrypto_constants.rs @@ -62,12 +62,7 @@ * permissions under this License. */ -use jni::objects::JClass; -use jni::sys::jbyteArray; -use jni::JNIEnv; - -use crate::engine_prelude::*; -use crate::java::utils::jni_sbor_coded_call; +use crate::jni_prelude::*; #[no_mangle] extern "system" fn Java_com_radixdlt_rev2_ScryptoConstants_getXrdResourceAddress( diff --git a/core-rust/node-common/src/lib.rs b/core-rust/node-common/src/lib.rs index 2f898a4b4b..03ef428dab 100644 --- a/core-rust/node-common/src/lib.rs +++ b/core-rust/node-common/src/lib.rs @@ -72,8 +72,41 @@ pub mod metrics; pub mod scheduler; pub mod store; pub mod utils; -pub use rocksdb; -pub(crate) mod engine_prelude { +pub mod prelude { + // Modules to export downstream + pub use crate::config::*; + pub use crate::locks::*; + pub use crate::metrics::*; + pub use crate::store::*; + pub use crate::utils::*; + + // Other commonly used imports which can be used across the node + pub use itertools::Itertools; + pub use prometheus::Registry as MetricRegistry; pub use radix_common::prelude::*; + pub use std::cmp::{min, Ordering}; + pub use std::ops::{Deref, DerefMut}; + pub use std::path::PathBuf; + pub use std::sync::Arc; + pub use std::time::Duration; + pub use std::time::Instant as StdInstant; // As opposed to an engine Instant + pub use std::time::SystemTime; + pub use tracing::{debug, error, info, trace, warn, Level as LogLevel}; + + // Re-export the rocksdb crate + pub use rocksdb; +} + +/// Explicitly for use when creating JNI integrations. +/// Includes the standard prelude for ease. +pub mod jni_prelude { + // Include the crate's own prelude when used internally + pub(crate) use crate::prelude::*; + + // Externally, just export the JNI-relevant stuff + pub use crate::java::*; + pub use jni::objects::*; + pub use jni::sys::jbyteArray; + pub use jni::{JNIEnv, JavaVM}; } diff --git a/core-rust/node-common/src/store/mod.rs b/core-rust/node-common/src/store/mod.rs index 561e3addfa..1a10d2c60e 100644 --- a/core-rust/node-common/src/store/mod.rs +++ b/core-rust/node-common/src/store/mod.rs @@ -1,2 +1,5 @@ -pub mod rocks_db; -pub mod typed_cf_api; +mod rocks_db; +mod typed_cf_api; + +pub use rocks_db::*; +pub use typed_cf_api::*; diff --git a/core-rust/node-common/src/store/rocks_db.rs b/core-rust/node-common/src/store/rocks_db.rs index 9035adb393..b27d1b362c 100644 --- a/core-rust/node-common/src/store/rocks_db.rs +++ b/core-rust/node-common/src/store/rocks_db.rs @@ -62,7 +62,7 @@ * permissions under this License. */ -use crate::engine_prelude::*; +use crate::prelude::*; use rocksdb::checkpoint::Checkpoint; use rocksdb::{ AsColumnFamilyRef, ColumnFamily, DBPinnableSlice, IteratorMode, Snapshot, WriteBatch, DB, diff --git a/core-rust/node-common/src/store/typed_cf_api.rs b/core-rust/node-common/src/store/typed_cf_api.rs index 7bf537418f..f06663a49f 100644 --- a/core-rust/node-common/src/store/typed_cf_api.rs +++ b/core-rust/node-common/src/store/typed_cf_api.rs @@ -62,9 +62,7 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use crate::store::rocks_db::{ReadableRocks, WriteableRocks}; -use itertools::Itertools; +use crate::prelude::*; use rocksdb::{ColumnFamily, Direction, IteratorMode, WriteBatch}; use std::ops::Range; @@ -617,7 +615,7 @@ pub trait OrderPreservingDbCodec {} /// - a `DbCodec` which turns an `(ip: u32, port: u16)` tuple into `ip[4B]|port[2B]` /// bytes *does* preserve grouping by host: /// - [3, 14, 0, 1, 0, 80] and [3, 14, 0, 1, 0, 22] bytes start with the same 4-byte prefix, and -/// indeed they represent port 80 and port 22 on the same host `3.14.0.1`. +/// indeed they represent port 80 and port 22 on the same host `3.14.0.1`. /// - the lexicographically-ordered range of *all* socket addresses on host `3.14.0.1` can be /// expressed as "from `[3, 14, 0, 1]` inclusive to `[3, 14, 0, 1, 255, 255, 0]` exclusive" /// (please note that it requires some knowledge on the maximum length of the part following the diff --git a/core-rust/node-common/src/utils.rs b/core-rust/node-common/src/utils.rs index cb1418995e..f8d5206110 100644 --- a/core-rust/node-common/src/utils.rs +++ b/core-rust/node-common/src/utils.rs @@ -62,7 +62,7 @@ * permissions under this License. */ -use crate::engine_prelude::*; +use crate::prelude::*; /// An implementation helper for a runtime-safe "capture a single expected value" functionality. pub enum CaptureSupport { @@ -109,6 +109,15 @@ impl CaptureSupport { self.capture_value(value.clone()); } + /// Calls [`Self::capture_value()`] with the constructed value, or does nothing if + /// not expecting any value at the moment. + pub fn capture_if_required(&mut self, constructor: impl FnOnce() -> T) { + if matches!(self, CaptureSupport::NotExpecting) { + return; // deliberately do nothing + } + self.capture_value(constructor()); + } + /// Returns the currently captured value and resets the instance to "not expecting" state. /// The [`Self::capture_value()`] must have been called before this method. pub fn retrieve_captured(&mut self) -> T { @@ -119,6 +128,15 @@ impl CaptureSupport { }; value } + + /// Extracts the captured value as an [`Option`]. + pub fn into_option(self) -> Option { + match self { + CaptureSupport::NotExpecting => None, + CaptureSupport::Expecting => None, + CaptureSupport::Captured(x) => Some(x), + } + } } pub trait IsAccountExt { @@ -131,8 +149,8 @@ impl IsAccountExt for GlobalAddress { Some(entity_type) => matches!( entity_type, EntityType::GlobalAccount - | EntityType::GlobalVirtualSecp256k1Account - | EntityType::GlobalVirtualEd25519Account + | EntityType::GlobalPreallocatedSecp256k1Account + | EntityType::GlobalPreallocatedEd25519Account ), _ => false, } diff --git a/core-rust/p2p/src/address_book_components.rs b/core-rust/p2p/src/address_book_components.rs index 1bec0b8497..4343edd868 100644 --- a/core-rust/p2p/src/address_book_components.rs +++ b/core-rust/p2p/src/address_book_components.rs @@ -62,9 +62,7 @@ * permissions under this License. */ -use crate::components; -use crate::engine_prelude::*; -use crate::engine_prelude::{ScryptoCategorize, ScryptoDecode, ScryptoEncode}; +use crate::prelude::*; use sbor::define_single_versioned; /// Timestamp of the various peer-related events @@ -79,26 +77,26 @@ use sbor::define_single_versioned; type PeerTimestamp = i64; /// Peer address entry with all components -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct PeerAddress { pub encoded_uri: Vec, pub latest_connection_status: Option, pub last_seen: Option, } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub enum ConnectionStatus { Connected, Disconnected, } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct NodeIdDTO { - pub key: components::NodeSecp256k1PublicKey, + pub key: NodeSecp256k1PublicKey, } /// Address book entry -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct AddressBookEntryV1 { pub node_id: NodeIdDTO, pub banned_until: Option, @@ -106,14 +104,14 @@ pub struct AddressBookEntryV1 { } define_single_versioned! { - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub VersionedAddressBookEntry(AddressBookEntryVersions) => AddressBookEntry = AddressBookEntryV1 } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct HighPriorityPeersV1(Vec); define_single_versioned! { - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub VersionedHighPriorityPeers(HighPriorityPeersVersions) => HighPriorityPeers = HighPriorityPeersV1 } diff --git a/core-rust/p2p/src/column_families.rs b/core-rust/p2p/src/column_families.rs index 3c4b247b97..5615c54570 100644 --- a/core-rust/p2p/src/column_families.rs +++ b/core-rust/p2p/src/column_families.rs @@ -67,7 +67,7 @@ use crate::components::NodeSecp256k1PublicKey; use crate::migration::MigrationStatus; use crate::safety_store_components::{SafetyState, VersionedSafetyState}; use crate::typed_cf_api::RawPublicKeyDbCodec; -use node_common::store::typed_cf_api::{DefaultCf, SborDbCodec, UnitDbCodec, VersionedCf}; +use node_common::store::*; /// Address book and safety state store migration status. Filled once during the migration. pub struct MigrationStatusCf; diff --git a/core-rust/p2p/src/components.rs b/core-rust/p2p/src/components.rs index 78c4908c87..4382c8590a 100644 --- a/core-rust/p2p/src/components.rs +++ b/core-rust/p2p/src/components.rs @@ -1,9 +1,7 @@ -use crate::engine_prelude::{ScryptoCategorize, ScryptoDecode, ScryptoEncode}; +use crate::prelude::*; /// The ID of the node stored in the Address book (Secp256k1 public key) -#[derive( - Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode, PartialOrd, Ord, PartialEq, Eq, -)] +#[derive(Debug, Clone, ScryptoSbor, PartialOrd, Ord, PartialEq, Eq)] #[sbor(transparent)] pub struct NodeSecp256k1PublicKey(pub [u8; NodeSecp256k1PublicKey::LENGTH]); @@ -20,7 +18,7 @@ impl NodeSecp256k1PublicKey { } /// The Secp256K1 signature -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct NodeSignature(pub [u8; NodeSignature::LENGTH]); impl NodeSignature { diff --git a/core-rust/p2p/src/lib.rs b/core-rust/p2p/src/lib.rs index 40a63c031a..a125758d98 100644 --- a/core-rust/p2p/src/lib.rs +++ b/core-rust/p2p/src/lib.rs @@ -7,6 +7,11 @@ pub mod safety_store_components; pub mod traits; pub mod typed_cf_api; -pub mod engine_prelude { - pub use radix_common::prelude::*; +pub mod prelude { + // External preludes re-imported for internal use + pub(crate) use node_common::prelude::*; + + // Important modules exported externally + pub use crate::components::*; + pub use crate::traits::*; } diff --git a/core-rust/p2p/src/rocks_db.rs b/core-rust/p2p/src/rocks_db.rs index 11271eb031..bfff89cbe9 100644 --- a/core-rust/p2p/src/rocks_db.rs +++ b/core-rust/p2p/src/rocks_db.rs @@ -64,17 +64,13 @@ use std::path::PathBuf; -use node_common::rocksdb::{ColumnFamilyDescriptor, Options, DB}; +use crate::prelude::*; +use rocksdb::{ColumnFamilyDescriptor, Options, DB}; use crate::address_book_components::*; use crate::column_families::*; -use crate::components::NodeSecp256k1PublicKey; -use crate::engine_prelude::*; use crate::migration::MigrationStatus; use crate::safety_store_components::SafetyState; -use crate::traits::node::{AddressBookStore, HighPriorityPeersStore, SafetyStateStore}; -use node_common::store::rocks_db::*; -use node_common::store::typed_cf_api::*; /// A listing of all column family names used by the Node. /// @@ -172,7 +168,7 @@ impl AddressBookStore for AddressBookDatabase { let binding = open_rw_context(&self.rocks); let context = binding.cf(AddressBookCf); - context.put(node_id, &entry); + context.put(node_id, entry); true } @@ -203,7 +199,7 @@ impl HighPriorityPeersStore for AddressBookDatabase { fn upsert_all_high_priority_peers(&self, peers: &HighPriorityPeers) { open_rw_context(&self.rocks) .cf(HighPriorityPeersCf) - .put(&(), &peers); + .put(&(), peers); } fn get_all_high_priority_peers(&self) -> Option { diff --git a/core-rust/p2p/src/safety_store_components.rs b/core-rust/p2p/src/safety_store_components.rs index cabb80254c..429a116f5d 100644 --- a/core-rust/p2p/src/safety_store_components.rs +++ b/core-rust/p2p/src/safety_store_components.rs @@ -62,11 +62,10 @@ * permissions under this License. */ -use crate::components::{NodeSecp256k1PublicKey, NodeSignature}; -use crate::engine_prelude::*; +use crate::prelude::*; use sbor::define_single_versioned; -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct SafetyStateV1 { validator_id: BFTValidatorId, round: Round, @@ -74,7 +73,7 @@ pub struct SafetyStateV1 { } define_single_versioned! { - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub VersionedSafetyState(SafetyStateVersions) => SafetyState = SafetyStateV1 } @@ -92,30 +91,26 @@ define_single_versioned! { // )] type SafetyStateTimestamp = i64; -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct BFTHeader { round: Round, vertex_id: VertexId, ledger_header: LedgerHeader, } -#[derive( - Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode, Ord, PartialOrd, Eq, PartialEq, -)] +#[derive(Debug, Clone, ScryptoSbor, Ord, PartialOrd, Eq, PartialEq)] pub struct BFTValidator { power: Vec, validator_id: BFTValidatorId, } -#[derive( - Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode, Ord, PartialOrd, Eq, PartialEq, -)] +#[derive(Debug, Clone, ScryptoSbor, Ord, PartialOrd, Eq, PartialEq)] pub struct BFTValidatorId { key: NodeSecp256k1PublicKey, validator_address: ComponentAddress, } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct HighQC { highest_quorum_certificate: QuorumCertificate, highest_committed_quorum_certificate: QuorumCertificate, @@ -125,7 +120,7 @@ pub struct HighQC { // FIXME: A duplicate of LedgerHeader from StateManager. // Made separate te reference only types within this module. De-duplication requires // careful merging of the other referenced types as well. -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct LedgerHeader { epoch: i64, round: Round, @@ -137,7 +132,7 @@ pub struct LedgerHeader { next_protocol_version: Option, } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct LedgerHashes { pub state_root: RawHash, pub transaction_root: RawHash, @@ -148,47 +143,47 @@ define_wrapped_hash! { RawHash } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct NextEpoch { epoch: i64, validators: Vec, } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct QuorumCertificate { signatures: TimestampedECDSASignatures, vote_data: VoteData, } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct Round { round: i64, } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct TimeoutCertificate { epoch: i64, round: Round, signatures: TimestampedECDSASignatures, } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct TimestampedECDSASignature { timestamp: SafetyStateTimestamp, signature: NodeSignature, } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct TimestampedECDSASignatures { node_to_timestamped_signature: BTreeMap, } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct VertexId { id_bytes: Vec, } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct Vote { author: BFTValidatorId, high_quorum_certificate: HighQC, @@ -198,7 +193,7 @@ pub struct Vote { timeout_signature: Option, } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct VoteData { proposed: BFTHeader, parent: BFTHeader, diff --git a/core-rust/p2p/src/traits.rs b/core-rust/p2p/src/traits.rs index ac1136d973..51724b7cfa 100644 --- a/core-rust/p2p/src/traits.rs +++ b/core-rust/p2p/src/traits.rs @@ -62,9 +62,11 @@ * permissions under this License. */ -use crate::engine_prelude::*; +use crate::prelude::*; -pub mod node { +pub use node::*; + +mod node { use super::*; use crate::address_book_components::*; use crate::components::NodeSecp256k1PublicKey; diff --git a/core-rust/p2p/src/typed_cf_api.rs b/core-rust/p2p/src/typed_cf_api.rs index 9bf833e20c..d807b20133 100644 --- a/core-rust/p2p/src/typed_cf_api.rs +++ b/core-rust/p2p/src/typed_cf_api.rs @@ -62,8 +62,7 @@ * permissions under this License. */ -use crate::components::NodeSecp256k1PublicKey; -use node_common::store::typed_cf_api::{BoundedDbCodec, DbCodec}; +use crate::prelude::*; #[derive(Clone, Default)] pub struct RawPublicKeyDbCodec {} diff --git a/core-rust/state-manager/src/accumulator_tree/mod.rs b/core-rust/state-manager/src/accumulator_tree/mod.rs index 994b221e37..db4cac5961 100644 --- a/core-rust/state-manager/src/accumulator_tree/mod.rs +++ b/core-rust/state-manager/src/accumulator_tree/mod.rs @@ -62,12 +62,15 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use tree_builder::Merklizable; +use crate::prelude::*; -pub mod slice_merger; -pub mod storage; -pub mod tree_builder; +mod slice_merger; +mod storage; +mod tree_builder; + +pub use slice_merger::*; +pub use storage::*; +pub use tree_builder::*; #[cfg(test)] mod test; diff --git a/core-rust/state-manager/src/accumulator_tree/storage.rs b/core-rust/state-manager/src/accumulator_tree/storage.rs index 9271da5a5b..6936ed0c6c 100644 --- a/core-rust/state-manager/src/accumulator_tree/storage.rs +++ b/core-rust/state-manager/src/accumulator_tree/storage.rs @@ -90,7 +90,7 @@ impl + WriteableAccuTreeStore, K, N> AccuTr /// A vertical slice of an accumulator tree. /// This is an "incremental" persistence part of a tree representing a batch of appended leaf nodes /// and the resulting merkle updates, propagating up to a single root. -#[derive(Debug, Clone, Eq, PartialEq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, Eq, PartialEq, ScryptoSbor)] #[sbor(categorize_types = "N")] pub struct TreeSlice { /// The tree-levels of this slice, arranged from leaves to root. @@ -122,7 +122,7 @@ impl TreeSlice { /// A single tree-level of a `TreeSlice`. /// Effectively this means that it is a horizontal slice of a corresponding level of an entire /// accumulator tree. -#[derive(Debug, Clone, Eq, PartialEq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, Eq, PartialEq, ScryptoSbor)] #[sbor(categorize_types = "N")] pub struct TreeSliceLevel { /// The cached left sibling of the first node of that level slice, i.e. present if and only if diff --git a/core-rust/state-manager/src/commit_bundle.rs b/core-rust/state-manager/src/commit_bundle.rs index 9a873a6272..94d56fd3ed 100644 --- a/core-rust/state-manager/src/commit_bundle.rs +++ b/core-rust/state-manager/src/commit_bundle.rs @@ -62,16 +62,7 @@ * permissions under this License. */ -use crate::staging::epoch_handling::EpochAwareAccuTreeFactory; - -use crate::store::traits::*; -use crate::transaction::*; - -use crate::*; - -use crate::engine_prelude::*; - -use crate::accumulator_tree::slice_merger::AccuTreeSliceMerger; +use crate::prelude::*; /// A builder of a [`CommitBundle`] from individual transactions and their commit results. pub struct CommitBundleBuilder { @@ -109,7 +100,7 @@ impl CommitBundleBuilder { state_version: StateVersion, proposer_timestamp_ms: i64, raw: RawLedgerTransaction, - validated: ValidatedLedgerTransaction, + hashes: LedgerTransactionHashes, result: ProcessedCommitResult, ) { self.substate_store_update.apply(result.database_updates); @@ -131,7 +122,7 @@ impl CommitBundleBuilder { raw, receipt: result.local_receipt, identifiers: CommittedTransactionIdentifiers { - payload: validated.create_identifiers(), + transaction_hashes: hashes, resultant_ledger_hashes: hash_structures_diff.ledger_hashes, proposer_timestamp_ms, }, diff --git a/core-rust/state-manager/src/committer.rs b/core-rust/state-manager/src/committer.rs index 3b5890533f..fdaf2e9b58 100644 --- a/core-rust/state-manager/src/committer.rs +++ b/core-rust/state-manager/src/committer.rs @@ -62,32 +62,13 @@ * permissions under this License. */ -use crate::mempool_manager::MempoolManager; -use crate::staging::epoch_handling::EpochAwareAccuTreeFactory; -use crate::store::traits::*; -use crate::transaction::*; -use crate::types::CommitRequest; -use crate::*; +use crate::prelude::*; -use crate::engine_prelude::*; - -use node_common::locks::{DbLock, RwLock}; - -use tracing::warn; - -use crate::protocol::*; use crate::system_commits::*; -use crate::accumulator_tree::storage::ReadableAccuTreeStore; - -use crate::store::rocks_db::ActualStateManagerDatabase; -use std::ops::Deref; -use std::sync::Arc; -use std::time::SystemTime; - pub struct Committer { database: Arc>, - ledger_transaction_validator: Arc, + validator: Arc>, transaction_executor_factory: Arc, mempool_manager: Arc, execution_cache_manager: Arc, @@ -101,7 +82,7 @@ impl Committer { pub fn new( database: Arc>, transaction_executor_factory: Arc, - ledger_transaction_validator: Arc, + ledger_transaction_validator: Arc>, mempool_manager: Arc, execution_cache_manager: Arc, pending_transaction_result_cache: Arc>, @@ -110,7 +91,7 @@ impl Committer { ) -> Self { Self { database, - ledger_transaction_validator, + validator: ledger_transaction_validator, transaction_executor_factory, mempool_manager, execution_cache_manager, @@ -153,9 +134,7 @@ impl Committer { .ledger_header .proposer_timestamp_ms; for (index, raw_transaction) in transactions.iter().enumerate() { - let result = self - .ledger_transaction_validator - .prepare_from_raw(raw_transaction); + let result = raw_transaction.prepare(self.validator.read().preparation_settings()); let prepared_transaction = match result { Ok(prepared_transaction) => prepared_transaction, Err(error) => { @@ -167,12 +146,20 @@ impl Committer { } }; - if let PreparedLedgerTransactionInner::RoundUpdateV1(_) = &prepared_transaction.inner { - let round_update = LedgerTransaction::from_raw(raw_transaction) + if let PreparedLedgerTransactionInner::Validator(_) = &prepared_transaction.inner { + let ledger_transaction = LedgerTransaction::from_raw(raw_transaction) .expect("the same transaction was parsed fine above"); - if let LedgerTransaction::RoundUpdateV1(round_update) = round_update { - leader_round_counters_builder.update(&round_update.leader_proposal_history); - proposer_timestamp_ms = round_update.proposer_timestamp_ms; + match ledger_transaction { + LedgerTransaction::RoundUpdateV1(round_update) => { + leader_round_counters_builder.update(&round_update.leader_proposal_history); + proposer_timestamp_ms = round_update.proposer_timestamp_ms; + } + LedgerTransaction::Genesis(_) + | LedgerTransaction::UserV1(_) + | LedgerTransaction::FlashV1(_) + | LedgerTransaction::UserV2(_) => { + panic!("A validator transaction can only be a RoundUpdate") + } } } @@ -224,22 +211,27 @@ impl Committer { .zip(prepared_transactions) .zip(proposer_timestamps) { - let validated = self - .ledger_transaction_validator - .validate_user_or_round_update(prepared) + let validated = prepared + .validate( + self.validator.read().deref(), + AcceptedLedgerTransactionKind::UserOrValidator, + ) .unwrap_or_else(|error| { panic!("cannot validate transaction to be committed: {error:?}"); }); + let hashes = validated.create_hashes(); + let executable = validated.create_ledger_executable(); + let commit = series_executor - .execute_and_update_state(&validated, "prepared") + .execute_and_update_state(&executable, &hashes, "prepared") .expect("cannot execute transaction to be committed"); - if let ValidatedLedgerTransactionInner::UserV1(user_transaction) = &validated.inner { + if let Some(user_hashes) = hashes.as_user() { committed_user_transactions.push(CommittedUserTransactionIdentifiers { state_version: series_executor.latest_state_version(), - intent_hash: user_transaction.intent_hash(), - notarized_transaction_hash: user_transaction.notarized_transaction_hash(), + transaction_intent_hash: user_hashes.transaction_intent_hash, + notarized_transaction_hash: user_hashes.notarized_transaction_hash, }); } transactions_metrics_data.push(TransactionMetricsData::new(&raw, &commit)); @@ -248,7 +240,7 @@ impl Committer { series_executor.latest_state_version(), proposer_timestamp_ms, raw, - validated, + hashes, commit, ); } @@ -278,7 +270,7 @@ impl Committer { self.mempool_manager.remove_committed( committed_user_transactions .iter() - .map(|txn| &txn.intent_hash), + .map(|txn| &txn.transaction_intent_hash), ); if let Some(epoch_change) = epoch_change { @@ -326,9 +318,14 @@ impl Committer { let mut commit_bundle_builder = series_executor.start_commit_builder(); let mut transactions_metrics_data = Vec::new(); - for RawAndValidatedTransaction { raw, validated } in transactions { + for ProcessedLedgerTransaction { + raw, + executable, + hashes, + } in transactions + { let mut commit = series_executor - .execute_and_update_state(&validated, "system transaction") + .execute_and_update_state(&executable, &hashes, "system transaction") .expect("cannot execute system transaction"); if require_committed_successes { commit = commit.expect_success("system transaction not successful"); @@ -339,7 +336,7 @@ impl Committer { series_executor.latest_state_version(), proposer_timestamp_ms, raw, - validated, + hashes, commit, ); } @@ -494,6 +491,6 @@ impl Committer { pub struct CommittedUserTransactionIdentifiers { pub state_version: StateVersion, - pub intent_hash: IntentHash, + pub transaction_intent_hash: TransactionIntentHash, pub notarized_transaction_hash: NotarizedTransactionHash, } diff --git a/core-rust/state-manager/src/jni/db_checkpoints.rs b/core-rust/state-manager/src/jni/db_checkpoints.rs index bdef10d881..5569f83c11 100644 --- a/core-rust/state-manager/src/jni/db_checkpoints.rs +++ b/core-rust/state-manager/src/jni/db_checkpoints.rs @@ -62,14 +62,7 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use jni::objects::{JClass, JObject}; -use jni::sys::jbyteArray; -use jni::JNIEnv; - -use node_common::java::*; - -use super::node_rust_environment::JNINodeRustEnvironment; +use crate::jni_prelude::*; // // JNI Interface diff --git a/core-rust/state-manager/src/jni/fatal_panic_handler.rs b/core-rust/state-manager/src/jni/fatal_panic_handler.rs index f7c05b56fd..77336bb0e9 100644 --- a/core-rust/state-manager/src/jni/fatal_panic_handler.rs +++ b/core-rust/state-manager/src/jni/fatal_panic_handler.rs @@ -62,9 +62,8 @@ * permissions under this License. */ -use jni::errors::Result; -use jni::objects::{GlobalRef, JObject}; -use jni::{JNIEnv, JavaVM}; +use crate::jni_prelude::*; +use jni::{errors::Result, JavaVM}; use std::ops::Deref; use tracing::error; diff --git a/core-rust/state-manager/src/jni/mempool.rs b/core-rust/state-manager/src/jni/mempool.rs index b226f4a919..8a8e25d15d 100644 --- a/core-rust/state-manager/src/jni/mempool.rs +++ b/core-rust/state-manager/src/jni/mempool.rs @@ -62,21 +62,8 @@ * permissions under this License. */ -use std::collections::HashSet; -use std::sync::Arc; +use crate::jni_prelude::*; -use crate::mempool::priority_mempool::MempoolTransaction; - -use jni::objects::{JClass, JObject}; -use jni::sys::jbyteArray; -use jni::JNIEnv; - -use crate::engine_prelude::*; -use crate::mempool::*; -use crate::MempoolAddSource; -use node_common::java::*; - -use super::node_rust_environment::JNINodeRustEnvironment; use super::transaction_preparer::JavaPreparedNotarizedTransaction; // @@ -182,7 +169,7 @@ extern "system" fn Java_com_radixdlt_mempool_RustMempool_reevaluateTransactionCo // DTO Models + Mapping // -#[derive(Debug, Categorize, Encode, Decode)] +#[derive(Debug, Sbor)] pub struct ProposalTransactionsRequest { pub max_count: u32, pub max_payload_size_bytes: u32, @@ -195,14 +182,14 @@ impl From> for JavaPreparedNotarizedTransaction { // to extract the raw payload bytes, to avoid having to clone the full bytes here. Self { notarized_transaction_bytes: value.raw.clone(), - intent_hash: value.intent_hash(), - signed_intent_hash: value.signed_intent_hash(), + intent_hash: value.transaction_intent_hash(), + signed_intent_hash: value.signed_transaction_intent_hash(), notarized_transaction_hash: value.notarized_transaction_hash(), } } } -#[derive(Debug, Categorize, Encode, Decode)] +#[derive(Debug, Sbor)] enum MempoolAddErrorJava { PriorityThresholdNotMet { min_tip_percentage_required: Option, @@ -217,11 +204,11 @@ impl From for MempoolAddErrorJava { fn from(err: MempoolAddError) -> Self { match err { MempoolAddError::PriorityThresholdNotMet { + min_tip_basis_points_required: min_tip_percentage_required, + tip_basis_points: tip_percentage, + } => MempoolAddErrorJava::PriorityThresholdNotMet { min_tip_percentage_required, tip_percentage, - } => MempoolAddErrorJava::PriorityThresholdNotMet { - min_tip_percentage_required: min_tip_percentage_required.map(|x| x as u32), - tip_percentage: tip_percentage as u32, }, MempoolAddError::Duplicate(hash) => MempoolAddErrorJava::Duplicate(hash), MempoolAddError::Rejected(rejection) => { diff --git a/core-rust/state-manager/src/jni/mod.rs b/core-rust/state-manager/src/jni/mod.rs index ccb138dfd9..d089b84bb5 100644 --- a/core-rust/state-manager/src/jni/mod.rs +++ b/core-rust/state-manager/src/jni/mod.rs @@ -83,7 +83,7 @@ use crate::engine_prelude::*; /// proofs GC. /// Please see the Java counterpart (i.e. `record LedgerSyncLimitsConfig`) for detailed descriptions /// of the fields. -#[derive(Debug, Categorize, Encode, Decode, Clone, Default)] +#[derive(Debug, Sbor, Clone, Default)] pub struct LedgerSyncLimitsConfig { pub max_txns_for_responses_spanning_more_than_one_proof: u32, pub max_txn_bytes_for_single_response: u32, diff --git a/core-rust/state-manager/src/jni/node_rust_environment.rs b/core-rust/state-manager/src/jni/node_rust_environment.rs index fb52268a51..e19a3b0c23 100644 --- a/core-rust/state-manager/src/jni/node_rust_environment.rs +++ b/core-rust/state-manager/src/jni/node_rust_environment.rs @@ -64,32 +64,20 @@ use std::ops::Deref; use std::path::{PathBuf, MAIN_SEPARATOR}; use std::str::FromStr; -use std::sync::Arc; -use crate::engine_prelude::*; -use jni::objects::{JClass, JObject}; -use jni::sys::jbyteArray; -use jni::JNIEnv; +use crate::jni_prelude::*; use node_common::environment::setup_tracing; -use node_common::java::{jni_call, jni_jbytearray_to_vector}; -use node_common::locks::*; use prometheus::Registry; use node_common::scheduler::{Scheduler, UntilDropTracker}; use tokio::runtime::Runtime; use tracing::Level; -use crate::mempool_manager::MempoolManager; -use crate::mempool_relay_dispatcher::MempoolRelayDispatcher; -use crate::priority_mempool::PriorityMempool; - use super::fatal_panic_handler::FatalPanicHandler; use crate::protocol::ProtocolManager; use crate::store::rocks_db::ActualStateManagerDatabase; use crate::transaction::Preparator; -use crate::{Committer, DatabaseBackendConfig, LedgerMetrics, SystemExecutor}; -use crate::{StateManager, StateManagerConfig}; use p2p::rocks_db::{ActualAddressBookDatabase, ActualSafetyStoreDatabase}; const POINTER_JNI_FIELD_NAME: &str = "rustNodeRustEnvironmentPointer"; diff --git a/core-rust/state-manager/src/jni/p2p/address_book.rs b/core-rust/state-manager/src/jni/p2p/address_book.rs index 99ac69cbb4..7ba1333048 100644 --- a/core-rust/state-manager/src/jni/p2p/address_book.rs +++ b/core-rust/state-manager/src/jni/p2p/address_book.rs @@ -62,14 +62,9 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use crate::jni::node_rust_environment::JNINodeRustEnvironment; -use jni::objects::{JClass, JObject}; -use jni::sys::jbyteArray; -use jni::JNIEnv; -use node_common::java::*; +use crate::jni_prelude::*; use p2p::address_book_components::{AddressBookEntry, NodeIdDTO}; -use p2p::traits::node::AddressBookStore; +use p2p::traits::AddressBookStore; #[no_mangle] extern "system" fn Java_com_radixdlt_p2p_RocksDbAddressBookStore_removeOne( diff --git a/core-rust/state-manager/src/jni/p2p/high_priority_peers.rs b/core-rust/state-manager/src/jni/p2p/high_priority_peers.rs index f97eada408..944839c5b3 100644 --- a/core-rust/state-manager/src/jni/p2p/high_priority_peers.rs +++ b/core-rust/state-manager/src/jni/p2p/high_priority_peers.rs @@ -62,15 +62,9 @@ * permissions under this License. */ -use jni::objects::{JClass, JObject}; -use jni::sys::jbyteArray; -use jni::JNIEnv; - -use crate::engine_prelude::*; -use crate::jni::node_rust_environment::JNINodeRustEnvironment; -use node_common::java::*; +use crate::jni_prelude::*; use p2p::address_book_components::HighPriorityPeers; -use p2p::traits::node::HighPriorityPeersStore; +use p2p::traits::HighPriorityPeersStore; #[no_mangle] extern "system" fn Java_com_radixdlt_p2p_RocksDbHighPriorityPeersStore_upsertAllHighPriorityPeers( diff --git a/core-rust/state-manager/src/jni/p2p/safety_store.rs b/core-rust/state-manager/src/jni/p2p/safety_store.rs index da1e375192..079b3832f3 100644 --- a/core-rust/state-manager/src/jni/p2p/safety_store.rs +++ b/core-rust/state-manager/src/jni/p2p/safety_store.rs @@ -62,14 +62,9 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use crate::jni::node_rust_environment::JNINodeRustEnvironment; -use jni::objects::{JClass, JObject}; -use jni::sys::jbyteArray; -use jni::JNIEnv; -use node_common::java::*; +use crate::jni_prelude::*; use p2p::safety_store_components::SafetyState; -use p2p::traits::node::SafetyStateStore; +use p2p::traits::SafetyStateStore; #[no_mangle] extern "system" fn Java_com_radixdlt_safety_RocksDbSafetyStore_upsert( diff --git a/core-rust/state-manager/src/jni/prometheus.rs b/core-rust/state-manager/src/jni/prometheus.rs index 5cffd02377..e4f6f22ee3 100644 --- a/core-rust/state-manager/src/jni/prometheus.rs +++ b/core-rust/state-manager/src/jni/prometheus.rs @@ -62,15 +62,9 @@ * permissions under this License. */ -use crate::{LedgerStatus, RecentSelfProposalMissStatistic}; -use jni::objects::{JClass, JObject}; -use jni::sys::jbyteArray; -use jni::JNIEnv; -use node_common::java::jni_sbor_coded_call; +use crate::jni_prelude::*; use prometheus::*; -use super::node_rust_environment::JNINodeRustEnvironment; - #[no_mangle] extern "system" fn Java_com_radixdlt_prometheus_RustPrometheus_prometheusMetrics( env: JNIEnv, diff --git a/core-rust/state-manager/src/jni/protocol_update.rs b/core-rust/state-manager/src/jni/protocol_update.rs index 77e3d2f486..6dd10f27ee 100644 --- a/core-rust/state-manager/src/jni/protocol_update.rs +++ b/core-rust/state-manager/src/jni/protocol_update.rs @@ -62,8 +62,8 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use crate::{protocol::*, ProtocolUpdateResult}; +use crate::jni_prelude::*; +use crate::protocol::*; use jni::objects::{JClass, JObject}; use jni::sys::jbyteArray; use jni::JNIEnv; diff --git a/core-rust/state-manager/src/jni/state_computer.rs b/core-rust/state-manager/src/jni/state_computer.rs index 7a85a80ff0..16ee872a17 100644 --- a/core-rust/state-manager/src/jni/state_computer.rs +++ b/core-rust/state-manager/src/jni/state_computer.rs @@ -62,24 +62,13 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use crate::protocol::ProtocolVersionName; -use crate::{protocol::ProtocolState, CommitSummary, LedgerProof}; -use jni::objects::{JClass, JObject}; -use jni::sys::jbyteArray; -use jni::JNIEnv; - -use node_common::java::*; - -use crate::types::{CommitRequest, InvalidCommitRequestError, PrepareRequest, PrepareResult}; - -use super::node_rust_environment::JNINodeRustEnvironment; +use crate::jni_prelude::*; // // JNI Interface // -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, ScryptoSbor)] pub struct JavaGenesisData { pub initial_epoch: Epoch, pub initial_timestamp_ms: i64, @@ -89,7 +78,7 @@ pub struct JavaGenesisData { pub scenarios_to_run: Vec, } -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, ScryptoSbor)] pub struct JavaConsensusManagerConfig { pub max_validators: u32, pub epoch_min_round_count: u64, diff --git a/core-rust/state-manager/src/jni/state_reader.rs b/core-rust/state-manager/src/jni/state_reader.rs index 957c8432c9..ef8542a766 100644 --- a/core-rust/state-manager/src/jni/state_reader.rs +++ b/core-rust/state-manager/src/jni/state_reader.rs @@ -87,13 +87,13 @@ extern "system" fn Java_com_radixdlt_state_RustStateReader_getValidatorProtocolU request_payload, |validator_address: ComponentAddress| -> JavaResult> { let database = JNINodeRustEnvironment::get_database(&env, j_node_rust_env); - let result = database - .snapshot() - .get_mapped::>( - &validator_address.into_node_id(), - MAIN_BASE_PARTITION, - &ValidatorField::ProtocolUpdateReadinessSignal.into() - ); + let result = database.snapshot().get_substate::>( + validator_address, + MAIN_BASE_PARTITION, + ValidatorField::ProtocolUpdateReadinessSignal, + ); Ok(result.and_then(|f| { f.into_payload() .fully_update_and_into_latest_version() @@ -114,10 +114,10 @@ extern "system" fn Java_com_radixdlt_state_RustStateReader_getConsensusManagerCo let database = JNINodeRustEnvironment::get_database(&env, j_node_rust_env); let substate = database .snapshot() - .get_mapped::( - CONSENSUS_MANAGER.as_node_id(), + .get_substate::( + CONSENSUS_MANAGER, MAIN_BASE_PARTITION, - &ConsensusManagerField::Configuration.into(), + ConsensusManagerField::Configuration, ) .expect("Missing ConsensusManagerConfigurationFieldSubstate"); let consensus_manager_config = substate @@ -142,10 +142,10 @@ extern "system" fn Java_com_radixdlt_state_RustStateReader_getConsensusManagerSt let database = JNINodeRustEnvironment::get_database(&env, j_node_rust_env); let substate = database .snapshot() - .get_mapped::( - CONSENSUS_MANAGER.as_node_id(), + .get_substate::( + CONSENSUS_MANAGER, MAIN_BASE_PARTITION, - &ConsensusManagerField::State.into(), + ConsensusManagerField::State, ) .expect("Missing ConsensusManagerStateFieldSubstate"); let consensus_manager_state = substate diff --git a/core-rust/state-manager/src/jni/test_state_reader.rs b/core-rust/state-manager/src/jni/test_state_reader.rs index 225e434eb4..a95d9b0f9a 100644 --- a/core-rust/state-manager/src/jni/test_state_reader.rs +++ b/core-rust/state-manager/src/jni/test_state_reader.rs @@ -62,29 +62,13 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use crate::{DetailedTransactionOutcome, LedgerTransactionOutcome, StateVersion}; -use jni::objects::{JClass, JObject}; -use jni::sys::jbyteArray; -use jni::JNIEnv; -use std::ops::Deref; - -use crate::jni::node_rust_environment::JNINodeRustEnvironment; -use crate::query::StateManagerSubstateQueries; -use node_common::java::*; - -use crate::store::traits::measurement::MeasurableDatabase; -use crate::store::traits::{ - gc::StateTreeGcStore, IterableProofStore, QueryableProofStore, QueryableTransactionStore, - SubstateNodeAncestryStore, -}; -use crate::transaction::LedgerTransactionHash; +use crate::jni_prelude::*; // // JNI Interface (for test purposes only) // -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, ScryptoSbor)] struct ExecutedTransaction { ledger_transaction_hash: LedgerTransactionHash, outcome: TransactionOutcomeJava, @@ -93,19 +77,19 @@ struct ExecutedTransaction { transaction_bytes: Vec, } -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, ScryptoSbor)] struct TransactionDetails { new_component_addresses: IndexSet, new_resource_addresses: IndexSet, } -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, ScryptoSbor)] pub enum TransactionOutcomeJava { Success, Failure, } -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, ScryptoSbor)] pub struct JavaValidatorInfo { pub stake_unit_resource: ResourceAddress, pub claim_resource: ResourceAddress, @@ -134,7 +118,9 @@ extern "system" fn Java_com_radixdlt_testutil_TestStateReader_getTransactionAtSt database.get_committed_local_transaction_execution(state_version)?; Some(ExecutedTransaction { - ledger_transaction_hash: committed_identifiers.payload.ledger_transaction_hash, + ledger_transaction_hash: committed_identifiers + .transaction_hashes + .ledger_transaction_hash, outcome: match committed_ledger_transaction_receipt.outcome { LedgerTransactionOutcome::Success => TransactionOutcomeJava::Success, LedgerTransactionOutcome::Failure => TransactionOutcomeJava::Failure, @@ -147,7 +133,7 @@ extern "system" fn Java_com_radixdlt_testutil_TestStateReader_getTransactionAtSt &committed_ledger_transaction_receipt.get_consensus_receipt(), ) .unwrap(), - transaction_bytes: committed_transaction.0, + transaction_bytes: committed_transaction.to_vec(), }) }, ) @@ -199,10 +185,10 @@ extern "system" fn Java_com_radixdlt_testutil_TestStateReader_componentXrdAmount // a quick fix for handling virtual accounts if database - .get_mapped::( + .get_substate::( node_id, TYPE_INFO_FIELD_PARTITION, - &TypeInfoField::TypeInfo.into(), + TypeInfoField::TypeInfo, ) .is_some() { @@ -231,10 +217,10 @@ extern "system" fn Java_com_radixdlt_testutil_TestStateReader_validatorInfo( let database = JNINodeRustEnvironment::get_database(&env, j_rust_global_context); let validator_state = database .snapshot() - .get_mapped::( - validator_address.as_node_id(), + .get_substate::( + validator_address, MAIN_BASE_PARTITION, - &ValidatorField::State.into(), + ValidatorField::State, ) .unwrap() .into_payload() diff --git a/core-rust/state-manager/src/jni/transaction_preparer.rs b/core-rust/state-manager/src/jni/transaction_preparer.rs index 80c5acbf90..37c7612702 100644 --- a/core-rust/state-manager/src/jni/transaction_preparer.rs +++ b/core-rust/state-manager/src/jni/transaction_preparer.rs @@ -62,14 +62,9 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use crate::transaction::*; -use jni::objects::JClass; -use jni::sys::jbyteArray; -use jni::JNIEnv; -use node_common::java::*; +use crate::jni_prelude::*; -#[derive(Debug, Clone, PartialEq, Eq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)] struct PrepareIntentRequest { network_definition: NetworkDefinition, header: TransactionHeaderJava, @@ -78,10 +73,10 @@ struct PrepareIntentRequest { message: Option, } -#[derive(Debug, Clone, PartialEq, Eq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)] struct PrepareIntentResponse { intent_bytes: Vec, - intent_hash: IntentHash, + intent_hash: TransactionIntentHash, } #[no_mangle] @@ -111,11 +106,11 @@ extern "system" fn Java_com_radixdlt_transaction_TransactionPreparer_prepareInte .unwrap_or_else(|| MessageV1::None), }; - let prepared_intent = intent.prepare()?; + let prepared_intent = intent.prepare(&PreparationSettings::latest())?; Ok(PrepareIntentResponse { - intent_bytes: intent.to_payload_bytes()?, - intent_hash: prepared_intent.intent_hash(), + intent_bytes: intent.to_raw()?.to_vec(), + intent_hash: prepared_intent.transaction_intent_hash(), }) }, ) @@ -123,7 +118,7 @@ extern "system" fn Java_com_radixdlt_transaction_TransactionPreparer_prepareInte // We use a separate model to ensure that any change to // TransactionHeader is picked up as a compile error, not an SBOR error -#[derive(Debug, Clone, PartialEq, Eq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)] struct TransactionHeaderJava { pub network_id: u8, pub start_epoch_inclusive: u64, @@ -148,37 +143,37 @@ impl From for TransactionHeaderV1 { } } -#[derive(Debug, Clone, PartialEq, Eq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)] enum TransactionMessageJava { Plaintext(PlaintextMessageJava), Encrypted(EncryptedMessageJava), } -#[derive(Debug, Clone, PartialEq, Eq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)] struct PlaintextMessageJava { mime_type: String, content: MessageContentJava, } -#[derive(Debug, Clone, PartialEq, Eq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)] enum MessageContentJava { String(String), Bytes(Vec), } -#[derive(Debug, Clone, PartialEq, Eq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)] struct EncryptedMessageJava { aes_gcm_payload: Vec, curve_decryptor_sets: Vec, } -#[derive(Debug, Clone, PartialEq, Eq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)] struct CurveDecryptorSetJava { dh_ephemeral_public_key: PublicKey, decryptors: Vec, } -#[derive(Debug, Clone, PartialEq, Eq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)] struct DecryptorJava { public_key_fingerprint: Vec, aes_wrapped_key: Vec, @@ -236,17 +231,17 @@ impl From for DecryptorsByCurve { } } -#[derive(Debug, Clone, PartialEq, Eq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)] struct PrepareSignedIntentRequest { - intent_bytes: Vec, + intent_bytes: RawTransactionIntent, signatures: Vec, } -#[derive(Debug, Clone, PartialEq, Eq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)] struct PrepareSignedIntentResponse { - signed_intent_bytes: Vec, - intent_hash: IntentHash, - signed_intent_hash: SignedIntentHash, + signed_intent_bytes: RawSignedTransactionIntent, + intent_hash: TransactionIntentHash, + signed_intent_hash: SignedTransactionIntentHash, } #[no_mangle] @@ -260,7 +255,7 @@ extern "system" fn Java_com_radixdlt_transaction_TransactionPreparer_prepareSign request_payload, |request: PrepareSignedIntentRequest| -> Result { let signed_intent = SignedIntentV1 { - intent: IntentV1::from_payload_bytes(&request.intent_bytes)?, + intent: IntentV1::from_raw(&request.intent_bytes)?, intent_signatures: IntentSignaturesV1 { signatures: request .signatures @@ -270,20 +265,20 @@ extern "system" fn Java_com_radixdlt_transaction_TransactionPreparer_prepareSign }, }; - let prepared_signed_intent = signed_intent.prepare()?; + let prepared_signed_intent = signed_intent.prepare(&PreparationSettings::latest())?; Ok(PrepareSignedIntentResponse { - signed_intent_bytes: signed_intent.to_payload_bytes()?, - intent_hash: prepared_signed_intent.intent_hash(), - signed_intent_hash: prepared_signed_intent.signed_intent_hash(), + signed_intent_bytes: signed_intent.to_raw()?, + intent_hash: prepared_signed_intent.transaction_intent_hash(), + signed_intent_hash: prepared_signed_intent.signed_transaction_intent_hash(), }) }, ) } -#[derive(Debug, Clone, PartialEq, Eq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)] struct PrepareNotarizedTransactionRequest { - signed_intent_bytes: Vec, + signed_intent_bytes: RawSignedTransactionIntent, notary_signature: SignatureV1, } @@ -291,8 +286,8 @@ struct PrepareNotarizedTransactionRequest { #[derive(Debug, Clone, PartialEq, Eq, ScryptoCategorize, ScryptoEncode)] pub struct JavaPreparedNotarizedTransaction { pub notarized_transaction_bytes: RawNotarizedTransaction, - pub intent_hash: IntentHash, - pub signed_intent_hash: SignedIntentHash, + pub intent_hash: TransactionIntentHash, + pub signed_intent_hash: SignedTransactionIntentHash, pub notarized_transaction_hash: NotarizedTransactionHash, } @@ -303,19 +298,19 @@ extern "system" fn Java_com_radixdlt_transaction_TransactionPreparer_prepareNota request_payload: jbyteArray, ) -> jbyteArray { jni_sbor_coded_call(&env, request_payload, |request: PrepareNotarizedTransactionRequest| -> Result { - let signed_intent = SignedIntentV1::from_payload_bytes(&request.signed_intent_bytes)?; + let signed_intent = SignedIntentV1::from_raw(&request.signed_intent_bytes)?; let notarized_transaction = NotarizedTransactionV1 { signed_intent, notary_signature: NotarySignatureV1(request.notary_signature), }; - let prepared = notarized_transaction.prepare()?; + let prepared = notarized_transaction.prepare(&PreparationSettings::latest())?; Ok(JavaPreparedNotarizedTransaction { - notarized_transaction_bytes: RawNotarizedTransaction(notarized_transaction.to_payload_bytes()?), - intent_hash: prepared.intent_hash(), - signed_intent_hash: prepared.signed_intent_hash(), + notarized_transaction_bytes: notarized_transaction.to_raw()?, + intent_hash: prepared.transaction_intent_hash(), + signed_intent_hash: prepared.signed_transaction_intent_hash(), notarized_transaction_hash: prepared.notarized_transaction_hash(), }) }) @@ -331,8 +326,8 @@ extern "system" fn Java_com_radixdlt_transaction_TransactionPreparer_userTransac &env, request_payload, |payload: RawNotarizedTransaction| -> Result { - let notarized_transaction = NotarizedTransactionV1::from_raw(&payload)?; - Ok(LedgerTransaction::UserV1(Box::new(notarized_transaction)).to_raw()?) + let ledger_transaction = LedgerTransaction::from(payload.into_typed()?); + Ok(ledger_transaction.to_raw()?) }, ) } diff --git a/core-rust/state-manager/src/jni/transaction_store.rs b/core-rust/state-manager/src/jni/transaction_store.rs index 1561380fbc..7be504510c 100644 --- a/core-rust/state-manager/src/jni/transaction_store.rs +++ b/core-rust/state-manager/src/jni/transaction_store.rs @@ -62,19 +62,9 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use crate::jni::node_rust_environment::JNINodeRustEnvironment; -use crate::jni::LedgerSyncLimitsConfig; -use crate::protocol::epoch_change_iter; -use crate::store::traits::*; -use crate::{LedgerProof, StateVersion}; -use jni::objects::{JClass, JObject}; -use jni::sys::jbyteArray; -use jni::JNIEnv; -use node_common::java::*; -use std::ops::Deref; +use crate::jni_prelude::*; -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Sbor)] struct TxnsAndProofRequest { start_state_version_inclusive: u64, limits_config: LedgerSyncLimitsConfig, diff --git a/core-rust/state-manager/src/jni/vertex_store_recovery.rs b/core-rust/state-manager/src/jni/vertex_store_recovery.rs index a5b8ca0a47..0260af2435 100644 --- a/core-rust/state-manager/src/jni/vertex_store_recovery.rs +++ b/core-rust/state-manager/src/jni/vertex_store_recovery.rs @@ -62,12 +62,7 @@ * permissions under this License. */ -use crate::jni::node_rust_environment::JNINodeRustEnvironment; -use crate::store::traits::{RecoverableVertexStore, VertexStoreBlobV1, WriteableVertexStore}; -use jni::objects::{JClass, JObject}; -use jni::sys::jbyteArray; -use jni::JNIEnv; -use node_common::java::*; +use crate::jni_prelude::*; #[no_mangle] extern "system" fn Java_com_radixdlt_recovery_VertexStoreRecovery_getVertexStore( diff --git a/core-rust/state-manager/src/lib.rs b/core-rust/state-manager/src/lib.rs index 5786e40818..56b636b61e 100644 --- a/core-rust/state-manager/src/lib.rs +++ b/core-rust/state-manager/src/lib.rs @@ -69,34 +69,56 @@ mod commit_bundle; mod committer; pub mod jni; mod limits; -pub mod mempool; -pub mod metrics; -pub mod protocol; +mod mempool; +mod metrics; +mod protocol; pub mod query; mod receipt; mod staging; -mod state_manager; +pub mod state_manager; pub mod store; -pub mod system_commits; +mod system_commits; mod system_executor; -pub mod transaction; +mod transaction; mod types; #[cfg(test)] mod test; -pub use crate::committer::*; -pub use crate::mempool::*; -pub use crate::metrics::*; -pub use crate::pending_transaction_result_cache::*; -pub use crate::receipt::*; -pub use crate::staging::*; -pub use crate::state_manager::*; -pub use crate::store::*; -pub use crate::system_executor::*; -pub use crate::types::*; +pub mod prelude { + // Other prelude re-exports + pub(crate) use crate::engine_prelude::*; + pub(crate) use node_common::prelude::*; -pub mod engine_prelude { + // Public prelude + pub use crate::mempool::*; + pub use crate::protocol::*; + pub use crate::query::*; + pub use crate::receipt::*; + pub use crate::store::*; + pub use crate::transaction::*; + pub use crate::types::*; + + // Extra items on the internal prelude + pub(crate) use crate::accumulator_tree::*; + pub(crate) use crate::committer::*; + pub(crate) use crate::jni::LedgerSyncLimitsConfig; + pub(crate) use crate::limits::*; + pub(crate) use crate::metrics::*; + pub(crate) use crate::staging::*; + pub(crate) use crate::state_manager::*; + pub(crate) use crate::system_commits::*; + pub(crate) use crate::system_executor::*; +} + +pub mod jni_prelude { + pub use crate::jni::node_rust_environment::*; + pub(crate) use crate::prelude::*; + pub use node_common::jni_prelude::*; +} + +#[allow(unused_imports)] +mod engine_prelude { pub use radix_common::prelude::*; pub use radix_engine::errors::*; diff --git a/core-rust/state-manager/src/limits.rs b/core-rust/state-manager/src/limits.rs index a8fb52481c..7ee8cbd588 100644 --- a/core-rust/state-manager/src/limits.rs +++ b/core-rust/state-manager/src/limits.rs @@ -62,8 +62,7 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use node_common::config::limits::VertexLimitsConfig; +use crate::prelude::*; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum VertexLimitsExceeded { diff --git a/core-rust/state-manager/src/mempool/mempool_manager.rs b/core-rust/state-manager/src/mempool/mempool_manager.rs index 44e4daf683..4c5cbfa98f 100644 --- a/core-rust/state-manager/src/mempool/mempool_manager.rs +++ b/core-rust/state-manager/src/mempool/mempool_manager.rs @@ -62,22 +62,10 @@ * permissions under this License. */ -use super::metrics::MempoolManagerMetrics; -use crate::mempool::priority_mempool::*; -use crate::mempool::*; -use crate::MempoolAddSource; -use node_common::metrics::TakesMetricLabels; -use prometheus::Registry; +use crate::prelude::*; -use std::collections::HashSet; -use std::sync::Arc; use std::time::Instant; -use crate::mempool_relay_dispatcher::MempoolRelayDispatcher; - -use crate::mempool::metrics::MempoolAddResult; -use crate::transaction::{CachedCommittabilityValidator, ForceRecalculation}; -use node_common::locks::RwLock; use tracing::warn; /// A high-level API giving a thread-safe access to the `PriorityMempool`. @@ -94,7 +82,7 @@ impl MempoolManager { mempool: Arc>, relay_dispatcher: MempoolRelayDispatcher, cached_committability_validator: CachedCommittabilityValidator, - metric_registry: &Registry, + metric_registry: &MetricRegistry, ) -> Self { Self { mempool, @@ -108,7 +96,7 @@ impl MempoolManager { pub fn new_for_testing( mempool: Arc>, cached_committability_validator: CachedCommittabilityValidator, - metric_registry: &Registry, + metric_registry: &MetricRegistry, ) -> Self { Self { mempool, @@ -152,7 +140,7 @@ impl MempoolManager { candidate_transactions .into_iter() .filter(|transaction| { - let increased_payload_size = payload_size_so_far + transaction.raw.0.len() as u64; + let increased_payload_size = payload_size_so_far + transaction.raw.len() as u64; let fits = increased_payload_size <= max_payload_size_bytes; if fits { payload_size_so_far = increased_payload_size; @@ -176,7 +164,10 @@ impl MempoolManager { for candidate_transaction in candidate_transactions { // invoking the check automatically removes the transaction when rejected self.cached_committability_validator - .check_for_rejection_validated(&candidate_transaction.transaction.validated); + .check_for_rejection_validated( + &candidate_transaction.transaction.executable, + &candidate_transaction.transaction.hashes, + ); } } @@ -234,11 +225,11 @@ impl MempoolManager { .prepare_from_raw(&raw_transaction) { Ok(prepared) => prepared, - Err(validation_error) => { + Err(prepare_error) => { // If the transaction fails to prepare at this point then we don't even have a hash to assign against it, // so we can't cache anything - just return an error return Err(MempoolAddError::Rejected( - MempoolAddRejection::for_static_rejection(validation_error), + MempoolAddRejection::for_static_rejection(prepare_error.into()), )); } }; @@ -269,20 +260,22 @@ impl MempoolManager { // STEP 4 - We check if the result should mean we add the transaction to our mempool let PendingExecutedTransaction { - transaction, + executable, + user_hashes, latest_attempt_against_state, } = record .should_accept_into_mempool(check_result) .map_err(MempoolAddError::Rejected)?; let mempool_transaction = Arc::new(MempoolTransaction { - validated: transaction, + executable, + hashes: user_hashes, raw: raw_transaction, }); match self.mempool.write().add_transaction_if_not_present( mempool_transaction.clone(), source, - Instant::now(), + StdInstant::now(), latest_attempt_against_state.committed_version(), ) { Ok(_evicted) => Ok(mempool_transaction), @@ -293,7 +286,10 @@ impl MempoolManager { /// Removes all the transactions that have the given intent hashes. /// This method is meant to be called for transactions that were successfully committed - and /// this assumption is important for metric correctness. - pub fn remove_committed<'a>(&self, intent_hashes: impl IntoIterator) { + pub fn remove_committed<'a>( + &self, + intent_hashes: impl IntoIterator, + ) { let mut write_mempool = self.mempool.write(); let removed = intent_hashes .into_iter() diff --git a/core-rust/state-manager/src/mempool/mempool_relay_dispatcher.rs b/core-rust/state-manager/src/mempool/mempool_relay_dispatcher.rs index 516f6cabce..77e2288600 100644 --- a/core-rust/state-manager/src/mempool/mempool_relay_dispatcher.rs +++ b/core-rust/state-manager/src/mempool/mempool_relay_dispatcher.rs @@ -110,7 +110,7 @@ impl MempoolRelayDispatcher { MempoolRelayDispatcher::TRIGGER_METHOD_DESCRIPTOR, &[JValue::Object(JObject::from(jni_slice_to_jbytearray( env, - &transaction.0, + transaction.as_slice(), )))], ); if result.is_err() && env.exception_check()? { diff --git a/core-rust/state-manager/src/mempool/metrics.rs b/core-rust/state-manager/src/mempool/metrics.rs index b6493f4f60..eb5512dc52 100644 --- a/core-rust/state-manager/src/mempool/metrics.rs +++ b/core-rust/state-manager/src/mempool/metrics.rs @@ -62,11 +62,9 @@ * permissions under this License. */ -use node_common::metrics::*; +use crate::prelude::*; use prometheus::*; -use crate::{MempoolAddError, MempoolAddSource, MempoolRejectionReason}; - pub struct MempoolMetrics { pub current_transactions: IntGauge, pub current_total_transactions_size: IntGauge, @@ -104,7 +102,7 @@ impl MempoolMetrics { } impl MempoolManagerMetrics { - pub fn new(registry: &Registry) -> Self { + pub fn new(registry: &MetricRegistry) -> Self { Self { submission_attempt: new_timer_vec( opts( diff --git a/core-rust/state-manager/src/mempool/mod.rs b/core-rust/state-manager/src/mempool/mod.rs index 6e2f349343..5dfc22bcb1 100644 --- a/core-rust/state-manager/src/mempool/mod.rs +++ b/core-rust/state-manager/src/mempool/mod.rs @@ -62,11 +62,19 @@ * permissions under this License. */ -use crate::engine_prelude::*; +use crate::prelude::*; -use std::string::ToString; +mod mempool_manager; +mod mempool_relay_dispatcher; +mod metrics; +mod pending_transaction_result_cache; +mod priority_mempool; -pub use crate::pending_transaction_result_cache::*; +pub use mempool_manager::*; +pub use mempool_relay_dispatcher::*; +pub use metrics::*; +pub use pending_transaction_result_cache::*; +pub use priority_mempool::*; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum MempoolAddSource { @@ -77,8 +85,8 @@ pub enum MempoolAddSource { #[derive(Debug, Clone)] pub enum MempoolAddError { PriorityThresholdNotMet { - min_tip_percentage_required: Option, - tip_percentage: u16, + min_tip_basis_points_required: Option, + tip_basis_points: u32, }, Duplicate(NotarizedTransactionHash), Rejected(MempoolAddRejection), @@ -139,27 +147,22 @@ impl MempoolAddRejection { } } -impl ToString for MempoolAddError { - fn to_string(&self) -> String { +impl Display for MempoolAddError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - MempoolAddError::PriorityThresholdNotMet {min_tip_percentage_required, tip_percentage} => { - match min_tip_percentage_required { - None => { - "Priority Threshold not met. There is no known tip to guarantee mempool submission.".to_string() - } - Some(min_tip_percentage_required) => { - format!("Priority Threshold not met: tip is {tip_percentage} while min tip required {min_tip_percentage_required}") - } + MempoolAddError::PriorityThresholdNotMet { + min_tip_basis_points_required: min_tip_percentage_required, + tip_basis_points: tip_percentage, + } => match min_tip_percentage_required { + None => { + write!(f, "Priority Threshold not met. There is no known tip to guarantee mempool submission.") + } + Some(min_tip_percentage_required) => { + write!(f, "Priority Threshold not met: tip is {tip_percentage} while min tip required {min_tip_percentage_required}") } }, - MempoolAddError::Duplicate(_) => "Duplicate Entry".to_string(), - MempoolAddError::Rejected(rejection) => rejection.reason.to_string(), + MempoolAddError::Duplicate(_) => write!(f, "Duplicate Entry"), + MempoolAddError::Rejected(rejection) => write!(f, "{}", rejection.reason), } } } - -pub mod mempool_manager; -pub mod mempool_relay_dispatcher; -pub mod metrics; -pub mod pending_transaction_result_cache; -pub mod priority_mempool; diff --git a/core-rust/state-manager/src/mempool/pending_transaction_result_cache.rs b/core-rust/state-manager/src/mempool/pending_transaction_result_cache.rs index 1a464bba98..2fe0cb4bf7 100644 --- a/core-rust/state-manager/src/mempool/pending_transaction_result_cache.rs +++ b/core-rust/state-manager/src/mempool/pending_transaction_result_cache.rs @@ -1,19 +1,11 @@ -use crate::engine_prelude::*; -use node_common::locks::RwLock; +use crate::prelude::*; -use crate::{ - transaction::{CheckMetadata, StaticValidation}, - CommittedUserTransactionIdentifiers, MempoolAddRejection, StateVersion, TransactionTreeHash, -}; - -use crate::priority_mempool::PriorityMempool; use lru::LruCache; use std::{ - collections::{hash_map::Entry, HashMap, HashSet}, + collections::hash_map::Entry, fmt, num::NonZeroUsize, ops::Add, - sync::Arc, time::{Duration, SystemTime}, }; @@ -57,8 +49,11 @@ impl MempoolRejectionReason { ExecutionRejectionReason::ErrorBeforeLoanAndDeferredCostsRepaid(_) => false, ExecutionRejectionReason::TransactionEpochNotYetValid { .. } => false, ExecutionRejectionReason::TransactionEpochNoLongerValid { .. } => false, + ExecutionRejectionReason::TransactionProposerTimestampNotYetValid { .. } => false, + ExecutionRejectionReason::TransactionProposerTimestampNoLongerValid { .. } => false, ExecutionRejectionReason::IntentHashPreviouslyCommitted => true, ExecutionRejectionReason::IntentHashPreviouslyCancelled => true, + ExecutionRejectionReason::SubintentsNotYetSupported => false, }, MempoolRejectionReason::ValidationError(_) => false, } @@ -79,24 +74,14 @@ impl MempoolRejectionReason { RejectionPermanence::PermanentForAnyPayloadWithThisIntent } MempoolRejectionReason::FromExecution(rejection_error) => match **rejection_error { - ExecutionRejectionReason::BootloadingError(_) => RejectionPermanence::Temporary { - retry: RetrySettings::AfterDelay { - base_delay: Duration::from_secs(2 * 60), - }, - }, + ExecutionRejectionReason::BootloadingError(_) => { + RejectionPermanence::default_temporary() + } ExecutionRejectionReason::SuccessButFeeLoanNotRepaid => { - RejectionPermanence::Temporary { - retry: RetrySettings::AfterDelay { - base_delay: Duration::from_secs(2 * 60), - }, - } + RejectionPermanence::default_temporary() } ExecutionRejectionReason::ErrorBeforeLoanAndDeferredCostsRepaid(_) => { - RejectionPermanence::Temporary { - retry: RetrySettings::AfterDelay { - base_delay: Duration::from_secs(2 * 60), - }, - } + RejectionPermanence::default_temporary() } ExecutionRejectionReason::TransactionEpochNotYetValid { valid_from, .. } => { RejectionPermanence::Temporary { @@ -106,12 +91,26 @@ impl MempoolRejectionReason { ExecutionRejectionReason::TransactionEpochNoLongerValid { .. } => { RejectionPermanence::PermanentForAnyPayloadWithThisIntent } + ExecutionRejectionReason::TransactionProposerTimestampNotYetValid { + valid_from_inclusive, + .. + } => RejectionPermanence::Temporary { + retry: RetrySettings::FromProposerTimestamp { + proposer_timestamp: valid_from_inclusive, + }, + }, + ExecutionRejectionReason::TransactionProposerTimestampNoLongerValid { .. } => { + RejectionPermanence::PermanentForAnyPayloadWithThisIntent + } ExecutionRejectionReason::IntentHashPreviouslyCommitted => { RejectionPermanence::PermanentForAnyPayloadWithThisIntent } ExecutionRejectionReason::IntentHashPreviouslyCancelled => { RejectionPermanence::PermanentForAnyPayloadWithThisIntent } + ExecutionRejectionReason::SubintentsNotYetSupported => { + RejectionPermanence::wait_for_protocol_update() + } }, MempoolRejectionReason::ValidationError(validation_error) => match validation_error { // The size is a property of the payload, not the intent @@ -135,15 +134,38 @@ impl MempoolRejectionReason { RejectionPermanence::PermanentForAnyPayloadWithThisIntent } // This is permanent for the intent - because all intents share the same manifest - TransactionValidationError::IdValidationError(_) => { + TransactionValidationError::InvalidMessage(_) => { RejectionPermanence::PermanentForAnyPayloadWithThisIntent } - // This is permanent for the intent - because all intents share the same manifest - TransactionValidationError::CallDataValidationError(_) => { + TransactionValidationError::TransactionVersionNotPermitted(_) => { + RejectionPermanence::wait_for_protocol_update() + } + // The manifest validity is a property of the intent + TransactionValidationError::ManifestBasicValidatorError(_) => { RejectionPermanence::PermanentForAnyPayloadWithThisIntent } - // This is permanent for the intent - because all intents share the same manifest - TransactionValidationError::InvalidMessage(_) => { + // The manifest validity is a property of the intent + TransactionValidationError::ManifestValidationError(_) => { + RejectionPermanence::PermanentForAnyPayloadWithThisIntent + } + // The subintent structure is a property of the intent + TransactionValidationError::SubintentError(_) => { + RejectionPermanence::PermanentForAnyPayloadWithThisIntent + } + // Total signature count is a property of the payload, not intent + TransactionValidationError::TooManySignatures { .. } => { + RejectionPermanence::PermanentForPayload + } + // Intent signature count is a property of the payload, not intent + TransactionValidationError::TooManySignaturesForIntent { .. } => { + RejectionPermanence::PermanentForPayload + } + // Total reference count is a property of the intent + TransactionValidationError::TooManyReferences { .. } => { + RejectionPermanence::PermanentForAnyPayloadWithThisIntent + } + // Reference count per intent is a property of the intent + TransactionValidationError::TooManyReferencesForIntent { .. } => { RejectionPermanence::PermanentForAnyPayloadWithThisIntent } }, @@ -159,6 +181,24 @@ pub enum RejectionPermanence { } impl RejectionPermanence { + pub fn wait_for_protocol_update() -> Self { + // For want of something better, let's just wait for 5 minutes + Self::Temporary { + retry: RetrySettings::AfterDelay { + base_delay: Duration::from_secs(5 * 60), + }, + } + } + + pub fn default_temporary() -> Self { + // Wait 2 minutes in case things clear up + Self::Temporary { + retry: RetrySettings::AfterDelay { + base_delay: Duration::from_secs(2 * 60), + }, + } + } + pub fn is_permanent_for_payload(&self) -> bool { match self { RejectionPermanence::PermanentForPayload => true, @@ -180,6 +220,7 @@ impl RejectionPermanence { pub enum RetrySettings { AfterDelay { base_delay: Duration }, FromEpoch { epoch: Epoch }, + FromProposerTimestamp { proposer_timestamp: Instant }, } impl fmt::Display for MempoolRejectionReason { @@ -211,7 +252,7 @@ impl fmt::Display for MempoolRejectionReason { /// the API can distinguish permanent rejections from non-permanent rejections. #[derive(Debug, Clone)] pub struct PendingTransactionRecord { - pub intent_hash: IntentHash, + pub intent_hash: TransactionIntentHash, /// Only needs to be specified if the rejection isn't permanent pub intent_invalid_from_epoch: Option, pub latest_attempt: TransactionAttempt, @@ -301,17 +342,23 @@ pub enum RetryFrom { #[derive(Debug, Clone)] pub struct PendingExecutedTransaction { - pub transaction: Box, + pub executable: ExecutableTransaction, + pub user_hashes: UserTransactionHashes, pub latest_attempt_against_state: AtSpecificState, } impl PendingExecutedTransaction { - pub fn new(transaction: Box, against_state: AtState) -> Self { + pub fn new( + executable: ExecutableTransaction, + user_hashes: UserTransactionHashes, + against_state: AtState, + ) -> Self { let AtState::Specific(latest_attempt_against_state) = against_state else { panic!("transaction must have been executed against some state") }; Self { - transaction, + executable, + user_hashes, latest_attempt_against_state, } } @@ -319,7 +366,7 @@ impl PendingExecutedTransaction { impl PendingTransactionRecord { pub fn new( - intent_hash: IntentHash, + intent_hash: TransactionIntentHash, invalid_from_epoch: Option, attempt: TransactionAttempt, ) -> Self { @@ -383,8 +430,8 @@ impl PendingTransactionRecord { } /// Precondition: - /// * If check = CheckMetadata::Cached, the latest attempt must be a rejection - /// This precondition is met if the record/metadata come from a call using ForceRecalculation::IfCachedAsValid + /// * If `check == CheckMetadata::Cached`, the latest attempt must be a rejection. + /// This precondition is met if the record/metadata come from a call using `ForceRecalculation::IfCachedAsValid` pub fn should_accept_into_mempool( self, check: CheckMetadata, @@ -413,9 +460,14 @@ impl PendingTransactionRecord { CheckMetadata::Cached => { panic!("Precondition was not met - the result was cached, but the latest attempt was not a rejection") } - CheckMetadata::Fresh(StaticValidation::Valid(transaction)) => Ok( - PendingExecutedTransaction::new(transaction, self.latest_attempt.against_state), - ), + CheckMetadata::Fresh(StaticValidation::Valid { + executable, + user_hashes, + }) => Ok(PendingExecutedTransaction::new( + executable, + user_hashes, + self.latest_attempt.against_state, + )), CheckMetadata::Fresh(StaticValidation::Invalid) => { panic!("A statically invalid transaction should already have been handled in the above") } @@ -460,7 +512,30 @@ impl PendingTransactionRecord { RetryFrom::FromTime(attempt.timestamp.add(delay)) } - _ => { + RejectionPermanence::Temporary { + retry: + RetrySettings::FromProposerTimestamp { + proposer_timestamp: + Instant { + seconds_since_unix_epoch, + }, + }, + } => { + u64::try_from(seconds_since_unix_epoch) + .ok() + // Add one more second so we don't risk retrying before the timestamp on ledger has updated + .and_then(|seconds_since_unix_epoch| { + seconds_since_unix_epoch.checked_add(1) + }) + .and_then(|retry_in_seconds| { + SystemTime::UNIX_EPOCH + .checked_add(Duration::from_secs(retry_in_seconds)) + }) + .map(RetryFrom::FromTime) + .unwrap_or(RetryFrom::Never) + } + RejectionPermanence::PermanentForPayload + | RejectionPermanence::PermanentForAnyPayloadWithThisIntent => { // If RejectionPermanence was Permanent, this has already been handled return; } @@ -485,8 +560,8 @@ const MAX_RECALCULATION_DELAY: Duration = Duration::from_secs(1000); pub struct PendingTransactionResultCache { mempool: Arc>, pending_transaction_records: LruCache, - intent_lookup: HashMap>, - recently_committed_intents: LruCache, + intent_lookup: HashMap>, + recently_committed_intents: LruCache, } impl PendingTransactionResultCache { @@ -510,7 +585,7 @@ impl PendingTransactionResultCache { /// Note - the invalid_from_epoch only needs to be provided if the attempt is not a permanent rejection pub fn track_transaction_result( &mut self, - intent_hash: IntentHash, + intent_hash: TransactionIntentHash, notarized_transaction_hash: NotarizedTransactionHash, invalid_from_epoch: Option, attempt: TransactionAttempt, @@ -549,7 +624,7 @@ impl PendingTransactionResultCache { committed_transactions: Vec, ) { for committed_transaction in committed_transactions { - let committed_intent_hash = committed_transaction.intent_hash; + let committed_intent_hash = committed_transaction.transaction_intent_hash; let committed_notarized_transaction_hash = committed_transaction.notarized_transaction_hash; // Note - we keep the relevant statuses of all known payloads for the intent in the cache @@ -592,7 +667,7 @@ impl PendingTransactionResultCache { pub fn get_pending_transaction_record( &mut self, - intent_hash: &IntentHash, + intent_hash: &TransactionIntentHash, notarized_transaction_hash: &NotarizedTransactionHash, ) -> Option { if let Some(x) = self @@ -629,7 +704,7 @@ impl PendingTransactionResultCache { pub fn peek_all_known_payloads_for_intent( &self, - intent_hash: &IntentHash, + intent_hash: &TransactionIntentHash, ) -> HashMap { match self.intent_lookup.get(intent_hash) { Some(payload_hashes) => payload_hashes @@ -648,7 +723,7 @@ impl PendingTransactionResultCache { fn handled_added( &mut self, - intent_hash: IntentHash, + intent_hash: TransactionIntentHash, notarized_transaction_hash: NotarizedTransactionHash, ) { // Add the intent hash <-> payload hash lookup @@ -704,8 +779,8 @@ mod tests { NotarizedTransactionHash::from(blake2b_256_hash([0, nonce])) } - fn intent_hash(nonce: u8) -> IntentHash { - IntentHash::from(blake2b_256_hash([1, nonce])) + fn intent_hash(nonce: u8) -> TransactionIntentHash { + TransactionIntentHash::from(blake2b_256_hash([1, nonce])) } #[test] @@ -874,7 +949,7 @@ mod tests { now, vec![CommittedUserTransactionIdentifiers { state_version: StateVersion::of(1), - intent_hash: intent_hash_1, + transaction_intent_hash: intent_hash_1, notarized_transaction_hash: payload_hash_1, }], ); diff --git a/core-rust/state-manager/src/mempool/priority_mempool.rs b/core-rust/state-manager/src/mempool/priority_mempool.rs index 468b19e731..6f36e38b33 100644 --- a/core-rust/state-manager/src/mempool/priority_mempool.rs +++ b/core-rust/state-manager/src/mempool/priority_mempool.rs @@ -62,21 +62,13 @@ * permissions under this License. */ -use node_common::config::MempoolConfig; -use node_common::metrics::TakesMetricLabels; -use prometheus::Registry; +use crate::prelude::*; use rand::seq::index::sample; -use tracing::warn; - -use crate::{mempool::*, StateVersion}; use std::cmp::{max, min, Ordering}; -use std::collections::{HashMap, HashSet}; use node_common::indexing::SecondaryIndex; use std::ops::Index; -use std::sync::Arc; -use std::time::Instant; use super::metrics::MempoolMetrics; @@ -95,7 +87,7 @@ pub struct MempoolData { /// it as part of mempool operations. pub transaction: Arc, /// The instant at which the transaction was added to the mempool. - pub added_at: Instant, + pub added_at: StdInstant, /// The source of the transaction. pub source: MempoolAddSource, /// The state version of this transaction's last successful execution. @@ -104,54 +96,46 @@ pub struct MempoolData { #[derive(Debug, Clone, Eq, PartialEq)] // (`Eq` for tests only) pub struct MempoolTransaction { - pub validated: Box, + pub executable: ExecutableTransaction, + pub hashes: UserTransactionHashes, pub raw: RawNotarizedTransaction, } impl MempoolTransaction { - pub fn tip_percentage(&self) -> u16 { - self.validated - .prepared - .signed_intent - .intent - .header - .inner - .tip_percentage + pub fn tip_basis_points(&self) -> u32 { + self.executable.costing_parameters().tip.basis_points() } pub fn end_epoch_exclusive(&self) -> Epoch { - self.validated - .prepared - .signed_intent - .intent - .header - .inner + self.executable + .overall_epoch_range() + .expect("User tranasctions must have an epoch validity range") .end_epoch_exclusive } } -impl HasIntentHash for MempoolTransaction { - fn intent_hash(&self) -> IntentHash { - self.validated.prepared.intent_hash() +impl HasTransactionIntentHash for MempoolTransaction { + fn transaction_intent_hash(&self) -> TransactionIntentHash { + self.hashes.transaction_intent_hash } } -impl HasSignedIntentHash for MempoolTransaction { - fn signed_intent_hash(&self) -> SignedIntentHash { - self.validated.prepared.signed_intent_hash() +impl HasSignedTransactionIntentHash for MempoolTransaction { + fn signed_transaction_intent_hash(&self) -> SignedTransactionIntentHash { + self.hashes.signed_transaction_intent_hash } } impl HasNotarizedTransactionHash for MempoolTransaction { fn notarized_transaction_hash(&self) -> NotarizedTransactionHash { - self.validated.prepared.notarized_transaction_hash() + self.hashes.notarized_transaction_hash } } impl MempoolData { fn new( transaction: Arc, - added_at: Instant, + added_at: StdInstant, source: MempoolAddSource, successfully_executed_at: StateVersion, ) -> Self { @@ -166,18 +150,18 @@ impl MempoolData { /// A transaction's proposal priority. /// -/// The greatest element (i.e. the one with the *highest* `tip_percentage`, and then the *oldest* -/// `added_at`) marks the "best" transaction (i.e. the one to be executed first). +/// The greatest element (i.e. the one with the *highest* [`tip_basis_points`][Self::tip_basis_points], +/// and then the *oldest* `added_at`) marks the "best" transaction (i.e. the one to be executed first). #[derive(Clone, Eq, PartialEq)] struct ProposalPriority { - tip_percentage: u16, - added_at: Instant, + tip_basis_points: u32, + added_at: StdInstant, } impl Ord for ProposalPriority { fn cmp(&self, other: &Self) -> Ordering { - self.tip_percentage - .cmp(&other.tip_percentage) + self.tip_basis_points + .cmp(&other.tip_basis_points) // Note: the `reverse()` below is deliberate; this is why we cannot do `#[derive(Ord)]` .then_with(|| self.added_at.cmp(&other.added_at).reverse()) } @@ -192,7 +176,7 @@ impl PartialOrd for ProposalPriority { impl ProposalPriority { pub fn new(mempool_data: &MempoolData) -> Self { Self { - tip_percentage: mempool_data.transaction.tip_percentage(), + tip_basis_points: mempool_data.transaction.tip_basis_points(), added_at: mempool_data.added_at, } } @@ -226,8 +210,8 @@ pub struct PriorityMempool { /// Mapping from [`NotarizedTransactionHash`] to [`MempoolData`] containing [`MempoolTransaction`] with said payload hash. /// We use [`IndexMap`] for it's O(1) [`get_index`] needed for efficient random sampling. data: IndexMap, - /// Mapping from [`IntentHash`] to all transactions ([`NotarizedTransactionHash`]) that submit said intent. - intent_lookup: HashMap>, + /// Mapping from [`TransactionIntentHash`] to all transactions ([`NotarizedTransactionHash`]) that submit said intent. + intent_lookup: HashMap>, /// Keeps ordering of the transactions by their [`ProposalPriority`]. proposal_priority_index: SecondaryIndex, /// Keeps ordering of the transactions by their validity end epoch. @@ -239,7 +223,7 @@ pub struct PriorityMempool { } impl PriorityMempool { - pub fn new(config: MempoolConfig, metric_registry: &Registry) -> PriorityMempool { + pub fn new(config: MempoolConfig, metric_registry: &MetricRegistry) -> PriorityMempool { PriorityMempool { remaining_transaction_count: config.max_transaction_count, remaining_total_transactions_size: config.max_total_transactions_size, @@ -262,7 +246,7 @@ impl PriorityMempool { &mut self, transaction: Arc, source: MempoolAddSource, - added_at: Instant, + added_at: StdInstant, executed_at: StateVersion, ) -> Result, MempoolAddError> { let notarized_transaction_hash = transaction.notarized_transaction_hash(); @@ -271,8 +255,8 @@ impl PriorityMempool { return Ok(vec![]); } - let intent_hash = transaction.intent_hash(); - let transaction_size = transaction.raw.0.len() as u64; + let intent_hash = transaction.transaction_intent_hash(); + let transaction_size = transaction.raw.len() as u64; let transaction_data = MempoolData::new(transaction, added_at, source, executed_at); let new_proposal_priority = ProposalPriority::new(&transaction_data); @@ -298,13 +282,12 @@ impl PriorityMempool { // Even with an empty mempool we are not able to fulfill the request. warn!("Impossible to add new transaction. Mempool max size lower than transaction size!"); return Err(MempoolAddError::PriorityThresholdNotMet { - min_tip_percentage_required: None, - tip_percentage: transaction_data.transaction.tip_percentage(), + min_tip_basis_points_required: None, + tip_basis_points: transaction_data.transaction.tip_basis_points(), }); } Some(mempool_data) => { - total_transaction_size_free_space += - mempool_data.transaction.raw.0.len() as u64; + total_transaction_size_free_space += mempool_data.transaction.raw.len() as u64; total_transaction_count_free_space += 1; to_be_removed.push(mempool_data.clone()); } @@ -318,11 +301,11 @@ impl PriorityMempool { if new_proposal_priority < ProposalPriority::new(best_to_be_removed) { let min_tip_percentage_required = best_to_be_removed .transaction - .tip_percentage() + .tip_basis_points() .checked_add(1); return Err(MempoolAddError::PriorityThresholdNotMet { - min_tip_percentage_required, - tip_percentage: transaction_data.transaction.tip_percentage(), + min_tip_basis_points_required: min_tip_percentage_required, + tip_basis_points: transaction_data.transaction.tip_basis_points(), }); } } @@ -399,7 +382,10 @@ impl PriorityMempool { } } - pub fn remove_by_intent_hash(&mut self, intent_hash: &IntentHash) -> Vec { + pub fn remove_by_intent_hash( + &mut self, + intent_hash: &TransactionIntentHash, + ) -> Vec { let data: Vec<_> = self .intent_lookup .get(intent_hash) @@ -409,9 +395,8 @@ impl PriorityMempool { .cloned() .collect(); data.into_iter() - .map(|data| { + .inspect(|data| { self.remove_data(data.clone()); - data }) .collect() } @@ -439,7 +424,7 @@ impl PriorityMempool { pub fn get_notarized_transaction_hashes_for_intent( &self, - intent_hash: &IntentHash, + intent_hash: &TransactionIntentHash, ) -> Vec { match self.intent_lookup.get(intent_hash) { Some(notarized_transaction_hashes) => { @@ -451,7 +436,7 @@ impl PriorityMempool { pub fn all_hashes_iter( &self, - ) -> impl Iterator { + ) -> impl Iterator { self.intent_lookup .iter() .flat_map(|(intent_hash, notarized_transaction_hashes)| { @@ -509,7 +494,7 @@ impl PriorityMempool { .take(max_transactions_to_try) .map(|hash| self.data.index(hash).transaction.clone()) .filter(|transaction| { - let increased_payload_size = payload_size_so_far + transaction.raw.0.len() as u64; + let increased_payload_size = payload_size_so_far + transaction.raw.len() as u64; let fits = increased_payload_size <= max_payload_size_bytes; if fits { payload_size_so_far = increased_payload_size; @@ -527,9 +512,9 @@ impl PriorityMempool { /// Note: assumes that the given transaction is currently in the mempool. fn remove_data(&mut self, data: MempoolData) { let notarized_transaction_hash = &data.transaction.notarized_transaction_hash(); - let intent_hash = &data.transaction.intent_hash(); + let intent_hash = &data.transaction.transaction_intent_hash(); - let transaction_size = data.transaction.raw.0.len(); + let transaction_size = data.transaction.raw.len(); self.remaining_transaction_count += 1; self.remaining_total_transactions_size += transaction_size as u64; @@ -601,81 +586,49 @@ mod tests { use crate::mempool::priority_mempool::*; - fn create_fake_pub_key() -> PublicKey { - PublicKey::Secp256k1(Secp256k1PublicKey([0; Secp256k1PublicKey::LENGTH])) - } - - fn create_fake_signature() -> NotarySignatureV1 { - NotarySignatureV1(SignatureV1::Secp256k1(Secp256k1Signature( - [0; Secp256k1Signature::LENGTH], - ))) - } - - fn create_fake_signature_with_public_key() -> IntentSignatureV1 { - IntentSignatureV1(SignatureWithPublicKeyV1::Secp256k1 { - signature: Secp256k1Signature([0; Secp256k1Signature::LENGTH]), - }) - } - - fn create_fake_notarized_transaction( - nonce: u32, - sigs_count: usize, - tip_percentage: u16, - ) -> PreparedNotarizedTransactionV1 { - NotarizedTransactionV1 { - signed_intent: SignedIntentV1 { - intent: IntentV1 { - header: TransactionHeaderV1 { - network_id: 1, - start_epoch_inclusive: Epoch::of(1), - end_epoch_exclusive: Epoch::of(2), - nonce, - notary_public_key: create_fake_pub_key(), - notary_is_signatory: false, - tip_percentage, - }, - instructions: InstructionsV1(vec![]), - blobs: BlobsV1 { blobs: vec![] }, - message: MessageV1::None, - }, - intent_signatures: IntentSignaturesV1 { - signatures: vec![0; sigs_count] - .into_iter() - .map(|_| create_fake_signature_with_public_key()) - .collect(), - }, - }, - notary_signature: create_fake_signature(), - } - .prepare() - .expect("Expected that it could be prepared") - } - - fn create_fake_pending_transaction( - nonce: u32, - sigs_count: usize, + fn create_mempool_transaction( + intent_discriminator: u32, + signer_discriminator: u64, tip_percentage: u16, ) -> Arc { + let notary = Ed25519PrivateKey::from_u64(999).unwrap(); + let raw = TransactionV1Builder::new() + .header(TransactionHeaderV1 { + network_id: 1, + start_epoch_inclusive: Epoch::of(1), + end_epoch_exclusive: Epoch::of(2), + nonce: intent_discriminator, + notary_public_key: notary.public_key().into(), + notary_is_signatory: false, + tip_percentage, + }) + .manifest(ManifestBuilder::new_v1().build()) + .sign(&Ed25519PrivateKey::from_u64(signer_discriminator).unwrap()) + .notarize(¬ary) + .build() + .to_raw() + .unwrap(); + let validated = raw + .validate(&TransactionValidator::new_with_latest_config_network_agnostic()) + .unwrap(); + let hashes = validated.hashes(); + let executable = validated.create_executable(); + Arc::new(MempoolTransaction { - validated: Box::new(ValidatedNotarizedTransactionV1 { - prepared: create_fake_notarized_transaction(nonce, sigs_count, tip_percentage), - // Fake these - encoded_instructions: vec![], - signer_keys: vec![], - num_of_signature_validations: 0, - }), - raw: RawNotarizedTransaction(vec![]), + executable, + hashes, + raw, }) } #[test] fn add_and_get_test() { - let mt1 = create_fake_pending_transaction(1, 0, 0); - let mt2 = create_fake_pending_transaction(2, 0, 0); - let mt3 = create_fake_pending_transaction(3, 0, 0); + let mt1 = create_mempool_transaction(1, 0, 0); + let mt2 = create_mempool_transaction(2, 0, 0); + let mt3 = create_mempool_transaction(3, 0, 0); let v1 = StateVersion::of(1); - let registry = Registry::new(); + let registry = MetricRegistry::new(); let mut mp = PriorityMempool::new( MempoolConfig { @@ -690,7 +643,7 @@ mod tests { mp.add_transaction_if_not_present( mt1.clone(), MempoolAddSource::CoreApi, - Instant::now(), + StdInstant::now(), v1, ) .unwrap(); @@ -701,7 +654,7 @@ mod tests { mp.add_transaction_if_not_present( mt2.clone(), MempoolAddSource::MempoolSync, - Instant::now(), + StdInstant::now(), v1, ) .unwrap(); @@ -710,14 +663,14 @@ mod tests { assert!(mp.contains_transaction(&mt1.notarized_transaction_hash())); assert!(mp.contains_transaction(&mt2.notarized_transaction_hash())); - let rem = mp.remove_by_intent_hash(&mt1.intent_hash()); + let rem = mp.remove_by_intent_hash(&mt1.transaction_intent_hash()); assert!(rem.iter().any(|d| d.transaction == mt1)); assert_eq!(rem.len(), 1); assert_eq!(mp.get_count(), 1); assert!(mp.data.contains_key(&mt2.notarized_transaction_hash())); assert!(!mp.data.contains_key(&mt1.notarized_transaction_hash())); - let rem = mp.remove_by_intent_hash(&mt2.intent_hash()); + let rem = mp.remove_by_intent_hash(&mt2.transaction_intent_hash()); assert!(rem.iter().any(|d| d.transaction == mt2)); assert_eq!(rem.len(), 1); assert_eq!(mp.get_count(), 0); @@ -725,21 +678,27 @@ mod tests { assert!(!mp.data.contains_key(&mt1.notarized_transaction_hash())); // mempool is empty. Should return no transactions. - assert!(mp.remove_by_intent_hash(&mt3.intent_hash()).is_empty()); - assert!(mp.remove_by_intent_hash(&mt2.intent_hash()).is_empty()); - assert!(mp.remove_by_intent_hash(&mt1.intent_hash()).is_empty()); + assert!(mp + .remove_by_intent_hash(&mt3.transaction_intent_hash()) + .is_empty()); + assert!(mp + .remove_by_intent_hash(&mt2.transaction_intent_hash()) + .is_empty()); + assert!(mp + .remove_by_intent_hash(&mt1.transaction_intent_hash()) + .is_empty()); } #[test] fn test_intent_lookup() { - let intent_1_payload_1 = create_fake_pending_transaction(1, 1, 0); - let intent_1_payload_2 = create_fake_pending_transaction(1, 2, 0); - let intent_1_payload_3 = create_fake_pending_transaction(1, 3, 0); - let intent_2_payload_1 = create_fake_pending_transaction(2, 1, 0); - let intent_2_payload_2 = create_fake_pending_transaction(2, 2, 0); + let intent_1_payload_1 = create_mempool_transaction(1, 1, 0); + let intent_1_payload_2 = create_mempool_transaction(1, 2, 0); + let intent_1_payload_3 = create_mempool_transaction(1, 3, 0); + let intent_2_payload_1 = create_mempool_transaction(2, 1, 0); + let intent_2_payload_2 = create_mempool_transaction(2, 2, 0); let v1 = StateVersion::of(1); - let registry = Registry::new(); + let registry = MetricRegistry::new(); let mut mp = PriorityMempool::new( MempoolConfig { @@ -752,7 +711,7 @@ mod tests { .add_transaction_if_not_present( intent_1_payload_1.clone(), MempoolAddSource::CoreApi, - Instant::now(), + StdInstant::now(), v1 ) .unwrap() @@ -761,7 +720,7 @@ mod tests { .add_transaction_if_not_present( intent_1_payload_2.clone(), MempoolAddSource::CoreApi, - Instant::now(), + StdInstant::now(), v1 ) .unwrap() @@ -770,7 +729,7 @@ mod tests { .add_transaction_if_not_present( intent_1_payload_3, MempoolAddSource::MempoolSync, - Instant::now(), + StdInstant::now(), v1 ) .unwrap() @@ -779,7 +738,7 @@ mod tests { .add_transaction_if_not_present( intent_2_payload_1.clone(), MempoolAddSource::CoreApi, - Instant::now(), + StdInstant::now(), v1 ) .unwrap() @@ -787,51 +746,63 @@ mod tests { assert_eq!(mp.get_count(), 4); assert_eq!( - mp.get_notarized_transaction_hashes_for_intent(&intent_2_payload_1.intent_hash()) - .len(), + mp.get_notarized_transaction_hashes_for_intent( + &intent_2_payload_1.transaction_intent_hash() + ) + .len(), 1 ); assert_eq!( - mp.get_notarized_transaction_hashes_for_intent(&intent_1_payload_1.intent_hash()) - .len(), + mp.get_notarized_transaction_hashes_for_intent( + &intent_1_payload_1.transaction_intent_hash() + ) + .len(), 3 ); mp.remove_by_notarized_transaction_hash(&intent_1_payload_2.notarized_transaction_hash()); assert_eq!( - mp.get_notarized_transaction_hashes_for_intent(&intent_1_payload_1.intent_hash()) - .len(), + mp.get_notarized_transaction_hashes_for_intent( + &intent_1_payload_1.transaction_intent_hash() + ) + .len(), 2 ); let removed_data = mp .remove_by_notarized_transaction_hash(&intent_2_payload_2.notarized_transaction_hash()); assert!(removed_data.is_none()); assert_eq!( - mp.get_notarized_transaction_hashes_for_intent(&intent_2_payload_2.intent_hash()) - .len(), + mp.get_notarized_transaction_hashes_for_intent( + &intent_2_payload_2.transaction_intent_hash() + ) + .len(), 1 ); let removed_data = mp .remove_by_notarized_transaction_hash(&intent_2_payload_1.notarized_transaction_hash()); assert!(removed_data.is_some()); assert_eq!( - mp.get_notarized_transaction_hashes_for_intent(&intent_2_payload_2.intent_hash()) - .len(), + mp.get_notarized_transaction_hashes_for_intent( + &intent_2_payload_2.transaction_intent_hash() + ) + .len(), 0 ); assert!(mp .add_transaction_if_not_present( intent_2_payload_1, MempoolAddSource::MempoolSync, - Instant::now(), + StdInstant::now(), v1 ) .unwrap() .is_empty()); - mp.remove_by_intent_hash(&intent_1_payload_2.intent_hash()); + mp.remove_by_intent_hash(&intent_1_payload_2.transaction_intent_hash()); assert_eq!( - mp.get_notarized_transaction_hashes_for_intent(&intent_1_payload_1.intent_hash()) - .len(), + mp.get_notarized_transaction_hashes_for_intent( + &intent_1_payload_1.transaction_intent_hash() + ) + .len(), 0 ); @@ -839,26 +810,28 @@ mod tests { .add_transaction_if_not_present( intent_2_payload_2.clone(), MempoolAddSource::CoreApi, - Instant::now(), + StdInstant::now(), v1 ) .unwrap() .is_empty()); assert_eq!( - mp.get_notarized_transaction_hashes_for_intent(&intent_2_payload_2.intent_hash()) - .len(), + mp.get_notarized_transaction_hashes_for_intent( + &intent_2_payload_2.transaction_intent_hash() + ) + .len(), 2 ); - mp.remove_by_intent_hash(&intent_2_payload_2.intent_hash()); + mp.remove_by_intent_hash(&intent_2_payload_2.transaction_intent_hash()); assert_eq!(mp.get_count(), 0); } #[test] fn test_proposal_priority_ordering() { - let mt1 = create_fake_pending_transaction(1, 0, 10); - let mt2 = create_fake_pending_transaction(2, 0, 20); + let mt1 = create_mempool_transaction(1, 0, 10); + let mt2 = create_mempool_transaction(2, 0, 20); - let now = Instant::now(); + let now = StdInstant::now(); let time_point = [now + Duration::from_secs(1), now + Duration::from_secs(2)]; let md1 = MempoolData::new( @@ -892,17 +865,17 @@ mod tests { #[test] fn test_proposal_priority_add_eviction() { - let mt1 = create_fake_pending_transaction(1, 0, 10); - let mt2 = create_fake_pending_transaction(1, 0, 20); - let mt3 = create_fake_pending_transaction(2, 0, 20); - let mt4 = create_fake_pending_transaction(1, 0, 30); - let mt5 = create_fake_pending_transaction(1, 0, 40); - let mt6 = create_fake_pending_transaction(2, 0, 40); - let mt7 = create_fake_pending_transaction(3, 0, 40); - let mt8 = create_fake_pending_transaction(4, 0, 40); - let mt9 = create_fake_pending_transaction(5, 0, 40); - - let now = Instant::now(); + let mt1 = create_mempool_transaction(1, 0, 10); + let mt2 = create_mempool_transaction(1, 0, 20); + let mt3 = create_mempool_transaction(2, 0, 20); + let mt4 = create_mempool_transaction(1, 0, 30); + let mt5 = create_mempool_transaction(1, 0, 40); + let mt6 = create_mempool_transaction(2, 0, 40); + let mt7 = create_mempool_transaction(3, 0, 40); + let mt8 = create_mempool_transaction(4, 0, 40); + let mt9 = create_mempool_transaction(5, 0, 40); + + let now = StdInstant::now(); let v1 = StateVersion::of(1); let time_point = [ now + Duration::from_secs(1), @@ -910,7 +883,7 @@ mod tests { now + Duration::from_secs(3), ]; - let registry = Registry::new(); + let registry = MetricRegistry::new(); let mut mp = PriorityMempool::new( MempoolConfig { @@ -989,12 +962,12 @@ mod tests { #[test] fn test_duplicate_txn_not_inserted() { - let mempool_txn = create_fake_pending_transaction(1, 0, 10); + let mempool_txn = create_mempool_transaction(1, 0, 10); - let now = Instant::now(); + let now = StdInstant::now(); let v1 = StateVersion::of(1); - let registry = Registry::new(); + let registry = MetricRegistry::new(); let mut mempool = PriorityMempool::new( MempoolConfig { diff --git a/core-rust/state-manager/src/metrics.rs b/core-rust/state-manager/src/metrics.rs index f1cdbc5e35..06665ff62d 100644 --- a/core-rust/state-manager/src/metrics.rs +++ b/core-rust/state-manager/src/metrics.rs @@ -62,27 +62,14 @@ * permissions under this License. */ -use std::cmp::min; +use crate::prelude::*; -use std::time::{SystemTime, UNIX_EPOCH}; +use std::time::UNIX_EPOCH; -use crate::limits::VertexLimitsExceeded; -use crate::transaction::{LeaderRoundCounter, RawLedgerTransaction}; -use crate::{ProcessedCommitResult, StateVersion, ValidatorId}; -use node_common::config::limits::*; -use node_common::locks::{LockFactory, Mutex}; -use node_common::metrics::*; use prometheus::{ Gauge, GaugeVec, Histogram, IntCounter, IntCounterVec, IntGauge, IntGaugeVec, Opts, Registry, }; -use crate::engine_prelude::*; -use crate::protocol::{ - PendingProtocolUpdateState, ProtocolState, ProtocolUpdateEnactmentCondition, -}; -use crate::store::traits::measurement::CategoryDbVolumeStatistic; -use crate::store::traits::QueryableProofStore; - pub struct LedgerMetrics { address_encoder: AddressBech32Encoder, // for label rendering only pub state_version: IntGauge, @@ -150,7 +137,7 @@ impl LedgerMetrics { "committed_transactions_size", "Size in bytes of committed transactions.", ), - higher_resolution_for_lower_values_buckets_for_limit(MAX_TRANSACTION_SIZE), + higher_resolution_for_lower_values_buckets_for_limit(PreparationSettings::latest().max_ledger_payload_length), ) .registered_at(registry), execution_cost_units_consumed: new_histogram( @@ -324,7 +311,7 @@ pub struct TransactionMetricsData { impl TransactionMetricsData { pub fn new(raw: &RawLedgerTransaction, commit_result: &ProcessedCommitResult) -> Self { TransactionMetricsData { - size: raw.0.len(), + size: raw.len(), fee_summary: commit_result .local_receipt .local_execution @@ -889,18 +876,22 @@ impl OverallLedgerHealthFactor { } /// Calculates the current value of the overall ledger health factor. + /// /// This is a proper fraction representation, where: /// - 0.0 means "critically unhealthy", /// - 1.0 means "fully healthy", /// - intermediate fractions mean some level of warning. + /// /// Implementation wise, the result depends on the "syncing rate" and "proposal reliability". fn calculate(&self) -> f64 { self.syncing_factor() * self.proposal_reliability_factor() } /// Calculates the health factor part related to ledger-syncing. + /// /// If the ledger is synced (i.e. the latest committed proposer timestamp is close to the /// wall-clock), then the result is "fully healthy" (i.e. 1.0). + /// /// Otherwise, the health factor depends on the proposer timestamp's progress rate (see /// [`HEALTHY_PROPOSER_TIMESTAMP_PROGRESS_RATE`] and [`MIN_PROPOSER_TIMESTAMP_PROGRESS_RATE`]). fn syncing_factor(&self) -> f64 { @@ -934,7 +925,7 @@ impl OverallLedgerHealthFactor { /// A simplified "overall ledger health" (see [`OverallLedgerHealthFactor::syncing_factor()`]). /// This enum is meant to be surfaced from a `/system/health` API. -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, ScryptoSbor)] pub enum LedgerStatus { /// Ledger is fully synced, i.e. the last committed proposer timestamp is closer than /// [`SYNCED_LEDGER_MAX_DELAY_SEC`] to wallclock. @@ -949,7 +940,7 @@ pub enum LedgerStatus { /// A recent statistic on a number of successful/missed proposals. /// This information is meant to be surfaced from a `/system/health` API. -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, ScryptoSbor)] pub struct RecentSelfProposalMissStatistic { /// A number of missed proposals among [`recent_proposals_tracked_count`] most recent ones. missed_count: u64, diff --git a/core-rust/state-manager/src/protocol/protocol_config.rs b/core-rust/state-manager/src/protocol/protocol_config.rs index bd4c0785c7..7f40210dfc 100644 --- a/core-rust/state-manager/src/protocol/protocol_config.rs +++ b/core-rust/state-manager/src/protocol/protocol_config.rs @@ -10,6 +10,7 @@ const MAX_PROTOCOL_VERSION_NAME_LEN: usize = 16; pub const GENESIS_PROTOCOL_VERSION: &str = "babylon-genesis"; pub const ANEMONE_PROTOCOL_VERSION: &str = "anemone"; pub const BOTTLENOSE_PROTOCOL_VERSION: &str = "bottlenose"; +pub const CUTTLEFISH_PROTOCOL_VERSION: &str = "cuttlefish"; pub fn resolve_update_definition_for_version( protocol_version_name: &ProtocolVersionName, @@ -20,6 +21,7 @@ pub fn resolve_update_definition_for_version( GENESIS_PROTOCOL_VERSION => Some(Box::new(NoOpProtocolDefinition)), ANEMONE_PROTOCOL_VERSION => Some(Box::new(AnemoneProtocolUpdateDefinition)), BOTTLENOSE_PROTOCOL_VERSION => Some(Box::new(BottlenoseProtocolUpdateDefinition)), + CUTTLEFISH_PROTOCOL_VERSION => Some(Box::new(CuttlefishProtocolUpdateDefinition)), // Updates starting "custom-" are intended for use with tests, where the thresholds and config are injected on all nodes name_string if CustomProtocolUpdateDefinition::matches(name_string) => { Some(Box::new(CustomProtocolUpdateDefinition)) diff --git a/core-rust/state-manager/src/protocol/protocol_configs/mod.rs b/core-rust/state-manager/src/protocol/protocol_configs/mod.rs index 56cdb1defa..ed6eaa09a2 100644 --- a/core-rust/state-manager/src/protocol/protocol_configs/mod.rs +++ b/core-rust/state-manager/src/protocol/protocol_configs/mod.rs @@ -9,7 +9,7 @@ use crate::engine_prelude::*; use crate::protocol::*; pub fn resolve_protocol_config(network: &NetworkDefinition) -> ProtocolConfig { - match network.logical_name.as_str() { + match network.logical_name.as_ref() { "mainnet" => mainnet_protocol_config::mainnet_protocol_config(), "stokenet" => stokenet_protocol_config::stokenet_protocol_config(), "dumunet" => dumunet_protocol_config::dumunet_protocol_config(), diff --git a/core-rust/state-manager/src/protocol/protocol_configs/testnet_protocol_config.rs b/core-rust/state-manager/src/protocol/protocol_configs/testnet_protocol_config.rs index 5c650dcaad..8b78922ae5 100644 --- a/core-rust/state-manager/src/protocol/protocol_configs/testnet_protocol_config.rs +++ b/core-rust/state-manager/src/protocol/protocol_configs/testnet_protocol_config.rs @@ -14,6 +14,6 @@ pub fn testnet_protocol_config() -> ProtocolConfig { // So we should target applying protocol updates from 3 onwards (1 per epoch) ProtocolConfig::new_with_triggers(hashmap! { ANEMONE_PROTOCOL_VERSION => EnactAtStartOfEpochUnconditionally(Epoch::of(3)), - BOTTLENOSE_PROTOCOL_VERSION => EnactAtStartOfEpochUnconditionally(Epoch::of(4)) + BOTTLENOSE_PROTOCOL_VERSION => EnactAtStartOfEpochUnconditionally(Epoch::of(4)), }) } diff --git a/core-rust/state-manager/src/protocol/protocol_state.rs b/core-rust/state-manager/src/protocol/protocol_state.rs index 978e44728e..4cc07a87ba 100644 --- a/core-rust/state-manager/src/protocol/protocol_state.rs +++ b/core-rust/state-manager/src/protocol/protocol_state.rs @@ -1,26 +1,9 @@ -use crate::engine_prelude::*; -use node_common::locks::{DbLock, LockFactory, RwLock}; -use prometheus::Registry; -use std::cmp::Ordering; -use std::collections::BTreeMap; -use std::ops::Deref; -use std::sync::Arc; -use tracing::info; - -use crate::protocol::*; -use crate::store::traits::{IterableProofStore, QueryableProofStore, QueryableTransactionStore}; - -use crate::store::rocks_db::ActualStateManagerDatabase; -use crate::{ - LocalTransactionReceipt, ProtocolMetrics, ScenariosExecutionConfig, StateVersion, - SystemExecutor, -}; -use ProtocolUpdateEnactmentCondition::*; +use crate::prelude::*; // This file contains types and utilities for managing the (dynamic) protocol state of a running // node. -pub struct ProtocolUpdateExecutor { +pub struct NodeProtocolUpdateExecutor { network: NetworkDefinition, protocol_update_content_overrides: RawProtocolUpdateContentOverrides, scenarios_execution_config: ScenariosExecutionConfig, @@ -28,7 +11,7 @@ pub struct ProtocolUpdateExecutor { system_executor: Arc, } -impl ProtocolUpdateExecutor { +impl NodeProtocolUpdateExecutor { pub fn new( network: NetworkDefinition, protocol_update_content_overrides: RawProtocolUpdateContentOverrides, @@ -60,7 +43,7 @@ impl ProtocolUpdateExecutor { } ProtocolUpdateProgress::UpdateInProgress { protocol_version_name, - last_batch_idx, + last_batch_index: last_batch_idx, } => { let next_batch_idx = last_batch_idx.checked_add(1).unwrap(); info!( @@ -85,7 +68,7 @@ impl ProtocolUpdateExecutor { fn execute_protocol_update_actions( &self, protocol_version: &ProtocolVersionName, - from_batch_idx: u32, + from_batch_idx: usize, ) { let overrides = self.protocol_update_content_overrides.get(protocol_version); let protocol_update_transactions = resolve_update_definition_for_version(protocol_version) @@ -99,11 +82,11 @@ impl ProtocolUpdateExecutor { .to_run_after_protocol_update(protocol_version), }; - for batch_idx in from_batch_idx..transactions_and_scenarios.batch_count() { + for batch_index in from_batch_idx..transactions_and_scenarios.batch_count() { self.system_executor.execute_protocol_update_action( protocol_version, - batch_idx, - transactions_and_scenarios.generate_batch(batch_idx), + batch_index, + transactions_and_scenarios.generate_batch(batch_index), ); } } @@ -122,7 +105,7 @@ impl ProtocolManager { protocol_update_triggers: Vec, database: &S, lock_factory: &LockFactory, - metric_registry: &Registry, + metric_registry: &MetricRegistry, ) -> Self { let initial_protocol_state = ProtocolState::compute_initial(database, &protocol_update_triggers); @@ -185,7 +168,7 @@ impl ProtocolManager { } } -#[derive(Clone, Debug, Eq, PartialEq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Clone, Debug, Eq, PartialEq, ScryptoSbor)] pub struct ProtocolState { /// A list of all protocol updates that have been enacted. pub enacted_protocol_updates: BTreeMap, @@ -193,13 +176,13 @@ pub struct ProtocolState { pub pending_protocol_updates: Vec, } -#[derive(Clone, Debug, Eq, PartialEq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Clone, Debug, Eq, PartialEq, ScryptoSbor)] pub struct PendingProtocolUpdate { pub protocol_update: ProtocolUpdateTrigger, pub state: PendingProtocolUpdateState, } -#[derive(Clone, Debug, Eq, PartialEq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Clone, Debug, Eq, PartialEq, ScryptoSbor)] pub enum PendingProtocolUpdateState { ForSignalledReadinessSupportCondition { thresholds_state: Vec<( @@ -213,7 +196,7 @@ pub enum PendingProtocolUpdateState { Empty, } -#[derive(Clone, Debug, Eq, PartialEq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Clone, Debug, Eq, PartialEq, ScryptoSbor)] pub struct SignalledReadinessThresholdState { /// A number of consecutive epochs on or above the threshold, /// including the current (uncompleted) epoch. @@ -234,7 +217,7 @@ fn compute_initial_protocol_update_status< protocol_update_trigger: &ProtocolUpdateTrigger, ) -> InitialProtocolUpdateStatus { match &protocol_update_trigger.enactment_condition { - EnactAtStartOfEpochIfValidatorsReady { + ProtocolUpdateEnactmentCondition::EnactAtStartOfEpochIfValidatorsReady { lower_bound_inclusive, upper_bound_exclusive, readiness_thresholds, @@ -245,7 +228,7 @@ fn compute_initial_protocol_update_status< upper_bound_exclusive, readiness_thresholds, ), - EnactAtStartOfEpochUnconditionally(epoch) => { + ProtocolUpdateEnactmentCondition::EnactAtStartOfEpochUnconditionally(epoch) => { compute_initial_at_epoch_protocol_update_status(store, *epoch) } } @@ -458,7 +441,7 @@ impl ProtocolState { let mut enactable_protocol_updates = vec![]; for mut pending_protocol_update in new_protocol_state.pending_protocol_updates { match &pending_protocol_update.protocol_update.enactment_condition { - EnactAtStartOfEpochIfValidatorsReady { + ProtocolUpdateEnactmentCondition::EnactAtStartOfEpochIfValidatorsReady { lower_bound_inclusive, upper_bound_exclusive, .. @@ -504,7 +487,9 @@ impl ProtocolState { expired_protocol_updates.push(pending_protocol_update); } } - EnactAtStartOfEpochUnconditionally(enactment_epoch) => { + ProtocolUpdateEnactmentCondition::EnactAtStartOfEpochUnconditionally( + enactment_epoch, + ) => { if let Some(next_epoch) = &local_receipt.local_execution.next_epoch { match next_epoch.epoch.cmp(enactment_epoch) { Ordering::Less => { diff --git a/core-rust/state-manager/src/protocol/protocol_updates/definitions/anemone_definition.rs b/core-rust/state-manager/src/protocol/protocol_updates/definitions/anemone_definition.rs index 9b36eb988b..fea082f8a6 100644 --- a/core-rust/state-manager/src/protocol/protocol_updates/definitions/anemone_definition.rs +++ b/core-rust/state-manager/src/protocol/protocol_updates/definitions/anemone_definition.rs @@ -1,8 +1,4 @@ -use crate::engine_prelude::*; -use crate::protocol::*; -use crate::store::rocks_db::ActualStateManagerDatabase; -use node_common::locks::DbLock; -use std::sync::Arc; +use crate::prelude::*; pub struct AnemoneProtocolUpdateDefinition; diff --git a/core-rust/state-manager/src/protocol/protocol_updates/definitions/bottlenose_definition.rs b/core-rust/state-manager/src/protocol/protocol_updates/definitions/bottlenose_definition.rs index 48530042a7..396ede2f4e 100644 --- a/core-rust/state-manager/src/protocol/protocol_updates/definitions/bottlenose_definition.rs +++ b/core-rust/state-manager/src/protocol/protocol_updates/definitions/bottlenose_definition.rs @@ -1,8 +1,4 @@ -use crate::engine_prelude::*; -use crate::protocol::*; -use crate::store::rocks_db::ActualStateManagerDatabase; -use node_common::locks::DbLock; -use std::sync::Arc; +use crate::prelude::*; pub struct BottlenoseProtocolUpdateDefinition; diff --git a/core-rust/state-manager/src/protocol/protocol_updates/definitions/custom_definition.rs b/core-rust/state-manager/src/protocol/protocol_updates/definitions/custom_definition.rs index 8a7fbff9d9..2a85587c76 100644 --- a/core-rust/state-manager/src/protocol/protocol_updates/definitions/custom_definition.rs +++ b/core-rust/state-manager/src/protocol/protocol_updates/definitions/custom_definition.rs @@ -1,8 +1,4 @@ -use crate::engine_prelude::*; -use crate::protocol::*; -use crate::store::rocks_db::ActualStateManagerDatabase; -use node_common::locks::DbLock; -use std::sync::Arc; +use crate::prelude::*; /// Any protocol update beginning `custom-` can have content injected via config. pub struct CustomProtocolUpdateDefinition; @@ -19,8 +15,20 @@ impl CustomProtocolUpdateDefinition { } } +/// This is a slightly different structure to [`ProtocolUpdateNodeBatch`] because the latter +/// was updated, but we needed to keep this in the old-style to avoid breaking any tests by +/// changing the models. +#[derive(Debug, Clone, PartialEq, Eq, Sbor)] +pub enum CustomProtocolUpdateBatch { + /// Flash transactions. + FlashTransactions(Vec), + + /// An execution of a single test Scenario. + Scenario(String), +} + impl ProtocolUpdateDefinition for CustomProtocolUpdateDefinition { - type Overrides = Vec; + type Overrides = Vec; fn create_batch_generator( &self, @@ -29,7 +37,23 @@ impl ProtocolUpdateDefinition for CustomProtocolUpdateDefinition { overrides: Option, ) -> Box { Box::new(ArbitraryNodeBatchGenerator { - batches: overrides.unwrap_or_default(), + batches: { + overrides + .unwrap_or_default() + .into_iter() + .map(|batch| match batch { + CustomProtocolUpdateBatch::FlashTransactions(transactions) => { + let batch = ProtocolUpdateBatch { + transactions: transactions.into_iter().map(|t| t.into()).collect(), + }; + ProtocolUpdateNodeBatch::ProtocolUpdateBatch(batch) + } + CustomProtocolUpdateBatch::Scenario(scenario_name) => { + ProtocolUpdateNodeBatch::Scenario(scenario_name) + } + }) + .collect() + }, }) } } @@ -39,11 +63,11 @@ pub struct ArbitraryNodeBatchGenerator { } impl ProtocolUpdateNodeBatchGenerator for ArbitraryNodeBatchGenerator { - fn generate_batch(&self, batch_idx: u32) -> ProtocolUpdateNodeBatch { - self.batches.get(batch_idx as usize).unwrap().clone() + fn generate_batch(&self, batch_idx: usize) -> ProtocolUpdateNodeBatch { + self.batches.get(batch_idx).unwrap().clone() } - fn batch_count(&self) -> u32 { - u32::try_from(self.batches.len()).unwrap() + fn batch_count(&self) -> usize { + self.batches.len() } } diff --git a/core-rust/state-manager/src/protocol/protocol_updates/definitions/cuttlefish_definition.rs b/core-rust/state-manager/src/protocol/protocol_updates/definitions/cuttlefish_definition.rs new file mode 100644 index 0000000000..7c4d75454e --- /dev/null +++ b/core-rust/state-manager/src/protocol/protocol_updates/definitions/cuttlefish_definition.rs @@ -0,0 +1,18 @@ +use crate::prelude::*; + +pub struct CuttlefishProtocolUpdateDefinition; + +impl ProtocolUpdateDefinition for CuttlefishProtocolUpdateDefinition { + type Overrides = (); + + fn create_batch_generator( + &self, + network: &NetworkDefinition, + database: Arc>, + _overrides: Option, + ) -> Box { + Box::new(engine_default_for_network::( + network, database, + )) + } +} diff --git a/core-rust/state-manager/src/protocol/protocol_updates/definitions/default_definition.rs b/core-rust/state-manager/src/protocol/protocol_updates/definitions/default_definition.rs index 8491f2fe7e..94ad0ef262 100644 --- a/core-rust/state-manager/src/protocol/protocol_updates/definitions/default_definition.rs +++ b/core-rust/state-manager/src/protocol/protocol_updates/definitions/default_definition.rs @@ -1,8 +1,4 @@ -use crate::engine_prelude::*; -use crate::protocol::*; -use crate::store::rocks_db::ActualStateManagerDatabase; -use node_common::locks::DbLock; -use std::sync::Arc; +use crate::prelude::*; pub struct NoOpProtocolDefinition; @@ -22,11 +18,11 @@ impl ProtocolUpdateDefinition for NoOpProtocolDefinition { struct EmptyNodeBatchGenerator; impl ProtocolUpdateNodeBatchGenerator for EmptyNodeBatchGenerator { - fn generate_batch(&self, _batch_idx: u32) -> ProtocolUpdateNodeBatch { + fn generate_batch(&self, _batch_idx: usize) -> ProtocolUpdateNodeBatch { panic!("no batches") } - fn batch_count(&self) -> u32 { + fn batch_count(&self) -> usize { 0 } } diff --git a/core-rust/state-manager/src/protocol/protocol_updates/definitions/mod.rs b/core-rust/state-manager/src/protocol/protocol_updates/definitions/mod.rs index 8913985b9f..8256667ea4 100644 --- a/core-rust/state-manager/src/protocol/protocol_updates/definitions/mod.rs +++ b/core-rust/state-manager/src/protocol/protocol_updates/definitions/mod.rs @@ -1,70 +1,13 @@ mod anemone_definition; mod bottlenose_definition; mod custom_definition; +mod cuttlefish_definition; mod default_definition; mod test_definition; pub use anemone_definition::*; pub use bottlenose_definition::*; pub use custom_definition::*; +pub use cuttlefish_definition::*; pub use default_definition::*; pub use test_definition::*; - -use crate::engine_prelude::*; -use crate::protocol::*; -use crate::store::rocks_db::ActualStateManagerDatabase; -use crate::transaction::*; -use node_common::locks::DbLock; -use std::ops::Deref; -use std::sync::Arc; - -/// A [`ProtocolUpdateNodeBatchGenerator`] implementation for the actual Engine's protocol updates. -pub struct EngineBatchGenerator { - database: Arc>, - engine_batch_generator: G, -} - -/// Creates an [`EngineBatchGenerator`] for the given [`UpdateSettings`], with all -/// the features that Engine wants enabled by default. -pub fn engine_default_for_network( - network: &NetworkDefinition, - database: Arc>, -) -> EngineBatchGenerator { - EngineBatchGenerator { - database, - engine_batch_generator: U::all_enabled_as_default_for_network(network) - .create_batch_generator(), - } -} - -impl ProtocolUpdateNodeBatchGenerator for EngineBatchGenerator { - fn generate_batch(&self, batch_idx: u32) -> ProtocolUpdateNodeBatch { - let ProtocolUpdateBatch { transactions } = self - .engine_batch_generator - .generate_batch(self.database.lock().deref(), batch_idx); - ProtocolUpdateNodeBatch::FlashTransactions( - transactions - .into_iter() - .map(FlashTransactionV1::from) - .collect(), - ) - } - - fn batch_count(&self) -> u32 { - self.engine_batch_generator.batch_count() - } -} - -impl From for FlashTransactionV1 { - fn from(value: ProtocolUpdateTransactionDetails) -> Self { - let ProtocolUpdateTransactionDetails::FlashV1Transaction(flash) = value; - let FlashProtocolUpdateTransactionDetails { - name, - state_updates, - } = flash; - FlashTransactionV1 { - name, - state_updates, - } - } -} diff --git a/core-rust/state-manager/src/protocol/protocol_updates/definitions/test_definition.rs b/core-rust/state-manager/src/protocol/protocol_updates/definitions/test_definition.rs index c7e9c2432b..b65391d5ac 100644 --- a/core-rust/state-manager/src/protocol/protocol_updates/definitions/test_definition.rs +++ b/core-rust/state-manager/src/protocol/protocol_updates/definitions/test_definition.rs @@ -1,8 +1,4 @@ -use crate::engine_prelude::*; -use crate::store::rocks_db::ActualStateManagerDatabase; -use crate::{protocol::*, transaction::FlashTransactionV1}; -use node_common::locks::DbLock; -use std::sync::Arc; +use crate::prelude::*; /// Any protocol update beginning `test-` just injects a single transaction. pub struct TestProtocolUpdateDefinition { @@ -37,13 +33,14 @@ impl ProtocolUpdateDefinition for TestProtocolUpdateDefinition { _database: Arc>, _overrides: Option, ) -> Box { + let batch = ProtocolUpdateBatch { + transactions: vec![ProtocolUpdateTransaction::flash( + &format!("{}-txn", self.protocol_name), + StateUpdates::default(), + )], + }; Box::new(ArbitraryNodeBatchGenerator { - batches: vec![ProtocolUpdateNodeBatch::FlashTransactions(vec![ - FlashTransactionV1 { - name: format!("{}-txn", self.protocol_name), - state_updates: StateUpdates::default(), - }, - ])], + batches: vec![ProtocolUpdateNodeBatch::ProtocolUpdateBatch(batch)], }) } } diff --git a/core-rust/state-manager/src/protocol/protocol_updates/protocol_update_progress.rs b/core-rust/state-manager/src/protocol/protocol_updates/protocol_update_progress.rs index a9c9f1f8c4..baed68abc9 100644 --- a/core-rust/state-manager/src/protocol/protocol_updates/protocol_update_progress.rs +++ b/core-rust/state-manager/src/protocol/protocol_updates/protocol_update_progress.rs @@ -1,10 +1,4 @@ -use crate::engine_prelude::*; - -use crate::protocol::*; - -use crate::store::traits::*; - -use crate::LedgerProofOrigin; +use crate::prelude::*; pub enum ProtocolUpdateProgress { UpdateInitiatedButNothingCommitted { @@ -12,7 +6,7 @@ pub enum ProtocolUpdateProgress { }, UpdateInProgress { protocol_version_name: ProtocolVersionName, - last_batch_idx: u32, + last_batch_index: usize, }, /// This means that the last proof contains no notion of a protocol update, /// which in practice almost always means that it has already executed in full. @@ -45,10 +39,10 @@ impl ProtocolUpdateProgress { } LedgerProofOrigin::ProtocolUpdate { protocol_version_name, - batch_idx, + batch_index, } => ProtocolUpdateProgress::UpdateInProgress { protocol_version_name: protocol_version_name.clone(), - last_batch_idx: *batch_idx, + last_batch_index: *batch_index as usize, }, } } diff --git a/core-rust/state-manager/src/protocol/protocol_updates/protocol_updaters.rs b/core-rust/state-manager/src/protocol/protocol_updates/protocol_updaters.rs index 9f884b0367..28a4ab298a 100644 --- a/core-rust/state-manager/src/protocol/protocol_updates/protocol_updaters.rs +++ b/core-rust/state-manager/src/protocol/protocol_updates/protocol_updaters.rs @@ -1,12 +1,10 @@ -use crate::engine_prelude::*; - -use crate::transaction::FlashTransactionV1; +use crate::prelude::*; /// An atomic part of a protocol update. -#[derive(Debug, Clone, PartialEq, Eq, Sbor)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum ProtocolUpdateNodeBatch { - /// An explicit batch of flash transactions. - FlashTransactions(Vec), + /// A batch from the protocol update + ProtocolUpdateBatch(ProtocolUpdateBatch), /// An execution of a single test Scenario. Scenario(String), @@ -21,10 +19,47 @@ pub enum ProtocolUpdateNodeBatch { pub trait ProtocolUpdateNodeBatchGenerator { /// Returns a batch at the given index. /// Panics if the index is out of bounds (as given by the [`Self::batch_count()`]. - fn generate_batch(&self, batch_idx: u32) -> ProtocolUpdateNodeBatch; + fn generate_batch(&self, batch_index: usize) -> ProtocolUpdateNodeBatch; /// Returns the number of contained batches. - fn batch_count(&self) -> u32; + fn batch_count(&self) -> usize; +} + +/// A [`ProtocolUpdateNodeBatchGenerator`] implementation for the actual Engine's protocol updates. +pub struct EngineBatchGenerator { + database: Arc>, + engine_batch_generator: G, +} + +/// Creates an [`EngineBatchGenerator`] for the given [`UpdateSettings`], with all +/// the features that Engine wants enabled by default. +pub fn engine_default_for_network( + network: &NetworkDefinition, + database: Arc>, +) -> EngineBatchGenerator { + EngineBatchGenerator { + database, + engine_batch_generator: U::all_enabled_as_default_for_network(network) + .create_batch_generator(), + } +} + +impl ProtocolUpdateNodeBatchGenerator for EngineBatchGenerator { + fn generate_batch(&self, batch_idx: usize) -> ProtocolUpdateNodeBatch { + let batch = + self.engine_batch_generator + .generate_batch(self.database.lock().deref(), 0, batch_idx); + ProtocolUpdateNodeBatch::ProtocolUpdateBatch(batch) + } + + fn batch_count(&self) -> usize { + assert_eq!( + self.engine_batch_generator.batch_group_descriptors().len(), + 1, + "Currently the node only supports protocol updates with 1 batch group", + ); + self.engine_batch_generator.batch_count(0) + } } /// A [`ProtocolUpdateNodeBatchGenerator`] decorator which additionally executes post-update Scenarios. @@ -36,25 +71,21 @@ pub struct WithScenariosNodeBatchGenerator<'b, B: ProtocolUpdateNodeBatchGenerat impl<'b, B: ProtocolUpdateNodeBatchGenerator + ?Sized> ProtocolUpdateNodeBatchGenerator for WithScenariosNodeBatchGenerator<'b, B> { - fn generate_batch(&self, batch_idx: u32) -> ProtocolUpdateNodeBatch { + fn generate_batch(&self, batch_idx: usize) -> ProtocolUpdateNodeBatch { let base_batch_count = self.base_batch_generator.batch_count(); if batch_idx < base_batch_count { self.base_batch_generator.generate_batch(batch_idx) } else { let scenario_index = batch_idx.checked_sub(base_batch_count).unwrap(); - let scenario_name = self - .scenario_names - .get(scenario_index as usize) - .unwrap() - .clone(); + let scenario_name = self.scenario_names.get(scenario_index).unwrap().clone(); ProtocolUpdateNodeBatch::Scenario(scenario_name) } } - fn batch_count(&self) -> u32 { + fn batch_count(&self) -> usize { self.base_batch_generator .batch_count() - .checked_add(u32::try_from(self.scenario_names.len()).unwrap()) + .checked_add(self.scenario_names.len()) .unwrap() } } diff --git a/core-rust/state-manager/src/protocol/test.rs b/core-rust/state-manager/src/protocol/test.rs index a7a9f8561d..f166658e8a 100644 --- a/core-rust/state-manager/src/protocol/test.rs +++ b/core-rust/state-manager/src/protocol/test.rs @@ -62,15 +62,9 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use crate::store::traits::QueryableProofStore; - -use crate::protocol::*; -use crate::{LedgerProof, LedgerProofOrigin, StateManagerConfig}; -use std::ops::Deref; +use crate::prelude::*; use crate::test::{create_state_manager, prepare_and_commit_round_update}; -use crate::transaction::FlashTransactionV1; const CUSTOM_V2_PROTOCOL_VERSION: &str = "custom-v2"; @@ -101,10 +95,12 @@ fn flash_protocol_update_test() { let validator_fee_fix = AnemoneSettings::all_disabled() .enable(|anemone_settings| &mut anemone_settings.validator_fee_fix) .create_batch_generator() - .generate_batch(tmp_state_manager.database.access_direct().deref(), 0) + .generate_batch(tmp_state_manager.database.access_direct().deref(), 0, 0) .transactions .remove(0); - let ProtocolUpdateTransactionDetails::FlashV1Transaction(flash) = validator_fee_fix; + let ProtocolUpdateTransaction::FlashTransactionV1(flash) = validator_fee_fix else { + panic!(); + }; flash.state_updates }; @@ -113,7 +109,7 @@ fn flash_protocol_update_test() { .protocol_update_content_overrides = ProtocolUpdateContentOverrides::empty() .with_custom( custom_v2_protocol_version.clone(), - vec![ProtocolUpdateNodeBatch::FlashTransactions(vec![ + vec![CustomProtocolUpdateBatch::FlashTransactions(vec![ FlashTransactionV1 { name: format!("{CUSTOM_V2_PROTOCOL_VERSION}-flash"), state_updates: consensus_manager_state_updates, @@ -152,11 +148,13 @@ fn flash_protocol_update_test() { ); // Verify that a new consensus manager config has been flashed - let config_substate = database.get_mapped::>( - CONSENSUS_MANAGER.as_node_id(), - MAIN_BASE_PARTITION, - &ConsensusManagerField::Configuration.into() - ).unwrap(); + let config_substate = database + .get_substate::>( + CONSENSUS_MANAGER, + MAIN_BASE_PARTITION, + ConsensusManagerField::Configuration, + ) + .unwrap(); assert_eq!( config_substate @@ -182,7 +180,7 @@ fn flash_protocol_update_test() { latest_execution_proof.origin, LedgerProofOrigin::ProtocolUpdate { protocol_version_name: ProtocolVersionName::of_unchecked(CUSTOM_V2_PROTOCOL_VERSION), - batch_idx: 0 + batch_index: 0 } ); diff --git a/core-rust/state-manager/src/query/state_manager_substate_queries.rs b/core-rust/state-manager/src/query/state_manager_substate_queries.rs index 2c2e4d8b5d..a3170c9abd 100644 --- a/core-rust/state-manager/src/query/state_manager_substate_queries.rs +++ b/core-rust/state-manager/src/query/state_manager_substate_queries.rs @@ -7,10 +7,10 @@ pub trait StateManagerSubstateQueries { impl StateManagerSubstateQueries for T { fn get_epoch_and_round(&self) -> (Epoch, Round) { let consensus_manager_state = self - .get_mapped::( - CONSENSUS_MANAGER.as_node_id(), + .get_substate::( + CONSENSUS_MANAGER, MAIN_BASE_PARTITION, - &ConsensusManagerField::State.into(), + ConsensusManagerField::State, ) .unwrap() .into_payload() diff --git a/core-rust/state-manager/src/query/transaction_identifiers.rs b/core-rust/state-manager/src/query/transaction_identifiers.rs index edb046ab85..d6d3cd4459 100644 --- a/core-rust/state-manager/src/query/transaction_identifiers.rs +++ b/core-rust/state-manager/src/query/transaction_identifiers.rs @@ -1,4 +1,4 @@ -use crate::{CommittedTransactionIdentifiers, LedgerHashes, StateVersion}; +use crate::prelude::*; pub trait TransactionIdentifierLoader { fn get_top_transaction_identifiers( diff --git a/core-rust/state-manager/src/receipt.rs b/core-rust/state-manager/src/receipt.rs index b582e8b668..305dcd78f0 100644 --- a/core-rust/state-manager/src/receipt.rs +++ b/core-rust/state-manager/src/receipt.rs @@ -1,12 +1,4 @@ -use crate::engine_prelude::*; - -use crate::accumulator_tree::storage::{ReadableAccuTreeStore, TreeSlice, WriteableAccuTreeStore}; -use crate::accumulator_tree::tree_builder::{AccuTree, Merklizable}; -use crate::transaction::PayloadIdentifiers; -use crate::{ - ConsensusReceipt, EventHash, ExecutionFeeData, GlobalBalanceSummary, LedgerHashes, - PartitionReference, StateChangeHash, SubstateReference, -}; +use crate::prelude::*; define_single_versioned! { #[derive(Debug, Clone, Sbor)] @@ -15,13 +7,13 @@ define_single_versioned! { #[derive(Debug, Clone, Sbor)] pub struct CommittedTransactionIdentifiersV1 { - pub payload: PayloadIdentifiers, + pub transaction_hashes: LedgerTransactionHashes, pub resultant_ledger_hashes: LedgerHashes, pub proposer_timestamp_ms: i64, } /// A "flat" representation of an entire Partition's change, suitable for merkle hash computation. -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct PartitionChange { pub node_id: NodeId, pub partition_num: PartitionNumber, @@ -40,7 +32,7 @@ impl From<(PartitionReference, PartitionChangeAction)> for PartitionChange { } /// A "flat" representation of a single substate's change, suitable for merkle hash computation. -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct SubstateChange { pub node_id: NodeId, pub partition_num: PartitionNumber, @@ -61,7 +53,7 @@ impl From<(SubstateReference, SubstateChangeAction)> for SubstateChange { } /// An on-ledger change of an entire partition. -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub enum PartitionChangeAction { /// Deletion of an entire Partition. /// Note: contrary to [`SubstateChangeAction`]s, the previous contents of the Partition are not @@ -70,7 +62,7 @@ pub enum PartitionChangeAction { } /// An on-ledger change of an individual substate. -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub enum SubstateChangeAction { Create { /// A value after the transaction. @@ -93,7 +85,7 @@ pub enum SubstateChangeAction { }, } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct ApplicationEvent { pub type_id: EventTypeIdentifier, pub data: Vec, @@ -110,7 +102,7 @@ impl ApplicationEvent { } } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub enum LedgerTransactionOutcome { Success, Failure, @@ -125,7 +117,7 @@ impl LedgerTransactionOutcome { } } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub enum DetailedTransactionOutcome { Success(Vec>), Failure(LenientRuntimeError), @@ -133,7 +125,7 @@ pub enum DetailedTransactionOutcome { /// A wrapper for SBOR-encoded [`RuntimeError`] which may turn out to no longer be decodable (due /// to differences in historical error enum schema). -#[derive(Debug, Clone, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoEncode, ScryptoDecode, ScryptoDescribe)] #[sbor(transparent)] pub struct LenientRuntimeError(ScryptoValue); @@ -189,7 +181,7 @@ impl From for DetailedTransactionOutcome { /// A "flattened", unambiguous representation of state changes resulting from a transaction, /// suitable for merkle hash computation (to be recorded on-ledger). -#[derive(Debug, Clone, Default, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, Default, ScryptoSbor)] pub struct LedgerStateChanges { /// Changes applied on Partition level, affecting all substates of a Partition *except* the /// ones referenced in [`substate_level_changes`]. @@ -224,28 +216,36 @@ impl LedgerStateChanges { } } -/// A committed transaction (success or failure), extracted from the Engine's `TransactionReceipt` +/// A committed transaction (success or failure), extracted from the Engine's [`TransactionReceipt`] /// of any locally-executed transaction (slightly post-processed). +/// /// It contains all the critical, deterministic pieces of the Engine's receipt, but also some of its -/// other parts - for this reason, it is very clearly split into 2 parts (on-ledger vs off-ledger). -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +/// other parts - for this reason, it is very clearly split into 2 parts: +/// +/// * The [`LedgerTransactionReceipt`] contains the parts of the receipt which are validated at +/// consensus (success/failure, state changes and emitted events). +/// * The [`LocalTransactionExecution`] contains other information which is useful for transaction +/// analysis and investigation. +#[derive(Debug, Clone)] pub struct LocalTransactionReceipt { pub on_ledger: LedgerTransactionReceipt, pub local_execution: LocalTransactionExecution, } define_single_versioned! { - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub VersionedLedgerTransactionReceipt(LedgerTransactionReceiptVersions) => LedgerTransactionReceipt = LedgerTransactionReceiptV1 } /// A part of the [`LocalTransactionReceipt`] which is completely stored on ledger. It contains only /// the critical, deterministic pieces of the original Engine's `TransactionReceipt`. +/// /// All these pieces can be verified against the Receipt Root hash (found in the Ledger Proof). -/// Note: the Ledger Receipt is still a pretty large structure (i.e. containing entire collections, +/// +/// Note: the [`LedgerTransactionReceipt`] is still a pretty large structure (i.e. containing entire collections, /// like substate changes) and is not supposed to be hashed directly - it should instead go through /// a [`ConsensusReceipt`]. -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct LedgerTransactionReceiptV1 { /// A simple, high-level outcome of the transaction. /// Its omitted details may be found in `LocalTransactionExecution::outcome`. @@ -256,23 +256,65 @@ pub struct LedgerTransactionReceiptV1 { pub application_events: Vec, } -define_single_versioned! { - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] - pub VersionedLocalTransactionExecution(LocalTransactionExecutionVersions) => LocalTransactionExecution = LocalTransactionExecutionV1 +define_versioned! { + /// A computable/non-critical/non-deterministic part of the `LocalTransactionReceipt` + /// (e.g. logs, summaries). + /// It is not verifiable against ledger, but is still be useful for debugging. + #[derive(Debug, Clone, ScryptoSbor)] + pub VersionedLocalTransactionExecution(LocalTransactionExecutionVersions) { + previous_versions: [ + 1 => LocalTransactionExecutionV1: { updates_to: 2 }, + ], + latest_version: { + 2 => LocalTransactionExecution = LocalTransactionExecutionV2, + }, + } } -/// A computable/non-critical/non-deterministic part of the `LocalTransactionReceipt` (e.g. logs, -/// summaries). -/// It is not verifiable against ledger, but may still be useful for debugging. -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct LocalTransactionExecutionV1 { pub outcome: DetailedTransactionOutcome, pub fee_summary: TransactionFeeSummary, pub fee_source: FeeSource, pub fee_destination: FeeDestination, pub engine_costing_parameters: CostingParameters, - pub transaction_costing_parameters: TransactionCostingParametersReceipt, - pub application_logs: Vec<(Level, String)>, + pub transaction_costing_parameters: TransactionCostingParametersReceiptV1, + pub application_logs: Vec<(crate::engine_prelude::Level, String)>, + pub state_update_summary: StateUpdateSummary, + pub global_balance_summary: GlobalBalanceSummary, + pub substates_system_structure: BySubstate, + pub events_system_structure: IndexMap, + pub next_epoch: Option, +} + +impl From for LocalTransactionExecutionV2 { + fn from(value: LocalTransactionExecutionV1) -> Self { + LocalTransactionExecutionV2 { + outcome: value.outcome, + fee_summary: value.fee_summary, + fee_source: value.fee_source, + fee_destination: value.fee_destination, + engine_costing_parameters: value.engine_costing_parameters, + transaction_costing_parameters: value.transaction_costing_parameters.into(), + application_logs: value.application_logs, + state_update_summary: value.state_update_summary, + global_balance_summary: value.global_balance_summary, + substates_system_structure: value.substates_system_structure, + events_system_structure: value.events_system_structure, + next_epoch: value.next_epoch, + } + } +} + +#[derive(Debug, Clone, ScryptoSbor)] +pub struct LocalTransactionExecutionV2 { + pub outcome: DetailedTransactionOutcome, + pub fee_summary: TransactionFeeSummary, + pub fee_source: FeeSource, + pub fee_destination: FeeDestination, + pub engine_costing_parameters: CostingParameters, + pub transaction_costing_parameters: TransactionCostingParametersReceiptV2, + pub application_logs: Vec<(crate::engine_prelude::Level, String)>, pub state_update_summary: StateUpdateSummary, pub global_balance_summary: GlobalBalanceSummary, pub substates_system_structure: BySubstate, @@ -300,6 +342,12 @@ impl LedgerTransactionReceipt { } } +pub struct ExecutionFeeData { + pub fee_summary: TransactionFeeSummary, + pub engine_costing_parameters: CostingParameters, + pub transaction_costing_parameters: TransactionCostingParametersReceiptV2, +} + impl LocalTransactionReceipt { pub fn new( commit_result: CommitResult, @@ -342,7 +390,7 @@ impl LocalTransactionReceipt { /// A container of items associated with a specific partition. /// This simply offers a less wasteful representation of a `Vec<(PartitionReference, T)>`, by /// avoiding the repeated [`NodeId`]s (within [`PartitionReference`]s). -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] #[sbor(categorize_types = "T")] pub struct ByPartition { by_node_id: IndexMap>, @@ -401,7 +449,7 @@ impl Default for ByPartition { /// A container of items associated with a specific substate. /// This simply offers a less wasteful representation of a `Vec<(SubstateReference, T)>`, by /// avoiding the repeated [`NodeId`]s and [`PartitionNumber`]s (within [`SubstateReference`]s). -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] #[sbor(categorize_types = "T")] pub struct BySubstate { by_node_id: IndexMap>>, diff --git a/core-rust/state-manager/src/staging/cache.rs b/core-rust/state-manager/src/staging/cache.rs index 64b818973c..cbc46e530c 100644 --- a/core-rust/state-manager/src/staging/cache.rs +++ b/core-rust/state-manager/src/staging/cache.rs @@ -64,32 +64,10 @@ #![allow(clippy::too_many_arguments)] -use super::stage_tree::{Accumulator, Delta, DerivedStageKey, StageKey, StageTree}; -use super::ReadableStore; -use std::ops::{Deref, DerefMut}; -use std::sync::Arc; - -use crate::accumulator_tree::storage::{ReadableAccuTreeStore, TreeSlice}; -use crate::engine_prelude::*; -use crate::staging::overlays::{ - MapSubstateNodeAncestryStore, StagedSubstateNodeAncestryStore, SubstateOverlayIterator, -}; -use crate::staging::{ - AccuTreeDiff, HashStructuresDiff, HashUpdateContext, ProcessedTransactionReceipt, StateTreeDiff, -}; -use crate::transaction::{ - HasLedgerTransactionHash, LedgerTransactionHash, PreparedLedgerTransaction, TransactionLogic, -}; -use crate::{ - EpochTransactionIdentifiers, LedgerHashes, ReceiptTreeHash, StateVersion, TransactionTreeHash, -}; +use super::overlays::*; +use super::stage_tree::*; +use crate::prelude::*; use im::hashmap::HashMap as ImmutableHashMap; -use itertools::Itertools; - -use crate::store::rocks_db::ActualStateManagerDatabase; -use crate::store::traits::{ConfigurableDatabase, QueryableProofStore}; -use crate::store::traits::{SubstateNodeAncestryRecord, SubstateNodeAncestryStore}; -use node_common::locks::{DbLock, LockFactory, Mutex}; use slotmap::SecondaryMap; pub struct ExecutionCacheManager { @@ -179,16 +157,16 @@ struct InternalTransactionIds { /// A transaction may be unambiguously identified by 2 different business keys here: /// /// - By a [`TransactionPlacement`]: -/// A "transaction placement" of transaction X is technically a tuple `{X's parent's transaction -/// root, X's payload hash}`. It can be produced for any "candidate" transaction (i.e. even for ones -/// that would be rejected). +/// A "transaction placement" of transaction X is technically a tuple `{X's parent's transaction +/// root, X's payload hash}`. It can be produced for any "candidate" transaction (i.e. even for ones +/// that would be rejected). /// /// - By a transaction root: -/// This means just a regular transaction tree root (i.e. our replacement of accumulator hash). -/// There is a gotcha though: transaction root comes from transaction's [`LedgerHashes`], and we do -/// not compute them for transactions that are rejected (technically we could compute just the -/// transaction root alone, but in our current impl we do not - for simplicity and performance). -/// Yet, in this cache, we want to reference rejected transactions as well. +/// This means just a regular transaction tree root (i.e. our replacement of accumulator hash). +/// There is a gotcha though: transaction root comes from transaction's [`LedgerHashes`], and we do +/// not compute them for transactions that are rejected (technically we could compute just the +/// transaction root alone, but in our current impl we do not - for simplicity and performance). +/// Yet, in this cache, we want to reference rejected transactions as well. /// /// For the above reasons, we need two [`HashMap`]s leading to [`DerivedStageKey`]s (we identify the /// candidate transactions by their placement, and we identify their parents by transaction root). @@ -343,19 +321,23 @@ impl<'s, S> StagedStore<'s, S> { } impl<'s, S: SubstateDatabase> SubstateDatabase for StagedStore<'s, S> { - fn get_substate( + fn get_raw_substate_by_db_key( &self, partition_key: &DbPartitionKey, sort_key: &DbSortKey, ) -> Option { let partition_updates = self.overlay.partition_updates.get(partition_key); let Some(partition_updates) = partition_updates else { - return self.root.get_substate(partition_key, sort_key); + return self + .root + .get_raw_substate_by_db_key(partition_key, sort_key); }; match partition_updates { ImmutablePartitionUpdates::Delta { substate_updates } => { match substate_updates.get(sort_key) { - None => self.root.get_substate(partition_key, sort_key), + None => self + .root + .get_raw_substate_by_db_key(partition_key, sort_key), Some(update) => match update { DatabaseUpdate::Set(value) => Some(value.clone()), DatabaseUpdate::Delete => None, @@ -370,14 +352,16 @@ impl<'s, S: SubstateDatabase> SubstateDatabase for StagedStore<'s, S> { } } - fn list_entries_from( + fn list_raw_values_from_db_key( &self, partition_key: &DbPartitionKey, from_sort_key: Option<&DbSortKey>, ) -> Box + '_> { let partition_updates = self.overlay.partition_updates.get(partition_key); let Some(partition_updates) = partition_updates else { - return self.root.list_entries_from(partition_key, from_sort_key); + return self + .root + .list_raw_values_from_db_key(partition_key, from_sort_key); }; let cloned_from_sort_key = from_sort_key.cloned(); @@ -396,7 +380,8 @@ impl<'s, S: SubstateDatabase> SubstateDatabase for StagedStore<'s, S> { }); Box::new(SubstateOverlayIterator::new( - self.root.list_entries_from(partition_key, from_sort_key), + self.root + .list_raw_values_from_db_key(partition_key, from_sort_key), Box::new(overlaid_iter), )) } diff --git a/core-rust/state-manager/src/staging/epoch_handling.rs b/core-rust/state-manager/src/staging/epoch_handling.rs index 9fccd67635..b2b1477337 100644 --- a/core-rust/state-manager/src/staging/epoch_handling.rs +++ b/core-rust/state-manager/src/staging/epoch_handling.rs @@ -62,13 +62,7 @@ * permissions under this License. */ -use crate::accumulator_tree::slice_merger::AccuTreeSliceMerger; -use crate::accumulator_tree::storage::{ - AccuTreeStore, ReadableAccuTreeStore, TreeSlice, WriteableAccuTreeStore, -}; -use crate::accumulator_tree::tree_builder::AccuTree; -use crate::accumulator_tree::IsMerklizableHash; -use crate::{AccuTreeDiff, CollectingAccuTreeStore, StateVersion}; +use crate::prelude::*; /// A factory of accu tree utilities operating under the "accu tree per epoch" approach (where the /// first leaf of the next epoch's tree is an auto-inserted root of the previous epoch's tree). @@ -172,6 +166,7 @@ impl<'s, S: AccuTreeStore, N: IsMerklizableHash> EpochAccuTreeB /// Appends the next leaf to the epoch's accu tree. /// This method will handle a special case of an epoch that was just started (which requires /// inserting the previous epoch's root as the first leaf of this epoch's tree). + #[allow(unused)] pub fn append(&mut self, new_leaf_hash: N) { self.append_batch(vec![new_leaf_hash]); } diff --git a/core-rust/state-manager/src/staging/mod.rs b/core-rust/state-manager/src/staging/mod.rs index 02f7a180b5..c071bcc63d 100644 --- a/core-rust/state-manager/src/staging/mod.rs +++ b/core-rust/state-manager/src/staging/mod.rs @@ -62,20 +62,19 @@ * permissions under this License. */ +use crate::prelude::*; + mod cache; -pub mod epoch_handling; +mod epoch_handling; mod node_ancestry_resolver; mod overlays; mod result; mod stage_tree; -use crate::accumulator_tree::storage::ReadableAccuTreeStore; -use crate::engine_prelude::*; -use crate::{ReceiptTreeHash, StateVersion, TransactionTreeHash}; - -use crate::store::traits::ConfigurableDatabase; -use crate::store::traits::SubstateNodeAncestryStore; pub use cache::*; +pub use epoch_handling::*; +pub use node_ancestry_resolver::*; +pub use overlays::*; pub use result::*; pub trait ReadableStateTreeStore: ReadableTreeStore {} diff --git a/core-rust/state-manager/src/staging/node_ancestry_resolver.rs b/core-rust/state-manager/src/staging/node_ancestry_resolver.rs index 763fd8d115..97335d3019 100644 --- a/core-rust/state-manager/src/staging/node_ancestry_resolver.rs +++ b/core-rust/state-manager/src/staging/node_ancestry_resolver.rs @@ -62,9 +62,7 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use crate::store::traits::*; -use crate::{SubstateChangeAction, SubstateReference}; +use crate::prelude::*; use std::borrow::Borrow; use std::collections::hash_map::Entry; diff --git a/core-rust/state-manager/src/staging/overlays.rs b/core-rust/state-manager/src/staging/overlays.rs index ac54cbdc0e..e8b362a970 100644 --- a/core-rust/state-manager/src/staging/overlays.rs +++ b/core-rust/state-manager/src/staging/overlays.rs @@ -1,10 +1,7 @@ -use crate::engine_prelude::*; -use std::cmp::Ordering; +use crate::prelude::*; use std::hash::Hash; use std::iter::Peekable; -use crate::store::traits::{SubstateNodeAncestryRecord, SubstateNodeAncestryStore}; - pub struct SubstateOverlayIterator<'a> { root_db: Peekable + 'a>>, overlay: Peekable + 'a>>, diff --git a/core-rust/state-manager/src/staging/result.rs b/core-rust/state-manager/src/staging/result.rs index 143dc21111..28656d6eea 100644 --- a/core-rust/state-manager/src/staging/result.rs +++ b/core-rust/state-manager/src/staging/result.rs @@ -62,26 +62,7 @@ * permissions under this License. */ -use super::ReadableStateTreeStore; -use crate::accumulator_tree::storage::{ReadableAccuTreeStore, TreeSlice, WriteableAccuTreeStore}; - -use crate::engine_prelude::*; -use crate::staging::epoch_handling::EpochAwareAccuTreeFactory; -use crate::transaction::LedgerTransactionHash; -use crate::{ - ActiveValidatorInfo, ByPartition, BySubstate, DetailedTransactionOutcome, - EpochTransactionIdentifiers, LedgerHashes, LedgerStateChanges, LocalTransactionReceipt, - NextEpoch, PartitionChangeAction, ReceiptTreeHash, StateHash, StateVersion, - SubstateChangeAction, SubstateReference, TransactionTreeHash, -}; - -use crate::staging::ReadableStore; - -use crate::staging::node_ancestry_resolver::NodeAncestryResolver; -use crate::staging::overlays::{MapSubstateNodeAncestryStore, StagedSubstateNodeAncestryStore}; -use crate::store::traits::{ConfigurableDatabase, LeafSubstateKeyAssociation}; -use crate::store::traits::{KeyedSubstateNodeAncestryRecord, SubstateNodeAncestryStore}; -use node_common::utils::IsAccountExt; +use crate::prelude::*; pub enum ProcessedTransactionReceipt { Commit(ProcessedCommitResult), @@ -111,12 +92,6 @@ pub struct HashUpdateContext<'s, S> { pub ledger_transaction_hash: &'s LedgerTransactionHash, } -pub struct ExecutionFeeData { - pub fee_summary: TransactionFeeSummary, - pub engine_costing_parameters: CostingParameters, - pub transaction_costing_parameters: TransactionCostingParametersReceipt, -} - impl ProcessedTransactionReceipt { pub fn process( hash_update_context: HashUpdateContext, @@ -191,9 +166,7 @@ impl ProcessedCommitResult { let state_changes = Self::compute_ledger_state_changes(store, &commit_result.state_updates); - let database_updates = commit_result - .state_updates - .create_database_updates::(); + let database_updates = commit_result.state_updates.create_database_updates(); let GlobalBalanceUpdate { global_balance_summary, @@ -333,10 +306,8 @@ impl ProcessedCommitResult { }, }; for (substate_key, update) in substate_updates.as_ref() { - let previous_opt = store.get_substate( - &SpreadPrefixKeyMapper::to_db_partition_key(node_id, *partition_num), - &SpreadPrefixKeyMapper::to_db_sort_key(substate_key), - ); + let previous_opt = + store.get_raw_substate(node_id, *partition_num, substate_key); let change_action_opt = match (update, previous_opt) { (DatabaseUpdate::Set(new), Some(previous)) if previous != *new => { Some(SubstateChangeAction::Update { @@ -391,7 +362,7 @@ impl ProcessedCommitResult { } /// A summary of vault balances per global root entity. -#[derive(Debug, Clone, PartialEq, Eq, Default, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, PartialEq, Eq, Default, ScryptoSbor)] pub struct GlobalBalanceSummary { /// A cumulative balance change of each global root entity owning one or more vaults from the /// input "vault balance changes". @@ -651,10 +622,10 @@ impl<'s, S: SubstateDatabase + ConfigurableDatabase> WriteableTreeStore .push(LeafSubstateKeyAssociation { tree_node_key: state_tree_leaf_key.clone(), substate_value: match substate_value { - AssociatedSubstateValue::Upserted(value) => value.clone(), + AssociatedSubstateValue::Upserted(value) => value.to_vec(), AssociatedSubstateValue::Unchanged => self .readable_delegate - .get_substate(partition_key, sort_key) + .get_raw_substate_by_db_key(partition_key, sort_key) .expect("unchanged value not found in substate database"), }, }); diff --git a/core-rust/state-manager/src/state_manager.rs b/core-rust/state-manager/src/state_manager.rs index a7ad97b8cd..2ee9ad3ac9 100644 --- a/core-rust/state-manager/src/state_manager.rs +++ b/core-rust/state-manager/src/state_manager.rs @@ -62,40 +62,12 @@ * permissions under this License. */ -use std::ops::Deref; -use std::path::PathBuf; -use std::sync::Arc; -use std::time::Duration; - -use crate::engine_prelude::*; use crate::jni::LedgerSyncLimitsConfig; -use crate::protocol::{ - ProtocolConfig, ProtocolManager, ProtocolUpdateExecutor, ProtocolVersionName, -}; -use crate::store::jmt_gc::StateTreeGcConfig; +use crate::jni_prelude::*; +use crate::store::jmt_gc::*; use crate::store::proofs_gc::{LedgerProofsGc, LedgerProofsGcConfig}; -use crate::store::rocks_db::{ActualStateManagerDatabase, StateManagerDatabase}; -use crate::store::traits::proofs::QueryableProofStore; -use crate::store::traits::DatabaseConfigValidationError; -use crate::transaction::{ - ExecutionConfigurator, LedgerTransactionValidator, Preparator, TransactionExecutorFactory, -}; -use crate::{ - mempool_manager::MempoolManager, - mempool_relay_dispatcher::MempoolRelayDispatcher, - priority_mempool::PriorityMempool, - store::{jmt_gc::StateTreeGc, DatabaseBackendConfig, DatabaseConfig, RawDbMetricsCollector}, - transaction::{CachedCommittabilityValidator, CommittabilityValidator, TransactionPreviewer}, - Committer, ExecutionCacheManager, LedgerMetrics, PendingTransactionResultCache, - ProtocolUpdateResult, SystemExecutor, -}; -use node_common::java::{JavaError, JavaResult, StructFromJava}; + use node_common::scheduler::{Metrics, Scheduler, Spawner, Tracker}; -use node_common::{ - config::{limits::VertexLimitsConfig, MempoolConfig}, - locks::*, -}; -use prometheus::Registry; /// An interval between time-intensive measurement of raw DB metrics. /// Some of our raw DB metrics take ~a few milliseconds to collect. We cannot afford the overhead of @@ -104,7 +76,7 @@ use prometheus::Registry; /// (which in practice still runs more often than Prometheus' scraping). const RAW_DB_MEASUREMENT_INTERVAL: Duration = Duration::from_secs(10); -#[derive(Clone, Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Clone, Debug, ScryptoSbor)] pub struct StateManagerConfig { pub network_definition: NetworkDefinition, pub mempool_config: Option, @@ -183,7 +155,7 @@ pub struct StateManager { pub database: Arc>, pub mempool: Arc>, pub mempool_manager: Arc, - pub ledger_transaction_validator: Arc, + pub transaction_validator: Arc>, pub committability_validator: Arc>, pub transaction_previewer: Arc, pub preparator: Arc, @@ -193,7 +165,7 @@ pub struct StateManager { pub system_executor: Arc, pub pending_transaction_result_cache: Arc>, pub protocol_manager: Arc, - pub protocol_update_executor: Arc, + pub protocol_update_executor: Arc, pub ledger_metrics: Arc, } @@ -202,7 +174,7 @@ impl StateManager { config: StateManagerConfig, mempool_relay_dispatcher: Option, lock_factory: &LockFactory, - metrics_registry: &Registry, + metrics_registry: &MetricRegistry, scheduler: &Scheduler, ) -> Self { let StateManagerConfig { @@ -241,9 +213,9 @@ impl StateManager { let database = Arc::new(lock_factory.named("database").new_db_lock(raw_db)); - let ledger_transaction_validator = Arc::new( - LedgerTransactionValidator::default_from_network(&network_definition), - ); + let transaction_validator = Arc::new(lock_factory.named("validator").new_rwlock( + TransactionValidator::new(database.access_direct().deref(), &network_definition), + )); let protocol_manager = Arc::new(ProtocolManager::new( genesis_protocol_version, @@ -271,13 +243,13 @@ impl StateManager { Arc::new(lock_factory.named("pending_cache").new_rwlock( PendingTransactionResultCache::new(mempool.clone(), 10000, 10000), )); - let validation_config = ValidationConfig::default(network_definition.id); + let committability_validator = Arc::new(lock_factory.named("committability_validator").new_rwlock( CommittabilityValidator::new( database.clone(), execution_configurator.clone(), - NotarizedTransactionValidator::new(validation_config), + transaction_validator.clone(), ), )); let cached_committability_validator = CachedCommittabilityValidator::new( @@ -302,7 +274,7 @@ impl StateManager { let transaction_previewer = Arc::new(TransactionPreviewer::new( database.clone(), execution_configurator.clone(), - validation_config, + transaction_validator.clone(), )); let execution_cache_manager = @@ -316,7 +288,7 @@ impl StateManager { database.clone(), transaction_executor_factory.clone(), pending_transaction_result_cache.clone(), - ledger_transaction_validator.clone(), + transaction_validator.clone(), vertex_limits_config.unwrap_or_default(), metrics_registry, )); @@ -332,7 +304,7 @@ impl StateManager { let committer = Arc::new(Committer::new( database.clone(), transaction_executor_factory.clone(), - ledger_transaction_validator.clone(), + transaction_validator.clone(), mempool_manager.clone(), execution_cache_manager.clone(), pending_transaction_result_cache.clone(), @@ -347,7 +319,7 @@ impl StateManager { committer.clone(), )); - let protocol_update_executor = Arc::new(ProtocolUpdateExecutor::new( + let protocol_update_executor = Arc::new(NodeProtocolUpdateExecutor::new( network_definition.clone(), protocol_update_content_overrides, scenarios_execution_config, @@ -390,7 +362,7 @@ impl StateManager { database, mempool, mempool_manager, - ledger_transaction_validator, + transaction_validator, committability_validator, transaction_previewer, preparator, diff --git a/core-rust/state-manager/src/store/codecs.rs b/core-rust/state-manager/src/store/codecs.rs index c87c2e6aa5..4a322e868e 100644 --- a/core-rust/state-manager/src/store/codecs.rs +++ b/core-rust/state-manager/src/store/codecs.rs @@ -62,17 +62,10 @@ * permissions under this License. */ +use crate::prelude::*; use std::mem::size_of; use std::ops::Range; -use crate::engine_prelude::*; - -use crate::store::traits::indices::CreationId; -use crate::store::traits::scenario::ScenarioSequenceNumber; -use crate::transaction::RawLedgerTransaction; -use crate::StateVersion; -use node_common::store::typed_cf_api::*; - #[derive(Default)] pub struct StateVersionDbCodec {} @@ -123,11 +116,11 @@ pub struct RawLedgerTransactionDbCodec {} impl DbCodec for RawLedgerTransactionDbCodec { fn encode(&self, value: &RawLedgerTransaction) -> Vec { - value.0.to_vec() + value.as_slice().to_vec() } fn decode(&self, bytes: &[u8]) -> RawLedgerTransaction { - RawLedgerTransaction(bytes.to_vec()) + RawLedgerTransaction::from_slice(bytes) } } diff --git a/core-rust/state-manager/src/store/column_families.rs b/core-rust/state-manager/src/store/column_families.rs index 6a5756bb0c..13e478c62e 100644 --- a/core-rust/state-manager/src/store/column_families.rs +++ b/core-rust/state-manager/src/store/column_families.rs @@ -1,19 +1,8 @@ -use std::fmt; +use crate::prelude::*; -use radix_common::crypto::Hash; -use radix_common::prelude::{EntityType, Epoch, GlobalAddress, NodeId, PackageAddress}; use radix_substate_store_impls::state_tree::tree_store::*; -use radix_substate_store_interface::interface::{DbSubstateKey, DbSubstateValue}; -use radix_transactions::model::{IntentHash, NotarizedTransactionHash}; use crate::store::codecs::*; -use crate::store::traits::gc::{LedgerProofsGcProgress, VersionedLedgerProofsGcProgress}; -use crate::store::traits::indices::*; -use crate::store::traits::scenario::*; -use crate::store::traits::*; -use crate::transaction::{LedgerTransactionHash, RawLedgerTransaction}; -use crate::*; -use node_common::store::typed_cf_api::*; /// Committed transactions. /// Schema: `StateVersion.to_bytes()` -> `RawLedgerTransaction.as_ref::<[u8]>()` @@ -119,17 +108,17 @@ impl VersionedCf for ProtocolUpdateExecutionLedgerProofsCf { type VersionedValue = VersionedLedgerProof; } -/// DB "index" table for transaction's [`IntentHash`] resolution. -/// Schema: `IntentHash.as_ref::<[u8]>()` -> `StateVersion.to_bytes()` +/// DB "index" table for transaction's [`TransactionIntentHash`] resolution. +/// Schema: `TransactionIntentHash.as_ref::<[u8]>()` -> `StateVersion.to_bytes()` /// Note: This table does not use explicit versioning wrapper, since the value represents a DB /// key of another table (and versioning DB keys is not useful). pub struct IntentHashesCf; impl DefaultCf for IntentHashesCf { - type Key = IntentHash; + type Key = TransactionIntentHash; type Value = StateVersion; const DEFAULT_NAME: &'static str = "intent_hashes"; - type KeyCodec = HashDbCodec; + type KeyCodec = HashDbCodec; type ValueCodec = StateVersionDbCodec; } diff --git a/core-rust/state-manager/src/store/historical_state.rs b/core-rust/state-manager/src/store/historical_state.rs index 6a3accc1db..e4172f8d66 100644 --- a/core-rust/state-manager/src/store/historical_state.rs +++ b/core-rust/state-manager/src/store/historical_state.rs @@ -62,16 +62,8 @@ * permissions under this License. */ -use std::ops::Deref; - -use crate::engine_prelude::entity_tier::EntityTier; -use crate::engine_prelude::*; -use crate::query::StateManagerSubstateQueries; -use crate::store::rocks_db::StateManagerDatabase; -use crate::store::traits::indices::{CreationId, EntityBlueprintId, EntityListingIndex}; -use crate::store::traits::*; -use crate::{CommittedTransactionIdentifiers, LedgerStateSummary, StateVersion}; -use node_common::store::rocks_db::ReadableRocks; +use crate::prelude::*; +use entity_tier::EntityTier; /// An implementation of a [`SubstateDatabase`] viewed at a specific [`StateVersion`]. /// @@ -166,7 +158,7 @@ impl<'s, S: ReadableTreeStore + 's, DS: Deref> StateTreeBasedSubstat impl<'s, S: ReadableTreeStore + LeafSubstateValueStore + 's, DS: Deref> SubstateDatabase for StateTreeBasedSubstateDatabase<'s, DS> { - fn get_substate( + fn get_raw_substate_by_db_key( &self, partition_key: &DbPartitionKey, sort_key: &DbSortKey, @@ -178,7 +170,7 @@ impl<'s, S: ReadableTreeStore + LeafSubstateValueStore + 's, DS: Deref, @@ -313,32 +305,32 @@ impl<'s, R: ReadableRocks + 's, DS: Deref>> impl<'s, R: ReadableRocks + 's, DS: Deref>> SubstateDatabase for VersionScopedDatabase<'s, DS> { - fn get_substate( + fn get_raw_substate_by_db_key( &self, partition_key: &DbPartitionKey, sort_key: &DbSortKey, ) -> Option { match self { VersionScopedDatabase::Current(database) => { - database.get_substate(partition_key, sort_key) + database.get_raw_substate_by_db_key(partition_key, sort_key) } VersionScopedDatabase::Historical(database) => { - database.get_substate(partition_key, sort_key) + database.get_raw_substate_by_db_key(partition_key, sort_key) } } } - fn list_entries_from( + fn list_raw_values_from_db_key( &self, partition_key: &DbPartitionKey, from_sort_key: Option<&DbSortKey>, ) -> Box + '_> { match self { VersionScopedDatabase::Current(database) => { - database.list_entries_from(partition_key, from_sort_key) + database.list_raw_values_from_db_key(partition_key, from_sort_key) } VersionScopedDatabase::Historical(database) => { - database.list_entries_from(partition_key, from_sort_key) + database.list_raw_values_from_db_key(partition_key, from_sort_key) } } } @@ -483,11 +475,11 @@ mod tests { .put_substate_changes(vec![change(8, 7, 2, Some(8)), change(8, 1, 9, Some(1))]); let subject_v1 = test_stores.create_subject(v1); - let value_v1 = subject_v1.get_substate(&partition_key(8, 7), &sort_key(2)); + let value_v1 = subject_v1.get_raw_substate_by_db_key(&partition_key(8, 7), &sort_key(2)); assert_eq!(value_v1, Some(from_seed(7))); let subject_v2 = test_stores.create_subject(v2); - let value_v2 = subject_v2.get_substate(&partition_key(8, 7), &sort_key(2)); + let value_v2 = subject_v2.get_raw_substate_by_db_key(&partition_key(8, 7), &sort_key(2)); assert_eq!(value_v2, Some(from_seed(8))); } @@ -503,11 +495,11 @@ mod tests { test_stores.reset_partition(&partition_key(8, 7), vec![(sort_key(2), from_seed(9))]); let subject_v1 = test_stores.create_subject(v1); - let value_v1 = subject_v1.get_substate(&partition_key(8, 7), &sort_key(2)); + let value_v1 = subject_v1.get_raw_substate_by_db_key(&partition_key(8, 7), &sort_key(2)); assert_eq!(value_v1, Some(from_seed(7))); let subject_v2 = test_stores.create_subject(v2); - let value_v2 = subject_v2.get_substate(&partition_key(8, 7), &sort_key(2)); + let value_v2 = subject_v2.get_raw_substate_by_db_key(&partition_key(8, 7), &sort_key(2)); assert_eq!(value_v2, Some(from_seed(9))); } @@ -523,9 +515,9 @@ mod tests { .put_substate_changes(vec![change(8, 7, 2, Some(8)), change(8, 1, 9, Some(1))]); let subject_v1 = test_stores.create_subject(v1); - let value_v1 = subject_v1.get_substate(&partition_key(8, 6), &sort_key(3)); + let value_v1 = subject_v1.get_raw_substate_by_db_key(&partition_key(8, 6), &sort_key(3)); let subject_v2 = test_stores.create_subject(v2); - let value_v2 = subject_v2.get_substate(&partition_key(8, 6), &sort_key(3)); + let value_v2 = subject_v2.get_raw_substate_by_db_key(&partition_key(8, 6), &sort_key(3)); assert_eq!(value_v2, value_v1); } @@ -541,11 +533,11 @@ mod tests { .put_substate_changes(vec![change(8, 7, 2, Some(8)), change(8, 1, 9, Some(1))]); let subject_v1 = test_stores.create_subject(v1); - let value_v1 = subject_v1.get_substate(&partition_key(8, 1), &sort_key(9)); + let value_v1 = subject_v1.get_raw_substate_by_db_key(&partition_key(8, 1), &sort_key(9)); assert_eq!(value_v1, None); let subject_v2 = test_stores.create_subject(v2); - let value_v2 = subject_v2.get_substate(&partition_key(8, 1), &sort_key(9)); + let value_v2 = subject_v2.get_raw_substate_by_db_key(&partition_key(8, 1), &sort_key(9)); assert_eq!(value_v2, Some(from_seed(1))); } @@ -561,11 +553,11 @@ mod tests { test_stores.put_substate_changes(vec![change(8, 7, 2, None), change(8, 1, 9, Some(1))]); let subject_v2 = test_stores.create_subject(v2); - let value_v2 = subject_v2.get_substate(&partition_key(8, 7), &sort_key(2)); + let value_v2 = subject_v2.get_raw_substate_by_db_key(&partition_key(8, 7), &sort_key(2)); assert_eq!(value_v2, None); let subject_v1 = test_stores.create_subject(v1); - let value_v1 = subject_v1.get_substate(&partition_key(8, 7), &sort_key(2)); + let value_v1 = subject_v1.get_raw_substate_by_db_key(&partition_key(8, 7), &sort_key(2)); assert_eq!(value_v1, Some(from_seed(7))); } @@ -580,11 +572,11 @@ mod tests { let v2 = test_stores.reset_partition(&partition_key(8, 7), vec![]); let subject_v2 = test_stores.create_subject(v2); - let value_v2 = subject_v2.get_substate(&partition_key(8, 7), &sort_key(2)); + let value_v2 = subject_v2.get_raw_substate_by_db_key(&partition_key(8, 7), &sort_key(2)); assert_eq!(value_v2, None); let subject_v1 = test_stores.create_subject(v1); - let value_v1 = subject_v1.get_substate(&partition_key(8, 7), &sort_key(2)); + let value_v1 = subject_v1.get_raw_substate_by_db_key(&partition_key(8, 7), &sort_key(2)); assert_eq!(value_v1, Some(from_seed(7))); } @@ -607,7 +599,7 @@ mod tests { let subject_v1 = test_stores.create_subject(v1); let substates_v1 = subject_v1 - .list_entries_from(&partition_key(8, 7), None) + .list_raw_values_from_db_key(&partition_key(8, 7), None) .collect::>(); assert_eq!( substates_v1, @@ -620,7 +612,7 @@ mod tests { let subject_v2 = test_stores.create_subject(v2); let substates_v2 = subject_v2 - .list_entries_from(&partition_key(8, 7), None) + .list_raw_values_from_db_key(&partition_key(8, 7), None) .collect::>(); assert_eq!( substates_v2, @@ -644,7 +636,7 @@ mod tests { let subject = test_stores.create_subject(the_only_version); let all_substates = subject - .list_entries_from(&partition_key(8, 7), None) + .list_raw_values_from_db_key(&partition_key(8, 7), None) .collect::>(); assert_eq!( all_substates, @@ -657,22 +649,22 @@ mod tests { ); let from_existent = subject - .list_entries_from(&partition_key(8, 7), Some(&sort_key(2))) + .list_raw_values_from_db_key(&partition_key(8, 7), Some(&sort_key(2))) .collect::>(); assert_eq!(from_existent, all_substates[1..]); let from_non_existent = subject - .list_entries_from(&partition_key(8, 7), Some(&sort_key(3))) + .list_raw_values_from_db_key(&partition_key(8, 7), Some(&sort_key(3))) .collect::>(); assert_eq!(from_non_existent, all_substates[2..]); let from_lt_min = subject - .list_entries_from(&partition_key(8, 7), Some(&sort_key(0))) + .list_raw_values_from_db_key(&partition_key(8, 7), Some(&sort_key(0))) .collect::>(); assert_eq!(from_lt_min, all_substates); let from_gt_max = subject - .list_entries_from(&partition_key(8, 7), Some(&sort_key(9))) + .list_raw_values_from_db_key(&partition_key(8, 7), Some(&sort_key(9))) .collect::>(); assert_eq!(from_gt_max, vec![]); } diff --git a/core-rust/state-manager/src/store/jmt_gc.rs b/core-rust/state-manager/src/store/jmt_gc.rs index a2ba3822d6..aa2094dd18 100644 --- a/core-rust/state-manager/src/store/jmt_gc.rs +++ b/core-rust/state-manager/src/store/jmt_gc.rs @@ -62,26 +62,15 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use node_common::locks::DbLock; +use crate::prelude::*; use std::iter; -use std::ops::Deref; -use std::sync::Arc; -use std::time::Duration; -use tracing::info; - -use crate::store::rocks_db::ActualStateManagerDatabase; -use crate::store::traits::gc::StateTreeGcStore; -use crate::store::traits::proofs::QueryableProofStore; -use crate::store::traits::StaleTreePartsV1; -use crate::{StateVersion, StateVersionDelta}; /// A maximum number of JMT nodes collected into "batch delete" buffer. /// Needed only to avoid OOM problems. const DELETED_NODE_BUFFER_MAX_LEN: usize = 1000000; /// A configuration for [`StateTreeGc`]. -#[derive(Debug, Categorize, Encode, Decode, Clone, Default)] +#[derive(Debug, Clone, Default, Sbor)] pub struct StateTreeGcConfig { /// How often to run the GC, in seconds. /// This should be at least an order of magnitude shorter than an expected duration over which diff --git a/core-rust/state-manager/src/store/mod.rs b/core-rust/state-manager/src/store/mod.rs index 5263dee145..dadf61e04f 100644 --- a/core-rust/state-manager/src/store/mod.rs +++ b/core-rust/state-manager/src/store/mod.rs @@ -62,17 +62,10 @@ * permissions under this License. */ -use std::sync::Arc; +use crate::prelude::*; -use prometheus::Registry; -use sbor::{Categorize, Decode, Encode}; - -use node_common::locks::DbLock; -use rocks_db::ActualStateManagerDatabase; - -use crate::RawDbMetrics; -use traits::measurement::MeasurableDatabase; -pub use traits::DatabaseConfig; +pub use rocks_db::{ActualStateManagerDatabase, StateManagerDatabase}; +pub use traits::*; mod codecs; pub mod column_families; @@ -80,9 +73,9 @@ pub mod historical_state; pub mod jmt_gc; pub mod proofs_gc; pub mod rocks_db; -pub mod traits; +mod traits; -#[derive(Debug, Categorize, Encode, Decode, Clone)] +#[derive(Debug, Clone, Sbor)] pub struct DatabaseBackendConfig { pub rocks_db_path: String, } @@ -97,7 +90,7 @@ impl RawDbMetricsCollector { /// Creates a collector measuring the given DB and updating the metrics in the given registry. pub fn new( database: Arc>, - metric_registry: &Registry, + metric_registry: &MetricRegistry, ) -> Self { Self { database, diff --git a/core-rust/state-manager/src/store/proofs_gc.rs b/core-rust/state-manager/src/store/proofs_gc.rs index e08201d3e4..78d1fc05b2 100644 --- a/core-rust/state-manager/src/store/proofs_gc.rs +++ b/core-rust/state-manager/src/store/proofs_gc.rs @@ -62,29 +62,10 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use node_common::locks::DbLock; -use std::ops::Deref; -use std::sync::Arc; -use std::time::Duration; -use tracing::{error, info}; - -use crate::store::traits::gc::{ - LedgerProofsGcProgress, LedgerProofsGcProgressV1, LedgerProofsGcStore, -}; -use crate::store::traits::proofs::QueryableProofStore; - -use crate::jni::LedgerSyncLimitsConfig; -use crate::store::rocks_db::{ActualStateManagerDatabase, StateManagerDatabase}; -use crate::store::traits::GetSyncableTxnsAndProofError::{ - FailedToPrepareAResponseWithinLimits, NothingToServeAtTheGivenStateVersion, - RefusedToServeGenesis, RefusedToServeProtocolUpdate, -}; -use crate::{LedgerProof, StateVersion}; -use node_common::store::rocks_db::ReadableRocks; +use crate::prelude::*; /// A configuration for [`LedgerProofsGc`]. -#[derive(Debug, Categorize, Encode, Decode, Clone, Default)] +#[derive(Debug, Clone, Default, Sbor)] pub struct LedgerProofsGcConfig { /// How often to run the GC, in seconds. /// Since this GC operates with an epoch precision, we do not need to run more often than epoch @@ -248,11 +229,11 @@ impl LedgerProofsGc { } Err(err) => { match err { - NothingToServeAtTheGivenStateVersion => { + GetSyncableTxnsAndProofError::NothingToServeAtTheGivenStateVersion => { // No more proofs return None; } - RefusedToServeGenesis { refused_proof } => { + GetSyncableTxnsAndProofError::RefusedToServeGenesis { refused_proof } => { // We have encountered the genesis proof, which shouldn't be pruned. // Skipping to the next (post-proof) state version. skipped_proofs += 1; @@ -263,7 +244,9 @@ impl LedgerProofsGc { .expect("state version overflow"); continue; } - RefusedToServeProtocolUpdate { refused_proof } => { + GetSyncableTxnsAndProofError::RefusedToServeProtocolUpdate { + refused_proof, + } => { // Similarly here, we're skipping all protocol update // state versions and retrying from the next (post-update) // version in the next iteration. @@ -275,7 +258,7 @@ impl LedgerProofsGc { .expect("state version overflow"); continue; } - FailedToPrepareAResponseWithinLimits => { + GetSyncableTxnsAndProofError::FailedToPrepareAResponseWithinLimits => { // That's an error error!( "A chain of transactions-without-proof from state version {} does not fit within the limits {:?}; aborting the GC", @@ -308,16 +291,8 @@ impl ProofPruneRange { #[cfg(test)] mod tests { - use crate::engine_prelude::*; - use crate::jni::LedgerSyncLimitsConfig; - use crate::proofs_gc::{LedgerProofsGc, LedgerProofsGcConfig}; - use crate::protocol::*; - use crate::store::traits::proofs::QueryableProofStore; - use crate::store::traits::GetSyncableTxnsAndProofError; + use super::*; use crate::test::{commit_round_updates_until_epoch, create_state_manager}; - use crate::{StateManagerConfig, StateVersion}; - - use std::time::Duration; #[test] fn test_retain_protocol_update_proofs() { diff --git a/core-rust/state-manager/src/store/rocks_db.rs b/core-rust/state-manager/src/store/rocks_db.rs index d4775a6f4b..9f25840bf0 100644 --- a/core-rust/state-manager/src/store/rocks_db.rs +++ b/core-rust/state-manager/src/store/rocks_db.rs @@ -62,40 +62,12 @@ * permissions under this License. */ -use std::collections::HashSet; -use std::path::PathBuf; +use crate::prelude::*; -use node_common::rocksdb::{ColumnFamilyDescriptor, Direction, IteratorMode, Options, DB}; -use tracing::{error, info, warn}; - -use node_common::locks::Snapshottable; -use node_common::utils::IsAccountExt; - -use crate::accumulator_tree::storage::{ReadableAccuTreeStore, TreeSlice}; -use crate::engine_prelude::*; -use crate::query::TransactionIdentifierLoader; use crate::store::column_families::*; use crate::store::historical_state::StateTreeBasedSubstateDatabase; -use crate::store::traits::extensions::*; -use crate::store::traits::gc::{LedgerProofsGcProgress, LedgerProofsGcStore, StateTreeGcStore}; -use crate::store::traits::indices::{ - CreationId, EntityBlueprintId, EntityListingIndex, ObjectBlueprintNameV1, -}; -use crate::store::traits::measurement::{CategoryDbVolumeStatistic, MeasurableDatabase}; -use crate::store::traits::scenario::{ - ExecutedScenario, ExecutedScenarioStore, ScenarioSequenceNumber, -}; use crate::store::traits::*; -use crate::transaction::{ - LedgerTransactionHash, RawLedgerTransaction, TypedTransactionIdentifiers, -}; -use crate::{ - BySubstate, CommittedTransactionIdentifiers, LedgerProof, LedgerProofOrigin, - LedgerTransactionReceipt, LocalTransactionExecution, LocalTransactionReceipt, ReceiptTreeHash, - StateVersion, SubstateChangeAction, TransactionTreeHash, -}; -use node_common::store::rocks_db::*; -use node_common::store::typed_cf_api::*; +use rocksdb::*; /// A listing of all column family names used by the Node. /// @@ -425,7 +397,7 @@ impl StateManagerDatabase { let substate_leaf_keys = substate_database.iter_substate_leaf_keys(); for (tree_node_key, (partition_key, sort_key)) in substate_leaf_keys { let value = self - .get_substate(&partition_key, &sort_key) + .get_raw_substate_by_db_key(&partition_key, &sort_key) .expect("substate value referenced by hash tree does not exist"); associated_values_cf.put(&tree_node_key, &value); if db_context.buffered_data_size() >= SUBSTATE_BATCH_BYTE_SIZE { @@ -525,14 +497,12 @@ impl CommitStore for StateManagerDatabase { let commit_state_version = commit_ledger_header.state_version; for transaction_bundle in commit_bundle.transactions { - let payload_identifiers = &transaction_bundle.identifiers.payload; - if let TypedTransactionIdentifiers::User { intent_hash, .. } = - &payload_identifiers.typed - { - processed_intent_hashes.insert(*intent_hash); + let hashes = &transaction_bundle.identifiers.transaction_hashes; + if let Some(user_hashes) = hashes.as_user() { + processed_intent_hashes.insert(user_hashes.transaction_intent_hash); user_transactions_count += 1; } - processed_ledger_transaction_hashes.insert(payload_identifiers.ledger_transaction_hash); + processed_ledger_transaction_hashes.insert(hashes.ledger_transaction_hash); self.add_transaction_to_write_batch(&db_context, transaction_bundle); } @@ -668,29 +638,30 @@ impl StateManagerDatabase { receipt, identifiers, } = transaction_bundle; - let ledger_transaction_hash = identifiers.payload.ledger_transaction_hash; + let ledger_transaction_hash = identifiers.transaction_hashes.ledger_transaction_hash; // TEMPORARY until this is handled in the engine: we store both an intent lookup and the transaction itself - if let TypedTransactionIdentifiers::User { - intent_hash, + if let Some(UserTransactionHashes { + transaction_intent_hash, notarized_transaction_hash, .. - } = &identifiers.payload.typed + }) = identifiers.transaction_hashes.as_user().as_ref() { /* For user transactions we only need to check for duplicate intent hashes to know that user payload hash and ledger payload hash are also unique. */ - let maybe_existing_state_version = db_context.cf(IntentHashesCf).get(intent_hash); + let maybe_existing_state_version = + db_context.cf(IntentHashesCf).get(transaction_intent_hash); if let Some(existing_state_version) = maybe_existing_state_version { panic!( "Attempted to save intent hash {:?} which already exists at state version {:?}", - intent_hash, existing_state_version + transaction_intent_hash, existing_state_version ); } db_context .cf(IntentHashesCf) - .put(intent_hash, &state_version); + .put(transaction_intent_hash, &state_version); db_context .cf(NotarizedTransactionHashesCf) .put(notarized_transaction_hash, &state_version); @@ -905,10 +876,10 @@ impl QueryableTransactionStore for StateManagerDatabase { } } -impl TransactionIndex<&IntentHash> for StateManagerDatabase { +impl TransactionIndex<&TransactionIntentHash> for StateManagerDatabase { fn get_txn_state_version_by_identifier( &self, - intent_hash: &IntentHash, + intent_hash: &TransactionIntentHash, ) -> Option { self.open_read_context().cf(IntentHashesCf).get(intent_hash) } @@ -1072,7 +1043,7 @@ impl QueryableProofStore for StateManagerDatabase { { match txns_iter.next() { Some((next_txn_state_version, next_txn)) => { - payload_size_including_next_proof_txns += next_txn.0.len() as u32; + payload_size_including_next_proof_txns += next_txn.len() as u32; next_proof_txns.push(next_txn); if next_txn_state_version == next_proof_state_version { @@ -1216,7 +1187,7 @@ impl StateManagerDatabase { } impl SubstateDatabase for StateManagerDatabase { - fn get_substate( + fn get_raw_substate_by_db_key( &self, partition_key: &DbPartitionKey, sort_key: &DbSortKey, @@ -1226,7 +1197,7 @@ impl SubstateDatabase for StateManagerDatabase { .get(&(partition_key.clone(), sort_key.clone())) } - fn list_entries_from( + fn list_raw_values_from_db_key( &self, partition_key: &DbPartitionKey, from_sort_key: Option<&DbSortKey>, diff --git a/core-rust/state-manager/src/store/traits.rs b/core-rust/state-manager/src/store/traits.rs index c041434502..8704fe489a 100644 --- a/core-rust/state-manager/src/store/traits.rs +++ b/core-rust/state-manager/src/store/traits.rs @@ -65,13 +65,15 @@ use std::cmp::Ordering; use std::iter::Peekable; -use crate::engine_prelude::*; +use crate::prelude::*; use crate::staging::StateTreeDiff; - -use crate::transaction::*; -use crate::{CommittedTransactionIdentifiers, LedgerProof, LocalTransactionReceipt, StateVersion}; pub use commit::*; +pub use extensions::*; +pub use gc::*; +pub use indices::*; +pub use measurement::*; pub use proofs::*; +pub use scenario::*; pub use substate::*; pub use transactions::*; pub use vertex::*; @@ -83,7 +85,7 @@ pub enum DatabaseConfigValidationError { } /// Database flags required for initialization built from config file and environment variables. -#[derive(Debug, Categorize, Encode, Decode, Clone)] +#[derive(Debug, Clone, Sbor)] pub struct DatabaseConfig { pub enable_local_transaction_execution_index: bool, pub enable_account_change_index: bool, @@ -181,19 +183,16 @@ pub mod vertex { } define_single_versioned! { - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub VersionedVertexStoreBlob(VertexStoreBlobVersions) => VertexStoreBlob = VertexStoreBlobV1 } - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub struct VertexStoreBlobV1(pub Vec); } pub mod substate { use super::*; - use std::slice; - - use crate::SubstateReference; /// A low-level storage of [`SubstateNodeAncestryRecord`]. /// @@ -207,7 +206,7 @@ pub mod substate { /// - the `node_id` happens to be a root Node (since they do not have "ancestry"); /// - or the `node_id` does not exist yet. fn get_ancestry(&self, node_id: &NodeId) -> Option { - let records = self.batch_get_ancestry(slice::from_ref(node_id)); + let records = self.batch_get_ancestry([node_id]); if records.len() != 1 { panic!( "trait contract violated: expected a single result for {:?}, got {:?}", @@ -231,12 +230,12 @@ pub mod substate { } define_single_versioned! { - #[derive(Debug, Clone, Eq, PartialEq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, Eq, PartialEq, ScryptoSbor)] pub VersionedSubstateNodeAncestryRecord(SubstateNodeAncestryRecordVersions) => SubstateNodeAncestryRecord = SubstateNodeAncestryRecordV1 } /// Ancestry information of a RE Node. - #[derive(Debug, Clone, Eq, PartialEq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, Eq, PartialEq, ScryptoSbor)] pub struct SubstateNodeAncestryRecordV1 { /// A substate owning the Node (i.e. its immediate parent). /// Note: this will always be present, since we do not need ancestry of root RE Nodes. @@ -264,12 +263,6 @@ pub mod substate { pub mod transactions { use super::*; - use crate::store::traits::CommittedTransactionBundle; - use crate::{ - CommittedTransactionIdentifiers, LedgerHashes, LedgerTransactionReceipt, - LocalTransactionExecution, LocalTransactionReceipt, - }; - pub trait IterableTransactionStore { fn get_committed_transaction_bundle_iter( &self, @@ -366,13 +359,13 @@ pub mod proofs { fn get_latest_protocol_update_execution_proof(&self) -> Option; } - #[derive(Clone, Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Clone, Debug, ScryptoSbor)] pub struct TxnsAndProof { pub txns: Vec, pub proof: LedgerProof, } - #[derive(Clone, Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Clone, Debug, ScryptoSbor)] pub enum GetSyncableTxnsAndProofError { RefusedToServeGenesis { refused_proof: Box }, RefusedToServeProtocolUpdate { refused_proof: Box }, @@ -383,8 +376,6 @@ pub mod proofs { pub mod commit { use super::*; - use crate::accumulator_tree::storage::TreeSlice; - use crate::{ReceiptTreeHash, StateVersion, TransactionTreeHash}; pub struct CommitBundle { pub transactions: Vec, @@ -507,11 +498,11 @@ pub mod commit { } define_single_versioned! { - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub VersionedStaleTreeParts(StaleTreePartsVersions) => StaleTreeParts = StaleTreePartsV1 } - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub struct StaleTreePartsV1(pub Vec); pub struct StateTreeUpdate { @@ -551,19 +542,19 @@ pub mod commit { } define_single_versioned! { - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub VersionedTransactionAccuTreeSlice(TransactionAccuTreeSliceVersions) => TransactionAccuTreeSlice = TransactionAccuTreeSliceV1 } - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub struct TransactionAccuTreeSliceV1(pub TreeSlice); define_single_versioned! { - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub VersionedReceiptAccuTreeSlice(ReceiptAccuTreeSliceVersions) => ReceiptAccuTreeSlice = ReceiptAccuTreeSliceV1 } - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub struct ReceiptAccuTreeSliceV1(pub TreeSlice); pub trait CommitStore { @@ -577,28 +568,28 @@ pub mod scenario { pub type ScenarioSequenceNumber = u32; define_single_versioned! { - #[derive(Debug, Clone, Categorize, Encode, Decode)] + #[derive(Debug, Clone, Sbor)] pub VersionedExecutedScenario(ExecutedScenarioVersions) => ExecutedScenario = ExecutedScenarioV1 } - #[derive(Debug, Clone, Categorize, Encode, Decode)] + #[derive(Debug, Clone, Sbor)] pub struct ExecutedScenarioV1 { pub logical_name: String, pub committed_transactions: Vec, pub addresses: Vec, } - #[derive(Debug, Clone, Categorize, Encode, Decode)] + #[derive(Debug, Clone, Sbor)] pub struct DescribedAddressRendering { pub logical_name: String, pub rendered_address: String, // we store it pre-rendered, since `GlobalAddress` has no SBOR coding } - #[derive(Debug, Clone, Categorize, Encode, Decode)] + #[derive(Debug, Clone, Sbor)] pub struct ExecutedScenarioTransaction { pub logical_name: String, pub state_version: StateVersion, - pub intent_hash: IntentHash, + pub transaction_intent_hash: TransactionIntentHash, } /// A store of testing-specific [`ExecutedScenario`], meant to be as separated as possible from @@ -709,13 +700,13 @@ pub mod indices { } define_single_versioned! { - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub VersionedEntityBlueprintId(EntityBlueprintIdVersions) => EntityBlueprintId = EntityBlueprintIdV1 } /// An entity's ID and its blueprint reference. /// This is a "technical" structure stored in one of the Entity-listing indices. - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub struct EntityBlueprintIdV1 { /// Node ID. pub node_id: NodeId, @@ -743,13 +734,13 @@ pub mod indices { } define_single_versioned! { - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub VersionedObjectBlueprintName(ObjectBlueprintNameVersions) => ObjectBlueprintName = ObjectBlueprintNameV1 } /// An Object's ID and its blueprint name. /// This is a "technical" structure stored in one of the Entity-listing indices. - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub struct ObjectBlueprintNameV1 { /// Node ID - guaranteed to *not* be a Key-Value Store. pub node_id: NodeId, @@ -827,7 +818,6 @@ pub mod measurement { pub mod gc { use super::*; - use crate::LedgerHeader; /// A storage API tailored for the [`StateTreeGc`]. pub trait StateTreeGcStore { @@ -861,12 +851,12 @@ pub mod gc { } define_single_versioned! { - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub VersionedLedgerProofsGcProgress(LedgerProofsGcProgressVersions) => LedgerProofsGcProgress = LedgerProofsGcProgressV1 } /// A state of the GC's progress. - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub struct LedgerProofsGcProgressV1 { /// The last epoch pruned by the GC. The next run should start from the beginning of the /// next epoch. diff --git a/core-rust/state-manager/src/system_commits.rs b/core-rust/state-manager/src/system_commits.rs index 09a72eddd1..e70d96567f 100644 --- a/core-rust/state-manager/src/system_commits.rs +++ b/core-rust/state-manager/src/system_commits.rs @@ -62,9 +62,7 @@ * permissions under this License. */ -use crate::engine_prelude::*; -use crate::transaction::*; -use crate::*; +use crate::prelude::*; pub struct SystemCommitRequestFactory { pub epoch: Epoch, @@ -117,7 +115,7 @@ impl SystemCommitRequestFactory { /// An input to [`SystemCommitRequestFactory::create()`]. pub struct SystemPrepareResult { - pub committed_transactions: Vec, + pub committed_transactions: Vec, pub ledger_hashes: LedgerHashes, pub next_epoch: Option, } @@ -126,7 +124,7 @@ impl SystemPrepareResult { /// Creates an instance for committing the given pre-validated transactions, using the current /// end-state of the given series executor. pub fn from_committed_series( - committed_transactions: Vec, + committed_transactions: Vec, series_executor: TransactionSeriesExecutor, ) -> Self { Self { @@ -139,7 +137,7 @@ impl SystemPrepareResult { /// An output from [`SystemCommitRequestFactory::create()`]. pub struct SystemCommitRequest { - pub transactions: Vec, + pub transactions: Vec, pub proof: LedgerProof, pub require_committed_successes: bool, } @@ -152,7 +150,8 @@ impl SystemCommitRequest { } } -pub struct RawAndValidatedTransaction { +pub struct ProcessedLedgerTransaction { pub raw: RawLedgerTransaction, - pub validated: ValidatedLedgerTransaction, + pub executable: LedgerExecutable, + pub hashes: LedgerTransactionHashes, } diff --git a/core-rust/state-manager/src/system_executor.rs b/core-rust/state-manager/src/system_executor.rs index 0b02dde307..7b9410813e 100644 --- a/core-rust/state-manager/src/system_executor.rs +++ b/core-rust/state-manager/src/system_executor.rs @@ -62,30 +62,11 @@ * permissions under this License. */ -use crate::query::*; +use crate::prelude::*; -use crate::store::traits::*; -use crate::transaction::*; - -use crate::*; - -use crate::engine_prelude::*; - -use node_common::locks::DbLock; - -use tracing::info; - -use crate::store::traits::scenario::{ - DescribedAddressRendering, ExecutedScenario, ExecutedScenarioStore, ExecutedScenarioTransaction, -}; use crate::system_commits::*; -use crate::protocol::{ProtocolUpdateNodeBatch, ProtocolVersionName}; -use crate::store::rocks_db::ActualStateManagerDatabase; -use crate::store::traits::scenario::ExecutedScenarioV1; -use radix_transaction_scenarios::scenarios::ALL_SCENARIOS; -use std::sync::Arc; -use std::time::Instant; +use radix_transaction_scenarios::scenarios::get_scenario; pub struct SystemExecutor { network: NetworkDefinition, @@ -122,7 +103,7 @@ impl SystemExecutor { faucet_supply: Decimal, genesis_scenarios: Vec, ) -> LedgerProof { - let start_instant = Instant::now(); + let start_instant = StdInstant::now(); let database = self.database.lock(); if database.get_post_genesis_epoch_proof().is_some() { @@ -184,8 +165,7 @@ impl SystemExecutor { index + 1, genesis_data_chunks_len ); - let transaction = - create_genesis_data_ingestion_transaction(&GENESIS_HELPER, chunk, index); + let transaction = create_genesis_data_ingestion_transaction(chunk, index); let prepare_result = self .preparator .prepare_genesis(GenesisTransaction::Transaction(Box::new(transaction))); @@ -214,7 +194,7 @@ impl SystemExecutor { pub fn execute_protocol_update_action( &self, protocol_version: &ProtocolVersionName, - batch_idx: u32, + batch_index: usize, batch: ProtocolUpdateNodeBatch, ) { let database = self.database.lock(); @@ -240,13 +220,13 @@ impl SystemExecutor { state_version: latest_header.state_version, proof_origin: LedgerProofOrigin::ProtocolUpdate { protocol_version_name: protocol_version.clone(), - batch_idx, + batch_index: batch_index as u32, }, }; match batch { - ProtocolUpdateNodeBatch::FlashTransactions(flash_transactions) => { - let prepare_result = self.preparator.prepare_protocol_update(flash_transactions); + ProtocolUpdateNodeBatch::ProtocolUpdateBatch(batch) => { + let prepare_result = self.preparator.prepare_protocol_update(batch); let commit_request = system_commit_request_factory.create(prepare_result); self.committer.commit_system(commit_request); } @@ -359,20 +339,17 @@ impl SystemExecutor { starting_nonce: u32, scenario_name: &str, ) -> Box { - ALL_SCENARIOS - .get(scenario_name) - .expect(scenario_name) - .create(ScenarioCore::new( - self.network.clone(), - epoch, - starting_nonce, - )) + get_scenario(scenario_name).create(ScenarioCore::new( + self.network.clone(), + epoch, + starting_nonce, + )) } fn create_executed_scenario_entry( &self, logical_name: &str, - committed_transactions: &[RawAndValidatedTransaction], + committed_transactions: &[ProcessedLedgerTransaction], committed_transaction_names: Vec<(StateVersion, String)>, output: ScenarioOutput, ) -> ExecutedScenario { @@ -386,7 +363,11 @@ impl SystemExecutor { |(transaction, (state_version, logical_name))| ExecutedScenarioTransaction { logical_name, state_version, - intent_hash: transaction.validated.intent_hash_if_user().unwrap(), + transaction_intent_hash: transaction + .hashes + .as_user() + .unwrap() + .transaction_intent_hash, }, ) .collect(), @@ -419,7 +400,7 @@ fn log_executed_scenario_details(executed_scenario: &ExecutedScenario) { let ExecutedScenarioTransaction { logical_name, state_version, - intent_hash, + transaction_intent_hash: intent_hash, } = committed_transaction; info!( "Committed {} at state version {} ({:?})", @@ -452,7 +433,7 @@ impl SystemExecutor { let genesis_chunks = vec![ GenesisDataChunk::Validators(vec![genesis_validator.clone()]), GenesisDataChunk::Stakes { - accounts: vec![ComponentAddress::virtual_account_from_public_key( + accounts: vec![ComponentAddress::preallocated_account_from_public_key( &genesis_validator.key, )], allocations: vec![( @@ -499,14 +480,7 @@ impl SystemExecutor { #[cfg(test)] mod tests { - use std::ops::Deref; - - use crate::engine_prelude::*; - use crate::transaction::{LedgerTransaction, RoundUpdateTransactionV1}; - use crate::{ - LedgerProof, PrepareRequest, PrepareResult, RoundHistory, StateManager, StateManagerConfig, - }; - use node_common::config::limits::VertexLimitsConfig; + use super::*; use crate::test::create_state_manager; use tempfile::TempDir; @@ -561,7 +535,7 @@ mod tests { .lock_fee_from_faucet() .get_free_xrd_from_faucet() .try_deposit_entire_worktop_or_abort( - ComponentAddress::virtual_account_from_public_key( + ComponentAddress::preallocated_account_from_public_key( &sig_1_private_key.public_key(), ), None, @@ -637,36 +611,41 @@ mod tests { .transaction_executor_factory .start_series_execution(database.deref()); - let round_update = RoundUpdateTransactionV1::new( + let round_update = create_round_update_transaction( series_executor.epoch_header(), &prepare_request.round_history, ); let ledger_round_update = LedgerTransaction::RoundUpdateV1(Box::new(round_update)); - let validated_round_update = state_manager - .ledger_transaction_validator - .validate_user_or_round_update_from_model(&ledger_round_update) + let round_update_executable = ledger_round_update + .to_raw() + .unwrap() + .create_identifiable_ledger_executable( + state_manager.transaction_validator.read().deref(), + AcceptedLedgerTransactionKind::UserOrValidator, + ) .expect("expected to be able to prepare the round update transaction"); let round_update_result = series_executor - .execute_and_update_state(&validated_round_update, "cost computation - round update") + .execute_and_update_state( + &round_update_executable.executable, + &round_update_executable.hashes, + "cost computation - round update", + ) .expect("round update rejected"); prepare_request .proposed_transactions .iter() .map(|raw_user_transaction| { - let (_, prepared_transaction) = state_manager + let (_, executable, hashes) = state_manager .preparator - .try_prepare_ledger_transaction_from_user_transaction(raw_user_transaction) - .unwrap(); - - let validated = state_manager - .ledger_transaction_validator - .validate_user_or_round_update(prepared_transaction) - .unwrap(); + .prepare_known_valid_raw_user_transaction(raw_user_transaction); - let execute_result = - series_executor.execute_and_update_state(&validated, "cost computation"); + let execute_result = series_executor.execute_and_update_state( + &executable, + &hashes, + "cost computation", + ); match execute_result { Ok(commit) => { diff --git a/core-rust/state-manager/src/test/mod.rs b/core-rust/state-manager/src/test/mod.rs index 1fa48508f0..c6f84cc00b 100644 --- a/core-rust/state-manager/src/test/mod.rs +++ b/core-rust/state-manager/src/test/mod.rs @@ -1,13 +1,5 @@ -use crate::engine_prelude::*; -use crate::query::TransactionIdentifierLoader; -use crate::store::traits::QueryableProofStore; -use crate::{ - CommitRequest, CommitSummary, LedgerHeader, LedgerProof, LedgerProofOrigin, PrepareRequest, - PrepareResult, RoundHistory, StateManager, StateManagerConfig, -}; -use node_common::locks::LockFactory; +use crate::prelude::*; use node_common::scheduler::Scheduler; -use prometheus::Registry; // A bunch of test utils @@ -16,7 +8,7 @@ pub fn create_state_manager(config: StateManagerConfig) -> StateManager { config, None, &LockFactory::new("testing"), - &Registry::new(), + &MetricRegistry::new(), &Scheduler::new("testing"), ) } diff --git a/core-rust/state-manager/src/transaction/executable_logic.rs b/core-rust/state-manager/src/transaction/executable_logic.rs index e223f78385..18c18b1843 100644 --- a/core-rust/state-manager/src/transaction/executable_logic.rs +++ b/core-rust/state-manager/src/transaction/executable_logic.rs @@ -1,13 +1,4 @@ -use crate::engine_prelude::wasm::*; -use crate::engine_prelude::*; - -use std::collections::HashMap; - -use std::time::{Duration, Instant}; - -use tracing::warn; - -use super::ValidatedLedgerTransaction; +use crate::prelude::*; /// A logic of an already-validated transaction, ready to be executed against an arbitrary state of /// a substate store. @@ -20,10 +11,14 @@ pub trait TransactionLogic { pub enum ConfigType { /// A system genesis transaction. Genesis, + /// A (non-genesis) system protocol update transaction. + ProtocolUpdate, + /// A validator transaction (e.g. round update, which sometimes becomes a much larger epoch change). + Validator, /// A user transaction during regular execution (e.g. prepare or commit). - Regular, + User, /// A user transaction during "committability check" execution (e.g. in mempool). - Pending, + UserAbortingRejectionCheck, /// A user transaction during preview execution. Preview, /// A user transaction during preview execution with auth module disabled. @@ -38,8 +33,10 @@ const PREVIEW_RUNTIME_WARN_THRESHOLD: Duration = Duration::from_millis(500); impl ConfigType { pub fn get_transaction_runtime_warn_threshold(&self) -> Duration { match self { - ConfigType::Genesis => GENESIS_TRANSACTION_RUNTIME_WARN_THRESHOLD, - ConfigType::Pending => PENDING_UP_TO_FEE_LOAN_RUNTIME_WARN_THRESHOLD, + ConfigType::Genesis | ConfigType::ProtocolUpdate | ConfigType::Validator => { + GENESIS_TRANSACTION_RUNTIME_WARN_THRESHOLD + } + ConfigType::UserAbortingRejectionCheck => PENDING_UP_TO_FEE_LOAN_RUNTIME_WARN_THRESHOLD, ConfigType::Preview | ConfigType::PreviewNoAuth => PREVIEW_RUNTIME_WARN_THRESHOLD, _ => TRANSACTION_RUNTIME_WARN_THRESHOLD, } @@ -49,14 +46,14 @@ impl ConfigType { /// A preconfigured set of execution settings, allowing to turn `Executable` transactions into /// `TransactionLogic`. pub struct ExecutionConfigurator { - scrypto_vm: ScryptoVm, + vm_modules: DefaultVmModules, execution_configs: HashMap, } impl ExecutionConfigurator { pub fn new(network: &NetworkDefinition, no_fees: bool, engine_trace: bool) -> Self { Self { - scrypto_vm: ScryptoVm::::default(), + vm_modules: DefaultVmModules::default(), execution_configs: HashMap::from([ ( ConfigType::Genesis, @@ -65,17 +62,29 @@ impl ExecutionConfigurator { .with_kernel_trace(engine_trace), ), ( - ConfigType::Regular, - ExecutionConfig::for_notarized_transaction(network.clone()) + ConfigType::ProtocolUpdate, + ExecutionConfig::for_system_transaction(network.clone()) + .with_no_fees(no_fees) + .with_kernel_trace(engine_trace), + ), + ( + ConfigType::Validator, + ExecutionConfig::for_validator_transaction(network.clone()) .with_no_fees(no_fees) .with_kernel_trace(engine_trace), ), ( - ConfigType::Pending, + ConfigType::User, ExecutionConfig::for_notarized_transaction(network.clone()) .with_no_fees(no_fees) .with_kernel_trace(engine_trace), ), + ( + ConfigType::UserAbortingRejectionCheck, + ExecutionConfig::for_notarized_transaction_rejection_check(network.clone()) + .with_no_fees(no_fees) + .with_kernel_trace(engine_trace), + ), ( ConfigType::Preview, ExecutionConfig::for_preview(network.clone()).with_no_fees(no_fees), @@ -91,59 +100,67 @@ impl ExecutionConfigurator { /// Wraps the given `Executable` with a configuration resolved from its `ConfigType`. pub fn wrap_ledger_transaction<'a>( &'a self, - transaction: &'a ValidatedLedgerTransaction, + transaction_hashes: &LedgerTransactionHashes, + ledger_executable: &'a LedgerExecutable, description: impl ToString, - ) -> ConfiguredExecutable<'a> { - if let Some(executable) = transaction.as_flash() { - return executable; - } + ) -> ConfiguredExecutable { + match ledger_executable { + LedgerExecutable::GenesisFlash => ConfiguredExecutable::SystemFlash { + state_updates: create_system_bootstrap_flash_state_updates(), + }, + LedgerExecutable::Flash { updates } => ConfiguredExecutable::SystemFlash { + state_updates: updates.clone(), + }, + LedgerExecutable::Transaction { executable } => { + let config_type = match &transaction_hashes.kinded { + KindedTransactionHashes::Genesis { .. } => ConfigType::Genesis, + KindedTransactionHashes::User(..) => ConfigType::User, + KindedTransactionHashes::RoundUpdateV1 { .. } => ConfigType::Validator, + KindedTransactionHashes::FlashV1 { .. } => ConfigType::ProtocolUpdate, + }; - self.wrap_transaction( - transaction.get_executable(), - transaction.config_type(), - description.to_string(), - ) + self.wrap_transaction(executable, config_type, description.to_string()) + } + } } pub fn wrap_pending_transaction<'a>( &'a self, - transaction: &'a ValidatedNotarizedTransactionV1, + executable: &'a ExecutableTransaction, + user_hashes: &UserTransactionHashes, ) -> ConfiguredExecutable<'a> { self.wrap_transaction( - transaction.get_executable().abort_when_loan_repaid(), - ConfigType::Pending, + executable, + ConfigType::UserAbortingRejectionCheck, format!( "pending intent hash {:?}, up to fee loan", - transaction.prepared.intent_hash() + &user_hashes.transaction_intent_hash, ), ) } pub fn wrap_preview_transaction<'a>( &'a self, - validated_preview_intent: &'a ValidatedPreviewIntent, + executable: &'a ExecutableTransaction, + disable_auth: bool, ) -> ConfiguredExecutable<'a> { - let config_type = if validated_preview_intent.flags.disable_auth { + let config_type = if disable_auth { ConfigType::PreviewNoAuth } else { ConfigType::Preview }; - self.wrap_transaction( - validated_preview_intent.get_executable(), - config_type, - "preview".to_string(), - ) + self.wrap_transaction(executable, config_type, "preview".to_string()) } fn wrap_transaction<'a>( &'a self, - executable: Executable<'a>, + executable: &'a ExecutableTransaction, config_type: ConfigType, description: String, - ) -> ConfiguredExecutable<'a> { + ) -> ConfiguredExecutable { ConfiguredExecutable::Transaction { executable, - scrypto_interpreter: &self.scrypto_vm, + vm_modules: &self.vm_modules, execution_config: self.execution_configs.get(&config_type).unwrap(), threshold: config_type.get_transaction_runtime_warn_threshold(), description, @@ -153,15 +170,12 @@ impl ExecutionConfigurator { /// An `Executable` transaction bound to a specific execution configuration. pub enum ConfiguredExecutable<'a> { - GenesisFlash { - flash_receipt: FlashReceipt, - }, SystemFlash { state_updates: StateUpdates, }, Transaction { - executable: Executable<'a>, - scrypto_interpreter: &'a ScryptoVm, + executable: &'a ExecutableTransaction, + vm_modules: &'a DefaultVmModules, execution_config: &'a ExecutionConfig, threshold: Duration, description: String, @@ -171,46 +185,18 @@ pub enum ConfiguredExecutable<'a> { impl<'a, S: SubstateDatabase> TransactionLogic for ConfiguredExecutable<'a> { fn execute_on(self, store: &S) -> TransactionReceipt { match self { - ConfiguredExecutable::GenesisFlash { flash_receipt } => flash_receipt.into(), ConfiguredExecutable::SystemFlash { state_updates } => { - let application_events = Vec::new(); - let system_structure = - SystemStructure::resolve(store, &state_updates, &application_events); - let new_node_ids = collect_new_node_ids(&state_updates); - let state_update_summary = - StateUpdateSummary::new(store, new_node_ids, &state_updates); - - let commit_result = CommitResult { - state_updates, - state_update_summary, - fee_source: Default::default(), - fee_destination: Default::default(), - outcome: TransactionOutcome::Success(vec![]), - application_events, - application_logs: vec![], - system_structure, - execution_trace: None, - }; - - TransactionReceipt::empty_with_commit(commit_result) + FlashReceipt::from_state_updates(state_updates, store).into() } ConfiguredExecutable::Transaction { executable, - scrypto_interpreter, + vm_modules, execution_config, threshold, description, } => { - let start = Instant::now(); - let result = execute_transaction_with_configuration::<_, Vm<_, _>>( - store, - VmInit { - scrypto_vm: scrypto_interpreter, - native_vm_extension: NoExtension, - }, - execution_config, - &executable, - ); + let start = StdInstant::now(); + let result = execute_transaction(store, vm_modules, execution_config, executable); let elapsed = start.elapsed(); if elapsed > threshold { warn!( @@ -226,44 +212,20 @@ impl<'a, S: SubstateDatabase> TransactionLogic for ConfiguredExecutable<'a> { } } -/// Traverses the given [`StateUpdates`] and returns [`NodeId`]s of the newly-created entities. -/// -/// Note: this assumes that the [`TYPE_INFO_FIELD_PARTITION`] is mandatory and immutable, i.e. it is -/// written to exactly once, at the creation of its entity. -fn collect_new_node_ids(state_updates: &StateUpdates) -> IndexSet { - state_updates - .by_node - .iter() - .filter(|(_node_id, node_state_updates)| { - let NodeStateUpdates::Delta { by_partition } = node_state_updates; - by_partition.contains_key(&TYPE_INFO_FIELD_PARTITION) - }) - .map(|(node_id, _node_state_updates)| *node_id) - .collect() -} - /// An extension trait for easier, declarative customization of our various [`ExecutionConfig`]s. trait CustomizedExecutionConfig { fn with_no_fees(self, no_fees: bool) -> Self; } impl CustomizedExecutionConfig for ExecutionConfig { - fn with_no_fees(self, no_fees: bool) -> Self { - let ExecutionConfig { - enable_kernel_trace, - enable_cost_breakdown, - execution_trace, - system_overrides, - } = self; - ExecutionConfig { - enable_kernel_trace, - enable_cost_breakdown, - execution_trace, - system_overrides: Some(SystemOverrides { - disable_costing: no_fees, + fn with_no_fees(mut self, no_fees: bool) -> Self { + if no_fees { + self.system_overrides = Some(SystemOverrides { + disable_costing: true, // Note: In practice, all ExecutionConfig's constructors set the system_overrides. - ..system_overrides.unwrap_or_default() - }), + ..self.system_overrides.unwrap_or_default() + }) } + self } } diff --git a/core-rust/state-manager/src/transaction/ledger_transaction.rs b/core-rust/state-manager/src/transaction/ledger_transaction.rs deleted file mode 100644 index 4684fcaf99..0000000000 --- a/core-rust/state-manager/src/transaction/ledger_transaction.rs +++ /dev/null @@ -1,567 +0,0 @@ -use crate::engine_prelude::*; - -use crate::transaction::{ConfigType, ConfiguredExecutable}; - -use super::{ - HasRoundUpdateTransactionHash, PreparedRoundUpdateTransactionV1, RoundUpdateTransactionHash, - RoundUpdateTransactionV1, -}; - -#[derive(Debug, Clone, PartialEq, Eq, Sbor)] -pub struct PayloadIdentifiers { - pub ledger_transaction_hash: LedgerTransactionHash, - pub typed: TypedTransactionIdentifiers, -} - -#[derive(Debug, Clone, PartialEq, Eq, Sbor)] -pub enum TypedTransactionIdentifiers { - Genesis { - system_transaction_hash: SystemTransactionHash, - }, - User { - intent_hash: IntentHash, - signed_intent_hash: SignedIntentHash, - notarized_transaction_hash: NotarizedTransactionHash, - }, - RoundUpdateV1 { - round_update_hash: RoundUpdateTransactionHash, - }, - FlashV1 { - flash_transaction_hash: FlashTransactionHash, - }, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct UserTransactionIdentifiers<'a> { - pub intent_hash: &'a IntentHash, - pub signed_intent_hash: &'a SignedIntentHash, - pub notarized_transaction_hash: &'a NotarizedTransactionHash, -} - -impl TypedTransactionIdentifiers { - pub fn user(&self) -> Option { - match self { - TypedTransactionIdentifiers::User { - intent_hash, - signed_intent_hash, - notarized_transaction_hash, - } => Some(UserTransactionIdentifiers { - intent_hash, - signed_intent_hash, - notarized_transaction_hash, - }), - _ => None, - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq, ManifestCategorize, ManifestEncode, ManifestDecode)] -pub enum LedgerTransaction { - #[sbor(discriminator(GENESIS_LEDGER_TRANSACTION_DISCRIMINATOR))] - Genesis(Box), - #[sbor(discriminator(USER_V1_LEDGER_TRANSACTION_DISCRIMINATOR))] - UserV1(Box), - #[sbor(discriminator(ROUND_UPDATE_V1_LEDGER_TRANSACTION_DISCRIMINATOR))] - RoundUpdateV1(Box), - #[sbor(discriminator(FLASH_V1_LEDGER_TRANSACTION_DISCRIMINATOR))] - FlashV1(Box), -} - -const GENESIS_LEDGER_TRANSACTION_DISCRIMINATOR: u8 = 0; -const USER_V1_LEDGER_TRANSACTION_DISCRIMINATOR: u8 = 1; -const ROUND_UPDATE_V1_LEDGER_TRANSACTION_DISCRIMINATOR: u8 = 2; -const FLASH_V1_LEDGER_TRANSACTION_DISCRIMINATOR: u8 = 3; - -define_raw_transaction_payload!(RawLedgerTransaction); - -// We basically implement TransactionPayload manually for LedgerTransaction because it's not a struct -impl LedgerTransaction { - pub fn to_raw(&self) -> Result { - Ok(self.to_payload_bytes()?.into()) - } - - pub fn to_payload_bytes(&self) -> Result, EncodeError> { - manifest_encode(&FixedEnumVariant::< - { TransactionDiscriminator::V1Ledger as u8 }, - (&LedgerTransaction,), - >::new((self,))) - } - - pub fn from_raw(raw: &RawLedgerTransaction) -> Result { - Self::from_payload_bytes(&raw.0) - } - - pub fn from_raw_user(raw: &RawNotarizedTransaction) -> Result { - Ok(LedgerTransaction::UserV1(Box::new( - NotarizedTransactionV1::from_raw(raw)?, - ))) - } - - pub fn from_payload_bytes(payload_bytes: &[u8]) -> Result { - Ok(manifest_decode::< - FixedEnumVariant<{ TransactionDiscriminator::V1Ledger as u8 }, (LedgerTransaction,)>, - >(payload_bytes)? - .into_fields() - .0) - } - - pub fn prepare(&self) -> Result { - PreparedLedgerTransaction::prepare_from_payload(&self.to_payload_bytes()?) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, ManifestCategorize, ManifestEncode, ManifestDecode)] -pub enum GenesisTransaction { - #[sbor(discriminator(GENESIS_TRANSACTION_FLASH_DISCRIMINATOR))] - Flash, - #[sbor(discriminator(GENESIS_TRANSACTION_SYSTEM_TRANSACTION_DISCRIMINATOR))] - Transaction(Box), -} - -const GENESIS_TRANSACTION_FLASH_DISCRIMINATOR: u8 = 0; -const GENESIS_TRANSACTION_SYSTEM_TRANSACTION_DISCRIMINATOR: u8 = 1; - -#[derive(Debug, Clone, PartialEq, Eq, Sbor)] -pub struct FlashTransactionV1 { - pub name: String, - pub state_updates: StateUpdates, -} - -pub struct PreparedLedgerTransaction { - pub inner: PreparedLedgerTransactionInner, - pub summary: Summary, -} - -impl PreparedLedgerTransaction { - pub fn into_user(self) -> Option> { - match self.inner { - PreparedLedgerTransactionInner::UserV1(t) => Some(t), - _ => None, - } - } - - pub fn as_user(&self) -> Option<&PreparedNotarizedTransactionV1> { - match &self.inner { - PreparedLedgerTransactionInner::UserV1(t) => Some(t.as_ref()), - _ => None, - } - } - - pub fn create_identifiers(&self) -> PayloadIdentifiers { - PayloadIdentifiers { - ledger_transaction_hash: self.ledger_transaction_hash(), - typed: match &self.inner { - PreparedLedgerTransactionInner::Genesis(t) => { - TypedTransactionIdentifiers::Genesis { - system_transaction_hash: t.system_transaction_hash(), - } - } - PreparedLedgerTransactionInner::UserV1(t) => TypedTransactionIdentifiers::User { - intent_hash: t.intent_hash(), - signed_intent_hash: t.signed_intent_hash(), - notarized_transaction_hash: t.notarized_transaction_hash(), - }, - PreparedLedgerTransactionInner::RoundUpdateV1(t) => { - TypedTransactionIdentifiers::RoundUpdateV1 { - round_update_hash: t.round_update_transaction_hash(), - } - } - PreparedLedgerTransactionInner::FlashV1(t) => { - TypedTransactionIdentifiers::FlashV1 { - flash_transaction_hash: t.flash_transaction_hash(), - } - } - }, - } - } -} - -impl HasSummary for PreparedLedgerTransaction { - fn get_summary(&self) -> &Summary { - &self.summary - } -} - -#[derive(BasicCategorize)] -pub enum PreparedLedgerTransactionInner { - #[sbor(discriminator(GENESIS_LEDGER_TRANSACTION_DISCRIMINATOR))] - Genesis(Box), - #[sbor(discriminator(USER_V1_LEDGER_TRANSACTION_DISCRIMINATOR))] - UserV1(Box), - #[sbor(discriminator(ROUND_UPDATE_V1_LEDGER_TRANSACTION_DISCRIMINATOR))] - RoundUpdateV1(Box), - #[sbor(discriminator(FLASH_V1_LEDGER_TRANSACTION_DISCRIMINATOR))] - FlashV1(Box), -} - -impl PreparedLedgerTransactionInner { - pub fn get_ledger_hash(&self) -> LedgerTransactionHash { - LedgerTransactionHash::for_kind(self.get_discriminator(), &self.get_summary().hash) - } -} - -impl HasSummary for PreparedLedgerTransactionInner { - fn get_summary(&self) -> &Summary { - match self { - Self::Genesis(t) => t.get_summary(), - Self::UserV1(t) => t.get_summary(), - Self::RoundUpdateV1(t) => t.get_summary(), - Self::FlashV1(t) => t.get_summary(), - } - } -} - -impl TransactionFullChildPreparable for PreparedLedgerTransactionInner { - fn prepare_as_full_body_child(decoder: &mut TransactionDecoder) -> Result { - decoder.track_stack_depth_increase()?; - let (discriminator, length) = decoder.read_enum_header()?; - let prepared_inner = match discriminator { - GENESIS_LEDGER_TRANSACTION_DISCRIMINATOR => { - check_length(length, 1)?; - let (discriminator, length) = decoder.read_enum_header()?; - let genesis_transaction = match discriminator { - GENESIS_TRANSACTION_FLASH_DISCRIMINATOR => { - check_length(length, 0)?; - PreparedGenesisTransaction::Flash(Summary { - effective_length: 0, - total_bytes_hashed: 0, - hash: hash("Genesis Flash"), - }) - } - GENESIS_TRANSACTION_SYSTEM_TRANSACTION_DISCRIMINATOR => { - check_length(length, 1)?; - let prepared = - PreparedSystemTransactionV1::prepare_as_full_body_child(decoder)?; - PreparedGenesisTransaction::Transaction(Box::new(prepared)) - } - _ => return Err(unknown_discriminator(discriminator)), - }; - PreparedLedgerTransactionInner::Genesis(Box::new(genesis_transaction)) - } - USER_V1_LEDGER_TRANSACTION_DISCRIMINATOR => { - check_length(length, 1)?; - let prepared = PreparedNotarizedTransactionV1::prepare_as_full_body_child(decoder)?; - PreparedLedgerTransactionInner::UserV1(Box::new(prepared)) - } - ROUND_UPDATE_V1_LEDGER_TRANSACTION_DISCRIMINATOR => { - check_length(length, 1)?; - let prepared = - PreparedRoundUpdateTransactionV1::prepare_as_full_body_child(decoder)?; - PreparedLedgerTransactionInner::RoundUpdateV1(Box::new(prepared)) - } - FLASH_V1_LEDGER_TRANSACTION_DISCRIMINATOR => { - check_length(length, 1)?; - let prepared = PreparedFlashTransactionV1::prepare_as_full_body_child(decoder)?; - PreparedLedgerTransactionInner::FlashV1(Box::new(prepared)) - } - _ => return Err(unknown_discriminator(discriminator)), - }; - decoder.track_stack_depth_decrease()?; - - Ok(prepared_inner) - } -} - -fn check_length(actual: usize, expected: usize) -> Result<(), PrepareError> { - if actual != expected { - return Err(PrepareError::DecodeError(DecodeError::UnexpectedSize { - expected, - actual, - })); - } - Ok(()) -} - -fn unknown_discriminator(discriminator: u8) -> PrepareError { - PrepareError::DecodeError(DecodeError::UnknownDiscriminator(discriminator)) -} - -pub enum PreparedGenesisTransaction { - Flash(Summary), - Transaction(Box), -} - -impl HasSummary for PreparedGenesisTransaction { - fn get_summary(&self) -> &Summary { - match self { - PreparedGenesisTransaction::Flash(summary) => summary, - PreparedGenesisTransaction::Transaction(system_transaction) => { - system_transaction.get_summary() - } - } - } -} - -impl HasSystemTransactionHash for PreparedGenesisTransaction { - fn system_transaction_hash(&self) -> SystemTransactionHash { - match self { - PreparedGenesisTransaction::Flash(summary) => SystemTransactionHash(summary.hash), - PreparedGenesisTransaction::Transaction(transaction) => { - transaction.system_transaction_hash() - } - } - } -} - -pub struct PreparedFlashTransactionV1 { - pub name: String, - pub state_updates: StateUpdates, - pub summary: Summary, -} - -impl HasSummary for PreparedFlashTransactionV1 { - fn get_summary(&self) -> &Summary { - &self.summary - } -} - -impl HasFlashTransactionHash for PreparedFlashTransactionV1 { - fn flash_transaction_hash(&self) -> FlashTransactionHash { - FlashTransactionHash(self.summary.hash) - } -} - -impl TransactionFullChildPreparable for PreparedFlashTransactionV1 { - fn prepare_as_full_body_child(decoder: &mut TransactionDecoder) -> Result { - let ((name, state_updates), summary) = - ConcatenatedDigest::prepare_from_transaction_child_struct::<( - SummarizedRawFullBody, - SummarizedRawFullBody, - )>(decoder, TransactionDiscriminator::V1Flash)?; - Ok(Self { - name: name.inner, - state_updates: state_updates.inner, - summary, - }) - } -} - -impl TransactionPayloadPreparable for PreparedLedgerTransaction { - type Raw = RawLedgerTransaction; - - fn prepare_for_payload(decoder: &mut TransactionDecoder) -> Result { - decoder.track_stack_depth_increase()?; - decoder.read_expected_enum_variant_header(TransactionDiscriminator::V1Ledger as u8, 1)?; - let inner = PreparedLedgerTransactionInner::prepare_as_full_body_child(decoder)?; - decoder.track_stack_depth_decrease()?; - - let summary = Summary { - effective_length: inner.get_summary().effective_length, - total_bytes_hashed: inner.get_summary().total_bytes_hashed, - hash: inner.get_ledger_hash().0, - }; - Ok(Self { inner, summary }) - } -} - -pub struct ValidatedLedgerTransaction { - pub inner: ValidatedLedgerTransactionInner, - pub summary: Summary, -} - -#[derive(BasicCategorize)] -pub enum ValidatedLedgerTransactionInner { - #[sbor(discriminator(GENESIS_LEDGER_TRANSACTION_DISCRIMINATOR))] - Genesis(Box), - #[sbor(discriminator(USER_V1_LEDGER_TRANSACTION_DISCRIMINATOR))] - UserV1(Box), - #[sbor(discriminator(ROUND_UPDATE_V1_LEDGER_TRANSACTION_DISCRIMINATOR))] - RoundUpdateV1(Box), - #[sbor(discriminator(FLASH_V1_LEDGER_TRANSACTION_DISCRIMINATOR))] - FlashV1(Box), -} - -impl ValidatedLedgerTransaction { - pub fn intent_hash_if_user(&self) -> Option { - match &self.inner { - ValidatedLedgerTransactionInner::Genesis(_) => None, - ValidatedLedgerTransactionInner::UserV1(t) => Some(t.intent_hash()), - ValidatedLedgerTransactionInner::RoundUpdateV1(_) => None, - ValidatedLedgerTransactionInner::FlashV1(_) => None, - } - } - - pub fn as_flash(&self) -> Option { - match &self.inner { - ValidatedLedgerTransactionInner::Genesis(genesis) => match genesis.as_ref() { - PreparedGenesisTransaction::Flash(..) => Some(ConfiguredExecutable::GenesisFlash { - flash_receipt: create_substate_flash_for_genesis(), - }), - PreparedGenesisTransaction::Transaction(_) => None, - }, - ValidatedLedgerTransactionInner::FlashV1(system_flash) => { - Some(ConfiguredExecutable::SystemFlash { - state_updates: system_flash.state_updates.clone(), - }) - } - _ => None, - } - } - - /// Note - panics if it's a genesis flash - pub fn get_executable(&self) -> Executable<'_> { - match &self.inner { - ValidatedLedgerTransactionInner::Genesis(genesis) => match genesis.as_ref() { - PreparedGenesisTransaction::Flash(_) => { - panic!("Should not call get_executable on a genesis flash") - } - PreparedGenesisTransaction::Transaction(t) => { - t.get_executable(btreeset!(AuthAddresses::system_role())) - } - }, - ValidatedLedgerTransactionInner::UserV1(t) => t.get_executable(), - ValidatedLedgerTransactionInner::RoundUpdateV1(t) => t.get_executable(), - ValidatedLedgerTransactionInner::FlashV1(_) => { - panic!("Should not call get_executable on a flash transaction") - } - } - } - - /// Gets a [`ConfigType`] to be used during regular execution (i.e. not preview, not in-mempool - /// committability check). - pub fn config_type(&self) -> ConfigType { - match &self.inner { - ValidatedLedgerTransactionInner::Genesis(_) => ConfigType::Genesis, - ValidatedLedgerTransactionInner::UserV1(_) => ConfigType::Regular, - ValidatedLedgerTransactionInner::RoundUpdateV1(_) => ConfigType::Regular, - ValidatedLedgerTransactionInner::FlashV1(_) => ConfigType::Regular, - } - } - - pub fn create_identifiers(&self) -> PayloadIdentifiers { - PayloadIdentifiers { - ledger_transaction_hash: self.ledger_transaction_hash(), - typed: match &self.inner { - ValidatedLedgerTransactionInner::Genesis(t) => { - TypedTransactionIdentifiers::Genesis { - system_transaction_hash: t.system_transaction_hash(), - } - } - ValidatedLedgerTransactionInner::UserV1(t) => TypedTransactionIdentifiers::User { - intent_hash: t.intent_hash(), - signed_intent_hash: t.signed_intent_hash(), - notarized_transaction_hash: t.notarized_transaction_hash(), - }, - ValidatedLedgerTransactionInner::RoundUpdateV1(t) => { - TypedTransactionIdentifiers::RoundUpdateV1 { - round_update_hash: t.round_update_transaction_hash(), - } - } - ValidatedLedgerTransactionInner::FlashV1(t) => { - TypedTransactionIdentifiers::FlashV1 { - flash_transaction_hash: t.flash_transaction_hash(), - } - } - }, - } - } -} - -impl HasLedgerTransactionHash for ValidatedLedgerTransaction { - fn ledger_transaction_hash(&self) -> LedgerTransactionHash { - LedgerTransactionHash::from_hash(self.summary.hash) - } -} - -define_wrapped_hash!(LedgerTransactionHash); - -impl LedgerTransactionHash { - pub fn for_genesis(hash: &SystemTransactionHash) -> Self { - Self::for_kind(GENESIS_LEDGER_TRANSACTION_DISCRIMINATOR, &hash.0) - } - - pub fn for_user_v1(hash: &NotarizedTransactionHash) -> Self { - Self::for_kind(USER_V1_LEDGER_TRANSACTION_DISCRIMINATOR, &hash.0) - } - - pub fn for_round_update_v1(hash: &RoundUpdateTransactionHash) -> Self { - Self::for_kind(ROUND_UPDATE_V1_LEDGER_TRANSACTION_DISCRIMINATOR, &hash.0) - } - - fn for_kind(discriminator: u8, inner: &Hash) -> Self { - Self( - HashAccumulator::new() - .update([ - TRANSACTION_HASHABLE_PAYLOAD_PREFIX, - TransactionDiscriminator::V1Ledger as u8, - discriminator, - ]) - .update(inner.as_slice()) - .finalize(), - ) - } -} - -impl HashHasHrp for LedgerTransactionHash { - fn hrp(hrp_set: &HrpSet) -> &str { - &hrp_set.ledger_transaction - } -} - -pub trait HasLedgerTransactionHash { - fn ledger_transaction_hash(&self) -> LedgerTransactionHash; -} - -impl HasLedgerTransactionHash for PreparedLedgerTransaction { - fn ledger_transaction_hash(&self) -> LedgerTransactionHash { - LedgerTransactionHash::from_hash(self.summary.hash) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - pub fn v1_ledger_transaction_structure() { - let sig_1_private_key = Secp256k1PrivateKey::from_u64(1).unwrap(); - let sig_2_private_key = Ed25519PrivateKey::from_u64(2).unwrap(); - let notary_private_key = Ed25519PrivateKey::from_u64(3).unwrap(); - - let notarized = TransactionBuilder::new() - .header(TransactionHeaderV1 { - network_id: 21, - start_epoch_inclusive: Epoch::of(0), - end_epoch_exclusive: Epoch::of(100), - nonce: 0, - notary_public_key: notary_private_key.public_key().into(), - notary_is_signatory: true, - tip_percentage: 0, - }) - .manifest(ManifestBuilder::new().drop_all_proofs().build()) - .sign(&sig_1_private_key) - .sign(&sig_2_private_key) - .notarize(¬ary_private_key) - .build(); - - let prepared_notarized = notarized.prepare().expect("Notarized can be prepared"); - - let ledger = LedgerTransaction::UserV1(Box::new(notarized)); - let ledger_transaction_bytes = ledger.to_payload_bytes().expect("Can be encoded"); - LedgerTransaction::from_payload_bytes(&ledger_transaction_bytes).expect("Can be decoded"); - let prepared_ledger_transaction = - PreparedLedgerTransaction::prepare_from_payload(&ledger_transaction_bytes) - .expect("Can be prepared"); - - let expected_intent_hash = LedgerTransactionHash::from_hash(hash( - [ - [ - TRANSACTION_HASHABLE_PAYLOAD_PREFIX, - TransactionDiscriminator::V1Ledger as u8, - USER_V1_LEDGER_TRANSACTION_DISCRIMINATOR, - ] - .as_slice(), - prepared_notarized.notarized_transaction_hash().0.as_slice(), - ] - .concat(), - )); - assert_eq!( - prepared_ledger_transaction.ledger_transaction_hash(), - expected_intent_hash - ); - assert_eq!( - LedgerTransactionHash::for_user_v1(&prepared_notarized.notarized_transaction_hash()), - expected_intent_hash - ); - } -} diff --git a/core-rust/state-manager/src/transaction/mod.rs b/core-rust/state-manager/src/transaction/mod.rs index b69085c297..b99a6bc33f 100644 --- a/core-rust/state-manager/src/transaction/mod.rs +++ b/core-rust/state-manager/src/transaction/mod.rs @@ -63,17 +63,15 @@ */ mod executable_logic; -mod ledger_transaction; mod preparation; mod preview; -mod round_update_transaction; +mod round_updates; mod series_execution; mod validation; pub use executable_logic::*; -pub use ledger_transaction::*; pub use preparation::*; pub use preview::*; -pub use round_update_transaction::*; +pub use round_updates::*; pub use series_execution::*; pub use validation::*; diff --git a/core-rust/state-manager/src/transaction/preparation.rs b/core-rust/state-manager/src/transaction/preparation.rs index 3cc449375f..db751f152a 100644 --- a/core-rust/state-manager/src/transaction/preparation.rs +++ b/core-rust/state-manager/src/transaction/preparation.rs @@ -62,28 +62,13 @@ * permissions under this License. */ -use node_common::config::limits::VertexLimitsConfig; -use node_common::locks::*; -use prometheus::Registry; -use std::ops::Deref; -use std::sync::Arc; -use std::time::SystemTime; -use tracing::{debug, info}; - -use crate::engine_prelude::*; -use crate::limits::*; -use crate::store::rocks_db::ActualStateManagerDatabase; -use crate::*; - -use crate::system_commits::*; - -use crate::transaction::*; +use crate::prelude::*; pub struct Preparator { database: Arc>, transaction_executor_factory: Arc, pending_transaction_result_cache: Arc>, - ledger_transaction_validator: Arc, + transaction_validator: Arc>, vertex_prepare_metrics: VertexPrepareMetrics, vertex_limits_config: VertexLimitsConfig, } @@ -93,15 +78,15 @@ impl Preparator { database: Arc>, transaction_executor_factory: Arc, pending_transaction_result_cache: Arc>, - ledger_transaction_validator: Arc, + transaction_validator: Arc>, vertex_limits_config: VertexLimitsConfig, - metrics_registry: &Registry, + metrics_registry: &MetricRegistry, ) -> Self { Self { database, transaction_executor_factory, pending_transaction_result_cache, - ledger_transaction_validator, + transaction_validator, vertex_prepare_metrics: VertexPrepareMetrics::new(metrics_registry), vertex_limits_config, } @@ -111,9 +96,12 @@ impl Preparator { let raw = LedgerTransaction::Genesis(Box::new(genesis_transaction)) .to_raw() .expect("Could not encode genesis transaction"); - let prepared = PreparedLedgerTransaction::prepare_from_raw(&raw) - .expect("Could not prepare genesis transaction"); - let validated = self.ledger_transaction_validator.validate_genesis(prepared); + let IdentifiedLedgerExecutable { executable, hashes } = raw + .create_identifiable_ledger_executable( + self.transaction_validator.read().deref(), + AcceptedLedgerTransactionKind::GenesisOnly, + ) + .expect("Could not prepare and validate genesis transaction"); let database = self.database.lock(); let mut series_executor = self @@ -121,19 +109,23 @@ impl Preparator { .start_series_execution(database.deref()); series_executor - .execute_and_update_state(&validated, "genesis") + .execute_and_update_state(&executable, &hashes, "genesis") .expect("genesis not committable") .expect_success("genesis"); SystemPrepareResult::from_committed_series( - vec![RawAndValidatedTransaction { raw, validated }], + vec![ProcessedLedgerTransaction { + raw, + executable, + hashes, + }], series_executor, ) } pub fn prepare_protocol_update( &self, - flash_transactions: Vec, + protocol_update_batch: ProtocolUpdateBatch, ) -> SystemPrepareResult { let database = self.database.lock(); let mut series_executor = self @@ -141,19 +133,32 @@ impl Preparator { .start_series_execution(database.deref()); let mut committed_transactions = Vec::new(); - for flash_transaction in flash_transactions { + + for transaction in protocol_update_batch.transactions { + let ProtocolUpdateTransaction::FlashTransactionV1(flash_transaction) = transaction + else { + panic!("Non-flash transactions not yet supported in the node"); + }; let raw = LedgerTransaction::FlashV1(Box::new(flash_transaction)) .to_raw() - .unwrap(); - let prepared = PreparedLedgerTransaction::prepare_from_raw(&raw).unwrap(); - let validated = self.ledger_transaction_validator.validate_flash(prepared); + .expect("Could not encode protocol update transaction"); + let IdentifiedLedgerExecutable { executable, hashes } = raw + .create_identifiable_ledger_executable( + self.transaction_validator.read().deref(), + AcceptedLedgerTransactionKind::ProtocolUpdateOnly, + ) + .expect("Could not prepare and validate protocol update transaction"); series_executor - .execute_and_update_state(&validated, "protocol update") + .execute_and_update_state(&executable, &hashes, "protocol update") .expect("protocol update not committable") .expect_success("protocol update"); - committed_transactions.push(RawAndValidatedTransaction { raw, validated }); + committed_transactions.push(ProcessedLedgerTransaction { + raw, + executable, + hashes, + }); } SystemPrepareResult::from_committed_series(committed_transactions, series_executor) @@ -216,29 +221,27 @@ impl Preparator { series_executor: &mut TransactionSeriesExecutor, scenario_name: &str, next: &NextTransaction, - ) -> (RawAndValidatedTransaction, TransactionReceipt) { + ) -> (ProcessedLedgerTransaction, TransactionReceipt) { let qualified_name = format!( "{} scenario - {} transaction", scenario_name, &next.logical_name ); - let (raw, prepared) = self - .try_prepare_ledger_transaction_from_user_transaction(&next.raw_transaction) - .unwrap_or_else(|_| panic!("cannot prepare {}", qualified_name)); - - let validated = self - .ledger_transaction_validator - .validate_user_or_round_update(prepared) - .unwrap_or_else(|_| panic!("{} not valid", qualified_name)); + let (raw, executable, hashes) = + self.prepare_known_valid_raw_user_transaction(&next.raw_transaction); series_executor .capture_next_engine_receipt() - .execute_and_update_state(&validated, qualified_name.as_str()) + .execute_and_update_state(&executable, &hashes, qualified_name.as_str()) .ok(); // we need to consume the `Result<>`, but we actually only care about the receipt let engine_receipt = series_executor.retrieve_captured_engine_receipt(); ( - RawAndValidatedTransaction { raw, validated }, + ProcessedLedgerTransaction { + raw, + executable, + hashes, + }, engine_receipt, ) } @@ -279,13 +282,15 @@ impl Preparator { for raw_ancestor in prepare_request.ancestor_transactions { // TODO(optimization-only): We could avoid the hashing, decoding, signature verification // and executable creation by accessing the execution cache in a more clever way. - let validated = self - .ledger_transaction_validator - .validate_user_or_round_update_from_raw(&raw_ancestor) + let validated = raw_ancestor + .create_identifiable_ledger_executable( + self.transaction_validator.read().deref(), + AcceptedLedgerTransactionKind::UserOrValidator, + ) .expect("Ancestor transactions should be valid"); series_executor - .execute_and_update_state(&validated, "ancestor") + .execute_and_update_state(&validated.executable, &validated.hashes, "ancestor") .expect("ancestor transaction rejected"); } @@ -306,27 +311,34 @@ impl Preparator { let mut vertex_limits_tracker = VertexLimitsTracker::new(&self.vertex_limits_config); // TODO: Unify this with the proposed payloads execution - let round_update = RoundUpdateTransactionV1::new( + let round_update = create_round_update_transaction( series_executor.epoch_header(), &prepare_request.round_history, ); let ledger_round_update = LedgerTransaction::RoundUpdateV1(Box::new(round_update)); - let validated_round_update = self - .ledger_transaction_validator - .validate_user_or_round_update_from_model(&ledger_round_update) - .expect("expected to be able to prepare the round update transaction"); let raw_ledger_round_update = ledger_round_update .to_raw() .expect("Expected round update to be encodable"); + let validated_round_update = raw_ledger_round_update + .create_identifiable_ledger_executable( + self.transaction_validator.read().deref(), + AcceptedLedgerTransactionKind::ValidatorOnly, + ) + .expect("expected to be able to validate the round update transaction"); + let transaction_size = raw_ledger_round_update.as_slice().len(); vertex_limits_tracker .check_pre_execution(transaction_size) .expect("round update transaction should fit inside of empty vertex"); let round_update_result = series_executor - .execute_and_update_state(&validated_round_update, "round update") + .execute_and_update_state( + &validated_round_update.executable, + &validated_round_update.hashes, + "round update", + ) .expect("round update rejected"); vertex_limits_tracker @@ -344,9 +356,9 @@ impl Preparator { committable_transactions.push(CommittableTransaction { index: None, raw: raw_ledger_round_update, - intent_hash: None, + transaction_intent_hash: None, notarized_transaction_hash: None, - ledger_transaction_hash: validated_round_update.ledger_transaction_hash(), + ledger_transaction_hash: validated_round_update.hashes.ledger_transaction_hash, }); //======================================================================================== @@ -360,7 +372,7 @@ impl Preparator { let total_proposal_size: usize = prepare_request .proposed_transactions .iter() - .map(|tx| tx.0.len()) + .map(|tx| tx.len()) .sum(); let mut committed_proposal_size = 0; let mut stop_reason = VertexPrepareStopReason::ProposalComplete; @@ -394,72 +406,54 @@ impl Preparator { continue; } - let try_prepare_result = - self.try_prepare_ledger_transaction_from_user_transaction(&raw_user_transaction); + let mut prepared_details = CaptureSupport::Expecting; + let handle_result = + self.prepare_raw_user_transaction(&raw_user_transaction, &mut prepared_details); - let (raw_ledger_transaction, prepared_transaction) = match try_prepare_result { + let (raw_ledger_transaction, executable) = match handle_result { Ok(results) => results, Err(error) => { - rejected_transactions.push(RejectedTransaction { - index: index as u32, - intent_hash: None, - notarized_transaction_hash: None, - ledger_transaction_hash: None, - error: format!("{error:?}"), - }); + let error_message = format!("{error:?}"); + match prepared_details.into_option() { + Some(prepared_details) => { + let ledger_hash = prepared_details.hashes.ledger_transaction_hash; + let user_hashes = prepared_details.hashes.as_user().unwrap(); + rejected_transactions.push(RejectedTransaction::new( + index, + error_message, + ledger_hash, + user_hashes, + )); + pending_transaction_results.push(PendingTransactionResult { + transaction_intent_hash: user_hashes.transaction_intent_hash, + notarized_transaction_hash: user_hashes.notarized_transaction_hash, + invalid_at_epoch: prepared_details.end_epoch_exclusive, + rejection_reason: Some(error.into()), + }); + } + None => rejected_transactions.push( + RejectedTransaction::failed_before_prepare(index, error_message), + ), + }; continue; } }; - let prepared_user_transaction = prepared_transaction - .as_user() - .expect("Proposed was created from user"); - - let intent_hash = prepared_user_transaction.intent_hash(); - let notarized_transaction_hash = prepared_user_transaction.notarized_transaction_hash(); - let ledger_transaction_hash = prepared_transaction.ledger_transaction_hash(); - let invalid_at_epoch = prepared_user_transaction - .signed_intent - .intent - .header - .inner - .end_epoch_exclusive; - - // TODO(optimization-only): We could avoid signature verification by re-using the - // validated transaction from the mempool. - let validate_result = self - .ledger_transaction_validator - .validate_user_or_round_update(prepared_transaction); - - let validated = match validate_result { - Ok(validated) => validated, - Err(error) => { - rejected_transactions.push(RejectedTransaction { - index: index as u32, - intent_hash: Some(intent_hash), - notarized_transaction_hash: Some(notarized_transaction_hash), - ledger_transaction_hash: Some(ledger_transaction_hash), - error: format!("{:?}", &error), - }); - pending_transaction_results.push(PendingTransactionResult { - intent_hash, - notarized_transaction_hash, - invalid_at_epoch, - rejection_reason: Some(MempoolRejectionReason::ValidationError( - error.into_user_validation_error(), - )), - }); - continue; - } - }; + let prepared_details = prepared_details.retrieve_captured(); + let user_hashes = prepared_details.hashes.as_user().unwrap(); + let ledger_transaction_hash = prepared_details.hashes.ledger_transaction_hash; + let invalid_at_epoch = prepared_details.end_epoch_exclusive; // Note that we're using a "_no_state_update" variant here, because // we may still reject some *committable* transactions if they exceed // the limit, which would otherwise spoil the internal StateTracker. // So it's important to manually update the state if the transaction // is to be included (that's the `series_executor.update_state(...)` call below). - let execute_result = - series_executor.execute_no_state_update(&validated, "newly proposed"); + let execute_result = series_executor.execute_no_state_update( + &executable, + &prepared_details.hashes, + "newly proposed", + ); match execute_result { Ok(processed_commit_result) => { match vertex_limits_tracker.try_next_transaction( @@ -473,16 +467,15 @@ impl Preparator { // We're including the transaction, so updating the executor state series_executor.update_state(&processed_commit_result); committed_proposal_size += transaction_size; - committable_transactions.push(CommittableTransaction { - index: Some(index as u32), - raw: raw_ledger_transaction, - intent_hash: Some(intent_hash), - notarized_transaction_hash: Some(notarized_transaction_hash), + committable_transactions.push(CommittableTransaction::new( + index, + raw_ledger_transaction, ledger_transaction_hash, - }); + user_hashes, + )); pending_transaction_results.push(PendingTransactionResult { - intent_hash, - notarized_transaction_hash, + transaction_intent_hash: user_hashes.transaction_intent_hash, + notarized_transaction_hash: user_hashes.notarized_transaction_hash, invalid_at_epoch, rejection_reason: None, }); @@ -496,13 +489,12 @@ impl Preparator { } } Err(error) => { - rejected_transactions.push(RejectedTransaction { - index: index as u32, - intent_hash: Some(intent_hash), - notarized_transaction_hash: Some(notarized_transaction_hash), - ledger_transaction_hash: Some(ledger_transaction_hash), - error: format!("{:?}", &error), - }); + rejected_transactions.push(RejectedTransaction::new( + index, + format!("{:?}", &error), + ledger_transaction_hash, + user_hashes, + )); // In order to mitigate the worst-case scenario where the proposal contains lots of small // transactions that take maximum amount of time to execute, we stop right after first // exceeded vertex limit. @@ -517,21 +509,21 @@ impl Preparator { result, fee_summary, }) => { - rejected_transactions.push(RejectedTransaction { - index: index as u32, - intent_hash: Some(intent_hash), - notarized_transaction_hash: Some(notarized_transaction_hash), - ledger_transaction_hash: Some(ledger_transaction_hash), - error: format!("{:?}", &result.reason), - }); + let error_message = format!("{:?}", &result.reason); pending_transaction_results.push(PendingTransactionResult { - intent_hash, - notarized_transaction_hash, + transaction_intent_hash: user_hashes.transaction_intent_hash, + notarized_transaction_hash: user_hashes.notarized_transaction_hash, invalid_at_epoch, rejection_reason: Some(MempoolRejectionReason::FromExecution(Box::new( result.reason, ))), }); + rejected_transactions.push(RejectedTransaction::new( + index, + error_message, + ledger_transaction_hash, + user_hashes, + )); // We want to account for rejected execution costs too and stop accordingly since // executing the maximum number of (rejected) transactions in a proposal for the @@ -560,7 +552,7 @@ impl Preparator { timestamp: pending_transaction_timestamp, }; write_pending_transaction_result_cache.track_transaction_result( - pending_transaction_result.intent_hash, + pending_transaction_result.transaction_intent_hash, pending_transaction_result.notarized_transaction_hash, Some(pending_transaction_result.invalid_at_epoch), attempt, @@ -583,24 +575,55 @@ impl Preparator { } } - // only public for test purposes - pub fn try_prepare_ledger_transaction_from_user_transaction( + pub fn prepare_known_valid_raw_user_transaction( &self, raw_user_transaction: &RawNotarizedTransaction, - ) -> Result<(RawLedgerTransaction, PreparedLedgerTransaction), TransactionValidationError> { - LedgerTransaction::from_raw_user(raw_user_transaction) - .map_err(|err| TransactionValidationError::PrepareError(PrepareError::DecodeError(err))) - .and_then(|ledger_transaction| { - ledger_transaction.to_raw().map_err(|err| { - TransactionValidationError::PrepareError(PrepareError::EncodeError(err)) - }) - }) - .and_then(|raw_ledger_transaction| { - self.ledger_transaction_validator - .prepare_from_raw(&raw_ledger_transaction) - .map(|prepared_transaction| (raw_ledger_transaction, prepared_transaction)) - }) + ) -> ( + RawLedgerTransaction, + LedgerExecutable, + LedgerTransactionHashes, + ) { + let mut details = CaptureSupport::Expecting; + let (raw, executable) = self + .prepare_raw_user_transaction(raw_user_transaction, &mut details) + .expect("The caller should have certainty the user transaction should be valid"); + (raw, executable, details.retrieve_captured().hashes) } + + pub fn prepare_raw_user_transaction( + &self, + raw_user_transaction: &RawNotarizedTransaction, + prepared_details: &mut CaptureSupport, + ) -> Result<(RawLedgerTransaction, LedgerExecutable), TransactionValidationError> { + let user_transaction = raw_user_transaction + .into_typed() + .map_err(PrepareError::DecodeError)?; + let raw = LedgerTransaction::from(user_transaction) + .to_raw() + .map_err(PrepareError::EncodeError)?; + let prepared = raw.prepare(self.transaction_validator.read().preparation_settings())?; + prepared_details.capture_if_required(|| { + let hashes = prepared.create_hashes(); + let end_epoch_exclusive = prepared.as_user().unwrap().end_epoch_exclusive(); + PreparedUserTransactionDetails { + hashes, + end_epoch_exclusive, + } + }); + let executable = prepared + .validate( + self.transaction_validator.read().deref(), + AcceptedLedgerTransactionKind::UserOnly, + ) + .map_err(|err| err.into_user_validation_error())? + .create_ledger_executable(); + Ok((raw, executable)) + } +} + +pub struct PreparedUserTransactionDetails { + pub hashes: LedgerTransactionHashes, + pub end_epoch_exclusive: Epoch, } pub struct PreparedScenarioMetadata { @@ -609,7 +632,7 @@ pub struct PreparedScenarioMetadata { } struct PendingTransactionResult { - pub intent_hash: IntentHash, + pub transaction_intent_hash: TransactionIntentHash, pub notarized_transaction_hash: NotarizedTransactionHash, pub invalid_at_epoch: Epoch, pub rejection_reason: Option, diff --git a/core-rust/state-manager/src/transaction/preview.rs b/core-rust/state-manager/src/transaction/preview.rs index eeb0e5264b..c30f36bac7 100644 --- a/core-rust/state-manager/src/transaction/preview.rs +++ b/core-rust/state-manager/src/transaction/preview.rs @@ -1,21 +1,12 @@ -use crate::engine_prelude::*; -use node_common::locks::DbLock; -use std::sync::Arc; +use crate::prelude::*; -use crate::historical_state::{StateHistoryError, VersionScopingSupport}; - -use crate::store::rocks_db::ActualStateManagerDatabase; -use crate::transaction::*; -use crate::{ - GlobalBalanceSummary, LedgerStateChanges, LedgerStateSummary, PreviewRequest, - ProcessedCommitResult, StateVersion, -}; +use historical_state::{StateHistoryError, VersionScopingSupport}; /// A transaction preview runner. pub struct TransactionPreviewer { database: Arc>, execution_configurator: Arc, - validation_config: ValidationConfig, + transaction_validator: Arc>, } pub struct ProcessedPreviewResult { @@ -35,12 +26,12 @@ impl TransactionPreviewer { pub fn new( database: Arc>, execution_configurator: Arc, - validation_config: ValidationConfig, + transaction_validator: Arc>, ) -> Self { Self { database, execution_configurator, - validation_config, + transaction_validator, } } } @@ -63,13 +54,16 @@ impl TransactionPreviewer { let intent = self.create_intent(preview_request, base_ledger_state.epoch); - let validator = NotarizedTransactionValidator::new(self.validation_config); - let validated = validator + let validated = self + .transaction_validator + .read() .validate_preview_intent_v1(intent) .map_err(PreviewError::TransactionValidationError)?; + let disable_auth = validated.flags.disable_auth; + let executable = validated.create_executable(); let transaction_logic = self .execution_configurator - .wrap_preview_transaction(&validated); + .wrap_preview_transaction(&executable, disable_auth); let receipt = transaction_logic.execute_on(&database); let (state_changes, global_balance_summary) = match &receipt.result { @@ -119,17 +113,24 @@ impl TransactionPreviewer { let notary_public_key = notary_public_key.unwrap_or_else(|| { PublicKey::Secp256k1(Secp256k1PrivateKey::from_u64(2).unwrap().public_key()) }); + let (max_epoch_range, network_id) = { + let validator = self.transaction_validator.read(); + ( + validator.config().max_epoch_range, + validator.network_id().unwrap(), + ) + }; let start_epoch_inclusive = start_epoch_inclusive.unwrap_or(at_epoch); let end_epoch_exclusive = end_epoch_exclusive.unwrap_or_else(|| { start_epoch_inclusive - .after(self.validation_config.max_epoch_range) + .after(max_epoch_range) .expect("currently calculated max end epoch is outside of valid range") }); let (instructions, blobs) = manifest.for_intent(); PreviewIntentV1 { intent: IntentV1 { header: TransactionHeaderV1 { - network_id: self.validation_config.network_id, + network_id, start_epoch_inclusive, end_epoch_exclusive, nonce, @@ -161,10 +162,7 @@ impl From for PreviewerError { #[cfg(test)] mod tests { - - use crate::engine_prelude::*; - use crate::{PreviewRequest, StateManagerConfig}; - + use super::*; use crate::test::create_state_manager; #[test] diff --git a/core-rust/state-manager/src/transaction/round_update_transaction.rs b/core-rust/state-manager/src/transaction/round_update_transaction.rs deleted file mode 100644 index 30f23e5124..0000000000 --- a/core-rust/state-manager/src/transaction/round_update_transaction.rs +++ /dev/null @@ -1,262 +0,0 @@ -use crate::engine_prelude::*; - -use crate::{LedgerHeader, RoundHistory, ValidatorId}; - -#[derive(Debug, Clone, Categorize, Encode, Decode, PartialEq, Eq)] -pub struct RoundUpdateTransactionV1 { - pub proposer_timestamp_ms: i64, - pub epoch: Epoch, - pub round: Round, - pub leader_proposal_history: LeaderProposalHistory, -} - -impl RoundUpdateTransactionV1 { - pub fn new(epoch_header: Option<&LedgerHeader>, round_history: &RoundHistory) -> Self { - let validator_index_by_address = iterate_validators(epoch_header) - .enumerate() - .map(|(validator_index, validator_id)| { - ( - validator_id.component_address, - ValidatorIndex::try_from(validator_index) - .expect("validator set size limit guarantees this"), - ) - }) - .collect::>(); - RoundUpdateTransactionV1 { - proposer_timestamp_ms: round_history.proposer_timestamp_ms, - epoch: round_history.epoch, - round: round_history.round, - leader_proposal_history: LeaderProposalHistory { - gap_round_leaders: round_history - .gap_round_leader_addresses - .iter() - .map(|leader_address| { - *validator_index_by_address - .get(leader_address) - .expect("gap round leader must belong to the validator set") - }) - .collect::>(), - current_leader: *validator_index_by_address - .get(&round_history.proposer_address) - .expect("proposer must belong to the validator set"), - is_fallback: round_history.is_fallback, - }, - } - } - - /// Note - we purposefully restrict what the content of a Round Update transaction can do - /// so we convert it to instructions at run-time. - pub fn create_instructions(&self) -> Vec { - vec![InstructionV1::CallMethod { - address: CONSENSUS_MANAGER.into(), - method_name: CONSENSUS_MANAGER_NEXT_ROUND_IDENT.to_string(), - args: to_manifest_value(&ConsensusManagerNextRoundInput { - round: self.round, - proposer_timestamp_ms: self.proposer_timestamp_ms, - leader_proposal_history: self.leader_proposal_history.clone(), - }) - .expect("round update input encoding should succeed"), - }] - } - - pub fn prepare(&self) -> Result { - let prepared_instructions = InstructionsV1(self.create_instructions()).prepare_partial()?; - let encoded_source = manifest_encode(&self)?; - // Minor TODO - for a slight performance improvement, change this to be read from the decoder - // As per the other hashes, don't include the prefix byte - let source_hash = hash(&encoded_source[1..]); - let instructions_hash = prepared_instructions.summary.hash; - let round_update_hash = HashAccumulator::new() - .update([ - TRANSACTION_HASHABLE_PAYLOAD_PREFIX, - TransactionDiscriminator::V1RoundUpdate as u8, - ]) - // We include the full source transaction contents - .update(source_hash) - // We also include the instructions hash, so the exact instructions can be proven - .update(instructions_hash) - .finalize(); - Ok(PreparedRoundUpdateTransactionV1 { - encoded_instructions: manifest_encode(&prepared_instructions.inner.0)?, - references: prepared_instructions.references, - blobs: index_map_new(), - summary: Summary { - effective_length: prepared_instructions.summary.effective_length, - total_bytes_hashed: prepared_instructions.summary.total_bytes_hashed, - hash: round_update_hash, - }, - }) - } -} - -impl TransactionPayload for RoundUpdateTransactionV1 { - type Versioned = FixedEnumVariant<{ TransactionDiscriminator::V1RoundUpdate as u8 }, Self>; - type Prepared = PreparedRoundUpdateTransactionV1; - type Raw = RawRoundUpdateTransactionV1; -} - -pub struct PreparedRoundUpdateTransactionV1 { - pub encoded_instructions: Vec, - pub references: IndexSet, - pub blobs: IndexMap>, - pub summary: Summary, -} - -impl HasSummary for PreparedRoundUpdateTransactionV1 { - fn get_summary(&self) -> &Summary { - &self.summary - } -} - -define_raw_transaction_payload!(RawRoundUpdateTransactionV1); - -impl TransactionPayloadPreparable for PreparedRoundUpdateTransactionV1 { - type Raw = RawRoundUpdateTransactionV1; - - fn prepare_for_payload(decoder: &mut TransactionDecoder) -> Result { - let decoded = decoder - .decode::<::Versioned>()? - .fields; - decoded.prepare() - } -} - -impl TransactionFullChildPreparable for PreparedRoundUpdateTransactionV1 { - fn prepare_as_full_body_child(decoder: &mut TransactionDecoder) -> Result { - let decoded = decoder.decode::()?; - decoded.prepare() - } -} - -impl PreparedRoundUpdateTransactionV1 { - pub fn get_executable(&self) -> Executable<'_> { - Executable::new( - &self.encoded_instructions, - &self.references, - &self.blobs, - ExecutionContext { - intent_hash: TransactionIntentHash::NotToCheck { - intent_hash: self.summary.hash, - }, - epoch_range: None, - payload_size: 0, - num_of_signature_validations: 0, - auth_zone_params: AuthZoneParams { - initial_proofs: btreeset!(AuthAddresses::validator_role()), - virtual_resources: BTreeSet::new(), - }, - costing_parameters: TransactionCostingParameters { - tip_percentage: 0, - free_credit_in_xrd: Decimal::ZERO, - abort_when_loan_repaid: false, - }, - pre_allocated_addresses: vec![], - }, - true, - ) - } -} - -define_wrapped_hash!(RoundUpdateTransactionHash); - -impl HasRoundUpdateTransactionHash for PreparedRoundUpdateTransactionV1 { - fn round_update_transaction_hash(&self) -> RoundUpdateTransactionHash { - RoundUpdateTransactionHash::from_hash(self.summary.hash) - } -} - -pub trait HasRoundUpdateTransactionHash { - fn round_update_transaction_hash(&self) -> RoundUpdateTransactionHash; -} - -/// A builder of "successful/timeout/gap rounds by leader" counter update, for metrics purposes. -#[derive(Default)] -pub struct LeaderRoundCountersBuilder { - /// Counters per validator (of the corresponding [`ValidatorIndex`]). - /// Implementation note: - /// This structure starts as an empty one (on the builder's initialization via `default()`). - /// Then, it is lazily-initialized by any larger-than-previously-observed [`ValidatorIndex`] - /// (within `update()`; see `get_counter_mut()`). The size of this vector is thus effectively - /// bounded by `u8::MAX` (even if validator indices found in proposal history were invalid). - counters_by_index: Vec, -} - -impl LeaderRoundCountersBuilder { - /// Increments the counters according to the information from proposal history. - /// This will at least update the current round leader's entry (either being successful or - /// fallback), and potentially many gap rounds (that were missed by validators since the - /// previously reported round change). - pub fn update(&mut self, leader_proposal_history: &LeaderProposalHistory) { - let current_leader_counter = self.get_counter_mut(&leader_proposal_history.current_leader); - if leader_proposal_history.is_fallback { - current_leader_counter.missed_by_fallback += 1; - } else { - current_leader_counter.successful += 1; - } - for gap_round_leader_index in leader_proposal_history.gap_round_leaders.iter() { - let gap_round_leader_counter = self.get_counter_mut(gap_round_leader_index); - gap_round_leader_counter.missed_by_gap += 1; - } - } - - /// Finalizes the build of the counters per validator. - /// Resolves the validator [`ComponentAddress`]es from the given epoch header. - /// Returns only the entries of validators for which some counts have changed. - pub fn build( - self, - epoch_header: Option<&LedgerHeader>, - ) -> Vec<(ValidatorId, LeaderRoundCounter)> { - self.counters_by_index - .into_iter() - .zip(iterate_validators(epoch_header)) - .filter(|(counter, _)| counter.is_non_zero()) - .map(|(counter, validator_id)| (validator_id, counter)) - .collect() - } - - fn get_counter_mut(&mut self, validator_index: &ValidatorIndex) -> &mut LeaderRoundCounter { - let index = *validator_index as usize; - if self.counters_by_index.len() <= index { - self.counters_by_index - .resize_with(index + 1, LeaderRoundCounter::default); - } - self.counters_by_index - .get_mut(index) - .expect("ensured by the branch above") - } -} - -/// A set of counters of rounds led by a concrete leader. -#[derive(Default, Clone, Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] -pub struct LeaderRoundCounter { - pub successful: usize, - pub missed_by_fallback: usize, - pub missed_by_gap: usize, -} - -impl LeaderRoundCounter { - /// Returns a sum of both kinds of missed rounds. - pub fn missed(&self) -> usize { - self.missed_by_fallback + self.missed_by_gap - } - - /// Returns true if *any* of the counters is non-zero. - pub fn is_non_zero(&self) -> bool { - self.successful != 0 || self.missed_by_fallback != 0 || self.missed_by_gap != 0 - } -} - -/// Extracts an iterator of validator IDs (in their [`ValidatorIndex`] order) from -/// the given epoch header (i.e. assumes that it was found and contains the "next epoch"). -fn iterate_validators( - epoch_header: Option<&LedgerHeader>, -) -> impl Iterator + '_ { - epoch_header - .expect("at least genesis epoch is expected") - .next_epoch - .as_ref() - .expect("epoch header must contain next epoch information") - .validator_set - .iter() - .map(ValidatorId::from) -} diff --git a/core-rust/state-manager/src/transaction/round_updates.rs b/core-rust/state-manager/src/transaction/round_updates.rs new file mode 100644 index 0000000000..b3bcc9610f --- /dev/null +++ b/core-rust/state-manager/src/transaction/round_updates.rs @@ -0,0 +1,129 @@ +use crate::prelude::*; + +pub fn create_round_update_transaction( + epoch_header: Option<&LedgerHeader>, + round_history: &RoundHistory, +) -> RoundUpdateTransactionV1 { + let validator_index_by_address = iterate_validators(epoch_header) + .enumerate() + .map(|(validator_index, validator_id)| { + ( + validator_id.component_address, + ValidatorIndex::try_from(validator_index) + .expect("validator set size limit guarantees this"), + ) + }) + .collect::>(); + RoundUpdateTransactionV1 { + proposer_timestamp_ms: round_history.proposer_timestamp_ms, + epoch: round_history.epoch, + round: round_history.round, + leader_proposal_history: LeaderProposalHistory { + gap_round_leaders: round_history + .gap_round_leader_addresses + .iter() + .map(|leader_address| { + *validator_index_by_address + .get(leader_address) + .expect("gap round leader must belong to the validator set") + }) + .collect::>(), + current_leader: *validator_index_by_address + .get(&round_history.proposer_address) + .expect("proposer must belong to the validator set"), + is_fallback: round_history.is_fallback, + }, + } +} + +/// A builder of "successful/timeout/gap rounds by leader" counter update, for metrics purposes. +#[derive(Default)] +pub struct LeaderRoundCountersBuilder { + /// Counters per validator (of the corresponding [`ValidatorIndex`]). + /// Implementation note: + /// This structure starts as an empty one (on the builder's initialization via `default()`). + /// Then, it is lazily-initialized by any larger-than-previously-observed [`ValidatorIndex`] + /// (within `update()`; see `get_counter_mut()`). The size of this vector is thus effectively + /// bounded by `u8::MAX` (even if validator indices found in proposal history were invalid). + counters_by_index: Vec, +} + +impl LeaderRoundCountersBuilder { + /// Increments the counters according to the information from proposal history. + /// This will at least update the current round leader's entry (either being successful or + /// fallback), and potentially many gap rounds (that were missed by validators since the + /// previously reported round change). + pub fn update(&mut self, leader_proposal_history: &LeaderProposalHistory) { + let current_leader_counter = self.get_counter_mut(&leader_proposal_history.current_leader); + if leader_proposal_history.is_fallback { + current_leader_counter.missed_by_fallback += 1; + } else { + current_leader_counter.successful += 1; + } + for gap_round_leader_index in leader_proposal_history.gap_round_leaders.iter() { + let gap_round_leader_counter = self.get_counter_mut(gap_round_leader_index); + gap_round_leader_counter.missed_by_gap += 1; + } + } + + /// Finalizes the build of the counters per validator. + /// Resolves the validator [`ComponentAddress`]es from the given epoch header. + /// Returns only the entries of validators for which some counts have changed. + pub fn build( + self, + epoch_header: Option<&LedgerHeader>, + ) -> Vec<(ValidatorId, LeaderRoundCounter)> { + self.counters_by_index + .into_iter() + .zip(iterate_validators(epoch_header)) + .filter(|(counter, _)| counter.is_non_zero()) + .map(|(counter, validator_id)| (validator_id, counter)) + .collect() + } + + fn get_counter_mut(&mut self, validator_index: &ValidatorIndex) -> &mut LeaderRoundCounter { + let index = *validator_index as usize; + if self.counters_by_index.len() <= index { + self.counters_by_index + .resize_with(index + 1, LeaderRoundCounter::default); + } + self.counters_by_index + .get_mut(index) + .expect("ensured by the branch above") + } +} + +/// A set of counters of rounds led by a concrete leader. +#[derive(Default, Clone, Debug, ScryptoSbor)] +pub struct LeaderRoundCounter { + pub successful: usize, + pub missed_by_fallback: usize, + pub missed_by_gap: usize, +} + +impl LeaderRoundCounter { + /// Returns a sum of both kinds of missed rounds. + pub fn missed(&self) -> usize { + self.missed_by_fallback + self.missed_by_gap + } + + /// Returns true if *any* of the counters is non-zero. + pub fn is_non_zero(&self) -> bool { + self.successful != 0 || self.missed_by_fallback != 0 || self.missed_by_gap != 0 + } +} + +/// Extracts an iterator of validator IDs (in their [`ValidatorIndex`] order) from +/// the given epoch header (i.e. assumes that it was found and contains the "next epoch"). +fn iterate_validators( + epoch_header: Option<&LedgerHeader>, +) -> impl Iterator + '_ { + epoch_header + .expect("at least genesis epoch is expected") + .next_epoch + .as_ref() + .expect("epoch header must contain next epoch information") + .validator_set + .iter() + .map(ValidatorId::from) +} diff --git a/core-rust/state-manager/src/transaction/series_execution.rs b/core-rust/state-manager/src/transaction/series_execution.rs index 6e1dc88505..12754bf26e 100644 --- a/core-rust/state-manager/src/transaction/series_execution.rs +++ b/core-rust/state-manager/src/transaction/series_execution.rs @@ -62,20 +62,10 @@ * permissions under this License. */ -use node_common::utils::CaptureSupport; +use crate::prelude::*; use std::fmt::Formatter; -use std::ops::Deref; -use std::sync::Arc; use crate::commit_bundle::CommitBundleBuilder; -use crate::protocol::*; -use crate::query::*; -use crate::staging::ReadableStore; -use crate::store::traits::*; -use crate::transaction::*; -use crate::*; - -use crate::engine_prelude::*; pub struct TransactionExecutorFactory { execution_configurator: Arc, @@ -144,10 +134,11 @@ where /// the transaction's ledger hash). pub fn execute_and_update_state( &mut self, - transaction: &ValidatedLedgerTransaction, + executable: &LedgerExecutable, + hashes: &LedgerTransactionHashes, description: &str, ) -> Result { - let result = self.execute_no_state_update(transaction, description); + let result = self.execute_no_state_update(executable, hashes, description); if let Ok(commit) = &result { self.update_state(commit); } @@ -162,17 +153,21 @@ where /// the transaction's ledger hash). pub fn execute_no_state_update( &mut self, - transaction: &ValidatedLedgerTransaction, + executable: &LedgerExecutable, + hashes: &LedgerTransactionHashes, description: &str, ) -> Result { let described_ledger_transaction_hash = DescribedTransactionHash { - ledger_hash: transaction.ledger_transaction_hash(), + ledger_hash: hashes.ledger_transaction_hash, description, }; self.execute_wrapped_no_state_update( &described_ledger_transaction_hash, - self.execution_configurator - .wrap_ledger_transaction(transaction, &described_ledger_transaction_hash), + self.execution_configurator.wrap_ledger_transaction( + hashes, + executable, + &described_ledger_transaction_hash, + ), ) } diff --git a/core-rust/state-manager/src/transaction/validation.rs b/core-rust/state-manager/src/transaction/validation.rs index 298c5b1b7e..fc360b3e06 100644 --- a/core-rust/state-manager/src/transaction/validation.rs +++ b/core-rust/state-manager/src/transaction/validation.rs @@ -1,216 +1,58 @@ -use node_common::locks::{DbLock, RwLock}; -use std::ops::Deref; -use std::sync::Arc; -use std::time::SystemTime; - -use crate::engine_prelude::*; - -use crate::query::StateManagerSubstateQueries; - -use crate::store::rocks_db::ActualStateManagerDatabase; -use crate::store::traits::transactions::QueryableTransactionStore; -use crate::store::traits::{QueryableProofStore, TransactionIndex}; -use crate::transaction::{ExecutionConfigurator, TransactionLogic}; -use crate::{ - AlreadyCommittedError, AtSpecificState, AtState, ExecutionRejectionReason, - MempoolRejectionReason, PendingTransactionRecord, PendingTransactionResultCache, - TransactionAttempt, -}; - -use super::{ - LedgerTransaction, PreparedLedgerTransaction, PreparedLedgerTransactionInner, - RawLedgerTransaction, ValidatedLedgerTransaction, ValidatedLedgerTransactionInner, -}; - -pub struct LedgerTransactionValidator { - pub validation_config: ValidationConfig, - pub ledger_payload_limit: usize, - pub user_transaction_validator: NotarizedTransactionValidator, -} - -impl LedgerTransactionValidator { - pub fn default_from_network(network: &NetworkDefinition) -> Self { - Self::default_from_validation_config(ValidationConfig::default(network.id)) - } - - pub fn default_from_validation_config(validation_config: ValidationConfig) -> Self { - Self { - validation_config, - // Add a few extra bytes for the enum discriminator at the start(!) - ledger_payload_limit: validation_config.max_notarized_payload_size + 10, - user_transaction_validator: NotarizedTransactionValidator::new(validation_config), - } - } - - pub fn prepare_from_model( - &self, - transaction: &LedgerTransaction, - ) -> Result { - self.prepare_from_raw(&transaction.to_raw()?) - } - - pub fn prepare_from_raw( - &self, - raw: &RawLedgerTransaction, - ) -> Result { - self.prepare_from_payload_bytes(raw.as_slice()) - } - - fn prepare_from_payload_bytes( - &self, - raw_payload_bytes: &[u8], - ) -> Result { - if raw_payload_bytes.len() > self.ledger_payload_limit { - return Err(TransactionValidationError::TransactionTooLarge); - } - - Ok(PreparedLedgerTransaction::prepare_from_payload( - raw_payload_bytes, - )?) - } - - pub fn validate_user_or_round_update_from_model( - &self, - transaction: &LedgerTransaction, - ) -> Result { - self.validate_user_or_round_update(transaction.prepare()?) - } - - pub fn validate_user_or_round_update_from_raw( - &self, - raw: &RawLedgerTransaction, - ) -> Result { - self.validate_user_or_round_update_from_payload_bytes(raw.as_slice()) - } - - pub fn validate_user_or_round_update_from_payload_bytes( - &self, - payload_bytes: &[u8], - ) -> Result { - let prepared = self.prepare_from_payload_bytes(payload_bytes)?; - self.validate_user_or_round_update(prepared) - } - - pub fn validate_user_or_round_update( - &self, - prepared: PreparedLedgerTransaction, - ) -> Result { - let validated_inner = match prepared.inner { - PreparedLedgerTransactionInner::Genesis(_) => { - return Err(LedgerTransactionValidationError::GenesisTransactionProvided); - } - PreparedLedgerTransactionInner::UserV1(prepared) => { - let validated = self.user_transaction_validator.validate(*prepared)?; - ValidatedLedgerTransactionInner::UserV1(Box::new(validated)) - } - PreparedLedgerTransactionInner::RoundUpdateV1(prepared) => { - ValidatedLedgerTransactionInner::RoundUpdateV1(prepared) - } - PreparedLedgerTransactionInner::FlashV1(_) => { - return Err(LedgerTransactionValidationError::FlashTransactionProvided); - } - }; - Ok(ValidatedLedgerTransaction { - inner: validated_inner, - summary: prepared.summary, - }) - } +use crate::prelude::*; - pub fn validate_genesis( - &self, - prepared: PreparedLedgerTransaction, - ) -> ValidatedLedgerTransaction { - let PreparedLedgerTransactionInner::Genesis(t) = prepared.inner else { - panic!("Genesis transaction was not a system transaction") - }; - ValidatedLedgerTransaction { - inner: ValidatedLedgerTransactionInner::Genesis(t), - summary: prepared.summary, - } - } - - pub fn validate_flash( - &self, - prepared: PreparedLedgerTransaction, - ) -> ValidatedLedgerTransaction { - let PreparedLedgerTransactionInner::FlashV1(t) = prepared.inner else { - panic!("Flash transaction was not a system transaction") - }; - ValidatedLedgerTransaction { - inner: ValidatedLedgerTransactionInner::FlashV1(t), - summary: prepared.summary, - } - } -} - -#[derive(Debug, Clone)] -pub enum LedgerTransactionValidationError { - ValidationError(TransactionValidationError), - GenesisTransactionProvided, - FlashTransactionProvided, +pub trait LedgerTransactionValidationErrorExtensions { + fn into_user_validation_error(self) -> TransactionValidationError; } -impl LedgerTransactionValidationError { +impl LedgerTransactionValidationErrorExtensions for LedgerTransactionValidationError { // Should only be called on errors from validating user transactions - pub fn into_user_validation_error(self) -> TransactionValidationError { + fn into_user_validation_error(self) -> TransactionValidationError { match self { LedgerTransactionValidationError::ValidationError(x) => x, - LedgerTransactionValidationError::GenesisTransactionProvided => { - panic!("into_user_validation_error called on a genesis transaction payload") - } - LedgerTransactionValidationError::FlashTransactionProvided => { - panic!("into_user_validation_error called on a flash transaction payload") + LedgerTransactionValidationError::GenesisTransactionNotCurrentlyPermitted + | LedgerTransactionValidationError::UserTransactionNotCurrentlyPermitted + | LedgerTransactionValidationError::ValidateTransactionNotCurrentlyPermitted + | LedgerTransactionValidationError::ProtocolUpdateNotCurrentlyPermitted + | LedgerTransactionValidationError::FlashNotCurrentlyPermitted => { + panic!("into_user_validation_error called unexpectedly on an incorrect transaction type error") } } } } -impl From for LedgerTransactionValidationError { - fn from(value: TransactionValidationError) -> Self { - Self::ValidationError(value) - } -} - -impl From for LedgerTransactionValidationError { - fn from(value: PrepareError) -> Self { - Self::ValidationError(TransactionValidationError::PrepareError(value)) - } -} - /// A validator for `NotarizedTransaction`, deciding whether they would be rejected or not-rejected /// (i.e. "committable") at a specific state of the `store`. pub struct CommittabilityValidator { database: Arc>, execution_configurator: Arc, - user_transaction_validator: NotarizedTransactionValidator, + transaction_validator: Arc>, } impl CommittabilityValidator { pub fn new( database: Arc>, execution_configurator: Arc, - user_transaction_validator: NotarizedTransactionValidator, + transaction_validator: Arc>, ) -> Self { Self { database, execution_configurator, - user_transaction_validator, + transaction_validator, } } pub fn prepare_from_raw( &self, transaction: &RawNotarizedTransaction, - ) -> Result { - self.user_transaction_validator - .prepare_from_raw(transaction) + ) -> Result { + transaction.prepare(self.transaction_validator.read().preparation_settings()) } pub fn validate( &self, - transaction: PreparedNotarizedTransactionV1, - ) -> Result { - self.user_transaction_validator.validate(transaction) + transaction: PreparedUserTransaction, + ) -> Result { + transaction.validate(self.transaction_validator.read().deref()) } } @@ -218,14 +60,15 @@ impl CommittabilityValidator { /// Determine whether it would be rejected given the current state of the substate store. pub fn check_for_rejection( &self, - transaction: &ValidatedNotarizedTransactionV1, + executable: &ExecutableTransaction, + user_hashes: &UserTransactionHashes, timestamp: SystemTime, ) -> TransactionAttempt { let database = self.database.snapshot(); let executed_at_state_version = database.max_state_version(); let existing = - database.get_txn_state_version_by_identifier(&transaction.prepared.intent_hash()); + database.get_txn_state_version_by_identifier(&user_hashes.transaction_intent_hash); if let Some(state_version) = existing { let committed_transaction_identifiers = database @@ -235,14 +78,11 @@ impl CommittabilityValidator { return TransactionAttempt { rejection: Some(MempoolRejectionReason::AlreadyCommitted( AlreadyCommittedError { - notarized_transaction_hash: transaction - .prepared - .notarized_transaction_hash(), + notarized_transaction_hash: user_hashes.notarized_transaction_hash, committed_state_version: state_version, - committed_notarized_transaction_hash: *committed_transaction_identifiers - .payload - .typed - .user() + committed_notarized_transaction_hash: committed_transaction_identifiers + .transaction_hashes + .as_user() .expect("non-user transaction located by intent hash") .notarized_transaction_hash, }, @@ -256,7 +96,7 @@ impl CommittabilityValidator { let receipt = self .execution_configurator - .wrap_pending_transaction(transaction) + .wrap_pending_transaction(executable, user_hashes) .execute_on(database.deref()); let result = match receipt.result { @@ -267,7 +107,7 @@ impl CommittabilityValidator { ) { panic!( "intent {:?} not found by Node, but reported as committed by Engine", - transaction.prepared.intent_hash() + user_hashes.transaction_intent_hash ); } Err(MempoolRejectionReason::FromExecution(Box::new(reason))) @@ -314,21 +154,18 @@ impl CachedCommittabilityValidator { pub fn prepare_from_raw( &self, transaction: &RawNotarizedTransaction, - ) -> Result { + ) -> Result { self.committability_validator .read() .prepare_from_raw(transaction) } - fn read_record( - &self, - prepared: &PreparedNotarizedTransactionV1, - ) -> Option { + fn read_record(&self, prepared: &PreparedUserTransaction) -> Option { // Even though we only want to read the cache here, the LRU structs require a write lock self.pending_transaction_result_cache .write() .get_pending_transaction_record( - &prepared.intent_hash(), + &prepared.transaction_intent_hash(), &prepared.notarized_transaction_hash(), ) } @@ -343,31 +180,70 @@ impl CachedCommittabilityValidator { .track_transaction_result( metadata.intent_hash, metadata.notarized_transaction_hash, - Some(metadata.invalid_from_epoch), + Some(metadata.end_epoch_exclusive), attempt, ) } } struct TransactionMetadata { - intent_hash: IntentHash, + intent_hash: TransactionIntentHash, notarized_transaction_hash: NotarizedTransactionHash, - invalid_from_epoch: Epoch, + end_epoch_exclusive: Epoch, } impl TransactionMetadata { - pub fn read_from(prepared: &PreparedNotarizedTransactionV1) -> Self { + pub fn read_from_user_executable( + executable: &ExecutableTransaction, + user_hashes: &UserTransactionHashes, + ) -> Self { Self { - intent_hash: prepared.intent_hash(), - notarized_transaction_hash: prepared.notarized_transaction_hash(), - invalid_from_epoch: prepared - .signed_intent - .intent - .header - .inner + intent_hash: user_hashes.transaction_intent_hash, + notarized_transaction_hash: user_hashes.notarized_transaction_hash, + end_epoch_exclusive: executable + .overall_epoch_range() + .expect("User executable transactions should have an epoch range") .end_epoch_exclusive, } } + + pub fn read_from_prepared(prepared: &PreparedUserTransaction) -> Self { + Self { + intent_hash: prepared.transaction_intent_hash(), + notarized_transaction_hash: prepared.notarized_transaction_hash(), + end_epoch_exclusive: match prepared { + #[allow(deprecated)] + PreparedUserTransaction::V1(prepared) => { + prepared + .signed_intent + .intent + .header + .inner + .end_epoch_exclusive + } + PreparedUserTransaction::V2(prepared) => { + let transaction_intent = &prepared.signed_intent.transaction_intent; + + let root_intent_expiry_epoch = transaction_intent + .root_intent_core + .header + .inner + .end_epoch_exclusive; + let non_root_intent_expiry_epochs = transaction_intent + .non_root_subintents + .subintents + .iter() + .map(|subintent| subintent.intent_core.header.inner.end_epoch_exclusive); + + // Unwrapping as we know it's non-empty + std::iter::once(root_intent_expiry_epoch) + .chain(non_root_intent_expiry_epochs) + .min() + .unwrap() + } + }, + } + } } enum ShouldRecalculate { @@ -390,7 +266,10 @@ impl CheckMetadata { } pub enum StaticValidation { - Valid(Box), + Valid { + executable: ExecutableTransaction, + user_hashes: UserTransactionHashes, + }, Invalid, } @@ -413,7 +292,7 @@ impl CachedCommittabilityValidator { /// attempt was cached, and the validated notarized transaction (if it's new) pub fn check_for_rejection_cached( &self, - prepared: PreparedNotarizedTransactionV1, + prepared: PreparedUserTransaction, force_recalculate: ForceRecalculation, ) -> (PendingTransactionRecord, CheckMetadata) { let current_time = SystemTime::now(); @@ -424,17 +303,25 @@ impl CachedCommittabilityValidator { return (record, CheckMetadata::Cached); } - let metadata = TransactionMetadata::read_from(&prepared); + let metadata = TransactionMetadata::read_from_prepared(&prepared); let read_committability_validator = self.committability_validator.read(); match read_committability_validator.validate(prepared) { Ok(validated) => { // Transaction was valid - let's also attempt to execute it - let attempt = - read_committability_validator.check_for_rejection(&validated, current_time); + let user_hashes = validated.hashes(); + let executable = validated.create_executable(); + let attempt = read_committability_validator.check_for_rejection( + &executable, + &user_hashes, + current_time, + ); ( self.write_attempt(metadata, attempt), - CheckMetadata::Fresh(StaticValidation::Valid(Box::new(validated))), + CheckMetadata::Fresh(StaticValidation::Valid { + executable, + user_hashes, + }), ) } Err(validation_error) => { @@ -462,21 +349,23 @@ impl CachedCommittabilityValidator { /// Returns the transaction's new pending transaction record. pub fn check_for_rejection_validated( &self, - validated: &ValidatedNotarizedTransactionV1, + executable: &ExecutableTransaction, + user_hashes: &UserTransactionHashes, ) -> PendingTransactionRecord { - let metadata = TransactionMetadata::read_from(&validated.prepared); + let metadata = TransactionMetadata::read_from_user_executable(executable, user_hashes); - let attempt = self - .committability_validator - .read() - .check_for_rejection(validated, SystemTime::now()); + let attempt = self.committability_validator.read().check_for_rejection( + executable, + user_hashes, + SystemTime::now(), + ); self.write_attempt(metadata, attempt) } fn should_recalculate( &self, - prepared: &PreparedNotarizedTransactionV1, + prepared: &PreparedUserTransaction, current_time: SystemTime, force_recalculate: ForceRecalculation, ) -> ShouldRecalculate { diff --git a/core-rust/state-manager/src/types.rs b/core-rust/state-manager/src/types.rs index bd7ee10ed8..cbb6501f57 100644 --- a/core-rust/state-manager/src/types.rs +++ b/core-rust/state-manager/src/types.rs @@ -62,22 +62,18 @@ * permissions under this License. */ -use crate::accumulator_tree::IsMerklizableHash; -use crate::engine_prelude::*; -use crate::protocol::ProtocolVersionName; -use crate::transaction::*; -use crate::{LedgerTransactionOutcome, PartitionChange, SubstateChange}; +use crate::prelude::*; use std::fmt; use std::fmt::Formatter; use std::mem::size_of; use std::num::TryFromIntError; /// A complete ID of a Substate. -#[derive(Debug, Clone, Hash, Eq, PartialEq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, Hash, Eq, PartialEq, ScryptoSbor)] pub struct SubstateReference(pub NodeId, pub PartitionNumber, pub SubstateKey); /// A complete ID of a Partition. -#[derive(Debug, Clone, Hash, Eq, PartialEq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, Hash, Eq, PartialEq, ScryptoSbor)] pub struct PartitionReference(pub NodeId, pub PartitionNumber); define_wrapped_hash!(StateChangeHash); @@ -315,13 +311,13 @@ pub struct PreviewRequest { pub message: MessageV1, } -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, ScryptoSbor)] pub enum InvalidCommitRequestError { TransactionParsingFailed, TransactionRootMismatch, } -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, ScryptoSbor)] pub struct CommitRequest { pub transactions: Vec, pub proof: LedgerProof, @@ -329,13 +325,13 @@ pub struct CommitRequest { pub self_validator_id: Option, // for metrics calculation only } -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, ScryptoSbor)] pub struct CommitSummary { pub validator_round_counters: Vec<(ValidatorId, LeaderRoundCounter)>, pub num_user_transactions: u32, } -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, ScryptoSbor)] pub struct PrepareRequest { pub committed_ledger_hashes: LedgerHashes, pub ancestor_transactions: Vec, @@ -344,7 +340,7 @@ pub struct PrepareRequest { pub round_history: RoundHistory, } -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, ScryptoSbor)] pub struct RoundHistory { pub is_fallback: bool, pub epoch: Epoch, @@ -354,7 +350,7 @@ pub struct RoundHistory { pub proposer_timestamp_ms: i64, } -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, ScryptoSbor)] pub struct PrepareResult { pub committed: Vec, /// Note: this is only used for testing @@ -364,40 +360,92 @@ pub struct PrepareResult { pub ledger_hashes: LedgerHashes, } -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, ScryptoSbor)] pub struct CommittableTransaction { /// Not included for the Round Change transaction which is inserted and doesn't come from the proposal pub index: Option, pub raw: RawLedgerTransaction, - pub intent_hash: Option, + pub transaction_intent_hash: Option, pub notarized_transaction_hash: Option, pub ledger_transaction_hash: LedgerTransactionHash, } -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +impl CommittableTransaction { + pub fn new( + index: usize, + raw: RawLedgerTransaction, + ledger_transaction_hash: LedgerTransactionHash, + user_hashes: UserTransactionHashes, + ) -> Self { + Self { + index: Some( + index + .try_into() + .expect("Proposal index should be < u32::MAX"), + ), + raw, + transaction_intent_hash: Some(user_hashes.transaction_intent_hash), + notarized_transaction_hash: Some(user_hashes.notarized_transaction_hash), + ledger_transaction_hash, + } + } +} + +#[derive(Debug, ScryptoSbor)] pub struct RejectedTransaction { pub index: u32, // Note - these are None if the transaction can't even be prepared to determine the hashes - pub intent_hash: Option, + pub transaction_intent_hash: Option, pub notarized_transaction_hash: Option, pub ledger_transaction_hash: Option, pub error: String, } -#[derive(Debug, Clone, Eq, PartialEq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +impl RejectedTransaction { + pub fn failed_before_prepare(index: usize, error: String) -> Self { + Self { + index: index + .try_into() + .expect("Proposal index should be < u32::MAX"), + transaction_intent_hash: None, + notarized_transaction_hash: None, + ledger_transaction_hash: None, + error, + } + } + + pub fn new( + index: usize, + error: String, + ledger_transaction_hash: LedgerTransactionHash, + user_hashes: UserTransactionHashes, + ) -> Self { + Self { + index: index + .try_into() + .expect("Proposal index should be < u32::MAX"), + transaction_intent_hash: Some(user_hashes.transaction_intent_hash), + notarized_transaction_hash: Some(user_hashes.notarized_transaction_hash), + ledger_transaction_hash: Some(ledger_transaction_hash), + error, + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, ScryptoSbor)] pub struct ActiveValidatorInfo { pub address: ComponentAddress, pub key: Secp256k1PublicKey, pub stake: Decimal, } -#[derive(Debug, Clone, Eq, PartialEq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, Eq, PartialEq, ScryptoSbor)] pub struct NextEpoch { pub epoch: Epoch, pub validator_set: Vec, } -#[derive(Debug, Clone, Eq, PartialEq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, Eq, PartialEq, ScryptoSbor)] pub struct TimestampedValidatorSignature { pub key: Secp256k1PublicKey, pub validator_address: ComponentAddress, @@ -406,7 +454,7 @@ pub struct TimestampedValidatorSignature { } define_versioned!( - #[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] + #[derive(Debug, Clone, ScryptoSbor)] pub VersionedLedgerProof(LedgerProofVersions) { previous_versions: [ 1 => LedgerProofV1: { updates_to: 2 }, @@ -417,20 +465,20 @@ define_versioned!( } ); -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct LedgerProofV1 { pub opaque: Hash, pub ledger_header: LedgerHeaderV1, pub timestamped_signatures: Vec, } -#[derive(Debug, Clone, Eq, PartialEq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, Eq, PartialEq, ScryptoSbor)] pub struct LedgerProofV2 { pub ledger_header: LedgerHeader, pub origin: LedgerProofOrigin, } -#[derive(Debug, Clone, Eq, PartialEq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, Eq, PartialEq, ScryptoSbor)] pub enum LedgerProofOrigin { Genesis { genesis_opaque_hash: Hash, @@ -441,7 +489,7 @@ pub enum LedgerProofOrigin { }, ProtocolUpdate { protocol_version_name: ProtocolVersionName, - batch_idx: u32, + batch_index: u32, }, } @@ -465,7 +513,7 @@ impl From for LedgerProofV2 { } } -#[derive(Debug, Clone, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, ScryptoSbor)] pub struct LedgerHeaderV1 { pub epoch: Epoch, pub round: Round, @@ -476,7 +524,7 @@ pub struct LedgerHeaderV1 { pub next_epoch: Option, } -#[derive(Debug, Clone, Eq, PartialEq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, Eq, PartialEq, ScryptoSbor)] pub struct LedgerHeader { pub epoch: Epoch, pub round: Round, @@ -523,7 +571,7 @@ impl From for LedgerStateSummary { } } -#[derive(Debug, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, ScryptoSbor)] pub struct ProtocolUpdateResult { pub post_update_proof: LedgerProof, } @@ -553,7 +601,7 @@ impl EpochTransactionIdentifiers { } } -#[derive(Debug, Clone, Copy, Eq, PartialEq, ScryptoCategorize, ScryptoEncode, ScryptoDecode)] +#[derive(Debug, Clone, Copy, Eq, PartialEq, ScryptoSbor)] pub struct ValidatorId { pub component_address: ComponentAddress, pub key: Secp256k1PublicKey, diff --git a/core/src/integration/java/com/radixdlt/integration/steady_state/deterministic/rev2/consensus_ledger_sync/MultiNodeRebootTest.java b/core/src/integration/java/com/radixdlt/integration/steady_state/deterministic/rev2/consensus_ledger_sync/MultiNodeRebootTest.java index 9a92ac92a9..b8496d0f39 100644 --- a/core/src/integration/java/com/radixdlt/integration/steady_state/deterministic/rev2/consensus_ledger_sync/MultiNodeRebootTest.java +++ b/core/src/integration/java/com/radixdlt/integration/steady_state/deterministic/rev2/consensus_ledger_sync/MultiNodeRebootTest.java @@ -88,12 +88,16 @@ import java.util.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +@Ignore( + "Cuttlefish - Both the positive and negative tests are still somewhat flaky, so ignoring these" + + " tests for now") @RunWith(Parameterized.class) public final class MultiNodeRebootTest { @Parameterized.Parameters diff --git a/core/src/main/java/com/radixdlt/ledger/LedgerProofBundle.java b/core/src/main/java/com/radixdlt/ledger/LedgerProofBundle.java index 03ee3664a6..201f7332ab 100644 --- a/core/src/main/java/com/radixdlt/ledger/LedgerProofBundle.java +++ b/core/src/main/java/com/radixdlt/ledger/LedgerProofBundle.java @@ -79,12 +79,12 @@ public record LedgerProofBundle( LedgerProof primaryProof, // Latest (with respect to `primaryProof`) epoch change proof. // Could be the `primaryProof` itself. - LedgerProof closestEpochProofOnOrBefore, + LedgerProof latestProofWhichInitiatedAnEpochChange, // Latest (with respect to primaryProof) proof that initiated a protocol update. // Could be the `primaryProof` itself. - Option closestProtocolUpdateInitProofOnOrBefore, + Option latestProofWhichInitiatedAProtocolUpdate, // Latest (with respect to `primaryProof`) proof of ProtocolUpdate `origin`. - Option closestProtocolUpdateExecutionProofOnOrBefore) { + Option latestProtocolUpdateExecutionProof) { public static LedgerProofBundle mockedOfHeader(com.radixdlt.consensus.LedgerHeader ledgerHeader) { final var proof = @@ -101,20 +101,20 @@ public static LedgerProofBundle mockedOfHeader(com.radixdlt.consensus.LedgerHead * proof created during the protocol update. */ public LedgerHeader epochInitialHeader() { - return closestProtocolUpdateExecutionProofOnOrBefore + return latestProtocolUpdateExecutionProof .map( protocolUpdateExecutionProof -> { - // If we have executed some protocol updates, check if the latest + // If we have executed some protocoxl updates, check if the latest // proof we have is actually newer than the real epoch proof. // If so, use it instead of an epoch proof. if (protocolUpdateExecutionProof.stateVersion() - >= closestEpochProofOnOrBefore.stateVersion()) { + >= latestProofWhichInitiatedAnEpochChange.stateVersion()) { return protocolUpdateExecutionProof.ledgerHeader(); } else { - return closestEpochProofOnOrBefore.ledgerHeader(); + return latestProofWhichInitiatedAnEpochChange.ledgerHeader(); } }) - .orElse(closestEpochProofOnOrBefore.ledgerHeader()); + .orElse(latestProofWhichInitiatedAnEpochChange.ledgerHeader()); } /** @@ -129,7 +129,7 @@ public Round resultantRound() { case LedgerProofOrigin.ProtocolUpdate protocolUpdate -> // This assumes that protocol updates always happen at epoch boundary // (which is true, for now) - closestProtocolUpdateInitProofOnOrBefore.unwrap().ledgerHeader(); + latestProofWhichInitiatedAProtocolUpdate.unwrap().ledgerHeader(); }; return maybeEpochChangeHeader.nextEpoch().isPresent() @@ -138,7 +138,12 @@ public Round resultantRound() { } public long resultantEpoch() { - return closestEpochProofOnOrBefore.ledgerHeader().nextEpoch().unwrap().epoch().toLong(); + return latestProofWhichInitiatedAnEpochChange + .ledgerHeader() + .nextEpoch() + .unwrap() + .epoch() + .toLong(); } public long resultantStateVersion() { @@ -161,7 +166,7 @@ public LedgerProof trimProtocolUpdate() { // Since protocol updates can't themselves trigger another protocol update, // this is guaranteed to be a consensus (or, possibly in some testing corner case, genesis) // proof. - closestProtocolUpdateInitProofOnOrBefore().unwrap(); + latestProofWhichInitiatedAProtocolUpdate().unwrap(); }; } } diff --git a/core/src/main/java/com/radixdlt/logger/EventLoggerModule.java b/core/src/main/java/com/radixdlt/logger/EventLoggerModule.java index 21eab121f9..e2804c78e1 100644 --- a/core/src/main/java/com/radixdlt/logger/EventLoggerModule.java +++ b/core/src/main/java/com/radixdlt/logger/EventLoggerModule.java @@ -227,7 +227,7 @@ private static void logProtocolUpdate(LedgerProofBundle proof) { } else if (proof.primaryProof().origin() instanceof LedgerProofOrigin.ProtocolUpdate) { // Protocol update init proof must be present if latest proof is of ProtocolUpdate origin. final var protocolUpdateInitHeader = - proof.closestProtocolUpdateInitProofOnOrBefore().unwrap().ledgerHeader(); + proof.latestProofWhichInitiatedAProtocolUpdate().unwrap().ledgerHeader(); final var postProtocolUpdateHeader = proof.primaryProof().ledgerHeader(); final var initStateVersion = protocolUpdateInitHeader.stateVersion().toLong(); final var postStateVersion = postProtocolUpdateHeader.stateVersion().toLong(); diff --git a/core/src/main/java/com/radixdlt/monitoring/InMemorySystemInfo.java b/core/src/main/java/com/radixdlt/monitoring/InMemorySystemInfo.java index c1f66462b6..9cca63817b 100644 --- a/core/src/main/java/com/radixdlt/monitoring/InMemorySystemInfo.java +++ b/core/src/main/java/com/radixdlt/monitoring/InMemorySystemInfo.java @@ -86,7 +86,7 @@ public InMemorySystemInfo( ProtocolState initialProtocolState) { this.rustStateReader = rustStateReader; final var latestEpochChange = - latestProof.closestEpochProofOnOrBefore().ledgerHeader().nextEpoch().unwrap(); + latestProof.latestProofWhichInitiatedAnEpochChange().ledgerHeader().nextEpoch().unwrap(); this.state = new InMemorySystemInfoState( initialProtocolState, diff --git a/core/src/main/java/com/radixdlt/rev2/REv2StateComputer.java b/core/src/main/java/com/radixdlt/rev2/REv2StateComputer.java index 939d6a29f1..37ed2b6ea5 100644 --- a/core/src/main/java/com/radixdlt/rev2/REv2StateComputer.java +++ b/core/src/main/java/com/radixdlt/rev2/REv2StateComputer.java @@ -64,6 +64,8 @@ package com.radixdlt.rev2; +import static com.radixdlt.lang.Option.none; + import com.radixdlt.consensus.BFTConfiguration; import com.radixdlt.consensus.LedgerHashes; import com.radixdlt.consensus.NextEpoch; @@ -285,14 +287,13 @@ public StateComputerLedger.StateComputerPrepareResult prepare( @Override public LedgerProofBundle commit(LedgerExtension ledgerExtension, VertexStoreState vertexStore) { final var proof = ledgerExtension.proof(); - final var header = proof.ledgerHeader(); final Option vertexStoreBytes; if (vertexStore != null) { vertexStoreBytes = Option.some(serialization.toDson(vertexStore.toSerialized(), DsonOutput.Output.ALL)); } else { - vertexStoreBytes = Option.none(); + vertexStoreBytes = none(); } var commitRequest = @@ -308,43 +309,57 @@ public LedgerProofBundle commit(LedgerExtension ledgerExtension, VertexStoreStat }) .unwrap(); - final var maybeNextEpoch = header.nextEpoch(); - final var maybeNextProtocolVersion = header.nextProtocolVersion(); - - if (maybeNextProtocolVersion.isPresent() && maybeNextEpoch.isEmpty()) { - throw new IllegalStateException("Protocol updates must happen at epoch boundary"); + // Prepare to update the latestProof bundle + var newLatestProof = proof; + var latestProofWhichInitiatedAnEpochChange = + this.latestProof.latestProofWhichInitiatedAnEpochChange(); + var latestProofWhichInitiatedAProtocolUpdate = + this.latestProof.latestProofWhichInitiatedAProtocolUpdate(); + var latestProtocolUpdateExecutionProof = this.latestProof.latestProtocolUpdateExecutionProof(); + + if (newLatestProof.ledgerHeader().nextProtocolVersion().isPresent() + && newLatestProof.ledgerHeader().nextEpoch().isEmpty()) { + throw new IllegalStateException( + "Initial protocol update triggers must happen at epoch boundary"); } - // Synchronously apply a protocol update while we still hold a StateComputerResult lock - final var maybePostProtocolUpdateProof = - maybeNextProtocolVersion.map( - nextProtocolVersion -> - this.rustProtocolUpdate.applyProtocolUpdate(nextProtocolVersion).postUpdateProof()); - - final var newLatestProof = maybePostProtocolUpdateProof.orElse(proof); + // A loop here allows us to enact protocol updates back-to-back + LedgerProof lastHandledProof; + Option maybeNextEpoch = none(); + do { + lastHandledProof = newLatestProof; + final var newHeader = newLatestProof.ledgerHeader(); + if (newHeader.nextEpoch().isPresent()) { + latestProofWhichInitiatedAnEpochChange = newLatestProof; + maybeNextEpoch = newHeader.nextEpoch(); + } + if (newHeader.nextProtocolVersion().isPresent()) { + final var nextProtocolVersion = newHeader.nextProtocolVersion().unwrap(); + latestProofWhichInitiatedAProtocolUpdate = Option.some(newLatestProof); + final var finalExecutionProof = + this.rustProtocolUpdate.applyProtocolUpdate(nextProtocolVersion).postUpdateProof(); + newLatestProof = finalExecutionProof; + latestProtocolUpdateExecutionProof = Option.some(finalExecutionProof); + } + } while (newLatestProof != lastHandledProof); // This presence of the protocol update in the proof is validated in rust - to ensure that if - // any protocol update - // is present, our node agrees it should be committed. + // any protocol update is present, our node agrees it should be committed. // We then can trust that we should trigger the application of the protocol update here. // NOTE: In the future, we may be able to move this down into Rust. this.latestProof = new LedgerProofBundle( newLatestProof, - maybeNextEpoch.isPresent() ? proof : this.latestProof.closestEpochProofOnOrBefore(), - maybeNextProtocolVersion.isPresent() - ? Option.some(proof) - : this.latestProof.closestProtocolUpdateInitProofOnOrBefore(), - maybePostProtocolUpdateProof.isPresent() - ? Option.some(maybePostProtocolUpdateProof.unwrap()) - : this.latestProof.closestProtocolUpdateExecutionProofOnOrBefore()); + latestProofWhichInitiatedAnEpochChange, + latestProofWhichInitiatedAProtocolUpdate, + latestProtocolUpdateExecutionProof); final var maybeEpochChange = maybeNextEpoch.map( nextEpoch -> { final var initialState = VertexStoreState.createNewForNextEpoch( - REv2ToConsensus.ledgerHeader(latestProof.epochInitialHeader()), + REv2ToConsensus.ledgerHeader(this.latestProof.epochInitialHeader()), nextEpoch.epoch().toLong(), hasher); final var validatorSet = REv2ToConsensus.validatorSet(nextEpoch.validators()); @@ -352,7 +367,7 @@ public LedgerProofBundle commit(LedgerExtension ledgerExtension, VertexStoreStat ProposerElections.defaultRotation(nextEpoch.epoch().toLong(), validatorSet); final var bftConfiguration = new BFTConfiguration(proposerElection, validatorSet, initialState); - return new EpochChange(latestProof, bftConfiguration); + return new EpochChange(this.latestProof, bftConfiguration); }); maybeEpochChange.ifPresent( @@ -364,12 +379,12 @@ public LedgerProofBundle commit(LedgerExtension ledgerExtension, VertexStoreStat final var ledgerUpdate = new LedgerUpdate( commitSummary, - latestProof, + this.latestProof, maybeEpochChange, protocolState, ledgerExtension.transactions()); ledgerUpdateEventDispatcher.dispatch(ledgerUpdate); - return latestProof; + return this.latestProof; } } diff --git a/core/src/main/java/com/radixdlt/rev2/modules/REv2ConsensusRecoveryModule.java b/core/src/main/java/com/radixdlt/rev2/modules/REv2ConsensusRecoveryModule.java index 49813e4a42..f4504b566f 100644 --- a/core/src/main/java/com/radixdlt/rev2/modules/REv2ConsensusRecoveryModule.java +++ b/core/src/main/java/com/radixdlt/rev2/modules/REv2ConsensusRecoveryModule.java @@ -102,7 +102,7 @@ private BFTConfiguration initialConfig( private BFTValidatorSet initialValidatorSet(LedgerProofBundle latestProof) { return REv2ToConsensus.validatorSet( latestProof - .closestEpochProofOnOrBefore() + .latestProofWhichInitiatedAnEpochChange() .ledgerHeader() .nextEpoch() .orElseThrow() diff --git a/core/src/test-core/java/com/radixdlt/statecomputer/MockedStateComputer.java b/core/src/test-core/java/com/radixdlt/statecomputer/MockedStateComputer.java index 027750c7ae..f62d3f5fcd 100644 --- a/core/src/test-core/java/com/radixdlt/statecomputer/MockedStateComputer.java +++ b/core/src/test-core/java/com/radixdlt/statecomputer/MockedStateComputer.java @@ -131,10 +131,10 @@ public LedgerProofBundle commit( ledgerExtension.proof(), ledgerExtension.proof().ledgerHeader().nextEpoch().isPresent() ? ledgerExtension.proof() - : latestProof.closestEpochProofOnOrBefore(), + : latestProof.latestProofWhichInitiatedAnEpochChange(), ledgerExtension.proof().ledgerHeader().nextProtocolVersion().isPresent() ? Option.some(ledgerExtension.proof()) - : latestProof.closestProtocolUpdateInitProofOnOrBefore(), + : latestProof.latestProofWhichInitiatedAProtocolUpdate(), Option.empty()); final var maybeEpochChange = diff --git a/core/src/test/java/com/radixdlt/api/core/TransactionStreamTest.java b/core/src/test/java/com/radixdlt/api/core/TransactionStreamTest.java index ac37265045..556c8ec8e8 100644 --- a/core/src/test/java/com/radixdlt/api/core/TransactionStreamTest.java +++ b/core/src/test/java/com/radixdlt/api/core/TransactionStreamTest.java @@ -440,7 +440,7 @@ public void test_core_api_can_return_vm_boot_substate_in_protocol_update_receipt test.getInstance(0, REv2TransactionsAndProofReader.class) .getLatestProofBundle() .orElseThrow() - .closestProtocolUpdateInitProofOnOrBefore() + .latestProofWhichInitiatedAProtocolUpdate() .unwrap() .stateVersion(); diff --git a/core/src/test/java/com/radixdlt/rev2/protocol/AnemoneProtocolUpdateTest.java b/core/src/test/java/com/radixdlt/rev2/protocol/AnemoneProtocolUpdateTest.java index 1afe71b023..6cd33821ba 100644 --- a/core/src/test/java/com/radixdlt/rev2/protocol/AnemoneProtocolUpdateTest.java +++ b/core/src/test/java/com/radixdlt/rev2/protocol/AnemoneProtocolUpdateTest.java @@ -176,7 +176,7 @@ public void test_get_current_time_second_precision() { assertEquals( PROTOCOL_VERSION_NAME, postProtocolUpdateProof - .closestProtocolUpdateInitProofOnOrBefore() + .latestProofWhichInitiatedAProtocolUpdate() .unwrap() .ledgerHeader() .nextProtocolVersion() diff --git a/docs/development/README.md b/docs/development/README.md index 527616cca7..f2d8313dfd 100644 --- a/docs/development/README.md +++ b/docs/development/README.md @@ -12,7 +12,7 @@ Otherwise, please set it up as [directed by GitHub docs](https://docs.github.com Main dependencies: - Java 17.0.4+ SDK installed and configured. It's very important to have at least 17.0.4, else you will hit Java Compiler bugs. -- Install the latest [rust toolchain](https://www.rust-lang.org/tools/install). If you hit any rust compilation issues, try `rustup update` and try again. +- Install the latest [rust toolchain](https://www.rust-lang.org/tools/install). If you hit any rust compilation issues, try `rustup update` and try again. If you still hit issues, ensure you're running with the Rust version corresponding to the version in the engine at the given protocol update you're working on. - Follow the set-up instructions for [radixdlt-scrypto](https://github.com/radixdlt/radixdlt-scrypto). If you wish to launch a local network through Docker: