From c6546ef02c7d29cf36ce3af2f289f8da50171b35 Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Sun, 3 Mar 2024 22:36:26 +0000 Subject: [PATCH] feat: add light client support --- Cargo.lock | 705 +++++++++++++++++++++++++++++++++++-- Cargo.toml | 16 + src/commands/follow/mod.rs | 183 ++++++++++ src/commands/mod.rs | 2 + src/main.rs | 8 + 5 files changed, 893 insertions(+), 21 deletions(-) create mode 100644 src/commands/follow/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 90e81fa6..3c05580a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -212,6 +212,12 @@ version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" + [[package]] name = "ark-bls12-377" version = "0.4.0" @@ -640,6 +646,28 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "async-task" version = "4.7.0" @@ -1531,6 +1559,60 @@ dependencies = [ "libc", ] +[[package]] +name = "cranelift-bforest" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c22542c0b95bd3302f7ed6839869c561f2324bac2fd5e7e99f5cfa65fdc8b92" +dependencies = [ + "cranelift-entity 0.103.0", +] + +[[package]] +name = "cranelift-codegen" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3db903ef2e9c8a4de2ea6db5db052c7857282952f9df604aa55d169e6000d8" +dependencies = [ + "bumpalo", + "cranelift-bforest", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-control", + "cranelift-entity 0.103.0", + "cranelift-isle", + "gimli 0.28.1", + "hashbrown 0.14.3", + "log", + "regalloc2", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6590feb5a1d6438f974bf6a5ac4dddf69fca14e1f07f3265d880f69e61a94463" +dependencies = [ + "cranelift-codegen-shared", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7239038c56fafe77fddc8788fc8533dd6c474dc5bdc5637216404f41ba807330" + +[[package]] +name = "cranelift-control" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7dc9c595341404d381d27a3d950160856b35b402275f0c3990cd1ad683c8053" +dependencies = [ + "arbitrary", +] + [[package]] name = "cranelift-entity" version = "0.95.1" @@ -1540,6 +1622,61 @@ dependencies = [ "serde", ] +[[package]] +name = "cranelift-entity" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44e3ee532fc4776c69bcedf7e62f9632cbb3f35776fa9a525cdade3195baa3f7" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "cranelift-frontend" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a612c94d09e653662ec37681dc2d6fd2b9856e6df7147be0afc9aabb0abf19df" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-isle" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85db9830abeb1170b7d29b536ffd55af1d4d26ac8a77570b5d1aca003bf225cc" + +[[package]] +name = "cranelift-native" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301ef0edafeaeda5771a5d2db64ac53e1818ae3111220a185677025fe91db4a1" +dependencies = [ + "cranelift-codegen", + "libc", + "target-lexicon", +] + +[[package]] +name = "cranelift-wasm" +version = "0.103.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380f0abe8264e4570ac615fc31cef32a3b90a77f7eb97b08331f9dd357b1f500" +dependencies = [ + "cranelift-codegen", + "cranelift-entity 0.103.0", + "cranelift-frontend", + "itertools 0.10.5", + "log", + "smallvec", + "wasmparser 0.118.2", + "wasmtime-types 16.0.0", +] + [[package]] name = "crc32fast" version = "1.4.0" @@ -2590,6 +2727,18 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + [[package]] name = "fastrand" version = "1.9.0" @@ -2961,7 +3110,7 @@ version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" dependencies = [ - "fallible-iterator", + "fallible-iterator 0.2.0", "indexmap 1.9.3", "stable_deref_trait", ] @@ -2971,6 +3120,11 @@ name = "gimli" version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +dependencies = [ + "fallible-iterator 0.3.0", + "indexmap 2.2.5", + "stable_deref_trait", +] [[package]] name = "git2" @@ -3061,6 +3215,15 @@ dependencies = [ "serde", ] +[[package]] +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +dependencies = [ + "hashbrown 0.14.3", +] + [[package]] name = "heck" version = "0.4.1" @@ -3401,6 +3564,12 @@ dependencies = [ "cc", ] +[[package]] +name = "id-arena" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" + [[package]] name = "ident_case" version = "1.0.1" @@ -4073,6 +4242,12 @@ dependencies = [ "spin 0.5.2", ] +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + [[package]] name = "libc" version = "0.2.153" @@ -4272,6 +4447,17 @@ dependencies = [ "libsecp256k1-core", ] +[[package]] +name = "libsqlite3-sys" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + [[package]] name = "libssh2-sys" version = "0.3.0" @@ -4449,6 +4635,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + [[package]] name = "memory-db" version = "0.32.0" @@ -4525,6 +4720,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "multi-stash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685a9ac4b61f4e728e1d2c6a7844609c16527aeb5e6c865915c08e619c16410f" + [[package]] name = "multiaddr" version = "0.18.1" @@ -4701,6 +4902,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "num-format" version = "0.4.4" @@ -4787,6 +4999,9 @@ version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ + "crc32fast", + "hashbrown 0.14.3", + "indexmap 2.2.5", "memchr", ] @@ -5371,6 +5586,7 @@ dependencies = [ "ansi_term", "anyhow", "askama", + "async-stream", "clap", "cliclack", "console", @@ -5385,6 +5601,8 @@ dependencies = [ "reqwest", "serde", "serde_json", + "smoldot 0.17.0", + "smoldot-light 0.15.0", "sp-core 30.0.0", "sp-weights", "strum 0.26.1", @@ -5394,7 +5612,9 @@ dependencies = [ "symlink", "tempdir", "tempfile", + "thousands", "tokio", + "tokio-stream", "toml_edit 0.22.6", "tracing-subscriber 0.3.18", "url", @@ -5744,6 +5964,19 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "regalloc2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" +dependencies = [ + "hashbrown 0.13.2", + "log", + "rustc-hash", + "slice-group-by", + "smallvec", +] + [[package]] name = "regex" version = "1.10.3" @@ -5944,6 +6177,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rusqlite" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a78046161564f5e7cd9008aff3b2990b3850dc8e0349119b98e8f251e099f24d" +dependencies = [ + "bitflags 2.4.2", + "fallible-iterator 0.3.0", + "fallible-streaming-iterator", + "hashlink", + "libsqlite3-sys", + "smallvec", +] + [[package]] name = "rust_decimal" version = "1.34.3" @@ -6855,6 +7102,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "slice-group-by" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" + [[package]] name = "smallvec" version = "1.13.1" @@ -6962,7 +7215,7 @@ dependencies = [ "smallvec", "soketto", "twox-hash", - "wasmi", + "wasmi 0.31.2", "x25519-dalek", "zeroize", ] @@ -7017,7 +7270,65 @@ dependencies = [ "smallvec", "soketto", "twox-hash", - "wasmi", + "wasmi 0.31.2", + "x25519-dalek", + "zeroize", +] + +[[package]] +name = "smoldot" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65332bfea88002d2b47f33e5f3ccd22a1c94967f8ada0c912be56865a02e5e57" +dependencies = [ + "arrayvec 0.7.4", + "async-lock 3.3.0", + "atomic-take", + "base64 0.21.7", + "bip39", + "blake2-rfc", + "bs58 0.5.0", + "chacha20", + "crossbeam-queue", + "derive_more", + "ed25519-zebra 4.0.3", + "either", + "event-listener 4.0.3", + "fnv", + "futures-lite 2.2.0", + "futures-util", + "hashbrown 0.14.3", + "hex", + "hmac 0.12.1", + "itertools 0.12.1", + "libm", + "libsecp256k1", + "merlin 3.0.0", + "no-std-net", + "nom", + "num-bigint", + "num-rational", + "num-traits", + "parking_lot", + "pbkdf2 0.12.2", + "pin-project", + "poly1305", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rusqlite", + "ruzstd", + "schnorrkel 0.11.4", + "serde", + "serde_json", + "sha2 0.10.8", + "sha3", + "siphasher 1.0.0", + "slab", + "smallvec", + "soketto", + "twox-hash", + "wasmi 0.32.0-beta.6", + "wasmtime 16.0.0", "x25519-dalek", "zeroize", ] @@ -7094,6 +7405,42 @@ dependencies = [ "zeroize", ] +[[package]] +name = "smoldot-light" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416a29c366a0e6d41bf81dc6c1e4851c60834eabea7e65d056c6becfdfd89977" +dependencies = [ + "async-channel 2.2.0", + "async-lock 3.3.0", + "base64 0.21.7", + "blake2-rfc", + "derive_more", + "either", + "event-listener 4.0.3", + "fnv", + "futures-channel", + "futures-lite 2.2.0", + "futures-util", + "hashbrown 0.14.3", + "hex", + "itertools 0.12.1", + "log", + "lru", + "no-std-net", + "parking_lot", + "pin-project", + "rand 0.8.5", + "rand_chacha 0.3.1", + "serde", + "serde_json", + "siphasher 1.0.0", + "slab", + "smol 2.0.0", + "smoldot 0.17.0", + "zeroize", +] + [[package]] name = "socket2" version = "0.4.10" @@ -7648,7 +7995,7 @@ dependencies = [ "log", "parity-scale-codec", "sp-std 9.0.0", - "wasmtime", + "wasmtime 8.0.1", ] [[package]] @@ -7662,7 +8009,7 @@ dependencies = [ "log", "parity-scale-codec", "sp-std 14.0.0", - "wasmtime", + "wasmtime 8.0.1", ] [[package]] @@ -7703,6 +8050,12 @@ dependencies = [ "der", ] +[[package]] +name = "sptr" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" + [[package]] name = "ss58-registry" version = "1.46.0" @@ -8602,6 +8955,12 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "thousands" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820" + [[package]] name = "thread_local" version = "1.1.8" @@ -9525,6 +9884,15 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +[[package]] +name = "wasm-encoder" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad2b51884de9c7f4fe2fd1043fccb8dcad4b1e29558146ee57a144d15779f3f" +dependencies = [ + "leb128", +] + [[package]] name = "wasm-opt" version = "0.116.0" @@ -9587,7 +9955,23 @@ dependencies = [ "smallvec", "spin 0.9.8", "wasmi_arena", - "wasmi_core", + "wasmi_core 0.13.0", + "wasmparser-nostd", +] + +[[package]] +name = "wasmi" +version = "0.32.0-beta.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe300327c917a4542561357e52238745e9c82edc4621440e7995270b99467759" +dependencies = [ + "multi-stash", + "num-derive", + "num-traits", + "smallvec", + "spin 0.9.8", + "wasmi_arena", + "wasmi_core 0.15.0", "wasmparser-nostd", ] @@ -9609,6 +9993,18 @@ dependencies = [ "paste", ] +[[package]] +name = "wasmi_core" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ac482df6761020b2b75c9aade41c105993c5b9f64156c349bb7ccad226a6ecd" +dependencies = [ + "downcast-rs", + "libm", + "num-traits", + "paste", +] + [[package]] name = "wasmparser" version = "0.102.0" @@ -9619,6 +10015,16 @@ dependencies = [ "url", ] +[[package]] +name = "wasmparser" +version = "0.118.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77f1154f1ab868e2a01d9834a805faca7bf8b50d041b4ca714d005d0dab1c50c" +dependencies = [ + "indexmap 2.2.5", + "semver 1.0.22", +] + [[package]] name = "wasmparser-nostd" version = "0.100.1" @@ -9646,13 +10052,44 @@ dependencies = [ "psm", "serde", "target-lexicon", - "wasmparser", - "wasmtime-environ", - "wasmtime-jit", - "wasmtime-runtime", + "wasmparser 0.102.0", + "wasmtime-environ 8.0.1", + "wasmtime-jit 8.0.1", + "wasmtime-runtime 8.0.1", "windows-sys 0.45.0", ] +[[package]] +name = "wasmtime" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8e539fded2495422ea3c4dfa7beeddba45904eece182cf315294009e1a323bf" +dependencies = [ + "anyhow", + "async-trait", + "bincode", + "bumpalo", + "cfg-if", + "indexmap 2.2.5", + "libc", + "log", + "object 0.32.2", + "once_cell", + "paste", + "serde", + "serde_derive", + "serde_json", + "target-lexicon", + "wasmparser 0.118.2", + "wasmtime-component-macro", + "wasmtime-cranelift", + "wasmtime-environ 16.0.0", + "wasmtime-fiber", + "wasmtime-jit 16.0.0", + "wasmtime-runtime 16.0.0", + "windows-sys 0.48.0", +] + [[package]] name = "wasmtime-asm-macros" version = "8.0.1" @@ -9662,6 +10099,77 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "wasmtime-asm-macros" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "660ba9143e15a2acd921820df221b73aee256bd3ca2d208d73d8adc9587ccbb9" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "wasmtime-component-macro" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ef32643324e564e1c359e9044daa06cbf90d7e2d6c99a738d17a12959f01a5" +dependencies = [ + "anyhow", + "proc-macro2", + "quote", + "syn 2.0.52", + "wasmtime-component-util", + "wasmtime-wit-bindgen", + "wit-parser", +] + +[[package]] +name = "wasmtime-component-util" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c87d06c18d21a4818f354c00a85f4ebc62b2270961cd022968452b0e4dbed9d" + +[[package]] +name = "wasmtime-cranelift" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d648c8b4064a7911093b02237cd5569f71ca171d3a0a486bf80600b19e1cba2" +dependencies = [ + "anyhow", + "cfg-if", + "cranelift-codegen", + "cranelift-control", + "cranelift-entity 0.103.0", + "cranelift-frontend", + "cranelift-native", + "cranelift-wasm", + "gimli 0.28.1", + "log", + "object 0.32.2", + "target-lexicon", + "thiserror", + "wasmparser 0.118.2", + "wasmtime-cranelift-shared", + "wasmtime-environ 16.0.0", + "wasmtime-versioned-export-macros", +] + +[[package]] +name = "wasmtime-cranelift-shared" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290a89027688782da8ff60b12bb95695494b1874e0d0ba2ba387d23dace6d70c" +dependencies = [ + "anyhow", + "cranelift-codegen", + "cranelift-control", + "cranelift-native", + "gimli 0.28.1", + "object 0.32.2", + "target-lexicon", + "wasmtime-environ 16.0.0", +] + [[package]] name = "wasmtime-environ" version = "8.0.1" @@ -9669,7 +10177,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a990198cee4197423045235bf89d3359e69bd2ea031005f4c2d901125955c949" dependencies = [ "anyhow", - "cranelift-entity", + "cranelift-entity 0.95.1", "gimli 0.27.3", "indexmap 1.9.3", "log", @@ -9677,8 +10185,43 @@ dependencies = [ "serde", "target-lexicon", "thiserror", - "wasmparser", - "wasmtime-types", + "wasmparser 0.102.0", + "wasmtime-types 8.0.1", +] + +[[package]] +name = "wasmtime-environ" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61eb64fb3e0da883e2df4a13a81d6282e072336e6cb6295021d0f7ab2e352754" +dependencies = [ + "anyhow", + "cranelift-entity 0.103.0", + "gimli 0.28.1", + "indexmap 2.2.5", + "log", + "object 0.32.2", + "serde", + "serde_derive", + "target-lexicon", + "thiserror", + "wasmparser 0.118.2", + "wasmtime-types 16.0.0", +] + +[[package]] +name = "wasmtime-fiber" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecf1d3a838b0956b71ad3f8cb80069a228339775bf02dd35d86a5a68bbe443" +dependencies = [ + "anyhow", + "cc", + "cfg-if", + "rustix 0.38.31", + "wasmtime-asm-macros 16.0.0", + "wasmtime-versioned-export-macros", + "windows-sys 0.48.0", ] [[package]] @@ -9698,12 +10241,34 @@ dependencies = [ "rustc-demangle", "serde", "target-lexicon", - "wasmtime-environ", - "wasmtime-jit-icache-coherence", - "wasmtime-runtime", + "wasmtime-environ 8.0.1", + "wasmtime-jit-icache-coherence 8.0.1", + "wasmtime-runtime 8.0.1", "windows-sys 0.45.0", ] +[[package]] +name = "wasmtime-jit" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f485336add49267d8859e8f8084d2d4b9a4b1564496b6f30ba5b168d50c10ceb" +dependencies = [ + "anyhow", + "bincode", + "cfg-if", + "gimli 0.28.1", + "log", + "object 0.32.2", + "rustix 0.38.31", + "serde", + "serde_derive", + "target-lexicon", + "wasmtime-environ 16.0.0", + "wasmtime-jit-icache-coherence 16.0.0", + "wasmtime-runtime 16.0.0", + "windows-sys 0.48.0", +] + [[package]] name = "wasmtime-jit-debug" version = "8.0.1" @@ -9724,6 +10289,17 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "wasmtime-jit-icache-coherence" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b6d197fcc34ad32ed440e1f9552fd57d1f377d9699d31dee1b5b457322c1f8a" +dependencies = [ + "cfg-if", + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "wasmtime-runtime" version = "8.0.1" @@ -9738,28 +10314,98 @@ dependencies = [ "log", "mach", "memfd", - "memoffset", + "memoffset 0.8.0", "paste", "rand 0.8.5", "rustix 0.36.17", - "wasmtime-asm-macros", - "wasmtime-environ", + "wasmtime-asm-macros 8.0.1", + "wasmtime-environ 8.0.1", "wasmtime-jit-debug", "windows-sys 0.45.0", ] +[[package]] +name = "wasmtime-runtime" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "794b2bb19b99ef8322ff0dd9fe1ba7e19c41036dfb260b3f99ecce128c42ff92" +dependencies = [ + "anyhow", + "cc", + "cfg-if", + "indexmap 2.2.5", + "libc", + "log", + "mach", + "memfd", + "memoffset 0.9.0", + "paste", + "psm", + "rustix 0.38.31", + "sptr", + "wasm-encoder", + "wasmtime-asm-macros 16.0.0", + "wasmtime-environ 16.0.0", + "wasmtime-fiber", + "wasmtime-versioned-export-macros", + "wasmtime-wmemcheck", + "windows-sys 0.48.0", +] + [[package]] name = "wasmtime-types" version = "8.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4f6fffd2a1011887d57f07654dd112791e872e3ff4a2e626aee8059ee17f06f" dependencies = [ - "cranelift-entity", + "cranelift-entity 0.95.1", + "serde", + "thiserror", + "wasmparser 0.102.0", +] + +[[package]] +name = "wasmtime-types" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d995db8bb56f2cd8d2dc0ed5ffab94ffb435283b0fe6747f80f7aab40b2d06a1" +dependencies = [ + "cranelift-entity 0.103.0", "serde", + "serde_derive", "thiserror", - "wasmparser", + "wasmparser 0.118.2", +] + +[[package]] +name = "wasmtime-versioned-export-macros" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55c5565959287c21dd0f4277ae3518dd2ae62679f655ee2dbc4396e19d210db" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", ] +[[package]] +name = "wasmtime-wit-bindgen" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f328b2d4a690270324756e886ed5be3a4da4c00be0eea48253f4595ad068062b" +dependencies = [ + "anyhow", + "heck", + "indexmap 2.2.5", + "wit-parser", +] + +[[package]] +name = "wasmtime-wmemcheck" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67761d8f8c0b3c13a5d34356274b10a40baba67fe9cfabbfc379a8b414e45de2" + [[package]] name = "web-sys" version = "0.3.69" @@ -10073,6 +10719,23 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "wit-parser" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "316b36a9f0005f5aa4b03c39bc3728d045df136f8c13a73b7db4510dec725e08" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.2.5", + "log", + "semver 1.0.22", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", +] + [[package]] name = "wyz" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index 96645bf0..3384391d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,13 @@ ink_env = { version = "5.0.0-rc.2", optional = true } sp-weights = { version ="29.0.0", optional = true } ansi_term = "0.12.1" +# light-client +async-stream = { version = "0.3", optional = true } +smoldot = { version = "0.17", optional = true } +smoldot-light = { version = "0.15", optional = true } +thousands = { version = "0.2", optional = true } +tokio-stream = { version = "0.1", optional = true } + # parachains dirs = { version = "5.0", optional = true } indexmap = { version = "2.2", optional = true } @@ -61,6 +68,15 @@ contract = [ "dep:ink_env", "dep:sp-weights", ] +light-client = [ + "dep:async-stream", + "dep:serde", + "dep:serde_json", + "dep:smoldot", + "dep:smoldot-light", + "dep:thousands", + "dep:tokio-stream" +] parachain = [ "dep:dirs", "dep:indexmap", diff --git a/src/commands/follow/mod.rs b/src/commands/follow/mod.rs new file mode 100644 index 00000000..0607a346 --- /dev/null +++ b/src/commands/follow/mod.rs @@ -0,0 +1,183 @@ +use crate::Result; +use anyhow::anyhow; +use clap::{Args, Subcommand}; +use console::style; +use log::debug; +use serde::Deserialize; +use smoldot_light::{ + platform::DefaultPlatform, AddChainConfig, AddChainConfigJsonRpc, AddChainSuccess, ChainId, + Client, JsonRpcResponses, +}; +use std::{iter, num::NonZeroU32, pin::Pin, sync::Arc}; +use thousands::Separable; +use tokio_stream::{Stream, StreamExt, StreamMap}; + +#[derive(Args)] +#[command(args_conflicts_with_subcommands = true)] +pub(crate) struct FollowArgs { + #[command(subcommand)] + pub(crate) command: FollowCommands, +} + +#[derive(Subcommand)] +pub(crate) enum FollowCommands { + /// Follow one or more chains. + #[clap(alias = "c")] + Chain(FollowChainCommand), +} + +#[derive(Args)] +pub(crate) struct FollowChainCommand { + /// The path to a relay chain's chain-spec. + #[arg(short, long)] + relay_chain: String, + /// The path to a parachain's chain-spec. + #[arg(short, long)] + parachain: Option>, +} + +impl FollowChainCommand { + pub(crate) async fn execute(&self) -> Result<()> { + //tracing_subscriber::fmt().init(); + + let mut client = Client::new(DefaultPlatform::new( + env!("CARGO_PKG_NAME").into(), + env!("CARGO_PKG_VERSION").into(), + )); + + let json_rpc_config = AddChainConfigJsonRpc::Enabled { + max_pending_requests: NonZeroU32::new(128).expect("value is valid"), + max_subscriptions: 1024, + }; + + let mut chains = StreamMap::new(); + + // Add relay chain + let specification = std::fs::read_to_string(&self.relay_chain)?; + let AddChainSuccess { + chain_id: relay_chain_id, + json_rpc_responses, + } = client + .add_chain(AddChainConfig { + specification: &specification, + json_rpc: json_rpc_config.clone(), + potential_relay_chains: iter::empty(), + // todo: save/read database using cache + database_content: "", + user_data: (), + }) + .map_err(|e| anyhow!("{e}"))?; + chains.insert( + Chain::new(relay_chain_id, Self::name(&specification)?), + Self::stream(json_rpc_responses), + ); + + // Add parachain(s) + if let Some(parachains) = &self.parachain { + for parachain in parachains { + let specification = std::fs::read_to_string(¶chain)?; + let AddChainSuccess { + chain_id, + json_rpc_responses, + } = client + .add_chain(AddChainConfig { + specification: &specification, + json_rpc: json_rpc_config.clone(), + // todo: save/read database using cache + database_content: "", + user_data: (), + potential_relay_chains: [relay_chain_id].into_iter(), + }) + .map_err(|e| anyhow!("{e}"))?; + chains.insert( + Chain::new(chain_id, Self::name(&specification)?), + Self::stream(json_rpc_responses), + ); + } + } + + // Subscribe to best block on each chain + for chain in chains.keys() { + client + .json_rpc_request( + r#"{"id":1,"jsonrpc":"2.0","method":"chain_subscribeNewHeads","params":[]}"#, + chain.id, + ) + .unwrap(); + } + + loop { + let (chain, response) = chains.next().await.unwrap(); + match serde_json::from_str(&response) { + Ok(response) => match response { + Response::NewHead { header } => { + let block_number = u32::from_str_radix(&header.number[2..], 16).unwrap(); + println!( + "{}: #{}{}", + chain.name, + block_number.separate_with_commas(), + style(format!( + ", parent hash: {}, state root: {}, extrinsics root: {}", + header.parent_hash, header.state_root, header.extrinsics_root + )) + .dim() + ); + } + }, + Err(e) => { + debug!("unable to deserialize response: {e} {response}"); + } + } + } + } + + // Convert JSON RPC responses to a stream + fn stream( + json_rpc_responses: Option>>, + ) -> Pin + Send>> { + let mut json_rpc_responses = json_rpc_responses.unwrap(); + let stream = Box::pin(async_stream::stream! { + while let Some(item) = json_rpc_responses.next().await { + yield item; + } + }) as Pin + Send>>; + stream + } + + // Extract the name from a chain spec. + fn name(specification: &str) -> Result { + smoldot::chain_spec::ChainSpec::from_json_bytes(specification) + .map(|cs| cs.name().into()) + .map_err(|e| anyhow!("error parsing chain-spec: {e}")) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +struct Chain { + id: ChainId, + name: String, +} +impl Chain { + fn new(id: ChainId, name: String) -> Self { + Self { id, name } + } +} + +#[derive(Deserialize)] +#[serde(tag = "method", content = "params")] +enum Response { + #[serde(alias = "chain_newHead")] + NewHead { + #[serde(alias = "result")] + header: Header, + }, +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct Header { + parent_hash: String, + number: String, + state_root: String, + extrinsics_root: String, +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 8d0fc971..5ec2cc2f 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,5 +1,7 @@ pub(crate) mod build; pub(crate) mod call; +#[cfg(feature = "light-client")] +pub(crate) mod follow; pub(crate) mod new; pub(crate) mod test; pub(crate) mod up; diff --git a/src/main.rs b/src/main.rs index 05ee24aa..cec5f0a5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,6 +44,10 @@ enum Commands { /// Test a smart contract. #[clap(alias = "t")] Test(commands::test::TestArgs), + /// Follow one or more chains. + #[cfg(feature = "light-client")] + #[clap(alias = "f")] + Follow(commands::follow::FollowArgs), } #[tokio::main] @@ -78,6 +82,10 @@ async fn main() -> Result<()> { #[cfg(feature = "contract")] commands::test::TestCommands::Contract(cmd) => cmd.execute(), }, + #[cfg(feature = "light-client")] + Commands::Follow(args) => Ok(match &args.command { + commands::follow::FollowCommands::Chain(cmd) => cmd.execute().await?, + }), } }