diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3edab370..3c3e8996 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -122,9 +122,9 @@ jobs: echo "profile_dir=debug" >> $GITHUB_OUTPUT echo "Building DEBUG (RC pre-release: logging enabled)" else - echo "build_flags=--release --no-default-features" >> $GITHUB_OUTPUT + echo "build_flags=--release --no-default-features --features logging" >> $GITHUB_OUTPUT echo "profile_dir=release" >> $GITHUB_OUTPUT - echo "Building RELEASE (logging stripped)" + echo "Building RELEASE (logging enabled, other defaults stripped)" fi - name: Install Rust toolchain diff --git a/Cargo.lock b/Cargo.lock index 6cabe8d7..93e18431 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -124,9 +124,9 @@ dependencies = [ [[package]] name = "alloy-chains" -version = "0.2.33" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4e9e31d834fe25fe991b8884e4b9f0e59db4a97d86e05d1464d6899c013cd62" +checksum = "84e0378e959aa6a885897522080a990e80eb317f1e9a222a604492ea50e13096" dependencies = [ "alloy-primitives", "num_enum", @@ -428,13 +428,13 @@ dependencies = [ "derive_more", "foldhash 0.2.0", "hashbrown 0.16.1", - "indexmap 2.13.1", + "indexmap 2.14.0", "itoa", "k256", "keccak-asm", "paste", "proptest", - "rand 0.9.2", + "rand 0.9.4", "rapidhash", "ruint", "rustc-hash", @@ -650,7 +650,7 @@ dependencies = [ "alloy-sol-macro-input", "const-hex", "heck", - "indexmap 2.13.1", + "indexmap 2.14.0", "proc-macro-error2", "proc-macro2", "quote", @@ -836,7 +836,7 @@ dependencies = [ [[package]] name = "ant-node" -version = "0.10.0-rc.1" +version = "0.10.0" dependencies = [ "aes-gcm-siv", "alloy", @@ -867,7 +867,7 @@ dependencies = [ "saorsa-pqc 0.5.1", "self-replace", "self_encryption", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_json", "serial_test", @@ -1315,9 +1315,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" dependencies = [ "serde_core", ] @@ -1492,9 +1492,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.58" +version = "1.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" dependencies = [ "find-msvc-tools", "jobserver", @@ -1539,7 +1539,7 @@ checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ "cfg-if", "cpufeatures 0.3.0", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -2348,9 +2348,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "fastrlp" @@ -2655,7 +2655,7 @@ dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "rand_core 0.10.0", + "rand_core 0.10.1", "wasip2", "wasip3", ] @@ -2705,7 +2705,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.13.1", + "indexmap 2.14.0", "slab", "tokio", "tokio-util", @@ -2755,6 +2755,12 @@ dependencies = [ "serde_core", ] +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + [[package]] name = "heapless" version = "0.7.17" @@ -2777,9 +2783,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "heed" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a56c94661ddfb51aa9cdfbf102cfcc340aa69267f95ebccc4af08d7c530d393" +checksum = "ad82d6598ccf1dac15c8b758a1bd282b755b6776be600429176757190a1b0202" dependencies = [ "bitflags", "byteorder", @@ -2935,15 +2941,14 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.7" +version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ "http", "hyper", "hyper-util", "rustls", - "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", @@ -3125,7 +3130,7 @@ dependencies = [ "hyper", "hyper-util", "log", - "rand 0.10.0", + "rand 0.10.1", "tokio", "url", "xmltree", @@ -3170,12 +3175,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "serde", "serde_core", ] @@ -3300,9 +3305,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.94" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" dependencies = [ "cfg-if", "futures-util", @@ -3367,9 +3372,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.184" +version = "0.2.185" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" [[package]] name = "libm" @@ -3379,14 +3384,14 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" dependencies = [ "bitflags", "libc", "plain", - "redox_syscall 0.7.3", + "redox_syscall 0.7.4", ] [[package]] @@ -3403,9 +3408,9 @@ checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "lmdb-master-sys" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864808e0b19fb6dd3b70ba94ee671b82fce17554cf80aeb0a155c65bb08027df" +checksum = "aaeb9bd22e73bd1babffff614994b341e9b2008de7bb73bf1f7e9154f1978f8b" dependencies = [ "cc", "doxygen-rs", @@ -3429,9 +3434,9 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "lru" -version = "0.16.3" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" +checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" dependencies = [ "hashbrown 0.16.1", ] @@ -3951,9 +3956,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plain" @@ -4057,7 +4062,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.10+spec-1.1.0", + "toml_edit 0.25.11+spec-1.1.0", ] [[package]] @@ -4101,7 +4106,7 @@ dependencies = [ "bit-vec", "bitflags", "num-traits", - "rand 0.9.2", + "rand 0.9.4", "rand_chacha 0.9.0", "rand_xorshift", "regex-syntax", @@ -4146,7 +4151,7 @@ dependencies = [ "bytes", "getrandom 0.3.4", "lru-slab", - "rand 0.9.2", + "rand 0.9.4", "ring", "rustc-hash", "rustls", @@ -4226,9 +4231,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -4237,13 +4242,13 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ "chacha20 0.10.0", "getrandom 0.4.2", - "rand_core 0.10.0", + "rand_core 0.10.1", ] [[package]] @@ -4287,9 +4292,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "rand_xorshift" @@ -4311,9 +4316,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", @@ -4354,9 +4359,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" +checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" dependencies = [ "bitflags", ] @@ -4542,7 +4547,7 @@ dependencies = [ "primitive-types", "proptest", "rand 0.8.5", - "rand 0.9.2", + "rand 0.9.4", "rlp", "ruint-macro", "serde_core", @@ -4589,7 +4594,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver 1.0.27", + "semver 1.0.28", ] [[package]] @@ -4616,9 +4621,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.37" +version = "0.23.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +checksum = "69f9466fb2c14ea04357e91413efb882e2a6d4a406e625449bc0a5d360d53a21" dependencies = [ "aws-lc-rs", "log", @@ -4700,9 +4705,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.10" +version = "0.103.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" +checksum = "8279bb85272c9f10811ae6a6c547ff594d6a7f3c6c6b02ee9726d1d0dcfcdd06" dependencies = [ "aws-lc-rs", "ring", @@ -4754,8 +4759,9 @@ dependencies = [ [[package]] name = "saorsa-core" -version = "0.22.0" -source = "git+https://github.com/grumbach/saorsa-core.git?branch=fix/clock-skew-tolerance#3183f1d4f412d79974dc2325fc90a7009b68a0a0" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eefc3539465111e2769b9b8334ddd4d7071e12c183de4a9fee7d9bfbdb3da23" dependencies = [ "anyhow", "async-trait", @@ -4867,8 +4873,9 @@ dependencies = [ [[package]] name = "saorsa-transport" -version = "0.31.0" -source = "git+https://github.com/grumbach/saorsa-transport.git?branch=round4-combined#2cabf2b5e00d00650283265a915ab690d1529183" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "250826f52ac60992947359218d83c21f658aa85407e3980a5dbb258eff4c0cc3" dependencies = [ "anyhow", "async-trait", @@ -4883,7 +4890,7 @@ dependencies = [ "futures-util", "hex", "igd-next", - "indexmap 2.13.1", + "indexmap 2.14.0", "keyring", "libc", "lru-slab", @@ -5080,9 +5087,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "semver-parser" @@ -5164,7 +5171,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.13.1", + "indexmap 2.14.0", "schemars 0.9.0", "schemars 1.2.1", "serde_core", @@ -5191,7 +5198,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.13.1", + "indexmap 2.14.0", "itoa", "ryu", "serde", @@ -5663,9 +5670,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.51.0" +version = "1.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd1c4c0fc4a7ab90fc15ef6daaa3ec3b893f004f915f2392557ed23237820cd" +checksum = "a91135f59b1cbf38c91e73cf3386fca9bb77915c45ce2771460c9d92f0f3d776" dependencies = [ "bytes", "libc", @@ -5772,7 +5779,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.13.1", + "indexmap 2.14.0", "serde", "serde_spanned", "toml_datetime 0.6.11", @@ -5782,11 +5789,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.10+spec-1.1.0" +version = "0.25.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82418ca169e235e6c399a84e395ab6debeb3bc90edc959bf0f48647c6a32d1b" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" dependencies = [ - "indexmap 2.13.1", + "indexmap 2.14.0", "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", "winnow 1.0.1", @@ -6135,9 +6142,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ "cfg-if", "once_cell", @@ -6148,9 +6155,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.67" +version = "0.4.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03623de6905b7206edd0a75f69f747f134b7f0a2323392d664448bf2d3c5d87e" +checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" dependencies = [ "js-sys", "wasm-bindgen", @@ -6158,9 +6165,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6168,9 +6175,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ "bumpalo", "proc-macro2", @@ -6181,9 +6188,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" dependencies = [ "unicode-ident", ] @@ -6205,7 +6212,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" dependencies = [ "anyhow", - "indexmap 2.13.1", + "indexmap 2.14.0", "wasm-encoder", "wasmparser", ] @@ -6218,8 +6225,8 @@ checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags", "hashbrown 0.15.5", - "indexmap 2.13.1", - "semver 1.0.27", + "indexmap 2.14.0", + "semver 1.0.28", ] [[package]] @@ -6238,9 +6245,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.94" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" +checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" dependencies = [ "js-sys", "wasm-bindgen", @@ -6763,7 +6770,7 @@ checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", "heck", - "indexmap 2.13.1", + "indexmap 2.14.0", "prettyplease", "syn 2.0.117", "wasm-metadata", @@ -6794,7 +6801,7 @@ checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", "bitflags", - "indexmap 2.13.1", + "indexmap 2.14.0", "log", "serde", "serde_derive", @@ -6813,9 +6820,9 @@ checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ "anyhow", "id-arena", - "indexmap 2.13.1", + "indexmap 2.14.0", "log", - "semver 1.0.27", + "semver 1.0.28", "serde", "serde_derive", "serde_json", @@ -7059,7 +7066,7 @@ dependencies = [ "flate2", "getrandom 0.3.4", "hmac", - "indexmap 2.13.1", + "indexmap 2.14.0", "lzma-rs", "memchr", "pbkdf2", diff --git a/Cargo.toml b/Cargo.toml index eb09130a..7ab2eef5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ant-node" -version = "0.10.0-rc.1" +version = "0.10.0" edition = "2021" authors = ["David Irvine "] description = "Pure quantum-proof network node for the Autonomi decentralized network" @@ -24,7 +24,7 @@ path = "src/bin/ant-devnet/main.rs" [dependencies] # Core (provides EVERYTHING: networking, DHT, security, trust, storage) -saorsa-core = "0.22.0" +saorsa-core = "0.23.0" saorsa-pqc = "0.5" # Payment verification - autonomi network lookup + EVM payment diff --git a/src/bin/ant-devnet/cli.rs b/src/bin/ant-devnet/cli.rs index 8169351f..ae1e0178 100644 --- a/src/bin/ant-devnet/cli.rs +++ b/src/bin/ant-devnet/cli.rs @@ -44,7 +44,16 @@ pub struct Cli { #[arg(long)] pub manifest: Option, + /// Enable logging output. + /// When omitted, the tracing subscriber is not installed and no log + /// records are emitted, even if the binary was built with the + /// `logging` feature. `--log-level` is ignored unless this flag is set. + #[cfg(feature = "logging")] + #[arg(long, env = "ANT_ENABLE_LOGGING")] + pub enable_logging: bool, + /// Log level for devnet process. + #[cfg(feature = "logging")] #[arg(long, default_value = "info")] pub log_level: String, diff --git a/src/bin/ant-devnet/main.rs b/src/bin/ant-devnet/main.rs index d8c9fc87..1117f7de 100644 --- a/src/bin/ant-devnet/main.rs +++ b/src/bin/ant-devnet/main.rs @@ -15,7 +15,7 @@ async fn main() -> color_eyre::Result<()> { let cli = Cli::parse(); #[cfg(feature = "logging")] - { + if cli.enable_logging { use tracing_subscriber::{fmt, prelude::*, EnvFilter}; let filter = diff --git a/src/bin/ant-node/cli.rs b/src/bin/ant-node/cli.rs index ddbd00b4..8eb9fa51 100644 --- a/src/bin/ant-node/cli.rs +++ b/src/bin/ant-node/cli.rs @@ -12,6 +12,7 @@ use std::path::PathBuf; #[derive(Parser, Debug)] #[command(name = "ant-node")] #[command(author, version, about, long_about = None)] +#[allow(clippy::struct_excessive_bools)] // unrelated CLI toggles, not a state machine pub struct Cli { /// Root directory for node data. #[arg(long, env = "ANT_ROOT_DIR")] @@ -61,6 +62,15 @@ pub struct Cli { #[arg(long, default_value = "9100", env = "ANT_METRICS_PORT")] pub metrics_port: u16, + /// Enable logging output. + /// When omitted, the tracing subscriber is not installed and no log + /// records are emitted, even if the binary was built with the + /// `logging` feature. The remaining `--log-*` options are ignored + /// unless this flag is set. + #[cfg(feature = "logging")] + #[arg(long, env = "ANT_ENABLE_LOGGING")] + pub enable_logging: bool, + /// Log level. #[cfg(feature = "logging")] #[arg(long, value_enum, default_value = "info", env = "RUST_LOG")] diff --git a/src/bin/ant-node/main.rs b/src/bin/ant-node/main.rs index 30560e50..3af62dc9 100644 --- a/src/bin/ant-node/main.rs +++ b/src/bin/ant-node/main.rs @@ -9,18 +9,26 @@ use ant_node::config::BootstrapSource; use ant_node::NodeBuilder; use clap::Parser; use cli::Cli; +#[cfg(feature = "logging")] +use cli::CliLogFormat; +#[cfg(feature = "logging")] +use tracing_subscriber::prelude::*; +#[cfg(feature = "logging")] +use tracing_subscriber::{fmt, EnvFilter, Layer}; -/// Initialize the tracing subscriber when the `logging` feature is active. +/// Initialize the tracing subscriber when the `logging` feature is active +/// **and** the user passed `--enable-logging`. /// -/// Returns a guard that must be held for the lifetime of the process to ensure -/// buffered logs are flushed on shutdown. +/// Returns `Ok(None)` when logging was not requested. Otherwise returns a +/// guard (possibly `None` for stdout sinks) that must be held for the +/// lifetime of the process to ensure buffered logs are flushed on shutdown. #[cfg(feature = "logging")] fn init_logging( cli: &Cli, ) -> color_eyre::Result> { - use cli::CliLogFormat; - use tracing_subscriber::prelude::*; - use tracing_subscriber::{fmt, EnvFilter, Layer}; + if !cli.enable_logging { + return Ok(None); + } let log_format = cli.log_format; let log_dir = cli.log_dir.clone(); diff --git a/src/payment/pricing.rs b/src/payment/pricing.rs index 96c5bd82..2e324c17 100644 --- a/src/payment/pricing.rs +++ b/src/payment/pricing.rs @@ -1,48 +1,60 @@ -//! Simple quadratic pricing algorithm for ant-node. +//! Quadratic pricing with a baseline floor for ant-node (Phase 1 recalibration). //! -//! Uses the formula `(close_records_stored / 6000)^2` to calculate storage price. -//! Integer division means nodes with fewer than 6000 records get a ratio of 0, -//! but a minimum floor of 1 prevents free storage. +//! Formula: `price_per_chunk_ANT(n) = BASELINE + K × (n / D)²` +//! +//! This recalibration introduces a non-zero `BASELINE` so that empty nodes +//! charge a meaningful spam-barrier price, and re-anchors `K` so per-GB USD +//! pricing matches real-world targets at the current ~$0.10/ANT token price. +//! The legacy formula produced ~$25/GB at the lower stable boundary and ~$0/GB +//! when nodes were empty — both unreasonable. +//! +//! ## Parameters +//! +//! | Constant | Value | Role | +//! |-----------|---------------|-------------------------------------------------| +//! | BASELINE | 0.00390625 ANT| Price at empty (bootstrap-phase spam barrier) | +//! | K | 0.03515625 ANT| Quadratic coefficient | +//! | D | 6000 | Lower stable boundary (records stored) | //! //! ## Design Rationale //! -//! The quadratic curve creates natural load balancing: -//! - **Lightly loaded nodes** (< 6000 records) charge the minimum floor price -//! - **Moderately loaded nodes** charge proportionally more as records grow -//! - **Heavily loaded nodes** charge quadratically more, pushing clients elsewhere +//! - **Empty / lightly loaded nodes** charge the `BASELINE` floor, preventing +//! free storage and acting as a bootstrap-phase spam barrier. +//! - **Moderately loaded nodes** add a small quadratic contribution on top. +//! - **Heavily loaded nodes** charge quadratically more, pushing clients +//! toward less-loaded nodes elsewhere in the network. use evmlib::common::Amount; -/// Divisor for the pricing formula. -const PRICING_DIVISOR: u64 = 6000; +/// Lower stable boundary of the quadratic curve, in records stored. +const PRICING_DIVISOR: u128 = 6000; /// `PRICING_DIVISOR²`, precomputed to avoid repeated multiplication. -const DIVISOR_SQUARED: u64 = PRICING_DIVISOR * PRICING_DIVISOR; +const DIVISOR_SQUARED: u128 = PRICING_DIVISOR * PRICING_DIVISOR; -/// 1 token = 10^18 wei. -const WEI_PER_TOKEN: u128 = 1_000_000_000_000_000_000; +/// Baseline price at empty / bootstrap-phase spam barrier. +/// +/// `0.00390625 ANT × 10¹⁸ wei/ANT = 3_906_250_000_000_000 wei`. +const PRICE_BASELINE_WEI: u128 = 3_906_250_000_000_000; -/// Minimum price in wei (1 wei) to prevent free storage. -const MIN_PRICE_WEI: u128 = 1; +/// Quadratic coefficient `K`. +/// +/// `0.03515625 ANT × 10¹⁸ wei/ANT = 35_156_250_000_000_000 wei`. +const PRICE_COEFFICIENT_WEI: u128 = 35_156_250_000_000_000; /// Calculate storage price in wei from the number of close records stored. /// -/// Formula: `price_wei = n² × 10¹⁸ / 6000²` +/// Formula: `price_wei = BASELINE + n² × K / D²` /// -/// This is equivalent to `(n / 6000)²` in tokens, converted to wei, but -/// preserves sub-token precision by scaling before dividing. U256 arithmetic -/// prevents overflow for large record counts. +/// where `BASELINE = 0.00390625 ANT`, `K = 0.03515625 ANT`, and `D = 6000`. +/// U256 arithmetic prevents overflow for large record counts. #[must_use] pub fn calculate_price(close_records_stored: usize) -> Amount { let n = Amount::from(close_records_stored); let n_squared = n.saturating_mul(n); - let price_wei = - n_squared.saturating_mul(Amount::from(WEI_PER_TOKEN)) / Amount::from(DIVISOR_SQUARED); - if price_wei.is_zero() { - Amount::from(MIN_PRICE_WEI) - } else { - price_wei - } + let quadratic_wei = n_squared.saturating_mul(Amount::from(PRICE_COEFFICIENT_WEI)) + / Amount::from(DIVISOR_SQUARED); + Amount::from(PRICE_BASELINE_WEI).saturating_add(quadratic_wei) } #[cfg(test)] @@ -50,53 +62,67 @@ pub fn calculate_price(close_records_stored: usize) -> Amount { mod tests { use super::*; - const WEI: u128 = WEI_PER_TOKEN; + /// 1 token = 10¹⁸ wei (used for test sanity-checks). + const WEI_PER_TOKEN: u128 = 1_000_000_000_000_000_000; - /// Helper: expected price for n records = n² * 10^18 / 6000² + /// Helper: expected price matching the formula `BASELINE + n² × K / D²`. fn expected_price(n: u64) -> Amount { - let n = Amount::from(n); - n * n * Amount::from(WEI) / Amount::from(DIVISOR_SQUARED) + let n_amt = Amount::from(n); + let quad = + n_amt * n_amt * Amount::from(PRICE_COEFFICIENT_WEI) / Amount::from(DIVISOR_SQUARED); + Amount::from(PRICE_BASELINE_WEI) + quad } #[test] - fn test_zero_records_gets_min_price() { + fn test_zero_records_gets_baseline() { + // At n = 0 the quadratic term vanishes, leaving the baseline floor. let price = calculate_price(0); - assert_eq!(price, Amount::from(MIN_PRICE_WEI)); + assert_eq!(price, Amount::from(PRICE_BASELINE_WEI)); } #[test] - fn test_one_record_nonzero() { - // 1² * 1e18 / 36e6 = 1e18 / 36e6 ≈ 27_777_777_777 + fn test_baseline_is_nonzero_spam_barrier() { + // The baseline ensures even empty nodes charge a meaningful price, + // making the legacy MIN_PRICE_WEI = 1 sentinel redundant. + assert!(calculate_price(0) > Amount::ZERO); + assert!(calculate_price(1) > calculate_price(0)); + } + + #[test] + fn test_one_record_above_baseline() { let price = calculate_price(1); assert_eq!(price, expected_price(1)); - assert!(price > Amount::ZERO); + assert!(price > Amount::from(PRICE_BASELINE_WEI)); } #[test] - fn test_at_divisor_gets_one_token() { - // 6000² * 1e18 / 6000² = 1e18 + fn test_at_divisor_is_baseline_plus_k() { + // At n = D the quadratic contribution equals K × 1² = K. + // price = BASELINE + K = 0.00390625 + 0.03515625 = 0.0390625 ANT let price = calculate_price(6000); - assert_eq!(price, Amount::from(WEI)); + let expected = Amount::from(PRICE_BASELINE_WEI + PRICE_COEFFICIENT_WEI); + assert_eq!(price, expected); } #[test] - fn test_double_divisor_gets_four_tokens() { - // 12000² * 1e18 / 6000² = 4e18 + fn test_double_divisor_is_baseline_plus_four_k() { + // At n = 2D the quadratic contribution is 4K. let price = calculate_price(12000); - assert_eq!(price, Amount::from(4 * WEI)); + let expected = Amount::from(PRICE_BASELINE_WEI + 4 * PRICE_COEFFICIENT_WEI); + assert_eq!(price, expected); } #[test] - fn test_triple_divisor_gets_nine_tokens() { - // 18000² * 1e18 / 6000² = 9e18 + fn test_triple_divisor_is_baseline_plus_nine_k() { + // At n = 3D the quadratic contribution is 9K. let price = calculate_price(18000); - assert_eq!(price, Amount::from(9 * WEI)); + let expected = Amount::from(PRICE_BASELINE_WEI + 9 * PRICE_COEFFICIENT_WEI); + assert_eq!(price, expected); } #[test] fn test_smooth_pricing_no_staircase() { - // With the old integer-division approach, 6000 and 11999 gave the same price. - // Now 11999 should give a higher price than 6000. + // 11999 should give a strictly higher price than 6000 (no integer-division plateau). let price_6k = calculate_price(6000); let price_11k = calculate_price(11999); assert!( @@ -141,19 +167,23 @@ mod tests { } #[test] - fn test_quadratic_growth() { - // price at 4x records should be 16x price at 1x - let price_1x = calculate_price(6000); - let price_4x = calculate_price(24000); - assert_eq!(price_1x, Amount::from(WEI)); - assert_eq!(price_4x, Amount::from(16 * WEI)); + fn test_quadratic_growth_excluding_baseline() { + // Subtracting the baseline, quadratic contribution should scale with n². + // At 2× records the quadratic portion is 4×; at 4× records it is 16×. + let base = Amount::from(PRICE_BASELINE_WEI); + let quad_6k = calculate_price(6000) - base; + let quad_12k = calculate_price(12000) - base; + let quad_24k = calculate_price(24000) - base; + assert_eq!(quad_12k, quad_6k * Amount::from(4u64)); + assert_eq!(quad_24k, quad_6k * Amount::from(16u64)); } #[test] - fn test_small_record_counts_are_cheap() { - // 100 records: 100² * 1e18 / 36e6 ≈ 277_777_777_777_777 wei ≈ 0.000278 tokens + fn test_small_record_counts_near_baseline() { + // At small n, price is dominated by the baseline — quadratic term is tiny. let price = calculate_price(100); assert_eq!(price, expected_price(100)); - assert!(price < Amount::from(WEI)); // well below 1 token + assert!(price < Amount::from(WEI_PER_TOKEN)); // well below 1 ANT + assert!(price > Amount::from(PRICE_BASELINE_WEI)); // strictly above baseline } } diff --git a/src/replication/config.rs b/src/replication/config.rs index 649afbed..bdfd14a2 100644 --- a/src/replication/config.rs +++ b/src/replication/config.rs @@ -70,6 +70,15 @@ pub const SELF_LOOKUP_INTERVAL_MIN: Duration = Duration::from_secs(SELF_LOOKUP_I /// Periodic self-lookup cadence range (max). pub const SELF_LOOKUP_INTERVAL_MAX: Duration = Duration::from_secs(SELF_LOOKUP_INTERVAL_MAX_SECS); +/// Maximum number of concurrent outbound replication sends. +/// +/// Caps how many fresh-replication chunk transfers can be in-flight at once +/// across the entire replication engine. Prevents bandwidth saturation on +/// home broadband connections when multiple chunks arrive simultaneously. +/// Each send transfers up to 4 MB (`MAX_CHUNK_SIZE`), so a limit of 3 means +/// at most ~12 MB queued for the upload link at any instant. +pub const MAX_CONCURRENT_REPLICATION_SENDS: usize = 3; + /// Concurrent fetches cap, derived from hardware thread count. /// /// Uses `std::thread::available_parallelism()` so the node scales to the diff --git a/src/replication/fresh.rs b/src/replication/fresh.rs index 5bc47896..af3a93a9 100644 --- a/src/replication/fresh.rs +++ b/src/replication/fresh.rs @@ -11,6 +11,7 @@ use crate::logging::{debug, warn}; use rand::Rng; use saorsa_core::identity::PeerId; use saorsa_core::P2PNode; +use tokio::sync::Semaphore; use crate::ant_protocol::XorName; use crate::replication::config::{ReplicationConfig, REPLICATION_PROTOCOL_ID}; @@ -38,6 +39,10 @@ pub struct FreshWriteEvent { /// Sends fresh offers to close group members and `PaidNotify` to /// `PaidCloseGroup`. Both are fire-and-forget (no ack tracking or retry per /// Section 6.1, rule 8). +/// +/// The `send_semaphore` limits how many outbound chunk transfers can be +/// in-flight concurrently across the entire replication engine, preventing +/// bandwidth saturation on home broadband connections. pub async fn replicate_fresh( key: &XorName, data: &[u8], @@ -45,6 +50,7 @@ pub async fn replicate_fresh( p2p_node: &Arc, paid_list: &Arc, config: &ReplicationConfig, + send_semaphore: &Arc, ) { let self_id = *p2p_node.peer_id(); @@ -88,7 +94,15 @@ pub async fn replicate_fresh( let p2p = Arc::clone(p2p_node); let data = encoded.clone(); let peer_id = *peer; + let sem = Arc::clone(send_semaphore); tokio::spawn(async move { + // Acquire a permit before sending — this caps the number of + // concurrent outbound replication transfers across the engine. + let _permit = sem.acquire().await; + debug!( + "Replication send permit acquired for peer {peer_id} ({} available)", + sem.available_permits() + ); if let Err(e) = p2p .send_message(&peer_id, REPLICATION_PROTOCOL_ID, data, &[]) .await @@ -99,6 +113,8 @@ pub async fn replicate_fresh( } // Rule 7-8: Send PaidNotify to every member of PaidCloseGroup(K). + // PaidNotify messages are small metadata (no chunk data), so they don't + // need semaphore gating. send_paid_notify(key, proof_of_payment, p2p_node, config).await; debug!( diff --git a/src/replication/mod.rs b/src/replication/mod.rs index d956e00b..79a2888c 100644 --- a/src/replication/mod.rs +++ b/src/replication/mod.rs @@ -38,7 +38,7 @@ use crate::logging::{debug, error, info, warn}; use futures::stream::FuturesUnordered; use futures::{Future, StreamExt}; use rand::Rng; -use tokio::sync::{mpsc, Notify, RwLock}; +use tokio::sync::{mpsc, Notify, RwLock, Semaphore}; use tokio::task::JoinHandle; use tokio_util::sync::CancellationToken; @@ -46,7 +46,10 @@ use crate::ant_protocol::XorName; use crate::error::{Error, Result}; use crate::payment::PaymentVerifier; use crate::replication::audit::AuditTickResult; -use crate::replication::config::{max_parallel_fetch, ReplicationConfig, REPLICATION_PROTOCOL_ID}; +use crate::replication::config::{ + max_parallel_fetch, ReplicationConfig, MAX_CONCURRENT_REPLICATION_SENDS, + REPLICATION_PROTOCOL_ID, +}; use crate::replication::paid_list::PaidList; use crate::replication::protocol::{ FreshReplicationResponse, NeighborSyncResponse, ReplicationMessage, ReplicationMessageBody, @@ -122,6 +125,9 @@ pub struct ReplicationEngine { sync_trigger: Arc, /// Notified when `is_bootstrapping` transitions from `true` to `false`. bootstrap_complete_notify: Arc, + /// Limits concurrent outbound replication sends to prevent bandwidth + /// saturation on home broadband connections. + send_semaphore: Arc, /// Receiver for fresh-write events from the chunk PUT handler. /// /// When present, `start()` spawns a drainer task that calls @@ -173,6 +179,7 @@ impl ReplicationEngine { is_bootstrapping: Arc::new(RwLock::new(true)), sync_trigger: Arc::new(Notify::new()), bootstrap_complete_notify: Arc::new(Notify::new()), + send_semaphore: Arc::new(Semaphore::new(MAX_CONCURRENT_REPLICATION_SENDS)), fresh_write_rx: Some(fresh_write_rx), shutdown, task_handles: Vec::new(), @@ -249,8 +256,16 @@ impl ReplicationEngine { /// released (e.g. before reopening the same LMDB environment). pub async fn shutdown(&mut self) { self.shutdown.cancel(); - for handle in self.task_handles.drain(..) { - let _ = handle.await; + for (i, mut handle) in self.task_handles.drain(..).enumerate() { + match tokio::time::timeout(std::time::Duration::from_secs(10), &mut handle).await { + Ok(Ok(())) => {} + Ok(Err(e)) if e.is_cancelled() => {} + Ok(Err(e)) => warn!("Replication task {i} panicked during shutdown: {e}"), + Err(_) => { + warn!("Replication task {i} did not stop within 10s, aborting"); + handle.abort(); + } + } } } @@ -272,6 +287,7 @@ impl ReplicationEngine { &self.p2p_node, &self.paid_list, &self.config, + &self.send_semaphore, ) .await; } @@ -289,6 +305,7 @@ impl ReplicationEngine { let p2p = Arc::clone(&self.p2p_node); let paid_list = Arc::clone(&self.paid_list); let config = Arc::clone(&self.config); + let send_semaphore = Arc::clone(&self.send_semaphore); let shutdown = self.shutdown.clone(); let handle = tokio::spawn(async move { @@ -304,6 +321,7 @@ impl ReplicationEngine { &p2p, &paid_list, &config, + &send_semaphore, ) .await; } @@ -426,18 +444,23 @@ impl ReplicationEngine { debug!("Neighbor sync triggered by topology change"); } } - run_neighbor_sync_round( - &p2p, - &storage, - &paid_list, - &queues, - &config, - &sync_state, - &sync_history, - &is_bootstrapping, - &bootstrap_state, - ) - .await; + // Wrap the sync round in a select so shutdown cancels + // in-progress network operations rather than waiting for + // the full round to complete. + tokio::select! { + () = shutdown.cancelled() => break, + () = run_neighbor_sync_round( + &p2p, + &storage, + &paid_list, + &queues, + &config, + &sync_state, + &sync_history, + &is_bootstrapping, + &bootstrap_state, + ) => {} + } } debug!("Neighbor sync loop shut down"); });