feat(sequencer): use logos-blockchain zone-sdk

This commit is contained in:
Petar Radovic 2026-03-09 12:31:49 +00:00
parent 0586e98c61
commit 5191370360
16 changed files with 675 additions and 850 deletions

492
Cargo.lock generated
View File

@ -726,7 +726,7 @@ dependencies = [
"ark-ff 0.4.2",
"ark-std 0.4.0",
"tracing",
"tracing-subscriber",
"tracing-subscriber 0.2.25",
]
[[package]]
@ -738,7 +738,7 @@ dependencies = [
"ark-ff 0.5.0",
"ark-std 0.5.0",
"tracing",
"tracing-subscriber",
"tracing-subscriber 0.2.25",
]
[[package]]
@ -1198,7 +1198,7 @@ dependencies = [
"bitflags 2.11.0",
"cexpr",
"clang-sys",
"itertools 0.13.0",
"itertools 0.11.0",
"proc-macro2",
"quote",
"regex",
@ -1349,7 +1349,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85a885520bf6249ab931a764ffdb87b0ceef48e6e7d807cfdb21b751e086e1ad"
dependencies = [
"prost 0.14.3",
"prost-types",
"prost-types 0.14.3",
"tonic",
"tonic-prost",
"ureq",
@ -2344,7 +2344,7 @@ dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys 0.61.2",
"windows-sys 0.59.0",
]
[[package]]
@ -2645,7 +2645,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys 0.61.2",
"windows-sys 0.59.0",
]
[[package]]
@ -3309,6 +3309,17 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "hostname"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
dependencies = [
"libc",
"match_cfg",
"winapi",
]
[[package]]
name = "html-escape"
version = "0.2.13"
@ -3523,7 +3534,7 @@ dependencies = [
"libc",
"percent-encoding",
"pin-project-lite",
"socket2 0.6.3",
"socket2 0.5.10",
"system-configuration",
"tokio",
"tower-service",
@ -3709,6 +3720,7 @@ dependencies = [
"humantime-serde",
"log",
"logos-blockchain-core",
"logos-blockchain-zone-sdk",
"nssa",
"nssa_core",
"serde",
@ -4644,7 +4656,7 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "logos-blockchain-blend-crypto"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"blake2",
"logos-blockchain-groth16",
@ -4658,7 +4670,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-blend-message"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"blake2",
"derivative",
@ -4680,7 +4692,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-blend-proofs"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"ed25519-dalek",
"generic-array 1.3.5",
@ -4698,7 +4710,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-chain-broadcast-service"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"async-trait",
"derivative",
@ -4714,7 +4726,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-chain-service"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"async-trait",
"bytes",
@ -4729,6 +4741,7 @@ dependencies = [
"logos-blockchain-services-utils",
"logos-blockchain-storage-service",
"logos-blockchain-time-service",
"logos-blockchain-tracing",
"logos-blockchain-utils",
"num-bigint 0.4.6",
"overwatch",
@ -4744,7 +4757,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-circuits-prover"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"logos-blockchain-circuits-utils",
"tempfile",
@ -4753,7 +4766,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-circuits-utils"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"dirs",
]
@ -4761,7 +4774,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-common-http-client"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"futures",
"hex",
@ -4781,7 +4794,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-core"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"ark-ff 0.4.2",
"bincode",
@ -4811,7 +4824,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-cryptarchia-engine"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"cfg_eval",
"logos-blockchain-pol",
@ -4827,7 +4840,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-cryptarchia-sync"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"bytes",
"futures",
@ -4844,7 +4857,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-groth16"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"ark-bn254 0.4.0",
"ark-ec 0.4.2",
@ -4862,11 +4875,12 @@ dependencies = [
[[package]]
name = "logos-blockchain-http-api-common"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"axum 0.7.9",
"logos-blockchain-core",
"logos-blockchain-key-management-system-keys",
"logos-blockchain-tracing",
"serde",
"serde_json",
"serde_with",
@ -4876,7 +4890,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-key-management-system-keys"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"async-trait",
"bytes",
@ -4902,7 +4916,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-key-management-system-macros"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"proc-macro2",
"quote",
@ -4912,7 +4926,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-key-management-system-operators"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"async-trait",
"logos-blockchain-blend-proofs",
@ -4928,12 +4942,13 @@ dependencies = [
[[package]]
name = "logos-blockchain-key-management-system-service"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"async-trait",
"log",
"logos-blockchain-key-management-system-keys",
"logos-blockchain-key-management-system-operators",
"logos-blockchain-tracing",
"overwatch",
"serde",
"thiserror 2.0.18",
@ -4944,7 +4959,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-ledger"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"derivative",
"logos-blockchain-blend-crypto",
@ -4968,12 +4983,13 @@ dependencies = [
[[package]]
name = "logos-blockchain-network-service"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"async-trait",
"futures",
"logos-blockchain-core",
"logos-blockchain-cryptarchia-sync",
"logos-blockchain-tracing",
"overwatch",
"serde",
"tokio",
@ -4984,7 +5000,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-poc"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"logos-blockchain-circuits-prover",
"logos-blockchain-circuits-utils",
@ -5000,7 +5016,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-pol"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"astro-float",
"logos-blockchain-circuits-prover",
@ -5019,7 +5035,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-poq"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"logos-blockchain-circuits-prover",
"logos-blockchain-circuits-utils",
@ -5036,7 +5052,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-poseidon2"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"ark-bn254 0.4.0",
"ark-ff 0.4.2",
@ -5047,7 +5063,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-services-utils"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"async-trait",
"futures",
@ -5062,13 +5078,14 @@ dependencies = [
[[package]]
name = "logos-blockchain-storage-service"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"async-trait",
"bytes",
"futures",
"logos-blockchain-core",
"logos-blockchain-cryptarchia-engine",
"logos-blockchain-tracing",
"overwatch",
"serde",
"thiserror 1.0.69",
@ -5079,12 +5096,13 @@ dependencies = [
[[package]]
name = "logos-blockchain-time-service"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"async-trait",
"futures",
"log",
"logos-blockchain-cryptarchia-engine",
"logos-blockchain-tracing",
"overwatch",
"sntpc",
"thiserror 2.0.18",
@ -5094,10 +5112,33 @@ dependencies = [
"tracing",
]
[[package]]
name = "logos-blockchain-tracing"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"opentelemetry",
"opentelemetry-appender-tracing",
"opentelemetry-http",
"opentelemetry-otlp",
"opentelemetry-semantic-conventions",
"opentelemetry_sdk",
"rand 0.8.5",
"serde",
"tokio",
"tracing",
"tracing-appender",
"tracing-gelf",
"tracing-loki",
"tracing-opentelemetry",
"tracing-subscriber 0.3.23",
"url",
]
[[package]]
name = "logos-blockchain-utils"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"async-trait",
"blake2",
@ -5114,7 +5155,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-utxotree"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"ark-ff 0.4.2",
"logos-blockchain-groth16",
@ -5128,7 +5169,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-witness-generator"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"tempfile",
]
@ -5136,7 +5177,7 @@ dependencies = [
[[package]]
name = "logos-blockchain-zksign"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#81dbb4517aa466358ed425d92fad7d45a0c419fd"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"logos-blockchain-circuits-prover",
"logos-blockchain-circuits-utils",
@ -5150,6 +5191,33 @@ dependencies = [
"tracing",
]
[[package]]
name = "logos-blockchain-zone-sdk"
version = "0.2.1"
source = "git+https://github.com/logos-blockchain/logos-blockchain.git#c854beb0973a12d5f12fee658e63e48d1911270c"
dependencies = [
"futures",
"logos-blockchain-common-http-client",
"logos-blockchain-core",
"logos-blockchain-key-management-system-service",
"reqwest",
"rpds",
"serde",
"thiserror 2.0.18",
"tokio",
"tracing",
]
[[package]]
name = "loki-api"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdc38a304f59a03e6efa3876766a48c70a766a93f88341c3fff4212834b8e327"
dependencies = [
"prost 0.13.5",
"prost-types 0.13.5",
]
[[package]]
name = "lru-slab"
version = "0.1.2"
@ -5263,6 +5331,21 @@ dependencies = [
"syn 2.0.117",
]
[[package]]
name = "match_cfg"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
[[package]]
name = "matchers"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
dependencies = [
"regex-automata",
]
[[package]]
name = "matchit"
version = "0.7.3"
@ -5569,6 +5652,15 @@ dependencies = [
"thiserror 2.0.18",
]
[[package]]
name = "nu-ansi-term"
version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "num"
version = "0.4.3"
@ -5809,6 +5901,98 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "opentelemetry"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b84bcd6ae87133e903af7ef497404dda70c60d0ea14895fc8a5e6722754fc2a0"
dependencies = [
"futures-core",
"futures-sink",
"js-sys",
"pin-project-lite",
"thiserror 2.0.18",
]
[[package]]
name = "opentelemetry-appender-tracing"
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef6a1ac5ca3accf562b8c306fa8483c85f4390f768185ab775f242f7fe8fdcc2"
dependencies = [
"opentelemetry",
"tracing",
"tracing-core",
"tracing-subscriber 0.3.23",
]
[[package]]
name = "opentelemetry-http"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d"
dependencies = [
"async-trait",
"bytes",
"http 1.4.0",
"opentelemetry",
"reqwest",
]
[[package]]
name = "opentelemetry-otlp"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2366db2dca4d2ad033cad11e6ee42844fd727007af5ad04a1730f4cb8163bf"
dependencies = [
"http 1.4.0",
"opentelemetry",
"opentelemetry-http",
"opentelemetry-proto",
"opentelemetry_sdk",
"prost 0.14.3",
"reqwest",
"thiserror 2.0.18",
"tokio",
"tonic",
]
[[package]]
name = "opentelemetry-proto"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f"
dependencies = [
"opentelemetry",
"opentelemetry_sdk",
"prost 0.14.3",
"tonic",
"tonic-prost",
]
[[package]]
name = "opentelemetry-semantic-conventions"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e62e29dfe041afb8ed2a6c9737ab57db4907285d999ef8ad3a59092a36bdc846"
[[package]]
name = "opentelemetry_sdk"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14ae4f5991976fd48df6d843de219ca6d31b01daaab2dad5af2badeded372bd"
dependencies = [
"futures-channel",
"futures-executor",
"futures-util",
"opentelemetry",
"percent-encoding",
"rand 0.9.2",
"thiserror 2.0.18",
"tokio",
"tokio-stream",
]
[[package]]
name = "optfield"
version = "0.4.0"
@ -6215,7 +6399,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d"
dependencies = [
"anyhow",
"itertools 0.14.0",
"itertools 0.11.0",
"proc-macro2",
"quote",
"syn 2.0.117",
@ -6228,12 +6412,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b"
dependencies = [
"anyhow",
"itertools 0.14.0",
"itertools 0.11.0",
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "prost-types"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16"
dependencies = [
"prost 0.13.5",
]
[[package]]
name = "prost-types"
version = "0.14.3"
@ -6270,7 +6463,7 @@ dependencies = [
"quinn-udp",
"rustc-hash",
"rustls",
"socket2 0.6.3",
"socket2 0.5.10",
"thiserror 2.0.18",
"tokio",
"tracing",
@ -6307,9 +6500,9 @@ dependencies = [
"cfg_aliases",
"libc",
"once_cell",
"socket2 0.6.3",
"socket2 0.5.10",
"tracing",
"windows-sys 0.60.2",
"windows-sys 0.59.0",
]
[[package]]
@ -7152,7 +7345,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.61.2",
"windows-sys 0.59.0",
]
[[package]]
@ -7429,7 +7622,6 @@ version = "0.1.0"
dependencies = [
"anyhow",
"base58",
"bedrock_client",
"borsh",
"bytesize",
"chrono",
@ -7440,6 +7632,7 @@ dependencies = [
"log",
"logos-blockchain-core",
"logos-blockchain-key-management-system-service",
"logos-blockchain-zone-sdk",
"mempool",
"nssa",
"nssa_core",
@ -7461,7 +7654,6 @@ dependencies = [
"anyhow",
"base58",
"base64 0.22.1",
"bedrock_client",
"borsh",
"bytesize",
"common",
@ -7763,6 +7955,15 @@ dependencies = [
"digest",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]]
name = "shlex"
version = "1.3.0"
@ -7816,6 +8017,12 @@ version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "snap"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b"
[[package]]
name = "sntpc"
version = "0.5.2"
@ -8094,7 +8301,7 @@ dependencies = [
"getrandom 0.4.2",
"once_cell",
"rustix",
"windows-sys 0.61.2",
"windows-sys 0.59.0",
]
[[package]]
@ -8218,6 +8425,15 @@ dependencies = [
"syn 2.0.117",
]
[[package]]
name = "thread_local"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
dependencies = [
"cfg-if",
]
[[package]]
name = "throw_error"
version = "0.3.1"
@ -8618,6 +8834,18 @@ dependencies = [
"tracing-core",
]
[[package]]
name = "tracing-appender"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "786d480bce6247ab75f005b14ae1624ad978d3029d9113f0a22fa1ac773faeaf"
dependencies = [
"crossbeam-channel",
"thiserror 2.0.18",
"time",
"tracing-subscriber 0.3.23",
]
[[package]]
name = "tracing-attributes"
version = "0.1.31"
@ -8649,6 +8877,82 @@ dependencies = [
"tracing",
]
[[package]]
name = "tracing-gelf"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7c0170f1bf67b749d4377c2da1d99d6e722600051ee53870cfb6f618611e29e"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"hostname",
"serde_json",
"thiserror 1.0.69",
"tokio",
"tokio-util",
"tracing-core",
"tracing-futures",
"tracing-subscriber 0.3.23",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-loki"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3beec919fbdf99d719de8eda6adae3281f8a5b71ae40431f44dc7423053d34"
dependencies = [
"loki-api",
"reqwest",
"serde",
"serde_json",
"snap",
"tokio",
"tokio-stream",
"tracing",
"tracing-core",
"tracing-log",
"tracing-serde",
"tracing-subscriber 0.3.23",
"url",
]
[[package]]
name = "tracing-opentelemetry"
version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ac28f2d093c6c477eaa76b23525478f38de514fa9aeb1285738d4b97a9552fc"
dependencies = [
"js-sys",
"opentelemetry",
"smallvec",
"tracing",
"tracing-core",
"tracing-subscriber 0.3.23",
"web-time",
]
[[package]]
name = "tracing-serde"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1"
dependencies = [
"serde",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.2.25"
@ -8658,6 +8962,24 @@ dependencies = [
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319"
dependencies = [
"matchers",
"nu-ansi-term",
"once_cell",
"regex-automata",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
]
[[package]]
name = "triomphe"
version = "0.1.15"
@ -9246,7 +9568,7 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys 0.61.2",
"windows-sys 0.59.0",
]
[[package]]
@ -9352,15 +9674,6 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
"windows-targets 0.53.5",
]
[[package]]
name = "windows-sys"
version = "0.61.2"
@ -9394,30 +9707,13 @@ dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm 0.52.6",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.53.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
dependencies = [
"windows-link",
"windows_aarch64_gnullvm 0.53.1",
"windows_aarch64_msvc 0.53.1",
"windows_i686_gnu 0.53.1",
"windows_i686_gnullvm 0.53.1",
"windows_i686_msvc 0.53.1",
"windows_x86_64_gnu 0.53.1",
"windows_x86_64_gnullvm 0.53.1",
"windows_x86_64_msvc 0.53.1",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
@ -9430,12 +9726,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
@ -9448,12 +9738,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
@ -9466,24 +9750,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnu"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
@ -9496,12 +9768,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_i686_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
@ -9514,12 +9780,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
@ -9532,12 +9792,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
@ -9550,12 +9804,6 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
[[package]]
name = "winnow"
version = "0.7.15"

View File

@ -115,6 +115,7 @@ logos-blockchain-key-management-system-service = { git = "https://github.com/log
logos-blockchain-core = { git = "https://github.com/logos-blockchain/logos-blockchain.git" }
logos-blockchain-chain-broadcast-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git" }
logos-blockchain-chain-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git" }
logos-blockchain-zone-sdk = { git = "https://github.com/logos-blockchain/logos-blockchain.git" }
rocksdb = { version = "0.24.0", default-features = false, features = [
"snappy",

View File

@ -64,7 +64,9 @@ clean:
@echo "🧹 Cleaning run artifacts"
rm -rf sequencer_runner/bedrock_signing_key
rm -rf sequencer_runner/rocksdb
rm -rf sequencer_runner/zone_sdk_checkpoint.json
rm -rf indexer/service/rocksdb
rm -rf indexer/service/zone_sdk_indexer_cursor.json
rm -rf wallet/configs/debug/storage.json
rm -rf rocksdb
cd bedrock && docker compose down -v

View File

@ -10,6 +10,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
@ -18,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

View File

@ -1,15 +1,13 @@
use std::collections::VecDeque;
use std::sync::Arc;
use anyhow::Result;
use bedrock_client::{BedrockClient, HeaderId};
use common::block::{Block, HashableBlockData};
// ToDo: Remove after testnet
use common::{HashType, PINATA_BASE58};
use log::{debug, error, info};
use logos_blockchain_core::mantle::{
Op, SignedMantleTx,
ops::channel::{ChannelId, inscribe::InscriptionOp},
};
use futures::StreamExt as _;
use log::{error, info, warn};
use logos_blockchain_core::header::HeaderId;
use logos_blockchain_zone_sdk::indexer::ZoneIndexer;
use crate::{block_store::IndexerStore, config::IndexerConfig};
@ -18,25 +16,11 @@ pub mod config;
#[derive(Clone)]
pub struct IndexerCore {
pub bedrock_client: BedrockClient,
pub zone_indexer: Arc<ZoneIndexer>,
pub config: IndexerConfig,
pub store: IndexerStore,
}
#[derive(Clone)]
/// This struct represents one L1 block data fetched from backfilling.
pub struct BackfillBlockData {
l2_blocks: Vec<Block>,
l1_header: HeaderId,
}
#[derive(Clone)]
/// This struct represents data fetched fom backfilling in one iteration.
pub struct BackfillData {
block_data: VecDeque<BackfillBlockData>,
curr_fin_l1_lib_header: HeaderId,
}
impl IndexerCore {
pub fn new(config: IndexerConfig) -> Result<Self> {
let hashable_data = HashableBlockData {
@ -87,12 +71,15 @@ impl IndexerCore {
let home = config.home.join("rocksdb");
let auth = config.bedrock_client_config.auth.clone().map(Into::into);
let zone_indexer = ZoneIndexer::new(
config.channel_id,
config.bedrock_client_config.addr.clone(),
auth,
);
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)?,
})
@ -100,247 +87,41 @@ impl IndexerCore {
pub fn subscribe_parse_block_stream(&self) -> impl futures::Stream<Item = Result<Block>> {
async_stream::stream! {
info!("Searching for initial header");
info!("Starting zone-sdk indexer using follow()");
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
} 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 {
self.store.put_block(l2_block.clone(), l1_header).await?;
yield Ok(l2_block);
}
let follow_stream = match self.zone_indexer.follow().await {
Ok(s) => s,
Err(e) => {
error!("Failed to start zone-sdk follow stream: {e}");
return;
}
last_l1_lib_header
};
info!("Searching for initial header finished");
let mut follow_stream = std::pin::pin!(follow_stream);
info!("Starting backfilling from {prev_last_l1_lib_header}");
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);
while let Some(zone_block) = follow_stream.next().await {
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}");
continue;
}
}
}
}
}
async fn get_lib(&self) -> Result<HeaderId> {
Ok(self.bedrock_client.get_consensus_info().await?.lib)
}
async fn get_next_lib(&self, prev_lib: HeaderId) -> Result<HeaderId> {
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<BackfillData> {
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;
};
// 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()
);
info!("Indexed L2 block {}", block.header.block_id);
let (l2_block_vec, l1_header) =
parse_block_owned(&cycle_block, &self.config.channel_id);
// 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]);
info!("Parsed {} L2 blocks", l2_block_vec.len());
if !l2_block_vec.is_empty() {
block_buffer.push_front(BackfillBlockData {
l2_blocks: l2_block_vec.clone(),
l1_header,
});
if let Err(err) = self.store.put_block(block.clone(), placeholder_l1_header).await {
error!("Failed to store block {}: {err:#}", block.header.block_id);
}
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;
yield Ok(block);
}
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;
warn!("zone-sdk follow stream ended");
}
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<BackfillData> {
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<SignedMantleTx>,
decoded_channel_id: &ChannelId,
) -> (Vec<Block>, 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::<Block>(inscription)
.inspect_err(|err| {
error!("Failed to deserialize our inscription with err: {err:#?}");
})
.ok()
}
_ => None,
})
})
.collect(),
l1_block.header().id(),
)
}

View File

@ -33,6 +33,62 @@ impl Default for SequencerPartialConfig {
}
}
pub fn sequencer_config(
partial: SequencerPartialConfig,
home: PathBuf,
bedrock_addr: SocketAddr,
indexer_addr: SocketAddr,
initial_data: &InitialData,
) -> Result<SequencerConfig> {
let SequencerPartialConfig {
max_num_tx_in_block,
max_block_size,
mempool_max_size,
block_create_timeout,
} = partial;
Ok(SequencerConfig {
home,
override_rust_log: None,
genesis_id: 1,
is_genesis_random: true,
max_num_tx_in_block,
max_block_size,
mempool_max_size,
block_create_timeout,
retry_pending_blocks_timeout: Duration::from_secs(120),
port: 0,
initial_accounts: initial_data.sequencer_initial_accounts(),
initial_commitments: initial_data.sequencer_initial_commitments(),
signing_key: [37; 32],
bedrock_config: BedrockConfig {
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")?,
})
}
pub fn wallet_config(
sequencer_addr: SocketAddr,
initial_data: &InitialData,
) -> Result<WalletConfig> {
Ok(WalletConfig {
override_rust_log: None,
sequencer_addr: addr_to_url(UrlProtocol::Http, sequencer_addr)
.context("Failed to convert sequencer addr to URL")?,
seq_poll_timeout: Duration::from_secs(30),
seq_tx_poll_max_blocks: 15,
seq_poll_max_retries: 10,
seq_block_poll_max_amount: 100,
initial_accounts: initial_data.wallet_initial_accounts(),
basic_auth: None,
})
}
pub struct InitialData {
pub public_accounts: Vec<(PrivateKey, u128)>,
pub private_accounts: Vec<(KeyChain, Account)>,
@ -188,66 +244,6 @@ pub fn indexer_config(
})
}
pub fn sequencer_config(
partial: SequencerPartialConfig,
home: PathBuf,
bedrock_addr: SocketAddr,
indexer_addr: SocketAddr,
initial_data: &InitialData,
) -> Result<SequencerConfig> {
let SequencerPartialConfig {
max_num_tx_in_block,
max_block_size,
mempool_max_size,
block_create_timeout,
} = partial;
Ok(SequencerConfig {
home,
override_rust_log: None,
genesis_id: 1,
is_genesis_random: true,
max_num_tx_in_block,
max_block_size,
mempool_max_size,
block_create_timeout,
retry_pending_blocks_timeout: Duration::from_secs(120),
port: 0,
initial_accounts: initial_data.sequencer_initial_accounts(),
initial_commitments: initial_data.sequencer_initial_commitments(),
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")?,
})
}
pub fn wallet_config(
sequencer_addr: SocketAddr,
initial_data: &InitialData,
) -> Result<WalletConfig> {
Ok(WalletConfig {
override_rust_log: None,
sequencer_addr: addr_to_url(UrlProtocol::Http, sequencer_addr)
.context("Failed to convert sequencer addr to URL")?,
seq_poll_timeout: Duration::from_secs(30),
seq_tx_poll_max_blocks: 15,
seq_poll_max_retries: 10,
seq_block_poll_max_amount: 100,
initial_accounts: initial_data.wallet_initial_accounts(),
basic_auth: None,
})
}
pub fn addr_to_url(protocol: UrlProtocol, addr: SocketAddr) -> Result<Url> {
// 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:<random_port>

View File

@ -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
base58.workspace = true
anyhow.workspace = true

View File

@ -0,0 +1,95 @@
use std::{path::Path, sync::Arc, time::Duration};
use anyhow::{Context as _, Result};
use common::block::Block;
use log::info;
pub use logos_blockchain_core::mantle::ops::channel::MsgId;
pub use logos_blockchain_key_management_system_service::keys::Ed25519Key;
use logos_blockchain_zone_sdk::sequencer::{
PublishResult, SequencerCheckpoint, SequencerConfig as ZoneSdkSequencerConfig, ZoneSequencer,
};
use crate::config::BedrockConfig;
const CHECKPOINT_FILE_NAME: &str = "zone_sdk_checkpoint.json";
/// Trait for publishing L2 blocks to the L1 chain.
#[expect(async_fn_in_trait, reason = "We don't care about Send/Sync here")]
pub trait BlockPublisherTrait: Clone {
/// Initialize the publisher.
async fn new(
config: &BedrockConfig,
bedrock_signing_key: Ed25519Key,
checkpoint: Option<SequencerCheckpoint>,
resubmit_interval: Duration,
) -> Result<Self>;
/// Publish a block. Returns the checkpoint to persist.
async fn publish_block(&self, block: &Block) -> Result<SequencerCheckpoint>;
}
/// Real block publisher backed by zone-sdk's `ZoneSequencer`.
#[derive(Clone)]
pub struct ZoneSdkPublisher {
sequencer: Arc<ZoneSequencer>,
}
impl BlockPublisherTrait for ZoneSdkPublisher {
async fn new(
config: &BedrockConfig,
bedrock_signing_key: Ed25519Key,
checkpoint: Option<SequencerCheckpoint>,
resubmit_interval: Duration,
) -> Result<Self> {
let auth = config.auth.clone().map(Into::into);
let sequencer = ZoneSequencer::init_with_config(
config.channel_id,
bedrock_signing_key,
config.node_url.clone(),
auth,
ZoneSdkSequencerConfig {
resubmit_interval,
..ZoneSdkSequencerConfig::default()
},
checkpoint,
);
Ok(Self {
sequencer: Arc::new(sequencer),
})
}
async fn publish_block(&self, block: &Block) -> Result<SequencerCheckpoint> {
let data = borsh::to_vec(block).context("Failed to serialize block")?;
let PublishResult { checkpoint, .. } = self
.sequencer
.publish(data)
.await
.map_err(|e| anyhow::anyhow!("{e}"))?;
Ok(checkpoint)
}
}
/// Load a persisted checkpoint from the sequencer home directory.
pub fn load_checkpoint(home: &Path) -> Result<Option<SequencerCheckpoint>> {
let path = home.join(CHECKPOINT_FILE_NAME);
if path.exists() {
let data = std::fs::read(&path).context("Failed to read checkpoint file")?;
let checkpoint: SequencerCheckpoint =
serde_json::from_slice(&data).context("Failed to deserialize checkpoint")?;
info!("Loaded zone-sdk checkpoint from {}", path.display());
Ok(Some(checkpoint))
} else {
Ok(None)
}
}
/// Persist a checkpoint to the sequencer home directory.
pub fn save_checkpoint(home: &Path, checkpoint: &SequencerCheckpoint) -> Result<()> {
let path = home.join(CHECKPOINT_FILE_NAME);
let data = serde_json::to_vec(checkpoint).context("Failed to serialize checkpoint")?;
std::fs::write(&path, data).context("Failed to write checkpoint file")?;
Ok(())
}

View File

@ -1,127 +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 _, TxHash, ledger,
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<Self>;
/// 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 ledger_tx = ledger::Tx::new(vec![], vec![]);
let inscribe_tx = MantleTx {
ops: vec![Op::ChannelInscribe(inscribe_op)],
ledger_tx,
// Altruistic test config
storage_gas_price: 0,
execution_gas_price: 0,
};
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)],
ledger_tx_proof: empty_ledger_signature(&tx_hash),
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<Self> {
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
}
}
fn empty_ledger_signature(
tx_hash: &TxHash,
) -> logos_blockchain_key_management_system_service::keys::ZkSignature {
logos_blockchain_key_management_system_service::keys::ZkKey::multi_sign(&[], tx_hash.as_ref())
.expect("multi-sign with empty key set works")
}

View File

@ -6,7 +6,6 @@ use std::{
};
use anyhow::Result;
use bedrock_client::BackoffConfig;
use bytesize::ByteSize;
use common::{
block::{AccountInitialData, CommitmentsInitialData},
@ -57,9 +56,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.

View File

@ -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::{
@ -17,12 +16,12 @@ use mempool::{MemPool, MemPoolHandle};
pub use mock::SequencerCoreWithMockClients;
use crate::{
block_settlement_client::{BlockSettlementClient, BlockSettlementClientTrait, MsgId},
block_publisher::{BlockPublisherTrait, ZoneSdkPublisher, load_checkpoint, save_checkpoint},
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;
@ -31,7 +30,7 @@ pub mod indexer_client;
pub mod mock;
pub struct SequencerCore<
BC: BlockSettlementClientTrait = BlockSettlementClient,
BP: BlockPublisherTrait = ZoneSdkPublisher,
IC: IndexerClientTrait = IndexerClient,
> {
state: nssa::V02State,
@ -39,11 +38,11 @@ pub struct SequencerCore<
mempool: MemPool<NSSATransaction>,
sequencer_config: SequencerConfig,
chain_height: u64,
block_settlement_client: BC,
block_publisher: BP,
indexer_client: IC,
}
impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> SequencerCore<BC, IC> {
impl<BP: BlockPublisherTrait, IC: IndexerClientTrait> SequencerCore<BP, IC> {
/// 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.
@ -67,23 +66,20 @@ impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> SequencerCore<BC, I
load_or_create_signing_key(&config.home.join("bedrock_signing_key"))
.expect("Failed to load or create bedrock signing key");
let block_settlement_client = BC::new(&config.bedrock_config, bedrock_signing_key)
.expect("Failed to initialize Block Settlement Client");
let indexer_client = IC::new(&config.indexer_rpc_url)
.await
.expect("Failed to create Indexer Client");
let (_tx, genesis_msg_id) = block_settlement_client
.create_inscribe_tx(&genesis_block)
.expect("Failed to create inscribe tx for genesis block");
// TODO: Remove msg_id from BlockMeta — it is no longer needed now that
// zone-sdk manages L1 settlement state via its own checkpoint.
let genesis_msg_id = [0_u8; 32];
// Sequencer should panic if unable to open db,
// as fixing this issue may require actions non-native to program scope
let store = SequencerStore::open_db_with_genesis(
&config.home.join("rocksdb"),
&genesis_block,
genesis_msg_id.into(),
genesis_msg_id,
signing_key,
)
.unwrap();
@ -91,6 +87,26 @@ impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> SequencerCore<BC, I
.latest_block_meta()
.expect("Failed to read latest block meta from store");
// Load zone-sdk checkpoint from disk for crash recovery.
// On fresh start this will be None and zone-sdk starts from scratch.
let checkpoint = load_checkpoint(&config.home).expect("Failed to load zone-sdk checkpoint");
let is_fresh_start = checkpoint.is_none();
let block_publisher = BP::new(
&config.bedrock_config,
bedrock_signing_key,
checkpoint,
config.retry_pending_blocks_timeout,
)
.await
.expect("Failed to initialize Block Publisher");
// On fresh start, publish the genesis block so it gets inscribed to L1.
// The indexer requires block_id=1 to be on-chain to find the channel start.
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.");
@ -134,7 +150,7 @@ impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> SequencerCore<BC, I
mempool,
chain_height: latest_block_meta.id,
sequencer_config: config,
block_settlement_client,
block_publisher,
indexer_client,
};
@ -159,28 +175,33 @@ impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> SequencerCore<BC, I
Ok(tx)
}
/// Produces a new block from mempool transactions and publishes it via zone-sdk.
pub async fn produce_new_block(&mut self) -> Result<u64> {
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(()) => {}
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];
match self.block_publisher.publish_block(&block).await {
Ok(checkpoint) => {
self.store.update(&block, placeholder_msg_id, &self.state)?;
save_checkpoint(&self.sequencer_config.home, &checkpoint)?;
}
Err(err) => {
error!("Failed to post block data to Bedrock with error: {err:#}");
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<Block> {
let now = Instant::now();
let new_block_height = self
@ -255,21 +276,12 @@ impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> SequencerCore<BC, I
timestamp: curr_time,
};
// TODO: Remove bedrock_parent_id from Block — it is no longer needed now
// that zone-sdk manages the inscription parent chain internally.
let placeholder_parent_id = [0_u8; 32];
let block = hashable_data
.clone()
.into_pending_block(self.store.signing_key(), latest_block_meta.msg_id);
let (tx, msg_id) = self
.block_settlement_client
.create_inscribe_tx(&block)
.with_context(|| {
format!(
"Failed to create inscribe transaction for block with id {}",
block.header.block_id
)
})?;
self.store.update(&block, msg_id.into(), &self.state)?;
.into_pending_block(self.store.signing_key(), placeholder_parent_id);
self.chain_height = new_block_height;
@ -278,7 +290,7 @@ impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> SequencerCore<BC, I
hashable_data.transactions.len(),
now.elapsed().as_secs()
);
Ok((tx, msg_id))
Ok(block)
}
pub const fn state(&self) -> &nssa::V02State {
@ -326,8 +338,8 @@ impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> SequencerCore<BC, I
.collect())
}
pub fn block_settlement_client(&self) -> BC {
self.block_settlement_client.clone()
pub fn block_publisher(&self) -> BP {
self.block_publisher.clone()
}
pub fn indexer_client(&self) -> IC {
@ -365,7 +377,6 @@ mod tests {
use std::{pin::pin, str::FromStr as _, time::Duration};
use base58::ToBase58 as _;
use bedrock_client::BackoffConfig;
use common::{
block::AccountInitialData, test_utils::sequencer_sign_key_for_testing,
transaction::NSSATransaction,
@ -399,10 +410,6 @@ mod tests {
initial_commitments: vec![],
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,
@ -460,9 +467,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)
}
@ -646,23 +651,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 test_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);
}
@ -687,9 +690,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)
@ -714,9 +715,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)
@ -725,9 +724,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)
@ -759,9 +756,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)
@ -792,15 +787,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);
}
@ -809,15 +798,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
@ -850,9 +833,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()
@ -875,9 +856,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
@ -889,10 +868,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![tx],
@ -916,15 +891,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

