diff --git a/Cargo.lock b/Cargo.lock index 8b80e6dcc03..33bcc76f18c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,7 +120,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -131,7 +131,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -857,7 +857,7 @@ checksum = "3fce8dd7fcfcbf3a0a87d8f515194b49d6135acab73e18bd380d1d93bb1a15eb" dependencies = [ "clap", "heck 0.4.1", - "indexmap 2.13.0", + "indexmap 2.13.1", "log", "proc-macro2", "quote", @@ -876,7 +876,7 @@ checksum = "befbfd072a8e81c02f8c507aefce431fe5e7d051f83d48a23ffc9b9fe5a11799" dependencies = [ "clap", "heck 0.5.0", - "indexmap 2.13.0", + "indexmap 2.13.1", "log", "proc-macro2", "quote", @@ -889,9 +889,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.58" +version = "1.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1" +checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" dependencies = [ "find-msvc-tools", "jobserver", @@ -1114,7 +1114,7 @@ version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -1620,7 +1620,7 @@ dependencies = [ "futures", "hex", "hickory-resolver", - "indexmap 2.13.0", + "indexmap 2.13.1", "key-wallet", "key-wallet-manager", "log", @@ -1927,7 +1927,7 @@ dependencies = [ "getrandom 0.2.17", "grovedb-commitment-tree", "hex", - "indexmap 2.13.0", + "indexmap 2.13.1", "integer-encoding", "itertools 0.13.0", "json-schema-compatibility-validator", @@ -1991,7 +1991,7 @@ dependencies = [ "grovedb-storage", "grovedb-version", "hex", - "indexmap 2.13.0", + "indexmap 2.13.1", "integer-encoding", "intmap", "itertools 0.13.0", @@ -2035,7 +2035,7 @@ dependencies = [ "file-rotate", "grovedb-commitment-tree", "hex", - "indexmap 2.13.0", + "indexmap 2.13.1", "integer-encoding", "itertools 0.13.0", "lazy_static", @@ -2078,7 +2078,7 @@ dependencies = [ "dpp", "drive", "hex", - "indexmap 2.13.0", + "indexmap 2.13.1", "platform-serialization", "platform-serialization-derive", "serde", @@ -2285,7 +2285,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -2466,9 +2466,12 @@ dependencies = [ [[package]] name = "fragile" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" +checksum = "8878864ba14bb86e818a412bfd6f18f9eabd4ec0f008a28e8f7eb61db532fcf9" +dependencies = [ + "futures-core", +] [[package]] name = "fs_extra" @@ -2714,7 +2717,7 @@ dependencies = [ "grovedbg-types", "hex", "hex-literal", - "indexmap 2.13.0", + "indexmap 2.13.1", "integer-encoding", "intmap", "itertools 0.14.0", @@ -2829,7 +2832,7 @@ dependencies = [ "grovedb-version", "grovedb-visualize", "hex", - "indexmap 2.13.0", + "indexmap 2.13.1", "integer-encoding", "num_cpus", "rand 0.10.0", @@ -2866,7 +2869,7 @@ dependencies = [ "grovedb-costs", "grovedb-storage", "hex", - "indexmap 2.13.0", + "indexmap 2.13.1", "integer-encoding", "thiserror 2.0.18", ] @@ -2929,7 +2932,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.13.0", + "indexmap 2.13.1", "slab", "tokio", "tokio-util", @@ -3262,9 +3265,9 @@ checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" [[package]] name = "hyper" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ "atomic-waker", "bytes", @@ -3277,7 +3280,6 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -3347,7 +3349,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.3", "system-configuration", "tokio", "tower-service", @@ -3381,12 +3383,13 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", + "utf8_iter", "yoke", "zerofrom", "zerovec", @@ -3394,9 +3397,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -3407,9 +3410,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -3421,15 +3424,15 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ "icu_collections", "icu_locale_core", @@ -3441,15 +3444,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", @@ -3531,9 +3534,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -3603,7 +3606,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -3923,9 +3926,9 @@ checksum = "744a4c881f502e98c2241d2e5f50040ac73b30194d64452bb6260393b53f0dc9" [[package]] name = "libc" -version = "0.2.183" +version = "0.2.184" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" [[package]] name = "libloading" @@ -3993,9 +3996,9 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "lock_api" @@ -4132,7 +4135,7 @@ dependencies = [ "http-body-util", "hyper", "hyper-util", - "indexmap 2.13.0", + "indexmap 2.13.1", "ipnet", "metrics", "metrics-util", @@ -4337,7 +4340,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -4700,7 +4703,7 @@ checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ "fixedbitset", "hashbrown 0.15.5", - "indexmap 2.13.0", + "indexmap 2.13.1", ] [[package]] @@ -4767,12 +4770,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - [[package]] name = "pkcs8" version = "0.10.2" @@ -4827,7 +4824,7 @@ dependencies = [ "bs58", "ciborium", "hex", - "indexmap 2.13.0", + "indexmap 2.13.1", "platform-serialization", "platform-version", "rand 0.8.5", @@ -4872,7 +4869,7 @@ dependencies = [ "dash-sdk", "dashcore", "dpp", - "indexmap 2.13.0", + "indexmap 2.13.1", "key-wallet", "key-wallet-manager", "platform-encryption", @@ -4950,9 +4947,9 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -5034,7 +5031,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.8+spec-1.1.0", + "toml_edit 0.25.10+spec-1.1.0", ] [[package]] @@ -5109,7 +5106,7 @@ version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "itertools 0.14.0", "log", "multimap", @@ -5268,7 +5265,7 @@ dependencies = [ "quinn-udp", "rustc-hash 2.1.2", "rustls", - "socket2 0.5.10", + "socket2 0.6.3", "thiserror 2.0.18", "tokio", "tracing", @@ -5306,7 +5303,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.3", "tracing", "windows-sys 0.60.2", ] @@ -5853,7 +5850,6 @@ dependencies = [ "dpp", "hex", "platform-version", - "serde_json", ] [[package]] @@ -6032,7 +6028,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -6091,7 +6087,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -6372,7 +6368,7 @@ version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.13.1", "itoa", "memchr", "serde", @@ -6413,9 +6409,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876ac351060d4f882bb1032b6369eb0aef79ad9df1ea8bc404874d8cc3d0cd98" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ "serde_core", ] @@ -6458,7 +6454,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.13.0", + "indexmap 2.13.1", "schemars 0.9.0", "schemars 1.2.1", "serde_core", @@ -6680,7 +6676,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -6912,7 +6908,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix 1.1.4", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -7110,9 +7106,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -7155,9 +7151,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.50.0" +version = "1.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" +checksum = "2bd1c4c0fc4a7ab90fc15ef6daaa3ec3b893f004f915f2392557ed23237820cd" dependencies = [ "bytes", "libc", @@ -7173,9 +7169,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", @@ -7271,9 +7267,9 @@ version = "0.9.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.13.1", "serde_core", - "serde_spanned 1.1.0", + "serde_spanned 1.1.1", "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", @@ -7300,9 +7296,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "1.1.0+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97251a7c317e03ad83774a8752a7e81fb6067740609f75ea2b585b569a59198f" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ "serde_core", ] @@ -7313,7 +7309,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.13.1", "toml_datetime 0.6.11", "winnow 0.5.40", ] @@ -7324,7 +7320,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.13.0", + "indexmap 2.13.1", "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", @@ -7334,21 +7330,21 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.8+spec-1.1.0" +version = "0.25.10+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16bff38f1d86c47f9ff0647e6838d7bb362522bdf44006c7068c2b1e606f1f3c" +checksum = "a82418ca169e235e6c399a84e395ab6debeb3bc90edc959bf0f48647c6a32d1b" dependencies = [ - "indexmap 2.13.0", - "toml_datetime 1.1.0+spec-1.1.0", + "indexmap 2.13.1", + "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", "winnow 1.0.1", ] [[package]] name = "toml_parser" -version = "1.1.0+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ "winnow 1.0.1", ] @@ -7361,9 +7357,9 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "toml_writer" -version = "1.1.0+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d282ade6016312faf3e41e57ebbba0c073e4056dab1232ab1cb624199648f8ed" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "tonic" @@ -7519,7 +7515,7 @@ checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", - "indexmap 2.13.0", + "indexmap 2.13.1", "pin-project-lite", "slab", "sync_wrapper", @@ -8142,7 +8138,7 @@ dependencies = [ "dpp", "drive", "hex", - "indexmap 2.13.0", + "indexmap 2.13.1", "js-sys", "serde", "serde-wasm-bindgen 0.6.5", @@ -8180,7 +8176,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" dependencies = [ "anyhow", - "indexmap 2.13.0", + "indexmap 2.13.1", "wasm-encoder", "wasmparser", ] @@ -8242,7 +8238,7 @@ checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags 2.11.0", "hashbrown 0.15.5", - "indexmap 2.13.0", + "indexmap 2.13.1", "semver", ] @@ -8324,7 +8320,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -8689,7 +8685,7 @@ checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", "heck 0.5.0", - "indexmap 2.13.0", + "indexmap 2.13.1", "prettyplease", "syn 2.0.117", "wasm-metadata", @@ -8720,7 +8716,7 @@ checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", "bitflags 2.11.0", - "indexmap 2.13.0", + "indexmap 2.13.1", "log", "serde", "serde_derive", @@ -8739,7 +8735,7 @@ checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ "anyhow", "id-arena", - "indexmap 2.13.0", + "indexmap 2.13.1", "log", "semver", "serde", @@ -8764,9 +8760,9 @@ dependencies = [ [[package]] name = "writeable" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "wyz" @@ -8791,9 +8787,9 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yoke" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -8802,9 +8798,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", @@ -8855,18 +8851,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", @@ -8920,9 +8916,9 @@ dependencies = [ [[package]] name = "zerotrie" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -8931,9 +8927,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -8942,9 +8938,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", @@ -8964,7 +8960,7 @@ dependencies = [ "flate2", "getrandom 0.3.4", "hmac", - "indexmap 2.13.0", + "indexmap 2.13.1", "lzma-rust2", "memchr", "pbkdf2", @@ -8981,7 +8977,7 @@ checksum = "c42e33efc22a0650c311c2ef19115ce232583abbe80850bc8b66509ebef02de0" dependencies = [ "crc32fast", "flate2", - "indexmap 2.13.0", + "indexmap 2.13.1", "memchr", "typed-path", "zopfli", diff --git a/packages/rs-drive/src/fees/op.rs b/packages/rs-drive/src/fees/op.rs index 58fdc18606e..7ed6bd5be52 100644 --- a/packages/rs-drive/src/fees/op.rs +++ b/packages/rs-drive/src/fees/op.rs @@ -648,3 +648,811 @@ impl DriveCost for OperationCost { .ok_or_else(|| get_overflow_error("ephemeral cost addition overflow")) } } + +#[cfg(test)] +mod tests { + use super::*; + use grovedb_costs::storage_cost::removal::StorageRemovedBytes; + use grovedb_costs::storage_cost::StorageCost; + use platform_version::version::fee::storage::FeeStorageVersion; + use platform_version::version::fee::FeeVersion; + + /// Helper to get the canonical fee version used across these tests. + fn fee_version() -> &'static FeeVersion { + FeeVersion::first() + } + + // --------------------------------------------------------------- + // 1. BaseOp::cost() — spot-check several opcodes + // --------------------------------------------------------------- + + #[test] + fn base_op_stop_costs_zero() { + assert_eq!(BaseOp::Stop.cost(), 0); + } + + #[test] + fn base_op_add_costs_12() { + assert_eq!(BaseOp::Add.cost(), 12); + } + + #[test] + fn base_op_mul_costs_20() { + assert_eq!(BaseOp::Mul.cost(), 20); + } + + #[test] + fn base_op_signextend_costs_20() { + assert_eq!(BaseOp::Signextend.cost(), 20); + } + + #[test] + fn base_op_addmod_costs_32() { + assert_eq!(BaseOp::Addmod.cost(), 32); + } + + #[test] + fn base_op_mulmod_costs_32() { + assert_eq!(BaseOp::Mulmod.cost(), 32); + } + + #[test] + fn base_op_byte_costs_12() { + assert_eq!(BaseOp::Byte.cost(), 12); + } + + #[test] + fn base_op_sub_costs_12() { + assert_eq!(BaseOp::Sub.cost(), 12); + } + + #[test] + fn base_op_div_costs_20() { + assert_eq!(BaseOp::Div.cost(), 20); + } + + #[test] + fn base_op_comparison_ops_all_cost_12() { + for op in [ + BaseOp::Lt, + BaseOp::Gt, + BaseOp::Slt, + BaseOp::Sgt, + BaseOp::Eq, + BaseOp::Iszero, + ] { + assert_eq!(op.cost(), 12, "comparison op {:?} should cost 12", op); + } + } + + #[test] + fn base_op_bitwise_ops_all_cost_12() { + for op in [BaseOp::And, BaseOp::Or, BaseOp::Xor, BaseOp::Not] { + assert_eq!(op.cost(), 12, "bitwise op {:?} should cost 12", op); + } + } + + // --------------------------------------------------------------- + // 2. HashFunction — block_size / rounds / block_cost / base_cost + // --------------------------------------------------------------- + + #[test] + fn hash_function_block_size_all_64() { + // All four hash functions currently have a 64-byte block size. + assert_eq!(HashFunction::Sha256.block_size(), 64); + assert_eq!(HashFunction::Sha256_2.block_size(), 64); + assert_eq!(HashFunction::Blake3.block_size(), 64); + assert_eq!(HashFunction::Sha256RipeMD160.block_size(), 64); + } + + #[test] + fn hash_function_rounds() { + assert_eq!(HashFunction::Sha256.rounds(), 1); + assert_eq!(HashFunction::Sha256_2.rounds(), 2); + assert_eq!(HashFunction::Blake3.rounds(), 1); + assert_eq!(HashFunction::Sha256RipeMD160.rounds(), 1); + } + + #[test] + fn hash_function_block_cost_sha256_variants_use_sha256_per_block() { + let fv = fee_version(); + let expected = fv.hashing.sha256_per_block; + assert_eq!(HashFunction::Sha256.block_cost(fv), expected); + assert_eq!(HashFunction::Sha256_2.block_cost(fv), expected); + assert_eq!(HashFunction::Sha256RipeMD160.block_cost(fv), expected); + } + + #[test] + fn hash_function_block_cost_blake3_uses_blake3_per_block() { + let fv = fee_version(); + assert_eq!( + HashFunction::Blake3.block_cost(fv), + fv.hashing.blake3_per_block + ); + } + + #[test] + fn hash_function_base_cost_sha256() { + let fv = fee_version(); + assert_eq!( + HashFunction::Sha256.base_cost(fv), + fv.hashing.single_sha256_base + ); + } + + #[test] + fn hash_function_base_cost_sha256_2_uses_single_sha256_base() { + let fv = fee_version(); + // Sha256_2 intentionally uses single_sha256_base (extra rounds handle the double hash). + assert_eq!( + HashFunction::Sha256_2.base_cost(fv), + fv.hashing.single_sha256_base + ); + } + + #[test] + fn hash_function_base_cost_blake3() { + let fv = fee_version(); + assert_eq!(HashFunction::Blake3.base_cost(fv), fv.hashing.blake3_base); + } + + #[test] + fn hash_function_base_cost_sha256_ripe_md160() { + let fv = fee_version(); + assert_eq!( + HashFunction::Sha256RipeMD160.base_cost(fv), + fv.hashing.sha256_ripe_md160_base + ); + } + + // --------------------------------------------------------------- + // 3. FunctionOp::new_with_byte_count — verify blocks/rounds calc + // --------------------------------------------------------------- + + #[test] + fn function_op_new_with_byte_count_small_sha256() { + // 32 bytes => blocks = 32/64 + 1 = 1, rounds = 1 + 1 - 1 = 1 + let op = FunctionOp::new_with_byte_count(HashFunction::Sha256, 32); + assert_eq!(op.rounds, 1); + assert_eq!(op.hash, HashFunction::Sha256); + } + + #[test] + fn function_op_new_with_byte_count_exact_block_boundary_sha256() { + // 64 bytes => blocks = 64/64 + 1 = 2, rounds = 2 + 1 - 1 = 2 + let op = FunctionOp::new_with_byte_count(HashFunction::Sha256, 64); + assert_eq!(op.rounds, 2); + } + + #[test] + fn function_op_new_with_byte_count_large_sha256() { + // 200 bytes => blocks = 200/64 + 1 = 3 + 1 = 4, rounds = 4 + 1 - 1 = 4 + let op = FunctionOp::new_with_byte_count(HashFunction::Sha256, 200); + assert_eq!(op.rounds, 4); + } + + #[test] + fn function_op_new_with_byte_count_sha256_2_has_extra_round() { + // 32 bytes => blocks = 32/64 + 1 = 1, rounds = 1 + 2 - 1 = 2 + let op = FunctionOp::new_with_byte_count(HashFunction::Sha256_2, 32); + assert_eq!(op.rounds, 2); + } + + #[test] + fn function_op_new_with_byte_count_sha256_2_large() { + // 200 bytes => blocks = 200/64 + 1 = 4, rounds = 4 + 2 - 1 = 5 + let op = FunctionOp::new_with_byte_count(HashFunction::Sha256_2, 200); + assert_eq!(op.rounds, 5); + } + + #[test] + fn function_op_new_with_byte_count_blake3_small() { + // 10 bytes => blocks = 10/64 + 1 = 1, rounds = 1 + 1 - 1 = 1 + let op = FunctionOp::new_with_byte_count(HashFunction::Blake3, 10); + assert_eq!(op.rounds, 1); + assert_eq!(op.hash, HashFunction::Blake3); + } + + #[test] + fn function_op_new_with_byte_count_blake3_large() { + // 500 bytes => blocks = 500/64 + 1 = 7 + 1 = 8, rounds = 8 + 1 - 1 = 8 + let op = FunctionOp::new_with_byte_count(HashFunction::Blake3, 500); + assert_eq!(op.rounds, 8); + } + + #[test] + fn function_op_new_with_byte_count_zero_bytes() { + // 0 bytes => blocks = 0/64 + 1 = 1, rounds = 1 + 1 - 1 = 1 + let op = FunctionOp::new_with_byte_count(HashFunction::Sha256, 0); + assert_eq!(op.rounds, 1); + } + + #[test] + fn function_op_new_with_byte_count_sha256_ripemd160() { + // 20 bytes => blocks = 20/64 + 1 = 1, rounds = 1 + 1 - 1 = 1 + let op = FunctionOp::new_with_byte_count(HashFunction::Sha256RipeMD160, 20); + assert_eq!(op.rounds, 1); + assert_eq!(op.hash, HashFunction::Sha256RipeMD160); + } + + // --------------------------------------------------------------- + // 4. FunctionOp::cost — verify rounds * block_cost + base_cost + // --------------------------------------------------------------- + + #[test] + fn function_op_cost_sha256_one_round() { + let fv = fee_version(); + let op = FunctionOp::new_with_round_count(HashFunction::Sha256, 1); + // cost = base + rounds * block_cost = 100 + 1 * 5000 = 5100 + let expected = fv.hashing.single_sha256_base + 1 * fv.hashing.sha256_per_block; + assert_eq!(op.cost(fv), expected); + } + + #[test] + fn function_op_cost_sha256_2_two_rounds() { + let fv = fee_version(); + let op = FunctionOp::new_with_round_count(HashFunction::Sha256_2, 2); + // cost = base + rounds * block_cost = 100 + 2 * 5000 = 10100 + let expected = fv.hashing.single_sha256_base + 2 * fv.hashing.sha256_per_block; + assert_eq!(op.cost(fv), expected); + } + + #[test] + fn function_op_cost_blake3_one_round() { + let fv = fee_version(); + let op = FunctionOp::new_with_round_count(HashFunction::Blake3, 1); + // cost = blake3_base + 1 * blake3_per_block = 100 + 300 = 400 + let expected = fv.hashing.blake3_base + 1 * fv.hashing.blake3_per_block; + assert_eq!(op.cost(fv), expected); + } + + #[test] + fn function_op_cost_zero_rounds() { + let fv = fee_version(); + let op = FunctionOp::new_with_round_count(HashFunction::Blake3, 0); + // cost = blake3_base + 0 * blake3_per_block = blake3_base + assert_eq!(op.cost(fv), fv.hashing.blake3_base); + } + + #[test] + fn function_op_cost_from_byte_count_matches_manual_calc() { + let fv = fee_version(); + // 128 bytes of SHA256: blocks = 128/64 + 1 = 3, rounds = 3 + 1 - 1 = 3 + let op = FunctionOp::new_with_byte_count(HashFunction::Sha256, 128); + assert_eq!(op.rounds, 3); + let expected = fv.hashing.single_sha256_base + 3 * fv.hashing.sha256_per_block; + assert_eq!(op.cost(fv), expected); + } + + #[test] + fn function_op_cost_sha256_ripemd160() { + let fv = fee_version(); + let op = FunctionOp::new_with_round_count(HashFunction::Sha256RipeMD160, 1); + let expected = fv.hashing.sha256_ripe_md160_base + 1 * fv.hashing.sha256_per_block; + assert_eq!(op.cost(fv), expected); + } + + #[test] + fn function_op_cost_saturating_mul_does_not_panic_on_large_rounds() { + let fv = fee_version(); + let op = FunctionOp::new_with_round_count(HashFunction::Sha256, u32::MAX); + // u32::MAX as u64 * sha256_per_block (5000) fits in u64 without overflow, + // so cost = base + rounds * block_cost, computed via saturating ops. + let expected_block_cost = (u32::MAX as u64).saturating_mul(fv.hashing.sha256_per_block); + let expected = fv + .hashing + .single_sha256_base + .saturating_add(expected_block_cost); + assert_eq!(op.cost(fv), expected); + } + + #[test] + fn function_op_cost_saturates_to_max_with_extreme_fee_version() { + // Construct a fee version where block_cost is large enough that + // u32::MAX * block_cost overflows u64, triggering saturation. + let mut fv = fee_version().clone(); + fv.hashing.sha256_per_block = u64::MAX; + let op = FunctionOp::new_with_round_count(HashFunction::Sha256, 2); + // 2 * u64::MAX saturates to u64::MAX, then base.saturating_add(u64::MAX) = u64::MAX. + assert_eq!(op.cost(&fv), u64::MAX); + } + + // --------------------------------------------------------------- + // 5. operation_cost() — test all 4 match arms + // --------------------------------------------------------------- + + #[test] + fn operation_cost_calculated_cost_operation_returns_cost() { + let cost = OperationCost { + seek_count: 3, + storage_cost: StorageCost { + added_bytes: 100, + replaced_bytes: 50, + removed_bytes: StorageRemovedBytes::NoStorageRemoval, + }, + storage_loaded_bytes: 200, + hash_node_calls: 5, + sinsemilla_hash_calls: 0, + }; + let op = CalculatedCostOperation(cost.clone()); + let result = op.operation_cost().expect("should return Ok"); + assert_eq!(result, cost); + } + + #[test] + fn operation_cost_grove_operation_returns_error() { + let grove_op = LowLevelDriveOperation::insert_for_known_path_key_element( + vec![vec![1, 2, 3]], + vec![4, 5, 6], + Element::empty_tree(), + ); + let result = grove_op.operation_cost(); + assert!(result.is_err()); + let err_msg = format!("{:?}", result.unwrap_err()); + assert!( + err_msg.contains("grove operations must be executed"), + "unexpected error: {}", + err_msg + ); + } + + #[test] + fn operation_cost_pre_calculated_fee_result_returns_error() { + let fee = FeeResult { + storage_fee: 100, + processing_fee: 200, + ..Default::default() + }; + let op = PreCalculatedFeeResult(fee); + let result = op.operation_cost(); + assert!(result.is_err()); + let err_msg = format!("{:?}", result.unwrap_err()); + assert!( + err_msg.contains("pre calculated fees should not be requested"), + "unexpected error: {}", + err_msg + ); + } + + #[test] + fn operation_cost_function_operation_returns_error() { + let func_op = FunctionOperation(FunctionOp::new_with_round_count(HashFunction::Blake3, 1)); + let result = func_op.operation_cost(); + assert!(result.is_err()); + let err_msg = format!("{:?}", result.unwrap_err()); + assert!( + err_msg.contains("function operations should not be requested"), + "unexpected error: {}", + err_msg + ); + } + + // --------------------------------------------------------------- + // 6. combine_cost_operations — filter and sum + // --------------------------------------------------------------- + + #[test] + fn combine_cost_operations_sums_calculated_costs_only() { + let cost1 = OperationCost { + seek_count: 2, + storage_cost: StorageCost { + added_bytes: 10, + replaced_bytes: 0, + removed_bytes: StorageRemovedBytes::NoStorageRemoval, + }, + storage_loaded_bytes: 50, + hash_node_calls: 1, + sinsemilla_hash_calls: 0, + }; + let cost2 = OperationCost { + seek_count: 3, + storage_cost: StorageCost { + added_bytes: 20, + replaced_bytes: 5, + removed_bytes: StorageRemovedBytes::NoStorageRemoval, + }, + storage_loaded_bytes: 100, + hash_node_calls: 2, + sinsemilla_hash_calls: 1, + }; + + let operations = vec![ + CalculatedCostOperation(cost1.clone()), + // This FunctionOperation should be ignored by combine_cost_operations + FunctionOperation(FunctionOp::new_with_round_count(HashFunction::Sha256, 1)), + CalculatedCostOperation(cost2.clone()), + // PreCalculatedFeeResult should also be ignored + PreCalculatedFeeResult(FeeResult::default()), + ]; + + let combined = LowLevelDriveOperation::combine_cost_operations(&operations); + assert_eq!(combined.seek_count, 2 + 3); + assert_eq!(combined.storage_cost.added_bytes, 10 + 20); + assert_eq!(combined.storage_cost.replaced_bytes, 0 + 5); + assert_eq!(combined.storage_loaded_bytes, 50 + 100); + assert_eq!(combined.hash_node_calls, 1 + 2); + assert_eq!(combined.sinsemilla_hash_calls, 0 + 1); + } + + #[test] + fn combine_cost_operations_empty_list_returns_default() { + let combined = LowLevelDriveOperation::combine_cost_operations(&[]); + assert_eq!(combined, OperationCost::default()); + } + + #[test] + fn combine_cost_operations_no_calculated_costs_returns_default() { + let operations = vec![ + FunctionOperation(FunctionOp::new_with_round_count(HashFunction::Blake3, 2)), + PreCalculatedFeeResult(FeeResult { + processing_fee: 999, + ..Default::default() + }), + ]; + let combined = LowLevelDriveOperation::combine_cost_operations(&operations); + assert_eq!(combined, OperationCost::default()); + } + + // --------------------------------------------------------------- + // 7. grovedb_operations_batch / _consume / _consume_with_leftovers + // --------------------------------------------------------------- + + /// Helper: creates a GroveOperation variant (insert_or_replace). + fn make_grove_op(key_byte: u8) -> LowLevelDriveOperation { + LowLevelDriveOperation::insert_for_known_path_key_element( + vec![vec![0]], + vec![key_byte], + Element::new_item(vec![key_byte]), + ) + } + + fn make_mixed_ops() -> Vec { + vec![ + make_grove_op(1), + FunctionOperation(FunctionOp::new_with_round_count(HashFunction::Sha256, 1)), + make_grove_op(2), + CalculatedCostOperation(OperationCost::default()), + make_grove_op(3), + ] + } + + #[test] + fn grovedb_operations_batch_filters_grove_ops_from_ref() { + let ops = make_mixed_ops(); + let batch = LowLevelDriveOperation::grovedb_operations_batch(&ops); + assert_eq!(batch.len(), 3); + } + + #[test] + fn grovedb_operations_batch_empty_input() { + let batch = LowLevelDriveOperation::grovedb_operations_batch(&[]); + assert!(batch.is_empty()); + } + + #[test] + fn grovedb_operations_batch_no_grove_ops() { + let ops = vec![ + FunctionOperation(FunctionOp::new_with_round_count(HashFunction::Blake3, 1)), + CalculatedCostOperation(OperationCost::default()), + ]; + let batch = LowLevelDriveOperation::grovedb_operations_batch(&ops); + assert!(batch.is_empty()); + } + + #[test] + fn grovedb_operations_batch_consume_filters_grove_ops() { + let ops = make_mixed_ops(); + let batch = LowLevelDriveOperation::grovedb_operations_batch_consume(ops); + assert_eq!(batch.len(), 3); + } + + #[test] + fn grovedb_operations_batch_consume_empty_input() { + let batch = LowLevelDriveOperation::grovedb_operations_batch_consume(vec![]); + assert!(batch.is_empty()); + } + + #[test] + fn grovedb_operations_batch_consume_with_leftovers_partitions_correctly() { + let ops = make_mixed_ops(); + let (batch, leftovers) = + LowLevelDriveOperation::grovedb_operations_batch_consume_with_leftovers(ops); + assert_eq!(batch.len(), 3); + assert_eq!(leftovers.len(), 2); + + // Verify leftovers contain the non-grove operations. + for leftover in &leftovers { + assert!( + !matches!(leftover, GroveOperation(_)), + "leftovers should not contain GroveOperation variants" + ); + } + } + + #[test] + fn grovedb_operations_batch_consume_with_leftovers_all_grove() { + let ops = vec![make_grove_op(10), make_grove_op(20)]; + let (batch, leftovers) = + LowLevelDriveOperation::grovedb_operations_batch_consume_with_leftovers(ops); + assert_eq!(batch.len(), 2); + assert!(leftovers.is_empty()); + } + + #[test] + fn grovedb_operations_batch_consume_with_leftovers_no_grove() { + let ops = vec![ + CalculatedCostOperation(OperationCost::default()), + FunctionOperation(FunctionOp::new_with_round_count(HashFunction::Sha256, 1)), + ]; + let (batch, leftovers) = + LowLevelDriveOperation::grovedb_operations_batch_consume_with_leftovers(ops); + assert!(batch.is_empty()); + assert_eq!(leftovers.len(), 2); + } + + #[test] + fn grovedb_operations_batch_consume_with_leftovers_empty() { + let (batch, leftovers) = + LowLevelDriveOperation::grovedb_operations_batch_consume_with_leftovers(vec![]); + assert!(batch.is_empty()); + assert!(leftovers.is_empty()); + } + + // --------------------------------------------------------------- + // 8. DriveCost::ephemeral_cost — various scenarios + // --------------------------------------------------------------- + + #[test] + fn ephemeral_cost_zero_operation() { + let fv = fee_version(); + let cost = OperationCost::default(); + let result = cost.ephemeral_cost(fv).expect("should not overflow"); + assert_eq!(result, 0); + } + + #[test] + fn ephemeral_cost_seek_only() { + let fv = fee_version(); + let cost = OperationCost { + seek_count: 5, + storage_cost: StorageCost::default(), + storage_loaded_bytes: 0, + hash_node_calls: 0, + sinsemilla_hash_calls: 0, + }; + let result = cost.ephemeral_cost(fv).expect("should not overflow"); + let expected = 5u64 * fv.storage.storage_seek_cost; + assert_eq!(result, expected); + } + + #[test] + fn ephemeral_cost_storage_added_bytes() { + let fv = fee_version(); + let cost = OperationCost { + seek_count: 0, + storage_cost: StorageCost { + added_bytes: 100, + replaced_bytes: 0, + removed_bytes: StorageRemovedBytes::NoStorageRemoval, + }, + storage_loaded_bytes: 0, + hash_node_calls: 0, + sinsemilla_hash_calls: 0, + }; + let result = cost.ephemeral_cost(fv).expect("should not overflow"); + let expected = 100u64 * fv.storage.storage_processing_credit_per_byte; + assert_eq!(result, expected); + } + + #[test] + fn ephemeral_cost_storage_replaced_bytes() { + let fv = fee_version(); + let cost = OperationCost { + seek_count: 0, + storage_cost: StorageCost { + added_bytes: 0, + replaced_bytes: 50, + removed_bytes: StorageRemovedBytes::NoStorageRemoval, + }, + storage_loaded_bytes: 0, + hash_node_calls: 0, + sinsemilla_hash_calls: 0, + }; + let result = cost.ephemeral_cost(fv).expect("should not overflow"); + let expected = 50u64 * fv.storage.storage_processing_credit_per_byte; + assert_eq!(result, expected); + } + + #[test] + fn ephemeral_cost_storage_removed_bytes_basic() { + let fv = fee_version(); + let cost = OperationCost { + seek_count: 0, + storage_cost: StorageCost { + added_bytes: 0, + replaced_bytes: 0, + removed_bytes: StorageRemovedBytes::BasicStorageRemoval(75), + }, + storage_loaded_bytes: 0, + hash_node_calls: 0, + sinsemilla_hash_calls: 0, + }; + let result = cost.ephemeral_cost(fv).expect("should not overflow"); + let expected = 75u64 * fv.storage.storage_processing_credit_per_byte; + assert_eq!(result, expected); + } + + #[test] + fn ephemeral_cost_loaded_bytes() { + let fv = fee_version(); + let cost = OperationCost { + seek_count: 0, + storage_cost: StorageCost::default(), + storage_loaded_bytes: 300, + hash_node_calls: 0, + sinsemilla_hash_calls: 0, + }; + let result = cost.ephemeral_cost(fv).expect("should not overflow"); + let expected = 300u64 * fv.storage.storage_load_credit_per_byte; + assert_eq!(result, expected); + } + + #[test] + fn ephemeral_cost_hash_node_calls() { + let fv = fee_version(); + let cost = OperationCost { + seek_count: 0, + storage_cost: StorageCost::default(), + storage_loaded_bytes: 0, + hash_node_calls: 10, + sinsemilla_hash_calls: 0, + }; + let result = cost.ephemeral_cost(fv).expect("should not overflow"); + let blake3_total = fv.hashing.blake3_base + fv.hashing.blake3_per_block; + let expected = blake3_total * 10; + assert_eq!(result, expected); + } + + #[test] + fn ephemeral_cost_sinsemilla_hash_calls() { + let fv = fee_version(); + let cost = OperationCost { + seek_count: 0, + storage_cost: StorageCost::default(), + storage_loaded_bytes: 0, + hash_node_calls: 0, + sinsemilla_hash_calls: 3, + }; + let result = cost.ephemeral_cost(fv).expect("should not overflow"); + let expected = fv.hashing.sinsemilla_base * 3; + assert_eq!(result, expected); + } + + #[test] + fn ephemeral_cost_all_components_combined() { + let fv = fee_version(); + let cost = OperationCost { + seek_count: 2, + storage_cost: StorageCost { + added_bytes: 10, + replaced_bytes: 20, + removed_bytes: StorageRemovedBytes::BasicStorageRemoval(30), + }, + storage_loaded_bytes: 40, + hash_node_calls: 5, + sinsemilla_hash_calls: 1, + }; + let result = cost.ephemeral_cost(fv).expect("should not overflow"); + + let seek_cost = 2u64 * fv.storage.storage_seek_cost; + let processing_per_byte = fv.storage.storage_processing_credit_per_byte; + let added_cost = 10u64 * processing_per_byte; + let replaced_cost = 20u64 * processing_per_byte; + let removed_cost = 30u64 * processing_per_byte; + let loaded_cost = 40u64 * fv.storage.storage_load_credit_per_byte; + let blake3_total = fv.hashing.blake3_base + fv.hashing.blake3_per_block; + let hash_cost = blake3_total * 5; + let sinsemilla_cost = fv.hashing.sinsemilla_base * 1; + + let expected = seek_cost + + added_cost + + replaced_cost + + loaded_cost + + removed_cost + + hash_cost + + sinsemilla_cost; + assert_eq!(result, expected); + } + + #[test] + fn ephemeral_cost_overflow_seek_cost() { + let fv = &FeeVersion { + storage: FeeStorageVersion { + storage_seek_cost: u64::MAX, + ..fee_version().storage.clone() + }, + ..fee_version().clone() + }; + let cost = OperationCost { + seek_count: 2, // 2 * u64::MAX overflows + storage_cost: StorageCost::default(), + storage_loaded_bytes: 0, + hash_node_calls: 0, + sinsemilla_hash_calls: 0, + }; + let result = cost.ephemeral_cost(fv); + assert!(result.is_err(), "expected overflow error for seek cost"); + } + + #[test] + fn ephemeral_cost_overflow_storage_written_bytes() { + let fv = &FeeVersion { + storage: FeeStorageVersion { + storage_processing_credit_per_byte: u64::MAX, + ..fee_version().storage.clone() + }, + ..fee_version().clone() + }; + let cost = OperationCost { + seek_count: 0, + storage_cost: StorageCost { + added_bytes: 2, // 2 * u64::MAX overflows + replaced_bytes: 0, + removed_bytes: StorageRemovedBytes::NoStorageRemoval, + }, + storage_loaded_bytes: 0, + hash_node_calls: 0, + sinsemilla_hash_calls: 0, + }; + let result = cost.ephemeral_cost(fv); + assert!( + result.is_err(), + "expected overflow error for storage written bytes" + ); + } + + #[test] + fn ephemeral_cost_overflow_loaded_bytes() { + let fv = &FeeVersion { + storage: FeeStorageVersion { + storage_load_credit_per_byte: u64::MAX, + ..fee_version().storage.clone() + }, + ..fee_version().clone() + }; + let cost = OperationCost { + seek_count: 0, + storage_cost: StorageCost::default(), + storage_loaded_bytes: 2, // 2 * u64::MAX overflows + hash_node_calls: 0, + sinsemilla_hash_calls: 0, + }; + let result = cost.ephemeral_cost(fv); + assert!( + result.is_err(), + "expected overflow error for loaded bytes cost" + ); + } + + #[test] + fn ephemeral_cost_overflow_in_addition_chain() { + // Use values that individually do not overflow but whose sum does. + let fv = fee_version(); + let cost = OperationCost { + seek_count: u32::MAX, + storage_cost: StorageCost { + added_bytes: u32::MAX, + replaced_bytes: u32::MAX, + removed_bytes: StorageRemovedBytes::BasicStorageRemoval(u32::MAX), + }, + storage_loaded_bytes: u64::MAX, + hash_node_calls: u32::MAX, + sinsemilla_hash_calls: u32::MAX, + }; + let result = cost.ephemeral_cost(fv); + assert!( + result.is_err(), + "expected overflow error when summing large components" + ); + } +} diff --git a/packages/rs-scripts/Cargo.toml b/packages/rs-scripts/Cargo.toml index dc639760994..18bb06e33b9 100644 --- a/packages/rs-scripts/Cargo.toml +++ b/packages/rs-scripts/Cargo.toml @@ -15,4 +15,3 @@ base64 = "0.22" chrono = "0.4" hex = "0.4" clap = { version = "4", features = ["derive"] } -serde_json = "1"