diff --git a/.github/actions/librocksdb/action.yaml b/.github/actions/librocksdb/action.yaml index 5411bbc9859..8bb32f9fae1 100644 --- a/.github/actions/librocksdb/action.yaml +++ b/.github/actions/librocksdb/action.yaml @@ -6,9 +6,9 @@ name: "librocksdb" description: "Build and install librocksdb" inputs: version: - description: RocksDB version, eg. "9.9.3" + description: RocksDB version, eg. "11.8.1" required: false - default: "9.9.3" + default: "11.8.1" force: description: Force rebuild required: false diff --git a/Cargo.lock b/Cargo.lock index 61598d1da85..d9997eaa125 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -525,26 +525,6 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" -[[package]] -name = "bincode" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" -dependencies = [ - "bincode_derive", - "serde", - "unty", -] - -[[package]] -name = "bincode_derive" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" -dependencies = [ - "virtue 0.0.18", -] - [[package]] name = "bindgen" version = "0.65.1" @@ -577,7 +557,7 @@ dependencies = [ "bitflags 2.13.0", "cexpr", "clang-sys", - "itertools 0.10.5", + "itertools 0.13.0", "proc-macro2", "quote", "regex", @@ -1230,7 +1210,7 @@ version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1663,18 +1643,18 @@ dependencies = [ [[package]] name = "dash-network" version = "0.45.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=697bfb7251123e5ad12848631b819668119ef722#697bfb7251123e5ad12848631b819668119ef722" +source = "git+https://github.com/dashpay/rust-dashcore?rev=e4208c90786a6854bd498315bcb571ef24182c15#e4208c90786a6854bd498315bcb571ef24182c15" dependencies = [ - "bincode", - "bincode_derive", "cbindgen 0.29.4", + "grovedb-bincode", + "grovedb-bincode-derive", "serde", ] [[package]] name = "dash-network-seeds" version = "0.45.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=697bfb7251123e5ad12848631b819668119ef722#697bfb7251123e5ad12848631b819668119ef722" +source = "git+https://github.com/dashpay/rust-dashcore?rev=e4208c90786a6854bd498315bcb571ef24182c15#e4208c90786a6854bd498315bcb571ef24182c15" dependencies = [ "dash-network", ] @@ -1769,7 +1749,7 @@ dependencies = [ [[package]] name = "dash-spv" version = "0.45.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=697bfb7251123e5ad12848631b819668119ef722#697bfb7251123e5ad12848631b819668119ef722" +source = "git+https://github.com/dashpay/rust-dashcore?rev=e4208c90786a6854bd498315bcb571ef24182c15#e4208c90786a6854bd498315bcb571ef24182c15" dependencies = [ "async-trait", "chrono", @@ -1798,13 +1778,11 @@ dependencies = [ [[package]] name = "dashcore" version = "0.45.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=697bfb7251123e5ad12848631b819668119ef722#697bfb7251123e5ad12848631b819668119ef722" +source = "git+https://github.com/dashpay/rust-dashcore?rev=e4208c90786a6854bd498315bcb571ef24182c15#e4208c90786a6854bd498315bcb571ef24182c15" dependencies = [ "anyhow", "base64-compat", "bech32 0.9.1", - "bincode", - "bincode_derive", "bitvec", "blake3", "blsful", @@ -1812,6 +1790,8 @@ dependencies = [ "dashcore-private", "dashcore_hashes", "ed25519-dalek", + "grovedb-bincode", + "grovedb-bincode-derive", "hex", "hex_lit", "rustversion", @@ -1824,12 +1804,12 @@ dependencies = [ [[package]] name = "dashcore-private" version = "0.45.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=697bfb7251123e5ad12848631b819668119ef722#697bfb7251123e5ad12848631b819668119ef722" +source = "git+https://github.com/dashpay/rust-dashcore?rev=e4208c90786a6854bd498315bcb571ef24182c15#e4208c90786a6854bd498315bcb571ef24182c15" [[package]] name = "dashcore-rpc" version = "0.45.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=697bfb7251123e5ad12848631b819668119ef722#697bfb7251123e5ad12848631b819668119ef722" +source = "git+https://github.com/dashpay/rust-dashcore?rev=e4208c90786a6854bd498315bcb571ef24182c15#e4208c90786a6854bd498315bcb571ef24182c15" dependencies = [ "dashcore-rpc-json", "hex", @@ -1842,10 +1822,10 @@ dependencies = [ [[package]] name = "dashcore-rpc-json" version = "0.45.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=697bfb7251123e5ad12848631b819668119ef722#697bfb7251123e5ad12848631b819668119ef722" +source = "git+https://github.com/dashpay/rust-dashcore?rev=e4208c90786a6854bd498315bcb571ef24182c15#e4208c90786a6854bd498315bcb571ef24182c15" dependencies = [ - "bincode", "dashcore", + "grovedb-bincode", "hex", "key-wallet", "serde", @@ -1857,10 +1837,10 @@ dependencies = [ [[package]] name = "dashcore_hashes" version = "0.45.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=697bfb7251123e5ad12848631b819668119ef722#697bfb7251123e5ad12848631b819668119ef722" +source = "git+https://github.com/dashpay/rust-dashcore?rev=e4208c90786a6854bd498315bcb571ef24182c15#e4208c90786a6854bd498315bcb571ef24182c15" dependencies = [ - "bincode", "dashcore-private", + "grovedb-bincode", "rs-x11-hash", "serde", ] @@ -2118,7 +2098,6 @@ dependencies = [ "async-trait", "base64 0.22.1", "bech32 0.11.1", - "bincode", "bs58", "byteorder", "chrono", @@ -2133,6 +2112,7 @@ dependencies = [ "dpp-json-convertible-derive", "env_logger", "getrandom 0.2.17", + "grovedb-bincode", "grovedb-commitment-tree", "hex", "indexmap 2.14.0", @@ -2184,7 +2164,6 @@ dependencies = [ "arc-swap", "assert_matches", "base64 0.22.1", - "bincode", "bs58", "byteorder", "chrono", @@ -2194,6 +2173,7 @@ dependencies = [ "dpp", "enum-map", "grovedb", + "grovedb-bincode", "grovedb-costs", "grovedb-epoch-based-storage-flags", "grovedb-path", @@ -2226,7 +2206,6 @@ dependencies = [ "arc-swap", "assert_matches", "async-trait", - "bincode", "blake3", "bls-signatures", "chrono", @@ -2245,6 +2224,7 @@ dependencies = [ "drive-proof-verifier", "envy", "file-rotate", + "grovedb-bincode", "grovedb-commitment-tree", "grovedb-path", "grovedb-storage", @@ -2285,12 +2265,12 @@ dependencies = [ name = "drive-proof-verifier" version = "4.2.0-dev.8" dependencies = [ - "bincode", "dapi-grpc", "dash-context-provider", "derive_more 1.0.0", "dpp", "drive", + "grovedb-bincode", "hex", "indexmap 2.14.0", "platform-serialization", @@ -2497,7 +2477,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2927,7 +2907,7 @@ dependencies = [ [[package]] name = "git-state" version = "0.45.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=697bfb7251123e5ad12848631b819668119ef722#697bfb7251123e5ad12848631b819668119ef722" +source = "git+https://github.com/dashpay/rust-dashcore?rev=e4208c90786a6854bd498315bcb571ef24182c15#e4208c90786a6854bd498315bcb571ef24182c15" [[package]] name = "glob" @@ -2976,13 +2956,13 @@ dependencies = [ [[package]] name = "grovedb" -version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e#6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" +version = "6.0.0" +source = "git+https://github.com/dashpay/grovedb?rev=6816457d2b2df98653f286bf9a374f236a17748f#6816457d2b2df98653f286bf9a374f236a17748f" dependencies = [ "axum 0.8.9", - "bincode", - "bincode_derive", "blake3", + "grovedb-bincode", + "grovedb-bincode-derive", "grovedb-bulk-append-tree", "grovedb-commitment-tree", "grovedb-costs", @@ -3013,13 +2993,33 @@ dependencies = [ "zip-extensions", ] +[[package]] +name = "grovedb-bincode" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce912028682ecc5870a5ad609ea456b76b0bf4ec1ba1eb649400b64ff73a7782" +dependencies = [ + "grovedb-bincode-derive", + "serde", + "unty", +] + +[[package]] +name = "grovedb-bincode-derive" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eaff4e961dcb3e7e55c34c8c6982249036e5aaa19e55f6dab94ebcd4896b03a" +dependencies = [ + "virtue 0.0.18", +] + [[package]] name = "grovedb-bulk-append-tree" -version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e#6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" +version = "6.0.0" +source = "git+https://github.com/dashpay/grovedb?rev=6816457d2b2df98653f286bf9a374f236a17748f#6816457d2b2df98653f286bf9a374f236a17748f" dependencies = [ - "bincode", "blake3", + "grovedb-bincode", "grovedb-costs", "grovedb-dense-fixed-sized-merkle-tree", "grovedb-merkle-mountain-range", @@ -3033,8 +3033,8 @@ dependencies = [ [[package]] name = "grovedb-commitment-tree" -version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e#6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" +version = "6.0.0" +source = "git+https://github.com/dashpay/grovedb?rev=6816457d2b2df98653f286bf9a374f236a17748f#6816457d2b2df98653f286bf9a374f236a17748f" dependencies = [ "blake3", "grovedb-bulk-append-tree", @@ -3050,8 +3050,8 @@ dependencies = [ [[package]] name = "grovedb-costs" -version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e#6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" +version = "6.0.0" +source = "git+https://github.com/dashpay/grovedb?rev=6816457d2b2df98653f286bf9a374f236a17748f#6816457d2b2df98653f286bf9a374f236a17748f" dependencies = [ "integer-encoding", "intmap", @@ -3060,11 +3060,11 @@ dependencies = [ [[package]] name = "grovedb-dense-fixed-sized-merkle-tree" -version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e#6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" +version = "6.0.0" +source = "git+https://github.com/dashpay/grovedb?rev=6816457d2b2df98653f286bf9a374f236a17748f#6816457d2b2df98653f286bf9a374f236a17748f" dependencies = [ - "bincode", "blake3", + "grovedb-bincode", "grovedb-costs", "grovedb-query", "grovedb-storage", @@ -3074,11 +3074,11 @@ dependencies = [ [[package]] name = "grovedb-element" -version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e#6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" +version = "6.0.0" +source = "git+https://github.com/dashpay/grovedb?rev=6816457d2b2df98653f286bf9a374f236a17748f#6816457d2b2df98653f286bf9a374f236a17748f" dependencies = [ - "bincode", - "bincode_derive", + "grovedb-bincode", + "grovedb-bincode-derive", "grovedb-path", "grovedb-query", "grovedb-version", @@ -3090,8 +3090,8 @@ dependencies = [ [[package]] name = "grovedb-epoch-based-storage-flags" -version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e#6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" +version = "6.0.0" +source = "git+https://github.com/dashpay/grovedb?rev=6816457d2b2df98653f286bf9a374f236a17748f#6816457d2b2df98653f286bf9a374f236a17748f" dependencies = [ "grovedb-costs", "hex", @@ -3102,15 +3102,15 @@ dependencies = [ [[package]] name = "grovedb-merk" -version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e#6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" +version = "6.0.0" +source = "git+https://github.com/dashpay/grovedb?rev=6816457d2b2df98653f286bf9a374f236a17748f#6816457d2b2df98653f286bf9a374f236a17748f" dependencies = [ - "bincode", - "bincode_derive", "blake3", "byteorder", "colored", "ed", + "grovedb-bincode", + "grovedb-bincode-derive", "grovedb-costs", "grovedb-element", "grovedb-path", @@ -3128,11 +3128,11 @@ dependencies = [ [[package]] name = "grovedb-merkle-mountain-range" -version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e#6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" +version = "6.0.0" +source = "git+https://github.com/dashpay/grovedb?rev=6816457d2b2df98653f286bf9a374f236a17748f#6816457d2b2df98653f286bf9a374f236a17748f" dependencies = [ - "bincode", "blake3", + "grovedb-bincode", "grovedb-costs", "grovedb-storage", "grovedb-version", @@ -3141,16 +3141,16 @@ dependencies = [ [[package]] name = "grovedb-path" -version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e#6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" +version = "6.0.0" +source = "git+https://github.com/dashpay/grovedb?rev=6816457d2b2df98653f286bf9a374f236a17748f#6816457d2b2df98653f286bf9a374f236a17748f" dependencies = [ "hex", ] [[package]] name = "grovedb-private-document-store" -version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e#6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" +version = "6.0.0" +source = "git+https://github.com/dashpay/grovedb?rev=6816457d2b2df98653f286bf9a374f236a17748f#6816457d2b2df98653f286bf9a374f236a17748f" dependencies = [ "blake3", "grovedb-bulk-append-tree", @@ -3162,12 +3162,12 @@ dependencies = [ [[package]] name = "grovedb-query" -version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e#6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" +version = "6.0.0" +source = "git+https://github.com/dashpay/grovedb?rev=6816457d2b2df98653f286bf9a374f236a17748f#6816457d2b2df98653f286bf9a374f236a17748f" dependencies = [ - "bincode", "byteorder", "ed", + "grovedb-bincode", "grovedb-costs", "grovedb-storage", "hex", @@ -3178,8 +3178,8 @@ dependencies = [ [[package]] name = "grovedb-storage" -version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e#6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" +version = "6.0.0" +source = "git+https://github.com/dashpay/grovedb?rev=6816457d2b2df98653f286bf9a374f236a17748f#6816457d2b2df98653f286bf9a374f236a17748f" dependencies = [ "blake3", "grovedb-costs", @@ -3197,8 +3197,8 @@ dependencies = [ [[package]] name = "grovedb-version" -version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e#6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" +version = "6.0.0" +source = "git+https://github.com/dashpay/grovedb?rev=6816457d2b2df98653f286bf9a374f236a17748f#6816457d2b2df98653f286bf9a374f236a17748f" dependencies = [ "thiserror 2.0.18", "versioned-feature-core", @@ -3206,8 +3206,8 @@ dependencies = [ [[package]] name = "grovedb-visualize" -version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e#6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" +version = "6.0.0" +source = "git+https://github.com/dashpay/grovedb?rev=6816457d2b2df98653f286bf9a374f236a17748f#6816457d2b2df98653f286bf9a374f236a17748f" dependencies = [ "hex", "itertools 0.14.0", @@ -3215,8 +3215,8 @@ dependencies = [ [[package]] name = "grovedbg-types" -version = "5.0.1" -source = "git+https://github.com/dashpay/grovedb?rev=6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e#6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" +version = "6.0.0" +source = "git+https://github.com/dashpay/grovedb?rev=6816457d2b2df98653f286bf9a374f236a17748f#6816457d2b2df98653f286bf9a374f236a17748f" dependencies = [ "serde", "serde_with 3.21.0", @@ -3632,7 +3632,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.4", "system-configuration", "tokio", "tower-service", @@ -3883,7 +3883,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4139,13 +4139,11 @@ dependencies = [ [[package]] name = "key-wallet" version = "0.45.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=697bfb7251123e5ad12848631b819668119ef722#697bfb7251123e5ad12848631b819668119ef722" +source = "git+https://github.com/dashpay/rust-dashcore?rev=e4208c90786a6854bd498315bcb571ef24182c15#e4208c90786a6854bd498315bcb571ef24182c15" dependencies = [ "aes", "async-trait", "base58ck", - "bincode", - "bincode_derive", "bip39", "bitflags 2.13.0", "bs58", @@ -4153,6 +4151,8 @@ dependencies = [ "dashcore-private", "dashcore_hashes", "getrandom 0.2.17", + "grovedb-bincode", + "grovedb-bincode-derive", "hex", "rand 0.8.6", "scrypt", @@ -4168,7 +4168,7 @@ dependencies = [ [[package]] name = "key-wallet-ffi" version = "0.45.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=697bfb7251123e5ad12848631b819668119ef722#697bfb7251123e5ad12848631b819668119ef722" +source = "git+https://github.com/dashpay/rust-dashcore?rev=e4208c90786a6854bd498315bcb571ef24182c15#e4208c90786a6854bd498315bcb571ef24182c15" dependencies = [ "cbindgen 0.29.4", "dash-network", @@ -4184,11 +4184,11 @@ dependencies = [ [[package]] name = "key-wallet-manager" version = "0.45.0" -source = "git+https://github.com/dashpay/rust-dashcore?rev=697bfb7251123e5ad12848631b819668119ef722#697bfb7251123e5ad12848631b819668119ef722" +source = "git+https://github.com/dashpay/rust-dashcore?rev=e4208c90786a6854bd498315bcb571ef24182c15#e4208c90786a6854bd498315bcb571ef24182c15" dependencies = [ "async-trait", - "bincode", "dashcore", + "grovedb-bincode", "key-wallet", "rayon", "serde", @@ -4278,8 +4278,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "librocksdb-sys" -version = "0.18.0+10.7.5" -source = "git+https://github.com/QuantumExplorer/rust-rocksdb.git?rev=52772eea7bcd214d1d07d80aa538b1d24e5015b7#52772eea7bcd214d1d07d80aa538b1d24e5015b7" +version = "0.19.0+11.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f45e86edad8e88efe97dbf384b4e48e1ff0f111eabf154c7b09d7a1e5fb573c" dependencies = [ "bindgen 0.72.1", "bzip2-sys", @@ -4287,6 +4288,7 @@ dependencies = [ "libc", "libz-sys", "lz4-sys", + "rustflags", "zstd-sys", ] @@ -4706,7 +4708,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5184,7 +5186,7 @@ dependencies = [ name = "platform-serialization" version = "4.2.0-dev.8" dependencies = [ - "bincode", + "grovedb-bincode", "platform-version", ] @@ -5203,9 +5205,9 @@ name = "platform-value" version = "4.2.0-dev.8" dependencies = [ "base64 0.22.1", - "bincode", "bs58", "ciborium", + "grovedb-bincode", "hex", "indexmap 2.14.0", "platform-serialization", @@ -5229,7 +5231,7 @@ dependencies = [ name = "platform-version" version = "4.2.0-dev.8" dependencies = [ - "bincode", + "grovedb-bincode", "grovedb-version", "thiserror 2.0.18", "versioned-feature-core", @@ -5290,13 +5292,13 @@ version = "4.2.0-dev.8" dependencies = [ "anyhow", "async-trait", - "bincode", "bs58", "cbindgen 0.27.0", "dash-network", "dash-sdk", "dashcore", "dpp", + "grovedb-bincode", "hex", "key-wallet", "lazy_static", @@ -5319,7 +5321,6 @@ dependencies = [ "apple-native-keyring-store", "argon2", "assert_cmd", - "bincode", "chacha20poly1305", "chrono", "clap", @@ -5330,6 +5331,7 @@ dependencies = [ "fd-lock", "filetime", "getrandom 0.2.17", + "grovedb-bincode", "hex", "humantime", "key-wallet", @@ -5599,8 +5601,8 @@ version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042" dependencies = [ - "heck 0.4.1", - "itertools 0.10.5", + "heck 0.5.0", + "itertools 0.14.0", "log", "multimap", "petgraph", @@ -5621,7 +5623,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.14.0", "proc-macro2", "quote", "syn 2.0.117", @@ -5634,7 +5636,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.14.0", "proc-macro2", "quote", "syn 2.0.117", @@ -5770,7 +5772,7 @@ dependencies = [ "quinn-udp", "rustc-hash 2.1.2", "rustls", - "socket2 0.5.10", + "socket2 0.6.4", "thiserror 2.0.18", "tokio", "tracing", @@ -5808,7 +5810,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.4", "tracing", "windows-sys 0.59.0", ] @@ -6308,8 +6310,9 @@ dependencies = [ [[package]] name = "rocksdb" -version = "0.24.0" -source = "git+https://github.com/QuantumExplorer/rust-rocksdb.git?rev=52772eea7bcd214d1d07d80aa538b1d24e5015b7#52772eea7bcd214d1d07d80aa538b1d24e5015b7" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8d90add70d1d420ee487bce4a1449880a8d147451c6051b2ee5f8354553dcbf" dependencies = [ "libc", "librocksdb-sys", @@ -6439,7 +6442,6 @@ name = "rs-sdk-ffi" version = "4.2.0-dev.8" dependencies = [ "async-trait", - "bincode", "bs58", "cbindgen 0.27.0", "dash-async", @@ -6450,6 +6452,7 @@ dependencies = [ "env_logger", "envy", "getrandom 0.2.17", + "grovedb-bincode", "hex", "key-wallet", "libc", @@ -6608,6 +6611,12 @@ dependencies = [ "semver", ] +[[package]] +name = "rustflags" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a39e0e9135d7a7208ee80aa4e3e4b88f0f5ad7be92153ed70686c38a03db2e63" + [[package]] name = "rustix" version = "0.38.44" @@ -6631,7 +6640,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -6690,7 +6699,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -7240,8 +7249,8 @@ version = "4.2.0-dev.8" dependencies = [ "async-trait", "base64 0.22.1", - "bincode", "dpp", + "grovedb-bincode", "hex", "tracing", "zeroize", @@ -7375,9 +7384,9 @@ dependencies = [ name = "strategy-tests" version = "4.2.0-dev.8" dependencies = [ - "bincode", "dpp", "drive", + "grovedb-bincode", "hex", "platform-version", "rand 0.8.6", @@ -7541,7 +7550,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix 1.1.4", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -8754,8 +8763,8 @@ version = "4.2.0-dev.8" dependencies = [ "anyhow", "async-trait", - "bincode", "dpp", + "grovedb-bincode", "hex", "itertools 0.13.0", "js-sys", @@ -8778,9 +8787,9 @@ version = "4.2.0-dev.8" dependencies = [ "anyhow", "async-trait", - "bincode", "dpp", "dpp-json-convertible-derive", + "grovedb-bincode", "hex", "js-sys", "serde", @@ -8796,12 +8805,12 @@ name = "wasm-drive-verify" version = "4.2.0-dev.8" dependencies = [ "base64 0.22.1", - "bincode", "bs58", "ciborium", "console_error_panic_hook", "dpp", "drive", + "grovedb-bincode", "hex", "indexmap 2.14.0", "js-sys", @@ -8987,7 +8996,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 16cb05e44aa..8fb367a6361 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,14 +53,15 @@ members = [ ] [workspace.dependencies] -dashcore = { git = "https://github.com/dashpay/rust-dashcore", rev = "697bfb7251123e5ad12848631b819668119ef722" } -dash-network-seeds = { git = "https://github.com/dashpay/rust-dashcore", rev = "697bfb7251123e5ad12848631b819668119ef722" } -dash-spv = { git = "https://github.com/dashpay/rust-dashcore", rev = "697bfb7251123e5ad12848631b819668119ef722" } -key-wallet = { git = "https://github.com/dashpay/rust-dashcore", rev = "697bfb7251123e5ad12848631b819668119ef722" } -key-wallet-ffi = { git = "https://github.com/dashpay/rust-dashcore", rev = "697bfb7251123e5ad12848631b819668119ef722" } -key-wallet-manager = { git = "https://github.com/dashpay/rust-dashcore", rev = "697bfb7251123e5ad12848631b819668119ef722" } -dash-network = { git = "https://github.com/dashpay/rust-dashcore", rev = "697bfb7251123e5ad12848631b819668119ef722" } -dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore", rev = "697bfb7251123e5ad12848631b819668119ef722" } +bincode = { package = "grovedb-bincode", version = "=2.1.0" } +dashcore = { git = "https://github.com/dashpay/rust-dashcore", rev = "e4208c90786a6854bd498315bcb571ef24182c15" } +dash-network-seeds = { git = "https://github.com/dashpay/rust-dashcore", rev = "e4208c90786a6854bd498315bcb571ef24182c15" } +dash-spv = { git = "https://github.com/dashpay/rust-dashcore", rev = "e4208c90786a6854bd498315bcb571ef24182c15" } +key-wallet = { git = "https://github.com/dashpay/rust-dashcore", rev = "e4208c90786a6854bd498315bcb571ef24182c15" } +key-wallet-ffi = { git = "https://github.com/dashpay/rust-dashcore", rev = "e4208c90786a6854bd498315bcb571ef24182c15" } +key-wallet-manager = { git = "https://github.com/dashpay/rust-dashcore", rev = "e4208c90786a6854bd498315bcb571ef24182c15" } +dash-network = { git = "https://github.com/dashpay/rust-dashcore", rev = "e4208c90786a6854bd498315bcb571ef24182c15" } +dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore", rev = "e4208c90786a6854bd498315bcb571ef24182c15" } tokio-metrics = "0.5" # Size-tuned profile for the iOS `rs-unified-sdk-ffi` staticlib, which diff --git a/Dockerfile b/Dockerfile index 846150203f7..13a762334ce 100644 --- a/Dockerfile +++ b/Dockerfile @@ -306,7 +306,7 @@ ONBUILD ARG CARGO_BUILD_PROFILE=dev RUN --mount=type=secret,id=AWS < = + voters_1[31..=40].iter().rev().copied().collect(); + assert_eq!( + page(10, false, cursor(40, true)), + descending_from_40_inclusive + ); + let descending_from_40_exclusive: Vec = + voters_1[30..=39].iter().rev().copied().collect(); + assert_eq!( + page(10, false, cursor(40, false)), + descending_from_40_exclusive + ); + + // A short final page: the limit exceeds what remains. + assert_eq!(page(10, true, cursor(45, false)), voters_1[46..50].to_vec()); } } diff --git a/packages/rs-drive-proof-verifier/Cargo.toml b/packages/rs-drive-proof-verifier/Cargo.toml index d0246c9a8eb..fe5705e4b1f 100644 --- a/packages/rs-drive-proof-verifier/Cargo.toml +++ b/packages/rs-drive-proof-verifier/Cargo.toml @@ -31,7 +31,7 @@ dpp = { path = "../rs-dpp", features = [ dash-context-provider = { path = "../rs-context-provider", features = [ "mocks", ] } -bincode = { version = "=2.0.1", features = ["serde"] } +bincode = { workspace = true, features = ["serde"] } platform-serialization-derive = { path = "../rs-platform-serialization-derive", optional = true } platform-serialization = { path = "../rs-platform-serialization" } tenderdash-abci = { git = "https://github.com/dashpay/rs-tenderdash-abci", tag = "v1.5.1", features = [ diff --git a/packages/rs-drive/Cargo.toml b/packages/rs-drive/Cargo.toml index fcbb004cc3d..b73a0ebaec5 100644 --- a/packages/rs-drive/Cargo.toml +++ b/packages/rs-drive/Cargo.toml @@ -14,7 +14,7 @@ license = "MIT" resolver = "2" [dependencies] -bincode = { version = "=2.0.1", features = ["serde"] } +bincode = { workspace = true, features = ["serde"] } platform-version = { path = "../rs-platform-version" } # used to convert integers to bytes, needed in verifier integer-encoding = { version = "4.0.0" } @@ -52,13 +52,13 @@ enum-map = { version = "2.0.3", optional = true } intmap = { version = "3.0.1", features = ["serde"], optional = true } chrono = { version = "0.4.35", optional = true } itertools = { version = "0.13", optional = true } -grovedb = { git = "https://github.com/dashpay/grovedb", rev = "6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e", optional = true, default-features = false } -grovedb-costs = { git = "https://github.com/dashpay/grovedb", rev = "6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e", optional = true } -grovedb-path = { git = "https://github.com/dashpay/grovedb", rev = "6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" } -grovedb-query = { git = "https://github.com/dashpay/grovedb", rev = "6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" } -grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev = "6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e", optional = true } -grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" } -grovedb-epoch-based-storage-flags = { git = "https://github.com/dashpay/grovedb", rev = "6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" } +grovedb = { git = "https://github.com/dashpay/grovedb", rev = "6816457d2b2df98653f286bf9a374f236a17748f", optional = true, default-features = false } +grovedb-costs = { git = "https://github.com/dashpay/grovedb", rev = "6816457d2b2df98653f286bf9a374f236a17748f", optional = true } +grovedb-path = { git = "https://github.com/dashpay/grovedb", rev = "6816457d2b2df98653f286bf9a374f236a17748f" } +grovedb-query = { git = "https://github.com/dashpay/grovedb", rev = "6816457d2b2df98653f286bf9a374f236a17748f" } +grovedb-storage = { git = "https://github.com/dashpay/grovedb", rev = "6816457d2b2df98653f286bf9a374f236a17748f", optional = true } +grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "6816457d2b2df98653f286bf9a374f236a17748f" } +grovedb-epoch-based-storage-flags = { git = "https://github.com/dashpay/grovedb", rev = "6816457d2b2df98653f286bf9a374f236a17748f" } [dev-dependencies] criterion = "0.5" diff --git a/packages/rs-drive/src/drive/balances/add_to_system_credits_operations/v0/mod.rs b/packages/rs-drive/src/drive/balances/add_to_system_credits_operations/v0/mod.rs index 33b1740e104..16096317bc7 100644 --- a/packages/rs-drive/src/drive/balances/add_to_system_credits_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/balances/add_to_system_credits_operations/v0/mod.rs @@ -56,7 +56,8 @@ impl Drive { path_holding_total_credits_vec, TOTAL_SYSTEM_CREDITS_STORAGE_KEY.to_vec(), Item(new_total.encode_var_vec(), None), - ); + ) + .dont_check_for_backwards_references(); drive_operations.push(GroveOperation(replace_op)); Ok(drive_operations) } diff --git a/packages/rs-drive/src/drive/balances/remove_from_system_credits_operations/v0/mod.rs b/packages/rs-drive/src/drive/balances/remove_from_system_credits_operations/v0/mod.rs index 8bdb989d21f..d6cc791db2f 100644 --- a/packages/rs-drive/src/drive/balances/remove_from_system_credits_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/balances/remove_from_system_credits_operations/v0/mod.rs @@ -57,7 +57,8 @@ impl Drive { path_holding_total_credits_vec, TOTAL_SYSTEM_CREDITS_STORAGE_KEY.to_vec(), Item(new_total.encode_var_vec(), None), - ); + ) + .dont_check_for_backwards_references(); drive_operations.push(GroveOperation(replace_op)); Ok(drive_operations) } diff --git a/packages/rs-drive/src/drive/contract/update/update_keywords/v0/mod.rs b/packages/rs-drive/src/drive/contract/update/update_keywords/v0/mod.rs index 15a847c7e8a..0f93b9d4381 100644 --- a/packages/rs-drive/src/drive/contract/update/update_keywords/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/update/update_keywords/v0/mod.rs @@ -596,7 +596,10 @@ mod tests { .fold((0, 0), |(deletes, inserts), operation| match operation { LowLevelDriveOperation::GroveOperation(op) if op.path.to_path() == group_path => { match op.op { - GroveOp::Delete | GroveOp::DeleteTree(..) => (deletes + 1, inserts), + GroveOp::DeleteDontCheckForBackwardsReferences + | GroveOp::DeleteTreeDontCheckForBackwardsReferences(..) => { + (deletes + 1, inserts) + } _ => (deletes, inserts + 1), } } diff --git a/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/add_epoch_final_info_operation/v0/mod.rs b/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/add_epoch_final_info_operation/v0/mod.rs index 212ca01d11e..a2128f3f8ca 100644 --- a/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/add_epoch_final_info_operation/v0/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/epochs/credit_distribution_pools/add_epoch_final_info_operation/v0/mod.rs @@ -25,6 +25,7 @@ impl Drive { epoch_tree_path, epoch_key_constants::KEY_FINISHED_EPOCH_INFO.to_vec(), Element::new_item(serialized), - )) + ) + .dont_check_for_backwards_references()) } } diff --git a/packages/rs-drive/src/drive/credit_pools/epochs/operations_factory.rs b/packages/rs-drive/src/drive/credit_pools/epochs/operations_factory.rs index a3396005212..c030fb1ff43 100644 --- a/packages/rs-drive/src/drive/credit_pools/epochs/operations_factory.rs +++ b/packages/rs-drive/src/drive/credit_pools/epochs/operations_factory.rs @@ -194,6 +194,7 @@ impl EpochOperations for Epoch { KEY_PROTOCOL_VERSION.to_vec(), Element::Item(protocol_version.to_be_bytes().to_vec(), None), ) + .dont_check_for_backwards_references() } /// Returns a groveDB op which updates the epoch start time. @@ -203,6 +204,7 @@ impl EpochOperations for Epoch { KEY_START_TIME.to_vec(), Element::Item(time_ms.to_be_bytes().to_vec(), None), ) + .dont_check_for_backwards_references() } /// Returns a groveDB op which updates the epoch start block height. @@ -212,6 +214,7 @@ impl EpochOperations for Epoch { KEY_START_BLOCK_HEIGHT.to_vec(), Element::Item(start_block_height.to_be_bytes().to_vec(), None), ) + .dont_check_for_backwards_references() } /// Returns a groveDB op which updates the epoch start block core height. @@ -224,6 +227,7 @@ impl EpochOperations for Epoch { KEY_START_BLOCK_CORE_HEIGHT.to_vec(), Element::Item(start_block_core_height.to_be_bytes().to_vec(), None), ) + .dont_check_for_backwards_references() } /// Returns a groveDB op which updates the epoch fee multiplier. @@ -233,6 +237,7 @@ impl EpochOperations for Epoch { KEY_FEE_MULTIPLIER.to_vec(), Element::Item(multiplier_permille.to_be_bytes().to_vec(), None), ) + .dont_check_for_backwards_references() } /// Returns a groveDB op which updates the epoch processing credits for distribution. @@ -244,12 +249,14 @@ impl EpochOperations for Epoch { self.get_path_vec(), KEY_POOL_PROCESSING_FEES.to_vec(), Element::new_sum_item(processing_fee.to_signed()?), - )) + ) + .dont_check_for_backwards_references()) } /// Returns a groveDB op which deletes the epoch processing credits for distribution tree. fn delete_processing_credits_for_distribution_operation(&self) -> QualifiedGroveDbOp { QualifiedGroveDbOp::delete_op(self.get_path_vec(), KEY_POOL_PROCESSING_FEES.to_vec()) + .dont_check_for_backwards_references() } /// Returns a groveDB op which updates the epoch storage credits for distribution. @@ -261,12 +268,14 @@ impl EpochOperations for Epoch { self.get_path_vec(), KEY_POOL_STORAGE_FEES.to_vec(), Element::new_sum_item(storage_fee.to_signed()?), - )) + ) + .dont_check_for_backwards_references()) } /// Returns a groveDB op which deletes the epoch storage credits for distribution tree. fn delete_storage_credits_for_distribution_operation(&self) -> QualifiedGroveDbOp { QualifiedGroveDbOp::delete_op(self.get_path_vec(), KEY_POOL_STORAGE_FEES.to_vec()) + .dont_check_for_backwards_references() } /// Returns a groveDB op which updates the given epoch proposer's block count. @@ -280,6 +289,7 @@ impl EpochOperations for Epoch { proposer_pro_tx_hash.to_vec(), Element::Item(block_count.to_be_bytes().to_vec(), None), ) + .dont_check_for_backwards_references() } /// Returns a groveDB op which inserts an empty tree into the epoch proposers path. @@ -289,6 +299,7 @@ impl EpochOperations for Epoch { KEY_PROPOSERS.to_vec(), Element::empty_tree(), ) + .dont_check_for_backwards_references() } /// Returns a groveDB op which deletes the epoch proposers tree. @@ -299,6 +310,7 @@ impl EpochOperations for Epoch { TreeType::NormalTree, SubelementsDeletionBehavior::DeleteChildren, ) + .dont_check_for_backwards_references() } /// Adds a groveDB op to the batch which deletes the given epoch proposers from the proposers tree. diff --git a/packages/rs-drive/src/drive/credit_pools/mod.rs b/packages/rs-drive/src/drive/credit_pools/mod.rs index 0d8e3f29726..7af05d8b402 100644 --- a/packages/rs-drive/src/drive/credit_pools/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/mod.rs @@ -270,7 +270,7 @@ mod tests { Epoch::new(i as EpochIndex).unwrap().get_path_vec() ); - let GroveOp::InsertOrReplace { + let GroveOp::InsertOrReplaceDontCheckForBackwardsReferences { element: Element::SumItem(credits, _), } = operation.op else { @@ -334,7 +334,7 @@ mod tests { let updated_credits: Vec<_> = batch .into_iter() .map(|operation| { - let GroveOp::InsertOrReplace { + let GroveOp::InsertOrReplaceDontCheckForBackwardsReferences { element: Element::SumItem(credits, _), } = operation.op else { diff --git a/packages/rs-drive/src/drive/credit_pools/operations.rs b/packages/rs-drive/src/drive/credit_pools/operations.rs index 9aad69bf5b4..62e42a99d2d 100644 --- a/packages/rs-drive/src/drive/credit_pools/operations.rs +++ b/packages/rs-drive/src/drive/credit_pools/operations.rs @@ -26,7 +26,8 @@ pub fn update_storage_fee_distribution_pool_operation( pools_vec_path(), KEY_STORAGE_FEE_POOL.to_vec(), Element::new_sum_item(storage_fee.to_signed()?), - )) + ) + .dont_check_for_backwards_references()) } #[cfg(feature = "server")] @@ -37,6 +38,7 @@ pub fn update_unpaid_epoch_index_operation(epoch_index: EpochIndex) -> Qualified KEY_UNPAID_EPOCH_INDEX.to_vec(), Element::new_item(epoch_index.to_be_bytes().to_vec()), ) + .dont_check_for_backwards_references() } #[cfg(test)] diff --git a/packages/rs-drive/src/drive/credit_pools/pending_epoch_refunds/methods/add_delete_pending_epoch_refunds_except_specified/v0/mod.rs b/packages/rs-drive/src/drive/credit_pools/pending_epoch_refunds/methods/add_delete_pending_epoch_refunds_except_specified/v0/mod.rs index ed2b1a5d8e3..fcb4223f946 100644 --- a/packages/rs-drive/src/drive/credit_pools/pending_epoch_refunds/methods/add_delete_pending_epoch_refunds_except_specified/v0/mod.rs +++ b/packages/rs-drive/src/drive/credit_pools/pending_epoch_refunds/methods/add_delete_pending_epoch_refunds_except_specified/v0/mod.rs @@ -124,7 +124,10 @@ mod tests { assert_eq!(batch.len(), expected_pending_refunds.len()); for operation in batch.into_iter() { - assert!(matches!(operation.op, GroveOp::Delete)); + assert!(matches!( + operation.op, + GroveOp::DeleteDontCheckForBackwardsReferences + )); assert_eq!(operation.path.to_path(), pending_epoch_refunds_path_vec()); diff --git a/packages/rs-drive/src/drive/identity/balance/update.rs b/packages/rs-drive/src/drive/identity/balance/update.rs index 83d8278467b..d2dca9e0f2a 100644 --- a/packages/rs-drive/src/drive/identity/balance/update.rs +++ b/packages/rs-drive/src/drive/identity/balance/update.rs @@ -600,14 +600,14 @@ mod tests { _, _, LowLevelDriveOperation::GroveOperation(grovedb::batch::QualifiedGroveDbOp { - op: GroveOp::Replace { + op: GroveOp::ReplaceDontCheckForBackwardsReferences { element: Element::SumItem(refund_amount, None), }, .. }), .., LowLevelDriveOperation::GroveOperation(grovedb::batch::QualifiedGroveDbOp { - op: GroveOp::Replace { + op: GroveOp::ReplaceDontCheckForBackwardsReferences { element: Element::SumItem(other_refund_amount, None), }, .. @@ -696,13 +696,13 @@ mod tests { _, _, LowLevelDriveOperation::GroveOperation(grovedb::batch::QualifiedGroveDbOp { - op: GroveOp::Replace { + op: GroveOp::ReplaceDontCheckForBackwardsReferences { element: Element::SumItem(refund_amount, None), }, .. }), LowLevelDriveOperation::GroveOperation(grovedb::batch::QualifiedGroveDbOp { - op: GroveOp::Replace { + op: GroveOp::ReplaceDontCheckForBackwardsReferences { element: Element::Item(debt_bytes, None), }, .. @@ -771,7 +771,7 @@ mod tests { _, _, LowLevelDriveOperation::GroveOperation(grovedb::batch::QualifiedGroveDbOp { - op: GroveOp::Replace { + op: GroveOp::ReplaceDontCheckForBackwardsReferences { element: Element::Item(debt_bytes, None), }, .. @@ -826,7 +826,7 @@ mod tests { assert!(matches!( drive_operations[..], [_, LowLevelDriveOperation::GroveOperation(grovedb::batch::QualifiedGroveDbOp { - op: GroveOp::Replace { + op: GroveOp::ReplaceDontCheckForBackwardsReferences { element: Element::SumItem(balance, None), }, .. @@ -885,13 +885,13 @@ mod tests { [ _, LowLevelDriveOperation::GroveOperation(grovedb::batch::QualifiedGroveDbOp { - op: GroveOp::Replace { + op: GroveOp::ReplaceDontCheckForBackwardsReferences { element: Element::SumItem(balance, None), }, .. }), LowLevelDriveOperation::GroveOperation(grovedb::batch::QualifiedGroveDbOp { - op: GroveOp::Replace { + op: GroveOp::ReplaceDontCheckForBackwardsReferences { element: Element::Item(debt_bytes, None), }, .. diff --git a/packages/rs-drive/src/drive/prefunded_specialized_balances/add_prefunded_specialized_balance_operations/v0/mod.rs b/packages/rs-drive/src/drive/prefunded_specialized_balances/add_prefunded_specialized_balance_operations/v0/mod.rs index e4602733a57..f1a4f9b02d4 100644 --- a/packages/rs-drive/src/drive/prefunded_specialized_balances/add_prefunded_specialized_balance_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/prefunded_specialized_balances/add_prefunded_specialized_balance_operations/v0/mod.rs @@ -67,12 +67,14 @@ impl Drive { specialized_balance_id.to_vec(), Element::new_sum_item(new_total as i64), ) + .dont_check_for_backwards_references() } else { QualifiedGroveDbOp::insert_or_replace_op( path_holding_total_credits_vec, specialized_balance_id.to_vec(), Element::new_sum_item(new_total as i64), ) + .dont_check_for_backwards_references() }; drive_operations.push(GroveOperation(op)); Ok(drive_operations) diff --git a/packages/rs-drive/src/drive/prefunded_specialized_balances/add_prefunded_specialized_balance_operations/v1/mod.rs b/packages/rs-drive/src/drive/prefunded_specialized_balances/add_prefunded_specialized_balance_operations/v1/mod.rs index a65eb8f7564..0a49cc213d4 100644 --- a/packages/rs-drive/src/drive/prefunded_specialized_balances/add_prefunded_specialized_balance_operations/v1/mod.rs +++ b/packages/rs-drive/src/drive/prefunded_specialized_balances/add_prefunded_specialized_balance_operations/v1/mod.rs @@ -78,12 +78,14 @@ impl Drive { specialized_balance_id.to_vec(), Element::new_sum_item(new_total as i64), ) + .dont_check_for_backwards_references() } else { QualifiedGroveDbOp::insert_or_replace_op( path_holding_total_credits_vec, specialized_balance_id.to_vec(), Element::new_sum_item(new_total as i64), ) + .dont_check_for_backwards_references() }; drive_operations.push(GroveOperation(op)); Ok(drive_operations) diff --git a/packages/rs-drive/src/drive/prefunded_specialized_balances/deduct_from_prefunded_specialized_balance_operations/v0/mod.rs b/packages/rs-drive/src/drive/prefunded_specialized_balances/deduct_from_prefunded_specialized_balance_operations/v0/mod.rs index ef3a75fc580..bffbe462439 100644 --- a/packages/rs-drive/src/drive/prefunded_specialized_balances/deduct_from_prefunded_specialized_balance_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/prefunded_specialized_balances/deduct_from_prefunded_specialized_balance_operations/v0/mod.rs @@ -64,7 +64,8 @@ impl Drive { path_holding_total_credits_vec, specialized_balance_id.to_vec(), Element::new_sum_item(new_total as i64), - ); + ) + .dont_check_for_backwards_references(); drive_operations.push(GroveOperation(replace_op)); Ok(drive_operations) } diff --git a/packages/rs-drive/src/drive/prefunded_specialized_balances/deduct_from_prefunded_specialized_balance_operations/v1/mod.rs b/packages/rs-drive/src/drive/prefunded_specialized_balances/deduct_from_prefunded_specialized_balance_operations/v1/mod.rs index c043e83d78c..c7c21ebc7e9 100644 --- a/packages/rs-drive/src/drive/prefunded_specialized_balances/deduct_from_prefunded_specialized_balance_operations/v1/mod.rs +++ b/packages/rs-drive/src/drive/prefunded_specialized_balances/deduct_from_prefunded_specialized_balance_operations/v1/mod.rs @@ -84,7 +84,8 @@ impl Drive { path_holding_total_credits_vec, specialized_balance_id.to_vec(), Element::new_sum_item(new_total as i64), - ); + ) + .dont_check_for_backwards_references(); drive_operations.push(GroveOperation(replace_op)); Ok(drive_operations) } diff --git a/packages/rs-drive/src/drive/prefunded_specialized_balances/empty_prefunded_specialized_balance_operations/v0/mod.rs b/packages/rs-drive/src/drive/prefunded_specialized_balances/empty_prefunded_specialized_balance_operations/v0/mod.rs index b971adc53c2..1b748f43cf0 100644 --- a/packages/rs-drive/src/drive/prefunded_specialized_balances/empty_prefunded_specialized_balance_operations/v0/mod.rs +++ b/packages/rs-drive/src/drive/prefunded_specialized_balances/empty_prefunded_specialized_balance_operations/v0/mod.rs @@ -78,7 +78,8 @@ impl Drive { let delete_op = QualifiedGroveDbOp::delete_op( path_holding_total_credits_vec, specialized_balance_id.to_vec(), - ); + ) + .dont_check_for_backwards_references(); drive_operations.push(GroveOperation(delete_op)); Ok((previous_credits_in_specialized_balance, drive_operations)) } @@ -101,7 +102,13 @@ mod tests { fn has_delete_op(ops: &[crate::fees::op::LowLevelDriveOperation]) -> bool { ops.iter().any(|op| match op { GroveOperation(qualified) => { - matches!(qualified.op, GroveOp::Delete | GroveOp::DeleteTree { .. }) + matches!( + qualified.op, + GroveOp::Delete + | GroveOp::DeleteDontCheckForBackwardsReferences + | GroveOp::DeleteTree { .. } + | GroveOp::DeleteTreeDontCheckForBackwardsReferences { .. } + ) } _ => false, }) diff --git a/packages/rs-drive/src/drive/prefunded_specialized_balances/fetch/single_balance/v0/mod.rs b/packages/rs-drive/src/drive/prefunded_specialized_balances/fetch/single_balance/v0/mod.rs index a8811774b07..c02d03e5f60 100644 --- a/packages/rs-drive/src/drive/prefunded_specialized_balances/fetch/single_balance/v0/mod.rs +++ b/packages/rs-drive/src/drive/prefunded_specialized_balances/fetch/single_balance/v0/mod.rs @@ -194,7 +194,8 @@ mod tests { prefunded_specialized_balances_for_voting_path_vec(), id.to_vec(), Element::new_sum_item(-42), - ); + ) + .dont_check_for_backwards_references(); drive .grove_apply_batch( crate::util::batch::GroveDbOpBatch::from_operations(vec![op]), diff --git a/packages/rs-drive/src/drive/shielded/update_total_balance/v0/mod.rs b/packages/rs-drive/src/drive/shielded/update_total_balance/v0/mod.rs index b7fcc8814ca..278447e5991 100644 --- a/packages/rs-drive/src/drive/shielded/update_total_balance/v0/mod.rs +++ b/packages/rs-drive/src/drive/shielded/update_total_balance/v0/mod.rs @@ -26,7 +26,8 @@ impl Drive { pool_path, vec![SHIELDED_TOTAL_BALANCE_KEY], Element::new_sum_item(balance_i64), - ), + ) + .dont_check_for_backwards_references(), )]) } } diff --git a/packages/rs-drive/src/drive/tokens/balance/update.rs b/packages/rs-drive/src/drive/tokens/balance/update.rs index df479eb6200..cae7c826817 100644 --- a/packages/rs-drive/src/drive/tokens/balance/update.rs +++ b/packages/rs-drive/src/drive/tokens/balance/update.rs @@ -619,14 +619,14 @@ mod tests { _, _, LowLevelDriveOperation::GroveOperation(grovedb::batch::QualifiedGroveDbOp { - op: GroveOp::Replace { + op: GroveOp::ReplaceDontCheckForBackwardsReferences { element: Element::SumItem(refund_amount, None), }, .. }), .., LowLevelDriveOperation::GroveOperation(grovedb::batch::QualifiedGroveDbOp { - op: GroveOp::Replace { + op: GroveOp::ReplaceDontCheckForBackwardsReferences { element: Element::SumItem(other_refund_amount, None), }, .. @@ -715,13 +715,13 @@ mod tests { _, _, LowLevelDriveOperation::GroveOperation(grovedb::batch::QualifiedGroveDbOp { - op: GroveOp::Replace { + op: GroveOp::ReplaceDontCheckForBackwardsReferences { element: Element::SumItem(refund_amount, None), }, .. }), LowLevelDriveOperation::GroveOperation(grovedb::batch::QualifiedGroveDbOp { - op: GroveOp::Replace { + op: GroveOp::ReplaceDontCheckForBackwardsReferences { element: Element::Item(debt_bytes, None), }, .. @@ -790,7 +790,7 @@ mod tests { _, _, LowLevelDriveOperation::GroveOperation(grovedb::batch::QualifiedGroveDbOp { - op: GroveOp::Replace { + op: GroveOp::ReplaceDontCheckForBackwardsReferences { element: Element::Item(debt_bytes, None), }, .. @@ -845,7 +845,7 @@ mod tests { assert!(matches!( drive_operations[..], [_, LowLevelDriveOperation::GroveOperation(grovedb::batch::QualifiedGroveDbOp { - op: GroveOp::Replace { + op: GroveOp::ReplaceDontCheckForBackwardsReferences { element: Element::SumItem(balance, None), }, .. @@ -904,13 +904,13 @@ mod tests { [ _, LowLevelDriveOperation::GroveOperation(grovedb::batch::QualifiedGroveDbOp { - op: GroveOp::Replace { + op: GroveOp::ReplaceDontCheckForBackwardsReferences { element: Element::SumItem(balance, None), }, .. }), LowLevelDriveOperation::GroveOperation(grovedb::batch::QualifiedGroveDbOp { - op: GroveOp::Replace { + op: GroveOp::ReplaceDontCheckForBackwardsReferences { element: Element::Item(debt_bytes, None), }, .. diff --git a/packages/rs-drive/src/drive/tokens/direct_purchase/set_direct_purchase_price/v0/mod.rs b/packages/rs-drive/src/drive/tokens/direct_purchase/set_direct_purchase_price/v0/mod.rs index 9c05f3bcd29..0905d940dbf 100644 --- a/packages/rs-drive/src/drive/tokens/direct_purchase/set_direct_purchase_price/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/direct_purchase/set_direct_purchase_price/v0/mod.rs @@ -40,7 +40,8 @@ impl Drive { )); } else { drive_operations.push(LowLevelDriveOperation::GroveOperation( - QualifiedGroveDbOp::delete_op(direct_selling_path, token_id.to_vec()), + QualifiedGroveDbOp::delete_op(direct_selling_path, token_id.to_vec()) + .dont_check_for_backwards_references(), )); } diff --git a/packages/rs-drive/src/drive/tokens/system/add_to_token_total_supply/v0/mod.rs b/packages/rs-drive/src/drive/tokens/system/add_to_token_total_supply/v0/mod.rs index dd5626a67b6..eb74f24d56d 100644 --- a/packages/rs-drive/src/drive/tokens/system/add_to_token_total_supply/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/system/add_to_token_total_supply/v0/mod.rs @@ -138,7 +138,8 @@ impl Drive { path_holding_total_token_supply_vec, token_id.to_vec(), SumItem(new_total, None), - ); + ) + .dont_check_for_backwards_references(); drive_operations.push(GroveOperation(replace_op)); new_total as u64 - total_token_supply_in_platform } else if allow_first_mint { diff --git a/packages/rs-drive/src/drive/tokens/system/remove_from_token_total_supply/v0/mod.rs b/packages/rs-drive/src/drive/tokens/system/remove_from_token_total_supply/v0/mod.rs index 6efdc122fd6..4b5cda29f51 100644 --- a/packages/rs-drive/src/drive/tokens/system/remove_from_token_total_supply/v0/mod.rs +++ b/packages/rs-drive/src/drive/tokens/system/remove_from_token_total_supply/v0/mod.rs @@ -138,7 +138,8 @@ impl Drive { path_holding_total_token_supply_vec, token_id.to_vec(), SumItem(new_total as i64, None), - ); + ) + .dont_check_for_backwards_references(); drive_operations.push(GroveOperation(replace_op)); Ok(drive_operations) diff --git a/packages/rs-drive/src/fees/op.rs b/packages/rs-drive/src/fees/op.rs index 7e55a751bd4..97cde2a1921 100644 --- a/packages/rs-drive/src/fees/op.rs +++ b/packages/rs-drive/src/fees/op.rs @@ -1382,7 +1382,10 @@ impl LowLevelDriveOperation { key: Vec, element: Element, ) -> Self { - GroveOperation(QualifiedGroveDbOp::insert_or_replace_op(path, key, element)) + GroveOperation( + QualifiedGroveDbOp::insert_or_replace_op(path, key, element) + .dont_check_for_backwards_references(), + ) } /// Sets `GroveOperation` for replacement of an element at the given path and key @@ -1391,7 +1394,10 @@ impl LowLevelDriveOperation { key: Vec, element: Element, ) -> Self { - GroveOperation(QualifiedGroveDbOp::replace_op(path, key, element)) + GroveOperation( + QualifiedGroveDbOp::replace_op(path, key, element) + .dont_check_for_backwards_references(), + ) } /// Sets `GroveOperation` for patching of an element at the given path and key @@ -1402,12 +1408,10 @@ impl LowLevelDriveOperation { element: Element, change_in_bytes: i32, ) -> Self { - GroveOperation(QualifiedGroveDbOp::patch_op( - path, - key, - element, - change_in_bytes, - )) + GroveOperation( + QualifiedGroveDbOp::patch_op(path, key, element, change_in_bytes) + .dont_check_for_backwards_references(), + ) } /// Sets `GroveOperation` for inserting an element at an unknown estimated path and key @@ -1416,7 +1420,10 @@ impl LowLevelDriveOperation { key: KeyInfo, element: Element, ) -> Self { - GroveOperation(QualifiedGroveDbOp::insert_estimated_op(path, key, element)) + GroveOperation( + QualifiedGroveDbOp::insert_estimated_op(path, key, element) + .dont_check_for_backwards_references(), + ) } /// Sets `GroveOperation` for replacement of an element at an unknown estimated path and key @@ -1425,7 +1432,10 @@ impl LowLevelDriveOperation { key: KeyInfo, element: Element, ) -> Self { - GroveOperation(QualifiedGroveDbOp::replace_estimated_op(path, key, element)) + GroveOperation( + QualifiedGroveDbOp::replace_estimated_op(path, key, element) + .dont_check_for_backwards_references(), + ) } /// Sets `GroveOperation` for refresh of a reference at the given path and key @@ -2440,7 +2450,8 @@ mod tests { match op { LowLevelDriveOperation::GroveOperation(grove_op) => match grove_op.op { - GroveOp::InsertOrReplace { element } => assert!( + GroveOp::InsertOrReplace { element } + | GroveOp::InsertOrReplaceDontCheckForBackwardsReferences { element } => assert!( matches!(element, Element::ProvableSumTree(..)), "expected ProvableSumTree element, got: {:?}", element @@ -2525,7 +2536,10 @@ mod tests { }); let element = match op { LowLevelDriveOperation::GroveOperation(grove_op) => match grove_op.op { - GroveOp::InsertOrReplace { element } => element, + GroveOp::InsertOrReplace { element } + | GroveOp::InsertOrReplaceDontCheckForBackwardsReferences { element } => { + element + } other => panic!("expected InsertOrReplace, got {other:?}"), }, other => panic!("expected GroveOperation, got {other:?}"), diff --git a/packages/rs-drive/src/query/mod.rs b/packages/rs-drive/src/query/mod.rs index 27c23346f06..a5f8662d2c2 100644 --- a/packages/rs-drive/src/query/mod.rs +++ b/packages/rs-drive/src/query/mod.rs @@ -2042,23 +2042,73 @@ impl<'a> DriveDocumentQuery<'a> { &platform_version.drive.grove_version, ) .map_err(Error::from)?; - merged.query.limit = limit.map(|a| a.saturating_add(1)); - // The merged root must be walked ascending regardless of the - // page's `orderBy` direction: the `limit + 1` above reserves - // one result slot for the cursor document, and the prover - // spends the budget in root traversal order. Ascending, the - // cursor branch (key `[0]`) is visited first and takes its - // reserved slot; descending, the index branch sorts first, - // consumes the whole budget mid-timeline, and the prover then - // omits the cursor subtree's lower layer — an unverifiable - // proof (the verifier extracts the cursor document from the - // proof before rebuilding the main query). Only this - // synthesized root flips: each input's own query lands intact - // inside a subquery branch, keeping in-branch result order. - // The verifier never rebuilds the merged query — it runs the - // cursor and main queries as separate subset queries — so the - // root's direction is not client-visible. - merged.query.query.left_to_right = true; + // Where the merge lands decides how the two queries combine. An + // index-ordered page lives under its index tree while the cursor + // lookup lives under the primary-key tree, so the merge synthesizes + // a root one level above both with each query in its own branch. + // A `$id`-ordered page addresses the primary-key tree directly: the + // cursor lookup shares that path (or, for a history-keeping type, + // sits one level below it), so the merge point is the page query's + // own root layer and the merged query IS that layer. + let cursor_on_page_layer = merged.path == main_path_query.path; + // The cursor's key on that shared layer: the cursor query's own key + // when both paths coincide, otherwise the path component the cursor + // query descends through. + let cursor_key_on_page_layer: Option<&[u8]> = if !cursor_on_page_layer { + None + } else if let Some(component) = start_at_path_query.path.get(merged.path.len()) { + Some(component.as_slice()) + } else { + match start_at_path_query.query.query.items.as_slice() { + [QueryItem::Key(cursor_key)] => Some(cursor_key.as_slice()), + _ => None, + } + }; + // On a shared layer the cursor row is already one of the page's + // rows whenever the page's own items cover it (an inclusive + // `startAt` on a range, or an `in` list that names the cursor). It + // then needs no reserved slot: reserving one would make the layer + // return `limit + 1` rows matching the page query, which the + // verifier rejects as more data than its limit. + let cursor_row_in_page = cursor_key_on_page_layer.is_some_and(|cursor_key| { + main_path_query + .query + .query + .items + .iter() + .any(|item| item.contains(cursor_key)) + }); + merged.query.limit = limit.map(|a| { + if cursor_row_in_page { + a + } else { + a.saturating_add(1) + } + }); + if !cursor_on_page_layer { + // A synthesized root must be walked ascending regardless of + // the page's `orderBy` direction: the `limit + 1` above + // reserves one result slot for the cursor document, and the + // prover spends the budget in root traversal order. Ascending, + // the cursor branch (key `[0]`) is visited first and takes its + // reserved slot; descending, the index branch sorts first, + // consumes the whole budget mid-timeline, and the prover then + // omits the cursor subtree's lower layer — an unverifiable + // proof (the verifier extracts the cursor document from the + // proof before rebuilding the main query). Only this + // synthesized root flips: each input's own query lands intact + // inside a subquery branch, keeping in-branch result order. + // The verifier never rebuilds the merged query — it runs the + // cursor and main queries as separate subset queries — so the + // root's direction is not client-visible. + // + // A shared layer has no synthesized root to flip: the merged + // query IS the page query's own layer, which the verifier + // walks in the requested direction, and the cursor row sits at + // the page's boundary, so the requested direction reaches it + // first anyway. + merged.query.query.left_to_right = true; + } Ok(merged) } else { Ok(main_path_query) diff --git a/packages/rs-drive/src/util/batch/grovedb_op_batch/mod.rs b/packages/rs-drive/src/util/batch/grovedb_op_batch/mod.rs index 7e0c7e9ec8a..de7a8cc8eb6 100644 --- a/packages/rs-drive/src/util/batch/grovedb_op_batch/mod.rs +++ b/packages/rs-drive/src/util/batch/grovedb_op_batch/mod.rs @@ -347,6 +347,7 @@ impl fmt::Display for GroveDbOpBatch { writeln!(f, " Key: {}", key_string)?; match &op.op { GroveOp::InsertOrReplace { element } + | GroveOp::InsertOrReplaceDontCheckForBackwardsReferences { element } | GroveOp::InsertWithKnownToNotAlreadyExist { element } | GroveOp::InsertIfNotExists { element, .. } => { let flags = element.get_flags(); @@ -536,12 +537,10 @@ impl GroveDbOpBatchV0Methods for GroveDbOpBatch { /// Adds an `Insert` operation with an empty tree at the specified path and key to a list of GroveDB ops. fn add_insert_empty_tree(&mut self, path: Vec>, key: Vec) { - self.operations - .push(QualifiedGroveDbOp::insert_or_replace_op( - path, - key, - Element::empty_tree(), - )) + self.operations.push( + QualifiedGroveDbOp::insert_or_replace_op(path, key, Element::empty_tree()) + .dont_check_for_backwards_references(), + ) } /// Adds an `Insert` operation with an empty tree with storage flags to a list of GroveDB ops. @@ -551,24 +550,24 @@ impl GroveDbOpBatchV0Methods for GroveDbOpBatch { key: Vec, storage_flags: &Option>, ) { - self.operations - .push(QualifiedGroveDbOp::insert_or_replace_op( + self.operations.push( + QualifiedGroveDbOp::insert_or_replace_op( path, key, Element::empty_tree_with_flags( StorageFlags::map_borrowed_cow_to_some_element_flags(storage_flags), ), - )) + ) + .dont_check_for_backwards_references(), + ) } /// Adds an `Insert` operation with an empty sum tree at the specified path and key to a list of GroveDB ops. fn add_insert_empty_sum_tree(&mut self, path: Vec>, key: Vec) { - self.operations - .push(QualifiedGroveDbOp::insert_or_replace_op( - path, - key, - Element::empty_sum_tree(), - )) + self.operations.push( + QualifiedGroveDbOp::insert_or_replace_op(path, key, Element::empty_sum_tree()) + .dont_check_for_backwards_references(), + ) } /// Adds an `Insert` operation with an empty sum tree with storage flags to a list of GroveDB ops. @@ -578,38 +577,45 @@ impl GroveDbOpBatchV0Methods for GroveDbOpBatch { key: Vec, storage_flags: &Option>, ) { - self.operations - .push(QualifiedGroveDbOp::insert_or_replace_op( + self.operations.push( + QualifiedGroveDbOp::insert_or_replace_op( path, key, Element::empty_sum_tree_with_flags( StorageFlags::map_borrowed_cow_to_some_element_flags(storage_flags), ), - )) + ) + .dont_check_for_backwards_references(), + ) } /// Adds a `Delete` operation to a list of GroveDB ops. fn add_delete(&mut self, path: Vec>, key: Vec) { self.operations - .push(QualifiedGroveDbOp::delete_op(path, key)) + .push(QualifiedGroveDbOp::delete_op(path, key).dont_check_for_backwards_references()) } /// Adds a `Delete` tree operation to a list of GroveDB ops. /// Uses `DontCheckWithNoCleanup` because callers (e.g. `batch_delete_up_tree_while_empty`) /// have already verified the tree is empty. fn add_delete_tree(&mut self, path: Vec>, key: Vec, tree_type: TreeType) { - self.operations.push(QualifiedGroveDbOp::delete_tree_op( - path, - key, - tree_type, - SubelementsDeletionBehavior::DontCheckWithNoCleanup, - )) + self.operations.push( + QualifiedGroveDbOp::delete_tree_op( + path, + key, + tree_type, + SubelementsDeletionBehavior::DontCheckWithNoCleanup, + ) + .dont_check_for_backwards_references(), + ) } /// Adds an `Insert` operation with an element to a list of GroveDB ops. fn add_insert(&mut self, path: Vec>, key: Vec, element: Element) { - self.operations - .push(QualifiedGroveDbOp::insert_or_replace_op(path, key, element)) + self.operations.push( + QualifiedGroveDbOp::insert_or_replace_op(path, key, element) + .dont_check_for_backwards_references(), + ) } /// Verify consistency of operations @@ -707,10 +713,13 @@ impl GroveDbOpBatchV0Methods for GroveDbOpBatch { let op = if matches!( op, &GroveOp::InsertOrReplace { .. } + | &GroveOp::InsertOrReplaceDontCheckForBackwardsReferences { .. } | &GroveOp::InsertWithKnownToNotAlreadyExist { .. } | &GroveOp::InsertIfNotExists { .. } | &GroveOp::Replace { .. } + | &GroveOp::ReplaceDontCheckForBackwardsReferences { .. } | &GroveOp::Patch { .. } + | &GroveOp::PatchDontCheckForBackwardsReferences { .. } ) { self.operations.remove(index).op } else { diff --git a/packages/rs-drive/src/util/grove_operations/batch_delete/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_delete/v0/mod.rs index a1b7680314f..067766ccd8a 100644 --- a/packages/rs-drive/src/util/grove_operations/batch_delete/v0/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/batch_delete/v0/mod.rs @@ -6,6 +6,7 @@ use crate::util::grove_operations::{push_drive_operation_result, BatchDeleteAppl use grovedb::batch::key_info::KeyInfo; use grovedb::batch::KeyInfoPath; use grovedb::operations::delete::DeleteOptions; +use grovedb::BackwardsReferences; use grovedb::{GroveDb, TransactionArg}; use grovedb_path::SubtreePath; use grovedb_storage::rocksdb_storage::RocksDbStorage; @@ -23,6 +24,9 @@ impl Drive { drive_version: &DriveVersion, ) -> Result<(), Error> { let options = DeleteOptions { + // Drive stores no backward-reference participants; GroveDB checks the + // claim for free from the value it reads for the write. + backwards_references: BackwardsReferences::DontCheck, allow_deleting_non_empty_trees: false, deleting_non_empty_trees_returns_error: true, base_root_storage_is_free: true, @@ -66,6 +70,7 @@ impl Drive { true, 0, (estimated_key_size, estimated_value_size), + BackwardsReferences::DontCheck, &drive_version.grove_version, ) .map(|r| r.map(Some)), diff --git a/packages/rs-drive/src/util/grove_operations/batch_delete_items_in_path_query/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_delete_items_in_path_query/v0/mod.rs index 01952b937a0..3a3530aeadb 100644 --- a/packages/rs-drive/src/util/grove_operations/batch_delete_items_in_path_query/v0/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/batch_delete_items_in_path_query/v0/mod.rs @@ -8,6 +8,7 @@ use grovedb::batch::key_info::KeyInfo; use grovedb::batch::KeyInfoPath; use grovedb::operations::delete::DeleteOptions; use grovedb::query_result_type::QueryResultType; +use grovedb::BackwardsReferences; use grovedb::{GroveDb, PathQuery, TransactionArg}; use grovedb_storage::rocksdb_storage::RocksDbStorage; use platform_version::version::drive_versions::DriveVersion; @@ -80,6 +81,9 @@ impl Drive { let current_batch_operations = LowLevelDriveOperation::grovedb_operations_batch(drive_operations); let options = DeleteOptions { + // Drive stores no backward-reference participants; GroveDB checks the + // claim for free from the value it reads for the write. + backwards_references: BackwardsReferences::DontCheck, allow_deleting_non_empty_trees: false, deleting_non_empty_trees_returns_error: true, base_root_storage_is_free: true, @@ -98,6 +102,7 @@ impl Drive { true, 0, (estimated_key_size, estimated_value_size), + BackwardsReferences::DontCheck, &drive_version.grove_version, ) .map(|r| r.map(Some)), diff --git a/packages/rs-drive/src/util/grove_operations/batch_delete_up_tree_while_empty/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_delete_up_tree_while_empty/v0/mod.rs index d292aae1fdd..4f9f189b82a 100644 --- a/packages/rs-drive/src/util/grove_operations/batch_delete_up_tree_while_empty/v0/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/batch_delete_up_tree_while_empty/v0/mod.rs @@ -7,7 +7,7 @@ use crate::util::grove_operations::{push_drive_operation_result, BatchDeleteUpTr use grovedb::batch::key_info::KeyInfo; use grovedb::batch::KeyInfoPath; use grovedb::operations::delete::DeleteUpTreeOptions; -use grovedb::{GroveDb, TransactionArg}; +use grovedb::{BackwardsReferences, GroveDb, TransactionArg}; use grovedb_storage::rocksdb_storage::RocksDbStorage; use platform_version::version::drive_versions::DriveVersion; @@ -46,6 +46,7 @@ impl Drive { stop_path_height, true, estimated_layer_info, + BackwardsReferences::DontCheck, &drive_version.grove_version, ), BatchDeleteUpTreeApplyType::StatefulBatchDelete { @@ -57,6 +58,9 @@ impl Drive { base_root_storage_is_free: true, validate_tree_at_path_exists: false, stop_path_height, + // Drive stores no backward-reference participants; GroveDB checks + // the claim for free from the value it reads for each delete. + backwards_references: BackwardsReferences::DontCheck, }; self.grove.delete_operations_for_delete_up_tree_while_empty( path.to_path_refs().as_slice().into(), diff --git a/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/v0/mod.rs index 4e425c7296c..ed457b4cda9 100644 --- a/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/v0/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/batch_insert_empty_tree_if_not_exists/v0/mod.rs @@ -114,7 +114,11 @@ impl Drive { } else if let GroveOperation(grove_op) = previous_drive_operation { if grove_op.key == Some(KeyInfo::KnownKey(key.to_vec())) && grove_op.path == path - && matches!(grove_op.op, GroveOp::DeleteTree(_, _)) + && matches!( + grove_op.op, + GroveOp::DeleteTree(_, _) + | GroveOp::DeleteTreeDontCheckForBackwardsReferences(_, _) + ) { found = true; existing_operations.remove(i); @@ -177,7 +181,11 @@ impl Drive { } else if let GroveOperation(grove_op) = previous_drive_operation { if grove_op.key == Some(KeyInfo::KnownKey(key.to_vec())) && grove_op.path == path - && matches!(grove_op.op, GroveOp::DeleteTree(_, _)) + && matches!( + grove_op.op, + GroveOp::DeleteTree(_, _) + | GroveOp::DeleteTreeDontCheckForBackwardsReferences(_, _) + ) { found = true; existing_operations.remove(i); @@ -238,7 +246,11 @@ impl Drive { } else if let GroveOperation(grove_op) = previous_drive_operation { if grove_op.key == Some(KeyInfo::KnownKey(key.to_vec())) && grove_op.path == path - && matches!(grove_op.op, GroveOp::DeleteTree(_, _)) + && matches!( + grove_op.op, + GroveOp::DeleteTree(_, _) + | GroveOp::DeleteTreeDontCheckForBackwardsReferences(_, _) + ) { found = true; existing_operations.remove(i); @@ -299,7 +311,11 @@ impl Drive { } else if let GroveOperation(grove_op) = previous_drive_operation { if grove_op.key == Some(KeyInfo::KnownKey(key.to_vec())) && grove_op.path == path - && matches!(grove_op.op, GroveOp::DeleteTree(_, _)) + && matches!( + grove_op.op, + GroveOp::DeleteTree(_, _) + | GroveOp::DeleteTreeDontCheckForBackwardsReferences(_, _) + ) { found = true; existing_operations.remove(i); @@ -718,7 +734,7 @@ mod tests { let element = match ops.pop().expect("one operation must be pushed") { LowLevelDriveOperation::GroveOperation(grove_op) => match grove_op.op { - GroveOp::InsertOrReplace { element } => element, + GroveOp::InsertOrReplaceDontCheckForBackwardsReferences { element } => element, other => panic!("{description}: expected InsertOrReplace, got {other:?}"), }, other => panic!("{description}: expected GroveOperation, got {other:?}"), @@ -746,7 +762,7 @@ mod tests { assert!(inserted); let element = match ops.pop().expect("one operation must be pushed") { LowLevelDriveOperation::GroveOperation(grove_op) => match grove_op.op { - GroveOp::InsertOrReplace { element } => element, + GroveOp::InsertOrReplaceDontCheckForBackwardsReferences { element } => element, other => panic!("expected InsertOrReplace, got {other:?}"), }, other => panic!("expected GroveOperation, got {other:?}"), @@ -807,7 +823,7 @@ mod tests { assert!(inserted); let element = match ops.pop().expect("one operation must be pushed") { LowLevelDriveOperation::GroveOperation(grove_op) => match grove_op.op { - GroveOp::InsertOrReplace { element } => element, + GroveOp::InsertOrReplaceDontCheckForBackwardsReferences { element } => element, other => panic!("expected InsertOrReplace, got {other:?}"), }, other => panic!("expected GroveOperation, got {other:?}"), diff --git a/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_or_add_to_if_already_exists/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_or_add_to_if_already_exists/v0/mod.rs index e20dc882e83..8c5b6c3cf09 100644 --- a/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_or_add_to_if_already_exists/v0/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/batch_insert_sum_item_or_add_to_if_already_exists/v0/mod.rs @@ -328,7 +328,7 @@ mod tests { let insert_op = &ops[1]; match insert_op { LowLevelDriveOperation::GroveOperation(grove_op) => match &grove_op.op { - GroveOp::InsertOrReplace { element } => { + GroveOp::InsertOrReplaceDontCheckForBackwardsReferences { element } => { assert_eq!( *element, Element::new_sum_item(15), diff --git a/packages/rs-drive/src/util/grove_operations/batch_move/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_move/v0/mod.rs index 3b4c7025471..5666c01da7a 100644 --- a/packages/rs-drive/src/util/grove_operations/batch_move/v0/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/batch_move/v0/mod.rs @@ -7,6 +7,7 @@ use crate::util::grove_operations::{push_drive_operation_result, BatchMoveApplyT use grovedb::batch::key_info::KeyInfo; use grovedb::batch::{KeyInfoPath, QualifiedGroveDbOp}; use grovedb::operations::delete::DeleteOptions; +use grovedb::BackwardsReferences; use grovedb::{Element, GroveDb, TransactionArg}; use grovedb_epoch_based_storage_flags::StorageFlags; use grovedb_path::SubtreePath; @@ -60,6 +61,9 @@ impl Drive { // ── 2. Build the delete op ────────────────────────────────────────── let current_batch = LowLevelDriveOperation::grovedb_operations_batch(drive_operations); let delete_opts = DeleteOptions { + // Drive stores no backward-reference participants; GroveDB checks the + // claim for free from the value it reads for the write. + backwards_references: BackwardsReferences::DontCheck, allow_deleting_non_empty_trees: false, deleting_non_empty_trees_returns_error: true, base_root_storage_is_free: true, @@ -80,6 +84,7 @@ impl Drive { true, 0, (estimated_key_size, estimated_value_size), + BackwardsReferences::DontCheck, &drive_version.grove_version, ) .map(|r| r.map(Some)), @@ -103,11 +108,10 @@ impl Drive { } drive_operations.push(GroveOperation(delete_op)); - drive_operations.push(GroveOperation(QualifiedGroveDbOp::insert_or_replace_op( - to_path, - key.to_vec(), - element, - ))); + drive_operations.push(GroveOperation( + QualifiedGroveDbOp::insert_or_replace_op(to_path, key.to_vec(), element) + .dont_check_for_backwards_references(), + )); } Ok(()) diff --git a/packages/rs-drive/src/util/grove_operations/batch_move_items_in_path_query/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_move_items_in_path_query/v0/mod.rs index b65b3ccb69e..28206996cd8 100644 --- a/packages/rs-drive/src/util/grove_operations/batch_move_items_in_path_query/v0/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/batch_move_items_in_path_query/v0/mod.rs @@ -8,6 +8,7 @@ use grovedb::batch::key_info::KeyInfo; use grovedb::batch::{KeyInfoPath, QualifiedGroveDbOp}; use grovedb::operations::delete::DeleteOptions; use grovedb::query_result_type::QueryResultType; +use grovedb::BackwardsReferences; use grovedb::{GroveDb, PathQuery, TransactionArg}; use grovedb_epoch_based_storage_flags::StorageFlags; use grovedb_storage::rocksdb_storage::RocksDbStorage; @@ -86,6 +87,9 @@ impl Drive { let current_batch_operations = LowLevelDriveOperation::grovedb_operations_batch(drive_operations); let options = DeleteOptions { + // Drive stores no backward-reference participants; GroveDB checks the + // claim for free from the value it reads for the write. + backwards_references: BackwardsReferences::DontCheck, allow_deleting_non_empty_trees: false, deleting_non_empty_trees_returns_error: true, base_root_storage_is_free: true, @@ -105,6 +109,7 @@ impl Drive { true, 0, (estimated_key_size, estimated_value_size), + BackwardsReferences::DontCheck, &drive_version.grove_version, ) .map(|r| r.map(Some)), @@ -132,11 +137,10 @@ impl Drive { // Add the delete operation to the batch of drive operations drive_operations.push(GroveOperation(delete_operation)); // Adds the insert operation to the batch of drive operations - drive_operations.push(GroveOperation(QualifiedGroveDbOp::insert_or_replace_op( - new_path.clone(), - key, - element, - ))); + drive_operations.push(GroveOperation( + QualifiedGroveDbOp::insert_or_replace_op(new_path.clone(), key, element) + .dont_check_for_backwards_references(), + )); } } diff --git a/packages/rs-drive/src/util/grove_operations/batch_remove_raw/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_remove_raw/v0/mod.rs index 9da64b2262c..264ccf70e2e 100644 --- a/packages/rs-drive/src/util/grove_operations/batch_remove_raw/v0/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/batch_remove_raw/v0/mod.rs @@ -9,6 +9,7 @@ use dpp::version::drive_versions::DriveVersion; use grovedb::batch::key_info::KeyInfo; use grovedb::batch::{GroveOp, KeyInfoPath}; use grovedb::operations::delete::DeleteOptions; +use grovedb::BackwardsReferences; use grovedb::{Element, GroveDb, TransactionArg}; use grovedb_path::SubtreePath; use grovedb_storage::rocksdb_storage::RocksDbStorage; @@ -29,6 +30,9 @@ impl Drive { let mut current_batch_operations = LowLevelDriveOperation::grovedb_operations_batch(drive_operations); let options = DeleteOptions { + // Drive stores no backward-reference participants; GroveDB checks the + // claim for free from the value it reads for the write. + backwards_references: BackwardsReferences::DontCheck, allow_deleting_non_empty_trees: false, deleting_non_empty_trees_returns_error: true, base_root_storage_is_free: true, @@ -37,15 +41,28 @@ impl Drive { let needs_removal_from_state = match current_batch_operations.remove_if_insert(path.to_vec(), key) { - Some(GroveOp::InsertOrReplace { element }) - | Some(GroveOp::Replace { element }) - | Some(GroveOp::Patch { element, .. }) => return Ok(Some(element)), + Some( + GroveOp::InsertOrReplace { element } + | GroveOp::InsertOrReplaceDontCheckForBackwardsReferences { element }, + ) + | Some( + GroveOp::Replace { element } + | GroveOp::ReplaceDontCheckForBackwardsReferences { element }, + ) + | Some( + GroveOp::Patch { element, .. } + | GroveOp::PatchDontCheckForBackwardsReferences { element, .. }, + ) => return Ok(Some(element)), Some(GroveOp::InsertTreeWithRootHash { .. }) => { return Err(Error::Drive(DriveError::CorruptedCodeExecution( "we should not be seeing internal grovedb operations", ))); } - Some(GroveOp::Delete) | Some(GroveOp::DeleteTree(_, _)) => false, + Some(GroveOp::Delete | GroveOp::DeleteDontCheckForBackwardsReferences) + | Some( + GroveOp::DeleteTree(_, _) + | GroveOp::DeleteTreeDontCheckForBackwardsReferences(_, _), + ) => false, _ => true, }; @@ -79,6 +96,7 @@ impl Drive { true, 0, (estimated_key_size, estimated_value_size), + BackwardsReferences::DontCheck, &drive_version.grove_version, ) .map(|r| r.map(Some)), diff --git a/packages/rs-drive/src/util/grove_operations/batch_replace/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/batch_replace/v0/mod.rs index fc23b3f3d39..61898b6214d 100644 --- a/packages/rs-drive/src/util/grove_operations/batch_replace/v0/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/batch_replace/v0/mod.rs @@ -71,7 +71,10 @@ mod tests { match &ops[0] { LowLevelDriveOperation::GroveOperation(grove_op) => { assert!( - matches!(grove_op.op, GroveOp::Replace { .. }), + matches!( + grove_op.op, + GroveOp::ReplaceDontCheckForBackwardsReferences { .. } + ), "Expected GroveOp::Replace, got {:?}", grove_op.op ); diff --git a/packages/rs-drive/src/util/grove_operations/grove_clear/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/grove_clear/v0/mod.rs index 41588184c93..8a9491d035c 100644 --- a/packages/rs-drive/src/util/grove_operations/grove_clear/v0/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/grove_clear/v0/mod.rs @@ -1,6 +1,7 @@ use crate::drive::Drive; use crate::error::Error; use grovedb::operations::delete::ClearOptions; +use grovedb::BackwardsReferences; use grovedb::TransactionArg; use grovedb_path::SubtreePath; use platform_version::version::drive_versions::DriveVersion; @@ -14,6 +15,9 @@ impl Drive { drive_version: &DriveVersion, ) -> Result<(), Error> { let options = ClearOptions { + // Drive stores no backward-reference participants; GroveDB checks the + // claim for free from the value it reads for the write. + backwards_references: BackwardsReferences::DontCheck, check_for_subtrees: false, allow_deleting_subtrees: false, trying_to_clear_with_subtrees_returns_error: false, diff --git a/packages/rs-drive/src/util/grove_operations/grove_delete/v0/mod.rs b/packages/rs-drive/src/util/grove_operations/grove_delete/v0/mod.rs index d5e0c2ab1e2..0a7f29f2a07 100644 --- a/packages/rs-drive/src/util/grove_operations/grove_delete/v0/mod.rs +++ b/packages/rs-drive/src/util/grove_operations/grove_delete/v0/mod.rs @@ -3,6 +3,7 @@ use crate::error::Error; use crate::fees::op::LowLevelDriveOperation; use crate::util::grove_operations::push_drive_operation_result; use grovedb::operations::delete::DeleteOptions; +use grovedb::BackwardsReferences; use grovedb::TransactionArg; use grovedb_path::SubtreePath; use platform_version::version::drive_versions::DriveVersion; @@ -18,6 +19,9 @@ impl Drive { drive_version: &DriveVersion, ) -> Result<(), Error> { let options = DeleteOptions { + // Drive stores no backward-reference participants; GroveDB checks the + // claim for free from the value it reads for the write. + backwards_references: BackwardsReferences::DontCheck, allow_deleting_non_empty_trees: false, deleting_non_empty_trees_returns_error: true, base_root_storage_is_free: true, diff --git a/packages/rs-drive/src/util/operations/tests.rs b/packages/rs-drive/src/util/operations/tests.rs index 1dc9d637052..ecad1957d63 100644 --- a/packages/rs-drive/src/util/operations/tests.rs +++ b/packages/rs-drive/src/util/operations/tests.rs @@ -92,17 +92,19 @@ fn apply_batch_low_level_mixed_ops_applies_grove_and_preserves_leftovers() { // of guessing paths, we build grove ops against an already-existing // subtree by inserting at a *newly created* subtree first. let batch_ops = vec![ - LowLevelDriveOperation::GroveOperation(QualifiedGroveDbOp::insert_or_replace_op( - vec![], - vec![0xfe], - Element::empty_tree(), - )), + LowLevelDriveOperation::GroveOperation( + QualifiedGroveDbOp::insert_or_replace_op(vec![], vec![0xfe], Element::empty_tree()) + .dont_check_for_backwards_references(), + ), function_op(), - LowLevelDriveOperation::GroveOperation(QualifiedGroveDbOp::insert_or_replace_op( - vec![vec![0xfe]], - vec![0x01], - Element::new_item(vec![1, 2, 3]), - )), + LowLevelDriveOperation::GroveOperation( + QualifiedGroveDbOp::insert_or_replace_op( + vec![vec![0xfe]], + vec![0x01], + Element::new_item(vec![1, 2, 3]), + ) + .dont_check_for_backwards_references(), + ), ]; let mut drive_operations: Vec = vec![]; @@ -145,16 +147,18 @@ fn apply_batch_low_level_actually_persists_grove_inserts() { let platform_version = PlatformVersion::latest(); let batch_ops = vec![ - LowLevelDriveOperation::GroveOperation(QualifiedGroveDbOp::insert_or_replace_op( - vec![], - vec![0xfd], - Element::empty_tree(), - )), - LowLevelDriveOperation::GroveOperation(QualifiedGroveDbOp::insert_or_replace_op( - vec![vec![0xfd]], - b"hello".to_vec(), - Element::new_item(b"world".to_vec()), - )), + LowLevelDriveOperation::GroveOperation( + QualifiedGroveDbOp::insert_or_replace_op(vec![], vec![0xfd], Element::empty_tree()) + .dont_check_for_backwards_references(), + ), + LowLevelDriveOperation::GroveOperation( + QualifiedGroveDbOp::insert_or_replace_op( + vec![vec![0xfd]], + b"hello".to_vec(), + Element::new_item(b"world".to_vec()), + ) + .dont_check_for_backwards_references(), + ), ]; let mut drive_operations: Vec = vec![]; @@ -280,16 +284,18 @@ fn rollback_transaction_v0_discards_uncommitted_changes() { // Build ops inside the transaction. let batch_ops = vec![ - LowLevelDriveOperation::GroveOperation(QualifiedGroveDbOp::insert_or_replace_op( - vec![], - vec![0xfb], - Element::empty_tree(), - )), - LowLevelDriveOperation::GroveOperation(QualifiedGroveDbOp::insert_or_replace_op( - vec![vec![0xfb]], - b"k".to_vec(), - Element::new_item(b"v".to_vec()), - )), + LowLevelDriveOperation::GroveOperation( + QualifiedGroveDbOp::insert_or_replace_op(vec![], vec![0xfb], Element::empty_tree()) + .dont_check_for_backwards_references(), + ), + LowLevelDriveOperation::GroveOperation( + QualifiedGroveDbOp::insert_or_replace_op( + vec![vec![0xfb]], + b"k".to_vec(), + Element::new_item(b"v".to_vec()), + ) + .dont_check_for_backwards_references(), + ), ]; let mut drive_operations: Vec = vec![]; drive @@ -323,7 +329,8 @@ fn rollback_transaction_v0_discards_uncommitted_changes() { vec![vec![0xfb]], b"k2".to_vec(), Element::new_item(b"v2".to_vec()), - ), + ) + .dont_check_for_backwards_references(), )]; let mut drive_operations: Vec = vec![]; let res = drive.apply_batch_low_level_drive_operations_v0( @@ -387,16 +394,18 @@ fn public_apply_batch_low_level_drive_operations_routes_through_v0() { let platform_version = PlatformVersion::latest(); let batch_ops = vec![ - LowLevelDriveOperation::GroveOperation(QualifiedGroveDbOp::insert_or_replace_op( - vec![], - vec![0xfa], - Element::empty_tree(), - )), - LowLevelDriveOperation::GroveOperation(QualifiedGroveDbOp::insert_or_replace_op( - vec![vec![0xfa]], - b"x".to_vec(), - Element::new_item(b"y".to_vec()), - )), + LowLevelDriveOperation::GroveOperation( + QualifiedGroveDbOp::insert_or_replace_op(vec![], vec![0xfa], Element::empty_tree()) + .dont_check_for_backwards_references(), + ), + LowLevelDriveOperation::GroveOperation( + QualifiedGroveDbOp::insert_or_replace_op( + vec![vec![0xfa]], + b"x".to_vec(), + Element::new_item(b"y".to_vec()), + ) + .dont_check_for_backwards_references(), + ), ]; let mut drive_operations: Vec = vec![]; diff --git a/packages/rs-drive/src/verify/document/verify_start_at_document_in_proof/v0/mod.rs b/packages/rs-drive/src/verify/document/verify_start_at_document_in_proof/v0/mod.rs index 301afe65148..d22ff197018 100644 --- a/packages/rs-drive/src/verify/document/verify_start_at_document_in_proof/v0/mod.rs +++ b/packages/rs-drive/src/verify/document/verify_start_at_document_in_proof/v0/mod.rs @@ -43,10 +43,25 @@ impl DriveDocumentQuery<'_> { self.validate_in_clause_shape(platform_version)?; let (start_at_document_path, start_at_document_key) = self.start_at_document_path_and_key(&document_id); - let path_query = PathQuery::new_single_key( + let mut path_query = PathQuery::new_single_key( start_at_document_path.clone(), start_at_document_key.clone(), ); + if is_proof_subset { + // Inside a page proof this one-key lookup is merged with the main + // query, and grovedb's merge needs every input to walk the same + // way, so the prover emits the cursor layer in the page's + // `orderBy` direction (see `construct_path_query_operations`). + // A V1 layer proof only verifies in the op family of the + // direction it is read in, so read it the same way here. A single + // key decodes identically either way; this only selects the op + // family, and the direction never depends on the cursor document. + path_query.query.query.left_to_right = self + .construct_path_query(None, platform_version)? + .query + .query + .left_to_right; + } let (root_hash, mut proved_key_values) = if is_proof_subset { GroveDb::verify_subset_query(proof, &path_query, &platform_version.drive.grove_version)? } else { diff --git a/packages/rs-drive/src/verify/shielded/verify_shielded_pool_state/v0/mod.rs b/packages/rs-drive/src/verify/shielded/verify_shielded_pool_state/v0/mod.rs index c9028c29db3..0a1f202f7f7 100644 --- a/packages/rs-drive/src/verify/shielded/verify_shielded_pool_state/v0/mod.rs +++ b/packages/rs-drive/src/verify/shielded/verify_shielded_pool_state/v0/mod.rs @@ -91,7 +91,8 @@ mod tests { pool_path.clone(), vec![SHIELDED_TOTAL_BALANCE_KEY], Element::new_sum_item(balance as i64), - ); + ) + .dont_check_for_backwards_references(); drive .grove_apply_batch( diff --git a/packages/rs-drive/src/verify/system/verify_elements/v0/mod.rs b/packages/rs-drive/src/verify/system/verify_elements/v0/mod.rs index c03c15b4176..46dba77a198 100644 --- a/packages/rs-drive/src/verify/system/verify_elements/v0/mod.rs +++ b/packages/rs-drive/src/verify/system/verify_elements/v0/mod.rs @@ -37,7 +37,9 @@ impl Drive { keys: Vec>, platform_version: &PlatformVersion, ) -> Result<(RootHash, BTreeMap, Option>), Error> { - let mut query = Query::new(); + // Match prove_elements_v0: Query::default() emits a right-to-left proof. + // GroveDB verifies that the proof operation family matches this direction. + let mut query = Query::new_with_direction(false); query.insert_keys(keys); let path_query = PathQuery::new(path, SizedQuery::new(query, None, None)); diff --git a/packages/rs-drive/tests/drive_storage_ops_coverage.rs b/packages/rs-drive/tests/drive_storage_ops_coverage.rs index 25ea15b592e..6403e728fec 100644 --- a/packages/rs-drive/tests/drive_storage_ops_coverage.rs +++ b/packages/rs-drive/tests/drive_storage_ops_coverage.rs @@ -968,7 +968,8 @@ mod grovedb_op_batch_tests { fn push_increases_len() { let mut batch = GroveDbOpBatch::new(); let op = - QualifiedGroveDbOp::insert_or_replace_op(vec![vec![1]], vec![2], Element::empty_tree()); + QualifiedGroveDbOp::insert_or_replace_op(vec![vec![1]], vec![2], Element::empty_tree()) + .dont_check_for_backwards_references(); batch.push(op); assert_eq!(batch.len(), 1); assert!(!batch.is_empty()); @@ -977,8 +978,10 @@ mod grovedb_op_batch_tests { #[test] fn from_operations() { let ops = vec![ - QualifiedGroveDbOp::insert_or_replace_op(vec![vec![1]], vec![2], Element::empty_tree()), - QualifiedGroveDbOp::insert_or_replace_op(vec![vec![3]], vec![4], Element::empty_tree()), + QualifiedGroveDbOp::insert_or_replace_op(vec![vec![1]], vec![2], Element::empty_tree()) + .dont_check_for_backwards_references(), + QualifiedGroveDbOp::insert_or_replace_op(vec![vec![3]], vec![4], Element::empty_tree()) + .dont_check_for_backwards_references(), ]; let batch = GroveDbOpBatch::from_operations(ops); assert_eq!(batch.len(), 2); @@ -1002,8 +1005,10 @@ mod grovedb_op_batch_tests { fn extend_adds_operations() { let mut batch = GroveDbOpBatch::new(); let ops = vec![ - QualifiedGroveDbOp::insert_or_replace_op(vec![vec![1]], vec![2], Element::empty_tree()), - QualifiedGroveDbOp::insert_or_replace_op(vec![vec![3]], vec![4], Element::empty_tree()), + QualifiedGroveDbOp::insert_or_replace_op(vec![vec![1]], vec![2], Element::empty_tree()) + .dont_check_for_backwards_references(), + QualifiedGroveDbOp::insert_or_replace_op(vec![vec![3]], vec![4], Element::empty_tree()) + .dont_check_for_backwards_references(), ]; batch.extend(ops); assert_eq!(batch.len(), 2); diff --git a/packages/rs-drive/tests/query_tests.rs b/packages/rs-drive/tests/query_tests.rs index de895e70f2e..59d47298a03 100644 --- a/packages/rs-drive/tests/query_tests.rs +++ b/packages/rs-drive/tests/query_tests.rs @@ -8167,6 +8167,97 @@ mod tests { } #[cfg(all(feature = "server", feature = "verify"))] + #[test] + fn test_proved_primary_key_cursor_pages_in_both_directions() { + // A `$id`-ordered page with a cursor merges the cursor lookup and the + // page query at the same path: the primary-key tree. The merge then has + // no synthesized root above the page query, so the document layer must + // keep the requested direction in the proof; the verifier reads both + // the cursor lookup and the page in that direction, and GroveDB refuses + // a V1 layer proof read in the other op family. + use dpp::document::DocumentV0Getters; + use dpp::prelude::Identifier; + use platform_value::string_encoding::Encoding; + + let platform_version = PlatformVersion::latest(); + let (drive, contract) = setup_family_tests(10, 73509, platform_version); + let person_document_type = contract + .document_type_for_name("person") + .expect("contract should have a person document type"); + let root_hash = drive + .grove + .root_hash(None, &platform_version.drive.grove_version) + .unwrap() + .expect("there is always a root hash"); + + let ids_of = |results: &[Vec]| -> Vec { + results + .iter() + .map(|bytes| { + Document::from_bytes(bytes, person_document_type, platform_version) + .expect("we should be able to deserialize the document") + .id() + }) + .collect() + }; + let build = |query_value: serde_json::Value| { + let cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None) + .expect("expected to serialize to cbor"); + DriveDocumentQuery::from_cbor( + cbor.as_slice(), + &contract, + person_document_type, + &drive.config, + platform_version, + ) + .expect("query should be built") + }; + + let (all_results, _, _) = build(json!({ + "limit": 100, + "orderBy": [["$id", "asc"]], + })) + .execute_raw_results_no_proof(&drive, None, None, platform_version) + .expect("query should be executed"); + let ascending_ids = ids_of(&all_results); + assert_eq!(ascending_ids.len(), 10); + + for (ascending, included) in [(true, true), (true, false), (false, true), (false, false)] { + let ordered: Vec = if ascending { + ascending_ids.clone() + } else { + ascending_ids.iter().rev().cloned().collect() + }; + let cursor = ordered[3]; + let expected: Vec = if included { + ordered[3..6].to_vec() + } else { + ordered[4..7].to_vec() + }; + let cursor_key = if included { "startAt" } else { "startAfter" }; + let case = format!( + "orderBy $id {} with {cursor_key}", + if ascending { "asc" } else { "desc" } + ); + + let query = build(json!({ + cursor_key: cursor.to_string(Encoding::Base58), + "limit": 3, + "orderBy": [["$id", if ascending { "asc" } else { "desc" }]], + })); + let (results, _, _) = query + .execute_raw_results_no_proof(&drive, None, None, platform_version) + .expect("query should be executed"); + assert_eq!(ids_of(&results), expected, "{case}: unproved page"); + + let (proof_root_hash, proof_results, _) = query + .execute_with_proof_only_get_elements(&drive, None, None, platform_version) + .unwrap_or_else(|e| panic!("{case}: proved page should verify: {e}")); + assert_eq!(root_hash, proof_root_hash, "{case}: proof root hash"); + assert_eq!(results, proof_results, "{case}: proved page"); + } + } + #[test] fn test_proved_desc_range_continuation_page_includes_cursor_document() { // Issue #4540: a continuation page over a non-unique diff --git a/packages/rs-drive/tests/query_tests_history.rs b/packages/rs-drive/tests/query_tests_history.rs index a92fad69c74..604658a97f0 100644 --- a/packages/rs-drive/tests/query_tests_history.rs +++ b/packages/rs-drive/tests/query_tests_history.rs @@ -256,6 +256,98 @@ fn test_setup() { setup(10, Some(range_inserts), 73509, platform_version); } +#[cfg(all(feature = "server", feature = "verify"))] +#[test] +fn test_proved_primary_key_cursor_pages_over_history_in_both_directions() { + // The history-keeping twin of the primary-key cursor test in + // query_tests.rs. Here the cursor lookup lands one level below the page + // query (`.../0/` with key `[0]`), so the merge point is the page + // query's own root layer: the document-id layer must keep the requested + // direction in the proof and the cursor must not claim a second slot. + use dpp::document::DocumentV0Getters; + use dpp::platform_value::string_encoding::Encoding; + use dpp::prelude::Identifier; + use drive::query::DriveDocumentQuery; + + let platform_version = PlatformVersion::latest(); + let (drive, contract) = setup(10, None, 73509, platform_version); + let person_document_type = contract + .document_type_for_name("person") + .expect("contract should have a person document type"); + let root_hash = drive + .grove + .root_hash(None, &platform_version.drive.grove_version) + .unwrap() + .expect("there is always a root hash"); + + let ids_of = |results: &[Vec]| -> Vec { + results + .iter() + .map(|bytes| { + Document::from_bytes(bytes, person_document_type, platform_version) + .expect("we should be able to deserialize the document") + .id() + }) + .collect() + }; + let build = |query_value: serde_json::Value| { + let cbor = cbor_serializer::serializable_value_to_cbor(&query_value, None) + .expect("expected to serialize to cbor"); + DriveDocumentQuery::from_cbor( + cbor.as_slice(), + &contract, + person_document_type, + &drive.config, + platform_version, + ) + .expect("query should be built") + }; + + let (all_results, _, _) = build(json!({ + "limit": 100, + "orderBy": [["$id", "asc"]], + })) + .execute_raw_results_no_proof(&drive, None, None, platform_version) + .expect("query should be executed"); + let ascending_ids = ids_of(&all_results); + assert_eq!(ascending_ids.len(), 10); + + for (ascending, included) in [(true, true), (true, false), (false, true), (false, false)] { + let ordered: Vec = if ascending { + ascending_ids.clone() + } else { + ascending_ids.iter().rev().cloned().collect() + }; + let cursor = ordered[3]; + let expected: Vec = if included { + ordered[3..6].to_vec() + } else { + ordered[4..7].to_vec() + }; + let cursor_key = if included { "startAt" } else { "startAfter" }; + let case = format!( + "history orderBy $id {} with {cursor_key}", + if ascending { "asc" } else { "desc" } + ); + + let query = build(json!({ + cursor_key: cursor.to_string(Encoding::Base58), + "limit": 3, + "orderBy": [["$id", if ascending { "asc" } else { "desc" }]], + })); + let (results, _, _) = query + .execute_raw_results_no_proof(&drive, None, None, platform_version) + .expect("query should be executed"); + assert_eq!(ids_of(&results), expected, "{case}: unproved page"); + + let (proof_root_hash, proof_results, _) = query + .execute_with_proof_only_get_elements(&drive, None, None, platform_version) + .unwrap_or_else(|e| panic!("{case}: proved page should verify: {e}")); + assert_eq!(root_hash, proof_root_hash, "{case}: proof root hash"); + assert_eq!(results, proof_results, "{case}: proved page"); + } +} + #[cfg(feature = "server")] #[test] fn test_query_historical_first_platform_version() { diff --git a/packages/rs-platform-serialization/Cargo.toml b/packages/rs-platform-serialization/Cargo.toml index 7f83bc4226e..d55316ffc6e 100644 --- a/packages/rs-platform-serialization/Cargo.toml +++ b/packages/rs-platform-serialization/Cargo.toml @@ -8,5 +8,5 @@ rust-version.workspace = true license = "MIT" [dependencies] -bincode = { version = "=2.0.1", features = ["serde"] } +bincode = { workspace = true, features = ["serde"] } platform-version = { path = "../rs-platform-version" } diff --git a/packages/rs-platform-value/Cargo.toml b/packages/rs-platform-value/Cargo.toml index fda79d9f595..73cfd8fb8a9 100644 --- a/packages/rs-platform-value/Cargo.toml +++ b/packages/rs-platform-value/Cargo.toml @@ -8,7 +8,7 @@ rust-version.workspace = true license = "MIT" [dependencies] -bincode = { version = "=2.0.1", features = ["serde"] } +bincode = { workspace = true, features = ["serde"] } ciborium = { version = "0.2.2", optional = true } thiserror = "2.0.12" bs58 = "0.5.1" diff --git a/packages/rs-platform-version/Cargo.toml b/packages/rs-platform-version/Cargo.toml index 363b9490c19..94951daa007 100644 --- a/packages/rs-platform-version/Cargo.toml +++ b/packages/rs-platform-version/Cargo.toml @@ -9,9 +9,9 @@ license = "MIT" [dependencies] thiserror = { version = "2.0.12" } -bincode = { version = "=2.0.1" } +bincode = { workspace = true } versioned-feature-core = "1.0.0" -grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e" } +grovedb-version = { git = "https://github.com/dashpay/grovedb", rev = "6816457d2b2df98653f286bf9a374f236a17748f" } [features] mock-versions = [] diff --git a/packages/rs-platform-wallet-ffi/Cargo.toml b/packages/rs-platform-wallet-ffi/Cargo.toml index 9b8f9d279b1..83cd3fbb4cd 100644 --- a/packages/rs-platform-wallet-ffi/Cargo.toml +++ b/packages/rs-platform-wallet-ffi/Cargo.toml @@ -36,7 +36,7 @@ async-trait = "0.1" # Bincode used to serialize RootExtendedPubKey / ExtendedPubKey across # FFI for watch-only restore. Same version pinned elsewhere in workspace. -bincode = { version = "=2.0.1" } +bincode = { workspace = true } # Hex used for error diagnostics that include a wallet_id. hex = "0.4" diff --git a/packages/rs-platform-wallet-storage/Cargo.toml b/packages/rs-platform-wallet-storage/Cargo.toml index 87fc5a7977a..63e7491e009 100644 --- a/packages/rs-platform-wallet-storage/Cargo.toml +++ b/packages/rs-platform-wallet-storage/Cargo.toml @@ -60,7 +60,7 @@ time = { version = "=0.3.49", features = ["parsing"], optional = true } # (which derives bincode 2 `Encode`/`Decode`) and decode # `dpp::AssetLockProof` from the asset-lock blob column. Exact-pinned to # the lock-resolved version to match the crate's `=`-pin discipline. -bincode = { version = "=2.0.1", optional = true } +bincode = { workspace = true, optional = true, features = ["serde"] } tempfile = { version = "3", optional = true } chrono = { version = "0.4", default-features = false, features = [ "clock", diff --git a/packages/rs-platform-wallet/Cargo.toml b/packages/rs-platform-wallet/Cargo.toml index f71439ea73d..f4e5d000787 100644 --- a/packages/rs-platform-wallet/Cargo.toml +++ b/packages/rs-platform-wallet/Cargo.toml @@ -61,7 +61,7 @@ zeroize = "1" log = "0.4" # Shielded pool (optional, behind `shielded` feature) -grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e", optional = true } +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "6816457d2b2df98653f286bf9a374f236a17748f", optional = true } # Direct `rusqlite` access so `FileBackedShieldedStore::open_path` can set # WAL + synchronous=NORMAL pragmas before handing the connection to # `ClientPersistentCommitmentTree`. Version locked to match the rev grovedb diff --git a/packages/rs-sdk-ffi/Cargo.toml b/packages/rs-sdk-ffi/Cargo.toml index e603e523b9d..a25212abc97 100644 --- a/packages/rs-sdk-ffi/Cargo.toml +++ b/packages/rs-sdk-ffi/Cargo.toml @@ -47,7 +47,7 @@ dash-network = { workspace = true, features = ["ffi"] } # FFI and serialization serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -bincode = { version = "=2.0.1", features = ["serde"] } +bincode = { workspace = true, features = ["serde"] } # Async runtime tokio = { version = "1.41", features = ["rt-multi-thread", "macros", "sync", "time"] } diff --git a/packages/rs-sdk-ffi/src/system/queries/path_elements.rs b/packages/rs-sdk-ffi/src/system/queries/path_elements.rs index 96466024445..93eaa248b66 100644 --- a/packages/rs-sdk-ffi/src/system/queries/path_elements.rs +++ b/packages/rs-sdk-ffi/src/system/queries/path_elements.rs @@ -156,19 +156,29 @@ fn get_path_elements( /// `NonCounted` and `NotSummed` are transparent wrappers around another /// element; we render them as `non_counted()` / `not_summed()` /// so that the wrapped element's value is still visible to the caller. +/// Backward-reference metadata does not change the rendered payload; the +/// `type` field identifies the variants that support it. fn format_element_data(element: &Element) -> String { match element { - Element::Item(data, _) => hex::encode(data), + Element::Item(data, _) | Element::ItemWithBackwardsReferences(data, _, _) => { + hex::encode(data) + } Element::Reference(reference, _, _) => format!("{:?}", reference), + Element::BidirectionalReference(reference, _) => { + format!("{:?}", reference.forward_reference_path) + } Element::Tree(_, _) => "tree".to_string(), Element::SumTree(_, _, _) => "sum_tree".to_string(), - Element::SumItem(value, _) => format!("sum_item:{}", value), + Element::SumItem(value, _) | Element::SumItemWithBackwardsReferences(value, _, _) => { + format!("sum_item:{}", value) + } Element::BigSumTree(_, value, _) => format!("big_sum_tree:{}", value), Element::CountTree(_, count, _) => format!("count_tree:{}", count), Element::CountSumTree(_, count, sum, _) => { format!("count_sum_tree:{}:{}", count, sum) } - Element::ItemWithSumItem(data, sum, _) => { + Element::ItemWithSumItem(data, sum, _) + | Element::ItemWithSumItemWithBackwardsReferences(data, sum, _, _) => { format!("item_with_sum_item:{}:{}", hex::encode(data), sum) } Element::ReferenceWithSumItem(reference, _, sum, _) => { @@ -218,6 +228,16 @@ fn format_element_type(element: &Element) -> String { match element { Element::Item(_, _) => "item".to_string(), Element::Reference(_, _, _) => "reference".to_string(), + Element::BidirectionalReference(_, _) => "bidirectional_reference".to_string(), + Element::ItemWithBackwardsReferences(_, _, _) => { + "item_with_backwards_references".to_string() + } + Element::SumItemWithBackwardsReferences(_, _, _) => { + "sum_item_with_backwards_references".to_string() + } + Element::ItemWithSumItemWithBackwardsReferences(_, _, _, _) => { + "item_with_sum_item_with_backwards_references".to_string() + } Element::Tree(_, _) => "tree".to_string(), Element::SumTree(_, _, _) => "sum_tree".to_string(), Element::SumItem(_, _) => "sum_item".to_string(), @@ -257,6 +277,49 @@ fn format_element_type(element: &Element) -> String { mod tests { use super::*; use crate::test_utils::test_utils::create_mock_sdk_handle; + use dash_sdk::drive::grovedb::element::reference_path::ReferencePathType; + + #[test] + fn should_preserve_payload_rendering_for_backward_reference_variants() { + let path = ReferencePathType::SiblingReference(b"target".to_vec()); + let cases = [ + ( + Element::new_bidirectional_reference_with_options( + path.clone(), + Some(4), + true, + None, + ), + Element::Reference(path, Some(4), None), + "bidirectional_reference", + ), + ( + Element::ItemWithBackwardsReferences(vec![0, 255], Default::default(), None), + Element::Item(vec![0, 255], None), + "item_with_backwards_references", + ), + ( + Element::SumItemWithBackwardsReferences(-42, Default::default(), None), + Element::SumItem(-42, None), + "sum_item_with_backwards_references", + ), + ( + Element::ItemWithSumItemWithBackwardsReferences( + vec![0, 255], + -42, + Default::default(), + None, + ), + Element::ItemWithSumItem(vec![0, 255], -42, None), + "item_with_sum_item_with_backwards_references", + ), + ]; + + for (element, base, expected_type) in cases { + assert_eq!(format_element_data(&element), format_element_data(&base)); + assert_eq!(format_element_type(&element), expected_type); + } + } #[test] fn test_get_path_elements_null_handle() { diff --git a/packages/rs-sdk/Cargo.toml b/packages/rs-sdk/Cargo.toml index 3a142158e1b..a307441b67a 100644 --- a/packages/rs-sdk/Cargo.toml +++ b/packages/rs-sdk/Cargo.toml @@ -18,7 +18,7 @@ drive = { path = "../rs-drive", default-features = false, features = [ ] } drive-proof-verifier = { path = "../rs-drive-proof-verifier", default-features = false } -grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "6fc7e1e82de27a56c3428c0d5dd15b5f6a0ea23e", features = [ +grovedb-commitment-tree = { git = "https://github.com/dashpay/grovedb", rev = "6816457d2b2df98653f286bf9a374f236a17748f", features = [ "client", "sqlite", ], optional = true } diff --git a/packages/simple-signer/Cargo.toml b/packages/simple-signer/Cargo.toml index b95f827d797..089fae064ff 100644 --- a/packages/simple-signer/Cargo.toml +++ b/packages/simple-signer/Cargo.toml @@ -20,7 +20,7 @@ dpp = { path = "../rs-dpp", default-features = false, features = [ "ed25519-dalek", ] } async-trait = { version = "0.1.79" } -bincode = { version = "=2.0.1", features = ["serde"] } +bincode = { workspace = true, features = ["serde"] } base64 = { version = "0.22.1" } hex = { version = "0.4.3" } tracing = "0.1.41" diff --git a/packages/strategy-tests/Cargo.toml b/packages/strategy-tests/Cargo.toml index 5e7b2b71a1b..06a052a4f10 100644 --- a/packages/strategy-tests/Cargo.toml +++ b/packages/strategy-tests/Cargo.toml @@ -12,7 +12,7 @@ license = "MIT" [dependencies] tracing = "0.1.41" -bincode = { version = "=2.0.1", features = ["serde"] } +bincode = { workspace = true, features = ["serde"] } drive = { path = "../rs-drive", default-features = false, features = [ "verify", ] } diff --git a/packages/wasm-dpp/Cargo.toml b/packages/wasm-dpp/Cargo.toml index 859c8474525..23864d7e170 100644 --- a/packages/wasm-dpp/Cargo.toml +++ b/packages/wasm-dpp/Cargo.toml @@ -48,7 +48,7 @@ anyhow = { version = "1.0.75" } # required, cargo-machete false positive wasm-bindgen-futures = "0.4.58" async-trait = "0.1.59" -bincode = { version = "=2.0.1" } +bincode = { workspace = true } [package.metadata.cargo-machete] ignored = ["wasm-bindgen-futures"] diff --git a/packages/wasm-dpp2/Cargo.toml b/packages/wasm-dpp2/Cargo.toml index 7af47f47f09..d405cffcacb 100644 --- a/packages/wasm-dpp2/Cargo.toml +++ b/packages/wasm-dpp2/Cargo.toml @@ -10,7 +10,7 @@ crate-type = ["cdylib", "lib"] # TODO: Consider to use talc allocator #talc = { version = "=4.4.2", default-features = false, features = ["lock_api"] } async-trait = { version = "0.1.79" } -bincode = "=2.0.1" +bincode = { workspace = true, features = ["serde"] } wasm-bindgen = { version = "=0.2.108", default-features = false, features = [ "serde-serialize", ] } diff --git a/packages/wasm-drive-verify/Cargo.toml b/packages/wasm-drive-verify/Cargo.toml index 9868a27466b..ae145a41b8f 100644 --- a/packages/wasm-drive-verify/Cargo.toml +++ b/packages/wasm-drive-verify/Cargo.toml @@ -20,7 +20,7 @@ dpp = { path = "../rs-dpp", default-features = false, features = [ "platform-value-json", ] } -bincode = { version = "=2.0.1" } +bincode = { workspace = true } wasm-bindgen = { version = "=0.2.108" } serde = { version = "1.0.193", default-features = false, features = [ "alloc", diff --git a/packages/wasm-sdk/src/queries/system.rs b/packages/wasm-sdk/src/queries/system.rs index 1051361908f..0f068698282 100644 --- a/packages/wasm-sdk/src/queries/system.rs +++ b/packages/wasm-sdk/src/queries/system.rs @@ -29,6 +29,10 @@ export type GroveElementType = | "provableCountTree" | "itemWithSumItem" | "referenceWithSumItem" + | "bidirectionalReference" + | "itemWithBackwardsReferences" + | "sumItemWithBackwardsReferences" + | "itemWithSumItemWithBackwardsReferences" | "provableCountSumTree" | "provableCountProvableSumTree" | "provableSumTree" @@ -857,8 +861,10 @@ fn set_js_property(object: &Object, property: &str, value: &JsValue) -> Result<( fn element_value_bytes(element: &Element) -> Option> { match element { - Element::Item(bytes, _) => Some(bytes.clone()), - Element::ItemWithSumItem(bytes, _, _) => Some(bytes.clone()), + Element::Item(bytes, _) + | Element::ItemWithBackwardsReferences(bytes, _, _) + | Element::ItemWithSumItem(bytes, _, _) + | Element::ItemWithSumItemWithBackwardsReferences(bytes, _, _, _) => Some(bytes.clone()), Element::NonCounted(inner) | Element::NotSummed(inner) | Element::NotCountedOrSummed(inner) => element_value_bytes(inner), @@ -868,7 +874,9 @@ fn element_value_bytes(element: &Element) -> Option> { fn element_sum(element: &Element) -> Option { match element { - Element::SumItem(sum, _) => Some(*sum as i128), + Element::SumItem(sum, _) + | Element::SumItemWithBackwardsReferences(sum, _, _) + | Element::ItemWithSumItemWithBackwardsReferences(_, sum, _, _) => Some(*sum as i128), Element::SumTree(_, sum, _) => Some(*sum as i128), Element::BigSumTree(_, sum, _) => Some(*sum), Element::CountSumTree(_, _, sum, _) => Some(*sum as i128), @@ -901,16 +909,21 @@ fn element_reference_target( ) -> (Option>>, Option) { match element { Element::Reference(reference_path, _, _) - | Element::ReferenceWithSumItem(reference_path, _, _, _) => { - match path_from_reference_path_type(reference_path.clone(), parent_path, Some(key)) { - Ok(target) => (Some(target), None), - Err(error) => { - let message = error.to_string(); - tracing::warn!("failed to resolve GroveDB reference target: {}", message); - (None, Some(message)) - } + | Element::ReferenceWithSumItem(reference_path, _, _, _) + | Element::BidirectionalReference( + dash_sdk::drive::grovedb::element::BidirectionalReference { + forward_reference_path: reference_path, + .. + }, + _, + ) => match path_from_reference_path_type(reference_path.clone(), parent_path, Some(key)) { + Ok(target) => (Some(target), None), + Err(error) => { + let message = error.to_string(); + tracing::warn!("failed to resolve GroveDB reference target: {}", message); + (None, Some(message)) } - } + }, Element::NonCounted(inner) | Element::NotSummed(inner) | Element::NotCountedOrSummed(inner) => element_reference_target(inner, parent_path, key), @@ -920,6 +933,12 @@ fn element_reference_target( fn element_type_name(element: &Element) -> &'static str { match element { + Element::BidirectionalReference(_, _) => "bidirectionalReference", + Element::ItemWithBackwardsReferences(_, _, _) => "itemWithBackwardsReferences", + Element::SumItemWithBackwardsReferences(_, _, _) => "sumItemWithBackwardsReferences", + Element::ItemWithSumItemWithBackwardsReferences(_, _, _, _) => { + "itemWithSumItemWithBackwardsReferences" + } Element::Item(_, _) => "item", Element::Reference(_, _, _) => "reference", Element::Tree(_, _) => "tree", @@ -953,6 +972,11 @@ fn element_type_name(element: &Element) -> &'static str { fn non_counted_element_type_name(element: &Element) -> &'static str { match element { + // GroveDB rejects aggregation wrappers around these variants. + Element::BidirectionalReference(_, _) + | Element::ItemWithBackwardsReferences(_, _, _) + | Element::SumItemWithBackwardsReferences(_, _, _) + | Element::ItemWithSumItemWithBackwardsReferences(_, _, _, _) => element_type_name(element), Element::Item(_, _) => "nonCountedItem", Element::Reference(_, _, _) => "nonCountedReference", Element::Tree(_, _) => "nonCountedTree", @@ -1734,6 +1758,35 @@ mod tests { use super::*; use dash_sdk::drive::grovedb::element::reference_path::ReferencePathType; + #[test] + fn should_render_bidirectional_elements_without_losing_payloads() { + let item = Element::new_item_allowing_bidirectional_references(vec![1, 2]); + let sum = Element::new_sum_item_allowing_bidirectional_references(-3); + let combined = + Element::new_item_with_sum_item_allowing_bidirectional_references(vec![4, 5], 6); + let reference = Element::new_bidirectional_reference(ReferencePathType::SiblingReference( + b"target".to_vec(), + )); + let union = typescript_element_type_union(); + for (element, name) in [ + (&item, "itemWithBackwardsReferences"), + (&sum, "sumItemWithBackwardsReferences"), + (&combined, "itemWithSumItemWithBackwardsReferences"), + (&reference, "bidirectionalReference"), + ] { + assert_eq!(element_type_name(element), name); + assert!(union.contains(&format!("\"{name}\""))); + } + assert_eq!(element_value_bytes(&item), Some(vec![1, 2])); + assert_eq!(element_sum(&sum), Some(-3)); + assert_eq!(element_value_bytes(&combined), Some(vec![4, 5])); + assert_eq!(element_sum(&combined), Some(6)); + assert_eq!( + element_reference_target(&reference, &[b"parent".to_vec()], b"source"), + (Some(vec![b"parent".to_vec(), b"target".to_vec()]), None), + ); + } + #[test] fn should_decode_raw_bytes_without_utf8_expansion() { let input = [0x80, 0xff];