View File

@ -1,69 +1,40 @@
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 logos_blockchain_zone_sdk::sequencer::SequencerCheckpoint;
use url::Url;
use crate::{
block_settlement_client::BlockSettlementClientTrait, config::BedrockConfig,
indexer_client::IndexerClientTrait,
block_publisher::BlockPublisherTrait, config::BedrockConfig, indexer_client::IndexerClientTrait,
};
pub type SequencerCoreWithMockClients =
crate::SequencerCore<MockBlockSettlementClient, MockIndexerClient>;
pub type SequencerCoreWithMockClients = crate::SequencerCore<MockBlockPublisher, MockIndexerClient>;
#[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<Self> {
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,
_checkpoint: Option<SequencerCheckpoint>,
_resubmit_interval: Duration,
) -> Result<Self> {
Ok(Self)
}
async fn publish_block(&self, _block: &Block) -> Result<SequencerCheckpoint> {
use logos_blockchain_core::{header::HeaderId, mantle::ops::channel::MsgId};
Ok(SequencerCheckpoint {
last_msg_id: MsgId::from([0; 32]),
pending_txs: vec![],
lib: HeaderId::from([0; 32]),
lib_slot: 0.into(),
})
}
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<()> {
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<Self> {
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)]

View File

@ -12,7 +12,6 @@ nssa.workspace = true
common.workspace = true
mempool.workspace = true
sequencer_core = { workspace = true }
bedrock_client.workspace = true
anyhow.workspace = true
serde_json.workspace = true

