mirror of
https://github.com/serai-dex/serai.git
synced 2024-11-16 17:07:35 +00:00
Remove subxt (#460)
* Remove subxt Removes ~20 crates from our Cargo.lock. Removes downloading the metadata and enables removing the getMetadata RPC route (relevant to #379). Moves forward #337. Done now due to distinctions in the subxt 0.32 API surface which make it justifiable to not update. * fmt, update due to deny triggering on a yanked crate * Correct the handling of substrate_block_notifier now that it's ephemeral, not long-lived * Correct URL in tests/coordinator from ws to http
This commit is contained in:
parent
571195bfda
commit
695d1f0ecf
30 changed files with 473 additions and 718 deletions
439
Cargo.lock
generated
439
Cargo.lock
generated
|
@ -27,7 +27,7 @@ version = "0.21.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
|
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gimli 0.28.0",
|
"gimli 0.28.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -266,7 +266,7 @@ version = "2.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "41ed9d5715c2d329bf1b4da8d60455b99b187f27ba726df2883799af9af60997"
|
checksum = "41ed9d5715c2d329bf1b4da8d60455b99b187f27ba726df2883799af9af60997"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-lock 3.1.1",
|
"async-lock",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"concurrent-queue",
|
"concurrent-queue",
|
||||||
"futures-io",
|
"futures-io",
|
||||||
|
@ -282,20 +282,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-lock"
|
name = "async-lock"
|
||||||
version = "2.8.0"
|
version = "3.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b"
|
checksum = "dea8b3453dd7cc96711834b75400d671b73e3656975fa68d9f277163b7f7e316"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"event-listener 2.5.3",
|
"event-listener 4.0.0",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-lock"
|
|
||||||
version = "3.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "655b9c7fe787d3b25cc0f804a1a8401790f0c5bc395beb5a64dc77d8de079105"
|
|
||||||
dependencies = [
|
|
||||||
"event-listener 3.1.0",
|
|
||||||
"event-listener-strategy",
|
"event-listener-strategy",
|
||||||
"pin-project-lite 0.2.13",
|
"pin-project-lite 0.2.13",
|
||||||
]
|
]
|
||||||
|
@ -391,12 +382,6 @@ version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
|
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "base58"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base58-monero"
|
name = "base58-monero"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
@ -954,9 +939,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.4.8"
|
version = "4.4.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64"
|
checksum = "46ca43acc1b21c6cc2d1d3129c19e323a613935b5bc28fb3b33b5b2e5fb00030"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
|
@ -964,9 +949,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.4.8"
|
version = "4.4.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc"
|
checksum = "63361bae7eef3771745f02d8d892bec2fee5f6e34af316ba556e7f97a7069ff1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
|
@ -1391,76 +1376,6 @@ dependencies = [
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling"
|
|
||||||
version = "0.14.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
|
|
||||||
dependencies = [
|
|
||||||
"darling_core 0.14.4",
|
|
||||||
"darling_macro 0.14.4",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling"
|
|
||||||
version = "0.20.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
|
|
||||||
dependencies = [
|
|
||||||
"darling_core 0.20.3",
|
|
||||||
"darling_macro 0.20.3",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling_core"
|
|
||||||
version = "0.14.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
|
|
||||||
dependencies = [
|
|
||||||
"fnv",
|
|
||||||
"ident_case",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"strsim",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling_core"
|
|
||||||
version = "0.20.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621"
|
|
||||||
dependencies = [
|
|
||||||
"fnv",
|
|
||||||
"ident_case",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"strsim",
|
|
||||||
"syn 2.0.39",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling_macro"
|
|
||||||
version = "0.14.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
|
|
||||||
dependencies = [
|
|
||||||
"darling_core 0.14.4",
|
|
||||||
"quote",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling_macro"
|
|
||||||
version = "0.20.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
|
|
||||||
dependencies = [
|
|
||||||
"darling_core 0.20.3",
|
|
||||||
"quote",
|
|
||||||
"syn 2.0.39",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "data-encoding"
|
name = "data-encoding"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
|
@ -1530,17 +1445,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "derivative"
|
|
||||||
version = "2.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive-syn-parse"
|
name = "derive-syn-parse"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
|
@ -1807,7 +1711,7 @@ checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"curve25519-dalek",
|
"curve25519-dalek",
|
||||||
"ed25519",
|
"ed25519",
|
||||||
"hashbrown 0.14.2",
|
"hashbrown 0.14.3",
|
||||||
"hex",
|
"hex",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
"sha2",
|
"sha2",
|
||||||
|
@ -2126,9 +2030,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "event-listener"
|
name = "event-listener"
|
||||||
version = "3.1.0"
|
version = "4.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2"
|
checksum = "770d968249b5d99410d61f5bf89057f3199a077a04d087092f58e7d10692baae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"concurrent-queue",
|
"concurrent-queue",
|
||||||
"parking",
|
"parking",
|
||||||
|
@ -2137,11 +2041,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "event-listener-strategy"
|
name = "event-listener-strategy"
|
||||||
version = "0.3.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160"
|
checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"event-listener 3.1.0",
|
"event-listener 4.0.0",
|
||||||
"pin-project-lite 0.2.13",
|
"pin-project-lite 0.2.13",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2378,18 +2282,6 @@ dependencies = [
|
||||||
"sp-tracing",
|
"sp-tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "frame-metadata"
|
|
||||||
version = "15.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "878babb0b136e731cc77ec2fd883ff02745ff21e6fb662729953d44923df009c"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"parity-scale-codec",
|
|
||||||
"scale-info",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "frame-metadata"
|
name = "frame-metadata"
|
||||||
version = "16.0.0"
|
version = "16.0.0"
|
||||||
|
@ -2409,7 +2301,7 @@ source = "git+https://github.com/serai-dex/substrate#49b7d20ef96b6ad42ea0266ea27
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"environmental",
|
"environmental",
|
||||||
"frame-metadata 16.0.0",
|
"frame-metadata",
|
||||||
"frame-support-procedural",
|
"frame-support-procedural",
|
||||||
"impl-trait-for-tuples",
|
"impl-trait-for-tuples",
|
||||||
"log",
|
"log",
|
||||||
|
@ -2757,10 +2649,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
|
checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"js-sys",
|
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi",
|
||||||
"wasm-bindgen",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2786,9 +2676,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.28.0"
|
version = "0.28.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
|
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glob"
|
name = "glob"
|
||||||
|
@ -2798,15 +2688,15 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "globset"
|
name = "globset"
|
||||||
version = "0.4.13"
|
version = "0.4.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d"
|
checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"bstr",
|
"bstr",
|
||||||
"fnv",
|
|
||||||
"log",
|
"log",
|
||||||
"regex",
|
"regex-automata 0.4.3",
|
||||||
|
"regex-syntax 0.8.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2883,9 +2773,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.14.2"
|
version = "0.14.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
|
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"allocator-api2",
|
"allocator-api2",
|
||||||
|
@ -3067,7 +2957,6 @@ dependencies = [
|
||||||
"rustls-native-certs",
|
"rustls-native-certs",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"webpki-roots",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3106,12 +2995,6 @@ dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ident_case"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
|
@ -3243,7 +3126,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown 0.14.2",
|
"hashbrown 0.14.3",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -3336,9 +3219,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.65"
|
version = "0.3.66"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8"
|
checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
@ -3349,36 +3232,13 @@ version = "0.16.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "367a292944c07385839818bb71c8d76611138e2dedb0677d035b8da21d29c78b"
|
checksum = "367a292944c07385839818bb71c8d76611138e2dedb0677d035b8da21d29c78b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jsonrpsee-client-transport",
|
|
||||||
"jsonrpsee-core",
|
"jsonrpsee-core",
|
||||||
"jsonrpsee-http-client",
|
|
||||||
"jsonrpsee-proc-macros",
|
"jsonrpsee-proc-macros",
|
||||||
"jsonrpsee-server",
|
"jsonrpsee-server",
|
||||||
"jsonrpsee-types",
|
"jsonrpsee-types",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "jsonrpsee-client-transport"
|
|
||||||
version = "0.16.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c8b3815d9f5d5de348e5f162b316dc9cdf4548305ebb15b4eb9328e66cf27d7a"
|
|
||||||
dependencies = [
|
|
||||||
"futures-util",
|
|
||||||
"http",
|
|
||||||
"jsonrpsee-core",
|
|
||||||
"jsonrpsee-types",
|
|
||||||
"pin-project",
|
|
||||||
"rustls-native-certs",
|
|
||||||
"soketto",
|
|
||||||
"thiserror",
|
|
||||||
"tokio",
|
|
||||||
"tokio-rustls",
|
|
||||||
"tokio-util",
|
|
||||||
"tracing",
|
|
||||||
"webpki-roots",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jsonrpsee-core"
|
name = "jsonrpsee-core"
|
||||||
version = "0.16.3"
|
version = "0.16.3"
|
||||||
|
@ -3387,11 +3247,9 @@ checksum = "2b5dde66c53d6dcdc8caea1874a45632ec0fcf5b437789f1e45766a1512ce803"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"async-lock 2.8.0",
|
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"beef",
|
"beef",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-timer",
|
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"globset",
|
"globset",
|
||||||
"hyper",
|
"hyper",
|
||||||
|
@ -3407,25 +3265,6 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "jsonrpsee-http-client"
|
|
||||||
version = "0.16.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7e5f9fabdd5d79344728521bb65e3106b49ec405a78b66fbff073b72b389fa43"
|
|
||||||
dependencies = [
|
|
||||||
"async-trait",
|
|
||||||
"hyper",
|
|
||||||
"hyper-rustls",
|
|
||||||
"jsonrpsee-core",
|
|
||||||
"jsonrpsee-types",
|
|
||||||
"rustc-hash",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"thiserror",
|
|
||||||
"tokio",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jsonrpsee-proc-macros"
|
name = "jsonrpsee-proc-macros"
|
||||||
version = "0.16.3"
|
version = "0.16.3"
|
||||||
|
@ -4151,11 +3990,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lru"
|
name = "lru"
|
||||||
version = "0.12.0"
|
version = "0.12.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1efa59af2ddfad1854ae27d75009d538d0998b4b2fd47083e743ac1a10e46c60"
|
checksum = "2994eeba8ed550fd9b47a0b38f0242bc3344e496483c6180b69139cc2fa5d1d7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown 0.14.2",
|
"hashbrown 0.14.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -5317,9 +5156,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.0"
|
version = "2.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "petgraph"
|
name = "petgraph"
|
||||||
|
@ -5579,9 +5418,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.69"
|
version = "1.0.70"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
|
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
@ -7210,73 +7049,6 @@ dependencies = [
|
||||||
"sp-arithmetic",
|
"sp-arithmetic",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "scale-bits"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8dd7aca73785181cc41f0bbe017263e682b585ca660540ba569133901d013ecf"
|
|
||||||
dependencies = [
|
|
||||||
"parity-scale-codec",
|
|
||||||
"scale-info",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "scale-decode"
|
|
||||||
version = "0.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f0459d00b0dbd2e765009924a78ef36b2ff7ba116292d732f00eb0ed8e465d15"
|
|
||||||
dependencies = [
|
|
||||||
"parity-scale-codec",
|
|
||||||
"primitive-types",
|
|
||||||
"scale-bits",
|
|
||||||
"scale-decode-derive",
|
|
||||||
"scale-info",
|
|
||||||
"smallvec",
|
|
||||||
"thiserror",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "scale-decode-derive"
|
|
||||||
version = "0.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4391f0dfbb6690f035f6d2a15d6a12f88cc5395c36bcc056db07ffa2a90870ec"
|
|
||||||
dependencies = [
|
|
||||||
"darling 0.14.4",
|
|
||||||
"proc-macro-crate 1.3.1",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "scale-encode"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b0401b7cdae8b8aa33725f3611a051358d5b32887ecaa0fda5953a775b2d4d76"
|
|
||||||
dependencies = [
|
|
||||||
"parity-scale-codec",
|
|
||||||
"primitive-types",
|
|
||||||
"scale-bits",
|
|
||||||
"scale-encode-derive",
|
|
||||||
"scale-info",
|
|
||||||
"smallvec",
|
|
||||||
"thiserror",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "scale-encode-derive"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "316e0fb10ec0fee266822bd641bab5e332a4ab80ef8c5b5ff35e5401a394f5a6"
|
|
||||||
dependencies = [
|
|
||||||
"darling 0.14.4",
|
|
||||||
"proc-macro-crate 1.3.1",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scale-info"
|
name = "scale-info"
|
||||||
version = "2.10.0"
|
version = "2.10.0"
|
||||||
|
@ -7303,26 +7075,6 @@ dependencies = [
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "scale-value"
|
|
||||||
version = "0.10.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f2096d36e94ce9bf87d8addb752423b6b19730dc88edd7cc452bb2b90573f7a7"
|
|
||||||
dependencies = [
|
|
||||||
"base58",
|
|
||||||
"blake2",
|
|
||||||
"either",
|
|
||||||
"frame-metadata 15.1.0",
|
|
||||||
"parity-scale-codec",
|
|
||||||
"scale-bits",
|
|
||||||
"scale-decode",
|
|
||||||
"scale-encode",
|
|
||||||
"scale-info",
|
|
||||||
"serde",
|
|
||||||
"thiserror",
|
|
||||||
"yap",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "schannel"
|
name = "schannel"
|
||||||
version = "0.1.22"
|
version = "0.1.22"
|
||||||
|
@ -7516,18 +7268,18 @@ dependencies = [
|
||||||
"ciphersuite",
|
"ciphersuite",
|
||||||
"dockertest",
|
"dockertest",
|
||||||
"frost-schnorrkel",
|
"frost-schnorrkel",
|
||||||
"futures",
|
|
||||||
"hex",
|
"hex",
|
||||||
"modular-frost",
|
"modular-frost",
|
||||||
"monero-serai",
|
"monero-serai",
|
||||||
"parity-scale-codec",
|
"parity-scale-codec",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
"scale-info",
|
|
||||||
"serai-docker-tests",
|
"serai-docker-tests",
|
||||||
"serai-runtime",
|
"serai-runtime",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"simple-request",
|
||||||
"sp-core",
|
"sp-core",
|
||||||
"sp-runtime",
|
"sp-runtime",
|
||||||
"subxt",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
|
@ -8614,7 +8366,7 @@ name = "sp-metadata-ir"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/serai-dex/substrate#49b7d20ef96b6ad42ea0266ea27f128e0ef3214d"
|
source = "git+https://github.com/serai-dex/substrate#49b7d20ef96b6ad42ea0266ea27f128e0ef3214d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"frame-metadata 16.0.0",
|
"frame-metadata",
|
||||||
"parity-scale-codec",
|
"parity-scale-codec",
|
||||||
"scale-info",
|
"scale-info",
|
||||||
"sp-std",
|
"sp-std",
|
||||||
|
@ -8811,7 +8563,7 @@ source = "git+https://github.com/serai-dex/substrate#49b7d20ef96b6ad42ea0266ea27
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"hash-db",
|
"hash-db",
|
||||||
"hashbrown 0.14.2",
|
"hashbrown 0.14.3",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"memory-db",
|
"memory-db",
|
||||||
"nohash-hasher",
|
"nohash-hasher",
|
||||||
|
@ -8970,7 +8722,7 @@ dependencies = [
|
||||||
name = "std-shims"
|
name = "std-shims"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown 0.14.2",
|
"hashbrown 0.14.3",
|
||||||
"spin 0.9.8",
|
"spin 0.9.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -9106,83 +8858,6 @@ version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
|
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "subxt"
|
|
||||||
version = "0.29.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "31a734d66fa935fbda56ba6a71d7e969f424c8c5608d416ba8499d71d8cbfc1f"
|
|
||||||
dependencies = [
|
|
||||||
"base58",
|
|
||||||
"blake2",
|
|
||||||
"derivative",
|
|
||||||
"either",
|
|
||||||
"frame-metadata 15.1.0",
|
|
||||||
"futures",
|
|
||||||
"getrandom",
|
|
||||||
"hex",
|
|
||||||
"impl-serde",
|
|
||||||
"jsonrpsee",
|
|
||||||
"parity-scale-codec",
|
|
||||||
"primitive-types",
|
|
||||||
"scale-bits",
|
|
||||||
"scale-decode",
|
|
||||||
"scale-encode",
|
|
||||||
"scale-info",
|
|
||||||
"scale-value",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"sp-core-hashing",
|
|
||||||
"subxt-macro",
|
|
||||||
"subxt-metadata",
|
|
||||||
"thiserror",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "subxt-codegen"
|
|
||||||
version = "0.29.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4e2f231d97c145c564bd544212c0cc0c29c09ff516af199f4ce00c8e055f8138"
|
|
||||||
dependencies = [
|
|
||||||
"frame-metadata 15.1.0",
|
|
||||||
"heck",
|
|
||||||
"hex",
|
|
||||||
"jsonrpsee",
|
|
||||||
"parity-scale-codec",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"scale-info",
|
|
||||||
"subxt-metadata",
|
|
||||||
"syn 2.0.39",
|
|
||||||
"thiserror",
|
|
||||||
"tokio",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "subxt-macro"
|
|
||||||
version = "0.29.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e544e41e1c84b616632cd2f86862342868f62e11e4cd9062a9e3dbf5fc871f64"
|
|
||||||
dependencies = [
|
|
||||||
"darling 0.20.3",
|
|
||||||
"proc-macro-error",
|
|
||||||
"subxt-codegen",
|
|
||||||
"syn 2.0.39",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "subxt-metadata"
|
|
||||||
version = "0.29.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a01ce5044c81db3404d38c56f1e69d72eff72c54e5913c9bba4c0b58d376031f"
|
|
||||||
dependencies = [
|
|
||||||
"frame-metadata 15.1.0",
|
|
||||||
"parity-scale-codec",
|
|
||||||
"scale-info",
|
|
||||||
"sp-core-hashing",
|
|
||||||
"thiserror",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.109"
|
version = "1.0.109"
|
||||||
|
@ -9997,9 +9672,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.88"
|
version = "0.2.89"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce"
|
checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"wasm-bindgen-macro",
|
"wasm-bindgen-macro",
|
||||||
|
@ -10007,9 +9682,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-backend"
|
name = "wasm-bindgen-backend"
|
||||||
version = "0.2.88"
|
version = "0.2.89"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217"
|
checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"log",
|
"log",
|
||||||
|
@ -10022,9 +9697,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-futures"
|
name = "wasm-bindgen-futures"
|
||||||
version = "0.4.38"
|
version = "0.4.39"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02"
|
checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
@ -10034,9 +9709,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.88"
|
version = "0.2.89"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2"
|
checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
|
@ -10044,9 +9719,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.88"
|
version = "0.2.89"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907"
|
checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -10057,9 +9732,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.88"
|
version = "0.2.89"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b"
|
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-encoder"
|
name = "wasm-encoder"
|
||||||
|
@ -10374,9 +10049,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webpki-roots"
|
name = "webpki-roots"
|
||||||
version = "0.25.2"
|
version = "0.25.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
|
checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "which"
|
name = "which"
|
||||||
|
@ -10637,12 +10312,6 @@ dependencies = [
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "yap"
|
|
||||||
version = "0.10.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e2a7eb6d82a11e4d0b8e6bda8347169aff4ccd8235d039bba7c47482d977dcf7"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yasna"
|
name = "yasna"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
|
|
|
@ -75,7 +75,7 @@ impl<D: Db> CosignEvaluator<D> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_stakes(&self) -> Result<(), SeraiError> {
|
async fn update_stakes(&self) -> Result<(), SeraiError> {
|
||||||
let serai = self.serai.as_of(self.serai.latest_block_hash().await?);
|
let serai = self.serai.as_of_latest_finalized_block().await?;
|
||||||
|
|
||||||
let mut stakes = HashMap::new();
|
let mut stakes = HashMap::new();
|
||||||
for network in NETWORKS {
|
for network in NETWORKS {
|
||||||
|
@ -112,13 +112,13 @@ impl<D: Db> CosignEvaluator<D> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this an old cosign (older than a day), drop it
|
// If this an old cosign (older than a day), drop it
|
||||||
let latest_block = self.serai.latest_block().await?;
|
let latest_block = self.serai.latest_finalized_block().await?;
|
||||||
if (cosign.block_number + (24 * 60 * 60 / 6)) < latest_block.number() {
|
if (cosign.block_number + (24 * 60 * 60 / 6)) < latest_block.number() {
|
||||||
log::debug!("received old cosign supposedly signed by {:?}", cosign.network);
|
log::debug!("received old cosign supposedly signed by {:?}", cosign.network);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(block) = self.serai.block_by_number(cosign.block_number).await? else {
|
let Some(block) = self.serai.finalized_block_by_number(cosign.block_number).await? else {
|
||||||
log::warn!("received cosign with a block number which doesn't map to a block");
|
log::warn!("received cosign with a block number which doesn't map to a block");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
|
@ -1222,8 +1222,8 @@ async fn main() {
|
||||||
|
|
||||||
let serai = || async {
|
let serai = || async {
|
||||||
loop {
|
loop {
|
||||||
let Ok(serai) = Serai::new(&format!(
|
let Ok(serai) = Serai::new(format!(
|
||||||
"ws://{}:9944",
|
"http://{}:9944",
|
||||||
serai_env::var("SERAI_HOSTNAME").expect("Serai hostname wasn't provided")
|
serai_env::var("SERAI_HOSTNAME").expect("Serai hostname wasn't provided")
|
||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -24,7 +24,6 @@ use serai_db::DbTxn;
|
||||||
|
|
||||||
use processor_messages::SubstrateContext;
|
use processor_messages::SubstrateContext;
|
||||||
|
|
||||||
use futures::stream::StreamExt;
|
|
||||||
use tokio::{sync::mpsc, time::sleep};
|
use tokio::{sync::mpsc, time::sleep};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -81,7 +80,7 @@ async fn handle_new_set<D: Db>(
|
||||||
assert_eq!(block.number(), 0);
|
assert_eq!(block.number(), 0);
|
||||||
// Use the next block's time
|
// Use the next block's time
|
||||||
loop {
|
loop {
|
||||||
let Ok(Some(res)) = serai.block_by_number(1).await else {
|
let Ok(Some(res)) = serai.finalized_block_by_number(1).await else {
|
||||||
sleep(Duration::from_secs(5)).await;
|
sleep(Duration::from_secs(5)).await;
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
@ -340,7 +339,7 @@ async fn handle_new_blocks<D: Db, Pro: Processors>(
|
||||||
next_block: &mut u64,
|
next_block: &mut u64,
|
||||||
) -> Result<(), SeraiError> {
|
) -> Result<(), SeraiError> {
|
||||||
// Check if there's been a new Substrate block
|
// Check if there's been a new Substrate block
|
||||||
let latest_number = serai.latest_block().await?.number();
|
let latest_number = serai.latest_finalized_block().await?.number();
|
||||||
|
|
||||||
// TODO: If this block directly builds off a cosigned block *and* doesn't contain events, mark
|
// TODO: If this block directly builds off a cosigned block *and* doesn't contain events, mark
|
||||||
// cosigned,
|
// cosigned,
|
||||||
|
@ -369,7 +368,7 @@ async fn handle_new_blocks<D: Db, Pro: Processors>(
|
||||||
None => {
|
None => {
|
||||||
let serai = serai.as_of(
|
let serai = serai.as_of(
|
||||||
serai
|
serai
|
||||||
.block_by_number(block)
|
.finalized_block_by_number(block)
|
||||||
.await?
|
.await?
|
||||||
.expect("couldn't get block which should've been finalized")
|
.expect("couldn't get block which should've been finalized")
|
||||||
.hash(),
|
.hash(),
|
||||||
|
@ -432,7 +431,7 @@ async fn handle_new_blocks<D: Db, Pro: Processors>(
|
||||||
skipped_block.map(|skipped_block| skipped_block + COSIGN_DISTANCE);
|
skipped_block.map(|skipped_block| skipped_block + COSIGN_DISTANCE);
|
||||||
for block in (last_intended_to_cosign_block + 1) ..= latest_number {
|
for block in (last_intended_to_cosign_block + 1) ..= latest_number {
|
||||||
let actual_block = serai
|
let actual_block = serai
|
||||||
.block_by_number(block)
|
.finalized_block_by_number(block)
|
||||||
.await?
|
.await?
|
||||||
.expect("couldn't get block which should've been finalized");
|
.expect("couldn't get block which should've been finalized");
|
||||||
SeraiBlockNumber::set(&mut txn, actual_block.hash(), &block);
|
SeraiBlockNumber::set(&mut txn, actual_block.hash(), &block);
|
||||||
|
@ -535,7 +534,7 @@ async fn handle_new_blocks<D: Db, Pro: Processors>(
|
||||||
processors,
|
processors,
|
||||||
serai,
|
serai,
|
||||||
serai
|
serai
|
||||||
.block_by_number(b)
|
.finalized_block_by_number(b)
|
||||||
.await?
|
.await?
|
||||||
.expect("couldn't get block before the latest finalized block"),
|
.expect("couldn't get block before the latest finalized block"),
|
||||||
)
|
)
|
||||||
|
@ -561,6 +560,7 @@ pub async fn scan_task<D: Db, Pro: Processors>(
|
||||||
let mut db = SubstrateDb::new(db);
|
let mut db = SubstrateDb::new(db);
|
||||||
let mut next_substrate_block = db.next_block();
|
let mut next_substrate_block = db.next_block();
|
||||||
|
|
||||||
|
/*
|
||||||
let new_substrate_block_notifier = {
|
let new_substrate_block_notifier = {
|
||||||
let serai = &serai;
|
let serai = &serai;
|
||||||
move || async move {
|
move || async move {
|
||||||
|
@ -575,31 +575,55 @@ pub async fn scan_task<D: Db, Pro: Processors>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut substrate_block_notifier = new_substrate_block_notifier().await;
|
*/
|
||||||
|
// TODO: Restore the above subscription-based system
|
||||||
|
let new_substrate_block_notifier = {
|
||||||
|
let serai = &serai;
|
||||||
|
move |next_substrate_block| async move {
|
||||||
|
loop {
|
||||||
|
match serai.latest_finalized_block().await {
|
||||||
|
Ok(latest) => {
|
||||||
|
if latest.header().number >= next_substrate_block {
|
||||||
|
return latest;
|
||||||
|
} else {
|
||||||
|
sleep(Duration::from_secs(3)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("couldn't communicate with serai node: {e}");
|
||||||
|
sleep(Duration::from_secs(5)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// await the next block, yet if our notifier had an error, re-create it
|
// await the next block, yet if our notifier had an error, re-create it
|
||||||
{
|
{
|
||||||
let Ok(next_block) =
|
let Ok(_) = tokio::time::timeout(
|
||||||
tokio::time::timeout(Duration::from_secs(60), substrate_block_notifier.next()).await
|
Duration::from_secs(60),
|
||||||
|
new_substrate_block_notifier(next_substrate_block),
|
||||||
|
)
|
||||||
|
.await
|
||||||
else {
|
else {
|
||||||
// Timed out, which may be because Serai isn't finalizing or may be some issue with the
|
// Timed out, which may be because Serai isn't finalizing or may be some issue with the
|
||||||
// notifier
|
// notifier
|
||||||
if serai.latest_block().await.map(|block| block.number()).ok() ==
|
if serai.latest_finalized_block().await.map(|block| block.number()).ok() ==
|
||||||
Some(next_substrate_block.saturating_sub(1))
|
Some(next_substrate_block.saturating_sub(1))
|
||||||
{
|
{
|
||||||
log::info!("serai hasn't finalized a block in the last 60s...");
|
log::info!("serai hasn't finalized a block in the last 60s...");
|
||||||
} else {
|
|
||||||
substrate_block_notifier = new_substrate_block_notifier().await;
|
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
// next_block is a Option<Result>
|
// next_block is a Option<Result>
|
||||||
if next_block.and_then(Result::ok).is_none() {
|
if next_block.and_then(Result::ok).is_none() {
|
||||||
substrate_block_notifier = new_substrate_block_notifier().await;
|
substrate_block_notifier = new_substrate_block_notifier(next_substrate_block);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
match handle_new_blocks(
|
match handle_new_blocks(
|
||||||
|
@ -632,12 +656,10 @@ pub(crate) async fn get_expected_next_batch(serai: &Serai, network: NetworkId) -
|
||||||
}
|
}
|
||||||
first = false;
|
first = false;
|
||||||
|
|
||||||
let Ok(latest_block) = serai.latest_block().await else {
|
let Ok(serai) = serai.as_of_latest_finalized_block().await else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let Ok(last) =
|
let Ok(last) = serai.in_instructions().last_batch_for_network(network).await else {
|
||||||
serai.as_of(latest_block.hash()).in_instructions().last_batch_for_network(network).await
|
|
||||||
else {
|
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
break if let Some(last) = last { last + 1 } else { 0 };
|
break if let Some(last) = last { last + 1 } else { 0 };
|
||||||
|
|
|
@ -321,13 +321,22 @@ async fn dkg_test() {
|
||||||
async move {
|
async move {
|
||||||
// Version, Pallet, Call, Network, Key Pair, Signature
|
// Version, Pallet, Call, Network, Key Pair, Signature
|
||||||
let expected_len = 1 + 1 + 1 + 1 + 32 + 1 + key_pair.1.len() + 64;
|
let expected_len = 1 + 1 + 1 + 1 + 32 + 1 + key_pair.1.len() + 64;
|
||||||
assert_eq!(tx.len(), expected_len);
|
// It's length prefixed
|
||||||
|
assert_eq!(tx.len(), 2 + expected_len);
|
||||||
|
let expected_len = u16::try_from(expected_len).unwrap();
|
||||||
|
|
||||||
|
// Check the encoded length
|
||||||
|
// This is the compact encoding from SCALE, specifically the two-byte length encoding case
|
||||||
|
let bottom_six = expected_len & 0b111111;
|
||||||
|
let upper_eight = expected_len >> 6;
|
||||||
|
assert_eq!(u8::try_from((bottom_six << 2) | 1).unwrap(), tx[0]);
|
||||||
|
assert_eq!(u8::try_from(upper_eight).unwrap(), tx[1]);
|
||||||
|
|
||||||
// Version
|
// Version
|
||||||
assert_eq!(tx[0], 4);
|
assert_eq!(tx[2], 4);
|
||||||
|
|
||||||
// Call
|
// Call
|
||||||
let tx = serai_client::runtime::RuntimeCall::decode(&mut &tx[1 ..]).unwrap();
|
let tx = serai_client::runtime::RuntimeCall::decode(&mut &tx[3 ..]).unwrap();
|
||||||
match tx {
|
match tx {
|
||||||
serai_client::runtime::RuntimeCall::ValidatorSets(
|
serai_client::runtime::RuntimeCall::ValidatorSets(
|
||||||
serai_client::runtime::validator_sets::Call::set_keys {
|
serai_client::runtime::validator_sets::Call::set_keys {
|
||||||
|
|
|
@ -240,7 +240,7 @@ pub(crate) async fn scan_tributaries_task<
|
||||||
// creation
|
// creation
|
||||||
// TODO2: Differentiate connection errors from invariants
|
// TODO2: Differentiate connection errors from invariants
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if let Ok(serai) = serai.with_current_latest_block().await {
|
if let Ok(serai) = serai.as_of_latest_finalized_block().await {
|
||||||
let serai = serai.validator_sets();
|
let serai = serai.validator_sets();
|
||||||
// Check if this failed because the keys were already set by someone
|
// Check if this failed because the keys were already set by someone
|
||||||
// else
|
// else
|
||||||
|
|
|
@ -17,17 +17,15 @@ rustdoc-args = ["--cfg", "docsrs"]
|
||||||
zeroize = "^1.5"
|
zeroize = "^1.5"
|
||||||
thiserror = { version = "1", optional = true }
|
thiserror = { version = "1", optional = true }
|
||||||
|
|
||||||
futures = "0.3"
|
|
||||||
|
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
scale = { package = "parity-scale-codec", version = "3" }
|
scale = { package = "parity-scale-codec", version = "3" }
|
||||||
scale-info = { version = "2", optional = true }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde_json = "1"
|
||||||
|
|
||||||
sp-core = { git = "https://github.com/serai-dex/substrate" }
|
sp-core = { git = "https://github.com/serai-dex/substrate" }
|
||||||
sp-runtime = { git = "https://github.com/serai-dex/substrate" }
|
sp-runtime = { git = "https://github.com/serai-dex/substrate" }
|
||||||
serai-runtime = { path = "../runtime", version = "0.1" }
|
serai-runtime = { path = "../runtime", version = "0.1" }
|
||||||
|
simple-request = { path = "../../common/request", version = "0.1" }
|
||||||
subxt = { version = "0.29", default-features = false, features = ["jsonrpsee-ws"], optional = true }
|
|
||||||
|
|
||||||
bitcoin = { version = "0.31", optional = true }
|
bitcoin = { version = "0.31", optional = true }
|
||||||
|
|
||||||
|
@ -50,7 +48,7 @@ dockertest = "0.4"
|
||||||
serai-docker-tests = { path = "../../tests/docker" }
|
serai-docker-tests = { path = "../../tests/docker" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
serai = ["thiserror", "scale-info", "subxt"]
|
serai = ["thiserror"]
|
||||||
|
|
||||||
networks = []
|
networks = []
|
||||||
bitcoin = ["networks", "dep:bitcoin"]
|
bitcoin = ["networks", "dep:bitcoin"]
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
|
use scale::Encode;
|
||||||
|
|
||||||
use serai_runtime::{
|
use serai_runtime::{
|
||||||
primitives::{SeraiAddress, SubstrateAmount, Amount, Coin, Balance},
|
primitives::{SeraiAddress, Amount, Coin, Balance},
|
||||||
coins, Coins, Runtime,
|
coins, Runtime,
|
||||||
};
|
};
|
||||||
pub use coins::primitives;
|
pub use coins::primitives;
|
||||||
use primitives::OutInstructionWithBalance;
|
use primitives::OutInstructionWithBalance;
|
||||||
|
|
||||||
use crate::{TemporalSerai, SeraiError, scale_value};
|
use crate::{TemporalSerai, SeraiError};
|
||||||
|
|
||||||
const PALLET: &str = "Coins";
|
const PALLET: &str = "Coins";
|
||||||
|
|
||||||
|
@ -19,21 +21,33 @@ impl<'a> SeraiCoins<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn mint_events(&self) -> Result<Vec<CoinsEvent>, SeraiError> {
|
pub async fn mint_events(&self) -> Result<Vec<CoinsEvent>, SeraiError> {
|
||||||
self.0.events::<Coins, _>(|event| matches!(event, CoinsEvent::Mint { .. })).await
|
self
|
||||||
|
.0
|
||||||
|
.events(|event| {
|
||||||
|
if let serai_runtime::RuntimeEvent::Coins(event) = event {
|
||||||
|
Some(event).filter(|event| matches!(event, CoinsEvent::Mint { .. }))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn burn_with_instruction_events(&self) -> Result<Vec<CoinsEvent>, SeraiError> {
|
pub async fn burn_with_instruction_events(&self) -> Result<Vec<CoinsEvent>, SeraiError> {
|
||||||
self.0.events::<Coins, _>(|event| matches!(event, CoinsEvent::BurnWithInstruction { .. })).await
|
self
|
||||||
|
.0
|
||||||
|
.events(|event| {
|
||||||
|
if let serai_runtime::RuntimeEvent::Coins(event) = event {
|
||||||
|
Some(event).filter(|event| matches!(event, CoinsEvent::BurnWithInstruction { .. }))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn coin_supply(&self, coin: Coin) -> Result<Amount, SeraiError> {
|
pub async fn coin_supply(&self, coin: Coin) -> Result<Amount, SeraiError> {
|
||||||
Ok(Amount(
|
Ok(self.0.storage(PALLET, "Supply", coin).await?.unwrap_or(Amount(0)))
|
||||||
self
|
|
||||||
.0
|
|
||||||
.storage::<SubstrateAmount>(PALLET, "Supply", Some(vec![scale_value(coin)]))
|
|
||||||
.await?
|
|
||||||
.unwrap_or(0),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn coin_balance(
|
pub async fn coin_balance(
|
||||||
|
@ -41,17 +55,17 @@ impl<'a> SeraiCoins<'a> {
|
||||||
coin: Coin,
|
coin: Coin,
|
||||||
address: SeraiAddress,
|
address: SeraiAddress,
|
||||||
) -> Result<Amount, SeraiError> {
|
) -> Result<Amount, SeraiError> {
|
||||||
Ok(Amount(
|
Ok(
|
||||||
self
|
self
|
||||||
.0
|
.0
|
||||||
.storage::<SubstrateAmount>(
|
.storage(
|
||||||
PALLET,
|
PALLET,
|
||||||
"Balances",
|
"Balances",
|
||||||
Some(vec![scale_value(address), scale_value(coin)]),
|
(sp_core::hashing::blake2_128(&address.encode()), &address.0, coin),
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
.unwrap_or(0),
|
.unwrap_or(Amount(0)),
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transfer(to: SeraiAddress, balance: Balance) -> serai_runtime::RuntimeCall {
|
pub fn transfer(to: SeraiAddress, balance: Balance) -> serai_runtime::RuntimeCall {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use sp_core::bounded_vec::BoundedVec;
|
use sp_core::bounded_vec::BoundedVec;
|
||||||
use serai_runtime::{
|
use serai_runtime::{
|
||||||
primitives::{SeraiAddress, Amount, Coin},
|
primitives::{SeraiAddress, Amount, Coin},
|
||||||
dex, Dex, Runtime,
|
dex, Runtime,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{SeraiError, TemporalSerai};
|
use crate::{SeraiError, TemporalSerai};
|
||||||
|
@ -11,8 +11,19 @@ pub type DexEvent = dex::Event<Runtime>;
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct SeraiDex<'a>(pub(crate) TemporalSerai<'a>);
|
pub struct SeraiDex<'a>(pub(crate) TemporalSerai<'a>);
|
||||||
impl<'a> SeraiDex<'a> {
|
impl<'a> SeraiDex<'a> {
|
||||||
pub async fn all_events(&self) -> Result<Vec<DexEvent>, SeraiError> {
|
pub async fn events(&self) -> Result<Vec<DexEvent>, SeraiError> {
|
||||||
self.0.events::<Dex, _>(|_| true).await
|
self
|
||||||
|
.0
|
||||||
|
.events(
|
||||||
|
|event| {
|
||||||
|
if let serai_runtime::RuntimeEvent::Dex(event) = event {
|
||||||
|
Some(event)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_liquidity(
|
pub fn add_liquidity(
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use serai_runtime::{in_instructions, InInstructions, Runtime};
|
use serai_runtime::{in_instructions, Runtime};
|
||||||
pub use in_instructions::primitives;
|
pub use in_instructions::primitives;
|
||||||
use primitives::SignedBatch;
|
use primitives::SignedBatch;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
primitives::{BlockHash, NetworkId},
|
primitives::{BlockHash, NetworkId},
|
||||||
SeraiError, Serai, TemporalSerai, scale_value,
|
SeraiError, Serai, TemporalSerai,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type InInstructionsEvent = in_instructions::Event<Runtime>;
|
pub type InInstructionsEvent = in_instructions::Event<Runtime>;
|
||||||
|
@ -22,20 +22,26 @@ impl<'a> SeraiInInstructions<'a> {
|
||||||
&self,
|
&self,
|
||||||
network: NetworkId,
|
network: NetworkId,
|
||||||
) -> Result<Option<BlockHash>, SeraiError> {
|
) -> Result<Option<BlockHash>, SeraiError> {
|
||||||
self.0.storage(PALLET, "LatestNetworkBlock", Some(vec![scale_value(network)])).await
|
self.0.storage(PALLET, "LatestNetworkBlock", network).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn last_batch_for_network(
|
pub async fn last_batch_for_network(
|
||||||
&self,
|
&self,
|
||||||
network: NetworkId,
|
network: NetworkId,
|
||||||
) -> Result<Option<u32>, SeraiError> {
|
) -> Result<Option<u32>, SeraiError> {
|
||||||
self.0.storage(PALLET, "LastBatch", Some(vec![scale_value(network)])).await
|
self.0.storage(PALLET, "LastBatch", network).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn batch_events(&self) -> Result<Vec<InInstructionsEvent>, SeraiError> {
|
pub async fn batch_events(&self) -> Result<Vec<InInstructionsEvent>, SeraiError> {
|
||||||
self
|
self
|
||||||
.0
|
.0
|
||||||
.events::<InInstructions, _>(|event| matches!(event, InInstructionsEvent::Batch { .. }))
|
.events(|event| {
|
||||||
|
if let serai_runtime::RuntimeEvent::InInstructions(event) = event {
|
||||||
|
Some(event).filter(|event| matches!(event, InInstructionsEvent::Batch { .. }))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,36 +1,20 @@
|
||||||
use core::ops::Deref;
|
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use futures::stream::{Stream, StreamExt};
|
use simple_request::{hyper, Request, Client};
|
||||||
|
|
||||||
use scale::{Encode, Decode, Compact};
|
use scale::{Encode, Decode, Compact};
|
||||||
mod scale_value;
|
use serde::{Serialize, Deserialize, de::DeserializeOwned};
|
||||||
pub(crate) use scale_value::{Value, scale_value};
|
|
||||||
|
|
||||||
pub use sp_core::{
|
pub use sp_core::{
|
||||||
Pair as PairTrait,
|
Pair as PairTrait,
|
||||||
sr25519::{Public, Pair},
|
sr25519::{Public, Pair},
|
||||||
};
|
};
|
||||||
|
|
||||||
use subxt::{
|
|
||||||
error::Error as SubxtError,
|
|
||||||
config::{
|
|
||||||
Header as HeaderTrait,
|
|
||||||
substrate::{BlakeTwo256, SubstrateHeader},
|
|
||||||
extrinsic_params::BaseExtrinsicParams,
|
|
||||||
},
|
|
||||||
rpc::types::{ChainBlock, ChainBlockExtrinsic},
|
|
||||||
Config as SubxtConfig, OnlineClient,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub use serai_runtime::primitives;
|
pub use serai_runtime::primitives;
|
||||||
pub use primitives::{SeraiAddress, Signature, Amount};
|
pub use primitives::{SeraiAddress, Signature, Amount};
|
||||||
|
|
||||||
pub use serai_runtime as runtime;
|
pub use serai_runtime as runtime;
|
||||||
use serai_runtime::{
|
use serai_runtime::{Header, Block as SeraiBlock};
|
||||||
system::Config, support::traits::PalletInfo as PalletInfoTrait, PalletInfo, Runtime,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub mod coins;
|
pub mod coins;
|
||||||
pub use coins::SeraiCoins;
|
pub use coins::SeraiCoins;
|
||||||
|
@ -41,42 +25,11 @@ pub use in_instructions::SeraiInInstructions;
|
||||||
pub mod validator_sets;
|
pub mod validator_sets;
|
||||||
pub use validator_sets::SeraiValidatorSets;
|
pub use validator_sets::SeraiValidatorSets;
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Default, Debug, Encode, Decode)]
|
pub type Transaction = serai_runtime::UncheckedExtrinsic;
|
||||||
pub struct Tip {
|
|
||||||
#[codec(compact)]
|
|
||||||
pub tip: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type Header = SubstrateHeader<serai_runtime::BlockNumber, BlakeTwo256>;
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Block(SeraiBlock);
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
|
||||||
pub struct SeraiConfig;
|
|
||||||
impl SubxtConfig for SeraiConfig {
|
|
||||||
type Hash = <Runtime as Config>::Hash;
|
|
||||||
type Hasher = BlakeTwo256;
|
|
||||||
|
|
||||||
type Index = serai_runtime::Nonce;
|
|
||||||
type AccountId = <Runtime as Config>::AccountId;
|
|
||||||
// TODO: Bech32m
|
|
||||||
type Address = SeraiAddress;
|
|
||||||
|
|
||||||
type Header = Header;
|
|
||||||
type Signature = Signature;
|
|
||||||
|
|
||||||
type ExtrinsicParams = BaseExtrinsicParams<SeraiConfig, Tip>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Block(ChainBlock<SeraiConfig>);
|
|
||||||
impl Block {
|
impl Block {
|
||||||
fn new(block: ChainBlock<SeraiConfig>) -> Result<Block, SeraiError> {
|
|
||||||
for extrinsic in &block.extrinsics {
|
|
||||||
if extrinsic.0.len() < 3 {
|
|
||||||
Err(SeraiError::InvalidNode)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(Block(block))
|
|
||||||
}
|
|
||||||
pub fn hash(&self) -> [u8; 32] {
|
pub fn hash(&self) -> [u8; 32] {
|
||||||
self.0.header.hash().into()
|
self.0.header.hash().into()
|
||||||
}
|
}
|
||||||
|
@ -87,74 +40,134 @@ impl Block {
|
||||||
/// Returns the time of this block, set by its producer, in milliseconds since the epoch.
|
/// Returns the time of this block, set by its producer, in milliseconds since the epoch.
|
||||||
pub fn time(&self) -> Result<u64, SeraiError> {
|
pub fn time(&self) -> Result<u64, SeraiError> {
|
||||||
for extrinsic in &self.0.extrinsics {
|
for extrinsic in &self.0.extrinsics {
|
||||||
// Inherent/unsigned
|
if let serai_runtime::RuntimeCall::Timestamp(serai_runtime::timestamp::Call::set { now }) =
|
||||||
let inherent = (extrinsic.0[0] >> 7) == 0;
|
&extrinsic.function
|
||||||
|
{
|
||||||
// To timestamp pallet
|
return Ok(*now);
|
||||||
use serai_runtime::Timestamp;
|
|
||||||
let timestamp =
|
|
||||||
extrinsic.0[1] == u8::try_from(PalletInfo::index::<Timestamp>().unwrap()).unwrap();
|
|
||||||
|
|
||||||
// set call
|
|
||||||
let set = extrinsic.0[2] == 0;
|
|
||||||
|
|
||||||
if inherent && timestamp && set {
|
|
||||||
if extrinsic.0.len() < 4 {
|
|
||||||
Err(SeraiError::InvalidNode)?;
|
|
||||||
}
|
|
||||||
return Ok(
|
|
||||||
Compact::<u64>::decode(&mut &extrinsic.0[3 ..]).map_err(|_| SeraiError::InvalidNode)?.0,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(SeraiError::InvalidNode)
|
Err(SeraiError::InvalidNode("no time was present in block".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn header(&self) -> &Header {
|
pub fn header(&self) -> &Header {
|
||||||
&self.0.header
|
&self.0.header
|
||||||
}
|
}
|
||||||
pub fn transactions(&self) -> &[ChainBlockExtrinsic] {
|
pub fn transactions(&self) -> &[Transaction] {
|
||||||
&self.0.extrinsics
|
&self.0.extrinsics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for Block {
|
|
||||||
fn clone(&self) -> Block {
|
|
||||||
Block(ChainBlock::<SeraiConfig> {
|
|
||||||
header: self.0.header.clone(),
|
|
||||||
extrinsics: self.0.extrinsics.clone(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum SeraiError {
|
pub enum SeraiError {
|
||||||
#[error("failed to communicate with serai: {0}")]
|
#[error("failed to communicate with serai")]
|
||||||
RpcError(SubxtError),
|
ConnectionError,
|
||||||
#[error("serai-client library was intended for a different runtime version")]
|
#[error("node is faulty: {0}")]
|
||||||
InvalidRuntime,
|
InvalidNode(String),
|
||||||
#[error("node is faulty")]
|
#[error("error in response: {0}")]
|
||||||
InvalidNode,
|
ErrorInResponse(String),
|
||||||
|
#[error("serai-client library was intended for a different runtime version: {0}")]
|
||||||
|
InvalidRuntime(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Serai(OnlineClient<SeraiConfig>);
|
pub struct Serai {
|
||||||
|
url: String,
|
||||||
|
client: Client,
|
||||||
|
genesis: [u8; 32],
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct TemporalSerai<'a>(pub(crate) &'a Serai, pub(crate) [u8; 32]);
|
pub struct TemporalSerai<'a>(pub(crate) &'a Serai, pub(crate) [u8; 32]);
|
||||||
|
|
||||||
impl Serai {
|
impl Serai {
|
||||||
pub async fn new(url: &str) -> Result<Self, SeraiError> {
|
pub async fn call<Req: Serialize, Res: DeserializeOwned>(
|
||||||
Ok(Serai(OnlineClient::<SeraiConfig>::from_url(url).await.map_err(SeraiError::RpcError)?))
|
&self,
|
||||||
|
method: &str,
|
||||||
|
params: Req,
|
||||||
|
) -> Result<Res, SeraiError> {
|
||||||
|
let request = Request::from(
|
||||||
|
hyper::Request::post(&self.url)
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.body(
|
||||||
|
serde_json::to_vec(
|
||||||
|
&serde_json::json!({ "jsonrpc": "2.0", "id": 1, "method": method, "params": params }),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct Error {
|
||||||
|
message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
enum RpcResponse<T> {
|
||||||
|
Ok { result: T },
|
||||||
|
Err { error: Error },
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut res = self
|
||||||
|
.client
|
||||||
|
.request(request)
|
||||||
|
.await
|
||||||
|
.map_err(|_| SeraiError::ConnectionError)?
|
||||||
|
.body()
|
||||||
|
.await
|
||||||
|
.map_err(|_| SeraiError::ConnectionError)?;
|
||||||
|
|
||||||
|
let res: RpcResponse<Res> = serde_json::from_reader(&mut res).map_err(|e| {
|
||||||
|
SeraiError::InvalidRuntime(format!(
|
||||||
|
"response was a different type than expected: {:?}",
|
||||||
|
e.classify()
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
match res {
|
||||||
|
RpcResponse::Ok { result } => Ok(result),
|
||||||
|
RpcResponse::Err { error } => Err(SeraiError::ErrorInResponse(error.message)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hex_decode(str: String) -> Result<Vec<u8>, SeraiError> {
|
||||||
|
(if let Some(stripped) = str.strip_prefix("0x") {
|
||||||
|
hex::decode(stripped)
|
||||||
|
} else {
|
||||||
|
hex::decode(str)
|
||||||
|
})
|
||||||
|
.map_err(|_| SeraiError::InvalidNode("expected hex from node wasn't hex".to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn block_hash(&self, number: u64) -> Result<Option<[u8; 32]>, SeraiError> {
|
||||||
|
let hash: Option<String> = self.call("chain_getBlockHash", [number]).await?;
|
||||||
|
let Some(hash) = hash else { return Ok(None) };
|
||||||
|
Self::hex_decode(hash)?
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| SeraiError::InvalidNode("didn't respond to getBlockHash with hash".to_string()))
|
||||||
|
.map(Some)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn new(url: String) -> Result<Self, SeraiError> {
|
||||||
|
let client = Client::with_connection_pool();
|
||||||
|
let mut res = Serai { url, client, genesis: [0xfe; 32] };
|
||||||
|
res.genesis = res.block_hash(0).await?.ok_or_else(|| {
|
||||||
|
SeraiError::InvalidNode("node didn't have the first block's hash".to_string())
|
||||||
|
})?;
|
||||||
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unsigned(call: &serai_runtime::RuntimeCall) -> Vec<u8> {
|
fn unsigned(call: &serai_runtime::RuntimeCall) -> Vec<u8> {
|
||||||
// TODO: Should Serai purge the old transaction code AND set this to 0/1?
|
// TODO: Should Serai purge the old transaction code AND set this to 0/1?
|
||||||
const EXTRINSIC_FORMAT_VERSION: u8 = 4;
|
const EXTRINSIC_FORMAT_VERSION: u8 = 4;
|
||||||
|
|
||||||
let mut bytes = vec![EXTRINSIC_FORMAT_VERSION];
|
let mut tx = vec![EXTRINSIC_FORMAT_VERSION];
|
||||||
bytes.extend(call.encode());
|
tx.extend(call.encode());
|
||||||
bytes
|
|
||||||
|
let mut length_prefixed = Compact(u32::try_from(tx.len()).unwrap()).encode();
|
||||||
|
length_prefixed.extend(tx);
|
||||||
|
length_prefixed
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sign(
|
pub fn sign(
|
||||||
|
@ -162,15 +175,15 @@ impl Serai {
|
||||||
signer: &Pair,
|
signer: &Pair,
|
||||||
call: &serai_runtime::RuntimeCall,
|
call: &serai_runtime::RuntimeCall,
|
||||||
nonce: u32,
|
nonce: u32,
|
||||||
tip: Tip,
|
tip: u64,
|
||||||
) -> Vec<u8> {
|
) -> Vec<u8> {
|
||||||
const SPEC_VERSION: u32 = 1;
|
const SPEC_VERSION: u32 = 1;
|
||||||
const TX_VERSION: u32 = 1;
|
const TX_VERSION: u32 = 1;
|
||||||
const EXTRINSIC_FORMAT_VERSION: u8 = 4;
|
const EXTRINSIC_FORMAT_VERSION: u8 = 4;
|
||||||
|
|
||||||
let era = sp_runtime::generic::Era::Immortal;
|
let era = sp_runtime::generic::Era::Immortal;
|
||||||
let extra = (era, Compact(nonce), tip);
|
let extra = (era, Compact(nonce), Compact(tip));
|
||||||
let genesis = self.0.genesis_hash();
|
let genesis = self.genesis;
|
||||||
let mortality_checkpoint = genesis;
|
let mortality_checkpoint = genesis;
|
||||||
let mut signature_payload =
|
let mut signature_payload =
|
||||||
(call, extra, SPEC_VERSION, TX_VERSION, genesis, mortality_checkpoint).encode();
|
(call, extra, SPEC_VERSION, TX_VERSION, genesis, mortality_checkpoint).encode();
|
||||||
|
@ -180,115 +193,104 @@ impl Serai {
|
||||||
let signature = signer.sign(&signature_payload);
|
let signature = signer.sign(&signature_payload);
|
||||||
|
|
||||||
let signed = 1 << 7;
|
let signed = 1 << 7;
|
||||||
(signed + EXTRINSIC_FORMAT_VERSION, signer.public(), signature, extra, call).encode()
|
let tx = (signed + EXTRINSIC_FORMAT_VERSION, signer.public(), signature, extra, call).encode();
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn publish(&self, tx: &[u8]) -> Result<(), SeraiError> {
|
|
||||||
let mut length_prefixed = Compact(u32::try_from(tx.len()).unwrap()).encode();
|
let mut length_prefixed = Compact(u32::try_from(tx.len()).unwrap()).encode();
|
||||||
length_prefixed.extend(tx);
|
length_prefixed.extend(tx);
|
||||||
self
|
length_prefixed
|
||||||
.0
|
}
|
||||||
.rpc()
|
|
||||||
.deref()
|
// TODO: Move this to take in Transaction
|
||||||
.request::<String>(
|
pub async fn publish(&self, tx: &[u8]) -> Result<(), SeraiError> {
|
||||||
"author_submitExtrinsic",
|
// Drop the returned hash, which is the hash of the raw extrinsic, as extrinsics are allowed
|
||||||
subxt::rpc::rpc_params![hex::encode(length_prefixed)],
|
// to share hashes and this hash is accordingly useless/unsafe
|
||||||
)
|
|
||||||
.await
|
|
||||||
// Drop the hash, which is the hash of the raw extrinsic, as extrinsics are allowed to share
|
|
||||||
// hashes and this hash is accordingly useless/unsafe
|
|
||||||
// If we are to return something, it should be block included in and position within block
|
// If we are to return something, it should be block included in and position within block
|
||||||
.map(|_| ())
|
let _: String = self.call("author_submitExtrinsic", [hex::encode(tx)]).await?;
|
||||||
.map_err(SeraiError::RpcError)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn latest_block_hash(&self) -> Result<[u8; 32], SeraiError> {
|
pub async fn latest_finalized_block_hash(&self) -> Result<[u8; 32], SeraiError> {
|
||||||
Ok(self.0.rpc().finalized_head().await.map_err(SeraiError::RpcError)?.into())
|
let hash: String = self.call("chain_getFinalizedHead", ()).await?;
|
||||||
|
Self::hex_decode(hash)?.try_into().map_err(|_| {
|
||||||
|
SeraiError::InvalidNode("didn't respond to getFinalizedHead with hash".to_string())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn latest_block(&self) -> Result<Block, SeraiError> {
|
pub async fn header(&self, hash: [u8; 32]) -> Result<Option<Header>, SeraiError> {
|
||||||
Block::new(
|
self.call("chain_getHeader", [hex::encode(hash)]).await
|
||||||
self
|
}
|
||||||
.0
|
|
||||||
.rpc()
|
pub async fn block(&self, hash: [u8; 32]) -> Result<Option<Block>, SeraiError> {
|
||||||
.block(Some(self.0.rpc().finalized_head().await.map_err(SeraiError::RpcError)?))
|
// TODO: Remove this wrapping from Serai?
|
||||||
.await
|
#[derive(Deserialize)]
|
||||||
.map_err(SeraiError::RpcError)?
|
struct WrappedBlock {
|
||||||
.ok_or(SeraiError::InvalidNode)?
|
block: SeraiBlock,
|
||||||
.block,
|
}
|
||||||
)
|
let block: Option<WrappedBlock> = self.call("chain_getBlock", [hex::encode(hash)]).await?;
|
||||||
|
let Some(block) = block else { return Ok(None) };
|
||||||
|
Ok(Some(Block(block.block)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn latest_finalized_block(&self) -> Result<Block, SeraiError> {
|
||||||
|
let latest = self.latest_finalized_block_hash().await?;
|
||||||
|
let Some(block) = self.block(latest).await? else {
|
||||||
|
Err(SeraiError::InvalidNode("node didn't have a latest block".to_string()))?
|
||||||
|
};
|
||||||
|
Ok(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
// There is no provided method for this
|
// There is no provided method for this
|
||||||
// TODO: Add one to Serai
|
// TODO: Add one to Serai
|
||||||
pub async fn is_finalized(&self, header: &Header) -> Result<Option<bool>, SeraiError> {
|
pub async fn is_finalized(&self, header: &Header) -> Result<bool, SeraiError> {
|
||||||
// Get the latest finalized block
|
// Get the latest finalized block
|
||||||
let finalized = self.latest_block_hash().await?.into();
|
let finalized = self.latest_finalized_block_hash().await?;
|
||||||
// If the latest finalized block is this block, return true
|
// If the latest finalized block is this block, return true
|
||||||
if finalized == header.hash() {
|
if finalized == header.hash().as_ref() {
|
||||||
return Ok(Some(true));
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(finalized) =
|
let Some(finalized) = self.header(finalized).await? else {
|
||||||
self.0.rpc().header(Some(finalized)).await.map_err(SeraiError::RpcError)?
|
Err(SeraiError::InvalidNode("couldn't get finalized header".to_string()))?
|
||||||
else {
|
|
||||||
return Ok(None);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the finalized block has a lower number, this block can't be finalized
|
// If the finalized block has a lower number, this block can't be finalized
|
||||||
if finalized.number() < header.number() {
|
if finalized.number < header.number {
|
||||||
return Ok(Some(false));
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This block, if finalized, comes before the finalized block
|
// This block, if finalized, comes before the finalized block
|
||||||
// If we request the hash of this block's number, Substrate will return the hash on the main
|
// If we request the hash of this block's number, Substrate will return the hash on the main
|
||||||
// chain
|
// chain
|
||||||
// If that hash is this hash, this block is finalized
|
// If that hash is this hash, this block is finalized
|
||||||
let Some(hash) =
|
let Some(hash) = self.block_hash(header.number).await? else {
|
||||||
self.0.rpc().block_hash(Some(header.number().into())).await.map_err(SeraiError::RpcError)?
|
// This is an error since there is a finalized block at this index
|
||||||
else {
|
Err(SeraiError::InvalidNode(
|
||||||
// This is an error since there is a block at this index
|
"couldn't get block hash for a block number below the finalized block".to_string(),
|
||||||
Err(SeraiError::InvalidNode)?
|
))?
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Some(header.hash() == hash))
|
Ok(header.hash().as_ref() == hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn block(&self, hash: [u8; 32]) -> Result<Option<Block>, SeraiError> {
|
pub async fn finalized_block_by_number(&self, number: u64) -> Result<Option<Block>, SeraiError> {
|
||||||
let Some(res) = self.0.rpc().block(Some(hash.into())).await.map_err(SeraiError::RpcError)?
|
let hash = self.block_hash(number).await?;
|
||||||
else {
|
let Some(hash) = hash else { return Ok(None) };
|
||||||
return Ok(None);
|
let Some(block) = self.block(hash).await? else { return Ok(None) };
|
||||||
};
|
if !self.is_finalized(&block.0.header).await? {
|
||||||
|
|
||||||
// Only return finalized blocks
|
|
||||||
if self.is_finalized(&res.block.header).await? != Some(true) {
|
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
Ok(Some(block))
|
||||||
Ok(Some(Block::new(res.block)?))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ideally, this would be block_hash, not block_by_number
|
|
||||||
// Unfortunately, in order to only operate over only finalized data, we have to check the
|
|
||||||
// returned hash is for a finalized block. We can only do that by calling the extensive
|
|
||||||
// is_finalized method, which at least requires the header
|
|
||||||
// In practice, the block is likely more useful than the header
|
|
||||||
pub async fn block_by_number(&self, number: u64) -> Result<Option<Block>, SeraiError> {
|
|
||||||
let Some(hash) =
|
|
||||||
self.0.rpc().block_hash(Some(number.into())).await.map_err(SeraiError::RpcError)?
|
|
||||||
else {
|
|
||||||
return Ok(None);
|
|
||||||
};
|
|
||||||
self.block(hash.into()).await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/// A stream which yields whenever new block(s) have been finalized.
|
/// A stream which yields whenever new block(s) have been finalized.
|
||||||
pub async fn newly_finalized_block(
|
pub async fn newly_finalized_block(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<impl Stream<Item = Result<(), SeraiError>>, SeraiError> {
|
) -> Result<impl Stream<Item = Result<(), SeraiError>>, SeraiError> {
|
||||||
Ok(self.0.rpc().subscribe_finalized_block_headers().await.map_err(SeraiError::RpcError)?.map(
|
Ok(self.0.rpc().subscribe_finalized_block_headers().await
|
||||||
|
.map_err(|_| SeraiError::ConnectionError)?.map(
|
||||||
|next| {
|
|next| {
|
||||||
next.map_err(SeraiError::RpcError)?;
|
next.map_err(|_| SeraiError::ConnectionError)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
@ -300,12 +302,16 @@ impl Serai {
|
||||||
.rpc()
|
.rpc()
|
||||||
.system_account_next_index(&sp_core::sr25519::Public(address.0).to_string())
|
.system_account_next_index(&sp_core::sr25519::Public(address.0).to_string())
|
||||||
.await
|
.await
|
||||||
.map_err(SeraiError::RpcError)
|
.map_err(|_| SeraiError::ConnectionError)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/// Create a TemporalSerai using whatever is currently the latest block.
|
/// Create a TemporalSerai bound to whatever is currently the latest finalized block.
|
||||||
pub async fn with_current_latest_block(&self) -> Result<TemporalSerai, SeraiError> {
|
///
|
||||||
let latest = self.latest_block_hash().await?;
|
/// The binding occurs at time of call. This does not track the latest finalized block and update
|
||||||
|
/// itself.
|
||||||
|
pub async fn as_of_latest_finalized_block(&self) -> Result<TemporalSerai, SeraiError> {
|
||||||
|
let latest = self.latest_finalized_block_hash().await?;
|
||||||
Ok(TemporalSerai(self, latest))
|
Ok(TemporalSerai(self, latest))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,43 +326,41 @@ impl<'a> TemporalSerai<'a> {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn events<P: 'static, E: Decode>(
|
async fn events<E>(
|
||||||
&self,
|
&self,
|
||||||
filter: impl Fn(&E) -> bool,
|
filter_map: impl Fn(serai_runtime::RuntimeEvent) -> Option<E>,
|
||||||
) -> Result<Vec<E>, SeraiError> {
|
) -> Result<Vec<E>, SeraiError> {
|
||||||
let mut res = vec![];
|
let mut res = vec![];
|
||||||
for event in self.0 .0.events().at(self.1.into()).await.map_err(SeraiError::RpcError)?.iter() {
|
let all_events: Option<
|
||||||
let event = event.map_err(|_| SeraiError::InvalidRuntime)?;
|
Vec<serai_runtime::system::EventRecord<serai_runtime::RuntimeEvent, [u8; 32]>>,
|
||||||
if PalletInfo::index::<P>().unwrap() == usize::from(event.pallet_index()) {
|
> = self.storage("System", "Events", ()).await?;
|
||||||
let mut with_variant: &[u8] =
|
#[allow(clippy::unwrap_or_default)]
|
||||||
&[[event.variant_index()].as_ref(), event.field_bytes()].concat();
|
for event in all_events.unwrap_or(vec![]) {
|
||||||
let event = E::decode(&mut with_variant).map_err(|_| SeraiError::InvalidRuntime)?;
|
if let Some(event) = filter_map(event.event) {
|
||||||
if filter(&event) {
|
|
||||||
res.push(event);
|
res.push(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn storage<R: Decode>(
|
async fn storage<K: Encode, R: Decode>(
|
||||||
&self,
|
&self,
|
||||||
pallet: &'static str,
|
pallet: &'static str,
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
keys: Option<Vec<Value>>,
|
key: K,
|
||||||
) -> Result<Option<R>, SeraiError> {
|
) -> Result<Option<R>, SeraiError> {
|
||||||
let storage = self.0 .0.storage();
|
// TODO: Make this const?
|
||||||
#[allow(clippy::unwrap_or_default)]
|
let mut full_key = sp_core::hashing::twox_128(pallet.as_bytes()).to_vec();
|
||||||
let address = subxt::dynamic::storage(pallet, name, keys.unwrap_or(vec![]));
|
full_key.extend(sp_core::hashing::twox_128(name.as_bytes()));
|
||||||
debug_assert!(storage.validate(&address).is_ok(), "invalid storage address");
|
full_key.extend(key.encode());
|
||||||
|
|
||||||
storage
|
let res: Option<String> =
|
||||||
.at(self.1.into())
|
self.0.call("state_getStorage", [hex::encode(full_key), hex::encode(self.1)]).await?;
|
||||||
.fetch(&address)
|
let Some(res) = res else { return Ok(None) };
|
||||||
.await
|
let res = Serai::hex_decode(res)?;
|
||||||
.map_err(SeraiError::RpcError)?
|
Ok(Some(R::decode(&mut res.as_slice()).map_err(|_| {
|
||||||
.map(|res| R::decode(&mut res.encoded()).map_err(|_| SeraiError::InvalidRuntime))
|
SeraiError::InvalidRuntime("different type present at storage location".to_string())
|
||||||
.transpose()
|
})?))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn coins(self) -> SeraiCoins<'a> {
|
pub fn coins(self) -> SeraiCoins<'a> {
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
use ::scale::Encode;
|
|
||||||
use scale_info::{MetaType, TypeInfo, Registry, PortableRegistry};
|
|
||||||
|
|
||||||
use subxt::ext::scale_value;
|
|
||||||
pub(crate) use scale_value::Value;
|
|
||||||
use scale_value::scale;
|
|
||||||
|
|
||||||
pub(crate) fn scale_value<V: 'static + Encode + TypeInfo>(value: V) -> Value {
|
|
||||||
let mut registry = Registry::new();
|
|
||||||
let id = registry.register_type(&MetaType::new::<V>()).id;
|
|
||||||
let registry = PortableRegistry::from(registry);
|
|
||||||
scale::decode_as_type(&mut value.encode().as_ref(), id, ®istry).unwrap().remove_context()
|
|
||||||
}
|
|
|
@ -1,10 +1,12 @@
|
||||||
|
use scale::Encode;
|
||||||
|
|
||||||
use sp_core::sr25519::{Public, Signature};
|
use sp_core::sr25519::{Public, Signature};
|
||||||
|
|
||||||
use serai_runtime::{primitives::Amount, validator_sets, ValidatorSets, Runtime};
|
use serai_runtime::{primitives::Amount, validator_sets, Runtime};
|
||||||
pub use validator_sets::primitives;
|
pub use validator_sets::primitives;
|
||||||
use primitives::{Session, ValidatorSet, KeyPair};
|
use primitives::{Session, ValidatorSet, KeyPair};
|
||||||
|
|
||||||
use crate::{primitives::NetworkId, Serai, TemporalSerai, SeraiError, scale_value};
|
use crate::{primitives::NetworkId, Serai, TemporalSerai, SeraiError};
|
||||||
|
|
||||||
const PALLET: &str = "ValidatorSets";
|
const PALLET: &str = "ValidatorSets";
|
||||||
|
|
||||||
|
@ -20,47 +22,65 @@ impl<'a> SeraiValidatorSets<'a> {
|
||||||
pub async fn new_set_events(&self) -> Result<Vec<ValidatorSetsEvent>, SeraiError> {
|
pub async fn new_set_events(&self) -> Result<Vec<ValidatorSetsEvent>, SeraiError> {
|
||||||
self
|
self
|
||||||
.0
|
.0
|
||||||
.events::<ValidatorSets, _>(|event| matches!(event, ValidatorSetsEvent::NewSet { .. }))
|
.events(|event| {
|
||||||
|
if let serai_runtime::RuntimeEvent::ValidatorSets(event) = event {
|
||||||
|
Some(event).filter(|event| matches!(event, ValidatorSetsEvent::NewSet { .. }))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn key_gen_events(&self) -> Result<Vec<ValidatorSetsEvent>, SeraiError> {
|
pub async fn key_gen_events(&self) -> Result<Vec<ValidatorSetsEvent>, SeraiError> {
|
||||||
self
|
self
|
||||||
.0
|
.0
|
||||||
.events::<ValidatorSets, _>(|event| matches!(event, ValidatorSetsEvent::KeyGen { .. }))
|
.events(|event| {
|
||||||
|
if let serai_runtime::RuntimeEvent::ValidatorSets(event) = event {
|
||||||
|
Some(event).filter(|event| matches!(event, ValidatorSetsEvent::KeyGen { .. }))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn set_retired_events(&self) -> Result<Vec<ValidatorSetsEvent>, SeraiError> {
|
pub async fn set_retired_events(&self) -> Result<Vec<ValidatorSetsEvent>, SeraiError> {
|
||||||
self
|
self
|
||||||
.0
|
.0
|
||||||
.events::<ValidatorSets, _>(|event| matches!(event, ValidatorSetsEvent::SetRetired { .. }))
|
.events(|event| {
|
||||||
|
if let serai_runtime::RuntimeEvent::ValidatorSets(event) = event {
|
||||||
|
Some(event).filter(|event| matches!(event, ValidatorSetsEvent::SetRetired { .. }))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn session(&self, network: NetworkId) -> Result<Option<Session>, SeraiError> {
|
pub async fn session(&self, network: NetworkId) -> Result<Option<Session>, SeraiError> {
|
||||||
self.0.storage(PALLET, "CurrentSession", Some(vec![scale_value(network)])).await
|
self.0.storage(PALLET, "CurrentSession", network).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn participants(
|
pub async fn participants(
|
||||||
&self,
|
&self,
|
||||||
network: NetworkId,
|
network: NetworkId,
|
||||||
) -> Result<Option<Vec<(Public, u64)>>, SeraiError> {
|
) -> Result<Option<Vec<(Public, u64)>>, SeraiError> {
|
||||||
self.0.storage(PALLET, "Participants", Some(vec![scale_value(network)])).await
|
self.0.storage(PALLET, "Participants", network).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn allocation_per_key_share(
|
pub async fn allocation_per_key_share(
|
||||||
&self,
|
&self,
|
||||||
network: NetworkId,
|
network: NetworkId,
|
||||||
) -> Result<Option<Amount>, SeraiError> {
|
) -> Result<Option<Amount>, SeraiError> {
|
||||||
self.0.storage(PALLET, "AllocationPerKeyShare", Some(vec![scale_value(network)])).await
|
self.0.storage(PALLET, "AllocationPerKeyShare", network).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn total_allocated_stake(
|
pub async fn total_allocated_stake(
|
||||||
&self,
|
&self,
|
||||||
network: NetworkId,
|
network: NetworkId,
|
||||||
) -> Result<Option<Amount>, SeraiError> {
|
) -> Result<Option<Amount>, SeraiError> {
|
||||||
self.0.storage(PALLET, "TotalAllocatedStake", Some(vec![scale_value(network)])).await
|
self.0.storage(PALLET, "TotalAllocatedStake", network).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn allocation(
|
pub async fn allocation(
|
||||||
|
@ -68,16 +88,23 @@ impl<'a> SeraiValidatorSets<'a> {
|
||||||
network: NetworkId,
|
network: NetworkId,
|
||||||
key: Public,
|
key: Public,
|
||||||
) -> Result<Option<Amount>, SeraiError> {
|
) -> Result<Option<Amount>, SeraiError> {
|
||||||
self.0.storage(PALLET, "Allocations", Some(vec![scale_value(network), scale_value(key)])).await
|
self
|
||||||
|
.0
|
||||||
|
.storage(
|
||||||
|
PALLET,
|
||||||
|
"Allocations",
|
||||||
|
(sp_core::hashing::blake2_128(&(network, key).encode()), (network, key)),
|
||||||
|
)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn musig_key(&self, set: ValidatorSet) -> Result<Option<[u8; 32]>, SeraiError> {
|
pub async fn musig_key(&self, set: ValidatorSet) -> Result<Option<[u8; 32]>, SeraiError> {
|
||||||
self.0.storage(PALLET, "MuSigKeys", Some(vec![scale_value(set)])).await
|
self.0.storage(PALLET, "MuSigKeys", (sp_core::hashing::twox_64(&set.encode()), set)).await
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Store these separately since we almost never need both at once?
|
// TODO: Store these separately since we almost never need both at once?
|
||||||
pub async fn keys(&self, set: ValidatorSet) -> Result<Option<KeyPair>, SeraiError> {
|
pub async fn keys(&self, set: ValidatorSet) -> Result<Option<KeyPair>, SeraiError> {
|
||||||
self.0.storage(PALLET, "Keys", Some(vec![scale_value(set)])).await
|
self.0.storage(PALLET, "Keys", (sp_core::hashing::twox_64(&set.encode()), set)).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_keys(network: NetworkId, key_pair: KeyPair, signature: Signature) -> Vec<u8> {
|
pub fn set_keys(network: NetworkId, key_pair: KeyPair, signature: Signature) -> Vec<u8> {
|
||||||
|
|
|
@ -50,7 +50,8 @@ serai_test!(
|
||||||
let serai = serai.as_of(block);
|
let serai = serai.as_of(block);
|
||||||
{
|
{
|
||||||
let serai = serai.in_instructions();
|
let serai = serai.in_instructions();
|
||||||
assert_eq!(serai.latest_block_for_network(network).await.unwrap(), Some(block_hash));
|
let latest_finalized = serai.latest_block_for_network(network).await.unwrap();
|
||||||
|
assert_eq!(latest_finalized, Some(block_hash));
|
||||||
let batches = serai.batch_events().await.unwrap();
|
let batches = serai.batch_events().await.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
batches,
|
batches,
|
||||||
|
|
|
@ -94,7 +94,7 @@ serai_test!(
|
||||||
&pair,
|
&pair,
|
||||||
&SeraiCoins::burn_with_instruction(instruction.clone()),
|
&SeraiCoins::burn_with_instruction(instruction.clone()),
|
||||||
0,
|
0,
|
||||||
Default::default(),
|
0,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
|
@ -20,7 +20,7 @@ pub async fn add_liquidity(
|
||||||
&pair,
|
&pair,
|
||||||
&SeraiDex::add_liquidity(coin, coin_amount, sri_amount, Amount(1), Amount(1), address.into()),
|
&SeraiDex::add_liquidity(coin, coin_amount, sri_amount, Amount(1), Amount(1), address.into()),
|
||||||
nonce,
|
nonce,
|
||||||
Default::default(),
|
0,
|
||||||
);
|
);
|
||||||
|
|
||||||
publish_tx(serai, &tx).await
|
publish_tx(serai, &tx).await
|
||||||
|
|
|
@ -26,7 +26,7 @@ pub async fn provide_batch(serai: &Serai, batch: Batch) -> [u8; 32] {
|
||||||
let set = ValidatorSet { session: Session(0), network: batch.network };
|
let set = ValidatorSet { session: Session(0), network: batch.network };
|
||||||
let pair = insecure_pair_from_name(&format!("ValidatorSet {:?}", set));
|
let pair = insecure_pair_from_name(&format!("ValidatorSet {:?}", set));
|
||||||
let keys = if let Some(keys) =
|
let keys = if let Some(keys) =
|
||||||
serai.with_current_latest_block().await.unwrap().validator_sets().keys(set).await.unwrap()
|
serai.as_of_latest_finalized_block().await.unwrap().validator_sets().keys(set).await.unwrap()
|
||||||
{
|
{
|
||||||
keys
|
keys
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -42,18 +42,18 @@ macro_rules! serai_test {
|
||||||
test.run_async(|ops| async move {
|
test.run_async(|ops| async move {
|
||||||
// Sleep until the Substrate RPC starts
|
// Sleep until the Substrate RPC starts
|
||||||
let serai_rpc = ops.handle(handle).host_port(9944).unwrap();
|
let serai_rpc = ops.handle(handle).host_port(9944).unwrap();
|
||||||
let serai_rpc = format!("ws://{}:{}", serai_rpc.0, serai_rpc.1);
|
let serai_rpc = format!("http://{}:{}", serai_rpc.0, serai_rpc.1);
|
||||||
// Bound execution to 60 seconds
|
// Bound execution to 60 seconds
|
||||||
for _ in 0 .. 60 {
|
for _ in 0 .. 60 {
|
||||||
tokio::time::sleep(core::time::Duration::from_secs(1)).await;
|
tokio::time::sleep(core::time::Duration::from_secs(1)).await;
|
||||||
let Ok(client) = Serai::new(&serai_rpc).await else { continue };
|
let Ok(client) = Serai::new(serai_rpc.clone()).await else { continue };
|
||||||
if client.latest_block_hash().await.is_err() {
|
if client.latest_finalized_block_hash().await.is_err() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#[allow(clippy::redundant_closure_call)]
|
#[allow(clippy::redundant_closure_call)]
|
||||||
$test(Serai::new(&serai_rpc).await.unwrap()).await;
|
$test(Serai::new(serai_rpc).await.unwrap()).await;
|
||||||
}).await;
|
}).await;
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
|
|
|
@ -2,12 +2,18 @@ use core::time::Duration;
|
||||||
|
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
|
|
||||||
|
use scale::Encode;
|
||||||
|
|
||||||
use serai_client::Serai;
|
use serai_client::Serai;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub async fn publish_tx(serai: &Serai, tx: &[u8]) -> [u8; 32] {
|
pub async fn publish_tx(serai: &Serai, tx: &[u8]) -> [u8; 32] {
|
||||||
let mut latest =
|
let mut latest = serai
|
||||||
serai.block(serai.latest_block_hash().await.unwrap()).await.unwrap().unwrap().number();
|
.block(serai.latest_finalized_block_hash().await.unwrap())
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
.number();
|
||||||
|
|
||||||
serai.publish(tx).await.unwrap();
|
serai.publish(tx).await.unwrap();
|
||||||
|
|
||||||
|
@ -20,7 +26,7 @@ pub async fn publish_tx(serai: &Serai, tx: &[u8]) -> [u8; 32] {
|
||||||
let block = {
|
let block = {
|
||||||
let mut block;
|
let mut block;
|
||||||
while {
|
while {
|
||||||
block = serai.block_by_number(latest).await.unwrap();
|
block = serai.finalized_block_by_number(latest).await.unwrap();
|
||||||
block.is_none()
|
block.is_none()
|
||||||
} {
|
} {
|
||||||
sleep(Duration::from_secs(1)).await;
|
sleep(Duration::from_secs(1)).await;
|
||||||
|
@ -34,7 +40,7 @@ pub async fn publish_tx(serai: &Serai, tx: &[u8]) -> [u8; 32] {
|
||||||
};
|
};
|
||||||
|
|
||||||
for transaction in block.transactions() {
|
for transaction in block.transactions() {
|
||||||
if transaction.0 == tx {
|
if transaction.encode() == tx {
|
||||||
return block.hash();
|
return block.hash();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ pub async fn set_keys(serai: &Serai, set: ValidatorSet, key_pair: KeyPair) -> [u
|
||||||
let public_key = <Ristretto as Ciphersuite>::read_G::<&[u8]>(&mut public.0.as_ref()).unwrap();
|
let public_key = <Ristretto as Ciphersuite>::read_G::<&[u8]>(&mut public.0.as_ref()).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serai
|
serai
|
||||||
.with_current_latest_block()
|
.as_of_latest_finalized_block()
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.validator_sets()
|
.validator_sets()
|
||||||
|
@ -48,7 +48,7 @@ pub async fn set_keys(serai: &Serai, set: ValidatorSet, key_pair: KeyPair) -> [u
|
||||||
musig::<Ristretto>(&musig_context(set), &Zeroizing::new(secret_key), &[public_key]).unwrap();
|
musig::<Ristretto>(&musig_context(set), &Zeroizing::new(secret_key), &[public_key]).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serai
|
serai
|
||||||
.with_current_latest_block()
|
.as_of_latest_finalized_block()
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.validator_sets()
|
.validator_sets()
|
||||||
|
@ -69,7 +69,7 @@ pub async fn set_keys(serai: &Serai, set: ValidatorSet, key_pair: KeyPair) -> [u
|
||||||
&set_keys_message(&set, &key_pair),
|
&set_keys_message(&set, &key_pair),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Vote in a key pair
|
// Set the key pair
|
||||||
let block = publish_tx(
|
let block = publish_tx(
|
||||||
serai,
|
serai,
|
||||||
&SeraiValidatorSets::set_keys(set.network, key_pair.clone(), Signature(sig.to_bytes())),
|
&SeraiValidatorSets::set_keys(set.network, key_pair.clone(), Signature(sig.to_bytes())),
|
||||||
|
|
|
@ -29,8 +29,8 @@ use common::{
|
||||||
// TODO: Check Transfer events
|
// TODO: Check Transfer events
|
||||||
serai_test!(
|
serai_test!(
|
||||||
create_pool: (|serai: Serai| async move {
|
create_pool: (|serai: Serai| async move {
|
||||||
let block = serai.block_by_number(0).await.unwrap().unwrap().hash();
|
let block = serai.finalized_block_by_number(0).await.unwrap().unwrap().hash();
|
||||||
let events = serai.as_of(block).dex().all_events().await.unwrap();
|
let events = serai.as_of(block).dex().events().await.unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
events,
|
events,
|
||||||
|
@ -85,7 +85,7 @@ serai_test!(
|
||||||
pair.clone()
|
pair.clone()
|
||||||
).await;
|
).await;
|
||||||
// get only the add liq events
|
// get only the add liq events
|
||||||
let mut events = serai.as_of(block).dex().all_events().await.unwrap();
|
let mut events = serai.as_of(block).dex().events().await.unwrap();
|
||||||
events.retain(|e| matches!(e, DexEvent::LiquidityAdded { .. }));
|
events.retain(|e| matches!(e, DexEvent::LiquidityAdded { .. }));
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -133,7 +133,7 @@ serai_test!(
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// get only the swap events
|
// get only the swap events
|
||||||
let mut events = serai.as_of(block).dex().all_events().await.unwrap();
|
let mut events = serai.as_of(block).dex().events().await.unwrap();
|
||||||
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
|
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
|
||||||
|
|
||||||
let mut path = BoundedVec::try_from(vec![coin, Coin::Serai]).unwrap();
|
let mut path = BoundedVec::try_from(vec![coin, Coin::Serai]).unwrap();
|
||||||
|
@ -153,7 +153,7 @@ serai_test!(
|
||||||
block = common_swap(&serai, Coin::Serai, coin, amount_in, Amount(1), 2, pair.clone()).await;
|
block = common_swap(&serai, Coin::Serai, coin, amount_in, Amount(1), 2, pair.clone()).await;
|
||||||
|
|
||||||
// get only the swap events
|
// get only the swap events
|
||||||
let mut events = serai.as_of(block).dex().all_events().await.unwrap();
|
let mut events = serai.as_of(block).dex().events().await.unwrap();
|
||||||
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
|
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
|
||||||
|
|
||||||
path = BoundedVec::try_from(vec![Coin::Serai, coin]).unwrap();
|
path = BoundedVec::try_from(vec![Coin::Serai, coin]).unwrap();
|
||||||
|
@ -213,7 +213,7 @@ serai_test!(
|
||||||
let block = common_swap(&serai, coin1, coin2, amount_in, Amount(1), 2, pair.clone()).await;
|
let block = common_swap(&serai, coin1, coin2, amount_in, Amount(1), 2, pair.clone()).await;
|
||||||
|
|
||||||
// get only the swap events
|
// get only the swap events
|
||||||
let mut events = serai.as_of(block).dex().all_events().await.unwrap();
|
let mut events = serai.as_of(block).dex().events().await.unwrap();
|
||||||
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
|
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
|
||||||
|
|
||||||
let path = BoundedVec::try_from(vec![coin1, Coin::Serai, coin2]).unwrap();
|
let path = BoundedVec::try_from(vec![coin1, Coin::Serai, coin2]).unwrap();
|
||||||
|
@ -270,7 +270,7 @@ serai_test!(
|
||||||
};
|
};
|
||||||
|
|
||||||
let block = provide_batch(&serai, batch).await;
|
let block = provide_batch(&serai, batch).await;
|
||||||
let mut events = serai.as_of(block).dex().all_events().await.unwrap();
|
let mut events = serai.as_of(block).dex().events().await.unwrap();
|
||||||
events.retain(|e| matches!(e, DexEvent::LiquidityAdded { .. }));
|
events.retain(|e| matches!(e, DexEvent::LiquidityAdded { .. }));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
events,
|
events,
|
||||||
|
@ -356,7 +356,7 @@ serai_test!(
|
||||||
|
|
||||||
let block = provide_batch(&serai, batch).await;
|
let block = provide_batch(&serai, batch).await;
|
||||||
coin1_batch_id += 1;
|
coin1_batch_id += 1;
|
||||||
let mut events = serai.as_of(block).dex().all_events().await.unwrap();
|
let mut events = serai.as_of(block).dex().events().await.unwrap();
|
||||||
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
|
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
|
||||||
|
|
||||||
let path = BoundedVec::try_from(vec![coin1, Coin::Serai, coin2]).unwrap();
|
let path = BoundedVec::try_from(vec![coin1, Coin::Serai, coin2]).unwrap();
|
||||||
|
@ -395,7 +395,7 @@ serai_test!(
|
||||||
};
|
};
|
||||||
|
|
||||||
let block = provide_batch(&serai, batch).await;
|
let block = provide_batch(&serai, batch).await;
|
||||||
let mut events = serai.as_of(block).dex().all_events().await.unwrap();
|
let mut events = serai.as_of(block).dex().events().await.unwrap();
|
||||||
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
|
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
|
||||||
|
|
||||||
let path = BoundedVec::try_from(vec![coin2, Coin::Serai, coin1]).unwrap();
|
let path = BoundedVec::try_from(vec![coin2, Coin::Serai, coin1]).unwrap();
|
||||||
|
@ -433,7 +433,7 @@ serai_test!(
|
||||||
};
|
};
|
||||||
|
|
||||||
let block = provide_batch(&serai, batch).await;
|
let block = provide_batch(&serai, batch).await;
|
||||||
let mut events = serai.as_of(block).dex().all_events().await.unwrap();
|
let mut events = serai.as_of(block).dex().events().await.unwrap();
|
||||||
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
|
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
|
||||||
|
|
||||||
let path = BoundedVec::try_from(vec![coin1, Coin::Serai]).unwrap();
|
let path = BoundedVec::try_from(vec![coin1, Coin::Serai]).unwrap();
|
||||||
|
|
|
@ -8,11 +8,11 @@ mod common;
|
||||||
|
|
||||||
serai_test!(
|
serai_test!(
|
||||||
time: (|serai: Serai| async move {
|
time: (|serai: Serai| async move {
|
||||||
let mut number = serai.latest_block().await.unwrap().number();
|
let mut number = serai.latest_finalized_block().await.unwrap().number();
|
||||||
let mut done = 0;
|
let mut done = 0;
|
||||||
while done < 3 {
|
while done < 3 {
|
||||||
// Wait for the next block
|
// Wait for the next block
|
||||||
let block = serai.latest_block().await.unwrap();
|
let block = serai.latest_finalized_block().await.unwrap();
|
||||||
if block.number() == number {
|
if block.number() == number {
|
||||||
sleep(Duration::from_secs(1)).await;
|
sleep(Duration::from_secs(1)).await;
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -33,7 +33,7 @@ serai_test!(
|
||||||
// Make sure the genesis is as expected
|
// Make sure the genesis is as expected
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serai
|
serai
|
||||||
.as_of(serai.block_by_number(0).await.unwrap().unwrap().hash())
|
.as_of(serai.finalized_block_by_number(0).await.unwrap().unwrap().hash())
|
||||||
.validator_sets()
|
.validator_sets()
|
||||||
.new_set_events()
|
.new_set_events()
|
||||||
.await
|
.await
|
||||||
|
@ -48,7 +48,7 @@ serai_test!(
|
||||||
);
|
);
|
||||||
|
|
||||||
{
|
{
|
||||||
let vs_serai = serai.with_current_latest_block().await.unwrap().validator_sets();
|
let vs_serai = serai.as_of_latest_finalized_block().await.unwrap().validator_sets();
|
||||||
let participants = vs_serai.participants(set.network).await
|
let participants = vs_serai.participants(set.network).await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
|
@ -58,23 +58,23 @@ pub mod pallet {
|
||||||
// The ID of the last executed Batch for a network.
|
// The ID of the last executed Batch for a network.
|
||||||
#[pallet::storage]
|
#[pallet::storage]
|
||||||
#[pallet::getter(fn batches)]
|
#[pallet::getter(fn batches)]
|
||||||
pub(crate) type LastBatch<T: Config> = StorageMap<_, Blake2_256, NetworkId, u32, OptionQuery>;
|
pub(crate) type LastBatch<T: Config> = StorageMap<_, Identity, NetworkId, u32, OptionQuery>;
|
||||||
|
|
||||||
// The last Serai block in which this validator set included a batch
|
// The last Serai block in which this validator set included a batch
|
||||||
#[pallet::storage]
|
#[pallet::storage]
|
||||||
#[pallet::getter(fn last_batch_block)]
|
#[pallet::getter(fn last_batch_block)]
|
||||||
pub(crate) type LastBatchBlock<T: Config> =
|
pub(crate) type LastBatchBlock<T: Config> =
|
||||||
StorageMap<_, Blake2_256, NetworkId, BlockNumberFor<T>, OptionQuery>;
|
StorageMap<_, Identity, NetworkId, BlockNumberFor<T>, OptionQuery>;
|
||||||
|
|
||||||
// Halted networks.
|
// Halted networks.
|
||||||
#[pallet::storage]
|
#[pallet::storage]
|
||||||
pub(crate) type Halted<T: Config> = StorageMap<_, Blake2_256, NetworkId, (), OptionQuery>;
|
pub(crate) type Halted<T: Config> = StorageMap<_, Identity, NetworkId, (), OptionQuery>;
|
||||||
|
|
||||||
// The latest block a network has acknowledged as finalized
|
// The latest block a network has acknowledged as finalized
|
||||||
#[pallet::storage]
|
#[pallet::storage]
|
||||||
#[pallet::getter(fn latest_network_block)]
|
#[pallet::getter(fn latest_network_block)]
|
||||||
pub(crate) type LatestNetworkBlock<T: Config> =
|
pub(crate) type LatestNetworkBlock<T: Config> =
|
||||||
StorageMap<_, Blake2_256, NetworkId, BlockHash, OptionQuery>;
|
StorageMap<_, Identity, NetworkId, BlockHash, OptionQuery>;
|
||||||
|
|
||||||
impl<T: Config> Pallet<T> {
|
impl<T: Config> Pallet<T> {
|
||||||
// Use a dedicated transaction layer when executing this InInstruction
|
// Use a dedicated transaction layer when executing this InInstruction
|
||||||
|
|
|
@ -213,12 +213,12 @@ impl Processor {
|
||||||
|
|
||||||
// Sleep until the Substrate RPC starts
|
// Sleep until the Substrate RPC starts
|
||||||
let serai_rpc = ops.handle(&handles.0).host_port(9944).unwrap();
|
let serai_rpc = ops.handle(&handles.0).host_port(9944).unwrap();
|
||||||
let serai_rpc = format!("ws://{}:{}", serai_rpc.0, serai_rpc.1);
|
let serai_rpc = format!("http://{}:{}", serai_rpc.0, serai_rpc.1);
|
||||||
// Bound execution to 60 seconds
|
// Bound execution to 60 seconds
|
||||||
for _ in 0 .. 60 {
|
for _ in 0 .. 60 {
|
||||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||||
let Ok(client) = Serai::new(&serai_rpc).await else { continue };
|
let Ok(client) = Serai::new(serai_rpc.clone()).await else { continue };
|
||||||
if client.latest_block_hash().await.is_err() {
|
if client.latest_finalized_block_hash().await.is_err() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -371,7 +371,7 @@ impl Processor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn serai(&self) -> Serai {
|
pub async fn serai(&self) -> Serai {
|
||||||
Serai::new(&self.serai_rpc).await.unwrap()
|
Serai::new(self.serai_rpc.clone()).await.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send a message to the coordinator as a processor.
|
/// Send a message to the coordinator as a processor.
|
||||||
|
|
|
@ -176,7 +176,7 @@ pub async fn batch(
|
||||||
let batch = SignedBatch { batch, signature };
|
let batch = SignedBatch { batch, signature };
|
||||||
|
|
||||||
let serai = processors[0].serai().await;
|
let serai = processors[0].serai().await;
|
||||||
let mut last_serai_block = serai.latest_block().await.unwrap().number();
|
let mut last_serai_block = serai.latest_finalized_block().await.unwrap().number();
|
||||||
|
|
||||||
for (i, processor) in processors.iter_mut().enumerate() {
|
for (i, processor) in processors.iter_mut().enumerate() {
|
||||||
if i == excluded_signer {
|
if i == excluded_signer {
|
||||||
|
@ -194,9 +194,9 @@ pub async fn batch(
|
||||||
tokio::time::sleep(Duration::from_secs(6)).await;
|
tokio::time::sleep(Duration::from_secs(6)).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
while last_serai_block <= serai.latest_block().await.unwrap().number() {
|
while last_serai_block <= serai.latest_finalized_block().await.unwrap().number() {
|
||||||
let batch_events = serai
|
let batch_events = serai
|
||||||
.as_of(serai.block_by_number(last_serai_block).await.unwrap().unwrap().hash())
|
.as_of(serai.finalized_block_by_number(last_serai_block).await.unwrap().unwrap().hash())
|
||||||
.in_instructions()
|
.in_instructions()
|
||||||
.batch_events()
|
.batch_events()
|
||||||
.await
|
.await
|
||||||
|
@ -220,7 +220,7 @@ pub async fn batch(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the coordinator sends SubstrateBlock to all processors
|
// Verify the coordinator sends SubstrateBlock to all processors
|
||||||
let last_block = serai.block_by_number(last_serai_block).await.unwrap().unwrap();
|
let last_block = serai.finalized_block_by_number(last_serai_block).await.unwrap().unwrap();
|
||||||
for processor in processors {
|
for processor in processors {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
processor.recv_message().await,
|
processor.recv_message().await,
|
||||||
|
|
|
@ -109,7 +109,7 @@ pub async fn key_gen<C: Ciphersuite>(
|
||||||
let network_key = (C::generator() * *network_priv_key).to_bytes().as_ref().to_vec();
|
let network_key = (C::generator() * *network_priv_key).to_bytes().as_ref().to_vec();
|
||||||
|
|
||||||
let serai = processors[0].serai().await;
|
let serai = processors[0].serai().await;
|
||||||
let mut last_serai_block = serai.latest_block().await.unwrap().number();
|
let mut last_serai_block = serai.latest_finalized_block().await.unwrap().number();
|
||||||
|
|
||||||
wait_for_tributary().await;
|
wait_for_tributary().await;
|
||||||
for (i, processor) in processors.iter_mut().enumerate() {
|
for (i, processor) in processors.iter_mut().enumerate() {
|
||||||
|
@ -151,9 +151,9 @@ pub async fn key_gen<C: Ciphersuite>(
|
||||||
tokio::time::sleep(Duration::from_secs(6)).await;
|
tokio::time::sleep(Duration::from_secs(6)).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
while last_serai_block <= serai.latest_block().await.unwrap().number() {
|
while last_serai_block <= serai.latest_finalized_block().await.unwrap().number() {
|
||||||
if !serai
|
if !serai
|
||||||
.as_of(serai.block_by_number(last_serai_block).await.unwrap().unwrap().hash())
|
.as_of(serai.finalized_block_by_number(last_serai_block).await.unwrap().unwrap().hash())
|
||||||
.validator_sets()
|
.validator_sets()
|
||||||
.key_gen_events()
|
.key_gen_events()
|
||||||
.await
|
.await
|
||||||
|
@ -199,7 +199,7 @@ pub async fn key_gen<C: Ciphersuite>(
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serai
|
serai
|
||||||
.as_of(serai.block_by_number(last_serai_block).await.unwrap().unwrap().hash())
|
.as_of(serai.finalized_block_by_number(last_serai_block).await.unwrap().unwrap().hash())
|
||||||
.validator_sets()
|
.validator_sets()
|
||||||
.keys(set)
|
.keys(set)
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -241,7 +241,7 @@ async fn sign_test() {
|
||||||
|
|
||||||
{
|
{
|
||||||
let block_included_in_hash =
|
let block_included_in_hash =
|
||||||
serai.block_by_number(block_included_in).await.unwrap().unwrap().hash();
|
serai.finalized_block_by_number(block_included_in).await.unwrap().unwrap().hash();
|
||||||
|
|
||||||
let serai = serai.as_of(block_included_in_hash).coins();
|
let serai = serai.as_of(block_included_in_hash).coins();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -284,9 +284,9 @@ async fn sign_test() {
|
||||||
tokio::time::sleep(Duration::from_secs(6)).await;
|
tokio::time::sleep(Duration::from_secs(6)).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
while last_serai_block <= serai.latest_block().await.unwrap().number() {
|
while last_serai_block <= serai.latest_finalized_block().await.unwrap().number() {
|
||||||
let burn_events = serai
|
let burn_events = serai
|
||||||
.as_of(serai.block_by_number(last_serai_block).await.unwrap().unwrap().hash())
|
.as_of(serai.finalized_block_by_number(last_serai_block).await.unwrap().unwrap().hash())
|
||||||
.coins()
|
.coins()
|
||||||
.burn_with_instruction_events()
|
.burn_with_instruction_events()
|
||||||
.await
|
.await
|
||||||
|
@ -307,7 +307,8 @@ async fn sign_test() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let last_serai_block = serai.block_by_number(last_serai_block).await.unwrap().unwrap();
|
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 last_serai_block_hash = last_serai_block.hash();
|
||||||
let serai = serai.as_of(last_serai_block_hash).coins();
|
let serai = serai.as_of(last_serai_block_hash).coins();
|
||||||
assert_eq!(serai.coin_supply(Coin::Bitcoin).await.unwrap(), Amount(0));
|
assert_eq!(serai.coin_supply(Coin::Bitcoin).await.unwrap(), Amount(0));
|
||||||
|
|
|
@ -132,13 +132,13 @@ pub fn full_stack(name: &str) -> (Handles, Vec<TestBodySpecification>) {
|
||||||
impl Handles {
|
impl Handles {
|
||||||
pub async fn serai(&self, ops: &DockerOperations) -> Serai {
|
pub async fn serai(&self, ops: &DockerOperations) -> Serai {
|
||||||
let serai_rpc = ops.handle(&self.serai).host_port(9944).unwrap();
|
let serai_rpc = ops.handle(&self.serai).host_port(9944).unwrap();
|
||||||
let serai_rpc = format!("ws://{}:{}", serai_rpc.0, serai_rpc.1);
|
let serai_rpc = format!("http://{}:{}", serai_rpc.0, serai_rpc.1);
|
||||||
|
|
||||||
// If the RPC server has yet to start, sleep for up to 60s until it does
|
// If the RPC server has yet to start, sleep for up to 60s until it does
|
||||||
for _ in 0 .. 60 {
|
for _ in 0 .. 60 {
|
||||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||||
let Ok(client) = Serai::new(&serai_rpc).await else { continue };
|
let Ok(client) = Serai::new(serai_rpc.clone()).await else { continue };
|
||||||
if client.latest_block_hash().await.is_err() {
|
if client.latest_finalized_block_hash().await.is_err() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return client;
|
return client;
|
||||||
|
|
|
@ -201,7 +201,7 @@ async fn mint_and_burn_test() {
|
||||||
let print_at = halt_at / 2;
|
let print_at = halt_at / 2;
|
||||||
for i in 0 .. halt_at {
|
for i in 0 .. halt_at {
|
||||||
if let Some(key_pair) = serai
|
if let Some(key_pair) = serai
|
||||||
.with_current_latest_block()
|
.as_of_latest_finalized_block()
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.validator_sets()
|
.validator_sets()
|
||||||
|
@ -417,7 +417,7 @@ async fn mint_and_burn_test() {
|
||||||
let print_at = halt_at / 2;
|
let print_at = halt_at / 2;
|
||||||
for i in 0 .. halt_at {
|
for i in 0 .. halt_at {
|
||||||
if serai
|
if serai
|
||||||
.with_current_latest_block()
|
.as_of_latest_finalized_block()
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.in_instructions()
|
.in_instructions()
|
||||||
|
|
Loading…
Reference in a new issue