diff --git a/Cargo.lock b/Cargo.lock index 3f6fef3a..95e489fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -627,6 +627,51 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "asn1-rs" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56624a96882bb8c26d61312ae18cb45868e5a9992ea73c58e45c3101e56a1e60" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom 7.1.3", + "num-traits", + "rusticata-macros", + "thiserror 2.0.18", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "asn1_der" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4858a9d740c5007a9069007c3b4e91152d0506f13c1b31dd49051fd537656156" + [[package]] name = "astral-tokio-tar" version = "0.6.1" @@ -677,6 +722,36 @@ dependencies = [ "serde", ] +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "windows-sys 0.61.2", +] + [[package]] name = "async-lock" version = "3.4.2" @@ -694,6 +769,17 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4288f83726785267c6f2ef073a3d83dc3f9b81464e9f99898240cced85fce35a" +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "async-stream" version = "0.3.6" @@ -727,6 +813,19 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "asynchronous-codec" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a860072022177f903e59730004fb5dc13db9275b79bb2aef7ba8ce831956c233" +dependencies = [ + "bytes", + "futures-sink", + "futures-util", + "memchr", + "pin-project-lite", +] + [[package]] name = "ata_core" version = "0.1.0" @@ -760,6 +859,29 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "attohttpc" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d9a9bf8b79a749ee0b911b91b671cc2b6c670bdbc7e3dfd537576ddc94bb2a2" +dependencies = [ + "http 0.2.12", + "log", + "url", +] + +[[package]] +name = "attohttpc" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e2cdb6d5ed835199484bb92bb8b3edd526effe995c61732580439c1a67e2e9" +dependencies = [ + "base64 0.22.1", + "http 1.4.0", + "log", + "url", +] + [[package]] name = "attribute-derive" version = "0.10.5" @@ -806,7 +928,7 @@ dependencies = [ "axum-core 0.4.5", "bytes", "futures-util", - "http", + "http 1.4.0", "http-body", "http-body-util", "hyper", @@ -840,7 +962,7 @@ dependencies = [ "bytes", "form_urlencoded", "futures-util", - "http", + "http 1.4.0", "http-body", "http-body-util", "hyper", @@ -875,7 +997,7 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http", + "http 1.4.0", "http-body", "http-body-util", "mime", @@ -894,7 +1016,7 @@ checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" dependencies = [ "bytes", "futures-core", - "http", + "http 1.4.0", "http-body", "http-body-util", "mime", @@ -905,6 +1027,17 @@ dependencies = [ "tracing", ] +[[package]] +name = "backon" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef" +dependencies = [ + "fastrand", + "gloo-timers 0.3.0", + "tokio", +] + [[package]] name = "base-x" version = "0.2.11" @@ -957,24 +1090,6 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" -[[package]] -name = "bedrock_client" -version = "0.1.0" -dependencies = [ - "anyhow", - "common", - "futures", - "humantime-serde", - "log", - "logos-blockchain-chain-broadcast-service", - "logos-blockchain-chain-service", - "logos-blockchain-common-http-client", - "logos-blockchain-core", - "reqwest", - "serde", - "tokio-retry", -] - [[package]] name = "bincode" version = "1.3.3" @@ -1101,7 +1216,7 @@ dependencies = [ "futures-util", "hex", "home", - "http", + "http 1.4.0", "http-body-util", "hyper", "hyper-named-pipe", @@ -1354,17 +1469,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" -[[package]] -name = "cfg_eval" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45565fc9416b9896014f5732ac776f810ee53a66730c17e4020c3ec064a8f88f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "chacha20" version = "0.10.0" @@ -1974,6 +2078,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "der-parser" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom 7.1.3", + "num-bigint 0.4.6", + "num-traits", + "rusticata-macros", +] + [[package]] name = "deranged" version = "0.5.8" @@ -2123,6 +2241,17 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "dlopen2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b4f5f101177ff01b8ec4ecc81eead416a8aa42819a2869311b3420fa114ffa" +dependencies = [ + "libc", + "once_cell", + "winapi", +] + [[package]] name = "docker-compose-types" version = "0.23.0" @@ -2178,6 +2307,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "669a445ee724c5c69b1b06fe0b63e70a1c84bc9bb7d9696cd4f4e3ec45050408" +[[package]] +name = "dtoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" + [[package]] name = "duplicate" version = "2.0.1" @@ -2216,6 +2351,7 @@ version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ + "pkcs8", "serde", "signature", ] @@ -2317,6 +2453,18 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enum-as-inner" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "enum-map" version = "2.7.3" @@ -2584,15 +2732,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared 0.1.1", -] - [[package]] name = "foreign-types" version = "0.5.0" @@ -2600,7 +2739,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ "foreign-types-macros", - "foreign-types-shared 0.3.1", + "foreign-types-shared", ] [[package]] @@ -2614,12 +2753,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "foreign-types-shared" version = "0.3.1" @@ -2656,6 +2789,16 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-bounded" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91f328e7fb845fc832912fb6a34f40cf6d1888c92f974d1893a54e97b5ff542e" +dependencies = [ + "futures-timer", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.32" @@ -2689,6 +2832,16 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.32" @@ -2700,6 +2853,17 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "futures-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f2f12607f92c69b12ed746fabf9ca4f5c482cba46679c1a75b874ed7c26adb" +dependencies = [ + "futures-io", + "rustls", + "rustls-pki-types", +] + [[package]] name = "futures-sink" version = "0.3.32" @@ -2718,7 +2882,7 @@ version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" dependencies = [ - "gloo-timers", + "gloo-timers 0.2.6", "send_wrapper 0.4.0", ] @@ -2865,7 +3029,7 @@ dependencies = [ "futures-core", "futures-sink", "gloo-utils", - "http", + "http 1.4.0", "js-sys", "pin-project", "serde", @@ -2888,6 +3052,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "gloo-utils" version = "0.2.0" @@ -2929,7 +3105,7 @@ dependencies = [ "fnv", "futures-core", "futures-sink", - "http", + "http 1.4.0", "indexmap 2.13.0", "slab", "tokio", @@ -2977,6 +3153,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", + "equivalent", "foldhash", ] @@ -2986,6 +3163,15 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +[[package]] +name = "hashlink" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" +dependencies = [ + "hashbrown 0.14.5", +] + [[package]] name = "hashlink" version = "0.10.0" @@ -3015,6 +3201,12 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + [[package]] name = "hex" version = "0.4.3" @@ -3042,6 +3234,59 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1" +[[package]] +name = "hex_fmt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" + +[[package]] +name = "hickory-proto" +version = "0.25.0-alpha.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d00147af6310f4392a31680db52a3ed45a2e0f68eb18e8c3fe5537ecc96d9e2" +dependencies = [ + "async-recursion", + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna", + "ipnet", + "once_cell", + "rand 0.9.3", + "socket2 0.5.10", + "thiserror 2.0.18", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.25.0-alpha.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5762f69ebdbd4ddb2e975cd24690bf21fe6b2604039189c26acddbc427f12887" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "moka", + "once_cell", + "parking_lot", + "rand 0.9.3", + "resolv-conf", + "smallvec", + "thiserror 2.0.18", + "tokio", + "tracing", +] + [[package]] name = "hkdf" version = "0.12.4" @@ -3095,6 +3340,17 @@ dependencies = [ "utf8-width", ] +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http" version = "1.4.0" @@ -3112,7 +3368,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http", + "http 1.4.0", ] [[package]] @@ -3123,7 +3379,7 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", "futures-core", - "http", + "http 1.4.0", "http-body", "pin-project-lite", ] @@ -3198,7 +3454,7 @@ dependencies = [ "futures-channel", "futures-core", "h2", - "http", + "http 1.4.0", "http-body", "httparse", "httpdate", @@ -3231,7 +3487,7 @@ version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "http", + "http 1.4.0", "hyper", "hyper-util", "log", @@ -3256,22 +3512,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - [[package]] name = "hyper-util" version = "0.1.20" @@ -3282,19 +3522,17 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http", + "http 1.4.0", "http-body", "hyper", "ipnet", "libc", "percent-encoding", "pin-project-lite", - "socket2", - "system-configuration", + "socket2 0.6.3", "tokio", "tower-service", "tracing", - "windows-registry", ] [[package]] @@ -3450,6 +3688,81 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "if-addrs" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0a05c691e1fae256cf7013d99dad472dc52d5543322761f83ec8d47eab40d2b" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "if-watch" +version = "3.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71c02a5161c313f0cbdbadc511611893584a10a7b6153cb554bdf83ddce99ec2" +dependencies = [ + "async-io", + "core-foundation 0.9.4", + "fnv", + "futures", + "if-addrs", + "ipnet", + "log", + "netlink-packet-core 0.8.1", + "netlink-packet-route 0.28.0", + "netlink-proto", + "netlink-sys", + "rtnetlink", + "system-configuration 0.7.0", + "tokio", + "windows", +] + +[[package]] +name = "igd-next" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76b0d7d4541def58a37bf8efc559683f21edce7c82f0d866c93ac21f7e098f93" +dependencies = [ + "async-trait", + "attohttpc 0.24.1", + "bytes", + "futures", + "http 1.4.0", + "http-body-util", + "hyper", + "hyper-util", + "log", + "rand 0.8.5", + "tokio", + "url", + "xmltree", +] + +[[package]] +name = "igd-next" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516893339c97f6011282d5825ac94fc1c7aad5cad26bdc2d0cee068c0bf97f97" +dependencies = [ + "async-trait", + "attohttpc 0.30.1", + "bytes", + "futures", + "http 1.4.0", + "http-body-util", + "hyper", + "hyper-util", + "log", + "rand 0.9.3", + "tokio", + "url", + "xmltree", +] + [[package]] name = "include_bytes_aligned" version = "0.1.4" @@ -3462,13 +3775,13 @@ version = "0.1.0" dependencies = [ "anyhow", "async-stream", - "bedrock_client", "borsh", "common", "futures", "humantime-serde", "log", "logos-blockchain-core", + "logos-blockchain-zone-sdk", "nssa", "nssa_core", "serde", @@ -3604,6 +3917,7 @@ dependencies = [ "indexer_ffi", "indexer_service", "indexer_service_rpc", + "jsonrpsee", "key_protocol", "log", "nssa", @@ -3637,6 +3951,19 @@ dependencies = [ "rustversion", ] +[[package]] +name = "ipconfig" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222" +dependencies = [ + "socket2 0.6.3", + "widestring", + "windows-registry", + "windows-result", + "windows-sys 0.61.2", +] + [[package]] name = "ipnet" version = "2.12.0" @@ -3820,7 +4147,7 @@ dependencies = [ "futures-channel", "futures-util", "gloo-net", - "http", + "http 1.4.0", "jsonrpsee-core", "pin-project", "rustls", @@ -3845,7 +4172,7 @@ dependencies = [ "bytes", "futures-timer", "futures-util", - "http", + "http 1.4.0", "http-body", "http-body-util", "jsonrpsee-types", @@ -3906,7 +4233,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c51b7c290bb68ce3af2d029648148403863b982f138484a73f02a9dd52dbd7f" dependencies = [ "futures-util", - "http", + "http 1.4.0", "http-body", "http-body-util", "hyper", @@ -3932,7 +4259,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc88ff4688e43cc3fa9883a8a95c6fa27aa2e76c96e610b737b6554d650d7fd5" dependencies = [ - "http", + "http 1.4.0", "serde", "serde_json", "thiserror 2.0.18", @@ -3956,7 +4283,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b6fceceeb05301cc4c065ab3bd2fa990d41ff4eb44e4ca1b30fa99c057c3e79" dependencies = [ - "http", + "http 1.4.0", "jsonrpsee-client-transport", "jsonrpsee-core", "jsonrpsee-types", @@ -4312,18 +4639,401 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" +[[package]] +name = "libp2p" +version = "0.55.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b72dc443ddd0254cb49a794ed6b6728400ee446a0f7ab4a07d0209ee98de20e9" +dependencies = [ + "bytes", + "either", + "futures", + "futures-timer", + "getrandom 0.2.17", + "libp2p-allow-block-list", + "libp2p-autonat", + "libp2p-connection-limits", + "libp2p-core", + "libp2p-dns", + "libp2p-gossipsub", + "libp2p-identify", + "libp2p-identity", + "libp2p-kad", + "libp2p-mdns", + "libp2p-metrics", + "libp2p-quic", + "libp2p-swarm", + "libp2p-tcp", + "libp2p-upnp", + "multiaddr", + "pin-project", + "rw-stream-sink", + "thiserror 2.0.18", +] + +[[package]] +name = "libp2p-allow-block-list" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38944b7cb981cc93f2f0fb411ff82d0e983bd226fbcc8d559639a3a73236568b" +dependencies = [ + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", +] + +[[package]] +name = "libp2p-autonat" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e297bfc6cabb70c6180707f8fa05661b77ecb9cb67e8e8e1c469301358fa21d0" +dependencies = [ + "async-trait", + "asynchronous-codec", + "either", + "futures", + "futures-bounded", + "futures-timer", + "libp2p-core", + "libp2p-identity", + "libp2p-request-response", + "libp2p-swarm", + "quick-protobuf", + "quick-protobuf-codec", + "rand 0.8.5", + "rand_core 0.6.4", + "thiserror 2.0.18", + "tracing", + "web-time", +] + +[[package]] +name = "libp2p-connection-limits" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efe9323175a17caa8a2ed4feaf8a548eeef5e0b72d03840a0eab4bcb0210ce1c" +dependencies = [ + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", +] + +[[package]] +name = "libp2p-core" +version = "0.43.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "249128cd37a2199aff30a7675dffa51caf073b51aa612d2f544b19932b9aebca" +dependencies = [ + "either", + "fnv", + "futures", + "futures-timer", + "libp2p-identity", + "multiaddr", + "multihash", + "multistream-select", + "parking_lot", + "pin-project", + "quick-protobuf", + "rand 0.8.5", + "rw-stream-sink", + "thiserror 2.0.18", + "tracing", + "unsigned-varint 0.8.0", + "web-time", +] + +[[package]] +name = "libp2p-dns" +version = "0.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b780a1150214155b0ed1cdf09fbd2e1b0442604f9146a431d1b21d23eef7bd7" +dependencies = [ + "async-trait", + "futures", + "hickory-resolver", + "libp2p-core", + "libp2p-identity", + "parking_lot", + "smallvec", + "tracing", +] + +[[package]] +name = "libp2p-gossipsub" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d558548fa3b5a8e9b66392f785921e363c57c05dcadfda4db0d41ae82d313e4a" +dependencies = [ + "async-channel", + "asynchronous-codec", + "base64 0.22.1", + "byteorder", + "bytes", + "either", + "fnv", + "futures", + "futures-timer", + "getrandom 0.2.17", + "hashlink 0.9.1", + "hex_fmt", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "prometheus-client", + "quick-protobuf", + "quick-protobuf-codec", + "rand 0.8.5", + "regex", + "serde", + "sha2", + "tracing", + "web-time", +] + +[[package]] +name = "libp2p-identify" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c06862544f02d05d62780ff590cc25a75f5c2b9df38ec7a370dcae8bb873cf" +dependencies = [ + "asynchronous-codec", + "either", + "futures", + "futures-bounded", + "futures-timer", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "quick-protobuf", + "quick-protobuf-codec", + "smallvec", + "thiserror 2.0.18", + "tracing", +] + [[package]] name = "libp2p-identity" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0c7892c221730ba55f7196e98b0b8ba5e04b4155651736036628e9f73ed6fc3" dependencies = [ + "asn1_der", "bs58", + "ed25519-dalek", "hkdf", + "k256", "multihash", + "quick-protobuf", + "rand 0.8.5", + "serde", "sha2", "thiserror 2.0.18", "tracing", + "zeroize", +] + +[[package]] +name = "libp2p-kad" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bab0466a27ebe955bcbc27328fae5429c5b48c915fd6174931414149802ec23" +dependencies = [ + "asynchronous-codec", + "bytes", + "either", + "fnv", + "futures", + "futures-bounded", + "futures-timer", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "quick-protobuf", + "quick-protobuf-codec", + "rand 0.8.5", + "serde", + "sha2", + "smallvec", + "thiserror 2.0.18", + "tracing", + "uint", + "web-time", +] + +[[package]] +name = "libp2p-mdns" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d0ba095e1175d797540e16b62e7576846b883cb5046d4159086837b36846cc" +dependencies = [ + "futures", + "hickory-proto", + "if-watch", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "rand 0.8.5", + "smallvec", + "socket2 0.5.10", + "tokio", + "tracing", +] + +[[package]] +name = "libp2p-metrics" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ce58c64292e87af624fcb86465e7dd8342e46a388d71e8fec0ab37ee789630a" +dependencies = [ + "futures", + "libp2p-core", + "libp2p-gossipsub", + "libp2p-identify", + "libp2p-identity", + "libp2p-kad", + "libp2p-swarm", + "pin-project", + "prometheus-client", + "web-time", +] + +[[package]] +name = "libp2p-quic" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41432a159b00424a0abaa2c80d786cddff81055ac24aa127e0cf375f7858d880" +dependencies = [ + "futures", + "futures-timer", + "if-watch", + "libp2p-core", + "libp2p-identity", + "libp2p-tls", + "quinn", + "rand 0.8.5", + "ring", + "rustls", + "socket2 0.5.10", + "thiserror 2.0.18", + "tokio", + "tracing", +] + +[[package]] +name = "libp2p-request-response" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "548fe44a80ff275d400f1b26b090d441d83ef73efabbeb6415f4ce37e5aed865" +dependencies = [ + "async-trait", + "futures", + "futures-bounded", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "rand 0.8.5", + "smallvec", + "tracing", +] + +[[package]] +name = "libp2p-stream" +version = "0.3.0-alpha" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826716f1ee125895f1fb44911413cba023485b552ff96c7a2159bd037ac619bb" +dependencies = [ + "futures", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm", + "rand 0.8.5", + "tracing", +] + +[[package]] +name = "libp2p-swarm" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "803399b4b6f68adb85e63ab573ac568154b193e9a640f03e0f2890eabbcb37f8" +dependencies = [ + "either", + "fnv", + "futures", + "futures-timer", + "libp2p-core", + "libp2p-identity", + "libp2p-swarm-derive", + "lru", + "multistream-select", + "once_cell", + "rand 0.8.5", + "smallvec", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "libp2p-swarm-derive" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206e0aa0ebe004d778d79fb0966aa0de996c19894e2c0605ba2f8524dd4443d8" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "libp2p-tcp" +version = "0.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65346fb4d36035b23fec4e7be4c320436ba53537ce9b6be1d1db1f70c905cad0" +dependencies = [ + "futures", + "futures-timer", + "if-watch", + "libc", + "libp2p-core", + "socket2 0.5.10", + "tokio", + "tracing", +] + +[[package]] +name = "libp2p-tls" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96ff65a82e35375cbc31ebb99cacbbf28cb6c4fefe26bf13756ddcf708d40080" +dependencies = [ + "futures", + "futures-rustls", + "libp2p-core", + "libp2p-identity", + "rcgen", + "ring", + "rustls", + "rustls-webpki", + "thiserror 2.0.18", + "x509-parser", + "yasna", +] + +[[package]] +name = "libp2p-upnp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d457b9ecceb66e7199f049926fad447f1f17f040e8d29d690c086b4cab8ed14a" +dependencies = [ + "futures", + "futures-timer", + "igd-next 0.15.1", + "libp2p-core", + "libp2p-swarm", + "tokio", + "tracing", ] [[package]] @@ -4403,8 +5113,8 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "logos-blockchain-blend-crypto" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "blake2", "logos-blockchain-groth16", @@ -4417,8 +5127,8 @@ dependencies = [ [[package]] name = "logos-blockchain-blend-message" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "blake2", "derivative", @@ -4440,8 +5150,8 @@ dependencies = [ [[package]] name = "logos-blockchain-blend-proofs" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "ed25519-dalek", "generic-array 1.3.5", @@ -4459,8 +5169,8 @@ dependencies = [ [[package]] name = "logos-blockchain-chain-broadcast-service" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "async-trait", "derivative", @@ -4475,11 +5185,12 @@ dependencies = [ [[package]] name = "logos-blockchain-chain-service" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "async-trait", "bytes", + "derivative", "futures", "logos-blockchain-chain-broadcast-service", "logos-blockchain-core", @@ -4493,7 +5204,6 @@ dependencies = [ "logos-blockchain-time-service", "logos-blockchain-tracing", "logos-blockchain-utils", - "num-bigint 0.4.6", "overwatch", "serde", "serde_with", @@ -4506,8 +5216,8 @@ dependencies = [ [[package]] name = "logos-blockchain-circuits-prover" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "logos-blockchain-circuits-utils", "tempfile", @@ -4515,16 +5225,16 @@ dependencies = [ [[package]] name = "logos-blockchain-circuits-utils" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "dirs", ] [[package]] name = "logos-blockchain-common-http-client" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "futures", "hex", @@ -4543,8 +5253,8 @@ dependencies = [ [[package]] name = "logos-blockchain-core" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "ark-ff 0.4.2", "bincode", @@ -4557,6 +5267,7 @@ dependencies = [ "logos-blockchain-cryptarchia-engine", "logos-blockchain-groth16", "logos-blockchain-key-management-system-keys", + "logos-blockchain-mmr", "logos-blockchain-poc", "logos-blockchain-pol", "logos-blockchain-poseidon2", @@ -4565,6 +5276,7 @@ dependencies = [ "multiaddr", "nom 8.0.0", "num-bigint 0.4.6", + "rpds", "serde", "strum", "thiserror 1.0.69", @@ -4573,10 +5285,9 @@ dependencies = [ [[package]] name = "logos-blockchain-cryptarchia-engine" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ - "cfg_eval", "logos-blockchain-pol", "logos-blockchain-utils", "serde", @@ -4589,11 +5300,13 @@ dependencies = [ [[package]] name = "logos-blockchain-cryptarchia-sync" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "bytes", "futures", + "libp2p", + "libp2p-stream", "logos-blockchain-core", "logos-blockchain-cryptarchia-engine", "rand 0.8.5", @@ -4606,8 +5319,8 @@ dependencies = [ [[package]] name = "logos-blockchain-groth16" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "ark-bn254 0.4.0", "ark-ec 0.4.2", @@ -4624,8 +5337,8 @@ dependencies = [ [[package]] name = "logos-blockchain-http-api-common" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "axum 0.7.9", "logos-blockchain-core", @@ -4639,8 +5352,8 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-keys" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "async-trait", "bytes", @@ -4665,8 +5378,8 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-macros" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "proc-macro2", "quote", @@ -4675,8 +5388,8 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-operators" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "async-trait", "logos-blockchain-blend-proofs", @@ -4691,8 +5404,8 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-service" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "async-trait", "log", @@ -4708,8 +5421,8 @@ dependencies = [ [[package]] name = "logos-blockchain-ledger" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "derivative", "logos-blockchain-blend-crypto", @@ -4719,6 +5432,7 @@ dependencies = [ "logos-blockchain-cryptarchia-engine", "logos-blockchain-groth16", "logos-blockchain-key-management-system-keys", + "logos-blockchain-mmr", "logos-blockchain-pol", "logos-blockchain-utils", "logos-blockchain-utxotree", @@ -4731,17 +5445,61 @@ dependencies = [ "tracing", ] +[[package]] +name = "logos-blockchain-libp2p" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" +dependencies = [ + "async-trait", + "backon", + "blake2", + "either", + "futures", + "hex", + "igd-next 0.16.2", + "libp2p", + "logos-blockchain-cryptarchia-sync", + "logos-blockchain-utils", + "multiaddr", + "natpmp", + "netdev", + "num_enum", + "rand 0.8.5", + "serde", + "serde_with", + "thiserror 1.0.69", + "tokio", + "tracing", + "zerocopy", +] + +[[package]] +name = "logos-blockchain-mmr" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" +dependencies = [ + "ark-ff 0.4.2", + "logos-blockchain-groth16", + "logos-blockchain-poseidon2", + "rpds", + "serde", + "thiserror 2.0.18", +] + [[package]] name = "logos-blockchain-network-service" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "async-trait", "futures", "logos-blockchain-core", "logos-blockchain-cryptarchia-sync", + "logos-blockchain-libp2p", "logos-blockchain-tracing", "overwatch", + "rand 0.8.5", + "rand_chacha 0.3.1", "serde", "tokio", "tokio-stream", @@ -4750,8 +5508,8 @@ dependencies = [ [[package]] name = "logos-blockchain-poc" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "logos-blockchain-circuits-prover", "logos-blockchain-circuits-utils", @@ -4766,8 +5524,8 @@ dependencies = [ [[package]] name = "logos-blockchain-pol" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "astro-float", "logos-blockchain-circuits-prover", @@ -4785,8 +5543,8 @@ dependencies = [ [[package]] name = "logos-blockchain-poq" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "logos-blockchain-circuits-prover", "logos-blockchain-circuits-utils", @@ -4802,8 +5560,8 @@ dependencies = [ [[package]] name = "logos-blockchain-poseidon2" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "ark-bn254 0.4.0", "ark-ff 0.4.2", @@ -4813,8 +5571,8 @@ dependencies = [ [[package]] name = "logos-blockchain-services-utils" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "async-trait", "futures", @@ -4828,8 +5586,8 @@ dependencies = [ [[package]] name = "logos-blockchain-storage-service" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "async-trait", "bytes", @@ -4846,15 +5604,18 @@ dependencies = [ [[package]] name = "logos-blockchain-time-service" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "async-trait", "futures", "log", "logos-blockchain-cryptarchia-engine", "logos-blockchain-tracing", + "logos-blockchain-utils", "overwatch", + "serde", + "serde_with", "sntpc", "thiserror 2.0.18", "time", @@ -4865,8 +5626,8 @@ dependencies = [ [[package]] name = "logos-blockchain-tracing" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "opentelemetry", "opentelemetry-appender-tracing", @@ -4877,6 +5638,7 @@ dependencies = [ "rand 0.8.5", "serde", "tokio", + "tonic", "tracing", "tracing-appender", "tracing-gelf", @@ -4888,8 +5650,8 @@ dependencies = [ [[package]] name = "logos-blockchain-utils" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "async-trait", "blake2", @@ -4905,8 +5667,8 @@ dependencies = [ [[package]] name = "logos-blockchain-utxotree" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "ark-ff 0.4.2", "logos-blockchain-groth16", @@ -4919,16 +5681,16 @@ dependencies = [ [[package]] name = "logos-blockchain-witness-generator" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "tempfile", ] [[package]] name = "logos-blockchain-zksign" -version = "0.2.1" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=1da154c74b911318fb853d37261f8a05ffe513b4#1da154c74b911318fb853d37261f8a05ffe513b4" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" dependencies = [ "logos-blockchain-circuits-prover", "logos-blockchain-circuits-utils", @@ -4942,6 +5704,26 @@ dependencies = [ "tracing", ] +[[package]] +name = "logos-blockchain-zone-sdk" +version = "0.1.2" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=ee281a447d95a951752461ee0a6e88eb4a0f17cf#ee281a447d95a951752461ee0a6e88eb4a0f17cf" +dependencies = [ + "async-trait", + "futures", + "logos-blockchain-common-http-client", + "logos-blockchain-core", + "logos-blockchain-groth16", + "logos-blockchain-key-management-system-service", + "rand 0.8.5", + "reqwest", + "rpds", + "serde", + "thiserror 2.0.18", + "tokio", + "tracing", +] + [[package]] name = "loki-api" version = "0.1.3" @@ -4952,6 +5734,15 @@ dependencies = [ "prost-types 0.13.5", ] +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +dependencies = [ + "hashbrown 0.15.5", +] + [[package]] name = "lru-slab" version = "0.1.2" @@ -5156,7 +5947,7 @@ dependencies = [ "bitflags 2.11.0", "block", "core-graphics-types", - "foreign-types 0.5.0", + "foreign-types", "log", "objc", "paste", @@ -5205,6 +5996,23 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "moka" +version = "0.12.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046" +dependencies = [ + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "equivalent", + "parking_lot", + "portable-atomic", + "smallvec", + "tagptr", + "uuid", +] + [[package]] name = "multer" version = "3.1.0" @@ -5214,7 +6022,7 @@ dependencies = [ "bytes", "encoding_rs", "futures-util", - "http", + "http 1.4.0", "httparse", "memchr", "mime", @@ -5237,7 +6045,8 @@ dependencies = [ "percent-encoding", "serde", "static_assertions", - "unsigned-varint", + "unsigned-varint 0.8.0", + "url", ] [[package]] @@ -5259,24 +6068,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89ace881e3f514092ce9efbcb8f413d0ad9763860b828981c2de51ddc666936c" dependencies = [ "no_std_io2", - "unsigned-varint", + "serde", + "unsigned-varint 0.8.0", ] [[package]] -name = "native-tls" -version = "0.2.18" +name = "multistream-select" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" +checksum = "ea0df8e5eec2298a62b326ee4f0d7fe1a6b90a09dfcf9df37b38f947a8c42f19" dependencies = [ - "libc", + "bytes", + "futures", "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", + "pin-project", + "smallvec", + "unsigned-varint 0.7.2", +] + +[[package]] +name = "natpmp" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77366fa8ce34e2e1322dd97da65f11a62f451bd3daae8be6993c00800f61dd07" +dependencies = [ + "async-trait", + "cc", + "netdev", + "tokio", ] [[package]] @@ -5295,6 +6114,108 @@ dependencies = [ "rayon", ] +[[package]] +name = "netdev" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f901362e84cd407be6f8cd9d3a46bccf09136b095792785401ea7d283c79b91d" +dependencies = [ + "dlopen2", + "ipnet", + "libc", + "netlink-packet-core 0.7.0", + "netlink-packet-route 0.17.1", + "netlink-sys", + "once_cell", + "system-configuration 0.6.1", + "windows-sys 0.52.0", +] + +[[package]] +name = "netlink-packet-core" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" +dependencies = [ + "anyhow", + "byteorder", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-core" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3463cbb78394cb0141e2c926b93fc2197e473394b761986eca3b9da2c63ae0f4" +dependencies = [ + "paste", +] + +[[package]] +name = "netlink-packet-route" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "byteorder", + "libc", + "netlink-packet-core 0.7.0", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-route" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ce3636fa715e988114552619582b530481fd5ef176a1e5c1bf024077c2c9445" +dependencies = [ + "bitflags 2.11.0", + "libc", + "log", + "netlink-packet-core 0.8.1", +] + +[[package]] +name = "netlink-packet-utils" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" +dependencies = [ + "anyhow", + "byteorder", + "paste", + "thiserror 1.0.69", +] + +[[package]] +name = "netlink-proto" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b65d130ee111430e47eed7896ea43ca693c387f097dd97376bffafbf25812128" +dependencies = [ + "bytes", + "futures", + "log", + "netlink-packet-core 0.8.1", + "netlink-sys", + "thiserror 2.0.18", +] + +[[package]] +name = "netlink-sys" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6c30ed10fa69cc491d491b85cc971f6bdeb8e7367b7cde2ee6cc878d583fae" +dependencies = [ + "bytes", + "futures-util", + "libc", + "log", + "tokio", +] + [[package]] name = "next_tuple" version = "0.1.0" @@ -5319,6 +6240,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags 2.11.0", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "no_std_io2" version = "0.8.1" @@ -5583,6 +6516,15 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "oid-registry" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" +dependencies = [ + "asn1-rs", +] + [[package]] name = "once_cell" version = "1.21.3" @@ -5601,50 +6543,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" -[[package]] -name = "openssl" -version = "0.10.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" -dependencies = [ - "bitflags 2.11.0", - "cfg-if", - "foreign-types 0.3.2", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "openssl-probe" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" -[[package]] -name = "openssl-sys" -version = "0.9.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "opentelemetry" version = "0.31.0" @@ -5678,7 +6582,7 @@ checksum = "d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d" dependencies = [ "async-trait", "bytes", - "http", + "http 1.4.0", "opentelemetry", "reqwest", ] @@ -5689,7 +6593,7 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f69cd6acbb9af919df949cd1ec9e5e7fdc2ef15d234b6b795aaa525cc02f71f" dependencies = [ - "http", + "http 1.4.0", "opentelemetry", "opentelemetry-http", "opentelemetry-proto", @@ -5853,6 +6757,16 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" +[[package]] +name = "pem" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" +dependencies = [ + "base64 0.22.1", + "serde_core", +] + [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -5933,6 +6847,20 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "windows-sys 0.61.2", +] + [[package]] name = "polyval" version = "0.6.2" @@ -6107,6 +7035,29 @@ dependencies = [ "token_program", ] +[[package]] +name = "prometheus-client" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504ee9ff529add891127c4827eb481bd69dc0ebc72e9a682e187db4caa60c3ca" +dependencies = [ + "dtoa", + "itoa", + "parking_lot", + "prometheus-client-derive-encode", +] + +[[package]] +name = "prometheus-client-derive-encode" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "proptest" version = "1.10.0" @@ -6199,6 +7150,28 @@ dependencies = [ "parking_lot", ] +[[package]] +name = "quick-protobuf" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6da84cc204722a989e01ba2f6e1e276e190f22263d0cb6ce8526fcdb0d2e1f" +dependencies = [ + "byteorder", +] + +[[package]] +name = "quick-protobuf-codec" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15a0580ab32b169745d7a39db2ba969226ca16738931be152a3209b409de2474" +dependencies = [ + "asynchronous-codec", + "bytes", + "quick-protobuf", + "thiserror 1.0.69", + "unsigned-varint 0.8.0", +] + [[package]] name = "quinn" version = "0.11.9" @@ -6207,12 +7180,13 @@ checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" dependencies = [ "bytes", "cfg_aliases", + "futures-io", "pin-project-lite", "quinn-proto", "quinn-udp", "rustc-hash", "rustls", - "socket2", + "socket2 0.6.3", "thiserror 2.0.18", "tokio", "tracing", @@ -6249,7 +7223,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2", + "socket2 0.6.3", "tracing", "windows-sys 0.59.0", ] @@ -6414,6 +7388,19 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rcgen" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" +dependencies = [ + "pem", + "ring", + "rustls-pki-types", + "time", + "yasna", +] + [[package]] name = "reactive_graph" version = "0.2.13" @@ -6554,22 +7541,18 @@ checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes", - "encoding_rs", "futures-channel", "futures-core", "futures-util", "h2", - "http", + "http 1.4.0", "http-body", "http-body-util", "hyper", "hyper-rustls", - "hyper-tls", "hyper-util", "js-sys", "log", - "mime", - "native-tls", "percent-encoding", "pin-project-lite", "quinn", @@ -6580,7 +7563,6 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-native-tls", "tokio-rustls", "tokio-util", "tower", @@ -6594,6 +7576,12 @@ dependencies = [ "webpki-roots", ] +[[package]] +name = "resolv-conf" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" + [[package]] name = "rfc6979" version = "0.4.0" @@ -7052,6 +8040,24 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "rtnetlink" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b960d5d873a75b5be9761b1e73b146f52dddcd27bac75263f40fba686d4d7b5" +dependencies = [ + "futures-channel", + "futures-util", + "log", + "netlink-packet-core 0.8.1", + "netlink-packet-route 0.28.0", + "netlink-proto", + "netlink-sys", + "nix", + "thiserror 1.0.69", + "tokio", +] + [[package]] name = "ruint" version = "1.17.2" @@ -7095,6 +8101,15 @@ dependencies = [ "semver", ] +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom 7.1.3", +] + [[package]] name = "rustix" version = "1.1.4" @@ -7198,6 +8213,17 @@ dependencies = [ "twox-hash", ] +[[package]] +name = "rw-stream-sink" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8c9026ff5d2f23da5e45bbc283f156383001bfb09c4e44256d02c1a685fe9a1" +dependencies = [ + "futures", + "pin-project", + "static_assertions", +] + [[package]] name = "ryu" version = "1.0.23" @@ -7361,17 +8387,16 @@ name = "sequencer_core" version = "0.1.0" dependencies = [ "anyhow", - "bedrock_client", "borsh", "bytesize", "chrono", "common", "futures", "humantime-serde", - "jsonrpsee", "log", "logos-blockchain-core", "logos-blockchain-key-management-system-service", + "logos-blockchain-zone-sdk", "mempool", "nssa", "nssa_core", @@ -7397,7 +8422,6 @@ dependencies = [ "common", "env_logger", "futures", - "indexer_service_rpc", "jsonrpsee", "log", "mempool", @@ -7628,7 +8652,7 @@ dependencies = [ "const_format", "futures", "gloo-net", - "http", + "http 1.4.0", "http-body-util", "hyper", "inventory", @@ -7780,6 +8804,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "socket2" version = "0.6.3" @@ -7799,7 +8833,7 @@ dependencies = [ "base64 0.22.1", "bytes", "futures", - "http", + "http 1.4.0", "httparse", "log", "rand 0.8.5", @@ -7969,6 +9003,17 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.11.0", + "core-foundation 0.9.4", + "system-configuration-sys", +] + [[package]] name = "system-configuration" version = "0.7.0" @@ -8022,6 +9067,12 @@ dependencies = [ "web-sys", ] +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "tap" version = "1.0.1" @@ -8107,7 +9158,7 @@ dependencies = [ "etcetera", "ferroid", "futures", - "http", + "http 1.4.0", "itertools 0.14.0", "log", "memchr", @@ -8287,7 +9338,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.6.3", "tokio-macros", "windows-sys 0.61.2", ] @@ -8303,27 +9354,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-retry" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" -dependencies = [ - "pin-project", - "rand 0.8.5", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.4" @@ -8484,7 +9514,7 @@ dependencies = [ "base64 0.22.1", "bytes", "h2", - "http", + "http 1.4.0", "http-body", "http-body-util", "hyper", @@ -8492,7 +9522,7 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "socket2", + "socket2 0.6.3", "sync_wrapper", "tokio", "tokio-stream", @@ -8542,7 +9572,7 @@ dependencies = [ "bytes", "futures-core", "futures-util", - "http", + "http 1.4.0", "http-body", "http-body-util", "http-range-header", @@ -8750,7 +9780,7 @@ checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" dependencies = [ "bytes", "data-encoding", - "http", + "http 1.4.0", "httparse", "log", "rand 0.9.3", @@ -8831,6 +9861,18 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "uint" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909988d098b2f738727b161a106cfc7cab00c539c2687a8836f8e565976fb53e" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "unarray" version = "0.1.4" @@ -8898,6 +9940,12 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" +[[package]] +name = "unsigned-varint" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" + [[package]] name = "unsigned-varint" version = "0.8.0" @@ -8932,7 +9980,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f" dependencies = [ "base64 0.22.1", - "http", + "http 1.4.0", "httparse", "log", ] @@ -9299,6 +10347,12 @@ dependencies = [ "safe_arch", ] +[[package]] +name = "widestring" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" + [[package]] name = "winapi" version = "0.3.9" @@ -9330,6 +10384,27 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core", +] + [[package]] name = "windows-core" version = "0.62.2" @@ -9343,6 +10418,17 @@ dependencies = [ "windows-strings", ] +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + [[package]] name = "windows-implement" version = "0.60.2" @@ -9371,6 +10457,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core", + "windows-link", +] + [[package]] name = "windows-registry" version = "0.6.1" @@ -9467,6 +10563,15 @@ dependencies = [ "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -9681,6 +10786,23 @@ dependencies = [ "zeroize", ] +[[package]] +name = "x509-parser" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4569f339c0c402346d4a75a9e39cf8dad310e287eef1ff56d4c68e5067f53460" +dependencies = [ + "asn1-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom 7.1.3", + "oid-registry", + "rusticata-macros", + "thiserror 2.0.18", + "time", +] + [[package]] name = "xattr" version = "1.6.1" @@ -9691,6 +10813,21 @@ dependencies = [ "rustix", ] +[[package]] +name = "xml-rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + +[[package]] +name = "xmltree" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7d8a75eaf6557bb84a65ace8609883db44a29951042ada9b393151532e41fcb" +dependencies = [ + "xml-rs", +] + [[package]] name = "xxhash-rust" version = "0.8.15" @@ -9705,7 +10842,7 @@ checksum = "2462ea039c445496d8793d052e13787f2b90e750b833afee748e601c17621ed9" dependencies = [ "arraydeque", "encoding_rs", - "hashlink", + "hashlink 0.10.0", ] [[package]] @@ -9714,6 +10851,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" +[[package]] +name = "yasna" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" +dependencies = [ + "time", +] + [[package]] name = "yoke" version = "0.8.1" diff --git a/Cargo.toml b/Cargo.toml index 96b06460..4fcaf9f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,6 @@ members = [ "examples/program_deployment", "examples/program_deployment/methods", "examples/program_deployment/methods/guest", - "bedrock_client", "testnet_initial_state", "indexer_ffi", ] @@ -67,7 +66,6 @@ amm_program = { path = "programs/amm" } ata_core = { path = "programs/associated_token_account/core" } ata_program = { path = "programs/associated_token_account" } test_program_methods = { path = "test_program_methods" } -bedrock_client = { path = "bedrock_client" } testnet_initial_state = { path = "testnet_initial_state" } tokio = { version = "1.50", features = [ @@ -122,11 +120,12 @@ tokio-retry = "0.3.0" schemars = "1.2" async-stream = "0.3.6" -logos-blockchain-common-http-client = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "1da154c74b911318fb853d37261f8a05ffe513b4" } -logos-blockchain-key-management-system-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "1da154c74b911318fb853d37261f8a05ffe513b4" } -logos-blockchain-core = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "1da154c74b911318fb853d37261f8a05ffe513b4" } -logos-blockchain-chain-broadcast-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "1da154c74b911318fb853d37261f8a05ffe513b4" } -logos-blockchain-chain-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "1da154c74b911318fb853d37261f8a05ffe513b4" } +logos-blockchain-common-http-client = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "ee281a447d95a951752461ee0a6e88eb4a0f17cf" } +logos-blockchain-key-management-system-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "ee281a447d95a951752461ee0a6e88eb4a0f17cf" } +logos-blockchain-core = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "ee281a447d95a951752461ee0a6e88eb4a0f17cf" } +logos-blockchain-chain-broadcast-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "ee281a447d95a951752461ee0a6e88eb4a0f17cf" } +logos-blockchain-chain-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "ee281a447d95a951752461ee0a6e88eb4a0f17cf" } +logos-blockchain-zone-sdk = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "ee281a447d95a951752461ee0a6e88eb4a0f17cf" } rocksdb = { version = "0.24.0", default-features = false, features = [ "snappy", diff --git a/bedrock/deployment-settings.yaml b/bedrock/deployment-settings.yaml index d0c05e24..7ef63f03 100644 --- a/bedrock/deployment-settings.yaml +++ b/bedrock/deployment-settings.yaml @@ -39,42 +39,42 @@ cryptarchia: threshold: 1 timestamp: 0 gossipsub_protocol: /integration/logos-blockchain/cryptarchia/proto/1.0.0 - genesis_state: - mantle_tx: - ops: + genesis_block: + header: + version: Bedrock + parent_block: '0000000000000000000000000000000000000000000000000000000000000000' + slot: 0 + block_root: b5f8787ac23674822414c70eea15d842da38f2e806ede1a73cf7b5cf0277da07 + proof_of_leadership: + proof: '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' + entropy_contribution: '0000000000000000000000000000000000000000000000000000000000000000' + leader_key: '0000000000000000000000000000000000000000000000000000000000000000' + voucher_cm: '0000000000000000000000000000000000000000000000000000000000000000' + signature: '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' + transactions: + - mantle_tx: + ops: - opcode: 0 payload: - inputs: [ ] + inputs: [] outputs: - - value: 1 - pk: d204000000000000000000000000000000000000000000000000000000000000 - - value: 100 - pk: 2e03b2eff5a45478e7e79668d2a146cf2c5c7925bce927f2b1c67f2ab4fc0d26 + - value: 1 + pk: d204000000000000000000000000000000000000000000000000000000000000 + - value: 100 + pk: '2e03b2eff5a45478e7e79668d2a146cf2c5c7925bce927f2b1c67f2ab4fc0d26' + - value: 1 + pk: ed266e6e887b9b97059dc1aa1b7b2e19b934291753c6336a163fe4ebaa28e717 - opcode: 17 payload: - channel_id: "0000000000000000000000000000000000000000000000000000000000000000" - inscription: [ 103, 101, 110, 101, 115, 105, 115 ] # "genesis" in bytes - parent: "0000000000000000000000000000000000000000000000000000000000000000" - signer: "0000000000000000000000000000000000000000000000000000000000000000" - execution_gas_price: 0 - storage_gas_price: 0 - ops_proofs: - - !ZkSig - pi_a: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ] - pi_b: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ] - pi_c: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ] - - NoProof + channel_id: '0000000000000000000000000000000000000000000000000000000000000000' + inscription: '67656e65736973' + parent: '0000000000000000000000000000000000000000000000000000000000000000' + signer: '0000000000000000000000000000000000000000000000000000000000000000' + execution_gas_price: 0 + storage_gas_price: 0 + ops_proofs: + - !Ed25519Sig '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' + - !Ed25519Sig '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' time: slot_duration: '1.0' chain_start_time: PLACEHOLDER_CHAIN_START_TIME diff --git a/bedrock/docker-compose.yml b/bedrock/docker-compose.yml index 73795666..e16e505b 100644 --- a/bedrock/docker-compose.yml +++ b/bedrock/docker-compose.yml @@ -1,7 +1,7 @@ services: logos-blockchain-node-0: - image: ghcr.io/logos-blockchain/logos-blockchain@sha256:c5243681b353278cabb562a176f0a5cfbefc2056f18cebc47fe0e3720c29fb12 + image: ghcr.io/logos-blockchain/logos-blockchain@sha256:9f1829dea335c56f6ff68ae37ea872ed5313b96b69e8ffe143c02b7217de85fc ports: - "${PORT:-8080}:18080/tcp" volumes: diff --git a/bedrock_client/Cargo.toml b/bedrock_client/Cargo.toml deleted file mode 100644 index 2137cb74..00000000 --- a/bedrock_client/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "bedrock_client" -version = "0.1.0" -edition = "2024" -license = { workspace = true } - -[lints] -workspace = true - -[dependencies] -common.workspace = true - -reqwest.workspace = true -anyhow.workspace = true -tokio-retry.workspace = true -futures.workspace = true -log.workspace = true -serde.workspace = true -humantime-serde.workspace = true -logos-blockchain-common-http-client.workspace = true -logos-blockchain-core.workspace = true -logos-blockchain-chain-broadcast-service.workspace = true -logos-blockchain-chain-service.workspace = true diff --git a/bedrock_client/src/lib.rs b/bedrock_client/src/lib.rs deleted file mode 100644 index 4e9bfffd..00000000 --- a/bedrock_client/src/lib.rs +++ /dev/null @@ -1,121 +0,0 @@ -use std::time::Duration; - -use anyhow::{Context as _, Result}; -use common::config::BasicAuth; -use futures::{Stream, TryFutureExt as _}; -#[expect(clippy::single_component_path_imports, reason = "Satisfy machete")] -use humantime_serde; -use log::{info, warn}; -pub use logos_blockchain_chain_broadcast_service::BlockInfo; -use logos_blockchain_chain_service::CryptarchiaInfo; -pub use logos_blockchain_common_http_client::{CommonHttpClient, Error}; -pub use logos_blockchain_core::{block::Block, header::HeaderId, mantle::SignedMantleTx}; -use reqwest::{Client, Url}; -use serde::{Deserialize, Serialize}; -use tokio_retry::Retry; - -/// Fibonacci backoff retry strategy configuration. -#[derive(Debug, Copy, Clone, Serialize, Deserialize)] -pub struct BackoffConfig { - #[serde(with = "humantime_serde")] - pub start_delay: Duration, - pub max_retries: usize, -} - -impl Default for BackoffConfig { - fn default() -> Self { - Self { - start_delay: Duration::from_millis(100), - max_retries: 5, - } - } -} - -/// Simple wrapper -/// maybe extend in the future for our purposes -/// `Clone` is cheap because `CommonHttpClient` is internally reference counted (`Arc`). -#[derive(Clone)] -pub struct BedrockClient { - http_client: CommonHttpClient, - node_url: Url, - backoff: BackoffConfig, -} - -impl BedrockClient { - pub fn new(backoff: BackoffConfig, node_url: Url, auth: Option) -> Result { - info!("Creating Bedrock client with node URL {node_url}"); - let client = Client::builder() - //Add more fields if needed - .timeout(std::time::Duration::from_mins(1)) - .build() - .context("Failed to build HTTP client")?; - - let auth = auth.map(|a| { - logos_blockchain_common_http_client::BasicAuthCredentials::new(a.username, a.password) - }); - - let http_client = CommonHttpClient::new_with_client(client, auth); - Ok(Self { - http_client, - node_url, - backoff, - }) - } - - pub async fn post_transaction(&self, tx: SignedMantleTx) -> Result, Error> { - Retry::spawn(self.backoff_strategy(), || async { - match self - .http_client - .post_transaction(self.node_url.clone(), tx.clone()) - .await - { - Ok(()) => Ok(Ok(())), - Err(err) => match err { - // Retry arm. - // Retrying only reqwest errors: mainly connected to http. - Error::Request(_) => Err(err), - // Returning non-retryable error - Error::Server(_) | Error::Client(_) | Error::Url(_) => Ok(Err(err)), - }, - } - }) - .await - } - - pub async fn get_lib_stream(&self) -> Result, Error> { - self.http_client.get_lib_stream(self.node_url.clone()).await - } - - pub async fn get_block_by_id( - &self, - header_id: HeaderId, - ) -> Result>, Error> { - Retry::spawn(self.backoff_strategy(), || { - self.http_client - .get_block_by_id(self.node_url.clone(), header_id) - .inspect_err(|err| warn!("Block fetching failed with error: {err:#}")) - }) - .await - } - - pub async fn get_consensus_info(&self) -> Result { - Retry::spawn(self.backoff_strategy(), || { - self.http_client - .consensus_info(self.node_url.clone()) - .inspect_err(|err| warn!("Block fetching failed with error: {err:#}")) - }) - .await - } - - fn backoff_strategy(&self) -> impl Iterator { - let start_delay_millis = self - .backoff - .start_delay - .as_millis() - .try_into() - .expect("Start delay must be less than u64::MAX milliseconds"); - - tokio_retry::strategy::FibonacciBackoff::from_millis(start_delay_millis) - .take(self.backoff.max_retries) - } -} diff --git a/configs/docker-all-in-one/indexer_config.json b/configs/docker-all-in-one/indexer_config.json index c2b07e3e..ca99a90c 100644 --- a/configs/docker-all-in-one/indexer_config.json +++ b/configs/docker-all-in-one/indexer_config.json @@ -1,12 +1,8 @@ { "home": "./indexer/service", "consensus_info_polling_interval": "1s", - "bedrock_client_config": { - "addr": "http://logos-blockchain-node-0:18080", - "backoff": { - "start_delay": "100ms", - "max_retries": 5 - } + "bedrock_config": { + "addr": "http://logos-blockchain-node-0:18080" }, "channel_id": "0101010101010101010101010101010101010101010101010101010101010101", "initial_accounts": [ diff --git a/indexer/core/Cargo.toml b/indexer/core/Cargo.toml index 33fe2d9d..d609f5cb 100644 --- a/indexer/core/Cargo.toml +++ b/indexer/core/Cargo.toml @@ -9,7 +9,7 @@ workspace = true [dependencies] common.workspace = true -bedrock_client.workspace = true +logos-blockchain-zone-sdk.workspace = true nssa.workspace = true nssa_core.workspace = true storage.workspace = true @@ -19,13 +19,13 @@ anyhow.workspace = true log.workspace = true serde.workspace = true humantime-serde.workspace = true -tokio.workspace = true borsh.workspace = true futures.workspace = true url.workspace = true logos-blockchain-core.workspace = true serde_json.workspace = true async-stream.workspace = true +tokio.workspace = true [dev-dependencies] tempfile.workspace = true diff --git a/indexer/core/src/block_store.rs b/indexer/core/src/block_store.rs index cff07b0f..71ddfd82 100644 --- a/indexer/core/src/block_store.rs +++ b/indexer/core/src/block_store.rs @@ -1,11 +1,12 @@ use std::{path::Path, sync::Arc}; -use anyhow::Result; -use bedrock_client::HeaderId; +use anyhow::{Context as _, Result}; use common::{ block::{BedrockStatus, Block}, transaction::{NSSATransaction, clock_invocation}, }; +use logos_blockchain_core::{header::HeaderId, mantle::ops::channel::MsgId}; +use logos_blockchain_zone_sdk::Slot; use nssa::{Account, AccountId, V03State}; use nssa_core::BlockId; use storage::indexer::RocksDBIO; @@ -103,6 +104,22 @@ impl IndexerStore { Ok(self.dbio.calculate_state_for_id(block_id)?) } + pub fn get_zone_cursor(&self) -> Result> { + let Some(bytes) = self.dbio.get_zone_sdk_indexer_cursor_bytes()? else { + return Ok(None); + }; + let cursor: (MsgId, Slot) = serde_json::from_slice(&bytes) + .context("Failed to deserialize stored zone-sdk indexer cursor")?; + Ok(Some(cursor)) + } + + pub fn set_zone_cursor(&self, cursor: &(MsgId, Slot)) -> Result<()> { + let bytes = + serde_json::to_vec(cursor).context("Failed to serialize zone-sdk indexer cursor")?; + self.dbio.put_zone_sdk_indexer_cursor_bytes(&bytes)?; + Ok(()) + } + /// Recalculation of final state directly from DB. /// /// Used for indexer healthcheck. diff --git a/indexer/core/src/config.rs b/indexer/core/src/config.rs index 291e54f5..40ac0870 100644 --- a/indexer/core/src/config.rs +++ b/indexer/core/src/config.rs @@ -6,7 +6,6 @@ use std::{ }; use anyhow::{Context as _, Result}; -pub use bedrock_client::BackoffConfig; use common::config::BasicAuth; use humantime_serde; pub use logos_blockchain_core::mantle::ops::channel::ChannelId; @@ -16,8 +15,6 @@ use url::Url; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ClientConfig { - /// For individual RPC requests we use Fibonacci backoff retry strategy. - pub backoff: BackoffConfig, pub addr: Url, #[serde(default, skip_serializing_if = "Option::is_none")] pub auth: Option, @@ -31,7 +28,7 @@ pub struct IndexerConfig { pub signing_key: [u8; 32], #[serde(with = "humantime_serde")] pub consensus_info_polling_interval: Duration, - pub bedrock_client_config: ClientConfig, + pub bedrock_config: ClientConfig, pub channel_id: ChannelId, #[serde(skip_serializing_if = "Option::is_none")] pub initial_public_accounts: Option>, diff --git a/indexer/core/src/lib.rs b/indexer/core/src/lib.rs index 44f0dc19..3d57e540 100644 --- a/indexer/core/src/lib.rs +++ b/indexer/core/src/lib.rs @@ -1,15 +1,14 @@ -use std::collections::VecDeque; +use std::sync::Arc; use anyhow::Result; -use bedrock_client::{BedrockClient, HeaderId}; -use common::{ - HashType, PINATA_BASE58, - block::{Block, HashableBlockData}, -}; -use log::{debug, error, info}; -use logos_blockchain_core::mantle::{ - Op, SignedMantleTx, - ops::channel::{ChannelId, inscribe::InscriptionOp}, +use common::block::{Block, HashableBlockData}; +// ToDo: Remove after testnet +use common::{HashType, PINATA_BASE58}; +use futures::StreamExt as _; +use log::{error, info, warn}; +use logos_blockchain_core::header::HeaderId; +use logos_blockchain_zone_sdk::{ + CommonHttpClient, ZoneMessage, adapter::NodeHttpClient, indexer::ZoneIndexer, }; use nssa::V03State; use testnet_initial_state::initial_state_testnet; @@ -21,25 +20,11 @@ pub mod config; #[derive(Clone)] pub struct IndexerCore { - pub bedrock_client: BedrockClient, + pub zone_indexer: Arc>, pub config: IndexerConfig, pub store: IndexerStore, } -#[derive(Clone)] -/// This struct represents one L1 block data fetched from backfilling. -pub struct BackfillBlockData { - l2_blocks: Vec, - l1_header: HeaderId, -} - -#[derive(Clone)] -/// This struct represents data fetched fom backfilling in one iteration. -pub struct BackfillData { - block_data: VecDeque, - curr_fin_l1_lib_header: HeaderId, -} - impl IndexerCore { pub fn new(config: IndexerConfig) -> Result { let hashable_data = HashableBlockData { @@ -107,279 +92,88 @@ impl IndexerCore { let home = config.home.join("rocksdb"); + let basic_auth = config.bedrock_config.auth.clone().map(Into::into); + let node = NodeHttpClient::new( + CommonHttpClient::new(basic_auth), + config.bedrock_config.addr.clone(), + ); + let zone_indexer = ZoneIndexer::new(config.channel_id, node); + Ok(Self { - bedrock_client: BedrockClient::new( - config.bedrock_client_config.backoff, - config.bedrock_client_config.addr.clone(), - config.bedrock_client_config.auth.clone(), - )?, + zone_indexer: Arc::new(zone_indexer), config, store: IndexerStore::open_db_with_genesis(&home, &genesis_block, &state)?, }) } - pub fn subscribe_parse_block_stream(&self) -> impl futures::Stream> { + pub fn subscribe_parse_block_stream(&self) -> impl futures::Stream> + '_ { + let poll_interval = self.config.consensus_info_polling_interval; + let initial_cursor = self + .store + .get_zone_cursor() + .expect("Failed to load zone-sdk indexer cursor"); + async_stream::stream! { - info!("Searching for initial header"); + let mut cursor = initial_cursor; - let last_stored_l1_lib_header = self.store.last_observed_l1_lib_header()?; - - let mut prev_last_l1_lib_header = if let Some(last_l1_lib_header) = last_stored_l1_lib_header { - info!("Last l1 lib header found: {last_l1_lib_header}"); - last_l1_lib_header + if cursor.is_some() { + info!("Resuming indexer from cursor {cursor:?}"); } else { - info!("Last l1 lib header not found in DB"); - info!("Searching for the start of a channel"); - - let BackfillData { - block_data: start_buff, - curr_fin_l1_lib_header: last_l1_lib_header, - } = self.search_for_channel_start().await?; - - for BackfillBlockData { - l2_blocks: l2_block_vec, - l1_header, - } in start_buff { - let mut l2_blocks_parsed_ids: Vec<_> = l2_block_vec.iter().map(|block| block.header.block_id).collect(); - l2_blocks_parsed_ids.sort_unstable(); - info!("Parsed {} L2 blocks with ids {:?}", l2_block_vec.len(), l2_blocks_parsed_ids); - - for l2_block in l2_block_vec { - // TODO: proper fix is to make the sequencer's genesis include a - // trailing `clock_invocation(0)` (and have the indexer's - // `open_db_with_genesis` not pre-apply state transitions) so the - // inscribed genesis can flow through `put_block` like any other - // block. For now we skip re-applying it. - // - // The channel-start (block_id == 1) is the sequencer's genesis - // inscription that we re-discover during initial search. The - // indexer already has its own locally-constructed genesis in - // the store from `open_db_with_genesis`, so re-applying the - // inscribed copy is both redundant and would fail the strict - // block validation in `put_block` (the inscribed genesis lacks - // the trailing clock invocation). - if l2_block.header.block_id != 1 { - self - .store - .put_block(l2_block.clone(), l1_header) - .await - .inspect_err(|err| error!("Failed to put block with err {err:?}"))?; - } - - yield Ok(l2_block); - } - } - - last_l1_lib_header - }; - - info!("Searching for initial header finished"); - - info!("Starting backfilling from {prev_last_l1_lib_header}"); + info!("Starting indexer from beginning of channel"); + } loop { - let BackfillData { - block_data: buff, - curr_fin_l1_lib_header, - } = self - .backfill_to_last_l1_lib_header_id(prev_last_l1_lib_header, &self.config.channel_id) - .await - .inspect_err(|err| error!("Failed to backfill to last l1 lib header id with err {err:#?}"))?; - - prev_last_l1_lib_header = curr_fin_l1_lib_header; - - for BackfillBlockData { - l2_blocks: l2_block_vec, - l1_header: header, - } in buff { - let mut l2_blocks_parsed_ids: Vec<_> = l2_block_vec.iter().map(|block| block.header.block_id).collect(); - l2_blocks_parsed_ids.sort_unstable(); - info!("Parsed {} L2 blocks with ids {:?}", l2_block_vec.len(), l2_blocks_parsed_ids); - - for l2_block in l2_block_vec { - self.store.put_block(l2_block.clone(), header).await?; - - yield Ok(l2_block); + let stream = match self.zone_indexer.next_messages(cursor).await { + Ok(s) => s, + Err(err) => { + error!("Failed to start zone-sdk next_messages stream: {err}"); + tokio::time::sleep(poll_interval).await; + continue; } - } - } - } - } - - async fn get_lib(&self) -> Result { - Ok(self.bedrock_client.get_consensus_info().await?.lib) - } - - async fn get_next_lib(&self, prev_lib: HeaderId) -> Result { - loop { - let next_lib = self.get_lib().await?; - if next_lib == prev_lib { - info!( - "Wait {:?} to not spam the node", - self.config.consensus_info_polling_interval - ); - tokio::time::sleep(self.config.consensus_info_polling_interval).await; - } else { - break Ok(next_lib); - } - } - } - - /// WARNING: depending on channel state, - /// may take indefinite amount of time. - pub async fn search_for_channel_start(&self) -> Result { - let mut curr_last_l1_lib_header = self.get_lib().await?; - let mut backfill_start = curr_last_l1_lib_header; - // ToDo: How to get root? - let mut backfill_limit = HeaderId::from([0; 32]); - // ToDo: Not scalable, initial buffer should be stored in DB to not run out of memory - // Don't want to complicate DB even more right now. - let mut block_buffer = VecDeque::new(); - - 'outer: loop { - let mut cycle_header = curr_last_l1_lib_header; - - loop { - let Some(cycle_block) = self.bedrock_client.get_block_by_id(cycle_header).await? - else { - // First run can reach root easily - // so here we are optimistic about L1 - // failing to get parent. - break; }; + let mut stream = std::pin::pin!(stream); - // It would be better to have id, but block does not have it, so slot will do. - info!( - "INITIAL SEARCH: Observed L1 block at slot {}", - cycle_block.header().slot().into_inner() - ); - debug!( - "INITIAL SEARCH: This block header is {}", - cycle_block.header().id() - ); - debug!( - "INITIAL SEARCH: This block parent is {}", - cycle_block.header().parent() - ); + while let Some((msg, slot)) = stream.next().await { + let zone_block = match msg { + ZoneMessage::Block(b) => b, + // Non-block messages don't carry a cursor position; the + // next ZoneBlock advances past them implicitly. + ZoneMessage::Deposit(_) | ZoneMessage::Withdraw(_) => continue, + }; - let (l2_block_vec, l1_header) = - parse_block_owned(&cycle_block, &self.config.channel_id); + let block: Block = match borsh::from_slice(&zone_block.data) { + Ok(b) => b, + Err(e) => { + error!("Failed to deserialize L2 block from zone-sdk: {e}"); + // Advance past the broken inscription so we don't + // re-process it on restart. + cursor = Some((zone_block.id, slot)); + if let Err(err) = self.store.set_zone_cursor(&(zone_block.id, slot)) { + warn!("Failed to persist indexer cursor: {err:#}"); + } + continue; + } + }; - info!("Parsed {} L2 blocks", l2_block_vec.len()); + info!("Indexed L2 block {}", block.header.block_id); - if !l2_block_vec.is_empty() { - block_buffer.push_front(BackfillBlockData { - l2_blocks: l2_block_vec.clone(), - l1_header, - }); - } - - if let Some(first_l2_block) = l2_block_vec.first() - && first_l2_block.header.block_id == 1 - { - info!("INITIAL_SEARCH: Found channel start"); - break 'outer; - } - - // Step back to parent - let parent = cycle_block.header().parent(); - - if parent == backfill_limit { - break; - } - - cycle_header = parent; - } - - info!("INITIAL_SEARCH: Reached backfill limit, refetching last l1 lib header"); - - block_buffer.clear(); - backfill_limit = backfill_start; - curr_last_l1_lib_header = self.get_next_lib(curr_last_l1_lib_header).await?; - backfill_start = curr_last_l1_lib_header; - } - - Ok(BackfillData { - block_data: block_buffer, - curr_fin_l1_lib_header: curr_last_l1_lib_header, - }) - } - - pub async fn backfill_to_last_l1_lib_header_id( - &self, - last_fin_l1_lib_header: HeaderId, - channel_id: &ChannelId, - ) -> Result { - let curr_fin_l1_lib_header = self.get_next_lib(last_fin_l1_lib_header).await?; - // ToDo: Not scalable, buffer should be stored in DB to not run out of memory - // Don't want to complicate DB even more right now. - let mut block_buffer = VecDeque::new(); - - let mut cycle_header = curr_fin_l1_lib_header; - loop { - let Some(cycle_block) = self.bedrock_client.get_block_by_id(cycle_header).await? else { - return Err(anyhow::anyhow!("Parent not found")); - }; - - if cycle_block.header().id() == last_fin_l1_lib_header { - break; - } - // Step back to parent - cycle_header = cycle_block.header().parent(); - - // It would be better to have id, but block does not have it, so slot will do. - info!( - "Observed L1 block at slot {}", - cycle_block.header().slot().into_inner() - ); - - let (l2_block_vec, l1_header) = parse_block_owned(&cycle_block, channel_id); - - info!("Parsed {} L2 blocks", l2_block_vec.len()); - - if !l2_block_vec.is_empty() { - block_buffer.push_front(BackfillBlockData { - l2_blocks: l2_block_vec, - l1_header, - }); - } - } - - Ok(BackfillData { - block_data: block_buffer, - curr_fin_l1_lib_header, - }) - } -} - -fn parse_block_owned( - l1_block: &bedrock_client::Block, - decoded_channel_id: &ChannelId, -) -> (Vec, HeaderId) { - ( - #[expect( - clippy::wildcard_enum_match_arm, - reason = "We are only interested in channel inscription ops, so it's fine to ignore the rest" - )] - l1_block - .transactions() - .flat_map(|tx| { - tx.mantle_tx.ops.iter().filter_map(|op| match op { - Op::ChannelInscribe(InscriptionOp { - channel_id, - inscription, - .. - }) if channel_id == decoded_channel_id => { - borsh::from_slice::(inscription) - .inspect_err(|err| { - error!("Failed to deserialize our inscription with err: {err:#?}"); - }) - .ok() + // TODO: Remove l1_header placeholder once storage layer + // no longer requires it. Zone-sdk handles L1 tracking internally. + let placeholder_l1_header = HeaderId::from([0_u8; 32]); + if let Err(err) = self.store.put_block(block.clone(), placeholder_l1_header).await { + error!("Failed to store block {}: {err:#}", block.header.block_id); } - _ => None, - }) - }) - .collect(), - l1_block.header().id(), - ) + + cursor = Some((zone_block.id, slot)); + if let Err(err) = self.store.set_zone_cursor(&(zone_block.id, slot)) { + warn!("Failed to persist indexer cursor: {err:#}"); + } + yield Ok(block); + } + + // Stream ended (caught up to LIB). Sleep then poll again. + tokio::time::sleep(poll_interval).await; + } + } + } } diff --git a/indexer/service/configs/indexer_config.json b/indexer/service/configs/indexer_config.json index e4dd8f93..558a3bfe 100644 --- a/indexer/service/configs/indexer_config.json +++ b/indexer/service/configs/indexer_config.json @@ -1,12 +1,8 @@ { "home": ".", "consensus_info_polling_interval": "1s", - "bedrock_client_config": { - "addr": "http://localhost:8080", - "backoff": { - "start_delay": "100ms", - "max_retries": 5 - } + "bedrock_config": { + "addr": "http://localhost:8080" }, "channel_id": "0101010101010101010101010101010101010101010101010101010101010101", "initial_accounts": [ diff --git a/integration_tests/Cargo.toml b/integration_tests/Cargo.toml index 1fa0187f..a1704cdf 100644 --- a/integration_tests/Cargo.toml +++ b/integration_tests/Cargo.toml @@ -19,8 +19,9 @@ indexer_service.workspace = true serde_json.workspace = true token_core.workspace = true ata_core.workspace = true -indexer_service_rpc.workspace = true +indexer_service_rpc = { workspace = true, features = ["client"] } sequencer_service_rpc = { workspace = true, features = ["client"] } +jsonrpsee = { workspace = true, features = ["ws-client"] } wallet-ffi.workspace = true indexer_ffi.workspace = true testnet_initial_state.workspace = true diff --git a/integration_tests/src/config.rs b/integration_tests/src/config.rs index faff1e79..7b3825de 100644 --- a/integration_tests/src/config.rs +++ b/integration_tests/src/config.rs @@ -2,7 +2,7 @@ use std::{net::SocketAddr, path::PathBuf, time::Duration}; use anyhow::{Context as _, Result}; use bytesize::ByteSize; -use indexer_service::{BackoffConfig, ChannelId, ClientConfig, IndexerConfig}; +use indexer_service::{ChannelId, ClientConfig, IndexerConfig}; use key_protocol::key_management::KeyChain; use nssa::{Account, AccountId, PrivateKey, PublicKey}; use nssa_core::{account::Data, program::DEFAULT_PROGRAM_ID}; @@ -164,35 +164,10 @@ impl std::fmt::Display for UrlProtocol { } } -pub fn indexer_config( - bedrock_addr: SocketAddr, - home: PathBuf, - initial_data: &InitialData, -) -> Result { - Ok(IndexerConfig { - home, - consensus_info_polling_interval: Duration::from_secs(1), - bedrock_client_config: ClientConfig { - addr: addr_to_url(UrlProtocol::Http, bedrock_addr) - .context("Failed to convert bedrock addr to URL")?, - auth: None, - backoff: BackoffConfig { - start_delay: Duration::from_millis(100), - max_retries: 10, - }, - }, - initial_public_accounts: Some(initial_data.sequencer_initial_public_accounts()), - initial_private_accounts: Some(initial_data.sequencer_initial_private_accounts()), - signing_key: [37; 32], - channel_id: bedrock_channel_id(), - }) -} - pub fn sequencer_config( partial: SequencerPartialConfig, home: PathBuf, bedrock_addr: SocketAddr, - indexer_addr: SocketAddr, initial_data: &InitialData, ) -> Result { let SequencerPartialConfig { @@ -215,17 +190,11 @@ pub fn sequencer_config( initial_private_accounts: Some(initial_data.sequencer_initial_private_accounts()), signing_key: [37; 32], bedrock_config: BedrockConfig { - backoff: BackoffConfig { - start_delay: Duration::from_millis(100), - max_retries: 5, - }, channel_id: bedrock_channel_id(), node_url: addr_to_url(UrlProtocol::Http, bedrock_addr) .context("Failed to convert bedrock addr to URL")?, auth: None, }, - indexer_rpc_url: addr_to_url(UrlProtocol::Ws, indexer_addr) - .context("Failed to convert indexer addr to URL")?, }) } @@ -245,6 +214,26 @@ pub fn wallet_config( }) } +pub fn indexer_config( + bedrock_addr: SocketAddr, + home: PathBuf, + initial_data: &InitialData, +) -> Result { + Ok(IndexerConfig { + home, + consensus_info_polling_interval: Duration::from_secs(1), + bedrock_config: ClientConfig { + addr: addr_to_url(UrlProtocol::Http, bedrock_addr) + .context("Failed to convert bedrock addr to URL")?, + auth: None, + }, + initial_public_accounts: Some(initial_data.sequencer_initial_public_accounts()), + initial_private_accounts: Some(initial_data.sequencer_initial_private_accounts()), + signing_key: [37; 32], + channel_id: bedrock_channel_id(), + }) +} + pub fn addr_to_url(protocol: UrlProtocol, addr: SocketAddr) -> Result { // Convert 0.0.0.0 to 127.0.0.1 for client connections // When binding to port 0, the server binds to 0.0.0.0: diff --git a/integration_tests/src/indexer_client.rs b/integration_tests/src/indexer_client.rs new file mode 100644 index 00000000..5641d824 --- /dev/null +++ b/integration_tests/src/indexer_client.rs @@ -0,0 +1,34 @@ +//! Thin client wrapper for querying the indexer's JSON-RPC API in tests. +//! +//! The sequencer doesn't depend on the indexer at runtime — finalization comes +//! from zone-sdk events. This wrapper exists purely for test ergonomics so +//! integration tests can construct a single connection and call +//! `indexer_service_rpc::RpcClient` methods directly via `Deref`. + +use std::ops::Deref; + +use anyhow::{Context as _, Result}; +use jsonrpsee::ws_client::{WsClient, WsClientBuilder}; +use log::info; +use url::Url; + +pub struct IndexerClient(WsClient); + +impl IndexerClient { + pub async fn new(indexer_url: &Url) -> Result { + info!("Connecting to Indexer at {indexer_url}"); + let client = WsClientBuilder::default() + .build(indexer_url) + .await + .context("Failed to create websocket client")?; + Ok(Self(client)) + } +} + +impl Deref for IndexerClient { + type Target = WsClient; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/integration_tests/src/lib.rs b/integration_tests/src/lib.rs index fcae2c71..2a9e7c67 100644 --- a/integration_tests/src/lib.rs +++ b/integration_tests/src/lib.rs @@ -9,16 +9,19 @@ use indexer_service::IndexerHandle; use log::{debug, error}; use nssa::{AccountId, PrivacyPreservingTransaction}; use nssa_core::Commitment; -use sequencer_core::indexer_client::{IndexerClient, IndexerClientTrait as _}; use sequencer_service::SequencerHandle; use sequencer_service_rpc::{RpcClient as _, SequencerClient, SequencerClientBuilder}; use tempfile::TempDir; use testcontainers::compose::DockerCompose; use wallet::WalletCore; -use crate::setup::{setup_bedrock_node, setup_indexer, setup_sequencer, setup_wallet}; +use crate::{ + indexer_client::IndexerClient, + setup::{setup_bedrock_node, setup_indexer, setup_sequencer, setup_wallet}, +}; pub mod config; +pub mod indexer_client; pub mod setup; pub mod test_context_ffi; @@ -77,14 +80,10 @@ impl TestContext { .await .context("Failed to setup Indexer")?; - let (sequencer_handle, temp_sequencer_dir) = setup_sequencer( - sequencer_partial_config, - bedrock_addr, - indexer_handle.addr(), - &initial_data, - ) - .await - .context("Failed to setup Sequencer")?; + let (sequencer_handle, temp_sequencer_dir) = + setup_sequencer(sequencer_partial_config, bedrock_addr, &initial_data) + .await + .context("Failed to setup Sequencer")?; let (wallet, temp_wallet_dir, wallet_password) = setup_wallet(sequencer_handle.addr(), &initial_data) diff --git a/integration_tests/src/setup.rs b/integration_tests/src/setup.rs index 58b33c60..774c67e3 100644 --- a/integration_tests/src/setup.rs +++ b/integration_tests/src/setup.rs @@ -119,7 +119,6 @@ pub(crate) async fn setup_indexer( pub(crate) async fn setup_sequencer( partial: config::SequencerPartialConfig, bedrock_addr: SocketAddr, - indexer_addr: SocketAddr, initial_data: &config::InitialData, ) -> Result<(SequencerHandle, TempDir)> { let temp_sequencer_dir = @@ -134,7 +133,6 @@ pub(crate) async fn setup_sequencer( partial, temp_sequencer_dir.path().to_owned(), bedrock_addr, - indexer_addr, initial_data, ) .context("Failed to create Sequencer config")?; diff --git a/integration_tests/src/test_context_ffi.rs b/integration_tests/src/test_context_ffi.rs index 7d21aa28..b29ace7c 100644 --- a/integration_tests/src/test_context_ffi.rs +++ b/integration_tests/src/test_context_ffi.rs @@ -6,7 +6,6 @@ use indexer_ffi::IndexerServiceFFI; use indexer_service_rpc::RpcClient as _; use log::{debug, error}; use nssa::AccountId; -use sequencer_core::indexer_client::{IndexerClient, IndexerClientTrait as _}; use sequencer_service::SequencerHandle; use sequencer_service_rpc::{RpcClient as _, SequencerClient, SequencerClientBuilder}; use tempfile::TempDir; @@ -15,6 +14,7 @@ use wallet::WalletCore; use crate::{ BEDROCK_SERVICE_WITH_OPEN_PORT, LOGGER, TestContextBuilder, config, + indexer_client::IndexerClient, setup::{setup_bedrock_node, setup_indexer_ffi, setup_sequencer, setup_wallet}, }; @@ -85,8 +85,6 @@ impl TestContextFFI { .block_on(setup_sequencer( sequencer_partial_config, bedrock_addr, - // SAFETY: addr is valid if indexer_ffi is valid. - unsafe { indexer_ffi.addr() }, initial_data, )) .context("Failed to setup Sequencer")?; diff --git a/sequencer/core/Cargo.toml b/sequencer/core/Cargo.toml index efd0e359..827c8b2e 100644 --- a/sequencer/core/Cargo.toml +++ b/sequencer/core/Cargo.toml @@ -13,7 +13,7 @@ nssa_core.workspace = true common.workspace = true storage.workspace = true mempool.workspace = true -bedrock_client.workspace = true +logos-blockchain-zone-sdk.workspace = true testnet_initial_state.workspace = true anyhow.workspace = true @@ -30,7 +30,6 @@ rand.workspace = true borsh.workspace = true bytesize.workspace = true url.workspace = true -jsonrpsee = { workspace = true, features = ["ws-client"] } [features] default = [] diff --git a/sequencer/core/src/block_publisher.rs b/sequencer/core/src/block_publisher.rs new file mode 100644 index 00000000..9f4c8235 --- /dev/null +++ b/sequencer/core/src/block_publisher.rs @@ -0,0 +1,136 @@ +use std::{sync::Arc, time::Duration}; + +use anyhow::{Context as _, Result, anyhow}; +use common::block::Block; +use log::warn; +pub use logos_blockchain_core::mantle::ops::channel::MsgId; +pub use logos_blockchain_key_management_system_service::keys::Ed25519Key; +pub use logos_blockchain_zone_sdk::sequencer::SequencerCheckpoint; +use logos_blockchain_zone_sdk::{ + CommonHttpClient, + adapter::NodeHttpClient, + sequencer::{Event, SequencerConfig as ZoneSdkSequencerConfig, SequencerHandle, ZoneSequencer}, + state::InscriptionInfo, +}; +use tokio::task::JoinHandle; + +use crate::config::BedrockConfig; + +/// Sink for `Event::Published` checkpoints emitted by the drive task. +/// Caller is responsible for persistence (e.g. writing to rocksdb). +pub type CheckpointSink = Box; + +/// Sink for finalized L2 block ids derived from `Event::TxsFinalized` and +/// `Event::FinalizedInscriptions`. Caller is responsible for cleanup +/// (e.g. marking pending blocks as finalized in storage). +pub type FinalizedBlockSink = Box; + +#[expect(async_fn_in_trait, reason = "We don't care about Send/Sync here")] +pub trait BlockPublisherTrait: Clone { + async fn new( + config: &BedrockConfig, + bedrock_signing_key: Ed25519Key, + resubmit_interval: Duration, + initial_checkpoint: Option, + on_checkpoint: CheckpointSink, + on_finalized_block: FinalizedBlockSink, + ) -> Result; + + /// Fire-and-forget publish. Zone-sdk drives the actual submission and + /// retries internally; this just hands the payload off. + async fn publish_block(&self, block: &Block) -> Result<()>; +} + +/// Real block publisher backed by zone-sdk's `ZoneSequencer`. +#[derive(Clone)] +pub struct ZoneSdkPublisher { + handle: SequencerHandle, + // Aborts the drive task when the last clone is dropped. + _drive_task: Arc, +} + +struct DriveTaskGuard(JoinHandle<()>); + +impl Drop for DriveTaskGuard { + fn drop(&mut self) { + self.0.abort(); + } +} + +impl BlockPublisherTrait for ZoneSdkPublisher { + async fn new( + config: &BedrockConfig, + bedrock_signing_key: Ed25519Key, + resubmit_interval: Duration, + initial_checkpoint: Option, + on_checkpoint: CheckpointSink, + on_finalized_block: FinalizedBlockSink, + ) -> Result { + let basic_auth = config.auth.clone().map(Into::into); + let node = NodeHttpClient::new(CommonHttpClient::new(basic_auth), config.node_url.clone()); + + let zone_sdk_config = ZoneSdkSequencerConfig { + resubmit_interval, + ..ZoneSdkSequencerConfig::default() + }; + + let (mut sequencer, mut handle) = ZoneSequencer::init_with_config( + config.channel_id, + bedrock_signing_key, + node, + zone_sdk_config, + initial_checkpoint, + ); + + let drive_task = tokio::spawn(async move { + loop { + let Some(event) = sequencer.next_event().await else { + continue; + }; + match event { + Event::Published { checkpoint, .. } => on_checkpoint(checkpoint), + Event::TxsFinalized { inscriptions, .. } + | Event::FinalizedInscriptions { inscriptions } => { + if let Some(max_block_id) = max_block_id_from_inscriptions(&inscriptions) { + on_finalized_block(max_block_id); + } + } + Event::ChannelUpdate { .. } | Event::Ready => {} + } + } + }); + + handle.wait_ready().await; + + Ok(Self { + handle, + _drive_task: Arc::new(DriveTaskGuard(drive_task)), + }) + } + + async fn publish_block(&self, block: &Block) -> Result<()> { + let data = borsh::to_vec(block).context("Failed to serialize block")?; + self.handle + .publish_message(data) + .await + .map_err(|e| anyhow!("zone-sdk publish failed: {e}"))?; + Ok(()) + } +} + +/// Deserialize each inscription payload as a `Block` and return the highest +/// `block_id`. Bad payloads are logged and skipped. +fn max_block_id_from_inscriptions(inscriptions: &[InscriptionInfo]) -> Option { + inscriptions + .iter() + .filter_map( + |inscription| match borsh::from_slice::(&inscription.payload) { + Ok(block) => Some(block.header.block_id), + Err(err) => { + warn!("Failed to deserialize finalized inscription as Block: {err:#}"); + None + } + }, + ) + .max() +} diff --git a/sequencer/core/src/block_settlement_client.rs b/sequencer/core/src/block_settlement_client.rs deleted file mode 100644 index 6b32f8de..00000000 --- a/sequencer/core/src/block_settlement_client.rs +++ /dev/null @@ -1,116 +0,0 @@ -use anyhow::{Context as _, Result}; -use bedrock_client::BedrockClient; -pub use common::block::Block; -pub use logos_blockchain_core::mantle::{MantleTx, SignedMantleTx, ops::channel::MsgId}; -use logos_blockchain_core::mantle::{ - Op, OpProof, Transaction as _, - ops::channel::{ChannelId, inscribe::InscriptionOp}, -}; -pub use logos_blockchain_key_management_system_service::keys::Ed25519Key; -use logos_blockchain_key_management_system_service::keys::Ed25519PublicKey; - -use crate::config::BedrockConfig; - -#[expect(async_fn_in_trait, reason = "We don't care about Send/Sync here")] -pub trait BlockSettlementClientTrait: Clone { - //// Create a new client. - fn new(config: &BedrockConfig, signing_key: Ed25519Key) -> Result; - - /// Get the bedrock channel ID used by this client. - fn bedrock_channel_id(&self) -> ChannelId; - - /// Get the bedrock signing key used by this client. - fn bedrock_signing_key(&self) -> &Ed25519Key; - - /// Post a transaction to the node. - async fn submit_inscribe_tx_to_bedrock(&self, tx: SignedMantleTx) -> Result<()>; - - /// Create and sign a transaction for inscribing data. - fn create_inscribe_tx(&self, block: &Block) -> Result<(SignedMantleTx, MsgId)> { - let inscription_data = borsh::to_vec(block)?; - log::debug!( - "The size of the block {} is {} bytes", - block.header.block_id, - inscription_data.len() - ); - let verifying_key_bytes = self.bedrock_signing_key().public_key().to_bytes(); - let verifying_key = - Ed25519PublicKey::from_bytes(&verifying_key_bytes).expect("valid ed25519 public key"); - - let inscribe_op = InscriptionOp { - channel_id: self.bedrock_channel_id(), - inscription: inscription_data, - parent: block.bedrock_parent_id.into(), - signer: verifying_key, - }; - let inscribe_op_id = inscribe_op.id(); - - let inscribe_tx = MantleTx { - ops: vec![Op::ChannelInscribe(inscribe_op)], - // Altruistic test config - storage_gas_price: 0.into(), - execution_gas_price: 0.into(), - }; - - let tx_hash = inscribe_tx.hash(); - let signature_bytes = self - .bedrock_signing_key() - .sign_payload(tx_hash.as_signing_bytes().as_ref()) - .to_bytes(); - let signature = - logos_blockchain_key_management_system_service::keys::Ed25519Signature::from_bytes( - &signature_bytes, - ); - - let signed_mantle_tx = SignedMantleTx { - ops_proofs: vec![OpProof::Ed25519Sig(signature)], - mantle_tx: inscribe_tx, - }; - Ok((signed_mantle_tx, inscribe_op_id)) - } -} - -/// A component that posts block data to logos blockchain. -#[derive(Clone)] -pub struct BlockSettlementClient { - client: BedrockClient, - signing_key: Ed25519Key, - channel_id: ChannelId, -} - -impl BlockSettlementClientTrait for BlockSettlementClient { - fn new(config: &BedrockConfig, signing_key: Ed25519Key) -> Result { - let client = - BedrockClient::new(config.backoff, config.node_url.clone(), config.auth.clone()) - .context("Failed to initialize bedrock client")?; - Ok(Self { - client, - signing_key, - channel_id: config.channel_id, - }) - } - - async fn submit_inscribe_tx_to_bedrock(&self, tx: SignedMantleTx) -> Result<()> { - let (parent_id, msg_id) = match tx.mantle_tx.ops.first() { - Some(Op::ChannelInscribe(inscribe)) => (inscribe.parent, inscribe.id()), - _ => panic!("Expected ChannelInscribe op"), - }; - self.client - .post_transaction(tx) - .await - .context("Failed to post transaction to Bedrock after retries")? - .context("Failed to post transaction to Bedrock with non-retryable error")?; - - log::debug!("Posted block to Bedrock with parent id {parent_id:?} and msg id: {msg_id:?}"); - - Ok(()) - } - - fn bedrock_channel_id(&self) -> ChannelId { - self.channel_id - } - - fn bedrock_signing_key(&self) -> &Ed25519Key { - &self.signing_key - } -} diff --git a/sequencer/core/src/block_store.rs b/sequencer/core/src/block_store.rs index 7e47005d..e85b5d33 100644 --- a/sequencer/core/src/block_store.rs +++ b/sequencer/core/src/block_store.rs @@ -1,16 +1,17 @@ -use std::{collections::HashMap, path::Path}; +use std::{collections::HashMap, path::Path, sync::Arc}; -use anyhow::Result; +use anyhow::{Context as _, Result}; use common::{ HashType, block::{Block, BlockMeta, MantleMsgId}, transaction::NSSATransaction, }; +use logos_blockchain_zone_sdk::sequencer::SequencerCheckpoint; use nssa::V03State; use storage::{error::DbError, sequencer::RocksDBIO}; pub struct SequencerStore { - dbio: RocksDBIO, + dbio: Arc, // TODO: Consider adding the hashmap to the database for faster recovery. tx_hash_to_block_map: HashMap, genesis_id: u64, @@ -30,7 +31,11 @@ impl SequencerStore { ) -> Result { let tx_hash_to_block_map = block_to_transactions_map(genesis_block); - let dbio = RocksDBIO::open_or_create(location, genesis_block, genesis_msg_id)?; + let dbio = Arc::new(RocksDBIO::open_or_create( + location, + genesis_block, + genesis_msg_id, + )?); let genesis_id = dbio.get_meta_first_block_in_db()?; @@ -42,6 +47,14 @@ impl SequencerStore { }) } + /// Shared handle to the underlying rocksdb. Used to persist the zone-sdk + /// checkpoint from the sequencer's drive task without needing &mut to the + /// store. + #[must_use] + pub fn dbio(&self) -> Arc { + Arc::clone(&self.dbio) + } + pub fn get_block_at_id(&self, id: u64) -> Result, DbError> { self.dbio.get_block(id) } @@ -55,6 +68,7 @@ impl SequencerStore { } /// Returns the transaction corresponding to the given hash, if it exists in the blockchain. + #[must_use] pub fn get_transaction_by_hash(&self, hash: HashType) -> Option { let block_id = *self.tx_hash_to_block_map.get(&hash)?; let block = self @@ -76,10 +90,12 @@ impl SequencerStore { Ok(self.dbio.latest_block_meta()?) } + #[must_use] pub const fn genesis_id(&self) -> u64 { self.genesis_id } + #[must_use] pub const fn signing_key(&self) -> &nssa::PrivateKey { &self.signing_key } @@ -100,9 +116,26 @@ impl SequencerStore { Ok(()) } + #[must_use] pub fn get_nssa_state(&self) -> Option { self.dbio.get_nssa_state().ok() } + + pub fn get_zone_checkpoint(&self) -> Result> { + let Some(bytes) = self.dbio.get_zone_sdk_checkpoint_bytes()? else { + return Ok(None); + }; + let checkpoint: SequencerCheckpoint = serde_json::from_slice(&bytes) + .context("Failed to deserialize stored zone-sdk checkpoint")?; + Ok(Some(checkpoint)) + } + + pub fn set_zone_checkpoint(&self, checkpoint: &SequencerCheckpoint) -> Result<()> { + let bytes = + serde_json::to_vec(checkpoint).context("Failed to serialize zone-sdk checkpoint")?; + self.dbio.put_zone_sdk_checkpoint_bytes(&bytes)?; + Ok(()) + } } pub(crate) fn block_to_transactions_map(block: &Block) -> HashMap { diff --git a/sequencer/core/src/config.rs b/sequencer/core/src/config.rs index fa4a2fa7..b33dd694 100644 --- a/sequencer/core/src/config.rs +++ b/sequencer/core/src/config.rs @@ -6,7 +6,6 @@ use std::{ }; use anyhow::Result; -use bedrock_client::BackoffConfig; use bytesize::ByteSize; use common::config::BasicAuth; use humantime_serde; @@ -42,8 +41,6 @@ pub struct SequencerConfig { pub signing_key: [u8; 32], /// Bedrock configuration options. pub bedrock_config: BedrockConfig, - /// Indexer RPC URL. - pub indexer_rpc_url: Url, #[serde(skip_serializing_if = "Option::is_none")] pub initial_public_accounts: Option>, #[serde(skip_serializing_if = "Option::is_none")] @@ -52,9 +49,6 @@ pub struct SequencerConfig { #[derive(Clone, Serialize, Deserialize)] pub struct BedrockConfig { - /// Fibonacci backoff retry strategy configuration. - #[serde(default)] - pub backoff: BackoffConfig, /// Bedrock channel ID. pub channel_id: ChannelId, /// Bedrock Url. diff --git a/sequencer/core/src/indexer_client.rs b/sequencer/core/src/indexer_client.rs deleted file mode 100644 index 960b77a4..00000000 --- a/sequencer/core/src/indexer_client.rs +++ /dev/null @@ -1,34 +0,0 @@ -use std::{ops::Deref, sync::Arc}; - -use anyhow::{Context as _, Result}; -use log::info; -pub use url::Url; - -#[expect(async_fn_in_trait, reason = "We don't care about Send/Sync here")] -pub trait IndexerClientTrait: Clone { - async fn new(indexer_url: &Url) -> Result; -} - -#[derive(Clone)] -pub struct IndexerClient(Arc); - -impl IndexerClientTrait for IndexerClient { - async fn new(indexer_url: &Url) -> Result { - info!("Connecting to Indexer at {indexer_url}"); - - let client = jsonrpsee::ws_client::WsClientBuilder::default() - .build(indexer_url) - .await - .context("Failed to create websocket client")?; - - Ok(Self(Arc::new(client))) - } -} - -impl Deref for IndexerClient { - type Target = jsonrpsee::ws_client::WsClient; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} diff --git a/sequencer/core/src/lib.rs b/sequencer/core/src/lib.rs index 5f118a2f..bce8151f 100644 --- a/sequencer/core/src/lib.rs +++ b/sequencer/core/src/lib.rs @@ -1,7 +1,6 @@ use std::{path::Path, time::Instant}; use anyhow::{Context as _, Result, anyhow}; -use bedrock_client::SignedMantleTx; #[cfg(feature = "testnet")] use common::PINATA_BASE58; use common::{ @@ -20,33 +19,27 @@ pub use storage::error::DbError; use testnet_initial_state::initial_state; use crate::{ - block_settlement_client::{BlockSettlementClient, BlockSettlementClientTrait, MsgId}, + block_publisher::{BlockPublisherTrait, ZoneSdkPublisher}, block_store::SequencerStore, - indexer_client::{IndexerClient, IndexerClientTrait}, }; -pub mod block_settlement_client; +pub mod block_publisher; pub mod block_store; pub mod config; -pub mod indexer_client; #[cfg(feature = "mock")] pub mod mock; -pub struct SequencerCore< - BC: BlockSettlementClientTrait = BlockSettlementClient, - IC: IndexerClientTrait = IndexerClient, -> { +pub struct SequencerCore { state: nssa::V03State, store: SequencerStore, mempool: MemPool, sequencer_config: SequencerConfig, chain_height: u64, - block_settlement_client: BC, - indexer_client: IC, + block_publisher: BP, } -impl SequencerCore { +impl SequencerCore { /// Starts the sequencer using the provided configuration. /// If an existing database is found, the sequencer state is loaded from it and /// assumed to represent the correct latest state consistent with Bedrock-finalized data. @@ -70,23 +63,16 @@ impl SequencerCore SequencerCore b, + Err(err) => { + error!("Failed to serialize zone-sdk checkpoint: {err:#}"); + return; + } + }; + if let Err(err) = dbio_for_checkpoint.put_zone_sdk_checkpoint_bytes(&bytes) { + error!("Failed to persist zone-sdk checkpoint: {err:#}"); + } + }); + + let dbio_for_finalized = store.dbio(); + let on_finalized_block: block_publisher::FinalizedBlockSink = Box::new(move |block_id| { + if let Err(err) = dbio_for_finalized.clean_pending_blocks_up_to(block_id) { + error!("Failed to mark pending blocks finalized up to {block_id}: {err:#}"); + } + }); + + let block_publisher = BP::new( + &config.bedrock_config, + bedrock_signing_key, + config.retry_pending_blocks_timeout, + initial_checkpoint, + on_checkpoint, + on_finalized_block, + ) + .await + .expect("Failed to initialize Block Publisher"); + + // On a truly fresh start (no checkpoint persisted yet), publish the + // genesis block so the indexer can find the channel start. After the + // first publish, zone-sdk's checkpoint persistence covers further + // restarts. + if is_fresh_start && let Err(err) = block_publisher.publish_block(&genesis_block).await { + error!("Failed to publish genesis block: {err:#}"); + } + #[cfg_attr(not(feature = "testnet"), allow(unused_mut))] let mut state = if let Some(state) = store.get_nssa_state() { info!("Found local database. Loading state and pending blocks from it."); @@ -159,35 +190,33 @@ impl SequencerCore Result { - let (tx, _msg_id) = self - .produce_new_block_with_mempool_transactions() - .context("Failed to produce new block with mempool transactions")?; - match self - .block_settlement_client - .submit_inscribe_tx_to_bedrock(tx) - .await - { - Ok(()) => {} - Err(err) => { - error!("Failed to post block data to Bedrock with error: {err:#}"); - } + let block = self + .build_block_from_mempool() + .context("Failed to build block from mempool transactions")?; + + // TODO: Remove msg_id from store.update — it is no longer needed now that + // zone-sdk manages L1 settlement state via its own checkpoint. + let placeholder_msg_id = [0_u8; 32]; + + if let Err(err) = self.block_publisher.publish_block(&block).await { + error!("Failed to publish block to Bedrock with error: {err:#}"); } + self.store.update(&block, placeholder_msg_id, &self.state)?; Ok(self.chain_height) } - /// Produces new block from transactions in mempool and packs it into a `SignedMantleTx`. - pub fn produce_new_block_with_mempool_transactions( - &mut self, - ) -> Result<(SignedMantleTx, MsgId)> { + /// Builds a new block from transactions in the mempool. + /// Does NOT publish or store the block — the caller is responsible for that. + pub fn build_block_from_mempool(&mut self) -> Result { let now = Instant::now(); let new_block_height = self.next_block_id(); @@ -277,21 +306,12 @@ impl SequencerCore SequencerCore &nssa::V03State { @@ -319,22 +339,19 @@ impl SequencerCore Result<()> { - self.get_pending_blocks()? - .iter() - .map(|block| block.header.block_id) - .min() - .map_or(Ok(()), |first_pending_block_id| { - info!("Clearing pending blocks up to id: {last_finalized_block_id}"); - // TODO: Delete blocks instead of marking them as finalized. - // Current approach is used because we still have `GetBlockDataRequest`. - (first_pending_block_id..=last_finalized_block_id) - .try_for_each(|id| self.store.mark_block_as_finalized(id)) - }) + /// Marks all pending blocks with `block_id <= last_finalized_block_id` as + /// finalized. Idempotent. Production callers don't invoke this directly — + /// it's wired up in `start_from_config` to the publisher's + /// `on_finalized_block` sink, which fires on `Event::TxsFinalized` / + /// `Event::FinalizedInscriptions`. Kept on the type for tests. + // TODO: Delete blocks instead of marking them as finalized. Current + // approach is used because we still have `GetBlockDataRequest`. + pub fn clean_finalized_blocks_from_db(&self, last_finalized_block_id: u64) -> Result<()> { + info!("Clearing pending blocks up to id: {last_finalized_block_id}"); + self.store + .dbio() + .clean_pending_blocks_up_to(last_finalized_block_id)?; + Ok(()) } /// Returns the list of stored pending blocks. @@ -348,12 +365,8 @@ impl SequencerCore BC { - self.block_settlement_client.clone() - } - - pub fn indexer_client(&self) -> IC { - self.indexer_client.clone() + pub fn block_publisher(&self) -> BP { + self.block_publisher.clone() } fn next_block_id(&self) -> u64 { @@ -392,7 +405,6 @@ mod tests { use std::{pin::pin, time::Duration}; - use bedrock_client::BackoffConfig; use common::{ test_utils::sequencer_sign_key_for_testing, transaction::{NSSATransaction, clock_invocation}, @@ -420,16 +432,11 @@ mod tests { block_create_timeout: Duration::from_secs(1), signing_key: *sequencer_sign_key_for_testing().value(), bedrock_config: BedrockConfig { - backoff: BackoffConfig { - start_delay: Duration::from_millis(100), - max_retries: 5, - }, channel_id: ChannelId::from([0; 32]), node_url: "http://not-used-in-unit-tests".parse().unwrap(), auth: None, }, retry_pending_blocks_timeout: Duration::from_mins(4), - indexer_rpc_url: "ws://localhost:8779".parse().unwrap(), initial_public_accounts: None, initial_private_accounts: None, } @@ -457,9 +464,7 @@ mod tests { let tx = common::test_utils::produce_dummy_empty_transaction(); mempool_handle.push(tx).await.unwrap(); - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); + sequencer.produce_new_block().await.unwrap(); (sequencer, mempool_handle) } @@ -604,23 +609,21 @@ mod tests { assert!(poll.is_pending()); // Empty the mempool by producing a block - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); + sequencer.produce_new_block().await.unwrap(); // Resolve the pending push assert!(push_fut.await.is_ok()); } #[tokio::test] - async fn produce_new_block_with_mempool_transactions() { + async fn build_block_from_mempool() { let (mut sequencer, mempool_handle) = common_setup().await; let genesis_height = sequencer.chain_height; let tx = common::test_utils::produce_dummy_empty_transaction(); mempool_handle.push(tx).await.unwrap(); - let result = sequencer.produce_new_block_with_mempool_transactions(); + let result = sequencer.build_block_from_mempool(); assert!(result.is_ok()); assert_eq!(sequencer.chain_height, genesis_height + 1); } @@ -645,9 +648,7 @@ mod tests { mempool_handle.push(tx_replay).await.unwrap(); // Create block - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); + sequencer.produce_new_block().await.unwrap(); let block = sequencer .store .get_block_at_id(sequencer.chain_height) @@ -679,9 +680,7 @@ mod tests { // The transaction should be included the first time mempool_handle.push(tx.clone()).await.unwrap(); - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); + sequencer.produce_new_block().await.unwrap(); let block = sequencer .store .get_block_at_id(sequencer.chain_height) @@ -697,9 +696,7 @@ mod tests { // Add same transaction should fail mempool_handle.push(tx.clone()).await.unwrap(); - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); + sequencer.produce_new_block().await.unwrap(); let block = sequencer .store .get_block_at_id(sequencer.chain_height) @@ -738,9 +735,7 @@ mod tests { ); mempool_handle.push(tx.clone()).await.unwrap(); - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); + sequencer.produce_new_block().await.unwrap(); let block = sequencer .store .get_block_at_id(sequencer.chain_height) @@ -778,15 +773,9 @@ mod tests { let config = setup_sequencer_config(); let (mut sequencer, _mempool_handle) = SequencerCoreWithMockClients::start_from_config(config).await; - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); + sequencer.produce_new_block().await.unwrap(); + sequencer.produce_new_block().await.unwrap(); + sequencer.produce_new_block().await.unwrap(); assert_eq!(sequencer.get_pending_blocks().unwrap().len(), 4); } @@ -795,15 +784,9 @@ mod tests { let config = setup_sequencer_config(); let (mut sequencer, _mempool_handle) = SequencerCoreWithMockClients::start_from_config(config).await; - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); + sequencer.produce_new_block().await.unwrap(); + sequencer.produce_new_block().await.unwrap(); + sequencer.produce_new_block().await.unwrap(); let last_finalized_block = 3; sequencer @@ -836,9 +819,7 @@ mod tests { ); mempool_handle.push(tx).await.unwrap(); - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); + sequencer.produce_new_block().await.unwrap(); // Get the metadata of the last block produced sequencer.store.latest_block_meta().unwrap() @@ -861,9 +842,7 @@ mod tests { mempool_handle.push(tx.clone()).await.unwrap(); // Step 4: Produce new block - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); + sequencer.produce_new_block().await.unwrap(); // Step 5: Verify the new block has correct previous block metadata let new_block = sequencer @@ -876,10 +855,6 @@ mod tests { new_block.header.prev_block_hash, expected_prev_meta.hash, "New block's prev_block_hash should match the stored metadata hash" ); - assert_eq!( - new_block.bedrock_parent_id, expected_prev_meta.msg_id, - "New block's bedrock_parent_id should match the stored metadata msg_id" - ); assert_eq!( new_block.body.transactions, vec![ @@ -914,9 +889,7 @@ mod tests { .await .unwrap(); mempool_handle.push(crafted_clock_tx).await.unwrap(); - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); + sequencer.produce_new_block().await.unwrap(); let block = sequencer .store @@ -949,15 +922,11 @@ mod tests { // Produce multiple blocks to advance chain height let tx = common::test_utils::produce_dummy_empty_transaction(); mempool_handle.push(tx).await.unwrap(); - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); + sequencer.produce_new_block().await.unwrap(); let tx = common::test_utils::produce_dummy_empty_transaction(); mempool_handle.push(tx).await.unwrap(); - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); + sequencer.produce_new_block().await.unwrap(); // Return the current chain height (should be genesis_id + 2) sequencer.chain_height @@ -994,9 +963,7 @@ mod tests { ), )); mempool_handle.push(deploy_tx).await.unwrap(); - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); + sequencer.produce_new_block().await.unwrap(); // Build a user transaction that invokes clock_chain_caller, which in turn chain-calls the // clock program with the clock accounts. The sequencer should detect that the resulting @@ -1021,9 +988,7 @@ mod tests { )); mempool_handle.push(user_tx).await.unwrap(); - sequencer - .produce_new_block_with_mempool_transactions() - .unwrap(); + sequencer.produce_new_block().await.unwrap(); let block = sequencer .store @@ -1057,7 +1022,7 @@ mod tests { mempool_handle.push(tx).await.unwrap(); // Block production must fail because the appended clock tx cannot execute. - let result = sequencer.produce_new_block_with_mempool_transactions(); + let result = sequencer.produce_new_block().await; assert!( result.is_err(), "Block production should abort when clock account data is corrupted" diff --git a/sequencer/core/src/mock.rs b/sequencer/core/src/mock.rs index 45a682e2..ebe6ea5d 100644 --- a/sequencer/core/src/mock.rs +++ b/sequencer/core/src/mock.rs @@ -1,76 +1,34 @@ -use anyhow::{Result, anyhow}; -use bedrock_client::SignedMantleTx; -use logos_blockchain_core::mantle::ops::channel::ChannelId; +use std::time::Duration; + +use anyhow::Result; +use common::block::Block; use logos_blockchain_key_management_system_service::keys::Ed25519Key; -use url::Url; use crate::{ - block_settlement_client::BlockSettlementClientTrait, config::BedrockConfig, - indexer_client::IndexerClientTrait, + block_publisher::{ + BlockPublisherTrait, CheckpointSink, FinalizedBlockSink, SequencerCheckpoint, + }, + config::BedrockConfig, }; -pub type SequencerCoreWithMockClients = - crate::SequencerCore; +pub type SequencerCoreWithMockClients = crate::SequencerCore; #[derive(Clone)] -pub struct MockBlockSettlementClient { - bedrock_channel_id: ChannelId, - bedrock_signing_key: Ed25519Key, -} +pub struct MockBlockPublisher; -impl BlockSettlementClientTrait for MockBlockSettlementClient { - fn new(config: &BedrockConfig, signing_key: Ed25519Key) -> Result { - Ok(Self { - bedrock_channel_id: config.channel_id, - bedrock_signing_key: signing_key, - }) +impl BlockPublisherTrait for MockBlockPublisher { + async fn new( + _config: &BedrockConfig, + _bedrock_signing_key: Ed25519Key, + _resubmit_interval: Duration, + _initial_checkpoint: Option, + _on_checkpoint: CheckpointSink, + _on_finalized_block: FinalizedBlockSink, + ) -> Result { + Ok(Self) } - fn bedrock_channel_id(&self) -> ChannelId { - self.bedrock_channel_id - } - - fn bedrock_signing_key(&self) -> &Ed25519Key { - &self.bedrock_signing_key - } - - async fn submit_inscribe_tx_to_bedrock(&self, _tx: SignedMantleTx) -> Result<()> { + async fn publish_block(&self, _block: &Block) -> Result<()> { Ok(()) } } - -#[derive(Clone)] -pub struct MockBlockSettlementClientWithError { - bedrock_channel_id: ChannelId, - bedrock_signing_key: Ed25519Key, -} - -impl BlockSettlementClientTrait for MockBlockSettlementClientWithError { - fn new(config: &BedrockConfig, signing_key: Ed25519Key) -> Result { - Ok(Self { - bedrock_channel_id: config.channel_id, - bedrock_signing_key: signing_key, - }) - } - - fn bedrock_channel_id(&self) -> ChannelId { - self.bedrock_channel_id - } - - fn bedrock_signing_key(&self) -> &Ed25519Key { - &self.bedrock_signing_key - } - - async fn submit_inscribe_tx_to_bedrock(&self, _tx: SignedMantleTx) -> Result<()> { - Err(anyhow!("Mock error")) - } -} - -#[derive(Copy, Clone)] -pub struct MockIndexerClient; - -impl IndexerClientTrait for MockIndexerClient { - async fn new(_indexer_url: &Url) -> Result { - Ok(Self) - } -} diff --git a/sequencer/service/Cargo.toml b/sequencer/service/Cargo.toml index 6fee808c..beed6be2 100644 --- a/sequencer/service/Cargo.toml +++ b/sequencer/service/Cargo.toml @@ -14,7 +14,6 @@ mempool.workspace = true sequencer_core = { workspace = true, features = ["testnet"] } sequencer_service_protocol.workspace = true sequencer_service_rpc = { workspace = true, features = ["server"] } -indexer_service_rpc = { workspace = true, features = ["client"] } clap = { workspace = true, features = ["derive", "env"] } anyhow.workspace = true diff --git a/sequencer/service/src/lib.rs b/sequencer/service/src/lib.rs index 5373b31f..319b75ad 100644 --- a/sequencer/service/src/lib.rs +++ b/sequencer/service/src/lib.rs @@ -5,15 +5,13 @@ use bytesize::ByteSize; use common::transaction::NSSATransaction; use futures::never::Never; use jsonrpsee::server::ServerHandle; -#[cfg(not(feature = "standalone"))] -use log::warn; use log::{error, info}; use mempool::MemPoolHandle; +#[cfg(not(feature = "standalone"))] +use sequencer_core::SequencerCore; #[cfg(feature = "standalone")] use sequencer_core::SequencerCoreWithMockClients as SequencerCore; pub use sequencer_core::config::*; -#[cfg(not(feature = "standalone"))] -use sequencer_core::{SequencerCore, block_settlement_client::BlockSettlementClientTrait as _}; use sequencer_service_rpc::RpcServer as _; use tokio::{sync::Mutex, task::JoinHandle}; @@ -29,8 +27,6 @@ pub struct SequencerHandle { /// Option because of `Drop` which forbids to simply move out of `self` in `stopped()`. server_handle: Option, main_loop_handle: JoinHandle>, - retry_pending_blocks_loop_handle: JoinHandle>, - listen_for_bedrock_blocks_loop_handle: JoinHandle>, } impl SequencerHandle { @@ -38,15 +34,11 @@ impl SequencerHandle { addr: SocketAddr, server_handle: ServerHandle, main_loop_handle: JoinHandle>, - retry_pending_blocks_loop_handle: JoinHandle>, - listen_for_bedrock_blocks_loop_handle: JoinHandle>, ) -> Self { Self { addr, server_handle: Some(server_handle), main_loop_handle, - retry_pending_blocks_loop_handle, - listen_for_bedrock_blocks_loop_handle, } } @@ -60,8 +52,6 @@ impl SequencerHandle { addr: _, server_handle, main_loop_handle, - retry_pending_blocks_loop_handle, - listen_for_bedrock_blocks_loop_handle, } = &mut self; let server_handle = server_handle.take().expect("Server handle is set"); @@ -75,16 +65,6 @@ impl SequencerHandle { .context("Main loop task panicked")? .context("Main loop exited unexpectedly") } - res = retry_pending_blocks_loop_handle => { - res - .context("Retry pending blocks loop task panicked")? - .context("Retry pending blocks loop exited unexpectedly") - } - res = listen_for_bedrock_blocks_loop_handle => { - res - .context("Listen for bedrock blocks loop task panicked")? - .context("Listen for bedrock blocks loop exited unexpectedly") - } } } @@ -98,14 +78,10 @@ impl SequencerHandle { addr: _, server_handle, main_loop_handle, - retry_pending_blocks_loop_handle, - listen_for_bedrock_blocks_loop_handle, } = self; let stopped = server_handle.as_ref().is_none_or(ServerHandle::is_stopped) - || main_loop_handle.is_finished() - || retry_pending_blocks_loop_handle.is_finished() - || listen_for_bedrock_blocks_loop_handle.is_finished(); + || main_loop_handle.is_finished(); !stopped } @@ -121,13 +97,9 @@ impl Drop for SequencerHandle { addr: _, server_handle, main_loop_handle, - retry_pending_blocks_loop_handle, - listen_for_bedrock_blocks_loop_handle, } = self; main_loop_handle.abort(); - retry_pending_blocks_loop_handle.abort(); - listen_for_bedrock_blocks_loop_handle.abort(); let Some(handle) = server_handle else { return; @@ -141,7 +113,6 @@ impl Drop for SequencerHandle { pub async fn run(config: SequencerConfig, port: u16) -> Result { let block_timeout = config.block_create_timeout; - let retry_pending_blocks_timeout = config.retry_pending_blocks_timeout; let max_block_size = config.max_block_size; let (sequencer_core, mempool_handle) = SequencerCore::start_from_config(config).await; @@ -159,34 +130,10 @@ pub async fn run(config: SequencerConfig, port: u16) -> Result .await?; info!("RPC server started"); - #[cfg(not(feature = "standalone"))] - { - info!("Submitting stored pending blocks"); - retry_pending_blocks(&seq_core_wrapped) - .await - .expect("Failed to submit pending blocks on startup"); - } - info!("Starting main sequencer loop"); - let main_loop_handle = tokio::spawn(main_loop(Arc::clone(&seq_core_wrapped), block_timeout)); + let main_loop_handle = tokio::spawn(main_loop(seq_core_wrapped, block_timeout)); - info!("Starting pending block retry loop"); - let retry_pending_blocks_loop_handle = tokio::spawn(retry_pending_blocks_loop( - Arc::clone(&seq_core_wrapped), - retry_pending_blocks_timeout, - )); - - info!("Starting bedrock block listening loop"); - let listen_for_bedrock_blocks_loop_handle = - tokio::spawn(listen_for_bedrock_blocks_loop(seq_core_wrapped)); - - Ok(SequencerHandle::new( - addr, - server_handle, - main_loop_handle, - retry_pending_blocks_loop_handle, - listen_for_bedrock_blocks_loop_handle, - )) + Ok(SequencerHandle::new(addr, server_handle, main_loop_handle)) } async fn run_server( @@ -235,118 +182,3 @@ async fn main_loop(seq_core: Arc>, block_timeout: Duration) info!("Waiting for new transactions"); } } - -#[cfg(not(feature = "standalone"))] -async fn retry_pending_blocks(seq_core: &Arc>) -> Result<()> { - use std::time::Instant; - - use log::debug; - - let (mut pending_blocks, block_settlement_client) = { - let sequencer_core = seq_core.lock().await; - let client = sequencer_core.block_settlement_client(); - let pending_blocks = sequencer_core - .get_pending_blocks() - .expect("Sequencer should be able to retrieve pending blocks"); - (pending_blocks, client) - }; - - pending_blocks.sort_by(|block1, block2| block1.header.block_id.cmp(&block2.header.block_id)); - - if !pending_blocks.is_empty() { - info!( - "Resubmitting blocks from {} to {}", - pending_blocks.first().unwrap().header.block_id, - pending_blocks.last().unwrap().header.block_id - ); - } - - for block in &pending_blocks { - debug!( - "Resubmitting pending block with id {}", - block.header.block_id - ); - // TODO: We could cache the inscribe tx for each pending block to avoid re-creating it - // on every retry. - let now = Instant::now(); - let (tx, _msg_id) = block_settlement_client - .create_inscribe_tx(block) - .context("Failed to create inscribe tx for pending block")?; - - debug!("Create inscribe: {:?}", now.elapsed()); - - let now = Instant::now(); - if let Err(e) = block_settlement_client - .submit_inscribe_tx_to_bedrock(tx) - .await - { - warn!( - "Failed to resubmit block with id {} with error {e:#}", - block.header.block_id - ); - } - debug!("Post: {:?}", now.elapsed()); - } - Ok(()) -} - -#[cfg(not(feature = "standalone"))] -async fn retry_pending_blocks_loop( - seq_core: Arc>, - retry_pending_blocks_timeout: Duration, -) -> Result { - loop { - tokio::time::sleep(retry_pending_blocks_timeout).await; - retry_pending_blocks(&seq_core).await?; - } -} - -#[cfg(not(feature = "standalone"))] -async fn listen_for_bedrock_blocks_loop(seq_core: Arc>) -> Result { - use indexer_service_rpc::RpcClient as _; - - let indexer_client = seq_core.lock().await.indexer_client(); - - let retry_delay = Duration::from_secs(5); - - loop { - // TODO: Subscribe from the first pending block ID? - let mut subscription = indexer_client - .subscribe_to_finalized_blocks() - .await - .context("Failed to subscribe to finalized blocks")?; - - while let Some(block_id) = subscription.next().await { - let block_id = block_id.context("Failed to get next block from subscription")?; - - info!("Received new L2 block with ID {block_id}"); - - seq_core - .lock() - .await - .clean_finalized_blocks_from_db(block_id) - .with_context(|| { - format!("Failed to clean finalized blocks from DB for block ID {block_id}") - })?; - } - - warn!( - "Block subscription closed unexpectedly, reason: {:?}, retrying after {retry_delay:?}", - subscription.close_reason() - ); - tokio::time::sleep(retry_delay).await; - } -} - -#[cfg(feature = "standalone")] -async fn listen_for_bedrock_blocks_loop(_seq_core: Arc>) -> Result { - std::future::pending::>().await -} - -#[cfg(feature = "standalone")] -async fn retry_pending_blocks_loop( - _seq_core: Arc>, - _retry_pending_blocks_timeout: Duration, -) -> Result { - std::future::pending::>().await -} diff --git a/sequencer/service/src/service.rs b/sequencer/service/src/service.rs index 71645363..0bb8e1dd 100644 --- a/sequencer/service/src/service.rs +++ b/sequencer/service/src/service.rs @@ -8,10 +8,7 @@ use jsonrpsee::{ use log::warn; use mempool::MemPoolHandle; use nssa::{self, program::Program}; -use sequencer_core::{ - DbError, SequencerCore, block_settlement_client::BlockSettlementClientTrait, - indexer_client::IndexerClientTrait, -}; +use sequencer_core::{DbError, SequencerCore, block_publisher::BlockPublisherTrait}; use sequencer_service_protocol::{ Account, AccountId, Block, BlockId, Commitment, HashType, MembershipProof, Nonce, ProgramId, }; @@ -19,15 +16,15 @@ use tokio::sync::Mutex; const NOT_FOUND_ERROR_CODE: i32 = -31999; -pub struct SequencerService { - sequencer: Arc>>, +pub struct SequencerService { + sequencer: Arc>>, mempool_handle: MemPoolHandle, max_block_size: u64, } -impl SequencerService { +impl SequencerService { pub const fn new( - sequencer: Arc>>, + sequencer: Arc>>, mempool_handle: MemPoolHandle, max_block_size: u64, ) -> Self { @@ -40,8 +37,8 @@ impl SequencerService - sequencer_service_rpc::RpcServer for SequencerService +impl sequencer_service_rpc::RpcServer + for SequencerService { async fn send_transaction(&self, tx: NSSATransaction) -> Result { // Reserve ~200 bytes for block header overhead diff --git a/storage/src/indexer/indexer_cells.rs b/storage/src/indexer/indexer_cells.rs index 76a2c035..615902bd 100644 --- a/storage/src/indexer/indexer_cells.rs +++ b/storage/src/indexer/indexer_cells.rs @@ -8,7 +8,8 @@ use crate::{ indexer::{ ACC_NUM_CELL_NAME, BLOCK_HASH_CELL_NAME, BREAKPOINT_CELL_NAME, CF_ACC_META, CF_BREAKPOINT_NAME, CF_HASH_TO_ID, CF_TX_TO_ID, DB_META_LAST_BREAKPOINT_ID, - DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, TX_HASH_CELL_NAME, + DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY, DB_META_ZONE_SDK_INDEXER_CURSOR_KEY, + TX_HASH_CELL_NAME, }, }; @@ -211,6 +212,41 @@ impl SimpleWritableCell for AccNumTxCell { } } +/// Opaque bytes for the zone-sdk indexer cursor `Option<(MsgId, Slot)>`. +/// The caller serializes via `serde_json` (neither type derives borsh). +#[derive(BorshDeserialize)] +pub struct ZoneSdkIndexerCursorCellOwned(pub Vec); + +impl SimpleStorableCell for ZoneSdkIndexerCursorCellOwned { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_ZONE_SDK_INDEXER_CURSOR_KEY; + const CF_NAME: &'static str = CF_META_NAME; +} + +impl SimpleReadableCell for ZoneSdkIndexerCursorCellOwned {} + +#[derive(BorshSerialize)] +pub struct ZoneSdkIndexerCursorCellRef<'bytes>(pub &'bytes [u8]); + +impl SimpleStorableCell for ZoneSdkIndexerCursorCellRef<'_> { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_ZONE_SDK_INDEXER_CURSOR_KEY; + const CF_NAME: &'static str = CF_META_NAME; +} + +impl SimpleWritableCell for ZoneSdkIndexerCursorCellRef<'_> { + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message( + err, + Some("Failed to serialize zone-sdk indexer cursor cell".to_owned()), + ) + }) + } +} + #[cfg(test)] mod uniform_tests { use crate::{ diff --git a/storage/src/indexer/mod.rs b/storage/src/indexer/mod.rs index 7ef21258..75538835 100644 --- a/storage/src/indexer/mod.rs +++ b/storage/src/indexer/mod.rs @@ -22,6 +22,8 @@ pub const DB_META_LAST_OBSERVED_L1_LIB_HEADER_ID_IN_DB_KEY: &str = "last_observed_l1_lib_header_in_db"; /// Key base for storing metainformation about the last breakpoint. pub const DB_META_LAST_BREAKPOINT_ID: &str = "last_breakpoint_id"; +/// Key base for storing the zone-sdk indexer cursor (opaque bytes). +pub const DB_META_ZONE_SDK_INDEXER_CURSOR_KEY: &str = "zone_sdk_indexer_cursor"; /// Cell name for a breakpoint. pub const BREAKPOINT_CELL_NAME: &str = "breakpoint"; diff --git a/storage/src/indexer/read_once.rs b/storage/src/indexer/read_once.rs index b1ae0ada..8ab7fd23 100644 --- a/storage/src/indexer/read_once.rs +++ b/storage/src/indexer/read_once.rs @@ -4,7 +4,7 @@ use crate::{ cells::shared_cells::{BlockCell, FirstBlockCell, FirstBlockSetCell, LastBlockCell}, indexer::indexer_cells::{ AccNumTxCell, BlockHashToBlockIdMapCell, BreakpointCellOwned, LastBreakpointIdCell, - LastObservedL1LibHeaderCell, TxHashToBlockIdMapCell, + LastObservedL1LibHeaderCell, TxHashToBlockIdMapCell, ZoneSdkIndexerCursorCellOwned, }, }; @@ -64,4 +64,10 @@ impl RocksDBIO { self.get_opt::(acc_id) .map(|opt| opt.map(|cell| cell.0)) } + + pub fn get_zone_sdk_indexer_cursor_bytes(&self) -> DbResult>> { + Ok(self + .get_opt::(())? + .map(|cell| cell.0)) + } } diff --git a/storage/src/indexer/write_non_atomic.rs b/storage/src/indexer/write_non_atomic.rs index 62b466a2..505360fa 100644 --- a/storage/src/indexer/write_non_atomic.rs +++ b/storage/src/indexer/write_non_atomic.rs @@ -4,6 +4,7 @@ use crate::{ cells::shared_cells::{FirstBlockSetCell, LastBlockCell}, indexer::indexer_cells::{ BreakpointCellRef, LastBreakpointIdCell, LastObservedL1LibHeaderCell, + ZoneSdkIndexerCursorCellRef, }, }; @@ -30,6 +31,10 @@ impl RocksDBIO { self.put(&FirstBlockSetCell(true), ()) } + pub fn put_zone_sdk_indexer_cursor_bytes(&self, bytes: &[u8]) -> DbResult<()> { + self.put(&ZoneSdkIndexerCursorCellRef(bytes), ()) + } + // State pub fn put_breakpoint(&self, br_id: u64, breakpoint: &V03State) -> DbResult<()> { diff --git a/storage/src/sequencer/mod.rs b/storage/src/sequencer/mod.rs index 508f6c29..537d198d 100644 --- a/storage/src/sequencer/mod.rs +++ b/storage/src/sequencer/mod.rs @@ -12,7 +12,7 @@ use crate::{ error::DbError, sequencer::sequencer_cells::{ LastFinalizedBlockIdCell, LatestBlockMetaCellOwned, LatestBlockMetaCellRef, - NSSAStateCellOwned, NSSAStateCellRef, + NSSAStateCellOwned, NSSAStateCellRef, ZoneSdkCheckpointCellOwned, ZoneSdkCheckpointCellRef, }, }; @@ -22,6 +22,8 @@ pub mod sequencer_cells; pub const DB_META_LAST_FINALIZED_BLOCK_ID: &str = "last_finalized_block_id"; /// Key base for storing metainformation about the latest block meta. pub const DB_META_LATEST_BLOCK_META_KEY: &str = "latest_block_meta"; +/// Key base for storing the zone-sdk sequencer checkpoint (opaque bytes). +pub const DB_META_ZONE_SDK_CHECKPOINT_KEY: &str = "zone_sdk_checkpoint"; /// Key base for storing the NSSA state. pub const DB_NSSA_STATE_KEY: &str = "nssa_state"; @@ -205,6 +207,16 @@ impl RocksDBIO { self.get::(()).map(|val| val.0) } + pub fn get_zone_sdk_checkpoint_bytes(&self) -> DbResult>> { + Ok(self + .get_opt::(())? + .map(|cell| cell.0)) + } + + pub fn put_zone_sdk_checkpoint_bytes(&self, bytes: &[u8]) -> DbResult<()> { + self.put(&ZoneSdkCheckpointCellRef(bytes), ()) + } + pub fn put_block( &self, block: &Block, @@ -275,6 +287,22 @@ impl RocksDBIO { Ok(()) } + /// Mark every pending block with `block_id <= last_finalized` as finalized. + /// Idempotent — already-finalized blocks are skipped. + pub fn clean_pending_blocks_up_to(&self, last_finalized: u64) -> DbResult<()> { + let pending_ids: Vec = self + .get_all_blocks() + .filter_map(Result::ok) + .filter(|b| matches!(b.bedrock_status, BedrockStatus::Pending)) + .map(|b| b.header.block_id) + .filter(|id| *id <= last_finalized) + .collect(); + for id in pending_ids { + self.mark_block_as_finalized(id)?; + } + Ok(()) + } + pub fn mark_block_as_finalized(&self, block_id: u64) -> DbResult<()> { let mut block = self.get_block(block_id)?.ok_or_else(|| { DbError::db_interaction_error(format!("Block with id {block_id} not found")) diff --git a/storage/src/sequencer/sequencer_cells.rs b/storage/src/sequencer/sequencer_cells.rs index 0ad092d7..2bf65367 100644 --- a/storage/src/sequencer/sequencer_cells.rs +++ b/storage/src/sequencer/sequencer_cells.rs @@ -8,7 +8,7 @@ use crate::{ error::DbError, sequencer::{ CF_NSSA_STATE_NAME, DB_META_LAST_FINALIZED_BLOCK_ID, DB_META_LATEST_BLOCK_META_KEY, - DB_NSSA_STATE_KEY, + DB_META_ZONE_SDK_CHECKPOINT_KEY, DB_NSSA_STATE_KEY, }, }; @@ -95,6 +95,42 @@ impl SimpleWritableCell for LatestBlockMetaCellRef<'_> { } } +/// Opaque bytes for the zone-sdk sequencer checkpoint. The caller is +/// responsible for the actual encoding (we use `serde_json` since +/// `SequencerCheckpoint` only derives serde, not borsh). +#[derive(BorshDeserialize)] +pub struct ZoneSdkCheckpointCellOwned(pub Vec); + +impl SimpleStorableCell for ZoneSdkCheckpointCellOwned { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_ZONE_SDK_CHECKPOINT_KEY; + const CF_NAME: &'static str = CF_META_NAME; +} + +impl SimpleReadableCell for ZoneSdkCheckpointCellOwned {} + +#[derive(BorshSerialize)] +pub struct ZoneSdkCheckpointCellRef<'bytes>(pub &'bytes [u8]); + +impl SimpleStorableCell for ZoneSdkCheckpointCellRef<'_> { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_ZONE_SDK_CHECKPOINT_KEY; + const CF_NAME: &'static str = CF_META_NAME; +} + +impl SimpleWritableCell for ZoneSdkCheckpointCellRef<'_> { + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message( + err, + Some("Failed to serialize zone-sdk checkpoint cell".to_owned()), + ) + }) + } +} + #[cfg(test)] mod uniform_tests { use crate::{