View File

@ -7,10 +7,10 @@ use common::{
use mempool::MemPoolHandle;
pub use net_utils::*;
#[cfg(feature = "standalone")]
use sequencer_core::mock::{MockBlockSettlementClient, MockIndexerClient};
use sequencer_core::mock::{MockBlockPublisher, MockIndexerClient};
use sequencer_core::{
SequencerCore,
block_settlement_client::{BlockSettlementClient, BlockSettlementClientTrait},
block_publisher::{BlockPublisherTrait, ZoneSdkPublisher},
indexer_client::{IndexerClient, IndexerClientTrait},
};
use serde::Serialize;
@ -24,14 +24,14 @@ pub mod process;
pub mod types;
#[cfg(feature = "standalone")]
pub type JsonHandlerWithMockClients = JsonHandler<MockBlockSettlementClient, MockIndexerClient>;
pub type JsonHandlerWithMockClients = JsonHandler<MockBlockPublisher, MockIndexerClient>;
// ToDo: Add necessary fields
pub struct JsonHandler<
BC: BlockSettlementClientTrait = BlockSettlementClient,
BP: BlockPublisherTrait = ZoneSdkPublisher,
IC: IndexerClientTrait = IndexerClient,
> {
sequencer_state: Arc<Mutex<SequencerCore<BC, IC>>>,
sequencer_state: Arc<Mutex<SequencerCore<BP, IC>>>,
mempool_handle: MemPoolHandle<NSSATransaction>,
max_block_size: usize,
}

View File

@ -25,9 +25,7 @@ use common::{
use itertools::Itertools as _;
use log::warn;
use nssa::{self, program::Program};
use sequencer_core::{
block_settlement_client::BlockSettlementClientTrait, indexer_client::IndexerClientTrait,
};
use sequencer_core::{block_publisher::BlockPublisherTrait, indexer_client::IndexerClientTrait};
use serde_json::Value;
use super::{JsonHandler, respond, types::err_rpc::RpcErr};
@ -56,7 +54,7 @@ pub trait Process: Send + Sync + 'static {
}
impl<
BC: BlockSettlementClientTrait + Send + Sync + 'static,
BC: BlockPublisherTrait + Send + Sync + 'static,
IC: IndexerClientTrait + Send + Sync + 'static,
> Process for JsonHandler<BC, IC>
{
@ -76,7 +74,7 @@ impl<
}
}
impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> JsonHandler<BC, IC> {
impl<BC: BlockPublisherTrait, IC: IndexerClientTrait> JsonHandler<BC, IC> {
/// Example of request processing.
fn process_temp_hello(request: Request) -> Result<Value, RpcErr> {
let _hello_request = HelloRequest::parse(Some(request.params))?;
@ -343,7 +341,6 @@ mod tests {
use base58::ToBase58 as _;
use base64::{Engine as _, engine::general_purpose};
use bedrock_client::BackoffConfig;
use common::{
block::AccountInitialData, config::BasicAuth, test_utils::sequencer_sign_key_for_testing,
transaction::NSSATransaction,
@ -351,7 +348,7 @@ mod tests {
use nssa::AccountId;
use sequencer_core::{
config::{BedrockConfig, SequencerConfig},
mock::{MockBlockSettlementClient, MockIndexerClient, SequencerCoreWithMockClients},
mock::{MockBlockPublisher, MockIndexerClient, SequencerCoreWithMockClients},
};
use serde_json::Value;
use tempfile::tempdir;
@ -359,8 +356,7 @@ mod tests {
use crate::rpc_handler;
type JsonHandlerWithMockClients =
crate::JsonHandler<MockBlockSettlementClient, MockIndexerClient>;
type JsonHandlerWithMockClients = crate::JsonHandler<MockBlockPublisher, MockIndexerClient>;
fn sequencer_config_for_tests() -> SequencerConfig {
let tempdir = tempdir().unwrap();
@ -402,10 +398,6 @@ mod tests {
signing_key: *sequencer_sign_key_for_testing().value(),
retry_pending_blocks_timeout: Duration::from_secs(60 * 4),
bedrock_config: BedrockConfig {
backoff: BackoffConfig {
start_delay: Duration::from_millis(100),
max_retries: 5,
},
channel_id: [42; 32].into(),
node_url: "http://localhost:8080".parse().unwrap(),
auth: Some(BasicAuth {
@ -450,9 +442,7 @@ mod tests {
.await
.expect("Mempool is closed, this is a bug");
sequencer_core
.produce_new_block_with_mempool_transactions()
.unwrap();
sequencer_core.produce_new_block().await.unwrap();
let max_block_size =
usize::try_from(sequencer_core.sequencer_config().max_block_size.as_u64())

View File

@ -8,11 +8,11 @@ use futures::{FutureExt as _, never::Never};
#[cfg(not(feature = "standalone"))]
use log::warn;
use log::{error, info};
#[cfg(not(feature = "standalone"))]
use sequencer_core::SequencerCore;
#[cfg(feature = "standalone")]
use sequencer_core::SequencerCoreWithMockClients as SequencerCore;
use sequencer_core::config::SequencerConfig;
#[cfg(not(feature = "standalone"))]
use sequencer_core::{SequencerCore, block_settlement_client::BlockSettlementClientTrait as _};
use sequencer_rpc::new_http_server;
use tokio::{sync::Mutex, task::JoinHandle};
@ -32,7 +32,6 @@ pub struct SequencerHandle {
addr: SocketAddr,
http_server_handle: ServerHandle,
main_loop_handle: JoinHandle<Result<Never>>,
retry_pending_blocks_loop_handle: JoinHandle<Result<Never>>,
listen_for_bedrock_blocks_loop_handle: JoinHandle<Result<Never>>,
}
@ -49,7 +48,6 @@ impl SequencerHandle {
addr: _,
http_server_handle: _,
main_loop_handle,
retry_pending_blocks_loop_handle,
listen_for_bedrock_blocks_loop_handle,
} = self;
@ -59,11 +57,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")?
@ -75,7 +68,6 @@ impl SequencerHandle {
#[must_use]
pub fn is_finished(&self) -> bool {
self.main_loop_handle.is_finished()
|| self.retry_pending_blocks_loop_handle.is_finished()
|| self.listen_for_bedrock_blocks_loop_handle.is_finished()
}
@ -91,12 +83,10 @@ impl Drop for SequencerHandle {
addr: _,
http_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();
// Can't wait here as Drop can't be async, but anyway stop signal should be sent
@ -106,7 +96,6 @@ impl Drop for SequencerHandle {
pub async fn startup_sequencer(app_config: SequencerConfig) -> Result<SequencerHandle> {
let block_timeout = app_config.block_create_timeout;
let retry_pending_blocks_timeout = app_config.retry_pending_blocks_timeout;
let port = app_config.port;
let (sequencer_core, mempool_handle) = SequencerCore::start_from_config(app_config).await;
@ -125,23 +114,9 @@ pub async fn startup_sequencer(app_config: SequencerConfig) -> Result<SequencerH
let http_server_handle = http_server.handle();
tokio::spawn(http_server);
#[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));
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));
@ -150,7 +125,6 @@ pub async fn startup_sequencer(app_config: SequencerConfig) -> Result<SequencerH
addr,
http_server_handle,
main_loop_handle,
retry_pending_blocks_loop_handle,
listen_for_bedrock_blocks_loop_handle,
})
}
@ -173,71 +147,6 @@ async fn main_loop(seq_core: Arc<Mutex<SequencerCore>>, block_timeout: Duration)
}
}
#[cfg(not(feature = "standalone"))]
async fn retry_pending_blocks(seq_core: &Arc<Mutex<SequencerCore>>) -> 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<Mutex<SequencerCore>>,
retry_pending_blocks_timeout: Duration,
) -> Result<Never> {
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<Mutex<SequencerCore>>) -> Result<Never> {
use indexer_service_rpc::RpcClient as _;
@ -280,14 +189,6 @@ async fn listen_for_bedrock_blocks_loop(_seq_core: Arc<Mutex<SequencerCore>>) ->
std::future::pending::<Result<Never>>().await
}
#[cfg(feature = "standalone")]
async fn retry_pending_blocks_loop(
_seq_core: Arc<Mutex<SequencerCore>>,
_retry_pending_blocks_timeout: Duration,
) -> Result<Never> {
std::future::pending::<Result<Never>>().await
}
pub async fn main_runner() -> Result<()> {
env_logger::init();