diff --git a/.github/nightly-version b/.github/nightly-version index 514aef61d..1852d9b51 100644 --- a/.github/nightly-version +++ b/.github/nightly-version @@ -1 +1 @@ -nightly-2024-05-01 +nightly-2024-06-01 diff --git a/Cargo.lock b/Cargo.lock index 7f1fc25dd..387f8979f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,11 +23,11 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ - "gimli 0.28.1", + "gimli 0.29.0", ] [[package]] @@ -99,10 +99,21 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "alloy-chains" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd47e5f8545bdf53beb545d3c039b4afa16040bdf69c50100581579b08776afd" +dependencies = [ + "num_enum", + "strum 0.26.2", +] + [[package]] name = "alloy-consensus" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=b79db21734cffddc11753fe62ba571565c896f42#b79db21734cffddc11753fe62ba571565c896f42" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a016bfa21193744d4c38b3f3ab845462284d129e5e23c7cc0fafca7e92d9db37" dependencies = [ "alloy-eips", "alloy-primitives", @@ -114,17 +125,18 @@ dependencies = [ [[package]] name = "alloy-core" -version = "0.7.0" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcbd9ee412dfb4e81d23cd1ae816d828c494a77d1eb00358035043695d4c5808" +checksum = "5af3faff14c12c8b11037e0a093dd157c3702becb8435577a2408534d0758315" dependencies = [ "alloy-primitives", ] [[package]] name = "alloy-eips" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=b79db21734cffddc11753fe62ba571565c896f42#b79db21734cffddc11753fe62ba571565c896f42" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32d6d8118b83b0489cfb7e6435106948add2b35217f4a5004ef895f613f60299" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -137,20 +149,20 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=b79db21734cffddc11753fe62ba571565c896f42#b79db21734cffddc11753fe62ba571565c896f42" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "894f33a7822abb018db56b10ab90398e63273ce1b5a33282afd186c132d764a6" dependencies = [ "alloy-primitives", "alloy-serde", "serde", - "serde_json", ] [[package]] name = "alloy-json-abi" -version = "0.7.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786689872ec4e7d354810ab0dffd48bb40b838c047522eb031cbd47d15634849" +checksum = "aaeaccd50238126e3a0ff9387c7c568837726ad4f4e399b528ca88104d6c25ef" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -159,8 +171,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=b79db21734cffddc11753fe62ba571565c896f42#b79db21734cffddc11753fe62ba571565c896f42" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61f0ae6e93b885cc70fe8dae449e7fd629751dbee8f59767eaaa7285333c5727" dependencies = [ "alloy-primitives", "serde", @@ -171,25 +184,29 @@ dependencies = [ [[package]] name = "alloy-network" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=b79db21734cffddc11753fe62ba571565c896f42#b79db21734cffddc11753fe62ba571565c896f42" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc122cbee2b8523854cc11d87bcd5773741602c553d2d2d106d82eeb9c16924a" dependencies = [ "alloy-consensus", "alloy-eips", "alloy-json-rpc", "alloy-primitives", - "alloy-rpc-types", + "alloy-rpc-types-eth", + "alloy-serde", "alloy-signer", "alloy-sol-types", "async-trait", + "auto_impl", "futures-utils-wasm", "thiserror", ] [[package]] name = "alloy-node-bindings" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=b79db21734cffddc11753fe62ba571565c896f42#b79db21734cffddc11753fe62ba571565c896f42" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0e005ecc1b41f0b3bf90f68df5a446971e7eb34e1ea051da401e7e8eeef8fd" dependencies = [ "alloy-genesis", "alloy-primitives", @@ -203,9 +220,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.7.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525448f6afc1b70dd0f9d0a8145631bf2f5e434678ab23ab18409ca264cae6b3" +checksum = "f783611babedbbe90db3478c120fb5f5daacceffc210b39adc0af4fe0da70bad" dependencies = [ "alloy-rlp", "bytes", @@ -225,16 +242,18 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=b79db21734cffddc11753fe62ba571565c896f42#b79db21734cffddc11753fe62ba571565c896f42" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d5af289798fe8783acd0c5f10644d9d26f54a12bc52a083e4f3b31718e9bf92" dependencies = [ + "alloy-chains", + "alloy-consensus", "alloy-eips", "alloy-json-rpc", "alloy-network", "alloy-primitives", "alloy-rpc-client", - "alloy-rpc-types", - "alloy-rpc-types-trace", + "alloy-rpc-types-eth", "alloy-transport", "async-stream", "async-trait", @@ -243,6 +262,8 @@ dependencies = [ "futures", "futures-utils-wasm", "lru", + "pin-project", + "serde", "serde_json", "tokio", "tracing", @@ -250,9 +271,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" +checksum = "b155716bab55763c95ba212806cf43d05bcc70e5f35b02bad20cf5ec7fe11fed" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -261,19 +282,20 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a047897373be4bbb0224c1afdabca92648dc57a9c9ef6e7b0be3aff7a859c83" +checksum = "8037e03c7f462a063f28daec9fda285a9a89da003c552f8637a80b9c8fd96241" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] name = "alloy-rpc-client" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=b79db21734cffddc11753fe62ba571565c896f42#b79db21734cffddc11753fe62ba571565c896f42" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b40fcb53b2a9d0a78a4968b2eca8805a4b7011b9ee3fdfa2acaf137c5128f36b" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -289,39 +311,28 @@ dependencies = [ ] [[package]] -name = "alloy-rpc-types" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=b79db21734cffddc11753fe62ba571565c896f42#b79db21734cffddc11753fe62ba571565c896f42" +name = "alloy-rpc-types-eth" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "083f443a83b9313373817236a8f4bea09cca862618e9177d822aee579640a5d6" dependencies = [ "alloy-consensus", "alloy-eips", - "alloy-genesis", "alloy-primitives", "alloy-rlp", "alloy-serde", "alloy-sol-types", - "itertools 0.12.1", + "itertools 0.13.0", "serde", "serde_json", "thiserror", ] -[[package]] -name = "alloy-rpc-types-trace" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=b79db21734cffddc11753fe62ba571565c896f42#b79db21734cffddc11753fe62ba571565c896f42" -dependencies = [ - "alloy-primitives", - "alloy-rpc-types", - "alloy-serde", - "serde", - "serde_json", -] - [[package]] name = "alloy-serde" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=b79db21734cffddc11753fe62ba571565c896f42#b79db21734cffddc11753fe62ba571565c896f42" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d94da1c0c4e27cc344b05626fe22a89dc6b8b531b9475f3b7691dbf6913e4109" dependencies = [ "alloy-primitives", "serde", @@ -330,8 +341,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=b79db21734cffddc11753fe62ba571565c896f42#b79db21734cffddc11753fe62ba571565c896f42" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58d876be3afd8b78979540084ff63995292a26aa527ad0d44276405780aa0ffd" dependencies = [ "alloy-primitives", "async-trait", @@ -354,28 +366,42 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.7.2" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bad41a7c19498e3f6079f7744656328699f8ea3e783bdd10d85788cd439f572" +dependencies = [ + "alloy-sol-macro-expander", + "alloy-sol-macro-input", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "alloy-sol-macro-expander" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c80a2cb97e7aa48611cbb63950336f9824a174cdf670527cc6465078a26ea1" +checksum = "fd9899da7d011b4fe4c406a524ed3e3f963797dbc93b45479d60341d3a27b252" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", "const-hex", - "heck 0.4.1", + "heck 0.5.0", "indexmap 2.2.6", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", "syn-solidity", "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "0.7.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58894b58ac50979eeac6249661991ac40b9d541830d9a725f7714cc9ef08c23" +checksum = "d32d595768fdc61331a132b6f65db41afae41b9b97d36c21eb1b955c422a7e60" dependencies = [ "alloy-json-abi", "const-hex", @@ -384,24 +410,24 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.60", + "syn 2.0.66", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "0.7.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8e71ea68e780cc203919e03f69f59e7afe92d2696fb1dcb6662f61e4031b6" +checksum = "baa2fbd22d353d8685bd9fee11ba2d8b5c3b1d11e56adb3265fcf1f32bfdf404" dependencies = [ - "winnow 0.6.6", + "winnow 0.6.13", ] [[package]] name = "alloy-sol-types" -version = "0.7.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "399287f68d1081ed8b1f4903c49687658b95b142207d7cb4ae2f4813915343ef" +checksum = "a49042c6d3b66a9fe6b2b5a8bf0d39fc2ae1ee0310a2a26ffedd79fb097878dd" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -411,11 +437,12 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=b79db21734cffddc11753fe62ba571565c896f42#b79db21734cffddc11753fe62ba571565c896f42" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245af9541f0a0dbd5258669c80dfe3af118164cacec978a520041fc130550deb" dependencies = [ "alloy-json-rpc", - "base64 0.22.0", + "base64 0.22.1", "futures-util", "futures-utils-wasm", "serde", @@ -424,13 +451,13 @@ dependencies = [ "tokio", "tower", "url", - "wasm-bindgen-futures", ] [[package]] name = "alloy-transport-http" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy?rev=b79db21734cffddc11753fe62ba571565c896f42#b79db21734cffddc11753fe62ba571565c896f42" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5619c017e1fdaa1db87f9182f4f0ed97c53d674957f4902fba655e972d359c6c" dependencies = [ "alloy-transport", "url", @@ -462,47 +489,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -510,9 +538,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "approx" @@ -655,9 +683,9 @@ dependencies = [ [[package]] name = "array-bytes" -version = "6.2.2" +version = "6.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f840fb7195bcfc5e17ea40c26e5ce6d5b9ce5d584466e17703209657e459ae0" +checksum = "5d5dde061bd34119e902bbb2d9b90c5692635cf59fb91d582c2b68043f1b8293" [[package]] name = "arrayref" @@ -723,9 +751,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" +checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" dependencies = [ "async-lock", "cfg-if", @@ -742,11 +770,11 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 4.0.3", + "event-listener 5.3.1", "event-listener-strategy", "pin-project-lite 0.2.14", ] @@ -770,7 +798,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -781,7 +809,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -816,27 +844,27 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ - "addr2line 0.21.0", + "addr2line 0.22.0", "cc", "cfg-if", "libc", "miniz_oxide", - "object 0.32.2", + "object 0.36.0", "rustc-demangle", ] @@ -862,6 +890,16 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "base58ck" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f" +dependencies = [ + "bitcoin-internals", + "bitcoin_hashes", +] + [[package]] name = "base64" version = "0.13.1" @@ -876,9 +914,9 @@ checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" @@ -888,9 +926,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bech32" -version = "0.10.0-beta" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98f7eed2b2781a6f0b5c903471d48e15f56fb4e1165df8a9a2337fd1a59d45ea" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" [[package]] name = "beef" @@ -927,7 +965,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -947,14 +985,16 @@ checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitcoin" -version = "0.31.2" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c85783c2fe40083ea54a33aa2f0ba58831d90fcd190f5bdc47e74e84d2a96ae" +checksum = "ea507acc1cd80fc084ace38544bbcf7ced7c2aa65b653b102de0ce718df668f6" dependencies = [ + "base58ck", "bech32", "bitcoin-internals", + "bitcoin-io", + "bitcoin-units", "bitcoin_hashes", - "core2 0.3.3", "hex-conservative", "hex_lit", "secp256k1", @@ -963,13 +1003,19 @@ dependencies = [ [[package]] name = "bitcoin-internals" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" +checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2" dependencies = [ "serde", ] +[[package]] +name = "bitcoin-io" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "340e09e8399c7bd8912f495af6aa58bea0c9214773417ffaa8f6460f93aaee56" + [[package]] name = "bitcoin-serai" version = "0.3.0" @@ -991,13 +1037,22 @@ dependencies = [ ] [[package]] -name = "bitcoin_hashes" -version = "0.13.0" +name = "bitcoin-units" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +checksum = "cb54da0b28892f3c52203a7191534033e051b6f4b52bc15480681b57b7e036f5" dependencies = [ "bitcoin-internals", - "core2 0.3.3", + "serde", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io", "hex-conservative", "serde", ] @@ -1112,9 +1167,9 @@ dependencies = [ [[package]] name = "blst" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b" +checksum = "62dc83a094a71d43eeadd254b1ec2d24cb6a0bb6cadce00df51f0db594711a32" dependencies = [ "cc", "glob", @@ -1135,7 +1190,7 @@ dependencies = [ "futures-util", "hex", "http 0.2.12", - "hyper 0.14.28", + "hyper 0.14.29", "hyperlocal", "log", "pin-project-lite 0.2.14", @@ -1164,9 +1219,9 @@ dependencies = [ [[package]] name = "borsh" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0901fc8eb0aca4c83be0106d6f2db17d86a08dfc2c25f0e84464bf381158add6" +checksum = "dbe5b10e214954177fb1dc9fbd20a1a2608fe99e6c832033bdc7cea287a20d77" dependencies = [ "borsh-derive", "cfg_aliases", @@ -1174,15 +1229,15 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.4.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51670c3aa053938b0ee3bd67c3817e471e626151131b934038e83c5bf8de48f5" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" dependencies = [ "once_cell", "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", "syn_derive", ] @@ -1240,9 +1295,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytemuck" -version = "1.15.0" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" [[package]] name = "byteorder" @@ -1272,9 +1327,9 @@ dependencies = [ [[package]] name = "c-kzg" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3130f3d8717cc02e668a896af24984d5d5d4e8bf12e278e982e0f1bd88a0f9af" +checksum = "cdf100c4cea8f207e883ff91ca886d621d8a166cb04971dfaa9bb8fd99ed95df" dependencies = [ "blst", "cc", @@ -1286,9 +1341,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" dependencies = [ "serde", ] @@ -1310,7 +1365,7 @@ checksum = "e7daec1a2a2129eeba1644b220b4647ec537b0b5d4bfd6876fcc5a540056b592" dependencies = [ "camino", "cargo-platform", - "semver 1.0.22", + "semver 1.0.23", "serde", "serde_json", "thiserror", @@ -1318,11 +1373,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.88" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" dependencies = [ + "jobserver", "libc", + "once_cell", ] [[package]] @@ -1391,7 +1448,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -1400,7 +1457,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd94671561e36e4e7de75f753f577edafb0e7c05d6e4547229fdf7938fbcd2c3" dependencies = [ - "core2 0.4.0", + "core2", "multibase", "multihash 0.18.1", "serde", @@ -1443,9 +1500,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", @@ -1454,9 +1511,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.4" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" dependencies = [ "clap_builder", "clap_derive", @@ -1464,9 +1521,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" dependencies = [ "anstream", "anstyle", @@ -1476,21 +1533,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.4" +version = "4.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "codespan-reporting" @@ -1504,24 +1561,24 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "concurrent-queue" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] [[package]] name = "const-hex" -version = "1.11.3" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ba00838774b4ab0233e355d26710fbfc8327a05c017f6dc4873f876d1f79f78" +checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6" dependencies = [ "cfg-if", "cpufeatures", @@ -1584,15 +1641,6 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" -[[package]] -name = "core2" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239fa3ae9b63c2dc74bd3fa852d4792b8b305ae64eeede946265b6af62f1fff3" -dependencies = [ - "memchr", -] - [[package]] name = "core2" version = "0.4.0" @@ -1730,9 +1778,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -1758,9 +1806,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -1802,9 +1850,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", @@ -1812,7 +1860,6 @@ dependencies = [ "digest 0.10.7", "fiat-crypto", "group", - "platforms", "rand_core", "rustc_version 0.4.0", "subtle", @@ -1827,14 +1874,14 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] name = "cxx" -version = "1.0.121" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21db378d04296a84d8b7d047c36bb3954f0b46529db725d7e62fb02f9ba53ccc" +checksum = "273dcfd3acd4e1e276af13ed2a43eea7001318823e7a726a6b3ed39b4acc0b82" dependencies = [ "cc", "cxxbridge-flags", @@ -1844,9 +1891,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.121" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5262a7fa3f0bae2a55b767c223ba98032d7c328f5c13fa5cdc980b77fc0658" +checksum = "d8b2766fbd92be34e9ed143898fce6c572dc009de39506ed6903e5a05b68914e" dependencies = [ "cc", "codespan-reporting", @@ -1854,24 +1901,24 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] name = "cxxbridge-flags" -version = "1.0.121" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8dcadd2e2fb4a501e1d9e93d6e88e6ea494306d8272069c92d5a9edf8855c0" +checksum = "839fcd5e43464614ffaa989eaf1c139ef1f0c51672a1ed08023307fa1b909ccd" [[package]] name = "cxxbridge-macro" -version = "1.0.121" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad08a837629ad949b73d032c637653d069e909cffe4ee7870b02301939ce39cc" +checksum = "4b2c1c1776b986979be68bb2285da855f8d8a35851a769fca8740df7c3d07877" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -1897,23 +1944,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "lock_api", "once_cell", - "parking_lot_core 0.9.9", + "parking_lot_core 0.9.10", ] [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "data-encoding-macro" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20c01c06f5f429efdf2bae21eb67c28b3df3cf85b7dd2d8ef09c0838dac5d33e" +checksum = "f1559b6cba622276d6d63706db152618eeb15b89b3e4041446b05876e352e639" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -1921,9 +1968,9 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0047d07f2c89b17dd631c80450d69841a6b5d7fb17278cbc43d7e4cfcf2576f3" +checksum = "332d754c0af53bc87c108fed664d121ecf59207ec4196041f04d6ab9002ad33f" dependencies = [ "data-encoding", "syn 1.0.109", @@ -1996,15 +2043,15 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version 0.4.0", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] @@ -2083,7 +2130,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -2235,7 +2282,7 @@ checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" dependencies = [ "curve25519-dalek", "ed25519", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "hex", "rand_core", "sha2", @@ -2244,9 +2291,9 @@ dependencies = [ [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "elliptic-curve" @@ -2289,7 +2336,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -2319,9 +2366,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -2337,7 +2384,7 @@ dependencies = [ "alloy-node-bindings", "alloy-provider", "alloy-rpc-client", - "alloy-rpc-types", + "alloy-rpc-types-eth", "alloy-simple-request-transport", "alloy-sol-types", "flexible-transcript", @@ -2357,9 +2404,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "4.0.3" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ "concurrent-queue", "parking", @@ -2368,11 +2415,11 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "event-listener 4.0.3", + "event-listener 5.3.1", "pin-project-lite 0.2.14", ] @@ -2395,7 +2442,7 @@ dependencies = [ "fs-err", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -2406,9 +2453,9 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fastrlp" @@ -2457,9 +2504,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c007b1ae3abe1cb6f85a16305acd418b7ca6343b953633fee2b76d8f108b830f" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "file-per-thread-logger" @@ -2495,7 +2542,7 @@ dependencies = [ "log", "num-traits", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "scale-info", ] @@ -2670,7 +2717,7 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -2682,7 +2729,7 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -2692,7 +2739,7 @@ source = "git+https://github.com/serai-dex/substrate#6e3f07bf5c98a6a3ec15f2b1a46 dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -2851,7 +2898,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -2861,7 +2908,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35bd3cf68c183738046838e300353e4716c674dc5e56890de4826801a6622a28" dependencies = [ "futures-io", - "rustls 0.21.11", + "rustls 0.21.12", ] [[package]] @@ -2941,15 +2988,16 @@ dependencies = [ [[package]] name = "generator" -version = "0.7.5" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +checksum = "186014d53bc231d0090ef8d6f03e0920c54d85a5ed22f4f2f74315ec56cf83fb" dependencies = [ "cc", + "cfg-if", "libc", "log", "rustversion", - "windows 0.48.0", + "windows 0.54.0", ] [[package]] @@ -2974,15 +3022,25 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", "wasi", ] +[[package]] +name = "getrandom_or_panic" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9" +dependencies = [ + "rand", + "rand_core", +] + [[package]] name = "ghash" version = "0.5.1" @@ -3006,9 +3064,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "glob" @@ -3025,8 +3083,8 @@ dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.6", - "regex-syntax 0.8.3", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] @@ -3091,9 +3149,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", @@ -3128,11 +3186,11 @@ dependencies = [ [[package]] name = "hex-conservative" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed443af458ccb6d81c1e7e661545f94d3176752fb1df2f543b902a1e0f51e2" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" dependencies = [ - "core2 0.3.3", + "arrayvec", ] [[package]] @@ -3236,12 +3294,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", + "futures-util", "http 1.1.0", "http-body 1.0.0", "pin-project-lite 0.2.14", @@ -3255,9 +3313,9 @@ checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "d0e7a4dd27b9476dc40cb050d3632d3bba3a70ddbff012285f7f8559a1e7e545" [[package]] name = "httpdate" @@ -3273,9 +3331,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" dependencies = [ "bytes", "futures-channel", @@ -3316,15 +3374,15 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "908bb38696d7a037a01ebcc68a00634112ac2bbf8ca74e30a2c3d2f4f021302b" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", "http 1.1.0", "hyper 1.3.1", "hyper-util", - "rustls 0.23.5", + "rustls 0.23.10", "rustls-native-certs", "rustls-pki-types", "tokio", @@ -3334,9 +3392,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" dependencies = [ "bytes", "futures-channel", @@ -3345,7 +3403,7 @@ dependencies = [ "http-body 1.0.0", "hyper 1.3.1", "pin-project-lite 0.2.14", - "socket2 0.5.6", + "socket2 0.5.7", "tokio", "tower", "tower-service", @@ -3360,7 +3418,7 @@ checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c" dependencies = [ "futures-util", "hex", - "hyper 0.14.28", + "hyper 0.14.29", "pin-project", "tokio", ] @@ -3376,7 +3434,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.51.1", ] [[package]] @@ -3459,7 +3517,7 @@ dependencies = [ "bytes", "futures", "http 0.2.12", - "hyper 0.14.28", + "hyper 0.14.29", "log", "rand", "tokio", @@ -3514,7 +3572,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "serde", ] @@ -3530,9 +3588,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] @@ -3558,7 +3616,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2 0.5.6", + "socket2 0.5.7", "widestring", "windows-sys 0.48.0", "winreg", @@ -3574,6 +3632,12 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" name = "is-terminal" version = "0.4.10" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.10.5" @@ -3592,12 +3656,30 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "jobserver" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.69" @@ -3633,9 +3715,9 @@ dependencies = [ "futures-channel", "futures-util", "globset", - "hyper 0.14.28", + "hyper 0.14.29", "jsonrpsee-types", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "rustc-hash", "serde", @@ -3668,7 +3750,7 @@ dependencies = [ "futures-channel", "futures-util", "http 0.2.12", - "hyper 0.14.28", + "hyper 0.14.29", "jsonrpsee-core", "jsonrpsee-types", "serde", @@ -3706,6 +3788,7 @@ dependencies = [ "elliptic-curve", "once_cell", "sha2", + "signature", ] [[package]] @@ -3719,9 +3802,9 @@ dependencies = [ [[package]] name = "keccak-asm" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb8515fff80ed850aea4a1595f2e519c003e2a00a82fe168ebf5269196caf444" +checksum = "47a3633291834c4fbebf8673acbc1b04ec9d151418ff9b8e26dcd79129928758" dependencies = [ "digest 0.10.7", "sha3-asm", @@ -3743,7 +3826,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf7a85fe66f9ff9cd74e169fdd2c94c6e1e74c412c99a73b4df3200b5d3760b2" dependencies = [ "kvdb", - "parking_lot 0.12.1", + "parking_lot 0.12.3", ] [[package]] @@ -3754,7 +3837,7 @@ checksum = "b644c70b92285f66bfc2032922a79000ea30af7bc2ab31902992a5dcb9b434f6" dependencies = [ "kvdb", "num_cpus", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "regex", "rocksdb 0.21.0", "smallvec", @@ -3782,9 +3865,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" @@ -3793,7 +3876,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.52.4", + "windows-targets 0.48.5", ] [[package]] @@ -3881,7 +3964,7 @@ dependencies = [ "multihash 0.19.1", "multistream-select", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project", "quick-protobuf", "rand", @@ -3903,7 +3986,7 @@ dependencies = [ "libp2p-core", "libp2p-identity", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "smallvec", "trust-dns-resolver", ] @@ -3965,9 +4048,9 @@ dependencies = [ [[package]] name = "libp2p-identity" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "999ec70441b2fb35355076726a6bc466c932e9bdc66f6a11c6c0aa17c7ab9be0" +checksum = "55cca1eb2bc1fd29f099f3daaab7effd01e1a54b7c577d0ed082521034d912e8" dependencies = [ "bs58", "ed25519-dalek", @@ -4025,7 +4108,7 @@ dependencies = [ "log", "rand", "smallvec", - "socket2 0.5.6", + "socket2 0.5.7", "tokio", "trust-dns-proto 0.22.0", "void", @@ -4106,12 +4189,12 @@ dependencies = [ "libp2p-identity", "libp2p-tls", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "quinn", "rand", "ring 0.16.20", - "rustls 0.21.11", - "socket2 0.5.6", + "rustls 0.21.12", + "socket2 0.5.7", "thiserror", "tokio", ] @@ -4167,7 +4250,7 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -4183,7 +4266,7 @@ dependencies = [ "libp2p-core", "libp2p-identity", "log", - "socket2 0.5.6", + "socket2 0.5.7", "tokio", ] @@ -4199,7 +4282,7 @@ dependencies = [ "libp2p-identity", "rcgen", "ring 0.16.20", - "rustls 0.21.11", + "rustls 0.21.12", "rustls-webpki 0.101.7", "thiserror", "x509-parser", @@ -4248,7 +4331,7 @@ dependencies = [ "libp2p-core", "libp2p-identity", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "quicksink", "rw-stream-sink", "soketto", @@ -4269,6 +4352,16 @@ dependencies = [ "yamux", ] +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.5.0", + "libc", +] + [[package]] name = "librocksdb-sys" version = "0.16.0+8.10.0" @@ -4287,9 +4380,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.16" +version = "1.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e143b5e666b2695d28f6bca6497720813f699c9602dd7f5cac91008b8ada7f9" +checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e" dependencies = [ "cc", "pkg-config", @@ -4331,15 +4424,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -4353,9 +4446,9 @@ checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "loom" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e045d70ddfbc984eacfa964ded019534e8f6cbf36f6410aee0ed5cefa5a9175" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" dependencies = [ "cfg-if", "generator", @@ -4370,7 +4463,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -4384,9 +4477,9 @@ dependencies = [ [[package]] name = "lz4" -version = "1.24.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1" +checksum = "d6eab492fe7f8651add23237ea56dbf11b3c4ff762ab83d40a47f11433421f91" dependencies = [ "libc", "lz4-sys", @@ -4394,9 +4487,9 @@ dependencies = [ [[package]] name = "lz4-sys" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +checksum = "e9764018d143cc854c9f17f0b907de70f14393b1f502da6375dce70f00514eb3" dependencies = [ "cc", "libc", @@ -4420,7 +4513,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -4434,7 +4527,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -4445,7 +4538,7 @@ checksum = "d710e1214dffbab3b5dacb21475dde7d6ed84c69ff722b3a47a782668d44fbac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -4456,7 +4549,7 @@ checksum = "b8fb85ec1620619edf2984a7693497d4ec88a9665d8b87e942856884c92dbf2a" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -4509,9 +4602,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memfd" @@ -4592,9 +4685,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] @@ -4757,7 +4850,7 @@ dependencies = [ "blake2b_simd", "blake2s_simd", "blake3", - "core2 0.4.0", + "core2", "digest 0.10.7", "multihash-derive 0.8.0", "sha2", @@ -4771,7 +4864,7 @@ version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "076d548d76a0e2a0d4ab471d0b1c36c577786dfc4471242035d97a12a735c492" dependencies = [ - "core2 0.4.0", + "core2", "unsigned-varint", ] @@ -4784,7 +4877,7 @@ dependencies = [ "blake2b_simd", "blake2s_simd", "blake3", - "core2 0.4.0", + "core2", "digest 0.10.7", "multihash-derive 0.9.0", "ripemd", @@ -4814,7 +4907,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "890e72cb7396cb99ed98c1246a97b243cc16394470d94e0bc8b0c2c11d84290e" dependencies = [ - "core2 0.4.0", + "core2", "multihash 0.19.1", "multihash-derive-impl", ] @@ -4855,9 +4948,9 @@ dependencies = [ [[package]] name = "nalgebra" -version = "0.32.5" +version = "0.32.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea4908d4f23254adda3daa60ffef0f1ac7b8c3e9a864cf3cc154b251908a2ef" +checksum = "7b5c17de023a86f59ed79891b2e5d5a94c705dbe904a5b5c9c952ea6221b03e4" dependencies = [ "approx", "matrixmultiply", @@ -5000,24 +5093,29 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" dependencies = [ - "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-complex" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-format" version = "0.4.4" @@ -5039,11 +5137,10 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", "num-bigint", "num-integer", "num-traits", @@ -5051,9 +5148,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -5069,6 +5166,26 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "object" version = "0.31.1" @@ -5083,9 +5200,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" dependencies = [ "memchr", ] @@ -5305,7 +5422,7 @@ dependencies = [ "log", "lz4", "memmap2", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "siphasher", "snap", @@ -5314,9 +5431,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec", "bitvec", @@ -5329,11 +5446,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 2.0.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -5354,49 +5471,38 @@ checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", + "parking_lot 0.12.3", ] [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core 0.9.9", + "parking_lot_core 0.9.10", ] [[package]] name = "parking_lot_core" version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", + "parking_lot_core 0.9.10", ] [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall 0.5.2", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -5433,9 +5539,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pbkdf2" @@ -5475,9 +5581,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.9" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" dependencies = [ "memchr", "thiserror", @@ -5486,9 +5592,9 @@ dependencies = [ [[package]] name = "petgraph" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", "indexmap 2.2.6", @@ -5511,7 +5617,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -5548,17 +5654,11 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" -[[package]] -name = "platforms" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" - [[package]] name = "polling" -version = "3.6.0" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c976a60b2d7e99d6f229e414670a9b85d13ac305cc6d1e9c134de58c5aaaf6" +checksum = "5e6a007746f34ed64099e88783b0ae369eaa3da6392868ba262e2af9b8fbaea1" dependencies = [ "cfg-if", "concurrent-queue", @@ -5724,29 +5824,29 @@ checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] [[package]] name = "prometheus" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" +checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" dependencies = [ "cfg-if", "fnv", "lazy_static", "memchr", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "thiserror", ] @@ -5758,7 +5858,7 @@ checksum = "3c99afa9a01501019ac3a14d71d9f94050346f55ca471ce90c799a15c58f61e2" dependencies = [ "dtoa", "itoa", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "prometheus-client-derive-encode", ] @@ -5770,7 +5870,7 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -5787,7 +5887,7 @@ dependencies = [ "rand", "rand_chacha", "rand_xorshift", - "regex-syntax 0.8.3", + "regex-syntax 0.8.4", "rusty-fork", "tempfile", "unarray", @@ -5907,7 +6007,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.21.11", + "rustls 0.21.12", "thiserror", "tokio", "tracing", @@ -5923,7 +6023,7 @@ dependencies = [ "rand", "ring 0.16.20", "rustc-hash", - "rustls 0.21.11", + "rustls 0.21.12", "slab", "thiserror", "tinyvec", @@ -5938,7 +6038,7 @@ checksum = "055b4e778e8feb9f93c4e439f71dc2156ef13360b432b799e179a8c4cdf0b1d7" dependencies = [ "bytes", "libc", - "socket2 0.5.6", + "socket2 0.5.7", "tracing", "windows-sys 0.48.0", ] @@ -6056,51 +6156,51 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ "getrandom", - "redox_syscall 0.2.16", + "libredox", "thiserror", ] [[package]] name = "ref-cast" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4846d4c50d1721b1a3bef8af76924eef20d5e723647333798c1b519b3a9473f" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -6118,14 +6218,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.3", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] @@ -6139,13 +6239,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.3", + "regex-syntax 0.8.4", ] [[package]] @@ -6156,9 +6256,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "resolv-conf" @@ -6284,9 +6384,9 @@ dependencies = [ [[package]] name = "ruint" -version = "1.12.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f308135fef9fc398342da5472ce7c484529df23743fb7c734e0f3d472971e62" +checksum = "2c3cc4c2511671f327125da14133d0c5c5d137f006a1017a16f557bc85b16286" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", @@ -6308,15 +6408,15 @@ dependencies = [ [[package]] name = "ruint-macro" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -6345,7 +6445,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.22", + "semver 1.0.23", ] [[package]] @@ -6359,9 +6459,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.32" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ "bitflags 2.5.0", "errno", @@ -6372,9 +6472,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.11" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring 0.17.8", @@ -6384,14 +6484,14 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.5" +version = "0.23.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afabcee0551bd1aa3e18e5adbf2c0544722014b899adb31bd186ec638d3da97e" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" dependencies = [ "once_cell", "ring 0.17.8", "rustls-pki-types", - "rustls-webpki 0.102.2", + "rustls-webpki 0.102.4", "subtle", "zeroize", ] @@ -6415,15 +6515,15 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64 0.22.0", + "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.4.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] name = "rustls-webpki" @@ -6437,9 +6537,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.2" +version = "0.102.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" dependencies = [ "ring 0.17.8", "rustls-pki-types", @@ -6448,9 +6548,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "rusty-fork" @@ -6477,15 +6577,15 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "safe_arch" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f398075ce1e6a179b46f51bd88d0598b92b00d3551f1a2d4ac49e771b56ac354" +checksum = "c3460605018fdc9612bce72735cba0d27efbcd9904780d44c7e3a9948f96148a" dependencies = [ "bytemuck", ] @@ -6603,7 +6703,7 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -6654,7 +6754,7 @@ dependencies = [ "futures", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-executor", "sc-transaction-pool-api", "sc-utils", @@ -6683,7 +6783,7 @@ dependencies = [ "log", "parity-db", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-client-api", "sc-state-db", "schnellru", @@ -6707,7 +6807,7 @@ dependencies = [ "libp2p-identity", "log", "mockall", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-client-api", "sc-utils", "serde", @@ -6734,7 +6834,7 @@ dependencies = [ "num-rational", "num-traits", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-client-api", "sc-consensus", "sc-consensus-epochs", @@ -6785,7 +6885,7 @@ dependencies = [ "futures-timer", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "sc-block-builder", "sc-chain-spec", @@ -6840,7 +6940,7 @@ version = "0.10.0-dev" source = "git+https://github.com/serai-dex/substrate#6e3f07bf5c98a6a3ec15f2b1a46148aa8c7d737a" dependencies = [ "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-executor-common", "sc-executor-wasmtime", "schnellru", @@ -6907,7 +7007,7 @@ version = "4.0.0-dev" source = "git+https://github.com/serai-dex/substrate#6e3f07bf5c98a6a3ec15f2b1a46148aa8c7d737a" dependencies = [ "array-bytes", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "serde_json", "sp-application-crypto", "sp-core", @@ -6935,7 +7035,7 @@ dependencies = [ "log", "mockall", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "partial_sort", "pin-project", "rand", @@ -7095,13 +7195,13 @@ dependencies = [ "fnv", "futures", "futures-timer", - "hyper 0.14.28", + "hyper 0.14.29", "libp2p", "log", "num_cpus", "once_cell", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "sc-client-api", "sc-network", @@ -7135,7 +7235,7 @@ dependencies = [ "jsonrpsee", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-block-builder", "sc-chain-spec", "sc-client-api", @@ -7202,7 +7302,7 @@ dependencies = [ "jsonrpsee", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-chain-spec", "sc-client-api", "sc-transaction-pool-api", @@ -7229,7 +7329,7 @@ dependencies = [ "jsonrpsee", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project", "rand", "sc-block-builder", @@ -7286,7 +7386,7 @@ source = "git+https://github.com/serai-dex/substrate#6e3f07bf5c98a6a3ec15f2b1a46 dependencies = [ "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sp-core", ] @@ -7318,7 +7418,7 @@ dependencies = [ "futures", "libp2p", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project", "rand", "sc-utils", @@ -7338,7 +7438,7 @@ dependencies = [ "lazy_static", "libc", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "regex", "rustc-hash", "sc-client-api", @@ -7364,7 +7464,7 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -7378,7 +7478,7 @@ dependencies = [ "linked-hash-map", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sc-client-api", "sc-transaction-pool-api", "sc-utils", @@ -7419,16 +7519,16 @@ dependencies = [ "futures-timer", "lazy_static", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "prometheus", "sp-arithmetic", ] [[package]] name = "scale-info" -version = "2.11.2" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c453e59a955f81fb62ee5d596b450383d699f152d350e9d23a0db2adb78e4c0" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" dependencies = [ "bitvec", "cfg-if", @@ -7440,11 +7540,11 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.11.2" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18cf6c6447f813ef19eb450e985bcce6705f9ce7660db221b59093d15c79c4b7" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -7461,9 +7561,9 @@ dependencies = [ [[package]] name = "schnellru" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "772575a524feeb803e5b0fcbc6dd9f367e579488197c94c6e4023aad2305774d" +checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" dependencies = [ "ahash", "cfg-if", @@ -7487,15 +7587,16 @@ dependencies = [ [[package]] name = "schnorrkel" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da18ffd9f2f5d01bc0b3050b37ce7728665f926b4dd1157fe3221b05737d924f" +checksum = "8de18f6d8ba0aad7045f5feae07ec29899c1112584a38509a84ad7b04451eaa0" dependencies = [ + "aead", "arrayref", "arrayvec", "curve25519-dalek", + "getrandom_or_panic", "merlin", - "rand", "rand_core", "serde_bytes", "sha2", @@ -7547,9 +7648,9 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.28.2" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" +checksum = "0e0cc0f1cf93f4969faf3ea1c7d8a9faed25918d96affa959720823dfe86d4f3" dependencies = [ "bitcoin_hashes", "rand", @@ -7559,9 +7660,9 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.9.2" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" +checksum = "1433bd67156263443f14d603720b082dd3121779323fce20cba2aa07b874bc1b" dependencies = [ "cc", ] @@ -7577,11 +7678,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "core-foundation", "core-foundation-sys", "libc", @@ -7590,9 +7691,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", "libc", @@ -7618,9 +7719,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] @@ -7818,6 +7919,17 @@ dependencies = [ name = "serai-env" version = "0.1.0" +[[package]] +name = "serai-ethereum-relayer" +version = "0.1.0" +dependencies = [ + "env_logger", + "log", + "serai-db", + "serai-env", + "tokio", +] + [[package]] name = "serai-full-stack-tests" version = "0.1.0" @@ -7974,6 +8086,7 @@ dependencies = [ "hex", "jsonrpsee", "libp2p", + "log", "pallet-transaction-payment-rpc", "rand_core", "sc-authority-discovery", @@ -8104,6 +8217,7 @@ dependencies = [ "dockertest", "ethereum-serai", "hex", + "k256", "monero-serai", "parity-scale-codec", "rand_core", @@ -8140,7 +8254,7 @@ dependencies = [ "frame-support", "frame-system", "frame-system-rpc-runtime-api", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "pallet-authorship", "pallet-babe", "pallet-grandpa", @@ -8149,6 +8263,7 @@ dependencies = [ "pallet-transaction-payment-rpc-runtime-api", "parity-scale-codec", "scale-info", + "serai-abi", "serai-coins-pallet", "serai-dex-pallet", "serai-genesis-liquidity-pallet", @@ -8206,7 +8321,7 @@ version = "0.1.0" dependencies = [ "frame-support", "frame-system", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "pallet-babe", "pallet-grandpa", "parity-scale-codec", @@ -8242,9 +8357,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.198" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] @@ -8260,20 +8375,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.198" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -8288,14 +8403,14 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" dependencies = [ "serde", ] @@ -8314,11 +8429,11 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.7.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" +checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", @@ -8376,9 +8491,9 @@ dependencies = [ [[package]] name = "sha3-asm" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac61da6b35ad76b195eb4771210f947734321a8d81d7738e1580d953bc7a15e" +checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40" dependencies = [ "cc", "cfg-if", @@ -8401,9 +8516,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -8507,9 +8622,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -8563,7 +8678,7 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -8624,7 +8739,7 @@ dependencies = [ "futures", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "schnellru", "sp-api", "sp-consensus", @@ -8717,7 +8832,7 @@ dependencies = [ "log", "merlin", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "paste", "primitive-types", "rand", @@ -8759,7 +8874,7 @@ source = "git+https://github.com/serai-dex/substrate#6e3f07bf5c98a6a3ec15f2b1a46 dependencies = [ "quote", "sp-core-hashing", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -8768,7 +8883,7 @@ version = "4.0.0-dev" source = "git+https://github.com/serai-dex/substrate#6e3f07bf5c98a6a3ec15f2b1a46148aa8c7d737a" dependencies = [ "kvdb", - "parking_lot 0.12.1", + "parking_lot 0.12.3", ] [[package]] @@ -8778,7 +8893,7 @@ source = "git+https://github.com/serai-dex/substrate#6e3f07bf5c98a6a3ec15f2b1a46 dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -8845,7 +8960,7 @@ version = "0.27.0" source = "git+https://github.com/serai-dex/substrate#6e3f07bf5c98a6a3ec15f2b1a46148aa8c7d737a" dependencies = [ "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "sp-core", "sp-externalities", "thiserror", @@ -8950,7 +9065,7 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -8990,7 +9105,7 @@ dependencies = [ "hash-db", "log", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "smallvec", "sp-core", @@ -9062,12 +9177,12 @@ source = "git+https://github.com/serai-dex/substrate#6e3f07bf5c98a6a3ec15f2b1a46 dependencies = [ "ahash", "hash-db", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "lazy_static", "memory-db", "nohash-hasher", "parity-scale-codec", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "scale-info", "schnellru", "sp-core", @@ -9103,7 +9218,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -9221,7 +9336,7 @@ dependencies = [ name = "std-shims" version = "0.1.1" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", "spin 0.9.8", ] @@ -9259,6 +9374,15 @@ dependencies = [ "strum_macros 0.25.3", ] +[[package]] +name = "strum" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +dependencies = [ + "strum_macros 0.26.4", +] + [[package]] name = "strum_macros" version = "0.24.3" @@ -9282,7 +9406,20 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.60", + "syn 2.0.66", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.66", ] [[package]] @@ -9326,7 +9463,7 @@ name = "substrate-prometheus-endpoint" version = "0.10.0-dev" source = "git+https://github.com/serai-dex/substrate#6e3f07bf5c98a6a3ec15f2b1a46148aa8c7d737a" dependencies = [ - "hyper 0.14.28", + "hyper 0.14.29", "log", "prometheus", "thiserror", @@ -9370,9 +9507,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -9381,14 +9518,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.7.2" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa0cefd02f532035d83cfec82647c6eb53140b0485220760e669f4bad489e36" +checksum = "8d71e19bca02c807c9faa67b5a47673ff231b6e7449b251695188522f1dc44b2" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -9400,7 +9537,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -9492,22 +9629,22 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -9531,12 +9668,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.31" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", "serde", "time-core", @@ -9551,10 +9689,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -9603,32 +9742,32 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", "libc", "mio", "num_cpus", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project-lite 0.2.14", "signal-hook-registry", - "socket2 0.5.6", + "socket2 0.5.7", "tokio-macros", "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -9637,7 +9776,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.5", + "rustls 0.23.10", "rustls-pki-types", "tokio", ] @@ -9656,9 +9795,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", @@ -9666,7 +9805,6 @@ dependencies = [ "futures-sink", "pin-project-lite 0.2.14", "tokio", - "tracing", ] [[package]] @@ -9692,9 +9830,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ "serde", ] @@ -9789,7 +9927,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -9982,7 +10120,7 @@ dependencies = [ "ipconfig", "lru-cache", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "rand", "resolv-conf", "smallvec", @@ -10069,9 +10207,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" @@ -10126,9 +10264,9 @@ dependencies = [ [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" @@ -10215,7 +10353,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", "wasm-bindgen-shared", ] @@ -10249,7 +10387,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -10340,7 +10478,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dfcdb72d96f01e6c85b6bf20102e7423bdbaad5c337301bab2bbf253d26413c" dependencies = [ "indexmap 2.2.6", - "semver 1.0.22", + "semver 1.0.23", ] [[package]] @@ -10558,7 +10696,7 @@ checksum = "ca7af9bb3ee875c4907835e607a275d10b04d15623d3aebe01afe8fbd3f85050" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -10591,9 +10729,9 @@ dependencies = [ [[package]] name = "wide" -version = "0.7.16" +version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a1851a719f11d1d2fea40e15c72f6c00de8c142d7ac47c1441cc7e4d0d5bc6" +checksum = "8a040b111774ab63a19ef46bbc149398ab372b4ccdcfd719e9814dbd7dfd76c8" dependencies = [ "bytemuck", "safe_arch", @@ -10623,11 +10761,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -10638,21 +10776,22 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.48.0" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" dependencies = [ + "windows-core 0.51.1", "windows-targets 0.48.5", ] [[package]] name = "windows" -version = "0.51.1" +version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" dependencies = [ - "windows-core", - "windows-targets 0.48.5", + "windows-core 0.54.0", + "windows-targets 0.52.5", ] [[package]] @@ -10664,6 +10803,25 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-core" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" +dependencies = [ + "windows-result", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-result" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b" +dependencies = [ + "windows-targets 0.52.5", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -10679,7 +10837,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -10699,17 +10857,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -10720,9 +10879,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -10732,9 +10891,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -10744,9 +10903,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -10756,9 +10921,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -10768,9 +10933,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -10780,9 +10945,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -10792,9 +10957,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" @@ -10807,9 +10972,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.6" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" +checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" [[package]] name = "winreg" @@ -10883,7 +11048,7 @@ dependencies = [ "futures", "log", "nohash-hasher", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project", "rand", "static_assertions", @@ -10902,34 +11067,35 @@ dependencies = [ name = "zalloc" version = "0.1.0" dependencies = [ + "rustversion", "zeroize", ] [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -10942,7 +11108,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.66", ] [[package]] @@ -10991,9 +11157,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" +version = "2.0.11+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +checksum = "75652c55c0b6f3e6f12eb786fe1bc960396bf05a1eb3bf1f3691c3610ac2e6d4" dependencies = [ "cc", "pkg-config", diff --git a/Cargo.toml b/Cargo.toml index 94b52ffb4..ce0062f01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,8 @@ resolver = "2" members = [ # Version patches + "patches/parking_lot_core", + "patches/parking_lot", "patches/zstd", "patches/rocksdb", "patches/proc-macro-crate", @@ -36,8 +38,11 @@ members = [ "crypto/schnorrkel", "coins/bitcoin", + "coins/ethereum/alloy-simple-request-transport", "coins/ethereum", + "coins/ethereum/relayer", + "coins/monero/generators", "coins/monero", @@ -112,6 +117,8 @@ lazy_static = { git = "https://github.com/rust-lang-nursery/lazy-static.rs", rev # Needed due to dockertest's usage of `Rc`s when we need `Arc`s dockertest = { git = "https://github.com/orcalabs/dockertest-rs", rev = "4dd6ae24738aa6dc5c89444cc822ea4745517493" } +parking_lot_core = { path = "patches/parking_lot_core" } +parking_lot = { path = "patches/parking_lot" } # wasmtime pulls in an old version for this zstd = { path = "patches/zstd" } # Needed for WAL compression diff --git a/coins/bitcoin/Cargo.toml b/coins/bitcoin/Cargo.toml index 4ff0f79a4..f003b36fa 100644 --- a/coins/bitcoin/Cargo.toml +++ b/coins/bitcoin/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT" repository = "https://github.com/serai-dex/serai/tree/develop/coins/bitcoin" authors = ["Luke Parker ", "Vrx "] edition = "2021" -rust-version = "1.74" +rust-version = "1.79" [package.metadata.docs.rs] all-features = true @@ -23,7 +23,7 @@ thiserror = { version = "1", default-features = false, optional = true } zeroize = { version = "^1.5", default-features = false } rand_core = { version = "0.6", default-features = false } -bitcoin = { version = "0.31", default-features = false, features = ["no-std"] } +bitcoin = { version = "0.32", default-features = false } k256 = { version = "^0.13.1", default-features = false, features = ["arithmetic", "bits"] } @@ -36,7 +36,7 @@ serde_json = { version = "1", default-features = false, optional = true } simple-request = { path = "../../common/request", version = "0.1", default-features = false, features = ["tls", "basic-auth"], optional = true } [dev-dependencies] -secp256k1 = { version = "0.28", default-features = false, features = ["std"] } +secp256k1 = { version = "0.29", default-features = false, features = ["std"] } frost = { package = "modular-frost", path = "../../crypto/frost", features = ["tests"] } diff --git a/coins/bitcoin/src/rpc.rs b/coins/bitcoin/src/rpc.rs index 6778636bd..fb1c35d6f 100644 --- a/coins/bitcoin/src/rpc.rs +++ b/coins/bitcoin/src/rpc.rs @@ -195,13 +195,13 @@ impl Rpc { // If this was already successfully published, consider this having succeeded if let RpcError::RequestError(Error { code, .. }) = e { if code == RPC_VERIFY_ALREADY_IN_CHAIN { - return Ok(tx.txid()); + return Ok(tx.compute_txid()); } } Err(e)? } }; - if txid != tx.txid() { + if txid != tx.compute_txid() { Err(RpcError::InvalidResponse("returned TX ID inequals calculated TX ID"))?; } Ok(txid) @@ -215,7 +215,7 @@ impl Rpc { let tx: Transaction = encode::deserialize(&bytes) .map_err(|_| RpcError::InvalidResponse("node sent an improperly serialized transaction"))?; - let mut tx_hash = *tx.txid().as_raw_hash().as_byte_array(); + let mut tx_hash = *tx.compute_txid().as_raw_hash().as_byte_array(); tx_hash.reverse(); if hash != &tx_hash { Err(RpcError::InvalidResponse("node replied with a different transaction"))?; diff --git a/coins/bitcoin/src/tests/crypto.rs b/coins/bitcoin/src/tests/crypto.rs index 2170219c0..cfc694f40 100644 --- a/coins/bitcoin/src/tests/crypto.rs +++ b/coins/bitcoin/src/tests/crypto.rs @@ -39,7 +39,7 @@ fn test_algorithm() { .verify_schnorr( &Signature::from_slice(&sig) .expect("couldn't convert produced signature to secp256k1::Signature"), - &Message::from(Hash::hash(MESSAGE)), + &Message::from_digest_slice(Hash::hash(MESSAGE).as_ref()).unwrap(), &x_only(&keys[&Participant::new(1).unwrap()].group_key()), ) .unwrap() diff --git a/coins/bitcoin/src/wallet/mod.rs b/coins/bitcoin/src/wallet/mod.rs index 3f099faac..195182fff 100644 --- a/coins/bitcoin/src/wallet/mod.rs +++ b/coins/bitcoin/src/wallet/mod.rs @@ -4,7 +4,7 @@ use std_shims::{ io::{self, Write}, }; #[cfg(feature = "std")] -use std_shims::io::Read; +use std::io::{Read, BufReader}; use k256::{ elliptic_curve::sec1::{Tag, ToEncodedPoint}, @@ -18,8 +18,8 @@ use frost::{ }; use bitcoin::{ - consensus::encode::serialize, key::TweakedPublicKey, address::Payload, OutPoint, ScriptBuf, - TxOut, Transaction, Block, + consensus::encode::serialize, key::TweakedPublicKey, OutPoint, ScriptBuf, TxOut, Transaction, + Block, }; #[cfg(feature = "std")] use bitcoin::consensus::encode::Decodable; @@ -46,12 +46,12 @@ pub fn tweak_keys(keys: &ThresholdKeys) -> ThresholdKeys { /// Return the Taproot address payload for a public key. /// /// If the key is odd, this will return None. -pub fn address_payload(key: ProjectivePoint) -> Option { +pub fn p2tr_script_buf(key: ProjectivePoint) -> Option { if key.to_encoded_point(true).tag() != Tag::CompressedEvenY { return None; } - Some(Payload::p2tr_tweaked(TweakedPublicKey::dangerous_assume_tweaked(x_only(&key)))) + Some(ScriptBuf::new_p2tr_tweaked(TweakedPublicKey::dangerous_assume_tweaked(x_only(&key)))) } /// A spendable output. @@ -89,11 +89,17 @@ impl ReceivedOutput { /// Read a ReceivedOutput from a generic satisfying Read. #[cfg(feature = "std")] pub fn read(r: &mut R) -> io::Result { - Ok(ReceivedOutput { - offset: Secp256k1::read_F(r)?, - output: TxOut::consensus_decode(r).map_err(|_| io::Error::other("invalid TxOut"))?, - outpoint: OutPoint::consensus_decode(r).map_err(|_| io::Error::other("invalid OutPoint"))?, - }) + let offset = Secp256k1::read_F(r)?; + let output; + let outpoint; + { + let mut buf_r = BufReader::with_capacity(0, r); + output = + TxOut::consensus_decode(&mut buf_r).map_err(|_| io::Error::other("invalid TxOut"))?; + outpoint = + OutPoint::consensus_decode(&mut buf_r).map_err(|_| io::Error::other("invalid OutPoint"))?; + } + Ok(ReceivedOutput { offset, output, outpoint }) } /// Write a ReceivedOutput to a generic satisfying Write. @@ -124,7 +130,7 @@ impl Scanner { /// Returns None if this key can't be scanned for. pub fn new(key: ProjectivePoint) -> Option { let mut scripts = HashMap::new(); - scripts.insert(address_payload(key)?.script_pubkey(), Scalar::ZERO); + scripts.insert(p2tr_script_buf(key)?, Scalar::ZERO); Some(Scanner { key, scripts }) } @@ -141,9 +147,8 @@ impl Scanner { // chance of being even // That means this should terminate within a very small amount of iterations loop { - match address_payload(self.key + (ProjectivePoint::GENERATOR * offset)) { - Some(address) => { - let script = address.script_pubkey(); + match p2tr_script_buf(self.key + (ProjectivePoint::GENERATOR * offset)) { + Some(script) => { if self.scripts.contains_key(&script) { None?; } @@ -166,7 +171,7 @@ impl Scanner { res.push(ReceivedOutput { offset: *offset, output: output.clone(), - outpoint: OutPoint::new(tx.txid(), vout), + outpoint: OutPoint::new(tx.compute_txid(), vout), }); } } diff --git a/coins/bitcoin/src/wallet/send.rs b/coins/bitcoin/src/wallet/send.rs index 24594ab4f..1980a5548 100644 --- a/coins/bitcoin/src/wallet/send.rs +++ b/coins/bitcoin/src/wallet/send.rs @@ -18,12 +18,12 @@ use bitcoin::{ absolute::LockTime, script::{PushBytesBuf, ScriptBuf}, transaction::{Version, Transaction}, - OutPoint, Sequence, Witness, TxIn, Amount, TxOut, Address, + OutPoint, Sequence, Witness, TxIn, Amount, TxOut, }; use crate::{ crypto::Schnorr, - wallet::{ReceivedOutput, address_payload}, + wallet::{ReceivedOutput, p2tr_script_buf}, }; #[rustfmt::skip] @@ -61,7 +61,11 @@ pub struct SignableTransaction { } impl SignableTransaction { - fn calculate_weight(inputs: usize, payments: &[(Address, u64)], change: Option<&Address>) -> u64 { + fn calculate_weight( + inputs: usize, + payments: &[(ScriptBuf, u64)], + change: Option<&ScriptBuf>, + ) -> u64 { // Expand this a full transaction in order to use the bitcoin library's weight function let mut tx = Transaction { version: Version(2), @@ -86,14 +90,14 @@ impl SignableTransaction { // The script pub key is not of a fixed size and does have to be used here .map(|payment| TxOut { value: Amount::from_sat(payment.1), - script_pubkey: payment.0.script_pubkey(), + script_pubkey: payment.0.clone(), }) .collect(), }; if let Some(change) = change { // Use a 0 value since we're currently unsure what the change amount will be, and since // the value is fixed size (so any value could be used here) - tx.output.push(TxOut { value: Amount::ZERO, script_pubkey: change.script_pubkey() }); + tx.output.push(TxOut { value: Amount::ZERO, script_pubkey: change.clone() }); } u64::from(tx.weight()) } @@ -121,8 +125,8 @@ impl SignableTransaction { /// If data is specified, an OP_RETURN output will be added with it. pub fn new( mut inputs: Vec, - payments: &[(Address, u64)], - change: Option<&Address>, + payments: &[(ScriptBuf, u64)], + change: Option, data: Option>, fee_per_weight: u64, ) -> Result { @@ -159,10 +163,7 @@ impl SignableTransaction { let payment_sat = payments.iter().map(|payment| payment.1).sum::(); let mut tx_outs = payments .iter() - .map(|payment| TxOut { - value: Amount::from_sat(payment.1), - script_pubkey: payment.0.script_pubkey(), - }) + .map(|payment| TxOut { value: Amount::from_sat(payment.1), script_pubkey: payment.0.clone() }) .collect::>(); // Add the OP_RETURN output @@ -213,12 +214,11 @@ impl SignableTransaction { // If there's a change address, check if there's change to give it if let Some(change) = change { - let weight_with_change = Self::calculate_weight(tx_ins.len(), payments, Some(change)); + let weight_with_change = Self::calculate_weight(tx_ins.len(), payments, Some(&change)); let fee_with_change = fee_per_weight * weight_with_change; if let Some(value) = input_sat.checked_sub(payment_sat + fee_with_change) { if value >= DUST { - tx_outs - .push(TxOut { value: Amount::from_sat(value), script_pubkey: change.script_pubkey() }); + tx_outs.push(TxOut { value: Amount::from_sat(value), script_pubkey: change }); weight = weight_with_change; needed_fee = fee_with_change; } @@ -248,7 +248,7 @@ impl SignableTransaction { /// Returns the TX ID of the transaction this will create. pub fn txid(&self) -> [u8; 32] { - let mut res = self.tx.txid().to_byte_array(); + let mut res = self.tx.compute_txid().to_byte_array(); res.reverse(); res } @@ -288,7 +288,7 @@ impl SignableTransaction { transcript.append_message(b"signing_input", u32::try_from(i).unwrap().to_le_bytes()); let offset = keys.clone().offset(self.offsets[i]); - if address_payload(offset.group_key())?.script_pubkey() != self.prevouts[i].script_pubkey { + if p2tr_script_buf(offset.group_key())? != self.prevouts[i].script_pubkey { None?; } diff --git a/coins/bitcoin/tests/wallet.rs b/coins/bitcoin/tests/wallet.rs index 9eca20c78..9db004f57 100644 --- a/coins/bitcoin/tests/wallet.rs +++ b/coins/bitcoin/tests/wallet.rs @@ -22,11 +22,10 @@ use bitcoin_serai::{ hashes::Hash as HashTrait, blockdata::opcodes::all::OP_RETURN, script::{PushBytesBuf, Instruction, Instructions, Script}, - address::NetworkChecked, OutPoint, Amount, TxOut, Transaction, Network, Address, }, wallet::{ - tweak_keys, address_payload, ReceivedOutput, Scanner, TransactionError, SignableTransaction, + tweak_keys, p2tr_script_buf, ReceivedOutput, Scanner, TransactionError, SignableTransaction, }, rpc::Rpc, }; @@ -48,7 +47,7 @@ async fn send_and_get_output(rpc: &Rpc, scanner: &Scanner, key: ProjectivePoint) "generatetoaddress", serde_json::json!([ 1, - Address::::new(Network::Regtest, address_payload(key).unwrap()) + Address::from_script(&p2tr_script_buf(key).unwrap(), Network::Regtest).unwrap() ]), ) .await @@ -69,7 +68,7 @@ async fn send_and_get_output(rpc: &Rpc, scanner: &Scanner, key: ProjectivePoint) assert_eq!(outputs, scanner.scan_transaction(&block.txdata[0])); assert_eq!(outputs.len(), 1); - assert_eq!(outputs[0].outpoint(), &OutPoint::new(block.txdata[0].txid(), 0)); + assert_eq!(outputs[0].outpoint(), &OutPoint::new(block.txdata[0].compute_txid(), 0)); assert_eq!(outputs[0].value(), block.txdata[0].output[0].value.to_sat()); assert_eq!( @@ -193,7 +192,7 @@ async_sequential! { assert_eq!(output.offset(), Scalar::ZERO); let inputs = vec![output]; - let addr = || Address::::new(Network::Regtest, address_payload(key).unwrap()); + let addr = || p2tr_script_buf(key).unwrap(); let payments = vec![(addr(), 1000)]; assert!(SignableTransaction::new(inputs.clone(), &payments, None, None, FEE).is_ok()); @@ -206,7 +205,7 @@ async_sequential! { // No change assert!(SignableTransaction::new(inputs.clone(), &[(addr(), 1000)], None, None, FEE).is_ok()); // Consolidation TX - assert!(SignableTransaction::new(inputs.clone(), &[], Some(&addr()), None, FEE).is_ok()); + assert!(SignableTransaction::new(inputs.clone(), &[], Some(addr()), None, FEE).is_ok()); // Data assert!(SignableTransaction::new(inputs.clone(), &[], None, Some(vec![]), FEE).is_ok()); // No outputs @@ -229,7 +228,7 @@ async_sequential! { ); assert_eq!( - SignableTransaction::new(inputs.clone(), &[], Some(&addr()), None, 0), + SignableTransaction::new(inputs.clone(), &[], Some(addr()), None, 0), Err(TransactionError::TooLowFee), ); @@ -261,20 +260,19 @@ async_sequential! { // Declare payments, change, fee let payments = [ - (Address::::new(Network::Regtest, address_payload(key).unwrap()), 1005), - (Address::::new(Network::Regtest, address_payload(offset_key).unwrap()), 1007) + (p2tr_script_buf(key).unwrap(), 1005), + (p2tr_script_buf(offset_key).unwrap(), 1007) ]; let change_offset = scanner.register_offset(Scalar::random(&mut OsRng)).unwrap(); let change_key = key + (ProjectivePoint::GENERATOR * change_offset); - let change_addr = - Address::::new(Network::Regtest, address_payload(change_key).unwrap()); + let change_addr = p2tr_script_buf(change_key).unwrap(); // Create and sign the TX let tx = SignableTransaction::new( vec![output.clone(), offset_output.clone()], &payments, - Some(&change_addr), + Some(change_addr.clone()), None, FEE ).unwrap(); @@ -287,7 +285,7 @@ async_sequential! { // Ensure we can scan it let outputs = scanner.scan_transaction(&tx); for (o, output) in outputs.iter().enumerate() { - assert_eq!(output.outpoint(), &OutPoint::new(tx.txid(), u32::try_from(o).unwrap())); + assert_eq!(output.outpoint(), &OutPoint::new(tx.compute_txid(), u32::try_from(o).unwrap())); assert_eq!(&ReceivedOutput::read::<&[u8]>(&mut output.serialize().as_ref()).unwrap(), output); } @@ -299,7 +297,7 @@ async_sequential! { for ((output, scanned), payment) in tx.output.iter().zip(outputs.iter()).zip(payments.iter()) { assert_eq!( output, - &TxOut { script_pubkey: payment.0.script_pubkey(), value: Amount::from_sat(payment.1) }, + &TxOut { script_pubkey: payment.0.clone(), value: Amount::from_sat(payment.1) }, ); assert_eq!(scanned.value(), payment.1 ); } @@ -314,13 +312,13 @@ async_sequential! { input_value - payments.iter().map(|payment| payment.1).sum::() - needed_fee; assert_eq!( tx.output[2], - TxOut { script_pubkey: change_addr.script_pubkey(), value: Amount::from_sat(change_amount) }, + TxOut { script_pubkey: change_addr, value: Amount::from_sat(change_amount) }, ); // This also tests send_raw_transaction and get_transaction, which the RPC test can't // effectively test rpc.send_raw_transaction(&tx).await.unwrap(); - let mut hash = *tx.txid().as_raw_hash().as_byte_array(); + let mut hash = *tx.compute_txid().as_raw_hash().as_byte_array(); hash.reverse(); assert_eq!(tx, rpc.get_transaction(&hash).await.unwrap()); assert_eq!(expected_id, hash); @@ -344,7 +342,7 @@ async_sequential! { &SignableTransaction::new( vec![output], &[], - Some(&Address::::new(Network::Regtest, address_payload(key).unwrap())), + Some(p2tr_script_buf(key).unwrap()), Some(data.clone()), FEE ).unwrap() diff --git a/coins/ethereum/Cargo.toml b/coins/ethereum/Cargo.toml index dc30764e9..f454c9d52 100644 --- a/coins/ethereum/Cargo.toml +++ b/coins/ethereum/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/serai-dex/serai/tree/develop/coins/ethereum" authors = ["Luke Parker ", "Elizabeth Binks "] edition = "2021" publish = false -rust-version = "1.74" +rust-version = "1.79" [package.metadata.docs.rs] all-features = true @@ -29,21 +29,21 @@ frost = { package = "modular-frost", path = "../../crypto/frost", default-featur alloy-core = { version = "0.7", default-features = false } alloy-sol-types = { version = "0.7", default-features = false, features = ["json"] } -alloy-consensus = { git = "https://github.com/alloy-rs/alloy", rev = "b79db21734cffddc11753fe62ba571565c896f42", default-features = false, features = ["k256"] } -alloy-network = { git = "https://github.com/alloy-rs/alloy", rev = "b79db21734cffddc11753fe62ba571565c896f42", default-features = false } -alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy", rev = "b79db21734cffddc11753fe62ba571565c896f42", default-features = false } -alloy-rpc-client = { git = "https://github.com/alloy-rs/alloy", rev = "b79db21734cffddc11753fe62ba571565c896f42", default-features = false } +alloy-consensus = { version = "0.1", default-features = false, features = ["k256"] } +alloy-network = { version = "0.1", default-features = false } +alloy-rpc-types-eth = { version = "0.1", default-features = false } +alloy-rpc-client = { version = "0.1", default-features = false } alloy-simple-request-transport = { path = "./alloy-simple-request-transport", default-features = false } -alloy-provider = { git = "https://github.com/alloy-rs/alloy", rev = "b79db21734cffddc11753fe62ba571565c896f42", default-features = false } +alloy-provider = { version = "0.1", default-features = false } -alloy-node-bindings = { git = "https://github.com/alloy-rs/alloy", rev = "b79db21734cffddc11753fe62ba571565c896f42", default-features = false, optional = true } +alloy-node-bindings = { version = "0.1", default-features = false, optional = true } [dev-dependencies] frost = { package = "modular-frost", path = "../../crypto/frost", default-features = false, features = ["tests"] } tokio = { version = "1", features = ["macros"] } -alloy-node-bindings = { git = "https://github.com/alloy-rs/alloy", rev = "b79db21734cffddc11753fe62ba571565c896f42", default-features = false } +alloy-node-bindings = { version = "0.1", default-features = false } [features] -tests = ["alloy-node-bindings"] +tests = ["alloy-node-bindings", "frost/tests"] diff --git a/coins/ethereum/alloy-simple-request-transport/Cargo.toml b/coins/ethereum/alloy-simple-request-transport/Cargo.toml index 0d9ea6b8f..9a192c171 100644 --- a/coins/ethereum/alloy-simple-request-transport/Cargo.toml +++ b/coins/ethereum/alloy-simple-request-transport/Cargo.toml @@ -21,8 +21,8 @@ tower = "0.4" serde_json = { version = "1", default-features = false } simple-request = { path = "../../../common/request", default-features = false } -alloy-json-rpc = { git = "https://github.com/alloy-rs/alloy", rev = "b79db21734cffddc11753fe62ba571565c896f42", default-features = false } -alloy-transport = { git = "https://github.com/alloy-rs/alloy", rev = "b79db21734cffddc11753fe62ba571565c896f42", default-features = false } +alloy-json-rpc = { version = "0.1", default-features = false } +alloy-transport = { version = "0.1", default-features = false } [features] default = ["tls"] diff --git a/coins/ethereum/relayer/Cargo.toml b/coins/ethereum/relayer/Cargo.toml new file mode 100644 index 000000000..22c200760 --- /dev/null +++ b/coins/ethereum/relayer/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "serai-ethereum-relayer" +version = "0.1.0" +description = "A relayer for Serai's Ethereum transactions" +license = "AGPL-3.0-only" +repository = "https://github.com/serai-dex/serai/tree/develop/coins/ethereum/relayer" +authors = ["Luke Parker "] +keywords = [] +edition = "2021" +publish = false + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[lints] +workspace = true + +[dependencies] +log = { version = "0.4", default-features = false, features = ["std"] } +env_logger = { version = "0.10", default-features = false, features = ["humantime"] } + +tokio = { version = "1", default-features = false, features = ["rt", "time", "io-util", "net", "macros"] } + +serai-env = { path = "../../../common/env" } +serai-db = { path = "../../../common/db" } + +[features] +parity-db = ["serai-db/parity-db"] +rocksdb = ["serai-db/rocksdb"] diff --git a/coins/ethereum/relayer/LICENSE b/coins/ethereum/relayer/LICENSE new file mode 100644 index 000000000..26d57cbb3 --- /dev/null +++ b/coins/ethereum/relayer/LICENSE @@ -0,0 +1,15 @@ +AGPL-3.0-only license + +Copyright (c) 2023-2024 Luke Parker + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License Version 3 as +published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . diff --git a/coins/ethereum/relayer/README.md b/coins/ethereum/relayer/README.md new file mode 100644 index 000000000..beed4b724 --- /dev/null +++ b/coins/ethereum/relayer/README.md @@ -0,0 +1,4 @@ +# Ethereum Transaction Relayer + +This server collects Ethereum router commands to be published, offering an RPC +to fetch them. diff --git a/coins/ethereum/relayer/src/main.rs b/coins/ethereum/relayer/src/main.rs new file mode 100644 index 000000000..545930040 --- /dev/null +++ b/coins/ethereum/relayer/src/main.rs @@ -0,0 +1,100 @@ +pub(crate) use tokio::{ + io::{AsyncReadExt, AsyncWriteExt}, + net::TcpListener, +}; + +use serai_db::{Get, DbTxn, Db as DbTrait}; + +#[tokio::main(flavor = "current_thread")] +async fn main() { + // Override the panic handler with one which will panic if any tokio task panics + { + let existing = std::panic::take_hook(); + std::panic::set_hook(Box::new(move |panic| { + existing(panic); + const MSG: &str = "exiting the process due to a task panicking"; + println!("{MSG}"); + log::error!("{MSG}"); + std::process::exit(1); + })); + } + + if std::env::var("RUST_LOG").is_err() { + std::env::set_var("RUST_LOG", serai_env::var("RUST_LOG").unwrap_or_else(|| "info".to_string())); + } + env_logger::init(); + + log::info!("Starting Ethereum relayer server..."); + + // Open the DB + #[allow(unused_variables, unreachable_code)] + let db = { + #[cfg(all(feature = "parity-db", feature = "rocksdb"))] + panic!("built with parity-db and rocksdb"); + #[cfg(all(feature = "parity-db", not(feature = "rocksdb")))] + let db = + serai_db::new_parity_db(&serai_env::var("DB_PATH").expect("path to DB wasn't specified")); + #[cfg(feature = "rocksdb")] + let db = + serai_db::new_rocksdb(&serai_env::var("DB_PATH").expect("path to DB wasn't specified")); + db + }; + + // Start command recipience server + // This should not be publicly exposed + // TODO: Add auth + tokio::spawn({ + let db = db.clone(); + async move { + // 5132 ^ ((b'E' << 8) | b'R') + let server = TcpListener::bind("0.0.0.0:20830").await.unwrap(); + loop { + let (mut socket, _) = server.accept().await.unwrap(); + let db = db.clone(); + tokio::spawn(async move { + let mut db = db.clone(); + loop { + let Ok(msg_len) = socket.read_u32_le().await else { break }; + let mut buf = vec![0; usize::try_from(msg_len).unwrap()]; + let Ok(_) = socket.read_exact(&mut buf).await else { break }; + + if buf.len() < 5 { + break; + } + let nonce = u32::from_le_bytes(buf[.. 4].try_into().unwrap()); + let mut txn = db.txn(); + txn.put(nonce.to_le_bytes(), &buf[4 ..]); + txn.commit(); + + let Ok(()) = socket.write_all(&[1]).await else { break }; + + log::info!("received signed command #{nonce}"); + } + }); + } + } + }); + + // Start command fetch server + // 5132 ^ ((b'E' << 8) | b'R') + 1 + let server = TcpListener::bind("0.0.0.0:20831").await.unwrap(); + loop { + let (mut socket, _) = server.accept().await.unwrap(); + let db = db.clone(); + tokio::spawn(async move { + let db = db.clone(); + loop { + // Nonce to get the router comamnd for + let mut buf = vec![0; 4]; + let Ok(_) = socket.read_exact(&mut buf).await else { break }; + + let command = db.get(&buf[.. 4]).unwrap_or(vec![]); + let Ok(()) = socket.write_all(&u32::try_from(command.len()).unwrap().to_le_bytes()).await + else { + break; + }; + let Ok(()) = socket.write_all(&command).await else { break }; + } + }); + } +} diff --git a/coins/ethereum/src/deployer.rs b/coins/ethereum/src/deployer.rs index 1a16664cb..19aa328d2 100644 --- a/coins/ethereum/src/deployer.rs +++ b/coins/ethereum/src/deployer.rs @@ -5,7 +5,7 @@ use alloy_consensus::{Signed, TxLegacy}; use alloy_sol_types::{SolCall, SolEvent}; -use alloy_rpc_types::{BlockNumberOrTag, Filter}; +use alloy_rpc_types_eth::{BlockNumberOrTag, Filter}; use alloy_simple_request_transport::SimpleRequest; use alloy_provider::{Provider, RootProvider}; @@ -58,14 +58,7 @@ impl Deployer { /// Construct a new view of the `Deployer`. pub async fn new(provider: Arc>) -> Result, Error> { let address = Self::address(); - #[cfg(not(test))] - let required_block = BlockNumberOrTag::Finalized; - #[cfg(test)] - let required_block = BlockNumberOrTag::Latest; - let code = provider - .get_code_at(address.into(), required_block.into()) - .await - .map_err(|_| Error::ConnectionError)?; + let code = provider.get_code_at(address.into()).await.map_err(|_| Error::ConnectionError)?; // Contract has yet to be deployed if code.is_empty() { return Ok(None); diff --git a/coins/ethereum/src/erc20.rs b/coins/ethereum/src/erc20.rs index 1d8744030..6a32f7cc1 100644 --- a/coins/ethereum/src/erc20.rs +++ b/coins/ethereum/src/erc20.rs @@ -4,7 +4,7 @@ use alloy_core::primitives::{Address, B256, U256}; use alloy_sol_types::{SolInterface, SolEvent}; -use alloy_rpc_types::Filter; +use alloy_rpc_types_eth::Filter; use alloy_simple_request_transport::SimpleRequest; use alloy_provider::{Provider, RootProvider}; diff --git a/coins/ethereum/src/lib.rs b/coins/ethereum/src/lib.rs index 322b5f839..38bd79e79 100644 --- a/coins/ethereum/src/lib.rs +++ b/coins/ethereum/src/lib.rs @@ -7,7 +7,7 @@ pub mod alloy { pub use alloy_consensus as consensus; pub use alloy_network as network; - pub use alloy_rpc_types as rpc_types; + pub use alloy_rpc_types_eth as rpc_types; pub use alloy_simple_request_transport as simple_request_transport; pub use alloy_rpc_client as rpc_client; pub use alloy_provider as provider; diff --git a/coins/ethereum/src/router.rs b/coins/ethereum/src/router.rs index 8d46b24f2..c569d4094 100644 --- a/coins/ethereum/src/router.rs +++ b/coins/ethereum/src/router.rs @@ -12,9 +12,9 @@ use alloy_consensus::TxLegacy; use alloy_sol_types::{SolValue, SolConstructor, SolCall, SolEvent}; -use alloy_rpc_types::Filter; +use alloy_rpc_types_eth::Filter; #[cfg(test)] -use alloy_rpc_types::{BlockId, TransactionRequest, TransactionInput}; +use alloy_rpc_types_eth::{BlockId, TransactionRequest, TransactionInput}; use alloy_simple_request_transport::SimpleRequest; use alloy_provider::{Provider, RootProvider}; diff --git a/coins/ethereum/src/tests/mod.rs b/coins/ethereum/src/tests/mod.rs index 085ef3a25..912513ffd 100644 --- a/coins/ethereum/src/tests/mod.rs +++ b/coins/ethereum/src/tests/mod.rs @@ -11,7 +11,7 @@ use alloy_core::{ }; use alloy_consensus::{SignableTransaction, TxLegacy}; -use alloy_rpc_types::{BlockNumberOrTag, TransactionReceipt}; +use alloy_rpc_types_eth::TransactionReceipt; use alloy_simple_request_transport::SimpleRequest; use alloy_provider::{Provider, RootProvider}; @@ -57,15 +57,14 @@ pub async fn send( // let chain_id = provider.get_chain_id().await.unwrap(); // tx.chain_id = Some(chain_id); tx.chain_id = None; - tx.nonce = - provider.get_transaction_count(address, BlockNumberOrTag::Latest.into()).await.unwrap(); + tx.nonce = provider.get_transaction_count(address).await.unwrap(); // 100 gwei tx.gas_price = 100_000_000_000u128; let sig = wallet.sign_prehash_recoverable(tx.signature_hash().as_ref()).unwrap(); assert_eq!(address, tx.clone().into_signed(sig.into()).recover_signer().unwrap()); assert!( - provider.get_balance(address, BlockNumberOrTag::Latest.into()).await.unwrap() > + provider.get_balance(address).await.unwrap() > ((U256::from(tx.gas_price) * U256::from(tx.gas_limit)) + tx.value) ); diff --git a/coins/ethereum/src/tests/router.rs b/coins/ethereum/src/tests/router.rs index 39a865bd9..e3804d7e3 100644 --- a/coins/ethereum/src/tests/router.rs +++ b/coins/ethereum/src/tests/router.rs @@ -14,6 +14,7 @@ use frost::{ use alloy_core::primitives::{Address, U256}; use alloy_simple_request_transport::SimpleRequest; +use alloy_rpc_types_eth::BlockTransactionsKind; use alloy_rpc_client::ClientBuilder; use alloy_provider::{Provider, RootProvider}; @@ -84,7 +85,7 @@ async fn setup_test() -> ( async fn latest_block_hash(client: &RootProvider) -> [u8; 32] { client - .get_block(client.get_block_number().await.unwrap().into(), false) + .get_block(client.get_block_number().await.unwrap().into(), BlockTransactionsKind::Hashes) .await .unwrap() .unwrap() diff --git a/coins/ethereum/src/tests/schnorr.rs b/coins/ethereum/src/tests/schnorr.rs index 21d8b45ae..2c72ed19d 100644 --- a/coins/ethereum/src/tests/schnorr.rs +++ b/coins/ethereum/src/tests/schnorr.rs @@ -15,7 +15,7 @@ use alloy_core::primitives::Address; use alloy_sol_types::SolCall; -use alloy_rpc_types::{TransactionInput, TransactionRequest}; +use alloy_rpc_types_eth::{TransactionInput, TransactionRequest}; use alloy_simple_request_transport::SimpleRequest; use alloy_rpc_client::ClientBuilder; use alloy_provider::{Provider, RootProvider}; diff --git a/coins/monero/Cargo.toml b/coins/monero/Cargo.toml index 357803c92..fb655b844 100644 --- a/coins/monero/Cargo.toml +++ b/coins/monero/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT" repository = "https://github.com/serai-dex/serai/tree/develop/coins/monero" authors = ["Luke Parker "] edition = "2021" -rust-version = "1.74" +rust-version = "1.79" [package.metadata.docs.rs] all-features = true diff --git a/coins/monero/src/wallet/scan.rs b/coins/monero/src/wallet/scan.rs index 0c2cebbdc..45bae04df 100644 --- a/coins/monero/src/wallet/scan.rs +++ b/coins/monero/src/wallet/scan.rs @@ -105,13 +105,13 @@ pub struct Metadata { /// but the payment ID will be returned here anyway: /// /// 1) If the payment ID is tied to an output received by a subaddress account - /// that spent Monero in the transaction (the received output is considered - /// "change" and is not considered a "payment" in this case). If there are multiple - /// spending subaddress accounts in a transaction, the highest index spent key image - /// is used to determine the spending subaddress account. + /// that spent Monero in the transaction (the received output is considered + /// "change" and is not considered a "payment" in this case). If there are multiple + /// spending subaddress accounts in a transaction, the highest index spent key image + /// is used to determine the spending subaddress account. /// /// 2) If the payment ID is the unencrypted variant and the block's hf version is - /// v12 or higher (https://github.com/serai-dex/serai/issues/512) + /// v12 or higher (https://github.com/serai-dex/serai/issues/512) pub payment_id: Option, /// Arbitrary data encoded in TX extra. pub arbitrary_data: Vec>, diff --git a/coins/monero/src/wallet/send/mod.rs b/coins/monero/src/wallet/send/mod.rs index f4ac208e3..153e6b6cf 100644 --- a/coins/monero/src/wallet/send/mod.rs +++ b/coins/monero/src/wallet/send/mod.rs @@ -364,8 +364,8 @@ impl Change { /// 1) The change in the tx is shunted to the fee (fingerprintable fee). /// /// 2) If there are 2 outputs in the tx, there would be no payment ID as is the case when the - /// reference wallet creates 2 output txs, since monero-serai doesn't know which output - /// to tie the dummy payment ID to. + /// reference wallet creates 2 output txs, since monero-serai doesn't know which output + /// to tie the dummy payment ID to. pub fn fingerprintable(address: Option) -> Change { Change { address, view: None } } diff --git a/common/zalloc/Cargo.toml b/common/zalloc/Cargo.toml index 1a4a6b45f..af4e7c1c8 100644 --- a/common/zalloc/Cargo.toml +++ b/common/zalloc/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/serai-dex/serai/tree/develop/common/zalloc" authors = ["Luke Parker "] keywords = [] edition = "2021" -rust-version = "1.60" +rust-version = "1.77.0" [package.metadata.docs.rs] all-features = true @@ -19,8 +19,10 @@ workspace = true [dependencies] zeroize = { version = "^1.5", default-features = false } +[build-dependencies] +rustversion = { version = "1", default-features = false } + [features] std = ["zeroize/std"] default = ["std"] -# Commented for now as it requires nightly and we don't use nightly -# allocator = [] +allocator = [] diff --git a/common/zalloc/build.rs b/common/zalloc/build.rs new file mode 100644 index 000000000..f3351e228 --- /dev/null +++ b/common/zalloc/build.rs @@ -0,0 +1,10 @@ +#[rustversion::nightly] +fn main() { + println!("cargo::rustc-check-cfg=cfg(zalloc_rustc_nightly)"); + println!("cargo::rustc-cfg=zalloc_rustc_nightly"); +} + +#[rustversion::not(nightly)] +fn main() { + println!("cargo::rustc-check-cfg=cfg(zalloc_rustc_nightly)"); +} diff --git a/common/zalloc/src/lib.rs b/common/zalloc/src/lib.rs index 0e4c1f75d..cc5562a0a 100644 --- a/common/zalloc/src/lib.rs +++ b/common/zalloc/src/lib.rs @@ -1,6 +1,6 @@ #![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(docsrs, feature(doc_auto_cfg))] -#![cfg_attr(feature = "allocator", feature(allocator_api))] +#![cfg_attr(all(zalloc_rustc_nightly, feature = "allocator"), feature(allocator_api))] //! Implementation of a Zeroizing Allocator, enabling zeroizing memory on deallocation. //! This can either be used with Box (requires nightly and the "allocator" feature) to provide the @@ -17,12 +17,12 @@ use zeroize::Zeroize; /// An allocator wrapper which zeroizes its memory on dealloc. pub struct ZeroizingAlloc(pub T); -#[cfg(feature = "allocator")] +#[cfg(all(zalloc_rustc_nightly, feature = "allocator"))] use core::{ ptr::NonNull, alloc::{AllocError, Allocator}, }; -#[cfg(feature = "allocator")] +#[cfg(all(zalloc_rustc_nightly, feature = "allocator"))] unsafe impl Allocator for ZeroizingAlloc { fn allocate(&self, layout: Layout) -> Result, AllocError> { self.0.allocate(layout) diff --git a/coordinator/src/db.rs b/coordinator/src/db.rs index 09eab1732..04ee9d350 100644 --- a/coordinator/src/db.rs +++ b/coordinator/src/db.rs @@ -122,7 +122,7 @@ impl QueuedBatchesDb { pub fn take(txn: &mut impl DbTxn, set: ValidatorSet) -> Vec { let batches_vec = Self::get(txn, set).unwrap_or_default(); - txn.del(&Self::key(set)); + txn.del(Self::key(set)); let mut batches: &[u8] = &batches_vec; let mut res = vec![]; diff --git a/coordinator/src/tributary/scanner.rs b/coordinator/src/tributary/scanner.rs index 25c8b5c20..9b56e0a0f 100644 --- a/coordinator/src/tributary/scanner.rs +++ b/coordinator/src/tributary/scanner.rs @@ -133,7 +133,13 @@ mod impl_pst_for_serai { key_pair: KeyPair, signature: Signature, ) { - let tx = SeraiValidatorSets::set_keys(set.network, removed, key_pair, signature); + // TODO: BoundedVec as an arg to avoid this expect + let tx = SeraiValidatorSets::set_keys( + set.network, + removed.try_into().expect("removing more than allowed"), + key_pair, + signature, + ); async fn check(serai: SeraiValidatorSets<'_>, set: ValidatorSet, (): ()) -> bool { if matches!(serai.keys(set).await, Ok(Some(_))) { log::info!("another coordinator set key pair for {:?}", set); diff --git a/coordinator/tributary/tendermint/src/block.rs b/coordinator/tributary/tendermint/src/block.rs index 6dfacfdb7..8fc790188 100644 --- a/coordinator/tributary/tendermint/src/block.rs +++ b/coordinator/tributary/tendermint/src/block.rs @@ -177,14 +177,14 @@ impl BlockData { let new_block = last_block_or_round(&mut txn, LATEST_BLOCK_KEY, self.number.0)?; if new_block { // Delete the latest round key - txn.del(&key(LATEST_ROUND_KEY)); + txn.del(key(LATEST_ROUND_KEY)); } let new_round = last_block_or_round(&mut txn, LATEST_ROUND_KEY, round_number.0.into())?; if new_block || new_round { // Delete the messages for the old round - txn.del(&key(PROPOSE_KEY)); - txn.del(&key(PEVOTE_KEY)); - txn.del(&key(PRECOMMIT_KEY)); + txn.del(key(PROPOSE_KEY)); + txn.del(key(PEVOTE_KEY)); + txn.del(key(PRECOMMIT_KEY)); } // Check we haven't sent this message within this round diff --git a/crypto/dkg/Cargo.toml b/crypto/dkg/Cargo.toml index bf308705e..7ed301f56 100644 --- a/crypto/dkg/Cargo.toml +++ b/crypto/dkg/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/serai-dex/serai/tree/develop/crypto/dkg" authors = ["Luke Parker "] keywords = ["dkg", "multisig", "threshold", "ff", "group"] edition = "2021" -rust-version = "1.74" +rust-version = "1.79" [package.metadata.docs.rs] all-features = true diff --git a/crypto/dkg/src/promote.rs b/crypto/dkg/src/promote.rs index 010abf80f..7cad4f23f 100644 --- a/crypto/dkg/src/promote.rs +++ b/crypto/dkg/src/promote.rs @@ -64,10 +64,7 @@ pub struct GeneratorPromotion { _c2: PhantomData, } -impl GeneratorPromotion -where - C2: Ciphersuite, -{ +impl> GeneratorPromotion { /// Begin promoting keys from one generator to another. Returns a proof this share was properly /// promoted. pub fn promote( diff --git a/crypto/dleq/Cargo.toml b/crypto/dleq/Cargo.toml index c9d525e18..fc25899f3 100644 --- a/crypto/dleq/Cargo.toml +++ b/crypto/dleq/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT" repository = "https://github.com/serai-dex/serai/tree/develop/crypto/dleq" authors = ["Luke Parker "] edition = "2021" -rust-version = "1.74" +rust-version = "1.79" [package.metadata.docs.rs] all-features = true diff --git a/crypto/dleq/src/cross_group/aos.rs b/crypto/dleq/src/cross_group/aos.rs index dac3356ac..b801aa3e7 100644 --- a/crypto/dleq/src/cross_group/aos.rs +++ b/crypto/dleq/src/cross_group/aos.rs @@ -53,11 +53,11 @@ pub(crate) struct Aos - Aos -where - G0::Scalar: PrimeFieldBits + Zeroize, - G1::Scalar: PrimeFieldBits + Zeroize, +impl< + G0: PrimeGroup + Zeroize, + G1: PrimeGroup + Zeroize, + const RING_LEN: usize, + > Aos { #[allow(non_snake_case)] fn nonces(mut transcript: T, nonces: (G0, G1)) -> (G0::Scalar, G1::Scalar) { diff --git a/crypto/dleq/src/cross_group/bits.rs b/crypto/dleq/src/cross_group/bits.rs index a5de897a0..1aeef1405 100644 --- a/crypto/dleq/src/cross_group/bits.rs +++ b/crypto/dleq/src/cross_group/bits.rs @@ -76,14 +76,11 @@ pub(crate) struct Bits< } impl< - G0: PrimeGroup + Zeroize, - G1: PrimeGroup + Zeroize, + G0: PrimeGroup + Zeroize, + G1: PrimeGroup + Zeroize, const SIGNATURE: u8, const RING_LEN: usize, > Bits -where - G0::Scalar: PrimeFieldBits + Zeroize, - G1::Scalar: PrimeFieldBits + Zeroize, { fn transcript(transcript: &mut T, i: usize, commitments: (G0, G1)) { transcript.domain_separate(b"bits"); diff --git a/crypto/dleq/src/cross_group/mod.rs b/crypto/dleq/src/cross_group/mod.rs index 77569c7ca..8014ea9fc 100644 --- a/crypto/dleq/src/cross_group/mod.rs +++ b/crypto/dleq/src/cross_group/mod.rs @@ -112,15 +112,12 @@ pub enum DLEqError { // anyone who wants it #[derive(Clone, PartialEq, Eq, Debug)] pub struct __DLEqProof< - G0: PrimeGroup + Zeroize, - G1: PrimeGroup + Zeroize, + G0: PrimeGroup + Zeroize, + G1: PrimeGroup + Zeroize, const SIGNATURE: u8, const RING_LEN: usize, const REMAINDER_RING_LEN: usize, -> where - G0::Scalar: PrimeFieldBits, - G1::Scalar: PrimeFieldBits, -{ +> { bits: Vec>, remainder: Option>, poks: (SchnorrPoK, SchnorrPoK), @@ -200,15 +197,12 @@ dleq!( ); impl< - G0: PrimeGroup + Zeroize, - G1: PrimeGroup + Zeroize, + G0: PrimeGroup + Zeroize, + G1: PrimeGroup + Zeroize, const SIGNATURE: u8, const RING_LEN: usize, const REMAINDER_RING_LEN: usize, > __DLEqProof -where - G0::Scalar: PrimeFieldBits + Zeroize, - G1::Scalar: PrimeFieldBits + Zeroize, { pub(crate) fn transcript( transcript: &mut T, diff --git a/crypto/dleq/src/cross_group/schnorr.rs b/crypto/dleq/src/cross_group/schnorr.rs index ec5603882..773af09b1 100644 --- a/crypto/dleq/src/cross_group/schnorr.rs +++ b/crypto/dleq/src/cross_group/schnorr.rs @@ -28,10 +28,7 @@ pub(crate) struct SchnorrPoK { s: G::Scalar, } -impl SchnorrPoK -where - G::Scalar: PrimeFieldBits + Zeroize, -{ +impl + Zeroize> SchnorrPoK { // Not HRAm due to the lack of m #[allow(non_snake_case)] fn hra(transcript: &mut T, generator: G, R: G, A: G) -> G::Scalar { diff --git a/crypto/dleq/src/lib.rs b/crypto/dleq/src/lib.rs index 5b813b648..a8958a2ef 100644 --- a/crypto/dleq/src/lib.rs +++ b/crypto/dleq/src/lib.rs @@ -105,19 +105,13 @@ pub enum DLEqError { /// A proof that points have the same discrete logarithm across generators. #[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)] -pub struct DLEqProof -where - G::Scalar: Zeroize, -{ +pub struct DLEqProof> { c: G::Scalar, s: G::Scalar, } #[allow(non_snake_case)] -impl DLEqProof -where - G::Scalar: Zeroize, -{ +impl> DLEqProof { fn transcript(transcript: &mut T, generator: G, nonce: G, point: G) { transcript.append_message(b"generator", generator.to_bytes()); transcript.append_message(b"nonce", nonce.to_bytes()); @@ -213,20 +207,14 @@ where /// across some generators, yet with a smaller overall proof size. #[cfg(feature = "std")] #[derive(Clone, PartialEq, Eq, Debug, Zeroize)] -pub struct MultiDLEqProof -where - G::Scalar: Zeroize, -{ +pub struct MultiDLEqProof> { c: G::Scalar, s: Vec, } #[cfg(feature = "std")] #[allow(non_snake_case)] -impl MultiDLEqProof -where - G::Scalar: Zeroize, -{ +impl> MultiDLEqProof { /// Prove for each scalar that the series of points created by multiplying it against its /// matching generators share a discrete logarithm. /// This function panics if `generators.len() != scalars.len()`. diff --git a/crypto/dleq/src/tests/cross_group/schnorr.rs b/crypto/dleq/src/tests/cross_group/schnorr.rs index e7039e00e..14e1e84b4 100644 --- a/crypto/dleq/src/tests/cross_group/schnorr.rs +++ b/crypto/dleq/src/tests/cross_group/schnorr.rs @@ -14,10 +14,7 @@ use transcript::{Transcript, RecommendedTranscript}; use crate::cross_group::schnorr::SchnorrPoK; -fn test_schnorr() -where - G::Scalar: PrimeFieldBits + Zeroize, -{ +fn test_schnorr + Zeroize>() { let transcript = RecommendedTranscript::new(b"Schnorr Test"); let mut batch = BatchVerifier::new(10); diff --git a/crypto/ed448/src/backend.rs b/crypto/ed448/src/backend.rs index 83dc3fcaa..db41e8110 100644 --- a/crypto/ed448/src/backend.rs +++ b/crypto/ed448/src/backend.rs @@ -34,7 +34,7 @@ macro_rules! math_op { impl $Op<$Other> for $Value { type Output = $Value; fn $op_fn(self, other: $Other) -> Self::Output { - Self($function(self.0, other.0)) + $Value($function(self.0, other.0)) } } impl $Assign<$Other> for $Value { @@ -45,7 +45,7 @@ macro_rules! math_op { impl<'a> $Op<&'a $Other> for $Value { type Output = $Value; fn $op_fn(self, other: &'a $Other) -> Self::Output { - Self($function(self.0, other.0)) + $Value($function(self.0, other.0)) } } impl<'a> $Assign<&'a $Other> for $Value { @@ -60,7 +60,7 @@ macro_rules! from_wrapper { ($wrapper: ident, $inner: ident, $uint: ident) => { impl From<$uint> for $wrapper { fn from(a: $uint) -> $wrapper { - Self(Residue::new(&$inner::from(a))) + $wrapper(Residue::new(&$inner::from(a))) } } }; @@ -127,7 +127,7 @@ macro_rules! field { impl Neg for $FieldName { type Output = $FieldName; fn neg(self) -> $FieldName { - Self(self.0.neg()) + $FieldName(self.0.neg()) } } @@ -141,13 +141,13 @@ macro_rules! field { impl $FieldName { /// Perform an exponentiation. pub fn pow(&self, other: $FieldName) -> $FieldName { - let mut table = [Self(Residue::ONE); 16]; + let mut table = [$FieldName(Residue::ONE); 16]; table[1] = *self; for i in 2 .. 16 { table[i] = table[i - 1] * self; } - let mut res = Self(Residue::ONE); + let mut res = $FieldName(Residue::ONE); let mut bits = 0; for (i, mut bit) in other.to_le_bits().iter_mut().rev().enumerate() { bits <<= 1; @@ -170,8 +170,8 @@ macro_rules! field { } impl Field for $FieldName { - const ZERO: Self = Self(Residue::ZERO); - const ONE: Self = Self(Residue::ONE); + const ZERO: Self = $FieldName(Residue::ZERO); + const ONE: Self = $FieldName(Residue::ONE); fn random(mut rng: impl RngCore) -> Self { let mut bytes = [0; 112]; @@ -188,12 +188,12 @@ macro_rules! field { fn invert(&self) -> CtOption { const NEG_2: $FieldName = - Self($ResidueType::sub(&$ResidueType::ZERO, &$ResidueType::new(&U448::from_u8(2)))); + $FieldName($ResidueType::sub(&$ResidueType::ZERO, &$ResidueType::new(&U448::from_u8(2)))); CtOption::new(self.pow(NEG_2), !self.is_zero()) } fn sqrt(&self) -> CtOption { - const MOD_1_4: $FieldName = Self($ResidueType::new( + const MOD_1_4: $FieldName = $FieldName($ResidueType::new( &$MODULUS.saturating_add(&U448::ONE).wrapping_div(&U448::from_u8(4)), )); @@ -217,14 +217,14 @@ macro_rules! field { const TWO_INV: Self = $FieldName($ResidueType::new(&U448::from_u8(2)).invert().0); const MULTIPLICATIVE_GENERATOR: Self = - Self(Residue::new(&U448::from_u8($MULTIPLICATIVE_GENERATOR))); + $FieldName(Residue::new(&U448::from_u8($MULTIPLICATIVE_GENERATOR))); // True for both the Ed448 Scalar field and FieldElement field const S: u32 = 1; // Both fields have their root of unity as -1 const ROOT_OF_UNITY: Self = - Self($ResidueType::sub(&$ResidueType::ZERO, &$ResidueType::new(&U448::ONE))); - const ROOT_OF_UNITY_INV: Self = Self(Self::ROOT_OF_UNITY.0.invert().0); + $FieldName($ResidueType::sub(&$ResidueType::ZERO, &$ResidueType::new(&U448::ONE))); + const ROOT_OF_UNITY_INV: Self = $FieldName(Self::ROOT_OF_UNITY.0.invert().0); const DELTA: Self = $FieldName(Residue::new(&U448::from_le_hex($DELTA))); diff --git a/crypto/ff-group-tests/Cargo.toml b/crypto/ff-group-tests/Cargo.toml index bb55d5a15..aa328fa1c 100644 --- a/crypto/ff-group-tests/Cargo.toml +++ b/crypto/ff-group-tests/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/serai-dex/serai/tree/develop/crypto/ff-group-te authors = ["Luke Parker "] keywords = ["ff", "group", "ecc"] edition = "2021" -rust-version = "1.60" +rust-version = "1.79" [package.metadata.docs.rs] all-features = true diff --git a/crypto/ff-group-tests/src/group.rs b/crypto/ff-group-tests/src/group.rs index b3f7a155f..0f0aab4e1 100644 --- a/crypto/ff-group-tests/src/group.rs +++ b/crypto/ff-group-tests/src/group.rs @@ -178,10 +178,7 @@ pub fn test_prime_group(rng: &mut R) { } /// Run all tests offered by this crate on the group. -pub fn test_prime_group_bits(rng: &mut R) -where - G::Scalar: PrimeFieldBits, -{ +pub fn test_prime_group_bits>(rng: &mut R) { test_prime_field_bits::(rng); test_prime_group::(rng); } diff --git a/crypto/frost/Cargo.toml b/crypto/frost/Cargo.toml index b89d5290c..7c32b6f08 100644 --- a/crypto/frost/Cargo.toml +++ b/crypto/frost/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/serai-dex/serai/tree/develop/crypto/frost" authors = ["Luke Parker "] keywords = ["frost", "multisig", "threshold"] edition = "2021" -rust-version = "1.74" +rust-version = "1.79" [package.metadata.docs.rs] all-features = true diff --git a/crypto/frost/README.md b/crypto/frost/README.md index 278458443..e6ed2b0a0 100644 --- a/crypto/frost/README.md +++ b/crypto/frost/README.md @@ -10,7 +10,7 @@ integrating with existing systems. This library offers ciphersuites compatible with the [IETF draft](https://github.com/cfrg/draft-irtf-cfrg-frost). Currently, version -11 is supported. +15 is supported. This library was [audited by Cypher Stack in March 2023](https://github.com/serai-dex/serai/raw/e1bb2c191b7123fd260d008e31656d090d559d21/audits/Cypher%20Stack%20crypto%20March%202023/Audit.pdf), diff --git a/crypto/frost/src/sign.rs b/crypto/frost/src/sign.rs index 73ea0a7dc..5115244f1 100644 --- a/crypto/frost/src/sign.rs +++ b/crypto/frost/src/sign.rs @@ -362,9 +362,7 @@ impl> SignMachine for AlgorithmSignMachi rho_transcript.append_message(b"message", C::hash_msg(msg)); rho_transcript.append_message( b"preprocesses", - &C::hash_commitments( - self.params.algorithm.transcript().challenge(b"preprocesses").as_ref(), - ), + C::hash_commitments(self.params.algorithm.transcript().challenge(b"preprocesses").as_ref()), ); // Generate the per-signer binding factors diff --git a/crypto/multiexp/Cargo.toml b/crypto/multiexp/Cargo.toml index 27b47ea9e..228b85ab8 100644 --- a/crypto/multiexp/Cargo.toml +++ b/crypto/multiexp/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/serai-dex/serai/tree/develop/crypto/multiexp" authors = ["Luke Parker "] keywords = ["multiexp", "ff", "group"] edition = "2021" -rust-version = "1.70" +rust-version = "1.79" [package.metadata.docs.rs] all-features = true diff --git a/crypto/multiexp/src/batch.rs b/crypto/multiexp/src/batch.rs index 1cc483494..8016047db 100644 --- a/crypto/multiexp/src/batch.rs +++ b/crypto/multiexp/src/batch.rs @@ -12,27 +12,21 @@ use crate::{multiexp, multiexp_vartime}; // Flatten the contained statements to a single Vec. // Wrapped in Zeroizing in case any of the included statements contain private values. #[allow(clippy::type_complexity)] -fn flat( +fn flat + Zeroize>( slice: &[(Id, Vec<(G::Scalar, G)>)], -) -> Zeroizing> -where - ::Scalar: PrimeFieldBits + Zeroize, -{ +) -> Zeroizing> { Zeroizing::new(slice.iter().flat_map(|pairs| pairs.1.iter()).copied().collect::>()) } /// A batch verifier intended to verify a series of statements are each equivalent to zero. #[allow(clippy::type_complexity)] #[derive(Clone, Zeroize)] -pub struct BatchVerifier( +pub struct BatchVerifier + Zeroize>( Zeroizing)>>, -) -where - ::Scalar: PrimeFieldBits + Zeroize; +); -impl BatchVerifier -where - ::Scalar: PrimeFieldBits + Zeroize, +impl + Zeroize> + BatchVerifier { /// Create a new batch verifier, expected to verify the following amount of statements. /// diff --git a/crypto/multiexp/src/lib.rs b/crypto/multiexp/src/lib.rs index cf0133fca..dfd8e0331 100644 --- a/crypto/multiexp/src/lib.rs +++ b/crypto/multiexp/src/lib.rs @@ -49,10 +49,10 @@ fn u8_from_bool(bit_ref: &mut bool) -> u8 { // Convert scalars to `window`-sized bit groups, as needed to index a table // This algorithm works for `window <= 8` -pub(crate) fn prep_bits(pairs: &[(G::Scalar, G)], window: u8) -> Vec> -where - G::Scalar: PrimeFieldBits, -{ +pub(crate) fn prep_bits>( + pairs: &[(G::Scalar, G)], + window: u8, +) -> Vec> { let w_usize = usize::from(window); let mut groupings = vec![]; @@ -175,10 +175,7 @@ fn algorithm(len: usize) -> Algorithm { /// Performs a multiexponentiation, automatically selecting the optimal algorithm based on the /// amount of pairs. -pub fn multiexp(pairs: &[(G::Scalar, G)]) -> G -where - G::Scalar: PrimeFieldBits + Zeroize, -{ +pub fn multiexp>(pairs: &[(G::Scalar, G)]) -> G { match algorithm(pairs.len()) { Algorithm::Null => Group::identity(), Algorithm::Single => pairs[0].1 * pairs[0].0, @@ -190,10 +187,7 @@ where /// Performs a multiexponentiation in variable time, automatically selecting the optimal algorithm /// based on the amount of pairs. -pub fn multiexp_vartime(pairs: &[(G::Scalar, G)]) -> G -where - G::Scalar: PrimeFieldBits, -{ +pub fn multiexp_vartime>(pairs: &[(G::Scalar, G)]) -> G { match algorithm(pairs.len()) { Algorithm::Null => Group::identity(), Algorithm::Single => pairs[0].1 * pairs[0].0, diff --git a/crypto/multiexp/src/pippenger.rs b/crypto/multiexp/src/pippenger.rs index 10d7d1410..3660b7b2f 100644 --- a/crypto/multiexp/src/pippenger.rs +++ b/crypto/multiexp/src/pippenger.rs @@ -7,10 +7,10 @@ use crate::prep_bits; // Pippenger's algorithm for multiexponentiation, as published in the SIAM Journal on Computing // DOI: 10.1137/0209022 -pub(crate) fn pippenger(pairs: &[(G::Scalar, G)], window: u8) -> G -where - G::Scalar: PrimeFieldBits, -{ +pub(crate) fn pippenger>( + pairs: &[(G::Scalar, G)], + window: u8, +) -> G { let mut bits = prep_bits(pairs, window); let mut res = G::identity(); @@ -37,10 +37,10 @@ where res } -pub(crate) fn pippenger_vartime(pairs: &[(G::Scalar, G)], window: u8) -> G -where - G::Scalar: PrimeFieldBits, -{ +pub(crate) fn pippenger_vartime>( + pairs: &[(G::Scalar, G)], + window: u8, +) -> G { let bits = prep_bits(pairs, window); let mut res = G::identity(); diff --git a/crypto/multiexp/src/straus.rs b/crypto/multiexp/src/straus.rs index 6f472c057..f576c9733 100644 --- a/crypto/multiexp/src/straus.rs +++ b/crypto/multiexp/src/straus.rs @@ -24,10 +24,10 @@ fn prep_tables(pairs: &[(G::Scalar, G)], window: u8) -> Vec> { // Straus's algorithm for multiexponentiation, as published in The American Mathematical Monthly // DOI: 10.2307/2310929 -pub(crate) fn straus(pairs: &[(G::Scalar, G)], window: u8) -> G -where - G::Scalar: PrimeFieldBits + Zeroize, -{ +pub(crate) fn straus>( + pairs: &[(G::Scalar, G)], + window: u8, +) -> G { let mut groupings = prep_bits(pairs, window); let tables = prep_tables(pairs, window); @@ -48,10 +48,10 @@ where res } -pub(crate) fn straus_vartime(pairs: &[(G::Scalar, G)], window: u8) -> G -where - G::Scalar: PrimeFieldBits, -{ +pub(crate) fn straus_vartime>( + pairs: &[(G::Scalar, G)], + window: u8, +) -> G { let groupings = prep_bits(pairs, window); let tables = prep_tables(pairs, window); diff --git a/crypto/multiexp/src/tests/batch.rs b/crypto/multiexp/src/tests/batch.rs index 5c6cd5818..2e78a5dce 100644 --- a/crypto/multiexp/src/tests/batch.rs +++ b/crypto/multiexp/src/tests/batch.rs @@ -9,10 +9,7 @@ use group::Group; use crate::BatchVerifier; -pub(crate) fn test_batch() -where - G::Scalar: PrimeFieldBits + Zeroize, -{ +pub(crate) fn test_batch + Zeroize>() { let valid = |batch: BatchVerifier<_, G>| { assert!(batch.verify()); assert!(batch.verify_vartime()); diff --git a/crypto/multiexp/src/tests/mod.rs b/crypto/multiexp/src/tests/mod.rs index 4a5b4ca93..3050c96ec 100644 --- a/crypto/multiexp/src/tests/mod.rs +++ b/crypto/multiexp/src/tests/mod.rs @@ -18,10 +18,7 @@ mod batch; use batch::test_batch; #[allow(dead_code)] -fn benchmark_internal(straus_bool: bool) -where - G::Scalar: PrimeFieldBits + Zeroize, -{ +fn benchmark_internal>(straus_bool: bool) { let runs: usize = 20; let mut start = 0; @@ -86,10 +83,7 @@ where } } -fn test_multiexp() -where - G::Scalar: PrimeFieldBits + Zeroize, -{ +fn test_multiexp>() { let test = |pairs: &[_], sum| { // These should automatically determine the best algorithm assert_eq!(multiexp(pairs), sum); diff --git a/crypto/schnorr/Cargo.toml b/crypto/schnorr/Cargo.toml index 91f8722b4..2ea04f5b2 100644 --- a/crypto/schnorr/Cargo.toml +++ b/crypto/schnorr/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/serai-dex/serai/tree/develop/crypto/schnorr" authors = ["Luke Parker "] keywords = ["schnorr", "ff", "group"] edition = "2021" -rust-version = "1.74" +rust-version = "1.79" [package.metadata.docs.rs] all-features = true diff --git a/crypto/schnorr/src/tests/rfc8032.rs b/crypto/schnorr/src/tests/rfc8032.rs index 991cf450b..418f4c0e7 100644 --- a/crypto/schnorr/src/tests/rfc8032.rs +++ b/crypto/schnorr/src/tests/rfc8032.rs @@ -52,7 +52,7 @@ fn test_rfc8032() { SchnorrSignature::::read::<&[u8]>(&mut hex::decode(vector.2).unwrap().as_ref()) .unwrap(); let hram = Sha512::new_with_prefix( - &[sig.R.to_bytes().as_ref(), &key.to_bytes(), &hex::decode(vector.1).unwrap()].concat(), + [sig.R.to_bytes().as_ref(), &key.to_bytes(), &hex::decode(vector.1).unwrap()].concat(), ); assert!(sig.verify(key, Scalar::from_hash(hram))); } diff --git a/crypto/schnorrkel/Cargo.toml b/crypto/schnorrkel/Cargo.toml index f58190707..2508bef0d 100644 --- a/crypto/schnorrkel/Cargo.toml +++ b/crypto/schnorrkel/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/serai-dex/serai/tree/develop/crypto/schnorrkel" authors = ["Luke Parker "] keywords = ["frost", "multisig", "threshold", "schnorrkel"] edition = "2021" -rust-version = "1.74" +rust-version = "1.79" [package.metadata.docs.rs] all-features = true diff --git a/crypto/transcript/Cargo.toml b/crypto/transcript/Cargo.toml index 566ad56bf..84e08abf1 100644 --- a/crypto/transcript/Cargo.toml +++ b/crypto/transcript/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/serai-dex/serai/tree/develop/crypto/transcript" authors = ["Luke Parker "] keywords = ["transcript"] edition = "2021" -rust-version = "1.73" +rust-version = "1.79" [package.metadata.docs.rs] all-features = true diff --git a/crypto/transcript/README.md b/crypto/transcript/README.md index a8772a0ae..171246934 100644 --- a/crypto/transcript/README.md +++ b/crypto/transcript/README.md @@ -3,9 +3,9 @@ Flexible Transcript is a crate offering: - `Transcript`, a trait offering functions transcripts should implement. - `DigestTranscript`, a competent transcript format instantiated against a -provided hash function. + provided hash function. - `MerlinTranscript`, a wrapper of `merlin` into the trait (available via the -`merlin` feature). + `merlin` feature). - `RecommendedTranscript`, a transcript recommended for usage in applications. Currently, this is `DigestTranscript` (available via the `recommended` feature). diff --git a/crypto/transcript/src/tests.rs b/crypto/transcript/src/tests.rs index 93651b03c..ce5a0a1c1 100644 --- a/crypto/transcript/src/tests.rs +++ b/crypto/transcript/src/tests.rs @@ -1,10 +1,7 @@ use crate::Transcript; /// Test the sanity of a transcript. -pub fn test_transcript() -where - T::Challenge: PartialEq, -{ +pub fn test_transcript>() { // Ensure distinct names cause distinct challenges { let mut t1 = T::new(b"1"); diff --git a/deny.toml b/deny.toml index 08f3d7b5a..fef45d1f6 100644 --- a/deny.toml +++ b/deny.toml @@ -1,19 +1,19 @@ [advisories] +version = 2 + db-path = "~/.cargo/advisory-db" db-urls = ["https://github.com/rustsec/advisory-db"] -vulnerability = "deny" yanked = "deny" -notice = "warn" -unmaintained = "warn" ignore = [ + "RUSTSEC-2020-0168", # mach is unmaintained "RUSTSEC-2021-0139", # https://github.com/serai-dex/serai/228 "RUSTSEC-2022-0061", # https://github.com/serai-dex/serai/227 ] [licenses] -unlicensed = "deny" +version = 2 allow = [ # Effective public domain @@ -36,14 +36,11 @@ allow = [ "GPL-3.0 WITH Classpath-exception-2.0", ] -copyleft = "deny" -allow-osi-fsf-free = "neither" -default = "deny" - exceptions = [ { allow = ["AGPL-3.0"], name = "serai-env" }, { allow = ["AGPL-3.0"], name = "ethereum-serai" }, + { allow = ["AGPL-3.0"], name = "serai-ethereum-relayer" }, { allow = ["AGPL-3.0"], name = "serai-message-queue" }, @@ -101,7 +98,6 @@ allow-git = [ "https://github.com/rust-lang-nursery/lazy-static.rs", "https://github.com/serai-dex/substrate-bip39", "https://github.com/serai-dex/substrate", - "https://github.com/alloy-rs/alloy", "https://github.com/monero-rs/base58-monero", "https://github.com/orcalabs/dockertest-rs", ] diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index 34e40cd92..f6d6627d1 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -13,7 +13,7 @@ GEM forwardable-extended (2.6.0) google-protobuf (3.25.3-x86_64-linux) http_parser.rb (0.8.0) - i18n (1.14.4) + i18n (1.14.5) concurrent-ruby (~> 1.0) jekyll (4.3.3) addressable (~> 2.4) @@ -55,17 +55,19 @@ GEM mercenary (0.4.0) pathutil (0.16.2) forwardable-extended (~> 2.6) - public_suffix (5.0.4) - rake (13.1.0) + public_suffix (5.0.5) + rake (13.2.1) rb-fsevent (0.11.2) - rb-inotify (0.10.1) + rb-inotify (0.11.1) ffi (~> 1.0) - rexml (3.2.6) - rouge (4.2.0) + rexml (3.2.8) + strscan (>= 3.0.9) + rouge (4.2.1) safe_yaml (1.0.5) sass-embedded (1.63.6) google-protobuf (~> 3.23) rake (>= 13.0.0) + strscan (3.1.0) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) unicode-display_width (2.5.0) diff --git a/orchestration/dev/coins/ethereum-relayer/.folder b/orchestration/dev/coins/ethereum-relayer/.folder new file mode 100644 index 000000000..675d44382 --- /dev/null +++ b/orchestration/dev/coins/ethereum-relayer/.folder @@ -0,0 +1,11 @@ +#!/bin/sh + +RPC_USER="${RPC_USER:=serai}" +RPC_PASS="${RPC_PASS:=seraidex}" + +# Run Monero +monerod --non-interactive --regtest --offline --fixed-difficulty=1 \ + --no-zmq --rpc-bind-ip=0.0.0.0 --rpc-bind-port=18081 --confirm-external-bind \ + --rpc-access-control-origins "*" --disable-rpc-ban \ + --rpc-login=$RPC_USER:$RPC_PASS \ + $1 diff --git a/orchestration/runtime/Dockerfile b/orchestration/runtime/Dockerfile index 2801f070b..e9a910d5e 100644 --- a/orchestration/runtime/Dockerfile +++ b/orchestration/runtime/Dockerfile @@ -1,5 +1,5 @@ -# rust:1.77.0-slim-bookworm as of March 22nd, 2024 (GMT) -FROM --platform=linux/amd64 rust@sha256:e785e4aa81f87bc1ee02fa2026ffbc491e0410bdaf6652cea74884373f452664 as deterministic +# rust:1.79.0-slim-bookworm as of June 14th, 2024 (GMT) +FROM --platform=linux/amd64 rust@sha256:fa189cd885739dd17fc6bb4e132687fce43f2bf42983c0ac39b60e4943201e9c as deterministic # Move to a Debian package snapshot RUN rm -rf /etc/apt/sources.list.d/debian.sources && \ diff --git a/orchestration/src/coordinator.rs b/orchestration/src/coordinator.rs index 13fdff596..26058886e 100644 --- a/orchestration/src/coordinator.rs +++ b/orchestration/src/coordinator.rs @@ -17,6 +17,7 @@ pub fn coordinator( let longer_reattempts = if network == Network::Dev { "longer-reattempts" } else { "" }; let setup = mimalloc(Os::Debian).to_string() + &build_serai_service( + "", network.release(), &format!("{db} {longer_reattempts}"), "serai-coordinator", diff --git a/orchestration/src/ethereum_relayer.rs b/orchestration/src/ethereum_relayer.rs new file mode 100644 index 000000000..523d3c62c --- /dev/null +++ b/orchestration/src/ethereum_relayer.rs @@ -0,0 +1,39 @@ +use std::path::Path; + +use crate::{Network, Os, mimalloc, os, build_serai_service, write_dockerfile}; + +pub fn ethereum_relayer(orchestration_path: &Path, network: Network) { + let setup = mimalloc(Os::Debian).to_string() + + &build_serai_service("", network.release(), network.db(), "serai-ethereum-relayer"); + + let env_vars = [ + ("DB_PATH", "/volume/ethereum-relayer-db".to_string()), + ("RUST_LOG", "info,serai_ethereum_relayer=trace".to_string()), + ]; + let mut env_vars_str = String::new(); + for (env_var, value) in env_vars { + env_vars_str += &format!(r#"{env_var}=${{{env_var}:="{value}"}} "#); + } + + let run_ethereum_relayer = format!( + r#" +# Copy the relayer server binary and relevant license +COPY --from=builder --chown=ethereumrelayer /serai/bin/serai-ethereum-relayer /bin + +# Run ethereum-relayer +EXPOSE 20830 +EXPOSE 20831 +CMD {env_vars_str} serai-ethereum-relayer +"# + ); + + let run = os(Os::Debian, "", "ethereumrelayer") + &run_ethereum_relayer; + let res = setup + &run; + + let mut ethereum_relayer_path = orchestration_path.to_path_buf(); + ethereum_relayer_path.push("coins"); + ethereum_relayer_path.push("ethereum-relayer"); + ethereum_relayer_path.push("Dockerfile"); + + write_dockerfile(ethereum_relayer_path, &res); +} diff --git a/orchestration/src/main.rs b/orchestration/src/main.rs index 0e6c7cb00..5422fb59f 100644 --- a/orchestration/src/main.rs +++ b/orchestration/src/main.rs @@ -32,6 +32,9 @@ use mimalloc::mimalloc; mod coins; use coins::*; +mod ethereum_relayer; +use ethereum_relayer::ethereum_relayer; + mod message_queue; use message_queue::message_queue; @@ -137,13 +140,13 @@ WORKDIR /home/{user} } } -fn build_serai_service(release: bool, features: &str, package: &str) -> String { +fn build_serai_service(prelude: &str, release: bool, features: &str, package: &str) -> String { let profile = if release { "release" } else { "debug" }; let profile_flag = if release { "--release" } else { "" }; format!( r#" -FROM rust:1.77-slim-bookworm as builder +FROM rust:1.79-slim-bookworm as builder COPY --from=mimalloc-debian libmimalloc.so /usr/lib RUN echo "/usr/lib/libmimalloc.so" >> /etc/ld.so.preload @@ -159,6 +162,8 @@ RUN apt install -y make protobuf-compiler # Add the wasm toolchain RUN rustup target add wasm32-unknown-unknown +{prelude} + # Add files for build ADD patches /serai/patches ADD common /serai/common @@ -278,6 +283,8 @@ fn dockerfiles(network: Network) { let ethereum_key = infrastructure_keys.remove("ethereum").unwrap(); let monero_key = infrastructure_keys.remove("monero").unwrap(); + ethereum_relayer(&orchestration_path, network); + message_queue( &orchestration_path, network, @@ -361,6 +368,7 @@ fn start(network: Network, services: HashSet) { let name = match service.as_ref() { "serai" => "serai", "coordinator" => "coordinator", + "ethereum-relayer" => "ethereum-relayer", "message-queue" => "message-queue", "bitcoin-daemon" => "bitcoin", "bitcoin-processor" => "bitcoin-processor", @@ -374,23 +382,17 @@ fn start(network: Network, services: HashSet) { let serai_runtime_volume = format!("serai-{}-runtime-volume", network.label()); if name == "serai" { // Check if it's built by checking if the volume has the expected runtime file + let wasm_build_container_name = format!("serai-{}-runtime", network.label()); let built = || { - if let Ok(path) = Command::new("docker") - .arg("volume") + if let Ok(state_and_status) = Command::new("docker") .arg("inspect") .arg("-f") - .arg("{{ .Mountpoint }}") - .arg(&serai_runtime_volume) + .arg("{{.State.Status}}:{{.State.ExitCode}}") + .arg(&wasm_build_container_name) .output() { - if let Ok(path) = String::from_utf8(path.stdout) { - if let Ok(iter) = std::fs::read_dir(PathBuf::from(path.trim())) { - for item in iter.flatten() { - if item.file_name() == "serai.wasm" { - return true; - } - } - } + if let Ok(state_and_status) = String::from_utf8(state_and_status.stdout) { + return state_and_status.trim() == "exited:0"; } } false @@ -493,6 +495,10 @@ fn start(network: Network, services: HashSet) { command } } + "ethereum-relayer" => { + // Expose the router command fetch server + command.arg("-p").arg("20831:20831") + } "monero" => { // Expose the RPC for tests if network == Network::Dev { @@ -559,6 +565,9 @@ Commands: - `message-queue` - `bitcoin-daemon` - `bitcoin-processor` + - `ethereum-daemon` + - `ethereum-processor` + - `ethereum-relayer` - `monero-daemon` - `monero-processor` - `monero-wallet-rpc` (if "dev") @@ -591,6 +600,9 @@ Commands: Some("start") => { let mut services = HashSet::new(); for arg in args { + if arg == "ethereum-processor" { + services.insert("ethereum-relayer".to_string()); + } if let Some(ext_network) = arg.strip_suffix("-processor") { services.insert(ext_network.to_string() + "-daemon"); } diff --git a/orchestration/src/message_queue.rs b/orchestration/src/message_queue.rs index eb662b671..ea97a6198 100644 --- a/orchestration/src/message_queue.rs +++ b/orchestration/src/message_queue.rs @@ -13,7 +13,7 @@ pub fn message_queue( monero_key: ::G, ) { let setup = mimalloc(Os::Debian).to_string() + - &build_serai_service(network.release(), network.db(), "serai-message-queue"); + &build_serai_service("", network.release(), network.db(), "serai-message-queue"); let env_vars = [ ("COORDINATOR_KEY", hex::encode(coordinator_key.to_bytes())), diff --git a/orchestration/src/processor.rs b/orchestration/src/processor.rs index 8a2c8c776..cefe6455b 100644 --- a/orchestration/src/processor.rs +++ b/orchestration/src/processor.rs @@ -17,6 +17,15 @@ pub fn processor( ) { let setup = mimalloc(Os::Debian).to_string() + &build_serai_service( + if coin == "ethereum" { + r#" +RUN cargo install svm-rs +RUN svm install 0.8.25 +RUN svm use 0.8.25 +"# + } else { + "" + }, network.release(), &format!("binaries {} {coin}", network.db()), "serai-processor", @@ -32,24 +41,32 @@ RUN apt install -y ca-certificates const RPC_PASS: &str = "seraidex"; // TODO: Isolate networks let hostname = format!("serai-{}-{coin}", network.label()); - let port = match coin { - "bitcoin" => 8332, - "ethereum" => return, // TODO - "monero" => 18081, - _ => panic!("unrecognized external network"), - }; + let port = format!( + "{}", + match coin { + "bitcoin" => 8332, + "ethereum" => 8545, + "monero" => 18081, + _ => panic!("unrecognized external network"), + } + ); - let env_vars = [ + let mut env_vars = vec![ ("MESSAGE_QUEUE_RPC", format!("serai-{}-message-queue", network.label())), ("MESSAGE_QUEUE_KEY", hex::encode(coin_key.to_repr())), ("ENTROPY", hex::encode(entropy.as_ref())), ("NETWORK", coin.to_string()), ("NETWORK_RPC_LOGIN", format!("{RPC_USER}:{RPC_PASS}")), ("NETWORK_RPC_HOSTNAME", hostname), - ("NETWORK_RPC_PORT", format!("{port}")), + ("NETWORK_RPC_PORT", port), ("DB_PATH", "/volume/processor-db".to_string()), ("RUST_LOG", "info,serai_processor=debug".to_string()), ]; + if coin == "ethereum" { + env_vars + .push(("ETHEREUM_RELAYER_HOSTNAME", format!("serai-{}-ethereum-relayer", network.label()))); + env_vars.push(("ETHEREUM_RELAYER_PORT", "20830".to_string())); + } let mut env_vars_str = String::new(); for (env_var, value) in env_vars { env_vars_str += &format!(r#"{env_var}=${{{env_var}:="{value}"}} "#); diff --git a/orchestration/src/serai.rs b/orchestration/src/serai.rs index 2e1e915c0..e2f96f6ad 100644 --- a/orchestration/src/serai.rs +++ b/orchestration/src/serai.rs @@ -11,9 +11,9 @@ pub fn serai( serai_key: &Zeroizing<::F>, ) { // Always builds in release for performance reasons - let setup = mimalloc(Os::Debian).to_string() + &build_serai_service(true, "", "serai-node"); + let setup = mimalloc(Os::Debian).to_string() + &build_serai_service("", true, "", "serai-node"); let setup_fast_epoch = - mimalloc(Os::Debian).to_string() + &build_serai_service(true, "fast-epoch", "serai-node"); + mimalloc(Os::Debian).to_string() + &build_serai_service("", true, "fast-epoch", "serai-node"); let env_vars = [("KEY", hex::encode(serai_key.to_repr()))]; let mut env_vars_str = String::new(); diff --git a/orchestration/testnet/coins/ethereum-relayer/.folder b/orchestration/testnet/coins/ethereum-relayer/.folder new file mode 100644 index 000000000..675d44382 --- /dev/null +++ b/orchestration/testnet/coins/ethereum-relayer/.folder @@ -0,0 +1,11 @@ +#!/bin/sh + +RPC_USER="${RPC_USER:=serai}" +RPC_PASS="${RPC_PASS:=seraidex}" + +# Run Monero +monerod --non-interactive --regtest --offline --fixed-difficulty=1 \ + --no-zmq --rpc-bind-ip=0.0.0.0 --rpc-bind-port=18081 --confirm-external-bind \ + --rpc-access-control-origins "*" --disable-rpc-ban \ + --rpc-login=$RPC_USER:$RPC_PASS \ + $1 diff --git a/patches/parking_lot/Cargo.toml b/patches/parking_lot/Cargo.toml new file mode 100644 index 000000000..957b19bff --- /dev/null +++ b/patches/parking_lot/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "parking_lot" +version = "0.11.2" +description = "parking_lot which patches to the latest update" +license = "MIT" +repository = "https://github.com/serai-dex/serai/tree/develop/patches/parking_lot" +authors = ["Luke Parker "] +keywords = [] +edition = "2021" +rust-version = "1.70" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[dependencies] +parking_lot = "0.12" diff --git a/patches/parking_lot/src/lib.rs b/patches/parking_lot/src/lib.rs new file mode 100644 index 000000000..df10a74d9 --- /dev/null +++ b/patches/parking_lot/src/lib.rs @@ -0,0 +1 @@ +pub use parking_lot::*; diff --git a/patches/parking_lot_core/Cargo.toml b/patches/parking_lot_core/Cargo.toml new file mode 100644 index 000000000..37dcc7035 --- /dev/null +++ b/patches/parking_lot_core/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "parking_lot_core" +version = "0.8.6" +description = "parking_lot_core which patches to the latest update" +license = "MIT" +repository = "https://github.com/serai-dex/serai/tree/develop/patches/parking_lot_core" +authors = ["Luke Parker "] +keywords = [] +edition = "2021" +rust-version = "1.70" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] + +[dependencies] +parking_lot_core = "0.9" diff --git a/patches/parking_lot_core/src/lib.rs b/patches/parking_lot_core/src/lib.rs new file mode 100644 index 000000000..bfecbfd8a --- /dev/null +++ b/patches/parking_lot_core/src/lib.rs @@ -0,0 +1 @@ +pub use parking_lot_core::*; diff --git a/processor/Cargo.toml b/processor/Cargo.toml index f90f6117c..cc0108488 100644 --- a/processor/Cargo.toml +++ b/processor/Cargo.toml @@ -45,7 +45,7 @@ frost-schnorrkel = { path = "../crypto/schnorrkel", default-features = false } k256 = { version = "^0.13.1", default-features = false, features = ["std"], optional = true } # Bitcoin -secp256k1 = { version = "0.28", default-features = false, features = ["std", "global-context", "rand-std"], optional = true } +secp256k1 = { version = "0.29", default-features = false, features = ["std", "global-context", "rand-std"], optional = true } bitcoin-serai = { path = "../coins/bitcoin", default-features = false, features = ["std"], optional = true } # Ethereum diff --git a/processor/src/key_gen.rs b/processor/src/key_gen.rs index f1a5b47c0..6976e225d 100644 --- a/processor/src/key_gen.rs +++ b/processor/src/key_gen.rs @@ -512,6 +512,7 @@ impl KeyGen { ProcessorMessage::GeneratedKeyPair { id, substrate_key: generated_substrate_key.unwrap().to_bytes(), + // TODO: This can be made more efficient since tweaked keys may be a subset of keys network_key: generated_network_key.unwrap().to_bytes().as_ref().to_vec(), } } diff --git a/processor/src/main.rs b/processor/src/main.rs index 1a50effa6..e0d97aa68 100644 --- a/processor/src/main.rs +++ b/processor/src/main.rs @@ -748,7 +748,15 @@ async fn main() { #[cfg(feature = "bitcoin")] NetworkId::Bitcoin => run(db, Bitcoin::new(url).await, coordinator).await, #[cfg(feature = "ethereum")] - NetworkId::Ethereum => run(db.clone(), Ethereum::new(db, url).await, coordinator).await, + NetworkId::Ethereum => { + let relayer_hostname = env::var("ETHEREUM_RELAYER_HOSTNAME") + .expect("ethereum relayer hostname wasn't specified") + .to_string(); + let relayer_port = + env::var("ETHEREUM_RELAYER_PORT").expect("ethereum relayer port wasn't specified"); + let relayer_url = relayer_hostname + ":" + &relayer_port; + run(db.clone(), Ethereum::new(db, url, relayer_url).await, coordinator).await + } #[cfg(feature = "monero")] NetworkId::Monero => run(db, Monero::new(url).await, coordinator).await, _ => panic!("spawning a processor for an unsupported network"), diff --git a/processor/src/multisigs/db.rs b/processor/src/multisigs/db.rs index 339b7bdcc..3d1d13bdf 100644 --- a/processor/src/multisigs/db.rs +++ b/processor/src/multisigs/db.rs @@ -231,7 +231,7 @@ impl ForwardedOutputDb { let res = InInstructionWithBalance::decode(&mut outputs_ref).unwrap(); assert!(outputs_ref.len() < outputs.len()); if outputs_ref.is_empty() { - txn.del(&Self::key(balance)); + txn.del(Self::key(balance)); } else { Self::set(txn, balance, &outputs); } diff --git a/processor/src/multisigs/mod.rs b/processor/src/multisigs/mod.rs index 75c91675d..12f017151 100644 --- a/processor/src/multisigs/mod.rs +++ b/processor/src/multisigs/mod.rs @@ -63,9 +63,22 @@ fn instruction_from_output( return (presumed_origin, None); } - let Ok(shorthand) = Shorthand::decode(&mut data) else { return (presumed_origin, None) }; - let Ok(instruction) = RefundableInInstruction::try_from(shorthand) else { - return (presumed_origin, None); + let shorthand = match Shorthand::decode(&mut data) { + Ok(shorthand) => shorthand, + Err(e) => { + info!("data in output {} wasn't valid shorthand: {e:?}", hex::encode(output.id())); + return (presumed_origin, None); + } + }; + let instruction = match RefundableInInstruction::try_from(shorthand) { + Ok(instruction) => instruction, + Err(e) => { + info!( + "shorthand in output {} wasn't convertible to a RefundableInInstruction: {e:?}", + hex::encode(output.id()) + ); + return (presumed_origin, None); + } }; let mut balance = output.balance(); diff --git a/processor/src/multisigs/scanner.rs b/processor/src/multisigs/scanner.rs index 3d28f3e83..1b25e1086 100644 --- a/processor/src/multisigs/scanner.rs +++ b/processor/src/multisigs/scanner.rs @@ -279,6 +279,8 @@ impl ScannerHandle { activation_number: usize, key: ::G, ) { + info!("Registering key {} in scanner at {activation_number}", hex::encode(key.to_bytes())); + let mut scanner_lock = self.scanner.write().await; let scanner = scanner_lock.as_mut().unwrap(); assert!( @@ -286,8 +288,6 @@ impl ScannerHandle { "activation block of new keys was already scanned", ); - info!("Registering key {} in scanner at {activation_number}", hex::encode(key.to_bytes())); - if scanner.keys.is_empty() { assert!(scanner.ram_scanned.is_none()); scanner.ram_scanned = Some(activation_number); diff --git a/processor/src/multisigs/scheduler/smart_contract.rs b/processor/src/multisigs/scheduler/smart_contract.rs index 4f48e391f..3da8acf48 100644 --- a/processor/src/multisigs/scheduler/smart_contract.rs +++ b/processor/src/multisigs/scheduler/smart_contract.rs @@ -116,7 +116,7 @@ impl> SchedulerTrait for Scheduler { assert!(self.coins.contains(&utxo.balance().coin)); } - let mut nonce = LastNonce::get(txn).map_or(1, |nonce| nonce + 1); + let mut nonce = LastNonce::get(txn).unwrap_or(1); let mut plans = vec![]; for chunk in payments.as_slice().chunks(N::MAX_OUTPUTS) { // Once we rotate, all further payments should be scheduled via the new multisig diff --git a/processor/src/multisigs/scheduler/utxo.rs b/processor/src/multisigs/scheduler/utxo.rs index e9aa33510..1865cab91 100644 --- a/processor/src/multisigs/scheduler/utxo.rs +++ b/processor/src/multisigs/scheduler/utxo.rs @@ -432,7 +432,7 @@ impl> Scheduler { } // If there's a UTXO to restore, restore it - // This is down now as if there is a to_restore output, and it was inserted into self.utxos + // This is done now as if there is a to_restore output, and it was inserted into self.utxos // earlier, self.utxos.len() may become `N::MAX_INPUTS + 1` // The prior block requires the len to be `<= N::MAX_INPUTS` if let Some(to_restore) = to_restore { @@ -442,9 +442,10 @@ impl> Scheduler { txn.put(scheduler_key::(&self.key), self.serialize()); log::info!( - "created {} plans containing {} payments to sign", + "created {} plans containing {} payments to sign, with {} payments pending scheduling", plans.len(), payments_at_start - self.payments.len(), + self.payments.len(), ); plans } @@ -589,7 +590,8 @@ impl> SchedulerTrait for Scheduler { output: N::Output, refund_to: N::Address, ) -> Plan { - Plan { + let output_id = output.id().as_ref().to_vec(); + let res = Plan { key: output.key(), // Uses a payment as this will still be successfully sent due to fee amortization, // and because change is currently always a Serai key @@ -597,7 +599,9 @@ impl> SchedulerTrait for Scheduler { inputs: vec![output], change: None, scheduler_addendum: (), - } + }; + log::info!("refund plan for {} has ID {}", hex::encode(output_id), hex::encode(res.id())); + res } fn shim_forward_plan(output: N::Output, to: ::G) -> Option> { diff --git a/processor/src/networks/bitcoin.rs b/processor/src/networks/bitcoin.rs index 3f8174e45..183444b12 100644 --- a/processor/src/networks/bitcoin.rs +++ b/processor/src/networks/bitcoin.rs @@ -20,12 +20,11 @@ use bitcoin_serai::{ key::{Parity, XOnlyPublicKey}, consensus::{Encodable, Decodable}, script::Instruction, - address::{NetworkChecked, Address as BAddress}, - Transaction, Block, Network as BNetwork, ScriptBuf, + Transaction, Block, ScriptBuf, opcodes::all::{OP_SHA256, OP_EQUALVERIFY}, }, wallet::{ - tweak_keys, address_payload, ReceivedOutput, Scanner, TransactionError, + tweak_keys, p2tr_script_buf, ReceivedOutput, Scanner, TransactionError, SignableTransaction as BSignableTransaction, TransactionMachine, }, rpc::{RpcError, Rpc}, @@ -175,7 +174,7 @@ pub struct Fee(u64); impl TransactionTrait for Transaction { type Id = [u8; 32]; fn id(&self) -> Self::Id { - let mut hash = *self.txid().as_raw_hash().as_byte_array(); + let mut hash = *self.compute_txid().as_raw_hash().as_byte_array(); hash.reverse(); hash } @@ -243,7 +242,8 @@ impl EventualityTrait for Eventuality { buf } fn read_completion(reader: &mut R) -> io::Result { - Transaction::consensus_decode(reader).map_err(|e| io::Error::other(format!("{e}"))) + Transaction::consensus_decode(&mut io::BufReader::with_capacity(0, reader)) + .map_err(|e| io::Error::other(format!("{e}"))) } } @@ -453,7 +453,7 @@ impl Bitcoin { match BSignableTransaction::new( inputs.iter().map(|input| input.output.clone()).collect(), &payments, - change.as_ref().map(AsRef::as_ref), + change.clone().map(Into::into), None, fee.0, ) { @@ -534,12 +534,14 @@ impl Bitcoin { input_index: usize, private_key: &PrivateKey, ) -> ScriptBuf { + use bitcoin_serai::bitcoin::{Network as BNetwork, Address as BAddress}; + let public_key = PublicKey::from_private_key(SECP256K1, private_key); - let main_addr = BAddress::p2pkh(&public_key, BNetwork::Regtest); + let main_addr = BAddress::p2pkh(public_key, BNetwork::Regtest); let mut der = SECP256K1 .sign_ecdsa_low_r( - &Message::from( + &Message::from_digest_slice( SighashCache::new(tx) .legacy_signature_hash( input_index, @@ -547,8 +549,10 @@ impl Bitcoin { EcdsaSighashType::All.to_u32(), ) .unwrap() - .to_raw_hash(), - ), + .to_raw_hash() + .as_ref(), + ) + .unwrap(), &private_key.inner, ) .serialize_der() @@ -577,8 +581,10 @@ const MAX_INPUTS: usize = 520; const MAX_OUTPUTS: usize = 520; fn address_from_key(key: ProjectivePoint) -> Address { - Address::new(BAddress::::new(BNetwork::Bitcoin, address_payload(key).unwrap())) - .unwrap() + Address::new( + p2tr_script_buf(key).expect("creating address from key which isn't properly tweaked"), + ) + .expect("couldn't create Serai-representable address for P2TR script") } #[async_trait] @@ -724,9 +730,7 @@ impl Network for Bitcoin { } tx.unwrap().output.swap_remove(usize::try_from(input.previous_output.vout).unwrap()) }; - BAddress::from_script(&spent_output.script_pubkey, BNetwork::Bitcoin) - .ok() - .and_then(Address::new) + Address::new(spent_output.script_pubkey) }; let data = Self::extract_serai_data(tx); for output in &mut outputs { @@ -858,7 +862,7 @@ impl Network for Bitcoin { Err(RpcError::ConnectionError) => Err(NetworkError::ConnectionError)?, // TODO: Distinguish already in pool vs double spend (other signing attempt succeeded) vs // invalid transaction - Err(e) => panic!("failed to publish TX {}: {e}", tx.txid()), + Err(e) => panic!("failed to publish TX {}: {e}", tx.compute_txid()), } Ok(()) } @@ -894,6 +898,8 @@ impl Network for Bitcoin { #[cfg(test)] async fn mine_block(&self) { + use bitcoin_serai::bitcoin::{Network as BNetwork, Address as BAddress}; + self .rpc .rpc_call::>( @@ -906,10 +912,12 @@ impl Network for Bitcoin { #[cfg(test)] async fn test_send(&self, address: Address) -> Block { + use bitcoin_serai::bitcoin::{Network as BNetwork, Address as BAddress}; + let secret_key = SecretKey::new(&mut rand_core::OsRng); let private_key = PrivateKey::new(secret_key, BNetwork::Regtest); let public_key = PublicKey::from_private_key(SECP256K1, &private_key); - let main_addr = BAddress::p2pkh(&public_key, BNetwork::Regtest); + let main_addr = BAddress::p2pkh(public_key, BNetwork::Regtest); let new_block = self.get_latest_block_number().await.unwrap() + 1; self @@ -923,14 +931,14 @@ impl Network for Bitcoin { version: Version(2), lock_time: LockTime::ZERO, input: vec![TxIn { - previous_output: OutPoint { txid: tx.txid(), vout: 0 }, + previous_output: OutPoint { txid: tx.compute_txid(), vout: 0 }, script_sig: Script::new().into(), sequence: Sequence(u32::MAX), witness: Witness::default(), }], output: vec![TxOut { value: tx.output[0].value - BAmount::from_sat(10000), - script_pubkey: address.as_ref().script_pubkey(), + script_pubkey: address.clone().into(), }], }; tx.input[0].script_sig = Self::sign_btc_input_for_p2pkh(&tx, 0, &private_key); diff --git a/processor/src/networks/ethereum.rs b/processor/src/networks/ethereum.rs index 7ffe70410..6a11b06d8 100644 --- a/processor/src/networks/ethereum.rs +++ b/processor/src/networks/ethereum.rs @@ -13,7 +13,7 @@ use frost::ThresholdKeys; use ethereum_serai::{ alloy::{ primitives::U256, - rpc_types::{BlockNumberOrTag, Transaction}, + rpc_types::{BlockTransactionsKind, BlockNumberOrTag, Transaction}, simple_request_transport::SimpleRequest, rpc_client::ClientBuilder, provider::{Provider, RootProvider}, @@ -31,6 +31,11 @@ use tokio::{ time::sleep, sync::{RwLock, RwLockReadGuard}, }; +#[cfg(not(test))] +use tokio::{ + io::{AsyncReadExt, AsyncWriteExt}, + net::TcpStream, +}; use serai_client::{ primitives::{Coin, Amount, Balance, NetworkId}, @@ -290,6 +295,8 @@ pub struct Ethereum { // address. Accordingly, all methods present are consistent to a Serai chain with a finalized // first key (regardless of local state), and this is safe. db: D, + #[cfg_attr(test, allow(unused))] + relayer_url: String, provider: Arc>, deployer: Deployer, router: Arc>>, @@ -309,9 +316,9 @@ impl fmt::Debug for Ethereum { } } impl Ethereum { - pub async fn new(db: D, url: String) -> Self { + pub async fn new(db: D, daemon_url: String, relayer_url: String) -> Self { let provider = Arc::new(RootProvider::new( - ClientBuilder::default().transport(SimpleRequest::new(url), true), + ClientBuilder::default().transport(SimpleRequest::new(daemon_url), true), )); let mut deployer = Deployer::new(provider.clone()).await; @@ -322,7 +329,9 @@ impl Ethereum { } let deployer = deployer.unwrap().unwrap(); - Ethereum { db, provider, deployer, router: Arc::new(RwLock::new(None)) } + dbg!(&relayer_url); + dbg!(relayer_url.len()); + Ethereum { db, relayer_url, provider, deployer, router: Arc::new(RwLock::new(None)) } } // Obtain a reference to the Router, sleeping until it's deployed if it hasn't already been. @@ -423,10 +432,10 @@ impl Network for Ethereum { async fn get_latest_block_number(&self) -> Result { let actual_number = self .provider - .get_block(BlockNumberOrTag::Finalized.into(), false) + .get_block(BlockNumberOrTag::Finalized.into(), BlockTransactionsKind::Hashes) .await .map_err(|_| NetworkError::ConnectionError)? - .expect("no blocks were finalized") + .ok_or(NetworkError::ConnectionError)? .header .number .unwrap(); @@ -451,7 +460,7 @@ impl Network for Ethereum { } else { self .provider - .get_block(u64::try_from(start - 1).unwrap().into(), false) + .get_block(u64::try_from(start - 1).unwrap().into(), BlockTransactionsKind::Hashes) .await .ok() .flatten() @@ -464,7 +473,7 @@ impl Network for Ethereum { let end_header = self .provider - .get_block(u64::try_from(start + 31).unwrap().into(), false) + .get_block(u64::try_from(start + 31).unwrap().into(), BlockTransactionsKind::Hashes) .await .ok() .flatten() @@ -714,8 +723,32 @@ impl Network for Ethereum { // Publish this to the dedicated TX server for a solver to actually publish #[cfg(not(test))] { - let _ = completion; - todo!("TODO"); + let mut msg = vec![]; + match completion.command() { + RouterCommand::UpdateSeraiKey { nonce, .. } | RouterCommand::Execute { nonce, .. } => { + msg.extend(&u32::try_from(nonce).unwrap().to_le_bytes()); + } + } + completion.write(&mut msg).unwrap(); + + let Ok(mut socket) = TcpStream::connect(&self.relayer_url).await else { + log::warn!("couldn't connect to the relayer server"); + Err(NetworkError::ConnectionError)? + }; + let Ok(()) = socket.write_all(&u32::try_from(msg.len()).unwrap().to_le_bytes()).await else { + log::warn!("couldn't send the message's len to the relayer server"); + Err(NetworkError::ConnectionError)? + }; + let Ok(()) = socket.write_all(&msg).await else { + log::warn!("couldn't write the message to the relayer server"); + Err(NetworkError::ConnectionError)? + }; + if socket.read_u8().await.ok() != Some(1) { + log::warn!("didn't get the ack from the relayer server"); + Err(NetworkError::ConnectionError)?; + } + + Ok(()) } // Publish this using a dummy account we fund with magic RPC commands @@ -774,7 +807,7 @@ impl Network for Ethereum { async fn get_block_number(&self, id: &>::Id) -> usize { self .provider - .get_block(B256::from(*id).into(), false) + .get_block(B256::from(*id).into(), BlockTransactionsKind::Hashes) .await .unwrap() .unwrap() diff --git a/processor/src/tests/literal/mod.rs b/processor/src/tests/literal/mod.rs index 5c5f3203b..d45649d59 100644 --- a/processor/src/tests/literal/mod.rs +++ b/processor/src/tests/literal/mod.rs @@ -70,7 +70,7 @@ mod bitcoin { // btc key pair to send from let private_key = PrivateKey::new(SecretKey::new(&mut rand_core::OsRng), BNetwork::Regtest); let public_key = PublicKey::from_private_key(SECP256K1, &private_key); - let main_addr = BAddress::p2pkh(&public_key, BNetwork::Regtest); + let main_addr = BAddress::p2pkh(public_key, BNetwork::Regtest); // get unlocked coins let new_block = btc.get_latest_block_number().await.unwrap() + 1; @@ -107,7 +107,7 @@ mod bitcoin { version: Version(2), lock_time: LockTime::ZERO, input: vec![TxIn { - previous_output: OutPoint { txid: tx.txid(), vout: 0 }, + previous_output: OutPoint { txid: tx.compute_txid(), vout: 0 }, script_sig: Script::new().into(), sequence: Sequence(u32::MAX), witness: Witness::default(), @@ -128,14 +128,14 @@ mod bitcoin { version: Version(2), lock_time: LockTime::ZERO, input: vec![TxIn { - previous_output: OutPoint { txid: tx.txid(), vout: 0 }, + previous_output: OutPoint { txid: tx.compute_txid(), vout: 0 }, script_sig: Script::new().into(), sequence: Sequence(u32::MAX), witness: Witness::new(), }], output: vec![TxOut { value: tx.output[0].value - BAmount::from_sat(10000), - script_pubkey: serai_btc_address.as_ref().script_pubkey(), + script_pubkey: serai_btc_address.into(), }], }; @@ -143,12 +143,14 @@ mod bitcoin { // This is the standard script with an extra argument of the InInstruction let mut sig = SECP256K1 .sign_ecdsa_low_r( - &Message::from( + &Message::from_digest_slice( SighashCache::new(&tx) .p2wsh_signature_hash(0, &script, initial_output_value, EcdsaSighashType::All) .unwrap() - .to_raw_hash(), - ), + .to_raw_hash() + .as_ref(), + ) + .unwrap(), &private_key.inner, ) .serialize_der() @@ -421,7 +423,7 @@ mod ethereum { }); } - Ethereum::new(db, url.clone()).await + Ethereum::new(db, url.clone(), String::new()).await }) } } diff --git a/processor/src/tests/scanner.rs b/processor/src/tests/scanner.rs index 078a07d54..6421c499a 100644 --- a/processor/src/tests/scanner.rs +++ b/processor/src/tests/scanner.rs @@ -115,6 +115,12 @@ pub async fn test_scanner( pub async fn test_no_deadlock_in_multisig_completed( new_network: impl Fn(MemDb) -> Pin>>, ) { + // This test scans two blocks then acknowledges one, yet a network with one confirm won't scan + // two blocks before the first is acknowledged (due to the look-ahead limit) + if N::CONFIRMATIONS <= 1 { + return; + } + let mut db = MemDb::new(); let network = new_network(db.clone()).await; @@ -139,6 +145,10 @@ pub async fn test_no_deadlock_in_multisig_completed( let mut txn = db.txn(); NetworkKeyDb::set(&mut txn, Session(0), &key.to_bytes().as_ref().to_vec()); txn.commit(); + + // Sleep for 5 seconds as setting the Network key value will trigger an async task for + // Ethereum + tokio::time::sleep(Duration::from_secs(5)).await; } key }; @@ -158,6 +168,7 @@ pub async fn test_no_deadlock_in_multisig_completed( network.mine_block().await; } + // Block for the second set of keys registered let block_id = match timeout(Duration::from_secs(30), scanner.events.recv()).await.unwrap().unwrap() { ScannerEvent::Block { is_retirement_block, block, outputs: _ } => { @@ -170,6 +181,7 @@ pub async fn test_no_deadlock_in_multisig_completed( } }; + // Block for the third set of keys registered match timeout(Duration::from_secs(30), scanner.events.recv()).await.unwrap().unwrap() { ScannerEvent::Block { .. } => {} ScannerEvent::Completed(_, _, _, _, _) => { diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 77a0cea27..fe9827842 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "1.77" +channel = "1.79" targets = ["wasm32-unknown-unknown"] profile = "minimal" components = ["rust-src", "rustfmt", "clippy"] diff --git a/substrate/abi/Cargo.toml b/substrate/abi/Cargo.toml index ac294930c..8212e4359 100644 --- a/substrate/abi/Cargo.toml +++ b/substrate/abi/Cargo.toml @@ -16,28 +16,50 @@ rustdoc-args = ["--cfg", "docsrs"] workspace = true [dependencies] -scale = { package = "parity-scale-codec", version = "3", features = ["derive"] } -scale-info = { version = "2", features = ["derive"] } +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2", default-features = false, features = ["derive"] } -borsh = { version = "1", features = ["derive", "de_strict_order"], optional = true } -serde = { version = "1", features = ["derive", "alloc"], optional = true } +borsh = { version = "1", default-features = false, features = ["derive", "de_strict_order"], optional = true } +serde = { version = "1", default-features = false, features = ["derive", "alloc"], optional = true } -sp-core = { git = "https://github.com/serai-dex/substrate" } -sp-runtime = { git = "https://github.com/serai-dex/substrate" } +sp-core = { git = "https://github.com/serai-dex/substrate", default-features = false } +sp-runtime = { git = "https://github.com/serai-dex/substrate", default-features = false } -sp-consensus-babe = { git = "https://github.com/serai-dex/substrate" } -sp-consensus-grandpa = { git = "https://github.com/serai-dex/substrate" } +sp-consensus-babe = { git = "https://github.com/serai-dex/substrate", default-features = false } +sp-consensus-grandpa = { git = "https://github.com/serai-dex/substrate", default-features = false } -serai-primitives = { path = "../primitives", version = "0.1" } -serai-coins-primitives = { path = "../coins/primitives", version = "0.1" } -serai-validator-sets-primitives = { path = "../validator-sets/primitives", version = "0.1" } -serai-genesis-liquidity-primitives = { path = "../genesis-liquidity/primitives", version = "0.1" } -serai-in-instructions-primitives = { path = "../in-instructions/primitives", version = "0.1" } -serai-signals-primitives = { path = "../signals/primitives", version = "0.1" } +frame-support = { git = "https://github.com/serai-dex/substrate", default-features = false } -frame-support = { git = "https://github.com/serai-dex/substrate" } +serai-primitives = { path = "../primitives", version = "0.1", default-features = false } +serai-coins-primitives = { path = "../coins/primitives", version = "0.1", default-features = false } +serai-validator-sets-primitives = { path = "../validator-sets/primitives", version = "0.1", default-features = false } +serai-genesis-liquidity-primitives = { path = "../genesis-liquidity/primitives", version = "0.1" } +serai-in-instructions-primitives = { path = "../in-instructions/primitives", version = "0.1", default-features = false } +serai-signals-primitives = { path = "../signals/primitives", version = "0.1", default-features = false } [features] +std = [ + "scale/std", + "scale-info/std", + + "borsh?/std", + "serde?/std", + + "sp-core/std", + "sp-runtime/std", + + "sp-consensus-babe/std", + "sp-consensus-grandpa/std", + + "frame-support/std", + + "serai-primitives/std", + "serai-coins-primitives/std", + "serai-validator-sets-primitives/std", + "serai-genesis-liquidity-primitives/std", + "serai-in-instructions-primitives/std", + "serai-signals-primitives/std", +] borsh = [ "dep:borsh", "serai-primitives/borsh", @@ -56,3 +78,4 @@ serde = [ "serai-in-instructions-primitives/serde", "serai-signals-primitives/serde", ] +default = ["std"] diff --git a/substrate/abi/src/babe.rs b/substrate/abi/src/babe.rs index 29bbee9ce..9bba63d90 100644 --- a/substrate/abi/src/babe.rs +++ b/substrate/abi/src/babe.rs @@ -4,7 +4,7 @@ use serai_primitives::{Header, SeraiAddress}; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] pub struct ReportEquivocation { - pub equivocation_proof: Box>, + pub equivocation_proof: alloc::boxed::Box>, pub key_owner_proof: SeraiAddress, } diff --git a/substrate/abi/src/coins.rs b/substrate/abi/src/coins.rs index c3fa2dada..56255b0a8 100644 --- a/substrate/abi/src/coins.rs +++ b/substrate/abi/src/coins.rs @@ -5,7 +5,8 @@ use primitives::OutInstructionWithBalance; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] #[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Call { transfer { to: SeraiAddress, balance: Balance }, burn { balance: Balance }, @@ -14,7 +15,17 @@ pub enum Call { #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] #[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] +pub enum LiquidityTokensCall { + transfer { to: SeraiAddress, balance: Balance }, + burn { balance: Balance }, +} + +#[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] +#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Event { Mint { to: SeraiAddress, balance: Balance }, Burn { from: SeraiAddress, balance: Balance }, diff --git a/substrate/abi/src/dex.rs b/substrate/abi/src/dex.rs index 5136e9740..2daa62f07 100644 --- a/substrate/abi/src/dex.rs +++ b/substrate/abi/src/dex.rs @@ -6,7 +6,8 @@ type PoolId = Coin; type MaxSwapPathLength = sp_core::ConstU32<3>; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Call { add_liquidity { coin: Coin, @@ -38,7 +39,8 @@ pub enum Call { } #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Event { PoolCreated { pool_id: PoolId, diff --git a/substrate/abi/src/grandpa.rs b/substrate/abi/src/grandpa.rs index 54de8182a..376b0b1d3 100644 --- a/substrate/abi/src/grandpa.rs +++ b/substrate/abi/src/grandpa.rs @@ -4,7 +4,7 @@ use serai_primitives::{BlockNumber, SeraiAddress}; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] pub struct ReportEquivocation { - pub equivocation_proof: Box>, + pub equivocation_proof: alloc::boxed::Box>, pub key_owner_proof: SeraiAddress, } @@ -15,10 +15,10 @@ pub enum Call { } #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] -#[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Event { - NewAuthorities { authority_set: Vec<(SeraiAddress, u64)> }, + NewAuthorities { authority_set: alloc::vec::Vec<(SeraiAddress, u64)> }, // TODO: Remove these Paused, Resumed, diff --git a/substrate/abi/src/in_instructions.rs b/substrate/abi/src/in_instructions.rs index 1e5d1bb54..d3ab5ca3d 100644 --- a/substrate/abi/src/in_instructions.rs +++ b/substrate/abi/src/in_instructions.rs @@ -5,14 +5,16 @@ use primitives::SignedBatch; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] #[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Call { execute_batch { batch: SignedBatch }, } #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] #[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Event { Batch { network: NetworkId, id: u32, block: BlockHash, instructions_hash: [u8; 32] }, InstructionFailure { network: NetworkId, id: u32, index: u32 }, diff --git a/substrate/abi/src/lib.rs b/substrate/abi/src/lib.rs index e59f30856..aef03963e 100644 --- a/substrate/abi/src/lib.rs +++ b/substrate/abi/src/lib.rs @@ -1,5 +1,12 @@ +#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![cfg_attr(not(feature = "std"), no_std)] #![allow(non_camel_case_types)] +extern crate alloc; + +pub use serai_primitives as primitives; + pub mod system; pub mod timestamp; @@ -16,15 +23,13 @@ pub mod genesis_liquidity; pub mod babe; pub mod grandpa; -pub use serai_primitives as primitives; +pub mod tx; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] pub enum Call { - System, Timestamp(timestamp::Call), - TransactionPayment, Coins(coins::Call), - LiquidityTokens(coins::Call), + LiquidityTokens(coins::LiquidityTokensCall), Dex(dex::Call), GenesisLiquidity(genesis_liquidity::Call), ValidatorSets(validator_sets::Call), @@ -57,16 +62,20 @@ pub enum Event { } #[derive(Clone, Copy, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub struct Extra { pub era: sp_runtime::generic::Era, - pub nonce: scale::Compact, - pub tip: scale::Compact, + #[codec(compact)] + pub nonce: u32, + #[codec(compact)] + pub tip: u64, } #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] #[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub struct SignedPayloadExtra { pub spec_version: u32, pub tx_version: u32, @@ -74,4 +83,4 @@ pub struct SignedPayloadExtra { pub mortality_checkpoint: [u8; 32], } -pub type Transaction = primitives::Transaction; +pub type Transaction = tx::Transaction; diff --git a/substrate/abi/src/signals.rs b/substrate/abi/src/signals.rs index 2c8dd5450..6a77672f2 100644 --- a/substrate/abi/src/signals.rs +++ b/substrate/abi/src/signals.rs @@ -7,7 +7,8 @@ use primitives::SignalId; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] #[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Call { register_retirement_signal { in_favor_of: [u8; 32] }, revoke_retirement_signal { retirement_signal_id: [u8; 32] }, @@ -18,7 +19,8 @@ pub enum Call { #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] #[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Event { RetirementSignalRegistered { signal_id: [u8; 32], diff --git a/substrate/abi/src/system.rs b/substrate/abi/src/system.rs index bb67c91c6..d025e767f 100644 --- a/substrate/abi/src/system.rs +++ b/substrate/abi/src/system.rs @@ -3,7 +3,6 @@ use frame_support::dispatch::{DispatchInfo, DispatchError}; use serai_primitives::SeraiAddress; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Event { ExtrinsicSuccess { dispatch_info: DispatchInfo }, ExtrinsicFailed { dispatch_error: DispatchError, dispatch_info: DispatchInfo }, diff --git a/substrate/abi/src/timestamp.rs b/substrate/abi/src/timestamp.rs index c6e7d8cdb..af7639289 100644 --- a/substrate/abi/src/timestamp.rs +++ b/substrate/abi/src/timestamp.rs @@ -1,5 +1,9 @@ #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Call { - set { now: scale::Compact }, + set { + #[codec(compact)] + now: u64, + }, } diff --git a/substrate/abi/src/tx.rs b/substrate/abi/src/tx.rs new file mode 100644 index 000000000..6c61535b8 --- /dev/null +++ b/substrate/abi/src/tx.rs @@ -0,0 +1,183 @@ +use scale::Encode; + +use sp_core::sr25519::{Public, Signature}; +use sp_runtime::traits::Verify; + +use serai_primitives::SeraiAddress; + +use frame_support::dispatch::GetDispatchInfo; + +pub trait TransactionMember: + Clone + PartialEq + Eq + core::fmt::Debug + scale::Encode + scale::Decode + scale_info::TypeInfo +{ +} +impl< + T: Clone + + PartialEq + + Eq + + core::fmt::Debug + + scale::Encode + + scale::Decode + + scale_info::TypeInfo, + > TransactionMember for T +{ +} + +type TransactionEncodeAs<'a, Extra> = + (&'a crate::Call, &'a Option<(SeraiAddress, Signature, Extra)>); +type TransactionDecodeAs = (crate::Call, Option<(SeraiAddress, Signature, Extra)>); + +// We use our own Transaction struct, over UncheckedExtrinsic, for more control, a bit more +// simplicity, and in order to be immune to https://github.com/paritytech/polkadot-sdk/issues/2947 +#[allow(private_bounds)] +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Transaction< + Call: 'static + TransactionMember + From, + Extra: 'static + TransactionMember, +> { + call: crate::Call, + mapped_call: Call, + signature: Option<(SeraiAddress, Signature, Extra)>, +} + +impl, Extra: 'static + TransactionMember> + Transaction +{ + pub fn new(call: crate::Call, signature: Option<(SeraiAddress, Signature, Extra)>) -> Self { + Self { call: call.clone(), mapped_call: call.into(), signature } + } + + pub fn call(&self) -> &crate::Call { + &self.call + } +} + +impl, Extra: 'static + TransactionMember> + scale::Encode for Transaction +{ + fn using_encoded R>(&self, f: F) -> R { + let tx: TransactionEncodeAs = (&self.call, &self.signature); + tx.using_encoded(f) + } +} +impl, Extra: 'static + TransactionMember> + scale::Decode for Transaction +{ + fn decode(input: &mut I) -> Result { + let (call, signature) = TransactionDecodeAs::decode(input)?; + let mapped_call = Call::from(call.clone()); + Ok(Self { call, mapped_call, signature }) + } +} +impl, Extra: 'static + TransactionMember> + scale_info::TypeInfo for Transaction +{ + type Identity = TransactionDecodeAs; + + // Define the type info as the info of the type equivalent to what we encode as + fn type_info() -> scale_info::Type { + TransactionDecodeAs::::type_info() + } +} + +#[cfg(feature = "serde")] +mod _serde { + use scale::Encode; + use serde::{ser::*, de::*}; + use super::*; + impl, Extra: 'static + TransactionMember> + Serialize for Transaction + { + fn serialize(&self, serializer: S) -> Result { + let encoded = self.encode(); + serializer.serialize_bytes(&encoded) + } + } + #[cfg(feature = "std")] + impl< + 'a, + Call: 'static + TransactionMember + From, + Extra: 'static + TransactionMember, + > Deserialize<'a> for Transaction + { + fn deserialize>(de: D) -> Result { + let bytes = sp_core::bytes::deserialize(de)?; + ::decode(&mut &bytes[..]) + .map_err(|e| serde::de::Error::custom(format!("invalid transaction: {e}"))) + } + } +} + +impl< + Call: 'static + TransactionMember + From + TryInto, + Extra: 'static + TransactionMember, + > sp_runtime::traits::Extrinsic for Transaction +{ + type Call = Call; + type SignaturePayload = (SeraiAddress, Signature, Extra); + fn is_signed(&self) -> Option { + Some(self.signature.is_some()) + } + fn new(call: Call, signature: Option) -> Option { + Some(Self { call: call.clone().try_into().ok()?, mapped_call: call, signature }) + } +} + +impl< + Call: 'static + TransactionMember + From + TryInto, + Extra: 'static + TransactionMember, + > frame_support::traits::ExtrinsicCall for Transaction +{ + fn call(&self) -> &Call { + &self.mapped_call + } +} + +impl< + Call: 'static + TransactionMember + From, + Extra: 'static + TransactionMember + sp_runtime::traits::SignedExtension, + > sp_runtime::traits::ExtrinsicMetadata for Transaction +{ + type SignedExtensions = Extra; + + const VERSION: u8 = 0; +} + +impl< + Call: 'static + TransactionMember + From + GetDispatchInfo, + Extra: 'static + TransactionMember, + > GetDispatchInfo for Transaction +{ + fn get_dispatch_info(&self) -> frame_support::dispatch::DispatchInfo { + self.mapped_call.get_dispatch_info() + } +} + +impl< + Call: 'static + TransactionMember + From, + Extra: 'static + TransactionMember + sp_runtime::traits::SignedExtension, + > sp_runtime::traits::BlindCheckable for Transaction +{ + type Checked = sp_runtime::generic::CheckedExtrinsic; + + fn check( + self, + ) -> Result { + Ok(match self.signature { + Some((signer, signature, extra)) => { + if !signature.verify( + (&self.call, &extra, extra.additional_signed()?).encode().as_slice(), + &signer.into(), + ) { + Err(sp_runtime::transaction_validity::InvalidTransaction::BadProof)? + } + + sp_runtime::generic::CheckedExtrinsic { + signed: Some((signer.into(), extra)), + function: self.mapped_call, + } + } + None => sp_runtime::generic::CheckedExtrinsic { signed: None, function: self.mapped_call }, + }) + } +} diff --git a/substrate/abi/src/validator_sets.rs b/substrate/abi/src/validator_sets.rs index 1630f8aca..1e1e33591 100644 --- a/substrate/abi/src/validator_sets.rs +++ b/substrate/abi/src/validator_sets.rs @@ -1,4 +1,4 @@ -use sp_core::{ConstU32, bounded_vec::BoundedVec}; +use sp_core::{ConstU32, bounded::BoundedVec}; pub use serai_validator_sets_primitives as primitives; @@ -6,11 +6,12 @@ use serai_primitives::*; use serai_validator_sets_primitives::*; #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Call { set_keys { network: NetworkId, - removed_participants: Vec, + removed_participants: BoundedVec>, key_pair: KeyPair, signature: Signature, }, @@ -35,7 +36,8 @@ pub enum Call { #[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] #[cfg_attr(feature = "borsh", derive(borsh::BorshSerialize, borsh::BorshDeserialize))] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(all(feature = "std", feature = "serde"), derive(serde::Deserialize))] pub enum Event { NewSet { set: ValidatorSet, diff --git a/substrate/client/Cargo.toml b/substrate/client/Cargo.toml index f97e40fba..0eeb3a2f5 100644 --- a/substrate/client/Cargo.toml +++ b/substrate/client/Cargo.toml @@ -36,7 +36,7 @@ async-lock = "3" simple-request = { path = "../../common/request", version = "0.1", optional = true } -bitcoin = { version = "0.31", optional = true } +bitcoin = { version = "0.32", optional = true } ciphersuite = { path = "../../crypto/ciphersuite", version = "0.4", optional = true } monero-serai = { path = "../../coins/monero", version = "0.1.4-alpha", optional = true } diff --git a/substrate/client/src/networks/bitcoin.rs b/substrate/client/src/networks/bitcoin.rs index 5ea37898a..502bfb440 100644 --- a/substrate/client/src/networks/bitcoin.rs +++ b/substrate/client/src/networks/bitcoin.rs @@ -6,38 +6,46 @@ use bitcoin::{ hashes::{Hash as HashTrait, hash160::Hash}, PubkeyHash, ScriptHash, network::Network, - WitnessVersion, WitnessProgram, - address::{Error, Payload, NetworkChecked, Address as BAddressGeneric}, + WitnessVersion, WitnessProgram, ScriptBuf, + address::{AddressType, NetworkChecked, Address as BAddress}, }; -type BAddress = BAddressGeneric; - #[derive(Clone, Eq, Debug)] -pub struct Address(BAddress); +pub struct Address(ScriptBuf); impl PartialEq for Address { fn eq(&self, other: &Self) -> bool { - // Since Serai defines the Bitcoin-address specification as a variant of the payload alone, - // define equivalency as the payload alone - self.0.payload() == other.0.payload() + // Since Serai defines the Bitcoin-address specification as a variant of the script alone, + // define equivalency as the script alone + self.0 == other.0 + } +} + +impl From
for ScriptBuf { + fn from(addr: Address) -> ScriptBuf { + addr.0 } } impl FromStr for Address { - type Err = Error; - fn from_str(str: &str) -> Result { + type Err = (); + fn from_str(str: &str) -> Result { Address::new( - BAddressGeneric::from_str(str) - .map_err(|_| Error::UnrecognizedScript)? - .require_network(Network::Bitcoin)?, + BAddress::from_str(str) + .map_err(|_| ())? + .require_network(Network::Bitcoin) + .map_err(|_| ())? + .script_pubkey(), ) - .ok_or(Error::UnrecognizedScript) + .ok_or(()) } } impl fmt::Display for Address { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) + BAddress::::from_script(&self.0, Network::Bitcoin) + .map_err(|_| fmt::Error)? + .fmt(f) } } @@ -54,55 +62,52 @@ enum EncodedAddress { impl TryFrom> for Address { type Error = (); fn try_from(data: Vec) -> Result { - Ok(Address(BAddress::new( - Network::Bitcoin, - match EncodedAddress::decode(&mut data.as_ref()).map_err(|_| ())? { - EncodedAddress::P2PKH(hash) => { - Payload::PubkeyHash(PubkeyHash::from_raw_hash(Hash::from_byte_array(hash))) - } - EncodedAddress::P2SH(hash) => { - Payload::ScriptHash(ScriptHash::from_raw_hash(Hash::from_byte_array(hash))) - } - EncodedAddress::P2WPKH(hash) => { - Payload::WitnessProgram(WitnessProgram::new(WitnessVersion::V0, hash).unwrap()) - } - EncodedAddress::P2WSH(hash) => { - Payload::WitnessProgram(WitnessProgram::new(WitnessVersion::V0, hash).unwrap()) - } - EncodedAddress::P2TR(key) => { - Payload::WitnessProgram(WitnessProgram::new(WitnessVersion::V1, key).unwrap()) - } - }, - ))) + Ok(Address(match EncodedAddress::decode(&mut data.as_ref()).map_err(|_| ())? { + EncodedAddress::P2PKH(hash) => { + ScriptBuf::new_p2pkh(&PubkeyHash::from_raw_hash(Hash::from_byte_array(hash))) + } + EncodedAddress::P2SH(hash) => { + ScriptBuf::new_p2sh(&ScriptHash::from_raw_hash(Hash::from_byte_array(hash))) + } + EncodedAddress::P2WPKH(hash) => { + ScriptBuf::new_witness_program(&WitnessProgram::new(WitnessVersion::V0, &hash).unwrap()) + } + EncodedAddress::P2WSH(hash) => { + ScriptBuf::new_witness_program(&WitnessProgram::new(WitnessVersion::V0, &hash).unwrap()) + } + EncodedAddress::P2TR(key) => { + ScriptBuf::new_witness_program(&WitnessProgram::new(WitnessVersion::V1, &key).unwrap()) + } + })) } } fn try_to_vec(addr: &Address) -> Result, ()> { + let parsed_addr = + BAddress::::from_script(&addr.0, Network::Bitcoin).map_err(|_| ())?; Ok( - (match addr.0.payload() { - Payload::PubkeyHash(hash) => EncodedAddress::P2PKH(*hash.as_raw_hash().as_byte_array()), - Payload::ScriptHash(hash) => EncodedAddress::P2SH(*hash.as_raw_hash().as_byte_array()), - Payload::WitnessProgram(program) => match program.version() { - WitnessVersion::V0 => { - let program = program.program(); - if program.len() == 20 { - let mut buf = [0; 20]; - buf.copy_from_slice(program.as_ref()); - EncodedAddress::P2WPKH(buf) - } else if program.len() == 32 { - let mut buf = [0; 32]; - buf.copy_from_slice(program.as_ref()); - EncodedAddress::P2WSH(buf) - } else { - Err(())? - } - } - WitnessVersion::V1 => { - let program_ref: &[u8] = program.program().as_ref(); - EncodedAddress::P2TR(program_ref.try_into().map_err(|_| ())?) - } - _ => Err(())?, - }, + (match parsed_addr.address_type() { + Some(AddressType::P2pkh) => { + EncodedAddress::P2PKH(*parsed_addr.pubkey_hash().unwrap().as_raw_hash().as_byte_array()) + } + Some(AddressType::P2sh) => { + EncodedAddress::P2SH(*parsed_addr.script_hash().unwrap().as_raw_hash().as_byte_array()) + } + Some(AddressType::P2wpkh) => { + let program = parsed_addr.witness_program().ok_or(())?; + let program = program.program().as_bytes(); + EncodedAddress::P2WPKH(program.try_into().map_err(|_| ())?) + } + Some(AddressType::P2wsh) => { + let program = parsed_addr.witness_program().ok_or(())?; + let program = program.program().as_bytes(); + EncodedAddress::P2WSH(program.try_into().map_err(|_| ())?) + } + Some(AddressType::P2tr) => { + let program = parsed_addr.witness_program().ok_or(())?; + let program = program.program().as_bytes(); + EncodedAddress::P2TR(program.try_into().map_err(|_| ())?) + } _ => Err(())?, }) .encode(), @@ -116,20 +121,8 @@ impl From
for Vec { } } -impl From
for BAddress { - fn from(addr: Address) -> BAddress { - addr.0 - } -} - -impl AsRef for Address { - fn as_ref(&self) -> &BAddress { - &self.0 - } -} - impl Address { - pub fn new(address: BAddress) -> Option { + pub fn new(address: ScriptBuf) -> Option { let res = Self(address); if try_to_vec(&res).is_ok() { return Some(res); diff --git a/substrate/client/src/serai/mod.rs b/substrate/client/src/serai/mod.rs index fc4a9ea7b..93060c41c 100644 --- a/substrate/client/src/serai/mod.rs +++ b/substrate/client/src/serai/mod.rs @@ -4,7 +4,7 @@ use thiserror::Error; use async_lock::RwLock; use simple_request::{hyper, Request, Client}; -use scale::{Compact, Decode, Encode}; +use scale::{Decode, Encode}; use serde::{Serialize, Deserialize, de::DeserializeOwned}; pub use sp_core::{ @@ -48,8 +48,8 @@ impl Block { /// Returns the time of this block, set by its producer, in milliseconds since the epoch. pub fn time(&self) -> Result { for transaction in &self.transactions { - if let Call::Timestamp(timestamp::Call::set { now }) = &transaction.call { - return Ok(u64::from(*now)); + if let Call::Timestamp(timestamp::Call::set { now }) = transaction.call() { + return Ok(*now); } } Err(SeraiError::InvalidNode("no time was present in block".to_string())) @@ -167,15 +167,14 @@ impl Serai { } fn unsigned(call: Call) -> Transaction { - Transaction { call, signature: None } + Transaction::new(call, None) } pub fn sign(&self, signer: &Pair, call: Call, nonce: u32, tip: u64) -> Transaction { const SPEC_VERSION: u32 = 1; const TX_VERSION: u32 = 1; - let extra = - Extra { era: sp_runtime::generic::Era::Immortal, nonce: Compact(nonce), tip: Compact(tip) }; + let extra = Extra { era: sp_runtime::generic::Era::Immortal, nonce, tip }; let signature_payload = ( &call, &extra, @@ -189,7 +188,7 @@ impl Serai { .encode(); let signature = signer.sign(&signature_payload); - Transaction { call, signature: Some((signer.public().into(), signature, extra)) } + Transaction::new(call, Some((signer.public().into(), signature, extra))) } pub async fn publish(&self, tx: &Transaction) -> Result<(), SeraiError> { @@ -202,7 +201,7 @@ impl Serai { // TODO: move this into substrate/client/src/validator_sets.rs async fn active_network_validators(&self, network: NetworkId) -> Result, SeraiError> { - let hash: String = self + let validators: String = self .call("state_call", ["SeraiRuntimeApi_validators".to_string(), hex::encode(network.encode())]) .await?; let bytes = hex_decode(hash) @@ -378,7 +377,10 @@ impl<'a> TemporalSerai<'a> { let res = hex_decode(res) .map_err(|_| SeraiError::InvalidNode("expected hex from node wasn't hex".to_string()))?; Ok(Some(R::decode(&mut res.as_slice()).map_err(|_| { - SeraiError::InvalidRuntime("different type present at storage location".to_string()) + SeraiError::InvalidRuntime(format!( + "different type present at storage location, raw value: {}", + hex::encode(res) + )) })?)) } diff --git a/substrate/client/src/serai/validator_sets.rs b/substrate/client/src/serai/validator_sets.rs index c4e296441..959f8ee60 100644 --- a/substrate/client/src/serai/validator_sets.rs +++ b/substrate/client/src/serai/validator_sets.rs @@ -180,7 +180,10 @@ impl<'a> SeraiValidatorSets<'a> { pub fn set_keys( network: NetworkId, - removed_participants: Vec, + removed_participants: sp_runtime::BoundedVec< + SeraiAddress, + sp_core::ConstU32<{ primitives::MAX_KEY_SHARES_PER_SET / 3 }>, + >, key_pair: KeyPair, signature: Signature, ) -> Transaction { diff --git a/substrate/client/tests/common/in_instructions.rs b/substrate/client/tests/common/in_instructions.rs index b4c248980..e335244a2 100644 --- a/substrate/client/tests/common/in_instructions.rs +++ b/substrate/client/tests/common/in_instructions.rs @@ -31,7 +31,7 @@ pub async fn provide_batch(serai: &Serai, batch: Batch) -> [u8; 32] { keys } else { let keys = KeyPair(pair.public(), vec![].try_into().unwrap()); - set_keys(serai, set, keys.clone()).await; + set_keys(serai, set, keys.clone(), &[insecure_pair_from_name("Alice")]).await; keys }; assert_eq!(keys.0, pair.public()); diff --git a/substrate/client/tests/common/validator_sets.rs b/substrate/client/tests/common/validator_sets.rs index b7257a1ce..3238501a3 100644 --- a/substrate/client/tests/common/validator_sets.rs +++ b/substrate/client/tests/common/validator_sets.rs @@ -14,7 +14,6 @@ use frost::dkg::musig::musig; use schnorrkel::Schnorrkel; use serai_client::{ - primitives::insecure_pair_from_name, validator_sets::{ primitives::{ValidatorSet, KeyPair, musig_context, set_keys_message}, ValidatorSetsEvent, @@ -25,33 +24,52 @@ use serai_client::{ use crate::common::tx::publish_tx; #[allow(dead_code)] -pub async fn set_keys(serai: &Serai, set: ValidatorSet, key_pair: KeyPair) -> [u8; 32] { - let pair = insecure_pair_from_name("Alice"); - let public = pair.public(); +pub async fn set_keys( + serai: &Serai, + set: ValidatorSet, + key_pair: KeyPair, + pairs: &[Pair], +) -> [u8; 32] { + let mut pub_keys = vec![]; + for pair in pairs { + let public_key = + ::read_G::<&[u8]>(&mut pair.public().0.as_ref()).unwrap(); + pub_keys.push(public_key); + } - let public_key = ::read_G::<&[u8]>(&mut public.0.as_ref()).unwrap(); - let secret_key = ::read_F::<&[u8]>( - &mut pair.as_ref().secret.to_bytes()[.. 32].as_ref(), - ) - .unwrap(); - assert_eq!(Ristretto::generator() * secret_key, public_key); - let threshold_keys = - musig::(&musig_context(set), &Zeroizing::new(secret_key), &[public_key]).unwrap(); + let mut threshold_keys = vec![]; + for i in 0 .. pairs.len() { + let secret_key = ::read_F::<&[u8]>( + &mut pairs[i].as_ref().secret.to_bytes()[.. 32].as_ref(), + ) + .unwrap(); + assert_eq!(Ristretto::generator() * secret_key, pub_keys[i]); + + threshold_keys.push( + musig::(&musig_context(set), &Zeroizing::new(secret_key), &pub_keys).unwrap(), + ); + } + + let mut musig_keys = HashMap::new(); + for tk in threshold_keys { + musig_keys.insert(tk.params().i(), tk.into()); + } let sig = frost::tests::sign_without_caching( &mut OsRng, - frost::tests::algorithm_machines( - &mut OsRng, - &Schnorrkel::new(b"substrate"), - &HashMap::from([(threshold_keys.params().i(), threshold_keys.into())]), - ), + frost::tests::algorithm_machines(&mut OsRng, &Schnorrkel::new(b"substrate"), &musig_keys), &set_keys_message(&set, &[], &key_pair), ); // Set the key pair let block = publish_tx( serai, - &SeraiValidatorSets::set_keys(set.network, vec![], key_pair.clone(), Signature(sig.to_bytes())), + &SeraiValidatorSets::set_keys( + set.network, + vec![].try_into().unwrap(), + key_pair.clone(), + Signature(sig.to_bytes()), + ), ) .await; diff --git a/substrate/client/tests/validator_sets.rs b/substrate/client/tests/validator_sets.rs index a44a0ac43..8aa8174f4 100644 --- a/substrate/client/tests/validator_sets.rs +++ b/substrate/client/tests/validator_sets.rs @@ -1,36 +1,71 @@ use rand_core::{RngCore, OsRng}; -use sp_core::{sr25519::Public, Pair}; +use sp_core::{ + sr25519::{Public, Pair}, + Pair as PairTrait, +}; use serai_client::{ - primitives::{NETWORKS, NetworkId, insecure_pair_from_name}, + primitives::{NETWORKS, NetworkId, BlockHash, insecure_pair_from_name}, validator_sets::{ primitives::{Session, ValidatorSet, KeyPair}, ValidatorSetsEvent, }, + in_instructions::{ + primitives::{Batch, SignedBatch, batch_message}, + SeraiInInstructions, + }, Amount, Serai, }; mod common; -use common::validator_sets::{set_keys, allocate_stake, deallocate_stake}; +use common::{ + tx::publish_tx, + validator_sets::{allocate_stake, deallocate_stake, set_keys}, +}; -const EPOCH_INTERVAL: u64 = 300; +fn get_random_key_pair() -> KeyPair { + let mut ristretto_key = [0; 32]; + OsRng.fill_bytes(&mut ristretto_key); + let mut external_key = vec![0; 33]; + OsRng.fill_bytes(&mut external_key); + KeyPair(Public(ristretto_key), external_key.try_into().unwrap()) +} + +async fn get_ordered_keys(serai: &Serai, network: NetworkId, accounts: &[Pair]) -> Vec { + // retrieve the current session validators so that we know the order of the keys + // that is necessary for the correct musig signature. + let validators = serai + .as_of_latest_finalized_block() + .await + .unwrap() + .validator_sets() + .active_network_validators(network) + .await + .unwrap(); + + // collect the pairs of the validators + let mut pairs = vec![]; + for v in validators { + let p = accounts.iter().find(|pair| pair.public() == v).unwrap().clone(); + pairs.push(p); + } + + pairs +} serai_test!( set_keys_test: (|serai: Serai| async move { let network = NetworkId::Bitcoin; let set = ValidatorSet { session: Session(0), network }; - let public = insecure_pair_from_name("Alice").public(); + let pair = insecure_pair_from_name("Alice"); + let public = pair.public(); // Neither of these keys are validated // The external key is infeasible to validate on-chain, the Ristretto key is feasible // TODO: Should the Ristretto key be validated? - let mut ristretto_key = [0; 32]; - OsRng.fill_bytes(&mut ristretto_key); - let mut external_key = vec![0; 33]; - OsRng.fill_bytes(&mut external_key); - let key_pair = KeyPair(Public(ristretto_key), external_key.try_into().unwrap()); + let key_pair = get_random_key_pair(); // Make sure the genesis is as expected assert_eq!( @@ -62,7 +97,7 @@ serai_test!( assert_eq!(participants_ref, [public].as_ref()); } - let block = set_keys(&serai, set, key_pair.clone()).await; + let block = set_keys(&serai, set, key_pair.clone(), &[pair]).await; // While the set_keys function should handle this, it's beneficial to // independently test it @@ -149,11 +184,13 @@ async fn validator_set_rotation() { ); // genesis accounts - let pair1 = insecure_pair_from_name("Alice"); - let pair2 = insecure_pair_from_name("Bob"); - let pair3 = insecure_pair_from_name("Charlie"); - let pair4 = insecure_pair_from_name("Dave"); - let pair5 = insecure_pair_from_name("Eve"); + let accounts = vec![ + insecure_pair_from_name("Alice"), + insecure_pair_from_name("Bob"), + insecure_pair_from_name("Charlie"), + insecure_pair_from_name("Dave"), + insecure_pair_from_name("Eve"), + ]; // amounts for single key share per network let key_shares = HashMap::from([ @@ -164,8 +201,9 @@ async fn validator_set_rotation() { ]); // genesis participants per network + #[allow(clippy::redundant_closure_for_method_calls)] let default_participants = - vec![pair1.public(), pair2.public(), pair3.public(), pair4.public()]; + accounts[.. 4].to_vec().iter().map(|pair| pair.public()).collect::>(); let mut participants = HashMap::from([ (NetworkId::Serai, default_participants.clone()), (NetworkId::Bitcoin, default_participants.clone()), @@ -181,28 +219,83 @@ async fn validator_set_rotation() { participants.sort(); verify_session_and_active_validators(&serai, network, 0, participants).await; - // add 1 participant & verify - let hash = - allocate_stake(&serai, network, key_shares[&network], &pair5, i.try_into().unwrap()) - .await; - participants.push(pair5.public()); + // add 1 participant + let last_participant = accounts[4].clone(); + let hash = allocate_stake( + &serai, + network, + key_shares[&network], + &last_participant, + i.try_into().unwrap(), + ) + .await; + participants.push(last_participant.public()); + // the session at which set changes becomes active + let activation_session = get_session_at_which_changes_activate(&serai, network, hash).await; + + // set the keys if it is an external set + if network != NetworkId::Serai { + let set = ValidatorSet { session: Session(0), network }; + let key_pair = get_random_key_pair(); + let pairs = get_ordered_keys(&serai, network, &accounts).await; + set_keys(&serai, set, key_pair, &pairs).await; + } + + // verify participants.sort(); - verify_session_and_active_validators( + verify_session_and_active_validators(&serai, network, activation_session, participants) + .await; + + // remove 1 participant + let participant_to_remove = accounts[1].clone(); + let hash = deallocate_stake( &serai, network, - get_active_session(&serai, network, hash).await, - participants, + key_shares[&network], + &participant_to_remove, + i.try_into().unwrap(), ) .await; + participants.swap_remove( + participants.iter().position(|k| *k == participant_to_remove.public()).unwrap(), + ); + let activation_session = get_session_at_which_changes_activate(&serai, network, hash).await; + + if network != NetworkId::Serai { + // set the keys if it is an external set + let set = ValidatorSet { session: Session(1), network }; + + // we need the whole substrate key pair to sign the batch + let (substrate_pair, key_pair) = { + let pair = insecure_pair_from_name("session-1-key-pair"); + let public = pair.public(); + + let mut external_key = vec![0; 33]; + OsRng.fill_bytes(&mut external_key); + + (pair, KeyPair(public, external_key.try_into().unwrap())) + }; + let pairs = get_ordered_keys(&serai, network, &accounts).await; + set_keys(&serai, set, key_pair, &pairs).await; + + // provide a batch to complete the handover and retire the previous set + let mut block_hash = BlockHash([0; 32]); + OsRng.fill_bytes(&mut block_hash.0); + let batch = Batch { network, id: 0, block: block_hash, instructions: vec![] }; + publish_tx( + &serai, + &SeraiInInstructions::execute_batch(SignedBatch { + batch: batch.clone(), + signature: substrate_pair.sign(&batch_message(&batch)), + }), + ) + .await; + } - // remove 1 participant & verify - let hash = - deallocate_stake(&serai, network, key_shares[&network], &pair2, i.try_into().unwrap()) - .await; - participants.swap_remove(participants.iter().position(|k| *k == pair2.public()).unwrap()); - let active_session = get_active_session(&serai, network, hash).await; + // verify participants.sort(); - verify_session_and_active_validators(&serai, network, active_session, participants).await; + verify_session_and_active_validators(&serai, network, activation_session, participants) + .await; // check pending deallocations let pending = serai @@ -212,8 +305,8 @@ async fn validator_set_rotation() { .validator_sets() .pending_deallocations( network, - pair2.public(), - Session(u32::try_from(active_session + 1).unwrap()), + participant_to_remove.public(), + Session(activation_session + 1), ) .await .unwrap(); @@ -223,24 +316,39 @@ async fn validator_set_rotation() { .await; } +async fn session_for_block(serai: &Serai, block: [u8; 32], network: NetworkId) -> u32 { + serai.as_of(block).validator_sets().session(network).await.unwrap().unwrap().0 +} + async fn verify_session_and_active_validators( serai: &Serai, network: NetworkId, - session: u64, + session: u32, participants: &[Public], ) { - // wait untill the epoch block finalized - let epoch_block = (session * EPOCH_INTERVAL) + 1; - while serai.finalized_block_by_number(epoch_block).await.unwrap().is_none() { - // sleep 1 block - tokio::time::sleep(tokio::time::Duration::from_secs(6)).await; - } - let serai_for_block = - serai.as_of(serai.finalized_block_by_number(epoch_block).await.unwrap().unwrap().hash()); + // wait until the active session. This wait should be max 30 secs since the epoch time. + let block = tokio::time::timeout(core::time::Duration::from_secs(2 * 60), async move { + loop { + let mut block = serai.latest_finalized_block_hash().await.unwrap(); + if session_for_block(serai, block, network).await < session { + // Sleep a block + tokio::time::sleep(core::time::Duration::from_secs(6)).await; + continue; + } + while session_for_block(serai, block, network).await > session { + block = serai.block(block).await.unwrap().unwrap().header.parent_hash.0; + } + assert_eq!(session_for_block(serai, block, network).await, session); + break block; + } + }) + .await + .unwrap(); + let serai_for_block = serai.as_of(block); // verify session let s = serai_for_block.validator_sets().session(network).await.unwrap().unwrap(); - assert_eq!(u64::from(s.0), session); + assert_eq!(s.0, session); // verify participants let mut validators = @@ -249,10 +357,11 @@ async fn verify_session_and_active_validators( assert_eq!(validators, participants); // make sure finalization continues as usual after the changes - tokio::time::timeout(tokio::time::Duration::from_secs(60), async move { + let current_finalized_block = serai.latest_finalized_block().await.unwrap().header.number; + tokio::time::timeout(core::time::Duration::from_secs(60), async move { let mut finalized_block = serai.latest_finalized_block().await.unwrap().header.number; - while finalized_block <= epoch_block + 2 { - tokio::time::sleep(tokio::time::Duration::from_secs(6)).await; + while finalized_block <= current_finalized_block + 2 { + tokio::time::sleep(core::time::Duration::from_secs(6)).await; finalized_block = serai.latest_finalized_block().await.unwrap().header.number; } }) @@ -262,15 +371,18 @@ async fn verify_session_and_active_validators( // TODO: verify key shares as well? } -async fn get_active_session(serai: &Serai, network: NetworkId, hash: [u8; 32]) -> u64 { - let block_number = serai.block(hash).await.unwrap().unwrap().header.number; - let epoch = block_number / EPOCH_INTERVAL; +async fn get_session_at_which_changes_activate( + serai: &Serai, + network: NetworkId, + hash: [u8; 32], +) -> u32 { + let session = session_for_block(serai, hash, network).await; // changes should be active in the next session if network == NetworkId::Serai { // it takes 1 extra session for serai net to make the changes active. - epoch + 2 + session + 2 } else { - epoch + 1 + session + 1 } } diff --git a/substrate/coins/pallet/Cargo.toml b/substrate/coins/pallet/Cargo.toml index da9a27f6d..2aba1fbd1 100644 --- a/substrate/coins/pallet/Cargo.toml +++ b/substrate/coins/pallet/Cargo.toml @@ -49,6 +49,9 @@ std = [ "coins-primitives/std", ] +# TODO +try-runtime = [] + runtime-benchmarks = [ "frame-system/runtime-benchmarks", "frame-support/runtime-benchmarks", diff --git a/substrate/in-instructions/pallet/Cargo.toml b/substrate/in-instructions/pallet/Cargo.toml index c91c32508..f684cbaad 100644 --- a/substrate/in-instructions/pallet/Cargo.toml +++ b/substrate/in-instructions/pallet/Cargo.toml @@ -62,3 +62,6 @@ std = [ "genesis-liquidity-pallet/std", ] default = ["std"] + +# TODO +try-runtime = [] diff --git a/substrate/node/Cargo.toml b/substrate/node/Cargo.toml index 60f7dc0f6..0e551c72b 100644 --- a/substrate/node/Cargo.toml +++ b/substrate/node/Cargo.toml @@ -20,10 +20,11 @@ workspace = true name = "serai-node" [dependencies] +rand_core = "0.6" zeroize = "1" hex = "0.4" +log = "0.4" -rand_core = "0.6" schnorrkel = "0.11" libp2p = "0.52" diff --git a/substrate/node/src/chain_spec.rs b/substrate/node/src/chain_spec.rs index 428f929c7..976c54cd8 100644 --- a/substrate/node/src/chain_spec.rs +++ b/substrate/node/src/chain_spec.rs @@ -19,9 +19,12 @@ fn account_from_name(name: &'static str) -> PublicKey { fn wasm_binary() -> Vec { // TODO: Accept a config of runtime path - if let Ok(binary) = std::fs::read("/runtime/serai.wasm") { + const WASM_PATH: &str = "/runtime/serai.wasm"; + if let Ok(binary) = std::fs::read(WASM_PATH) { + log::info!("using {WASM_PATH}"); return binary; } + log::info!("using built-in wasm"); WASM_BINARY.ok_or("compiled in wasm not available").unwrap().to_vec() } diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index 970cf46e4..2af36e22d 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -37,9 +37,6 @@ pub use balance::*; mod account; pub use account::*; -mod tx; -pub use tx::*; - pub type BlockNumber = u64; pub type Header = sp_runtime::generic::Header; diff --git a/substrate/primitives/src/tx.rs b/substrate/primitives/src/tx.rs deleted file mode 100644 index b97ec3a2f..000000000 --- a/substrate/primitives/src/tx.rs +++ /dev/null @@ -1,124 +0,0 @@ -use scale::Encode; - -use sp_core::sr25519::{Public, Signature}; -use sp_runtime::traits::Verify; - -use crate::SeraiAddress; - -trait TransactionMember: - Clone + PartialEq + Eq + core::fmt::Debug + scale::Encode + scale::Decode + scale_info::TypeInfo -{ -} -impl< - T: Clone - + PartialEq - + Eq - + core::fmt::Debug - + scale::Encode - + scale::Decode - + scale_info::TypeInfo, - > TransactionMember for T -{ -} - -// We use our own Transaction struct, over UncheckedExtrinsic, for more control, a bit more -// simplicity, and in order to be immune to https://github.com/paritytech/polkadot-sdk/issues/2947 -#[allow(private_bounds)] -#[derive(Clone, PartialEq, Eq, Debug, scale::Encode, scale::Decode, scale_info::TypeInfo)] -pub struct Transaction { - pub call: Call, - pub signature: Option<(SeraiAddress, Signature, Extra)>, -} - -#[cfg(feature = "serde")] -mod _serde { - use scale::Encode; - use serde::{ser::*, de::*}; - use super::*; - impl Serialize for Transaction { - fn serialize(&self, serializer: S) -> Result { - let encoded = self.encode(); - serializer.serialize_bytes(&encoded) - } - } - #[cfg(feature = "std")] - impl<'a, Call: TransactionMember, Extra: TransactionMember> Deserialize<'a> - for Transaction - { - fn deserialize>(de: D) -> Result { - let bytes = sp_core::bytes::deserialize(de)?; - scale::Decode::decode(&mut &bytes[..]) - .map_err(|e| serde::de::Error::custom(format!("invalid transaction: {e}"))) - } - } -} - -impl sp_runtime::traits::Extrinsic - for Transaction -{ - type Call = Call; - type SignaturePayload = (SeraiAddress, Signature, Extra); - fn is_signed(&self) -> Option { - Some(self.signature.is_some()) - } - fn new(call: Call, signature: Option) -> Option { - Some(Self { call, signature }) - } -} - -impl frame_support::traits::ExtrinsicCall - for Transaction -{ - fn call(&self) -> &Call { - &self.call - } -} - -impl sp_runtime::traits::ExtrinsicMetadata - for Transaction -where - Extra: sp_runtime::traits::SignedExtension, -{ - type SignedExtensions = Extra; - - const VERSION: u8 = 0; -} - -impl frame_support::dispatch::GetDispatchInfo - for Transaction -where - Call: frame_support::dispatch::GetDispatchInfo, -{ - fn get_dispatch_info(&self) -> frame_support::dispatch::DispatchInfo { - self.call.get_dispatch_info() - } -} - -impl sp_runtime::traits::BlindCheckable - for Transaction -where - Extra: sp_runtime::traits::SignedExtension, -{ - type Checked = sp_runtime::generic::CheckedExtrinsic; - - fn check( - self, - ) -> Result { - Ok(match self.signature { - Some((signer, signature, extra)) => { - if !signature.verify( - (&self.call, &extra, extra.additional_signed()?).encode().as_slice(), - &signer.into(), - ) { - Err(sp_runtime::transaction_validity::InvalidTransaction::BadProof)? - } - - sp_runtime::generic::CheckedExtrinsic { - signed: Some((signer.into(), extra)), - function: self.call, - } - } - None => sp_runtime::generic::CheckedExtrinsic { signed: None, function: self.call }, - }) - } -} diff --git a/substrate/runtime/Cargo.toml b/substrate/runtime/Cargo.toml index 7a8169ec6..a8e60174f 100644 --- a/substrate/runtime/Cargo.toml +++ b/substrate/runtime/Cargo.toml @@ -49,6 +49,7 @@ frame-executive = { git = "https://github.com/serai-dex/substrate", default-feat frame-benchmarking = { git = "https://github.com/serai-dex/substrate", default-features = false, optional = true } serai-primitives = { path = "../primitives", default-features = false } +serai-abi = { path = "../abi", default-features = false, features = ["serde"] } pallet-timestamp = { git = "https://github.com/serai-dex/substrate", default-features = false } pallet-authorship = { git = "https://github.com/serai-dex/substrate", default-features = false } @@ -103,6 +104,8 @@ std = [ "frame-executive/std", "serai-primitives/std", + "serai-abi/std", + "serai-abi/serde", "pallet-timestamp/std", "pallet-authorship/std", diff --git a/substrate/runtime/src/abi.rs b/substrate/runtime/src/abi.rs new file mode 100644 index 000000000..45c2aa334 --- /dev/null +++ b/substrate/runtime/src/abi.rs @@ -0,0 +1,363 @@ +use core::marker::PhantomData; + +use scale::{Encode, Decode}; + +use serai_abi::Call; + +use crate::{ + Vec, + primitives::{PublicKey, SeraiAddress}, + timestamp, coins, dex, + validator_sets::{self, MembershipProof}, + in_instructions, signals, babe, grandpa, RuntimeCall, +}; + +impl From for RuntimeCall { + fn from(call: Call) -> RuntimeCall { + match call { + Call::Timestamp(serai_abi::timestamp::Call::set { now }) => { + RuntimeCall::Timestamp(timestamp::Call::set { now }) + } + Call::Coins(coins) => match coins { + serai_abi::coins::Call::transfer { to, balance } => { + RuntimeCall::Coins(coins::Call::transfer { to: to.into(), balance }) + } + serai_abi::coins::Call::burn { balance } => { + RuntimeCall::Coins(coins::Call::burn { balance }) + } + serai_abi::coins::Call::burn_with_instruction { instruction } => { + RuntimeCall::Coins(coins::Call::burn_with_instruction { instruction }) + } + }, + Call::LiquidityTokens(lt) => match lt { + serai_abi::coins::LiquidityTokensCall::transfer { to, balance } => { + RuntimeCall::LiquidityTokens(coins::Call::transfer { to: to.into(), balance }) + } + serai_abi::coins::LiquidityTokensCall::burn { balance } => { + RuntimeCall::LiquidityTokens(coins::Call::burn { balance }) + } + }, + Call::Dex(dex) => match dex { + serai_abi::dex::Call::add_liquidity { + coin, + coin_desired, + sri_desired, + coin_min, + sri_min, + mint_to, + } => RuntimeCall::Dex(dex::Call::add_liquidity { + coin, + coin_desired, + sri_desired, + coin_min, + sri_min, + mint_to: mint_to.into(), + }), + serai_abi::dex::Call::remove_liquidity { + coin, + lp_token_burn, + coin_min_receive, + sri_min_receive, + withdraw_to, + } => RuntimeCall::Dex(dex::Call::remove_liquidity { + coin, + lp_token_burn, + coin_min_receive, + sri_min_receive, + withdraw_to: withdraw_to.into(), + }), + serai_abi::dex::Call::swap_exact_tokens_for_tokens { + path, + amount_in, + amount_out_min, + send_to, + } => RuntimeCall::Dex(dex::Call::swap_exact_tokens_for_tokens { + path, + amount_in, + amount_out_min, + send_to: send_to.into(), + }), + serai_abi::dex::Call::swap_tokens_for_exact_tokens { + path, + amount_out, + amount_in_max, + send_to, + } => RuntimeCall::Dex(dex::Call::swap_tokens_for_exact_tokens { + path, + amount_out, + amount_in_max, + send_to: send_to.into(), + }), + }, + Call::ValidatorSets(vs) => match vs { + serai_abi::validator_sets::Call::set_keys { + network, + removed_participants, + key_pair, + signature, + } => RuntimeCall::ValidatorSets(validator_sets::Call::set_keys { + network, + removed_participants: <_>::try_from( + removed_participants.into_iter().map(PublicKey::from).collect::>(), + ) + .unwrap(), + key_pair, + signature, + }), + serai_abi::validator_sets::Call::report_slashes { network, slashes, signature } => { + RuntimeCall::ValidatorSets(validator_sets::Call::report_slashes { + network, + slashes: <_>::try_from( + slashes + .into_iter() + .map(|(addr, slash)| (PublicKey::from(addr), slash)) + .collect::>(), + ) + .unwrap(), + signature, + }) + } + serai_abi::validator_sets::Call::allocate { network, amount } => { + RuntimeCall::ValidatorSets(validator_sets::Call::allocate { network, amount }) + } + serai_abi::validator_sets::Call::deallocate { network, amount } => { + RuntimeCall::ValidatorSets(validator_sets::Call::deallocate { network, amount }) + } + serai_abi::validator_sets::Call::claim_deallocation { network, session } => { + RuntimeCall::ValidatorSets(validator_sets::Call::claim_deallocation { network, session }) + } + }, + Call::InInstructions(ii) => match ii { + serai_abi::in_instructions::Call::execute_batch { batch } => { + RuntimeCall::InInstructions(in_instructions::Call::execute_batch { batch }) + } + }, + Call::Signals(signals) => match signals { + serai_abi::signals::Call::register_retirement_signal { in_favor_of } => { + RuntimeCall::Signals(signals::Call::register_retirement_signal { in_favor_of }) + } + serai_abi::signals::Call::revoke_retirement_signal { retirement_signal_id } => { + RuntimeCall::Signals(signals::Call::revoke_retirement_signal { retirement_signal_id }) + } + serai_abi::signals::Call::favor { signal_id, for_network } => { + RuntimeCall::Signals(signals::Call::favor { signal_id, for_network }) + } + serai_abi::signals::Call::revoke_favor { signal_id, for_network } => { + RuntimeCall::Signals(signals::Call::revoke_favor { signal_id, for_network }) + } + serai_abi::signals::Call::stand_against { signal_id, for_network } => { + RuntimeCall::Signals(signals::Call::stand_against { signal_id, for_network }) + } + }, + Call::Babe(babe) => match babe { + serai_abi::babe::Call::report_equivocation(report) => { + RuntimeCall::Babe(babe::Call::report_equivocation { + // TODO: Find a better way to go from Proof<[u8; 32]> to Proof + equivocation_proof: <_>::decode(&mut report.equivocation_proof.encode().as_slice()) + .unwrap(), + key_owner_proof: MembershipProof(report.key_owner_proof.into(), PhantomData), + }) + } + serai_abi::babe::Call::report_equivocation_unsigned(report) => { + RuntimeCall::Babe(babe::Call::report_equivocation_unsigned { + // TODO: Find a better way to go from Proof<[u8; 32]> to Proof + equivocation_proof: <_>::decode(&mut report.equivocation_proof.encode().as_slice()) + .unwrap(), + key_owner_proof: MembershipProof(report.key_owner_proof.into(), PhantomData), + }) + } + }, + Call::Grandpa(grandpa) => match grandpa { + serai_abi::grandpa::Call::report_equivocation(report) => { + RuntimeCall::Grandpa(grandpa::Call::report_equivocation { + // TODO: Find a better way to go from Proof<[u8; 32]> to Proof + equivocation_proof: <_>::decode(&mut report.equivocation_proof.encode().as_slice()) + .unwrap(), + key_owner_proof: MembershipProof(report.key_owner_proof.into(), PhantomData), + }) + } + serai_abi::grandpa::Call::report_equivocation_unsigned(report) => { + RuntimeCall::Grandpa(grandpa::Call::report_equivocation_unsigned { + // TODO: Find a better way to go from Proof<[u8; 32]> to Proof + equivocation_proof: <_>::decode(&mut report.equivocation_proof.encode().as_slice()) + .unwrap(), + key_owner_proof: MembershipProof(report.key_owner_proof.into(), PhantomData), + }) + } + }, + } + } +} + +impl TryInto for RuntimeCall { + type Error = (); + + fn try_into(self) -> Result { + Ok(match self { + RuntimeCall::Timestamp(timestamp::Call::set { now }) => { + Call::Timestamp(serai_abi::timestamp::Call::set { now }) + } + RuntimeCall::Coins(call) => Call::Coins(match call { + coins::Call::transfer { to, balance } => { + serai_abi::coins::Call::transfer { to: to.into(), balance } + } + coins::Call::burn { balance } => serai_abi::coins::Call::burn { balance }, + coins::Call::burn_with_instruction { instruction } => { + serai_abi::coins::Call::burn_with_instruction { instruction } + } + _ => Err(())?, + }), + RuntimeCall::LiquidityTokens(call) => Call::LiquidityTokens(match call { + coins::Call::transfer { to, balance } => { + serai_abi::coins::LiquidityTokensCall::transfer { to: to.into(), balance } + } + coins::Call::burn { balance } => serai_abi::coins::LiquidityTokensCall::burn { balance }, + _ => Err(())?, + }), + RuntimeCall::Dex(call) => Call::Dex(match call { + dex::Call::add_liquidity { + coin, + coin_desired, + sri_desired, + coin_min, + sri_min, + mint_to, + } => serai_abi::dex::Call::add_liquidity { + coin, + coin_desired, + sri_desired, + coin_min, + sri_min, + mint_to: mint_to.into(), + }, + dex::Call::remove_liquidity { + coin, + lp_token_burn, + coin_min_receive, + sri_min_receive, + withdraw_to, + } => serai_abi::dex::Call::remove_liquidity { + coin, + lp_token_burn, + coin_min_receive, + sri_min_receive, + withdraw_to: withdraw_to.into(), + }, + dex::Call::swap_exact_tokens_for_tokens { path, amount_in, amount_out_min, send_to } => { + serai_abi::dex::Call::swap_exact_tokens_for_tokens { + path, + amount_in, + amount_out_min, + send_to: send_to.into(), + } + } + dex::Call::swap_tokens_for_exact_tokens { path, amount_out, amount_in_max, send_to } => { + serai_abi::dex::Call::swap_tokens_for_exact_tokens { + path, + amount_out, + amount_in_max, + send_to: send_to.into(), + } + } + _ => Err(())?, + }), + RuntimeCall::ValidatorSets(call) => Call::ValidatorSets(match call { + validator_sets::Call::set_keys { network, removed_participants, key_pair, signature } => { + serai_abi::validator_sets::Call::set_keys { + network, + removed_participants: <_>::try_from( + removed_participants.into_iter().map(SeraiAddress::from).collect::>(), + ) + .unwrap(), + key_pair, + signature, + } + } + validator_sets::Call::report_slashes { network, slashes, signature } => { + serai_abi::validator_sets::Call::report_slashes { + network, + slashes: <_>::try_from( + slashes + .into_iter() + .map(|(addr, slash)| (SeraiAddress::from(addr), slash)) + .collect::>(), + ) + .unwrap(), + signature, + } + } + validator_sets::Call::allocate { network, amount } => { + serai_abi::validator_sets::Call::allocate { network, amount } + } + validator_sets::Call::deallocate { network, amount } => { + serai_abi::validator_sets::Call::deallocate { network, amount } + } + validator_sets::Call::claim_deallocation { network, session } => { + serai_abi::validator_sets::Call::claim_deallocation { network, session } + } + _ => Err(())?, + }), + RuntimeCall::InInstructions(call) => Call::InInstructions(match call { + in_instructions::Call::execute_batch { batch } => { + serai_abi::in_instructions::Call::execute_batch { batch } + } + _ => Err(())?, + }), + RuntimeCall::Signals(call) => Call::Signals(match call { + signals::Call::register_retirement_signal { in_favor_of } => { + serai_abi::signals::Call::register_retirement_signal { in_favor_of } + } + signals::Call::revoke_retirement_signal { retirement_signal_id } => { + serai_abi::signals::Call::revoke_retirement_signal { retirement_signal_id } + } + signals::Call::favor { signal_id, for_network } => { + serai_abi::signals::Call::favor { signal_id, for_network } + } + signals::Call::revoke_favor { signal_id, for_network } => { + serai_abi::signals::Call::revoke_favor { signal_id, for_network } + } + signals::Call::stand_against { signal_id, for_network } => { + serai_abi::signals::Call::stand_against { signal_id, for_network } + } + _ => Err(())?, + }), + RuntimeCall::Babe(call) => Call::Babe(match call { + babe::Call::report_equivocation { equivocation_proof, key_owner_proof } => { + serai_abi::babe::Call::report_equivocation(serai_abi::babe::ReportEquivocation { + // TODO: Find a better way to go from Proof to Proof<[u8; 32]> + equivocation_proof: <_>::decode(&mut equivocation_proof.encode().as_slice()).unwrap(), + key_owner_proof: key_owner_proof.0.into(), + }) + } + babe::Call::report_equivocation_unsigned { equivocation_proof, key_owner_proof } => { + serai_abi::babe::Call::report_equivocation_unsigned(serai_abi::babe::ReportEquivocation { + // TODO: Find a better way to go from Proof to Proof<[u8; 32]> + equivocation_proof: <_>::decode(&mut equivocation_proof.encode().as_slice()).unwrap(), + key_owner_proof: key_owner_proof.0.into(), + }) + } + _ => Err(())?, + }), + RuntimeCall::Grandpa(call) => Call::Grandpa(match call { + grandpa::Call::report_equivocation { equivocation_proof, key_owner_proof } => { + serai_abi::grandpa::Call::report_equivocation(serai_abi::grandpa::ReportEquivocation { + // TODO: Find a better way to go from Proof to Proof<[u8; 32]> + equivocation_proof: <_>::decode(&mut equivocation_proof.encode().as_slice()).unwrap(), + key_owner_proof: key_owner_proof.0.into(), + }) + } + grandpa::Call::report_equivocation_unsigned { equivocation_proof, key_owner_proof } => { + serai_abi::grandpa::Call::report_equivocation_unsigned( + serai_abi::grandpa::ReportEquivocation { + // TODO: Find a better way to go from Proof to Proof<[u8; 32]> + equivocation_proof: <_>::decode(&mut equivocation_proof.encode().as_slice()).unwrap(), + key_owner_proof: key_owner_proof.0.into(), + }, + ) + } + _ => Err(())?, + }), + _ => Err(())?, + }) + } +} diff --git a/substrate/runtime/src/lib.rs b/substrate/runtime/src/lib.rs index b95593f91..3f034eed2 100644 --- a/substrate/runtime/src/lib.rs +++ b/substrate/runtime/src/lib.rs @@ -65,6 +65,8 @@ use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use babe::AuthorityId as BabeId; use grandpa::AuthorityId as GrandpaId; +mod abi; + /// Nonce of a transaction in the chain, for a given account. pub type Nonce = u32; @@ -82,7 +84,7 @@ pub type SignedExtra = ( transaction_payment::ChargeTransactionPayment, ); -pub type Transaction = serai_primitives::Transaction; +pub type Transaction = serai_abi::tx::Transaction; pub type Block = generic::Block; pub type BlockId = generic::BlockId; @@ -162,38 +164,9 @@ parameter_types! { pub struct CallFilter; impl Contains for CallFilter { fn contains(call: &RuntimeCall) -> bool { - match call { - RuntimeCall::Timestamp(call) => match call { - timestamp::Call::set { .. } => true, - timestamp::Call::__Ignore(_, _) => false, - }, - - // All of these pallets are our own, and all of their written calls are intended to be called - RuntimeCall::Coins(call) => !matches!(call, coins::Call::__Ignore(_, _)), - RuntimeCall::LiquidityTokens(call) => match call { - coins::Call::transfer { .. } | coins::Call::burn { .. } => true, - coins::Call::burn_with_instruction { .. } | coins::Call::__Ignore(_, _) => false, - }, - RuntimeCall::Dex(call) => !matches!(call, dex::Call::__Ignore(_, _)), - RuntimeCall::ValidatorSets(call) => !matches!(call, validator_sets::Call::__Ignore(_, _)), - RuntimeCall::GenesisLiquidity(call) => { - !matches!(call, genesis_liquidity::Call::__Ignore(_, _)) - } - RuntimeCall::InInstructions(call) => !matches!(call, in_instructions::Call::__Ignore(_, _)), - RuntimeCall::Signals(call) => !matches!(call, signals::Call::__Ignore(_, _)), - - RuntimeCall::Babe(call) => match call { - babe::Call::report_equivocation { .. } | - babe::Call::report_equivocation_unsigned { .. } => true, - babe::Call::plan_config_change { .. } | babe::Call::__Ignore(_, _) => false, - }, - - RuntimeCall::Grandpa(call) => match call { - grandpa::Call::report_equivocation { .. } | - grandpa::Call::report_equivocation_unsigned { .. } => true, - grandpa::Call::note_stalled { .. } | grandpa::Call::__Ignore(_, _) => false, - }, - } + // If the call is defined in our ABI, it's allowed + let call: Result = call.clone().try_into(); + call.is_ok() } } diff --git a/substrate/signals/pallet/Cargo.toml b/substrate/signals/pallet/Cargo.toml index 582a3e097..e06b5e6bb 100644 --- a/substrate/signals/pallet/Cargo.toml +++ b/substrate/signals/pallet/Cargo.toml @@ -57,4 +57,7 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", ] +# TODO +try-runtime = [] + default = ["std"] diff --git a/substrate/validator-sets/pallet/Cargo.toml b/substrate/validator-sets/pallet/Cargo.toml index 3b5537884..dd67d1bc3 100644 --- a/substrate/validator-sets/pallet/Cargo.toml +++ b/substrate/validator-sets/pallet/Cargo.toml @@ -70,6 +70,9 @@ std = [ "dex-pallet/std", ] +# TODO +try-runtime = [] + runtime-benchmarks = [ "frame-system/runtime-benchmarks", "frame-support/runtime-benchmarks", diff --git a/substrate/validator-sets/pallet/src/lib.rs b/substrate/validator-sets/pallet/src/lib.rs index c852c4ce2..8a002bab7 100644 --- a/substrate/validator-sets/pallet/src/lib.rs +++ b/substrate/validator-sets/pallet/src/lib.rs @@ -124,7 +124,9 @@ pub mod pallet { #[pallet::getter(fn allocation_per_key_share)] pub type AllocationPerKeyShare = StorageMap<_, Identity, NetworkId, Amount, OptionQuery>; - /// The validators selected to be in-set. + /// The validators selected to be in-set (and their key shares), regardless of if removed. + /// + /// This method allows iterating over all validators and their stake. #[pallet::storage] #[pallet::getter(fn participants_for_latest_decided_set)] pub(crate) type Participants = StorageMap< @@ -134,8 +136,10 @@ pub mod pallet { BoundedVec<(Public, u64), ConstU32<{ MAX_KEY_SHARES_PER_SET }>>, OptionQuery, >; - /// The validators selected to be in-set, regardless of if removed, with the ability to perform a - /// check for presence. + /// The validators selected to be in-set, regardless of if removed. + /// + /// This method allows quickly checking for presence in-set and looking up a validator's key + /// shares. // Uses Identity for NetworkId to avoid a hash of a severely limited fixed key-space. #[pallet::storage] pub(crate) type InSet = @@ -364,7 +368,6 @@ pub mod pallet { let allocation_per_key_share = Self::allocation_per_key_share(network).unwrap().0; let mut participants = vec![]; - let mut total_stake = 0; { let mut iter = SortedAllocationsIter::::new(network); let mut key_shares = 0; @@ -376,7 +379,6 @@ pub mod pallet { participants.push((key, these_key_shares)); key_shares += these_key_shares; - total_stake += amount.0; } amortize_excess_key_shares(&mut participants); } @@ -384,7 +386,6 @@ pub mod pallet { for (key, shares) in &participants { InSet::::set(network, key, Some(*shares)); } - TotalAllocatedStake::::set(network, Some(Amount(total_stake))); let set = ValidatorSet { network, session }; Pallet::::deposit_event(Event::NewSet { set }); @@ -523,11 +524,16 @@ pub mod pallet { Err(Error::::AllocationWouldPreventFaultTolerance)?; } - if InSet::::contains_key(network, account) { - TotalAllocatedStake::::set( - network, - Some(Amount(TotalAllocatedStake::::get(network).unwrap_or(Amount(0)).0 + amount.0)), - ); + // If they're in the current set, and the current set has completed its handover (so its + // currently being tracked by TotalAllocatedStake), update the TotalAllocatedStake + if let Some(session) = Self::session(network) { + if InSet::::contains_key(network, account) && Self::handover_completed(network, session) + { + TotalAllocatedStake::::set( + network, + Some(Amount(TotalAllocatedStake::::get(network).unwrap_or(Amount(0)).0 + amount.0)), + ); + } } Ok(()) @@ -643,8 +649,9 @@ pub mod pallet { // Checks if this session has completed the handover from the prior session. fn handover_completed(network: NetworkId, session: Session) -> bool { let Some(current_session) = Self::session(network) else { return false }; - // No handover occurs on genesis - if current_session.0 == 0 { + + // If the session we've been queried about is old, it must have completed its handover + if current_session.0 > session.0 { return true; } // If the session we've been queried about has yet to start, it can't have completed its @@ -652,19 +659,21 @@ pub mod pallet { if current_session.0 < session.0 { return false; } - if current_session.0 == session.0 { - // Handover is automatically complete for Serai as it doesn't have a handover protocol - // If not Serai, check the prior session had its keys cleared, which happens once its - // retired - return (network == NetworkId::Serai) || - (!Keys::::contains_key(ValidatorSet { - network, - session: Session(current_session.0 - 1), - })); + + // Handover is automatically complete for Serai as it doesn't have a handover protocol + if network == NetworkId::Serai { + return true; } - // We're currently in a future session, meaning this session definitely performed itself - // handover - true + + // The current session must have set keys for its handover to be completed + if !Keys::::contains_key(ValidatorSet { network, session }) { + return false; + } + + // This must be the first session (which has set keys) OR the prior session must have been + // retired (signified by its keys no longer being present) + (session.0 == 0) || + (!Keys::::contains_key(ValidatorSet { network, session: Session(session.0 - 1) })) } fn new_session() { @@ -682,6 +691,8 @@ pub mod pallet { } } + // TODO: This is called retire_set, yet just starts retiring the set + // Update the nomenclature within this function pub fn retire_set(set: ValidatorSet) { // If the prior prior set didn't report, emit they're retired now if PendingSlashReport::::get(set.network).is_some() { @@ -690,7 +701,7 @@ pub mod pallet { }); } - // Serai network slashes are handled by BABE/GRANDPA + // Serai doesn't set keys and network slashes are handled by BABE/GRANDPA if set.network != NetworkId::Serai { // This overwrites the prior value as the prior to-report set's stake presumably just // unlocked, making their report unenforceable @@ -702,6 +713,14 @@ pub mod pallet { Self::deposit_event(Event::AcceptedHandover { set: ValidatorSet { network: set.network, session: Session(set.session.0 + 1) }, }); + + // Update the total allocated stake to be for the current set + let participants = + Participants::::get(set.network).expect("set retired without a new set"); + let total_stake = participants.iter().fold(0, |acc, (addr, _)| { + acc + Allocations::::get((set.network, addr)).unwrap_or(Amount(0)).0 + }); + TotalAllocatedStake::::set(set.network, Some(Amount(total_stake))); } /// Take the amount deallocatable. @@ -873,7 +892,7 @@ pub mod pallet { pub fn set_keys( origin: OriginFor, network: NetworkId, - removed_participants: Vec, + removed_participants: BoundedVec>, key_pair: KeyPair, signature: Signature, ) -> DispatchResult { diff --git a/tests/coordinator/src/lib.rs b/tests/coordinator/src/lib.rs index e6b0324d1..c364128ca 100644 --- a/tests/coordinator/src/lib.rs +++ b/tests/coordinator/src/lib.rs @@ -60,12 +60,18 @@ pub fn coordinator_instance( ) } -pub fn serai_composition(name: &str) -> TestBodySpecification { - serai_docker_tests::build("serai".to_string()); - - TestBodySpecification::with_image( - Image::with_repository("serai-dev-serai").pull_policy(PullPolicy::Never), - ) +pub fn serai_composition(name: &str, fast_epoch: bool) -> TestBodySpecification { + (if fast_epoch { + serai_docker_tests::build("serai-fast-epoch".to_string()); + TestBodySpecification::with_image( + Image::with_repository("serai-dev-serai-fast-epoch").pull_policy(PullPolicy::Never), + ) + } else { + serai_docker_tests::build("serai".to_string()); + TestBodySpecification::with_image( + Image::with_repository("serai-dev-serai").pull_policy(PullPolicy::Never), + ) + }) .replace_env( [("SERAI_NAME".to_string(), name.to_lowercase()), ("KEY".to_string(), " ".to_string())].into(), ) diff --git a/tests/coordinator/src/tests/batch.rs b/tests/coordinator/src/tests/batch.rs index ebba957b9..bfe4e36eb 100644 --- a/tests/coordinator/src/tests/batch.rs +++ b/tests/coordinator/src/tests/batch.rs @@ -260,21 +260,29 @@ pub async fn batch( #[tokio::test] async fn batch_test() { - new_test(|mut processors: Vec| async move { - let (processor_is, substrate_key, _) = key_gen::(&mut processors).await; - batch( - &mut processors, - &processor_is, - Session(0), - &substrate_key, - Batch { - network: NetworkId::Bitcoin, - id: 0, - block: BlockHash([0x22; 32]), - instructions: vec![], - }, - ) - .await; - }) + new_test( + |mut processors: Vec| async move { + // pop the last participant since genesis keygen has only 4 participants + processors.pop().unwrap(); + assert_eq!(processors.len(), COORDINATORS); + + let (processor_is, substrate_key, _) = + key_gen::(&mut processors, Session(0)).await; + batch( + &mut processors, + &processor_is, + Session(0), + &substrate_key, + Batch { + network: NetworkId::Bitcoin, + id: 0, + block: BlockHash([0x22; 32]), + instructions: vec![], + }, + ) + .await; + }, + false, + ) .await; } diff --git a/tests/coordinator/src/tests/key_gen.rs b/tests/coordinator/src/tests/key_gen.rs index 8250b3bf3..8ea14cbc0 100644 --- a/tests/coordinator/src/tests/key_gen.rs +++ b/tests/coordinator/src/tests/key_gen.rs @@ -23,10 +23,12 @@ use crate::tests::*; pub async fn key_gen( processors: &mut [Processor], + session: Session, ) -> (Vec, Zeroizing<::F>, Zeroizing) { + let coordinators = processors.len(); let mut participant_is = vec![]; - let set = ValidatorSet { session: Session(0), network: NetworkId::Bitcoin }; + let set = ValidatorSet { session, network: NetworkId::Bitcoin }; let id = KeyGenId { session: set.session, attempt: 0 }; for (i, processor) in processors.iter_mut().enumerate() { @@ -46,8 +48,8 @@ pub async fn key_gen( CoordinatorMessage::KeyGen(messages::key_gen::CoordinatorMessage::GenerateKey { id, params: ThresholdParams::new( - u16::try_from(((COORDINATORS * 2) / 3) + 1).unwrap(), - u16::try_from(COORDINATORS).unwrap(), + u16::try_from(((coordinators * 2) / 3) + 1).unwrap(), + u16::try_from(coordinators).unwrap(), participant_is[i], ) .unwrap(), @@ -65,7 +67,7 @@ pub async fn key_gen( wait_for_tributary().await; for (i, processor) in processors.iter_mut().enumerate() { - let mut commitments = (0 .. u8::try_from(COORDINATORS).unwrap()) + let mut commitments = (0 .. u8::try_from(coordinators).unwrap()) .map(|l| { ( participant_is[usize::from(l)], @@ -83,7 +85,7 @@ pub async fn key_gen( ); // Recipient it's for -> (Sender i, Recipient i) - let mut shares = (0 .. u8::try_from(COORDINATORS).unwrap()) + let mut shares = (0 .. u8::try_from(coordinators).unwrap()) .map(|l| { ( participant_is[usize::from(l)], @@ -118,7 +120,7 @@ pub async fn key_gen( CoordinatorMessage::KeyGen(messages::key_gen::CoordinatorMessage::Shares { id, shares: { - let mut shares = (0 .. u8::try_from(COORDINATORS).unwrap()) + let mut shares = (0 .. u8::try_from(coordinators).unwrap()) .map(|l| { ( participant_is[usize::from(l)], @@ -182,14 +184,14 @@ pub async fn key_gen( .unwrap() .as_secs() .abs_diff(context.serai_time) < - 70 + (60 * 60 * 3) // 3 hours, which should exceed the length of any test we run ); assert_eq!(context.network_latest_finalized_block.0, [0; 32]); assert_eq!(set.session, session); assert_eq!(key_pair.0 .0, substrate_key); assert_eq!(&key_pair.1, &network_key); } - _ => panic!("coordinator didn't respond with ConfirmKeyPair"), + _ => panic!("coordinator didn't respond with ConfirmKeyPair. msg: {msg:?}"), } message = Some(msg); } else { @@ -220,8 +222,15 @@ pub async fn key_gen( #[tokio::test] async fn key_gen_test() { - new_test(|mut processors: Vec| async move { - key_gen::(&mut processors).await; - }) + new_test( + |mut processors: Vec| async move { + // pop the last participant since genesis keygen has only 4 participants + processors.pop().unwrap(); + assert_eq!(processors.len(), COORDINATORS); + + key_gen::(&mut processors, Session(0)).await; + }, + false, + ) .await; } diff --git a/tests/coordinator/src/tests/mod.rs b/tests/coordinator/src/tests/mod.rs index b564a26bf..ef67b0ac5 100644 --- a/tests/coordinator/src/tests/mod.rs +++ b/tests/coordinator/src/tests/mod.rs @@ -22,6 +22,8 @@ mod sign; #[allow(unused_imports)] pub use sign::sign; +mod rotation; + pub(crate) const COORDINATORS: usize = 4; pub(crate) const THRESHOLD: usize = ((COORDINATORS * 2) / 3) + 1; @@ -39,13 +41,15 @@ impl) -> F> Test } } -pub(crate) async fn new_test(test_body: impl TestBody) { +pub(crate) async fn new_test(test_body: impl TestBody, fast_epoch: bool) { let mut unique_id_lock = UNIQUE_ID.get_or_init(|| Mutex::new(0)).lock().await; let mut coordinators = vec![]; let mut test = DockerTest::new().with_network(dockertest::Network::Isolated); let mut coordinator_compositions = vec![]; - for i in 0 .. COORDINATORS { + // Spawn one extra coordinator which isn't in-set + #[allow(clippy::range_plus_one)] + for i in 0 .. (COORDINATORS + 1) { let name = match i { 0 => "Alice", 1 => "Bob", @@ -55,7 +59,7 @@ pub(crate) async fn new_test(test_body: impl TestBody) { 5 => "Ferdie", _ => panic!("needed a 7th name for a serai node"), }; - let serai_composition = serai_composition(name); + let serai_composition = serai_composition(name, fast_epoch); let (processor_key, message_queue_keys, message_queue_composition) = serai_message_queue_tests::instance(); diff --git a/tests/coordinator/src/tests/rotation.rs b/tests/coordinator/src/tests/rotation.rs new file mode 100644 index 000000000..1ebeec16a --- /dev/null +++ b/tests/coordinator/src/tests/rotation.rs @@ -0,0 +1,169 @@ +use tokio::time::{sleep, Duration}; + +use ciphersuite::Secp256k1; + +use serai_client::{ + primitives::{insecure_pair_from_name, NetworkId}, + validator_sets::{ + self, + primitives::{Session, ValidatorSet}, + ValidatorSetsEvent, + }, + Amount, Pair, Transaction, +}; + +use crate::{*, tests::*}; + +// TODO: This is duplicated with serai-client's tests +async fn publish_tx(serai: &Serai, tx: &Transaction) -> [u8; 32] { + let mut latest = serai + .block(serai.latest_finalized_block_hash().await.unwrap()) + .await + .unwrap() + .unwrap() + .number(); + + serai.publish(tx).await.unwrap(); + + // Get the block it was included in + // TODO: Add an RPC method for this/check the guarantee on the subscription + let mut ticks = 0; + loop { + latest += 1; + + let block = { + let mut block; + while { + block = serai.finalized_block_by_number(latest).await.unwrap(); + block.is_none() + } { + sleep(Duration::from_secs(1)).await; + ticks += 1; + + if ticks > 60 { + panic!("60 seconds without inclusion in a finalized block"); + } + } + block.unwrap() + }; + + for transaction in &block.transactions { + if transaction == tx { + return block.hash(); + } + } + } +} + +#[allow(dead_code)] +async fn allocate_stake( + serai: &Serai, + network: NetworkId, + amount: Amount, + pair: &Pair, + nonce: u32, +) -> [u8; 32] { + // get the call + let tx = + serai.sign(pair, validator_sets::SeraiValidatorSets::allocate(network, amount), nonce, 0); + publish_tx(serai, &tx).await +} + +#[allow(dead_code)] +async fn deallocate_stake( + serai: &Serai, + network: NetworkId, + amount: Amount, + pair: &Pair, + nonce: u32, +) -> [u8; 32] { + // get the call + let tx = + serai.sign(pair, validator_sets::SeraiValidatorSets::deallocate(network, amount), nonce, 0); + publish_tx(serai, &tx).await +} + +async fn get_session(serai: &Serai, network: NetworkId) -> Session { + serai + .as_of_latest_finalized_block() + .await + .unwrap() + .validator_sets() + .session(network) + .await + .unwrap() + .unwrap() +} + +async fn wait_till_session_1(serai: &Serai, network: NetworkId) { + let mut current_session = get_session(serai, network).await; + + while current_session.0 < 1 { + sleep(Duration::from_secs(6)).await; + current_session = get_session(serai, network).await; + } +} + +async fn most_recent_new_set_event(serai: &Serai, network: NetworkId) -> ValidatorSetsEvent { + let mut current_block = serai.latest_finalized_block().await.unwrap(); + loop { + let events = serai.as_of(current_block.hash()).validator_sets().new_set_events().await.unwrap(); + for event in events { + match event { + ValidatorSetsEvent::NewSet { set } => { + if set.network == network { + return event; + } + } + _ => panic!("new_set_events gave non-NewSet event: {event:?}"), + } + } + current_block = serai.block(current_block.header.parent_hash.0).await.unwrap().unwrap(); + } +} + +#[tokio::test] +async fn set_rotation_test() { + new_test( + |mut processors: Vec| async move { + // exclude the last processor from keygen since we will add him later + let mut excluded = processors.pop().unwrap(); + assert_eq!(processors.len(), COORDINATORS); + + // excluded participant + let pair5 = insecure_pair_from_name("Eve"); + let network = NetworkId::Bitcoin; + let amount = Amount(1_000_000 * 10_u64.pow(8)); + let serai = processors[0].serai().await; + + // allocate now for the last participant so that it is guaranteed to be included into session + // 1 set. This doesn't affect the genesis set at all since that is a predetermined set. + allocate_stake(&serai, network, amount, &pair5, 0).await; + + // genesis keygen + let _ = key_gen::(&mut processors, Session(0)).await; + // Even the excluded processor should receive the key pair confirmation + match excluded.recv_message().await { + CoordinatorMessage::Substrate( + messages::substrate::CoordinatorMessage::ConfirmKeyPair { session, .. }, + ) => assert_eq!(session, Session(0)), + _ => panic!("excluded got message other than ConfirmKeyPair"), + } + + // wait until next session to see the effect on coordinator + wait_till_session_1(&serai, network).await; + + // Ensure the new validator was included in the new set + assert_eq!( + most_recent_new_set_event(&serai, network).await, + ValidatorSetsEvent::NewSet { set: ValidatorSet { session: Session(1), network } }, + ); + + // add the last participant & do the keygen + processors.push(excluded); + let _ = key_gen::(&mut processors, Session(1)).await; + }, + true, + ) + .await; +} diff --git a/tests/coordinator/src/tests/sign.rs b/tests/coordinator/src/tests/sign.rs index e46e8890b..db8a72034 100644 --- a/tests/coordinator/src/tests/sign.rs +++ b/tests/coordinator/src/tests/sign.rs @@ -168,161 +168,172 @@ pub async fn sign( #[tokio::test] async fn sign_test() { - new_test(|mut processors: Vec| async move { - let (participant_is, substrate_key, _) = key_gen::(&mut processors).await; - - // 'Send' external coins into Serai - let serai = processors[0].serai().await; - let (serai_pair, serai_addr) = { - let mut name = [0; 4]; - OsRng.fill_bytes(&mut name); - let pair = insecure_pair_from_name(&hex::encode(name)); - let address = SeraiAddress::from(pair.public()); - - // Fund the new account to pay for fees - let balance = Balance { coin: Coin::Serai, amount: Amount(1_000_000_000) }; + new_test( + |mut processors: Vec| async move { + // pop the last participant since genesis keygen has only 4 participant. + processors.pop().unwrap(); + assert_eq!(processors.len(), COORDINATORS); + + let (participant_is, substrate_key, _) = + key_gen::(&mut processors, Session(0)).await; + + // 'Send' external coins into Serai + let serai = processors[0].serai().await; + let (serai_pair, serai_addr) = { + let mut name = [0; 4]; + OsRng.fill_bytes(&mut name); + let pair = insecure_pair_from_name(&hex::encode(name)); + let address = SeraiAddress::from(pair.public()); + + // Fund the new account to pay for fees + let balance = Balance { coin: Coin::Serai, amount: Amount(1_000_000_000) }; + serai + .publish(&serai.sign( + &insecure_pair_from_name("Ferdie"), + SeraiCoins::transfer(address, balance), + 0, + Default::default(), + )) + .await + .unwrap(); + + (pair, address) + }; + + #[allow(clippy::inconsistent_digit_grouping)] + let amount = Amount(1_000_000_00); + let balance = Balance { coin: Coin::Bitcoin, amount }; + + let coin_block = BlockHash([0x33; 32]); + let block_included_in = batch( + &mut processors, + &participant_is, + Session(0), + &substrate_key, + Batch { + network: NetworkId::Bitcoin, + id: 0, + block: coin_block, + instructions: vec![InInstructionWithBalance { + instruction: InInstruction::Transfer(serai_addr), + balance, + }], + }, + ) + .await; + + { + let block_included_in_hash = + serai.finalized_block_by_number(block_included_in).await.unwrap().unwrap().hash(); + + let serai = serai.as_of(block_included_in_hash); + let serai = serai.coins(); + assert_eq!( + serai.coin_balance(Coin::Serai, serai_addr).await.unwrap(), + Amount(1_000_000_000) + ); + + // Verify the mint occurred as expected + assert_eq!( + serai.mint_events().await.unwrap(), + vec![CoinsEvent::Mint { to: serai_addr, balance }] + ); + assert_eq!(serai.coin_supply(Coin::Bitcoin).await.unwrap(), amount); + assert_eq!(serai.coin_balance(Coin::Bitcoin, serai_addr).await.unwrap(), amount); + } + + // Trigger a burn + let out_instruction = OutInstructionWithBalance { + balance, + instruction: OutInstruction { + address: ExternalAddress::new(b"external".to_vec()).unwrap(), + data: None, + }, + }; serai .publish(&serai.sign( - &insecure_pair_from_name("Ferdie"), - SeraiCoins::transfer(address, balance), + &serai_pair, + SeraiCoins::burn_with_instruction(out_instruction.clone()), 0, Default::default(), )) .await .unwrap(); - (pair, address) - }; - - #[allow(clippy::inconsistent_digit_grouping)] - let amount = Amount(1_000_000_00); - let balance = Balance { coin: Coin::Bitcoin, amount }; - - let coin_block = BlockHash([0x33; 32]); - let block_included_in = batch( - &mut processors, - &participant_is, - Session(0), - &substrate_key, - Batch { - network: NetworkId::Bitcoin, - id: 0, - block: coin_block, - instructions: vec![InInstructionWithBalance { - instruction: InInstruction::Transfer(serai_addr), - balance, - }], - }, - ) - .await; - - { - let block_included_in_hash = - serai.finalized_block_by_number(block_included_in).await.unwrap().unwrap().hash(); - - let serai = serai.as_of(block_included_in_hash); - let serai = serai.coins(); - assert_eq!(serai.coin_balance(Coin::Serai, serai_addr).await.unwrap(), Amount(1_000_000_000)); - - // Verify the mint occurred as expected - assert_eq!( - serai.mint_events().await.unwrap(), - vec![CoinsEvent::Mint { to: serai_addr, balance }] - ); - assert_eq!(serai.coin_supply(Coin::Bitcoin).await.unwrap(), amount); - assert_eq!(serai.coin_balance(Coin::Bitcoin, serai_addr).await.unwrap(), amount); - } - - // Trigger a burn - let out_instruction = OutInstructionWithBalance { - balance, - instruction: OutInstruction { - address: ExternalAddress::new(b"external".to_vec()).unwrap(), - data: None, - }, - }; - serai - .publish(&serai.sign( - &serai_pair, - SeraiCoins::burn_with_instruction(out_instruction.clone()), - 0, - Default::default(), - )) - .await - .unwrap(); - - // TODO: We *really* need a helper for this pattern - let mut last_serai_block = block_included_in; - 'outer: for _ in 0 .. 20 { - tokio::time::sleep(Duration::from_secs(6)).await; - if std::env::var("GITHUB_CI") == Ok("true".to_string()) { + // TODO: We *really* need a helper for this pattern + let mut last_serai_block = block_included_in; + 'outer: for _ in 0 .. 20 { tokio::time::sleep(Duration::from_secs(6)).await; - } - - while last_serai_block <= serai.latest_finalized_block().await.unwrap().number() { - let burn_events = serai - .as_of(serai.finalized_block_by_number(last_serai_block).await.unwrap().unwrap().hash()) - .coins() - .burn_with_instruction_events() - .await - .unwrap(); + if std::env::var("GITHUB_CI") == Ok("true".to_string()) { + tokio::time::sleep(Duration::from_secs(6)).await; + } - if !burn_events.is_empty() { - assert_eq!(burn_events.len(), 1); - assert_eq!( - burn_events[0], - CoinsEvent::BurnWithInstruction { - from: serai_addr, - instruction: out_instruction.clone() - } - ); - break 'outer; + while last_serai_block <= serai.latest_finalized_block().await.unwrap().number() { + let burn_events = serai + .as_of(serai.finalized_block_by_number(last_serai_block).await.unwrap().unwrap().hash()) + .coins() + .burn_with_instruction_events() + .await + .unwrap(); + + if !burn_events.is_empty() { + assert_eq!(burn_events.len(), 1); + assert_eq!( + burn_events[0], + CoinsEvent::BurnWithInstruction { + from: serai_addr, + instruction: out_instruction.clone() + } + ); + break 'outer; + } + last_serai_block += 1; } - last_serai_block += 1; } - } - let last_serai_block = - serai.finalized_block_by_number(last_serai_block).await.unwrap().unwrap(); - let last_serai_block_hash = last_serai_block.hash(); - let serai = serai.as_of(last_serai_block_hash); - let serai = serai.coins(); - assert_eq!(serai.coin_supply(Coin::Bitcoin).await.unwrap(), Amount(0)); - assert_eq!(serai.coin_balance(Coin::Bitcoin, serai_addr).await.unwrap(), Amount(0)); - - let mut plan_id = [0; 32]; - OsRng.fill_bytes(&mut plan_id); - let plan_id = plan_id; - - // We should now get a SubstrateBlock - for processor in &mut processors { - assert_eq!( - processor.recv_message().await, - messages::CoordinatorMessage::Substrate( - messages::substrate::CoordinatorMessage::SubstrateBlock { - context: SubstrateContext { - serai_time: last_serai_block.time().unwrap() / 1000, - network_latest_finalized_block: coin_block, + let last_serai_block = + serai.finalized_block_by_number(last_serai_block).await.unwrap().unwrap(); + let last_serai_block_hash = last_serai_block.hash(); + let serai = serai.as_of(last_serai_block_hash); + let serai = serai.coins(); + assert_eq!(serai.coin_supply(Coin::Bitcoin).await.unwrap(), Amount(0)); + assert_eq!(serai.coin_balance(Coin::Bitcoin, serai_addr).await.unwrap(), Amount(0)); + + let mut plan_id = [0; 32]; + OsRng.fill_bytes(&mut plan_id); + let plan_id = plan_id; + + // We should now get a SubstrateBlock + for processor in &mut processors { + assert_eq!( + processor.recv_message().await, + messages::CoordinatorMessage::Substrate( + messages::substrate::CoordinatorMessage::SubstrateBlock { + context: SubstrateContext { + serai_time: last_serai_block.time().unwrap() / 1000, + network_latest_finalized_block: coin_block, + }, + block: last_serai_block.number(), + burns: vec![out_instruction.clone()], + batches: vec![], + } + ) + ); + + // Send the ACK, claiming there's a plan to sign + processor + .send_message(messages::ProcessorMessage::Coordinator( + messages::coordinator::ProcessorMessage::SubstrateBlockAck { + block: last_serai_block.number(), + plans: vec![PlanMeta { session: Session(0), id: plan_id }], }, - block: last_serai_block.number(), - burns: vec![out_instruction.clone()], - batches: vec![], - } - ) - ); - - // Send the ACK, claiming there's a plan to sign - processor - .send_message(messages::ProcessorMessage::Coordinator( - messages::coordinator::ProcessorMessage::SubstrateBlockAck { - block: last_serai_block.number(), - plans: vec![PlanMeta { session: Session(0), id: plan_id }], - }, - )) - .await; - } + )) + .await; + } - sign(&mut processors, &participant_is, Session(0), plan_id).await; - }) + sign(&mut processors, &participant_is, Session(0), plan_id).await; + }, + false, + ) .await; } diff --git a/tests/docker/src/lib.rs b/tests/docker/src/lib.rs index 3493d5029..986a1793c 100644 --- a/tests/docker/src/lib.rs +++ b/tests/docker/src/lib.rs @@ -85,7 +85,7 @@ pub fn build(name: String) { } let mut dockerfile_path = orchestration_path.clone(); - if HashSet::from(["bitcoin", "ethereum", "monero"]).contains(name.as_str()) { + if HashSet::from(["bitcoin", "ethereum", "ethereum-relayer", "monero"]).contains(name.as_str()) { dockerfile_path = dockerfile_path.join("coins"); } if name.contains("-processor") { @@ -125,6 +125,7 @@ pub fn build(name: String) { let meta = |path: PathBuf| (path.clone(), fs::metadata(path)); let mut metadatas = match name.as_str() { "bitcoin" | "ethereum" | "monero" => vec![], + "ethereum-relayer" => vec![meta(repo_path.join("common")), meta(repo_path.join("coins"))], "message-queue" => vec![ meta(repo_path.join("common")), meta(repo_path.join("crypto")), diff --git a/tests/full-stack/src/tests/mint_and_burn.rs b/tests/full-stack/src/tests/mint_and_burn.rs index 51b8156cf..4093e47dd 100644 --- a/tests/full-stack/src/tests/mint_and_burn.rs +++ b/tests/full-stack/src/tests/mint_and_burn.rs @@ -57,7 +57,7 @@ async fn mint_and_burn_test() { }; let addr = Address::p2pkh( - &PublicKey::from_private_key( + PublicKey::from_private_key( SECP256K1, &PrivateKey::new(SecretKey::from_slice(&[0x01; 32]).unwrap(), Network::Bitcoin), ), @@ -266,14 +266,13 @@ async fn mint_and_burn_test() { script::{PushBytesBuf, Script, ScriptBuf, Builder}, absolute::LockTime, transaction::{Version, Transaction}, - address::Payload, - Sequence, Witness, OutPoint, TxIn, Amount, TxOut, Network, + Sequence, Witness, OutPoint, TxIn, Amount, TxOut, Network, Address, }; let private_key = PrivateKey::new(SecretKey::from_slice(&[0x01; 32]).unwrap(), Network::Bitcoin); let public_key = PublicKey::from_private_key(SECP256K1, &private_key); - let addr = Payload::p2pkh(&public_key); + let addr = Address::p2pkh(public_key, Network::Bitcoin); // Use the first block's coinbase let rpc = handles[0].bitcoin(&ops).await; @@ -284,7 +283,7 @@ async fn mint_and_burn_test() { version: Version(2), lock_time: LockTime::ZERO, input: vec![TxIn { - previous_output: OutPoint { txid: tx.txid(), vout: 0 }, + previous_output: OutPoint { txid: tx.compute_txid(), vout: 0 }, script_sig: Script::new().into(), sequence: Sequence(u32::MAX), witness: Witness::default(), @@ -292,17 +291,23 @@ async fn mint_and_burn_test() { output: vec![ TxOut { value: Amount::from_sat(1_100_000_00), - script_pubkey: Payload::p2tr_tweaked(TweakedPublicKey::dangerous_assume_tweaked( - XOnlyPublicKey::from_slice(&bitcoin_key_pair.1[1 ..]).unwrap(), - )) + script_pubkey: Address::p2tr_tweaked( + TweakedPublicKey::dangerous_assume_tweaked( + XOnlyPublicKey::from_slice(&bitcoin_key_pair.1[1 ..]).unwrap(), + ), + Network::Bitcoin, + ) .script_pubkey(), }, TxOut { // change = amount spent - fee value: Amount::from_sat(tx.output[0].value.to_sat() - 1_100_000_00 - 1_000_00), - script_pubkey: Payload::p2tr_tweaked(TweakedPublicKey::dangerous_assume_tweaked( - XOnlyPublicKey::from_slice(&public_key.inner.serialize()[1 ..]).unwrap(), - )) + script_pubkey: Address::p2tr_tweaked( + TweakedPublicKey::dangerous_assume_tweaked( + XOnlyPublicKey::from_slice(&public_key.inner.serialize()[1 ..]).unwrap(), + ), + Network::Bitcoin, + ) .script_pubkey(), }, TxOut { @@ -316,12 +321,14 @@ async fn mint_and_burn_test() { let mut der = SECP256K1 .sign_ecdsa_low_r( - &Message::from( + &Message::from_digest_slice( SighashCache::new(&tx) .legacy_signature_hash(0, &addr.script_pubkey(), EcdsaSighashType::All.to_u32()) .unwrap() - .to_raw_hash(), - ), + .to_raw_hash() + .as_ref(), + ) + .unwrap(), &private_key.inner, ) .serialize_der() @@ -447,19 +454,17 @@ async fn mint_and_burn_test() { // Create a random Bitcoin/Monero address let bitcoin_addr = { - use bitcoin_serai::bitcoin::{network::Network, key::PublicKey, address::Address}; - // Uses Network::Bitcoin since it doesn't actually matter, Serai strips it out - // TODO: Move Serai to Payload from Address - Address::p2pkh( - &loop { + use bitcoin_serai::bitcoin::{key::PublicKey, ScriptBuf}; + ScriptBuf::new_p2pkh( + &(loop { let mut bytes = [0; 33]; OsRng.fill_bytes(&mut bytes); bytes[0] %= 4; if let Ok(key) = PublicKey::from_slice(&bytes) { break key; } - }, - Network::Bitcoin, + }) + .pubkey_hash(), ) }; @@ -552,7 +557,7 @@ async fn mint_and_burn_test() { let received_output = block.txdata[1] .output .iter() - .find(|output| output.script_pubkey == bitcoin_addr.script_pubkey()) + .find(|output| output.script_pubkey == bitcoin_addr) .unwrap(); let tx_fee = 1_100_000_00 - diff --git a/tests/full-stack/src/tests/mod.rs b/tests/full-stack/src/tests/mod.rs index 1fae8c481..7d92070ef 100644 --- a/tests/full-stack/src/tests/mod.rs +++ b/tests/full-stack/src/tests/mod.rs @@ -57,15 +57,19 @@ pub(crate) async fn new_test(test_body: impl TestBody) { let (coord_key, message_queue_keys, message_queue_composition) = message_queue_instance(); let (bitcoin_composition, bitcoin_port) = network_instance(NetworkId::Bitcoin); - let bitcoin_processor_composition = + let mut bitcoin_processor_composition = processor_instance(NetworkId::Bitcoin, bitcoin_port, message_queue_keys[&NetworkId::Bitcoin]); + assert_eq!(bitcoin_processor_composition.len(), 1); + let bitcoin_processor_composition = bitcoin_processor_composition.swap_remove(0); let (monero_composition, monero_port) = network_instance(NetworkId::Monero); - let monero_processor_composition = + let mut monero_processor_composition = processor_instance(NetworkId::Monero, monero_port, message_queue_keys[&NetworkId::Monero]); + assert_eq!(monero_processor_composition.len(), 1); + let monero_processor_composition = monero_processor_composition.swap_remove(0); let coordinator_composition = coordinator_instance(name, coord_key); - let serai_composition = serai_composition(name); + let serai_composition = serai_composition(name, false); // Give every item in this stack a unique ID // Uses a Mutex as we can't generate a 8-byte random ID without hitting hostname length limits diff --git a/tests/processor/Cargo.toml b/tests/processor/Cargo.toml index be27e7de9..e46312c59 100644 --- a/tests/processor/Cargo.toml +++ b/tests/processor/Cargo.toml @@ -23,11 +23,14 @@ zeroize = { version = "1", default-features = false } rand_core = { version = "0.6", default-features = false, features = ["getrandom"] } curve25519-dalek = "4" -ciphersuite = { path = "../../crypto/ciphersuite", default-features = false, features = ["ristretto"] } +ciphersuite = { path = "../../crypto/ciphersuite", default-features = false, features = ["secp256k1", "ristretto"] } dkg = { path = "../../crypto/dkg", default-features = false, features = ["tests"] } bitcoin-serai = { path = "../../coins/bitcoin" } + +k256 = "0.13" ethereum-serai = { path = "../../coins/ethereum" } + monero-serai = { path = "../../coins/monero" } messages = { package = "serai-processor-messages", path = "../../processor/messages" } @@ -43,7 +46,7 @@ serde_json = { version = "1", default-features = false } tokio = { version = "1", features = ["time"] } -processor = { package = "serai-processor", path = "../../processor", features = ["bitcoin", "monero"] } +processor = { package = "serai-processor", path = "../../processor", features = ["bitcoin", "ethereum", "monero"] } dockertest = "0.4" serai-docker-tests = { path = "../docker" } diff --git a/tests/processor/src/lib.rs b/tests/processor/src/lib.rs index 5e854272c..8aa6d48d2 100644 --- a/tests/processor/src/lib.rs +++ b/tests/processor/src/lib.rs @@ -28,7 +28,7 @@ pub fn processor_instance( network: NetworkId, port: u32, message_queue_key: ::F, -) -> TestBodySpecification { +) -> Vec { let mut entropy = [0; 32]; OsRng.fill_bytes(&mut entropy); @@ -41,7 +41,7 @@ pub fn processor_instance( let image = format!("{network_str}-processor"); serai_docker_tests::build(image.clone()); - TestBodySpecification::with_image( + let mut res = vec![TestBodySpecification::with_image( Image::with_repository(format!("serai-dev-{image}")).pull_policy(PullPolicy::Never), ) .replace_env( @@ -55,19 +55,40 @@ pub fn processor_instance( ("RUST_LOG".to_string(), "serai_processor=trace,".to_string()), ] .into(), - ) + )]; + + if network == NetworkId::Ethereum { + serai_docker_tests::build("ethereum-relayer".to_string()); + res.push( + TestBodySpecification::with_image( + Image::with_repository("serai-dev-ethereum-relayer".to_string()) + .pull_policy(PullPolicy::Never), + ) + .replace_env( + [ + ("DB_PATH".to_string(), "./ethereum-relayer-db".to_string()), + ("RUST_LOG".to_string(), "serai_ethereum_relayer=trace,".to_string()), + ] + .into(), + ) + .set_publish_all_ports(true), + ); + } + + res } -pub type Handles = (String, String, String); +pub type Handles = (String, String, String, String); pub fn processor_stack( network: NetworkId, + network_hostname_override: Option, ) -> (Handles, ::F, Vec) { let (network_composition, network_rpc_port) = network_instance(network); let (coord_key, message_queue_keys, message_queue_composition) = serai_message_queue_tests::instance(); - let processor_composition = + let mut processor_compositions = processor_instance(network, network_rpc_port, message_queue_keys[&network]); // Give every item in this stack a unique ID @@ -83,7 +104,7 @@ pub fn processor_stack( let mut compositions = vec![]; let mut handles = vec![]; for (name, composition) in [ - ( + Some(( match network { NetworkId::Serai => unreachable!(), NetworkId::Bitcoin => "bitcoin", @@ -91,10 +112,14 @@ pub fn processor_stack( NetworkId::Monero => "monero", }, network_composition, - ), - ("message_queue", message_queue_composition), - ("processor", processor_composition), - ] { + )), + Some(("message_queue", message_queue_composition)), + Some(("processor", processor_compositions.remove(0))), + processor_compositions.pop().map(|composition| ("relayer", composition)), + ] + .into_iter() + .flatten() + { let handle = format!("processor-{name}-{unique_id}"); compositions.push( composition.set_start_policy(StartPolicy::Strict).set_handle(handle.clone()).set_log_options( @@ -112,11 +137,27 @@ pub fn processor_stack( handles.push(handle); } - let processor_composition = compositions.last_mut().unwrap(); - processor_composition.inject_container_name(handles[0].clone(), "NETWORK_RPC_HOSTNAME"); + let processor_composition = compositions.get_mut(2).unwrap(); + processor_composition.inject_container_name( + network_hostname_override.unwrap_or_else(|| handles[0].clone()), + "NETWORK_RPC_HOSTNAME", + ); + if let Some(hostname) = handles.get(3) { + processor_composition.inject_container_name(hostname, "ETHEREUM_RELAYER_HOSTNAME"); + processor_composition.modify_env("ETHEREUM_RELAYER_PORT", "20830"); + } processor_composition.inject_container_name(handles[1].clone(), "MESSAGE_QUEUE_RPC"); - ((handles[0].clone(), handles[1].clone(), handles[2].clone()), coord_key, compositions) + ( + ( + handles[0].clone(), + handles[1].clone(), + handles[2].clone(), + handles.get(3).cloned().unwrap_or(String::new()), + ), + coord_key, + compositions, + ) } #[derive(serde::Deserialize, Debug)] @@ -130,6 +171,7 @@ pub struct Coordinator { message_queue_handle: String, #[allow(unused)] processor_handle: String, + relayer_handle: String, next_send_id: u64, next_recv_id: u64, @@ -140,7 +182,7 @@ impl Coordinator { pub fn new( network: NetworkId, ops: &DockerOperations, - handles: (String, String, String), + handles: Handles, coord_key: ::F, ) -> Coordinator { let rpc = ops.handle(&handles.1).host_port(2287).unwrap(); @@ -152,6 +194,7 @@ impl Coordinator { network_handle: handles.0, message_queue_handle: handles.1, processor_handle: handles.2, + relayer_handle: handles.3, next_send_id: 0, next_recv_id: 0, @@ -182,25 +225,52 @@ impl Coordinator { } } NetworkId::Ethereum => { - use ethereum_serai::alloy::{ - simple_request_transport::SimpleRequest, - rpc_client::ClientBuilder, - provider::{Provider, RootProvider}, - network::Ethereum, + use std::sync::Arc; + use ethereum_serai::{ + alloy::{ + simple_request_transport::SimpleRequest, + rpc_client::ClientBuilder, + provider::{Provider, RootProvider}, + network::Ethereum, + }, + deployer::Deployer, }; - let provider = RootProvider::<_, Ethereum>::new( + let provider = Arc::new(RootProvider::<_, Ethereum>::new( ClientBuilder::default().transport(SimpleRequest::new(rpc_url.clone()), true), - ); - - loop { - if handle - .block_on(provider.raw_request::<_, ()>("evm_setAutomine".into(), [false])) - .is_ok() - { - break; - } - handle.block_on(tokio::time::sleep(core::time::Duration::from_secs(1))); + )); + + if handle + .block_on(provider.raw_request::<_, ()>("evm_setAutomine".into(), [false])) + .is_ok() + { + handle.block_on(async { + // Deploy the deployer + let tx = Deployer::deployment_tx(); + let signer = tx.recover_signer().unwrap(); + let (tx, sig, _) = tx.into_parts(); + + provider + .raw_request::<_, ()>( + "anvil_setBalance".into(), + [signer.to_string(), (tx.gas_limit * tx.gas_price).to_string()], + ) + .await + .unwrap(); + + let mut bytes = vec![]; + tx.encode_with_signature_fields(&sig, &mut bytes); + let _ = provider.send_raw_transaction(&bytes).await.unwrap(); + + provider.raw_request::<_, ()>("anvil_mine".into(), [96]).await.unwrap(); + + let _ = Deployer::new(provider.clone()).await.unwrap().unwrap(); + + // Sleep until the actual time is ahead of whatever time is in the epoch we just + // mined + tokio::time::sleep(core::time::Duration::from_secs(30)).await; + }); + break; } } NetworkId::Monero => { @@ -295,7 +365,7 @@ impl Coordinator { NetworkId::Ethereum => { use ethereum_serai::alloy::{ simple_request_transport::SimpleRequest, - rpc_types::BlockNumberOrTag, + rpc_types::{BlockTransactionsKind, BlockNumberOrTag}, rpc_client::ClientBuilder, provider::{Provider, RootProvider}, network::Ethereum, @@ -305,7 +375,7 @@ impl Coordinator { ClientBuilder::default().transport(SimpleRequest::new(rpc_url.clone()), true), ); let start = provider - .get_block(BlockNumberOrTag::Latest.into(), false) + .get_block(BlockNumberOrTag::Latest.into(), BlockTransactionsKind::Hashes) .await .unwrap() .unwrap() @@ -316,7 +386,7 @@ impl Coordinator { provider.raw_request::<_, ()>("anvil_mine".into(), [96]).await.unwrap(); let end_of_epoch = start + 31; let hash = provider - .get_block(BlockNumberOrTag::Number(end_of_epoch).into(), false) + .get_block(BlockNumberOrTag::Number(end_of_epoch).into(), BlockTransactionsKind::Hashes) .await .unwrap() .unwrap() @@ -371,7 +441,10 @@ impl Coordinator { let rpc = Rpc::new(rpc_url).await.expect("couldn't connect to the Bitcoin RPC"); let to = rpc.get_latest_block_number().await.unwrap(); for coordinator in others { - let from = rpc.get_latest_block_number().await.unwrap() + 1; + let other_rpc = Rpc::new(network_rpc(self.network, ops, &coordinator.network_handle)) + .await + .expect("couldn't connect to the Bitcoin RPC"); + let from = other_rpc.get_latest_block_number().await.unwrap() + 1; for b in from ..= to { let mut buf = vec![]; @@ -382,12 +455,10 @@ impl Coordinator { .consensus_encode(&mut buf) .unwrap(); - let rpc_url = network_rpc(coordinator.network, ops, &coordinator.network_handle); - let rpc = - Rpc::new(rpc_url).await.expect("couldn't connect to the coordinator's Bitcoin RPC"); - - let res: Option = - rpc.rpc_call("submitblock", serde_json::json!([hex::encode(buf)])).await.unwrap(); + let res: Option = other_rpc + .rpc_call("submitblock", serde_json::json!([hex::encode(buf)])) + .await + .unwrap(); if let Some(err) = res { panic!("submitblock failed: {err}"); } @@ -397,22 +468,52 @@ impl Coordinator { NetworkId::Ethereum => { use ethereum_serai::alloy::{ simple_request_transport::SimpleRequest, + rpc_types::{BlockTransactionsKind, BlockNumberOrTag}, rpc_client::ClientBuilder, provider::{Provider, RootProvider}, network::Ethereum, }; - let provider = RootProvider::<_, Ethereum>::new( - ClientBuilder::default().transport(SimpleRequest::new(rpc_url.clone()), true), - ); - let state = provider.raw_request::<_, String>("anvil_dumpState".into(), ()).await.unwrap(); + let (expected_number, state) = { + let provider = RootProvider::<_, Ethereum>::new( + ClientBuilder::default().transport(SimpleRequest::new(rpc_url.clone()), true), + ); + + let expected_number = provider + .get_block(BlockNumberOrTag::Latest.into(), BlockTransactionsKind::Hashes) + .await + .unwrap() + .unwrap() + .header + .number; + ( + expected_number, + provider.raw_request::<_, String>("anvil_dumpState".into(), ()).await.unwrap(), + ) + }; for coordinator in others { let rpc_url = network_rpc(coordinator.network, ops, &coordinator.network_handle); let provider = RootProvider::<_, Ethereum>::new( ClientBuilder::default().transport(SimpleRequest::new(rpc_url.clone()), true), ); - provider.raw_request::<_, ()>("anvil_loadState".into(), &state).await.unwrap(); + assert!(provider + .raw_request::<_, bool>("anvil_loadState".into(), &[&state]) + .await + .unwrap()); + + let new_number = provider + .get_block(BlockNumberOrTag::Latest.into(), BlockTransactionsKind::Hashes) + .await + .unwrap() + .unwrap() + .header + .number; + + // TODO: https://github.com/foundry-rs/foundry/issues/7955 + let _ = expected_number; + let _ = new_number; + //assert_eq!(expected_number, new_number); } } NetworkId::Monero => { @@ -421,21 +522,17 @@ impl Coordinator { let rpc = HttpRpc::new(rpc_url).await.expect("couldn't connect to the Monero RPC"); let to = rpc.get_height().await.unwrap(); for coordinator in others { - let from = HttpRpc::new(network_rpc(self.network, ops, &coordinator.network_handle)) - .await - .expect("couldn't connect to the Monero RPC") - .get_height() - .await - .unwrap(); + let other_rpc = + HttpRpc::new(network_rpc(coordinator.network, ops, &coordinator.network_handle)) + .await + .expect("couldn't connect to the Monero RPC"); + + let from = other_rpc.get_height().await.unwrap(); for b in from .. to { let block = rpc.get_block(rpc.get_block_hash(b).await.unwrap()).await.unwrap().serialize(); - let rpc_url = network_rpc(coordinator.network, ops, &coordinator.network_handle); - let rpc = HttpRpc::new(rpc_url) - .await - .expect("couldn't connect to the coordinator's Monero RPC"); - let res: serde_json::Value = rpc + let res: serde_json::Value = other_rpc .json_rpc_call("submit_block", Some(serde_json::json!([hex::encode(block)]))) .await .unwrap(); @@ -450,7 +547,7 @@ impl Coordinator { } } - pub async fn publish_transacton(&self, ops: &DockerOperations, tx: &[u8]) { + pub async fn publish_transaction(&self, ops: &DockerOperations, tx: &[u8]) { let rpc_url = network_rpc(self.network, ops, &self.network_handle); match self.network { NetworkId::Bitcoin => { @@ -487,6 +584,14 @@ impl Coordinator { } } + pub async fn publish_eventuality_completion(&self, ops: &DockerOperations, tx: &[u8]) { + match self.network { + NetworkId::Bitcoin | NetworkId::Monero => self.publish_transaction(ops, tx).await, + NetworkId::Ethereum => (), + NetworkId::Serai => panic!("processor tests broadcasting block to Serai"), + } + } + pub async fn get_published_transaction( &self, ops: &DockerOperations, @@ -517,14 +622,7 @@ impl Coordinator { } } NetworkId::Ethereum => { - use ethereum_serai::alloy::{ - consensus::{TxLegacy, Signed}, - simple_request_transport::SimpleRequest, - rpc_client::ClientBuilder, - provider::{Provider, RootProvider}, - network::Ethereum, - }; - + /* let provider = RootProvider::<_, Ethereum>::new( ClientBuilder::default().transport(SimpleRequest::new(rpc_url.clone()), true), ); @@ -535,6 +633,43 @@ impl Coordinator { let mut bytes = vec![]; tx.encode_with_signature_fields(&sig, &mut bytes); Some(bytes) + */ + + // This is being passed a signature. We need to check the relayer has a TX with this + // signature + + use tokio::{ + io::{AsyncReadExt, AsyncWriteExt}, + net::TcpStream, + }; + + let (ip, port) = ops.handle(&self.relayer_handle).host_port(20831).unwrap(); + let relayer_url = format!("{ip}:{port}"); + + let mut socket = TcpStream::connect(&relayer_url).await.unwrap(); + // Iterate over every published command + for i in 1 .. u32::MAX { + socket.write_all(&i.to_le_bytes()).await.unwrap(); + + let mut recvd_len = [0; 4]; + socket.read_exact(&mut recvd_len).await.unwrap(); + if recvd_len == [0; 4] { + break; + } + + let mut msg = vec![0; usize::try_from(u32::from_le_bytes(recvd_len)).unwrap()]; + socket.read_exact(&mut msg).await.unwrap(); + for start_pos in 0 .. msg.len() { + if (start_pos + tx.len()) > msg.len() { + break; + } + if &msg[start_pos .. (start_pos + tx.len())] == tx { + return Some(msg); + } + } + } + + None } NetworkId::Monero => { use monero_serai::rpc::HttpRpc; diff --git a/tests/processor/src/networks.rs b/tests/processor/src/networks.rs index 5b54cc01c..9af339b74 100644 --- a/tests/processor/src/networks.rs +++ b/tests/processor/src/networks.rs @@ -96,6 +96,7 @@ pub enum Wallet { input_tx: bitcoin_serai::bitcoin::Transaction, }, Ethereum { + rpc_url: String, key: ::F, nonce: u64, }, @@ -125,7 +126,7 @@ impl Wallet { let secret_key = SecretKey::new(&mut rand_core::OsRng); let private_key = PrivateKey::new(secret_key, Network::Regtest); let public_key = PublicKey::from_private_key(SECP256K1, &private_key); - let main_addr = Address::p2pkh(&public_key, Network::Regtest); + let main_addr = Address::p2pkh(public_key, Network::Regtest); let rpc = Rpc::new(rpc_url).await.expect("couldn't connect to the Bitcoin RPC"); @@ -155,7 +156,7 @@ impl Wallet { } NetworkId::Ethereum => { - use ciphersuite::{group::ff::Field, Ciphersuite, Secp256k1}; + use ciphersuite::{group::ff::Field, Secp256k1}; use ethereum_serai::alloy::{ primitives::{U256, Address}, simple_request_transport::SimpleRequest, @@ -183,7 +184,7 @@ impl Wallet { .await .unwrap(); - Wallet::Ethereum { key, nonce: 0 } + Wallet::Ethereum { rpc_url: rpc_url.clone(), key, nonce: 0 } } NetworkId::Monero => { @@ -257,7 +258,6 @@ impl Wallet { consensus::Encodable, sighash::{EcdsaSighashType, SighashCache}, script::{PushBytesBuf, Script, ScriptBuf, Builder}, - address::Payload, OutPoint, Sequence, Witness, TxIn, Amount, TxOut, absolute::LockTime, transaction::{Version, Transaction}, @@ -268,7 +268,7 @@ impl Wallet { version: Version(2), lock_time: LockTime::ZERO, input: vec![TxIn { - previous_output: OutPoint { txid: input_tx.txid(), vout: 0 }, + previous_output: OutPoint { txid: input_tx.compute_txid(), vout: 0 }, script_sig: Script::new().into(), sequence: Sequence(u32::MAX), witness: Witness::default(), @@ -280,10 +280,11 @@ impl Wallet { }, TxOut { value: Amount::from_sat(AMOUNT), - script_pubkey: Payload::p2tr_tweaked(TweakedPublicKey::dangerous_assume_tweaked( - XOnlyPublicKey::from_slice(&to[1 ..]).unwrap(), - )) - .script_pubkey(), + script_pubkey: ScriptBuf::new_p2tr_tweaked( + TweakedPublicKey::dangerous_assume_tweaked( + XOnlyPublicKey::from_slice(&to[1 ..]).unwrap(), + ), + ), }, ], }; @@ -302,7 +303,7 @@ impl Wallet { let mut der = SECP256K1 .sign_ecdsa_low_r( - &Message::from( + &Message::from_digest_slice( SighashCache::new(&tx) .legacy_signature_hash( 0, @@ -310,8 +311,10 @@ impl Wallet { EcdsaSighashType::All.to_u32(), ) .unwrap() - .to_raw_hash(), - ), + .to_raw_hash() + .as_ref(), + ) + .unwrap(), &private_key.inner, ) .serialize_der() @@ -328,22 +331,107 @@ impl Wallet { (buf, Balance { coin: Coin::Bitcoin, amount: Amount(AMOUNT) }) } - Wallet::Ethereum { key, ref mut nonce } => { - /* - use ethereum_serai::alloy::primitives::U256; + Wallet::Ethereum { rpc_url, key, ref mut nonce } => { + use std::sync::Arc; + use ethereum_serai::{ + alloy::{ + primitives::{U256, TxKind}, + sol_types::SolCall, + simple_request_transport::SimpleRequest, + consensus::{TxLegacy, SignableTransaction}, + rpc_client::ClientBuilder, + provider::{Provider, RootProvider}, + network::Ethereum, + }, + crypto::PublicKey, + deployer::Deployer, + }; let eight_decimals = U256::from(100_000_000u64); let nine_decimals = eight_decimals * U256::from(10u64); let eighteen_decimals = nine_decimals * nine_decimals; + let one_eth = eighteen_decimals; + + let provider = Arc::new(RootProvider::<_, Ethereum>::new( + ClientBuilder::default().transport(SimpleRequest::new(rpc_url.clone()), true), + )); + + let to_as_key = PublicKey::new( + ::read_G(&mut to.as_slice()).unwrap(), + ) + .unwrap(); + let router_addr = { + // Find the deployer + let deployer = Deployer::new(provider.clone()).await.unwrap().unwrap(); + + // Find the router, deploying if non-existent + let router = if let Some(router) = + deployer.find_router(provider.clone(), &to_as_key).await.unwrap() + { + router + } else { + let mut tx = deployer.deploy_router(&to_as_key); + tx.gas_price = 1_000_000_000u64.into(); + let tx = ethereum_serai::crypto::deterministically_sign(&tx); + let signer = tx.recover_signer().unwrap(); + let (tx, sig, _) = tx.into_parts(); + + provider + .raw_request::<_, ()>( + "anvil_setBalance".into(), + [signer.to_string(), (tx.gas_limit * tx.gas_price).to_string()], + ) + .await + .unwrap(); + + let mut bytes = vec![]; + tx.encode_with_signature_fields(&sig, &mut bytes); + let _ = provider.send_raw_transaction(&bytes).await.unwrap(); + + provider.raw_request::<_, ()>("anvil_mine".into(), [96]).await.unwrap(); + + deployer.find_router(provider.clone(), &to_as_key).await.unwrap().unwrap() + }; - let tx = todo!("send to router"); + router.address() + }; + + let tx = TxLegacy { + chain_id: None, + nonce: *nonce, + gas_price: 1_000_000_000u128, + gas_limit: 200_000u128, + to: TxKind::Call(router_addr.into()), + // 1 ETH + value: one_eth, + input: ethereum_serai::router::abi::inInstructionCall::new(( + [0; 20].into(), + one_eth, + if let Some(instruction) = instruction { + Shorthand::Raw(RefundableInInstruction { origin: None, instruction }).encode().into() + } else { + vec![].into() + }, + )) + .abi_encode() + .into(), + }; *nonce += 1; - (tx, Balance { coin: Coin::Ether, amount: Amount(u64::try_from(eight_decimals).unwrap()) }) - */ - let _ = key; - let _ = nonce; - todo!() + + let sig = + k256::ecdsa::SigningKey::from(k256::elliptic_curve::NonZeroScalar::new(*key).unwrap()) + .sign_prehash_recoverable(tx.signature_hash().as_ref()) + .unwrap(); + + let mut bytes = vec![]; + tx.encode_with_signature_fields(&sig.into(), &mut bytes); + + // We drop the bottom 10 decimals + ( + bytes, + Balance { coin: Coin::Ether, amount: Amount(u64::try_from(eight_decimals).unwrap()) }, + ) } Wallet::Monero { handle, ref spend_key, ref view_pair, ref mut inputs } => { @@ -430,21 +518,18 @@ impl Wallet { match self { Wallet::Bitcoin { public_key, .. } => { - use bitcoin_serai::bitcoin::{Network, Address}; + use bitcoin_serai::bitcoin::ScriptBuf; ExternalAddress::new( - networks::bitcoin::Address::new(Address::p2pkh(public_key, Network::Regtest)) + networks::bitcoin::Address::new(ScriptBuf::new_p2pkh(&public_key.pubkey_hash())) .unwrap() .into(), ) .unwrap() } - Wallet::Ethereum { key, .. } => { - use ciphersuite::{Ciphersuite, Secp256k1}; - ExternalAddress::new( - ethereum_serai::crypto::address(&(Secp256k1::generator() * key)).into(), - ) - .unwrap() - } + Wallet::Ethereum { key, .. } => ExternalAddress::new( + ethereum_serai::crypto::address(&(ciphersuite::Secp256k1::generator() * key)).into(), + ) + .unwrap(), Wallet::Monero { view_pair, .. } => { use monero_serai::wallet::address::{Network, AddressSpec}; ExternalAddress::new( diff --git a/tests/processor/src/tests/batch.rs b/tests/processor/src/tests/batch.rs index 5729fd73e..6170270ac 100644 --- a/tests/processor/src/tests/batch.rs +++ b/tests/processor/src/tests/batch.rs @@ -17,7 +17,8 @@ use serai_client::{ validator_sets::primitives::Session, }; -use processor::networks::{Network, Bitcoin, Monero}; +use serai_db::MemDb; +use processor::networks::{Network, Bitcoin, Ethereum, Monero}; use crate::{*, tests::*}; @@ -188,7 +189,7 @@ pub(crate) async fn substrate_block( #[test] fn batch_test() { - for network in [NetworkId::Bitcoin, NetworkId::Monero] { + for network in [NetworkId::Bitcoin, NetworkId::Ethereum, NetworkId::Monero] { let (coordinators, test) = new_test(network); test.run(|ops| async move { @@ -228,7 +229,7 @@ fn batch_test() { let (tx, balance_sent) = wallet.send_to_address(&ops, &key_pair.1, instruction.clone()).await; for coordinator in &mut coordinators { - coordinator.publish_transacton(&ops, &tx).await; + coordinator.publish_transaction(&ops, &tx).await; } // Put the TX past the confirmation depth @@ -245,6 +246,8 @@ fn batch_test() { // The scanner works on a 5s interval, so this leaves a few s for any processing/latency tokio::time::sleep(Duration::from_secs(10)).await; + println!("sent in transaction. with in instruction: {}", instruction.is_some()); + let expected_batch = Batch { network, id: i, @@ -256,10 +259,11 @@ fn batch_test() { coin: balance_sent.coin, amount: Amount( balance_sent.amount.0 - - (2 * if network == NetworkId::Bitcoin { - Bitcoin::COST_TO_AGGREGATE - } else { - Monero::COST_TO_AGGREGATE + (2 * match network { + NetworkId::Bitcoin => Bitcoin::COST_TO_AGGREGATE, + NetworkId::Ethereum => Ethereum::::COST_TO_AGGREGATE, + NetworkId::Monero => Monero::COST_TO_AGGREGATE, + NetworkId::Serai => panic!("minted for Serai?"), }), ), }, @@ -272,6 +276,8 @@ fn batch_test() { }, }; + println!("receiving batch preprocesses..."); + // Make sure the processors picked it up by checking they're trying to sign a batch for it let (mut id, mut preprocesses) = recv_batch_preprocesses(&mut coordinators, Session(0), &expected_batch, 0).await; @@ -291,6 +297,8 @@ fn batch_test() { recv_batch_preprocesses(&mut coordinators, Session(0), &expected_batch, attempt).await; } + println!("signing batch..."); + // Continue with signing the batch let batch = sign_batch(&mut coordinators, key_pair.0 .0, id, preprocesses).await; diff --git a/tests/processor/src/tests/key_gen.rs b/tests/processor/src/tests/key_gen.rs index d50c12b79..7dea0bfd5 100644 --- a/tests/processor/src/tests/key_gen.rs +++ b/tests/processor/src/tests/key_gen.rs @@ -144,7 +144,7 @@ pub(crate) async fn key_gen(coordinators: &mut [Coordinator]) -> KeyPair { #[test] fn key_gen_test() { - for network in [NetworkId::Bitcoin, NetworkId::Monero] { + for network in [NetworkId::Bitcoin, NetworkId::Ethereum, NetworkId::Monero] { let (coordinators, test) = new_test(network); test.run(|ops| async move { diff --git a/tests/processor/src/tests/mod.rs b/tests/processor/src/tests/mod.rs index 54a17020f..afda97d5e 100644 --- a/tests/processor/src/tests/mod.rs +++ b/tests/processor/src/tests/mod.rs @@ -20,8 +20,14 @@ pub(crate) const THRESHOLD: usize = ((COORDINATORS * 2) / 3) + 1; fn new_test(network: NetworkId) -> (Vec<(Handles, ::F)>, DockerTest) { let mut coordinators = vec![]; let mut test = DockerTest::new().with_network(dockertest::Network::Isolated); + let mut eth_handle = None; for _ in 0 .. COORDINATORS { - let (handles, coord_key, compositions) = processor_stack(network); + let (handles, coord_key, compositions) = processor_stack(network, eth_handle.clone()); + // TODO: Remove this once https://github.com/foundry-rs/foundry/issues/7955 + // This has all processors share an Ethereum node until we can sync controlled nodes + if network == NetworkId::Ethereum { + eth_handle = eth_handle.or_else(|| Some(handles.0.clone())); + } coordinators.push((handles, coord_key)); for composition in compositions { test.provide_container(composition); diff --git a/tests/processor/src/tests/send.rs b/tests/processor/src/tests/send.rs index 4d0d3cd6b..62e80c095 100644 --- a/tests/processor/src/tests/send.rs +++ b/tests/processor/src/tests/send.rs @@ -8,12 +8,15 @@ use dkg::{Participant, tests::clone_without}; use messages::{sign::SignId, SubstrateContext}; use serai_client::{ - primitives::{BlockHash, NetworkId}, + primitives::{BlockHash, NetworkId, Amount, Balance, SeraiAddress}, coins::primitives::{OutInstruction, OutInstructionWithBalance}, - in_instructions::primitives::Batch, + in_instructions::primitives::{InInstruction, InInstructionWithBalance, Batch}, validator_sets::primitives::Session, }; +use serai_db::MemDb; +use processor::networks::{Network, Bitcoin, Ethereum, Monero}; + use crate::{*, tests::*}; #[allow(unused)] @@ -144,7 +147,7 @@ pub(crate) async fn sign_tx( #[test] fn send_test() { - for network in [NetworkId::Bitcoin, NetworkId::Monero] { + for network in [NetworkId::Bitcoin, NetworkId::Ethereum, NetworkId::Monero] { let (coordinators, test) = new_test(network); test.run(|ops| async move { @@ -173,9 +176,13 @@ fn send_test() { coordinators[0].sync(&ops, &coordinators[1 ..]).await; // Send into the processor's wallet - let (tx, balance_sent) = wallet.send_to_address(&ops, &key_pair.1, None).await; + let mut serai_address = [0; 32]; + OsRng.fill_bytes(&mut serai_address); + let instruction = InInstruction::Transfer(SeraiAddress(serai_address)); + let (tx, balance_sent) = + wallet.send_to_address(&ops, &key_pair.1, Some(instruction.clone())).await; for coordinator in &mut coordinators { - coordinator.publish_transacton(&ops, &tx).await; + coordinator.publish_transaction(&ops, &tx).await; } // Put the TX past the confirmation depth @@ -192,8 +199,25 @@ fn send_test() { // The scanner works on a 5s interval, so this leaves a few s for any processing/latency tokio::time::sleep(Duration::from_secs(10)).await; - let expected_batch = - Batch { network, id: 0, block: BlockHash(block_with_tx.unwrap()), instructions: vec![] }; + let amount_minted = Amount( + balance_sent.amount.0 - + (2 * match network { + NetworkId::Bitcoin => Bitcoin::COST_TO_AGGREGATE, + NetworkId::Ethereum => Ethereum::::COST_TO_AGGREGATE, + NetworkId::Monero => Monero::COST_TO_AGGREGATE, + NetworkId::Serai => panic!("minted for Serai?"), + }), + ); + + let expected_batch = Batch { + network, + id: 0, + block: BlockHash(block_with_tx.unwrap()), + instructions: vec![InInstructionWithBalance { + instruction, + balance: Balance { coin: balance_sent.coin, amount: amount_minted }, + }], + }; // Make sure the proceessors picked it up by checking they're trying to sign a batch for it let (id, preprocesses) = @@ -221,7 +245,7 @@ fn send_test() { block: substrate_block_num, burns: vec![OutInstructionWithBalance { instruction: OutInstruction { address: wallet.address(), data: None }, - balance: balance_sent, + balance: Balance { coin: balance_sent.coin, amount: amount_minted }, }], batches: vec![batch.batch.id], }, @@ -271,7 +295,7 @@ fn send_test() { .unwrap(); for (i, coordinator) in coordinators.iter_mut().enumerate() { if !participating.contains(&i) { - coordinator.publish_transacton(&ops, &tx).await; + coordinator.publish_eventuality_completion(&ops, &tx).await; // Tell them of it as a completion of the relevant signing nodes coordinator .send_message(messages::sign::CoordinatorMessage::Completed {