diff --git a/Cargo.lock b/Cargo.lock index ca28d6210..0c03ac236 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1315,11 +1315,12 @@ dependencies = [ "hotshot-orchestrator", "hotshot-stake-table", "hotshot-state-prover", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "jf-merkle-tree", "jf-signature", "libp2p", - "libp2p-networking 0.5.77 (git+https://github.com/EspressoSystems//HotShot.git?tag=0.5.77-patch1)", + "libp2p-networking", + "marketplace-builder-shared", "portpicker", "rand 0.8.5", "sequencer", @@ -2975,7 +2976,7 @@ dependencies = [ "hotshot-orchestrator", "hotshot-query-service", "hotshot-testing", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "itertools 0.12.1", "jf-merkle-tree", "jf-utils", @@ -3481,6 +3482,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + [[package]] name = "foreign-types" version = "0.3.2" @@ -3871,6 +3878,17 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + [[package]] name = "hashers" version = "1.0.1" @@ -4095,8 +4113,8 @@ dependencies = [ [[package]] name = "hotshot" -version = "0.5.77" -source = "git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1#fc947e625a95520569a98165b742fcc82e7b05ea" +version = "0.5.78" +source = "git+https://github.com/EspressoSystems/hotshot?tag=0.5.78#be7d9be60abbf8f293b7e95940ff77eff2e0739e" dependencies = [ "anyhow", "async-broadcast", @@ -4118,22 +4136,21 @@ dependencies = [ "either", "ethereum-types", "futures", - "hotshot-orchestrator", "hotshot-task", "hotshot-task-impls", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "jf-signature", "libp2p-identity", - "libp2p-networking 0.5.77 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", - "lru 0.12.4", + "libp2p-networking", + "lru 0.12.5", "num_enum", "parking_lot", "portpicker", "rand 0.8.5", "serde", "sha2 0.10.8", - "snafu 0.8.4", "surf-disco", + "thiserror", "time 0.3.36", "tokio", "tracing", @@ -4144,17 +4161,17 @@ dependencies = [ [[package]] name = "hotshot-builder-api" version = "0.1.7" -source = "git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1#fc947e625a95520569a98165b742fcc82e7b05ea" +source = "git+https://github.com/EspressoSystems/hotshot?tag=0.5.78#be7d9be60abbf8f293b7e95940ff77eff2e0739e" dependencies = [ "async-trait", "clap", "committable", "derive_more 1.0.0", "futures", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "serde", - "snafu 0.8.4", "tagged-base64", + "thiserror", "tide-disco", "toml", "vbs", @@ -4163,7 +4180,7 @@ dependencies = [ [[package]] name = "hotshot-builder-core" version = "0.1.51" -source = "git+https://github.com/EspressoSystems/marketplace-builder-core?tag=0.1.51#da0ac05c1c3dd8708a6cebc74334194e6816337e" +source = "git+https://github.com/EspressoSystems/marketplace-builder-core?tag=0.1.52#b9596777be830317a8b5022d5e7853b28f58f7dd" dependencies = [ "anyhow", "async-broadcast", @@ -4180,8 +4197,9 @@ dependencies = [ "hotshot", "hotshot-builder-api", "hotshot-events-service", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", - "lru 0.12.4", + "hotshot-types", + "lru 0.12.5", + "marketplace-builder-shared", "serde", "sha2 0.10.8", "snafu 0.8.4", @@ -4208,7 +4226,7 @@ dependencies = [ "contract-bindings", "diff-test-bn254", "ethers", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "jf-pcs", "jf-plonk", "jf-utils", @@ -4219,7 +4237,7 @@ dependencies = [ [[package]] name = "hotshot-events-service" version = "0.1.49" -source = "git+https://github.com/EspressoSystems/hotshot-events-service.git?tag=0.1.49#06700117ec9a5f73f042906b6b3eec4a7b28d0de" +source = "git+https://github.com/EspressoSystems/hotshot-events-service.git?tag=0.1.50#8cbc0e0787ebcfef750c0b4f2f9f7f16d8ea21a8" dependencies = [ "async-broadcast", "async-compatibility-layer", @@ -4231,7 +4249,7 @@ dependencies = [ "derive_more 0.99.18", "either", "futures", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "rand 0.8.5", "serde", "snafu 0.8.4", @@ -4244,8 +4262,8 @@ dependencies = [ [[package]] name = "hotshot-example-types" -version = "0.5.77" -source = "git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1#fc947e625a95520569a98165b742fcc82e7b05ea" +version = "0.5.78" +source = "git+https://github.com/EspressoSystems/hotshot?tag=0.5.78#be7d9be60abbf8f293b7e95940ff77eff2e0739e" dependencies = [ "anyhow", "async-broadcast", @@ -4261,13 +4279,13 @@ dependencies = [ "hotshot", "hotshot-task", "hotshot-task-impls", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "rand 0.8.5", "reqwest 0.12.8", "serde", "sha2 0.10.8", "sha3", - "snafu 0.8.4", + "thiserror", "time 0.3.36", "tokio", "tracing", @@ -4277,15 +4295,16 @@ dependencies = [ [[package]] name = "hotshot-fakeapi" -version = "0.5.77" -source = "git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1#fc947e625a95520569a98165b742fcc82e7b05ea" +version = "0.5.78" +source = "git+https://github.com/EspressoSystems/hotshot?tag=0.5.78#be7d9be60abbf8f293b7e95940ff77eff2e0739e" dependencies = [ "anyhow", + "async-compatibility-layer", "async-lock 2.8.0", "async-trait", "futures", "hotshot-example-types", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "rand 0.8.5", "serde", "tide-disco", @@ -4296,8 +4315,8 @@ dependencies = [ [[package]] name = "hotshot-macros" -version = "0.5.77" -source = "git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1#fc947e625a95520569a98165b742fcc82e7b05ea" +version = "0.5.78" +source = "git+https://github.com/EspressoSystems/hotshot?tag=0.5.78#be7d9be60abbf8f293b7e95940ff77eff2e0739e" dependencies = [ "derive_builder", "proc-macro2", @@ -4307,8 +4326,8 @@ dependencies = [ [[package]] name = "hotshot-orchestrator" -version = "0.5.77" -source = "git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1#fc947e625a95520569a98165b742fcc82e7b05ea" +version = "0.5.78" +source = "git+https://github.com/EspressoSystems/hotshot?tag=0.5.78#be7d9be60abbf8f293b7e95940ff77eff2e0739e" dependencies = [ "anyhow", "async-compatibility-layer", @@ -4319,11 +4338,10 @@ dependencies = [ "clap", "csv", "futures", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "libp2p", "multiaddr", "serde", - "serde-inline-default", "serde_json", "surf-disco", "thiserror", @@ -4338,7 +4356,7 @@ dependencies = [ [[package]] name = "hotshot-query-service" version = "0.1.62" -source = "git+https://github.com/EspressoSystems/hotshot-query-service?tag=0.1.63#38c9df53d2c05956da7d6570df720c5575fed8f3" +source = "git+https://github.com/EspressoSystems/hotshot-query-service?tag=0.1.64#b344b0f87b8a68bfde86f161fe1eea4e978e2a8b" dependencies = [ "anyhow", "ark-serialize", @@ -4359,7 +4377,7 @@ dependencies = [ "hotshot", "hotshot-example-types", "hotshot-testing", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "include_dir", "itertools 0.12.1", "jf-merkle-tree", @@ -4390,8 +4408,8 @@ dependencies = [ [[package]] name = "hotshot-stake-table" -version = "0.5.77" -source = "git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1#fc947e625a95520569a98165b742fcc82e7b05ea" +version = "0.5.78" +source = "git+https://github.com/EspressoSystems/hotshot?tag=0.5.78#be7d9be60abbf8f293b7e95940ff77eff2e0739e" dependencies = [ "ark-bn254", "ark-ed-on-bn254", @@ -4400,7 +4418,7 @@ dependencies = [ "ark-std", "digest 0.10.7", "ethereum-types", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "jf-crhf", "jf-rescue", "jf-signature", @@ -4429,7 +4447,7 @@ dependencies = [ "futures", "hotshot-contract-adapter", "hotshot-stake-table", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "itertools 0.12.1", "jf-crhf", "jf-pcs", @@ -4452,8 +4470,8 @@ dependencies = [ [[package]] name = "hotshot-task" -version = "0.5.77" -source = "git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1#fc947e625a95520569a98165b742fcc82e7b05ea" +version = "0.5.78" +source = "git+https://github.com/EspressoSystems/hotshot?tag=0.5.78#be7d9be60abbf8f293b7e95940ff77eff2e0739e" dependencies = [ "anyhow", "async-broadcast", @@ -4467,8 +4485,8 @@ dependencies = [ [[package]] name = "hotshot-task-impls" -version = "0.5.77" -source = "git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1#fc947e625a95520569a98165b742fcc82e7b05ea" +version = "0.5.78" +source = "git+https://github.com/EspressoSystems/hotshot?tag=0.5.78#be7d9be60abbf8f293b7e95940ff77eff2e0739e" dependencies = [ "anyhow", "async-broadcast", @@ -4485,15 +4503,15 @@ dependencies = [ "futures", "hotshot-builder-api", "hotshot-task", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "jf-signature", "jf-vid", "rand 0.8.5", "serde", "sha2 0.10.8", - "snafu 0.8.4", "surf-disco", "tagged-base64", + "thiserror", "time 0.3.36", "tokio", "tracing", @@ -4504,8 +4522,8 @@ dependencies = [ [[package]] name = "hotshot-testing" -version = "0.5.77" -source = "git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1#fc947e625a95520569a98165b742fcc82e7b05ea" +version = "0.5.78" +source = "git+https://github.com/EspressoSystems/hotshot?tag=0.5.78#be7d9be60abbf8f293b7e95940ff77eff2e0739e" dependencies = [ "anyhow", "async-broadcast", @@ -4527,19 +4545,19 @@ dependencies = [ "hotshot-orchestrator", "hotshot-task", "hotshot-task-impls", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "itertools 0.13.0", "jf-signature", "jf-vid", - "lru 0.12.4", + "lru 0.12.5", "portpicker", "rand 0.8.5", "reqwest 0.12.8", "serde", "sha2 0.10.8", "sha3", - "snafu 0.8.4", "tagged-base64", + "thiserror", "tide-disco", "tokio", "tracing", @@ -4551,61 +4569,7 @@ dependencies = [ [[package]] name = "hotshot-types" version = "0.1.11" -source = "git+https://github.com/EspressoSystems//HotShot.git?tag=0.5.77-patch1#fc947e625a95520569a98165b742fcc82e7b05ea" -dependencies = [ - "anyhow", - "ark-bn254", - "ark-ed-on-bn254", - "ark-ff", - "ark-serialize", - "ark-srs", - "ark-std", - "async-compatibility-layer", - "async-lock 2.8.0", - "async-std", - "async-trait", - "bincode", - "bitvec", - "blake3", - "cdn-proto 0.4.0 (git+https://github.com/EspressoSystems/Push-CDN?tag=0.4.7)", - "committable", - "custom_debug 0.5.1", - "derivative", - "digest 0.10.7", - "displaydoc", - "dyn-clone 1.0.17 (git+https://github.com/dtolnay/dyn-clone?tag=1.0.17)", - "either", - "espresso-systems-common 0.4.1", - "ethereum-types", - "futures", - "jf-pcs", - "jf-signature", - "jf-utils", - "jf-vid", - "lazy_static", - "libp2p", - "memoize", - "rand 0.8.5", - "rand_chacha 0.3.1", - "reqwest 0.12.8", - "serde", - "serde_bytes", - "sha2 0.10.8", - "snafu 0.8.4", - "tagged-base64", - "time 0.3.36", - "tokio", - "tracing", - "typenum", - "url", - "vbs", - "vec1", -] - -[[package]] -name = "hotshot-types" -version = "0.1.11" -source = "git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1#fc947e625a95520569a98165b742fcc82e7b05ea" +source = "git+https://github.com/EspressoSystems/hotshot?tag=0.5.78#be7d9be60abbf8f293b7e95940ff77eff2e0739e" dependencies = [ "anyhow", "ark-bn254", @@ -4622,6 +4586,7 @@ dependencies = [ "bitvec", "blake3", "cdn-proto 0.4.0 (git+https://github.com/EspressoSystems/Push-CDN?tag=0.4.7)", + "clap", "committable", "custom_debug 0.5.1", "derivative", @@ -4643,12 +4608,16 @@ dependencies = [ "rand_chacha 0.3.1", "reqwest 0.12.8", "serde", + "serde-inline-default", "serde_bytes", + "serde_json", "sha2 0.10.8", - "snafu 0.8.4", + "surf-disco", "tagged-base64", + "thiserror", "time 0.3.36", "tokio", + "toml", "tracing", "typenum", "url", @@ -5757,7 +5726,7 @@ dependencies = [ "libp2p-core", "libp2p-identity", "libp2p-swarm", - "lru 0.12.4", + "lru 0.12.5", "quick-protobuf", "quick-protobuf-codec 0.3.1", "smallvec", @@ -5860,8 +5829,8 @@ dependencies = [ [[package]] name = "libp2p-networking" -version = "0.5.77" -source = "git+https://github.com/EspressoSystems//HotShot.git?tag=0.5.77-patch1#fc947e625a95520569a98165b742fcc82e7b05ea" +version = "0.5.78" +source = "git+https://github.com/EspressoSystems/hotshot?tag=0.5.78#be7d9be60abbf8f293b7e95940ff77eff2e0739e" dependencies = [ "anyhow", "async-compatibility-layer", @@ -5875,7 +5844,7 @@ dependencies = [ "derive_builder", "either", "futures", - "hotshot-types 0.1.11 (git+https://github.com/EspressoSystems//HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "lazy_static", "libp2p", "libp2p-identity", @@ -5886,42 +5855,7 @@ dependencies = [ "serde", "serde_bytes", "serde_json", - "snafu 0.8.4", - "tokio", - "tokio-stream", - "tracing", - "void", -] - -[[package]] -name = "libp2p-networking" -version = "0.5.77" -source = "git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1#fc947e625a95520569a98165b742fcc82e7b05ea" -dependencies = [ - "anyhow", - "async-compatibility-layer", - "async-lock 2.8.0", - "async-std", - "async-trait", - "bincode", - "blake3", - "custom_debug 0.5.1", - "delegate", - "derive_builder", - "either", - "futures", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", - "lazy_static", - "libp2p", - "libp2p-identity", - "libp2p-swarm-derive", - "pin-project", - "portpicker", - "rand 0.8.5", - "serde", - "serde_bytes", - "serde_json", - "snafu 0.8.4", + "thiserror", "tokio", "tokio-stream", "tracing", @@ -5990,7 +5924,7 @@ dependencies = [ "libp2p-core", "libp2p-identity", "libp2p-swarm-derive", - "lru 0.12.4", + "lru 0.12.5", "multistream-select", "once_cell", "rand 0.8.5", @@ -6216,11 +6150,11 @@ dependencies = [ [[package]] name = "lru" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.14.5", + "hashbrown 0.15.0", ] [[package]] @@ -6264,10 +6198,11 @@ dependencies = [ "hotshot-orchestrator", "hotshot-query-service", "hotshot-stake-table", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "jf-merkle-tree", "jf-signature", "marketplace-builder-core", + "marketplace-builder-shared", "marketplace-solver", "portpicker", "sequencer", @@ -6284,7 +6219,7 @@ dependencies = [ [[package]] name = "marketplace-builder-core" version = "0.1.51" -source = "git+https://github.com/EspressoSystems/marketplace-builder-core?tag=0.1.51#da0ac05c1c3dd8708a6cebc74334194e6816337e" +source = "git+https://github.com/EspressoSystems/marketplace-builder-core?tag=0.1.52#b9596777be830317a8b5022d5e7853b28f58f7dd" dependencies = [ "anyhow", "async-broadcast", @@ -6302,10 +6237,10 @@ dependencies = [ "hotshot-builder-api", "hotshot-events-service", "hotshot-task-impls", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", - "lru 0.12.4", + "hotshot-types", + "lru 0.12.5", + "marketplace-builder-shared", "multimap", - "rkyv", "serde", "serde_json", "sha2 0.10.8", @@ -6320,6 +6255,29 @@ dependencies = [ "vbs", ] +[[package]] +name = "marketplace-builder-shared" +version = "0.1.51" +source = "git+https://github.com/EspressoSystems/marketplace-builder-core?tag=0.1.52#b9596777be830317a8b5022d5e7853b28f58f7dd" +dependencies = [ + "anyhow", + "async-broadcast", + "async-trait", + "committable", + "either", + "futures", + "hex", + "hotshot", + "hotshot-builder-api", + "hotshot-events-service", + "hotshot-task-impls", + "hotshot-types", + "surf-disco", + "tracing", + "url", + "vbs", +] + [[package]] name = "marketplace-solver" version = "0.1.0" @@ -6337,7 +6295,7 @@ dependencies = [ "hotshot", "hotshot-events-service", "hotshot-query-service", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "jf-signature", "portpicker", "rand 0.8.5", @@ -6720,7 +6678,7 @@ dependencies = [ "hotshot", "hotshot-query-service", "hotshot-stake-table", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "prometheus-parse", "reqwest 0.12.8", "serde", @@ -8731,7 +8689,7 @@ dependencies = [ "hotshot-stake-table", "hotshot-state-prover", "hotshot-testing", - "hotshot-types 0.1.11 (git+https://www.github.com/EspressoSystems/HotShot.git?tag=0.5.77-patch1)", + "hotshot-types", "include_dir", "itertools 0.12.1", "jf-crhf", @@ -8740,8 +8698,9 @@ dependencies = [ "jf-signature", "jf-vid", "libp2p", - "libp2p-networking 0.5.77 (git+https://github.com/EspressoSystems//HotShot.git?tag=0.5.77-patch1)", + "libp2p-networking", "marketplace-builder-core", + "marketplace-builder-shared", "marketplace-solver", "num_enum", "portpicker", @@ -8810,13 +8769,13 @@ dependencies = [ [[package]] name = "serde-inline-default" -version = "0.1.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa824cde50b5f01ff28a955114d8152a07cd62d81f53459dad0f2610136be844" +checksum = "b3acbd21cb24261fc36f595b38d3b34d0ff4e31a6b42edd6a43387d27c5787c8" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.77", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index d0633a021..b5d258cad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,23 +57,24 @@ dyn-clone = "1.0" ethers = { version = "2.0", features = ["solc"] } futures = "0.3" -hotshot = { git = "https://github.com/EspressoSystems/hotshot", tag = "0.5.77", features = ["dependency-tasks"] } +hotshot = { git = "https://github.com/EspressoSystems/hotshot", tag = "0.5.78" } # Hotshot imports -hotshot-builder-api = { git = "https://github.com/EspressoSystems/HotShot.git", tag = "0.5.77" } -hotshot-builder-core = { git = "https://github.com/EspressoSystems/marketplace-builder-core", tag = "0.1.51" } -marketplace-builder-core = { git = "https://github.com/EspressoSystems/marketplace-builder-core", tag = "0.1.51" } -hotshot-events-service = { git = "https://github.com/EspressoSystems/hotshot-events-service.git", tag = "0.1.49" } -hotshot-orchestrator = { git = "https://github.com/EspressoSystems/hotshot", tag = "0.5.77" } -hotshot-query-service = { git = "https://github.com/EspressoSystems/hotshot-query-service", tag = "0.1.63" } -hotshot-stake-table = { git = "https://github.com/EspressoSystems/hotshot", tag = "0.5.77" } +hotshot-builder-api = { git = "https://github.com/EspressoSystems/HotShot.git", tag = "0.5.78" } +hotshot-builder-core = { git = "https://github.com/EspressoSystems/marketplace-builder-core", tag = "0.1.52" } +marketplace-builder-core = { git = "https://github.com/EspressoSystems/marketplace-builder-core", tag = "0.1.52" } +marketplace-builder-shared = { git = "https://github.com/EspressoSystems/marketplace-builder-core", tag = "0.1.52" } +hotshot-events-service = { git = "https://github.com/EspressoSystems/hotshot-events-service.git", tag = "0.1.50" } +hotshot-orchestrator = { git = "https://github.com/EspressoSystems/hotshot", tag = "0.5.78" } +hotshot-query-service = { git = "https://github.com/EspressoSystems/hotshot-query-service", tag = "0.1.64" } +hotshot-stake-table = { git = "https://github.com/EspressoSystems/hotshot", tag = "0.5.78" } hotshot-state-prover = { version = "0.1.0", path = "hotshot-state-prover" } -hotshot-task = { git = "https://github.com/EspressoSystems/hotshot", tag = "0.5.77" } -hotshot-testing = { git = "https://github.com/EspressoSystems/hotshot", tag = "0.5.77", features = ["dependency-tasks"] } -hotshot-types = { git = "https://github.com/EspressoSystems/hotshot", tag = "0.5.77" } -libp2p-networking = { git = "https://github.com/EspressoSystems/hotshot", tag = "0.5.77" } +hotshot-task = { git = "https://github.com/EspressoSystems/hotshot", tag = "0.5.78" } +hotshot-testing = { git = "https://github.com/EspressoSystems/hotshot", tag = "0.5.78" } +hotshot-types = { git = "https://github.com/EspressoSystems/hotshot", tag = "0.5.78" } +libp2p-networking = { git = "https://github.com/EspressoSystems/hotshot", tag = "0.5.78" } hotshot-contract-adapter = { version = "0.1.0", path = "contracts/rust/adapter" } # Temporary, used to pull in the mock auction results provider -hotshot-example-types = { git = "https://github.com/EspressoSystems/hotshot", tag = "0.5.77" } +hotshot-example-types = { git = "https://github.com/EspressoSystems/hotshot", tag = "0.5.78" } # Push CDN imports cdn-broker = { git = "https://github.com/EspressoSystems/Push-CDN", features = [ @@ -154,15 +155,3 @@ debug = false strip = "debuginfo" [profile.dev.package."*"] opt-level = 3 - -[patch."https://github.com/EspressoSystems/HotShot.git"] -hotshot = { git = "https://www.github.com/EspressoSystems/HotShot.git", tag = "0.5.77-patch1" } -hotshot-builder-api = { git = "https://www.github.com/EspressoSystems/HotShot.git", tag = "0.5.77-patch1" } -hotshot-orchestrator = { git = "https://www.github.com/EspressoSystems/HotShot.git", tag = "0.5.77-patch1" } -hotshot-stake-table = { git = "https://www.github.com/EspressoSystems/HotShot.git", tag = "0.5.77-patch1" } -hotshot-task ={ git = "https://www.github.com/EspressoSystems/HotShot.git", tag = "0.5.77-patch1" } -hotshot-task-impls ={ git = "https://www.github.com/EspressoSystems/HotShot.git", tag = "0.5.77-patch1" } -hotshot-testing ={ git = "https://www.github.com/EspressoSystems/HotShot.git", tag = "0.5.77-patch1" } -hotshot-types = { git = "https://www.github.com/EspressoSystems/HotShot.git", tag = "0.5.77-patch1" } -libp2p-networking = { git = "https://github.com/EspressoSystems//HotShot.git", tag = "0.5.77-patch1" } -hotshot-example-types = { git = "https://www.github.com/EspressoSystems/HotShot.git", tag = "0.5.77-patch1" } diff --git a/builder/Cargo.toml b/builder/Cargo.toml index abcdc9809..820e44ca9 100644 --- a/builder/Cargo.toml +++ b/builder/Cargo.toml @@ -35,6 +35,7 @@ jf-merkle-tree = { workspace = true } jf-signature = { workspace = true, features = ["bls"] } libp2p = { workspace = true } libp2p-networking = { workspace = true } +marketplace-builder-shared = { workspace = true } portpicker = { workspace = true } rand = "0.8.5" sequencer = { path = "../sequencer", features = ["testing"] } diff --git a/builder/src/bin/permissioned-builder.rs b/builder/src/bin/permissioned-builder.rs deleted file mode 100644 index cada6bf53..000000000 --- a/builder/src/bin/permissioned-builder.rs +++ /dev/null @@ -1,478 +0,0 @@ -use std::{collections::HashMap, num::NonZeroUsize, path::PathBuf, time::Duration}; - -use anyhow::{bail, Context}; -use builder::permissioned::init_node; -use clap::Parser; -use espresso_types::{ - eth_signature_key::EthKeyPair, parse_duration, FeeVersion, MarketplaceVersion, - SequencerVersions, V0_0, V0_1, -}; -use ethers::types::Address; -use hotshot_types::{ - data::ViewNumber, - light_client::StateSignKey, - signature_key::BLSPrivKey, - traits::{ - metrics::NoMetrics, - node_implementation::{ConsensusTime, Versions}, - }, -}; -use libp2p::Multiaddr; -use sequencer::{persistence::no_storage::NoStorage, Genesis, L1Params, NetworkParams}; -use sequencer_utils::logging; -use url::Url; -use vbs::version::StaticVersionType; - -#[derive(Parser, Clone, Debug)] -pub struct PermissionedBuilderOptions { - /// URL of the HotShot orchestrator. - #[clap( - short, - long, - env = "ESPRESSO_SEQUENCER_ORCHESTRATOR_URL", - default_value = "http://localhost:8080" - )] - pub orchestrator_url: Url, - - /// The socket address of the HotShot CDN's main entry point (the marshal) - /// in `IP:port` form - #[clap( - short, - long, - env = "ESPRESSO_SEQUENCER_CDN_ENDPOINT", - default_value = "127.0.0.1:8081" - )] - pub cdn_endpoint: String, - - /// The address to bind to for Libp2p (in `host:port` form) - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_BIND_ADDRESS", - default_value = "0.0.0.0:1769" - )] - pub libp2p_bind_address: String, - - /// The address we advertise to other nodes as being a Libp2p endpoint. - /// Should be supplied in `host:port` form. - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_ADVERTISE_ADDRESS", - default_value = "localhost:1769" - )] - pub libp2p_advertise_address: String, - - /// A comma-separated list of Libp2p multiaddresses to use as bootstrap - /// nodes. - /// - /// Overrides those loaded from the `HotShot` config. - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_BOOTSTRAP_NODES", - value_delimiter = ',', - num_args = 1.. - )] - pub libp2p_bootstrap_nodes: Option>, - - /// URL of the Light Client State Relay Server - #[clap( - long, - env = "ESPRESSO_STATE_RELAY_SERVER_URL", - default_value = "http://localhost:8083" - )] - pub state_relay_server_url: Url, - - /// The amount of time to wait between each request to the HotShot - /// consensus or DA web servers during polling. - #[clap( - short, - long, - env = "ESPRESSO_SEQUENCER_WEBSERVER_POLL_INTERVAL", - default_value = "100ms", - value_parser = parse_duration - )] - pub webserver_poll_interval: Duration, - - /// Path to TOML file containing genesis state. - #[clap(long, name = "GENESIS_FILE", env = "ESPRESSO_BUILDER_GENESIS_FILE")] - pub genesis_file: PathBuf, - - /// Path to file containing private keys. - /// - /// The file should follow the .env format, with two keys: - /// * ESPRESSO_BUILDER_PRIVATE_STAKING_KEY - /// * ESPRESSO_BUILDER_PRIVATE_STATE_KEY - /// - /// Appropriate key files can be generated with the `keygen` utility program. - #[clap(long, name = "KEY_FILE", env = "ESPRESSO_BUILDER_KEY_FILE")] - pub key_file: Option, - - /// Private staking key. - /// - /// This can be used as an alternative to KEY_FILE. - #[clap( - long, - env = "ESPRESSO_BUILDER_PRIVATE_STAKING_KEY", - conflicts_with = "KEY_FILE" - )] - pub private_staking_key: Option, - - /// Private state signing key. - /// - /// This can be used as an alternative to KEY_FILE. - #[clap( - long, - env = "ESPRESSO_BUILDER_PRIVATE_STATE_KEY", - conflicts_with = "KEY_FILE" - )] - pub private_state_key: Option, - - /// Mnemonic phrase for builder account. - /// - /// This is the address fees will be charged to. - /// It must be funded with ETH in the Espresso fee ledger - #[clap(long, env = "ESPRESSO_BUILDER_ETH_MNEMONIC")] - pub eth_mnemonic: String, - - /// Index of a funded account derived from eth-mnemonic. - #[clap(long, env = "ESPRESSO_BUILDER_ETH_ACCOUNT_INDEX", default_value = "8")] - pub eth_account_index: u32, - - /// Url we will use for RPC communication with L1. - #[clap(long, env = "ESPRESSO_BUILDER_L1_PROVIDER")] - pub l1_provider_url: Url, - - /// Peer nodes use to fetch missing state - #[clap(long, env = "ESPRESSO_SEQUENCER_STATE_PEERS", value_delimiter = ',')] - pub state_peers: Vec, - - /// Port to run the builder server on. - #[clap(short, long, env = "ESPRESSO_BUILDER_SERVER_PORT")] - pub port: u16, - - /// Port to run the builder server on. - #[clap(short, long, env = "ESPRESSO_BUILDER_ADDRESS")] - pub address: Address, - - /// Bootstrapping View number - #[clap(short, long, env = "ESPRESSO_BUILDER_BOOTSTRAPPED_VIEW")] - pub view_number: u64, - - /// BUILDER TRANSACTIONS CHANNEL CAPACITY - #[clap(long, env = "ESPRESSO_BUILDER_TX_CHANNEL_CAPACITY")] - pub tx_channel_capacity: NonZeroUsize, - - /// BUILDER HS EVENTS CHANNEL CAPACITY - #[clap(long, env = "ESPRESSO_BUILDER_EVENT_CHANNEL_CAPACITY")] - pub event_channel_capacity: NonZeroUsize, - - /// Url a sequencer can use to stream hotshot events - #[clap(long, env = "ESPRESSO_SEQUENCER_HOTSHOT_EVENTS_PROVIDER")] - pub hotshot_events_streaming_server_url: Url, - - /// Time between each Libp2p heartbeat - #[clap(long, env = "ESPRESSO_SEQUENCER_LIBP2P_HEARTBEAT_INTERVAL", default_value = "1s", value_parser = parse_duration)] - pub libp2p_heartbeat_interval: Duration, - - /// Number of past heartbeats to gossip about on Libp2p - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_HISTORY_GOSSIP", - default_value = "3" - )] - pub libp2p_history_gossip: usize, - - /// Number of heartbeats to keep in the Libp2p `memcache` - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_HISTORY_LENGTH", - default_value = "5" - )] - pub libp2p_history_length: usize, - - /// Target number of peers for the Libp2p mesh network - #[clap(long, env = "ESPRESSO_SEQUENCER_LIBP2P_MESH_N", default_value = "8")] - pub libp2p_mesh_n: usize, - - /// Maximum number of peers in the Libp2p mesh network before removing some - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_MESH_N_HIGH", - default_value = "12" - )] - pub libp2p_mesh_n_high: usize, - - /// Minimum number of peers in the Libp2p mesh network before adding more - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_MESH_N_LOW", - default_value = "6" - )] - pub libp2p_mesh_n_low: usize, - - /// Minimum number of outbound Libp2p peers in the mesh network before adding more - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_MESH_OUTBOUND_MIN", - default_value = "2" - )] - pub libp2p_mesh_outbound_min: usize, - - /// The maximum number of messages to include in a Libp2p IHAVE message - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_MAX_IHAVE_LENGTH", - default_value = "5000" - )] - pub libp2p_max_ihave_length: usize, - - /// The maximum number of IHAVE messages to accept from a Libp2p peer within a heartbeat - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_MAX_IHAVE_MESSAGES", - default_value = "10" - )] - pub libp2p_max_ihave_messages: usize, - - /// Libp2p published message ids time cache duration - #[clap(long, env = "ESPRESSO_SEQUENCER_LIBP2P_PUBLISHED_MESSAGE_IDS_CACHE_TIME", default_value = "10s", value_parser = parse_duration)] - pub libp2p_published_message_ids_cache_time: Duration, - - /// Time to wait for a Libp2p message requested through IWANT following an IHAVE advertisement - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_MAX_IWANT_FOLLOWUP_TIME", - default_value = "3s", value_parser = parse_duration - )] - pub libp2p_iwant_followup_time: Duration, - - /// The maximum number of Libp2p messages we will process in a given RPC - #[clap(long, env = "ESPRESSO_SEQUENCER_LIBP2P_MAX_MESSAGES_PER_RPC")] - pub libp2p_max_messages_per_rpc: Option, - - /// How many times we will allow a Libp2p peer to request the same message id through IWANT gossip before we start ignoring them - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_GOSSIP_RETRANSMISSION", - default_value = "3" - )] - pub libp2p_gossip_retransmission: u32, - - /// If enabled newly created messages will always be sent to all peers that are subscribed to the topic and have a good enough score - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_FLOOD_PUBLISH", - default_value = "true" - )] - pub libp2p_flood_publish: bool, - - /// The time period that Libp2p message hashes are stored in the cache - #[clap(long, env = "ESPRESSO_SEQUENCER_LIBP2P_DUPLICATE_CACHE_TIME", default_value = "20m", value_parser = parse_duration)] - pub libp2p_duplicate_cache_time: Duration, - - /// Time to live for Libp2p fanout peers - #[clap(long, env = "ESPRESSO_SEQUENCER_LIBP2P_FANOUT_TTL", default_value = "60s", value_parser = parse_duration)] - pub libp2p_fanout_ttl: Duration, - - /// Initial delay in each Libp2p heartbeat - #[clap(long, env = "ESPRESSO_SEQUENCER_LIBP2P_HEARTBEAT_INITIAL_DELAY", default_value = "5s", value_parser = parse_duration)] - pub libp2p_heartbeat_initial_delay: Duration, - - /// How many Libp2p peers we will emit gossip to at each heartbeat - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_GOSSIP_FACTOR", - default_value = "0.25" - )] - pub libp2p_gossip_factor: f64, - - /// Minimum number of Libp2p peers to emit gossip to during a heartbeat - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_GOSSIP_LAZY", - default_value = "6" - )] - pub libp2p_gossip_lazy: usize, - - /// The maximum number of bytes we will send in a single Libp2p gossip message - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_MAX_TRANSMIT_SIZE", - default_value = "2000000" - )] - pub libp2p_max_transmit_size: usize, - - /// The amount of time a builder can wait before timing out a request to the API. - #[clap( - short, - long, - env = "ESPRESSO_BUILDER_WEBSERVER_RESPONSE_TIMEOUT_DURATION", - default_value = "1s", - value_parser = parse_duration - )] - pub max_api_timeout_duration: Duration, - - /// The number of views to buffer before a builder garbage collects its state - #[clap( - long, - env = "ESPRESSO_BUILDER_BUFFER_VIEW_NUM_COUNT", - default_value = "15" - )] - pub buffer_view_num_count: usize, - - /// Whether or not we are a DA node. - #[clap(long, env = "ESPRESSO_SEQUENCER_IS_DA", action)] - pub is_da: bool, - - #[clap(flatten)] - logging: logging::Config, -} - -impl PermissionedBuilderOptions { - pub fn private_keys(&self) -> anyhow::Result<(BLSPrivKey, StateSignKey)> { - if let Some(path) = &self.key_file { - let vars = dotenvy::from_path_iter(path)?.collect::, _>>()?; - let staking = vars - .get("ESPRESSO_BUILDER_PRIVATE_STAKING_KEY") - .context("key file missing ESPRESSO_BUILDER_PRIVATE_STAKING_KEY")? - .parse()?; - let state = vars - .get("ESPRESSO_BUILDER_PRIVATE_STATE_KEY") - .context("key file missing ESPRESSO_BUILDER_PRIVATE_STATE_KEY")? - .parse()?; - Ok((staking, state)) - } else if let (Some(staking), Some(state)) = ( - self.private_staking_key.clone(), - self.private_state_key.clone(), - ) { - Ok((staking, state)) - } else { - bail!("neither key file nor full set of private keys was provided") - } - } -} - -async fn run( - genesis: Genesis, - opt: PermissionedBuilderOptions, - versions: V, -) -> anyhow::Result<()> { - let (private_staking_key, private_state_key) = opt.private_keys()?; - - let l1_params = L1Params { - url: opt.l1_provider_url, - events_max_block_range: 10000, - }; - - let builder_key_pair = EthKeyPair::from_mnemonic(&opt.eth_mnemonic, opt.eth_account_index)?; - - let network_params = NetworkParams { - cdn_endpoint: opt.cdn_endpoint, - libp2p_advertise_address: opt.libp2p_advertise_address, - libp2p_bind_address: opt.libp2p_bind_address, - libp2p_bootstrap_nodes: opt.libp2p_bootstrap_nodes, - orchestrator_url: opt.orchestrator_url, - state_relay_server_url: opt.state_relay_server_url, - private_staking_key: private_staking_key.clone(), - private_state_key, - state_peers: opt.state_peers, - public_api_url: None, - libp2p_history_gossip: opt.libp2p_history_gossip, - libp2p_history_length: opt.libp2p_history_length, - libp2p_max_ihave_length: opt.libp2p_max_ihave_length, - libp2p_max_ihave_messages: opt.libp2p_max_ihave_messages, - libp2p_max_transmit_size: opt.libp2p_max_transmit_size, - libp2p_mesh_n: opt.libp2p_mesh_n, - libp2p_mesh_n_high: opt.libp2p_mesh_n_high, - libp2p_heartbeat_interval: opt.libp2p_heartbeat_interval, - libp2p_mesh_n_low: opt.libp2p_mesh_n_low, - libp2p_mesh_outbound_min: opt.libp2p_mesh_outbound_min, - libp2p_published_message_ids_cache_time: opt.libp2p_published_message_ids_cache_time, - libp2p_iwant_followup_time: opt.libp2p_iwant_followup_time, - libp2p_max_messages_per_rpc: opt.libp2p_max_messages_per_rpc, - libp2p_gossip_retransmission: opt.libp2p_gossip_retransmission, - libp2p_flood_publish: opt.libp2p_flood_publish, - libp2p_duplicate_cache_time: opt.libp2p_duplicate_cache_time, - libp2p_fanout_ttl: opt.libp2p_fanout_ttl, - libp2p_heartbeat_initial_delay: opt.libp2p_heartbeat_initial_delay, - libp2p_gossip_factor: opt.libp2p_gossip_factor, - libp2p_gossip_lazy: opt.libp2p_gossip_lazy, - config_peers: None, - catchup_backoff: Default::default(), - }; - - let builder_server_url: Url = format!("http://0.0.0.0:{}", opt.port).parse().unwrap(); - - let bootstrapped_view = ViewNumber::new(opt.view_number); - - let max_api_response_timeout_duration = opt.max_api_timeout_duration; - // make the txn timeout as 1/4 of the api_response_timeout_duration - let txn_timeout_duration = max_api_response_timeout_duration / 4; - - let buffer_view_num_count = opt.buffer_view_num_count; - - // it will internally spawn the builder web server - let ctx = init_node( - genesis, - network_params, - &NoMetrics, - l1_params, - builder_server_url.clone(), - builder_key_pair, - bootstrapped_view, - opt.tx_channel_capacity, - opt.event_channel_capacity, - versions, - NoStorage, - max_api_response_timeout_duration, - buffer_view_num_count, - opt.is_da, - txn_timeout_duration, - ) - .await?; - - // Start doing consensus. - ctx.start_consensus().await; - - Ok(()) -} - -#[async_std::main] -async fn main() -> anyhow::Result<()> { - let opt = PermissionedBuilderOptions::parse(); - opt.logging.init(); - - let genesis = Genesis::from_file(&opt.genesis_file)?; - tracing::info!(?genesis, "genesis"); - - let base = genesis.base_version; - let upgrade = genesis.upgrade_version; - - match (base, upgrade) { - (V0_1::VERSION, FeeVersion::VERSION) => { - run(genesis, opt, SequencerVersions::::new()).await - } - (FeeVersion::VERSION, MarketplaceVersion::VERSION) => { - run( - genesis, - opt, - SequencerVersions::::new(), - ) - .await - } - (V0_1::VERSION, _) => run(genesis, opt, SequencerVersions::::new()).await, - (FeeVersion::VERSION, _) => { - run(genesis, opt, SequencerVersions::::new()).await - } - (MarketplaceVersion::VERSION, _) => { - run( - genesis, - opt, - SequencerVersions::::new(), - ) - .await - } - _ => panic!( - "Invalid base ({base}) and upgrade ({upgrade}) versions specified in the toml file." - ), - } -} diff --git a/builder/src/bin/permissionless-builder.rs b/builder/src/bin/permissionless-builder.rs index abbd46135..15b513fba 100644 --- a/builder/src/bin/permissionless-builder.rs +++ b/builder/src/bin/permissionless-builder.rs @@ -76,13 +76,15 @@ struct NonPermissionedBuilderOptions { )] max_api_timeout_duration: Duration, - /// The number of views to buffer before a builder garbage collects its state + /// The amount of time a builder can wait before incrementing the max block size. #[clap( + short, long, - env = "ESPRESSO_BUILDER_BUFFER_VIEW_NUM_COUNT", - default_value = "15" + env = "ESPRESSO_BUILDER_MAX_BLOCK_SIZE_INCREMENT_PERIOD", + default_value = "3600s", + value_parser = parse_duration )] - buffer_view_num_count: usize, + max_block_size_increment_period: Duration, /// Path to TOML file containing genesis state. #[clap(long, name = "GENESIS_FILE", env = "ESPRESSO_BUILDER_GENESIS_FILE")] @@ -148,20 +150,18 @@ async fn run( // make the txn timeout as 1/4 of the api_response_timeout_duration let txn_timeout_duration = api_response_timeout_duration / 4; - let buffer_view_num_count = opt.buffer_view_num_count; - let _builder_config = BuilderConfig::init::( builder_key_pair, bootstrapped_view, opt.tx_channel_capacity, opt.event_channel_capacity, opt.node_count, - instance_state, + instance_state.clone(), validated_state, opt.hotshot_event_streaming_url, builder_server_url, api_response_timeout_duration, - buffer_view_num_count, + opt.max_block_size_increment_period, txn_timeout_duration, base_fee, ) diff --git a/builder/src/lib.rs b/builder/src/lib.rs index d72d9518b..fe33f46e7 100755 --- a/builder/src/lib.rs +++ b/builder/src/lib.rs @@ -36,10 +36,8 @@ use hotshot_builder_api::v0_1::builder::{ BuildError, Error as BuilderApiError, Options as HotshotBuilderApiOptions, }; use hotshot_builder_core::service::{GlobalState, ProxyGlobalState}; -use hotshot_orchestrator::{ - client::{OrchestratorClient, ValidatorArgs}, - config::NetworkConfig, -}; +use hotshot_orchestrator::client::{OrchestratorClient, ValidatorArgs}; +use hotshot_types::network::NetworkConfig; // Should move `STAKE_TABLE_CAPACITY` in the sequencer repo when we have variate stake table support use hotshot_stake_table::config::STAKE_TABLE_CAPACITY; use hotshot_types::{ @@ -71,7 +69,6 @@ use tide_disco::{app, method::ReadState, App, Url}; use vbs::version::{StaticVersion, StaticVersionType}; pub mod non_permissioned; -pub mod permissioned; // It runs the api service for the builder pub fn run_builder_api_service(url: Url, source: ProxyGlobalState) { @@ -179,10 +176,7 @@ pub mod testing { use vbs::version::StaticVersion; use super::*; - use crate::{ - non_permissioned::BuilderConfig, - permissioned::{init_hotshot, BuilderContext}, - }; + use crate::non_permissioned::BuilderConfig; #[derive(Clone)] pub struct HotShotTestConfig { @@ -191,8 +185,6 @@ pub mod testing { priv_keys_non_staking_nodes: Vec, staking_nodes_state_key_pairs: Vec, non_staking_nodes_state_key_pairs: Vec, - non_staking_nodes_stake_entries: Vec>, - master_map: Arc>, anvil: Arc, } @@ -218,8 +210,6 @@ pub mod testing { .map(|x| ::public_key(&x.stake_table_entry)) .collect::>(); - let master_map = MasterMap::new(); - let builder_url = hotshot_builder_url(); let config: HotShotConfig = HotShotConfig { @@ -252,6 +242,7 @@ pub mod testing { start_voting_time: 0, stop_proposing_time: 0, stop_voting_time: 0, + epoch_height: 0, }; Self { @@ -260,8 +251,6 @@ pub mod testing { priv_keys_non_staking_nodes, staking_nodes_state_key_pairs, non_staking_nodes_state_key_pairs, - non_staking_nodes_stake_entries: known_nodes_without_stake, - master_map, anvil: Arc::new(Anvil::new().spawn()), } } @@ -343,100 +332,6 @@ pub mod testing { } } - pub async fn init_nodes( - &self, - bind_version: V, - options: impl PersistenceOptions, - ) -> Vec<( - Arc>, - Option>, - )> { - let num_staked_nodes = self.num_staked_nodes(); - let mut is_staked = false; - let stake_table_commit = static_stake_table_commitment( - &self.config.known_nodes_with_stake, - Self::total_nodes(), - ); - - join_all((0..self.num_staking_non_staking_nodes()).map(|i| { - is_staked = i < num_staked_nodes; - let options = options.clone(); - async move { - let persistence = options.create().await.unwrap(); - let (hotshot_handle, state_signer) = self - .init_node( - i, - is_staked, - stake_table_commit, - &NoMetrics, - bind_version, - persistence, - ) - .await; - // wrapped in some because need to take later - (Arc::new(hotshot_handle), Some(state_signer)) - } - })) - .await - } - - pub async fn init_node( - &self, - i: usize, - is_staked: bool, - stake_table_commit: StakeTableCommitmentType, - metrics: &dyn Metrics, - bind_version: V, - persistence: P, - ) -> ( - Consensus, - StateSigner, - ) { - let mut config = self.config.clone(); - - let num_staked_nodes = self.num_staked_nodes(); - if is_staked { - config.my_own_validator_config = self.get_validator_config(i, is_staked); - } else { - config.my_own_validator_config = - self.get_validator_config(i - num_staked_nodes, is_staked); - } - - let network = Arc::new(MemoryNetwork::new( - &config.my_own_validator_config.public_key, - &self.master_map, - &[Topic::Global, Topic::Da], - None, - )); - - let node_state = NodeState::new( - i as u64, - ChainConfig::default(), - L1Client::new(self.anvil.endpoint().parse().unwrap(), 1), - MockStateCatchup::default(), - V::Base::VERSION, - ) - .with_genesis(ValidatedState::default()); - - tracing::info!("Before init hotshot"); - let handle = init_hotshot( - config, - Some(self.non_staking_nodes_stake_entries.clone()), - node_state, - network, - metrics, - i as u64, - None, - stake_table_commit, - bind_version, - persistence, - ) - .await; - - tracing::info!("After init hotshot"); - handle - } - // url for the hotshot event streaming api pub fn hotshot_event_streaming_api_url() -> Url { // spawn the event streaming api @@ -571,7 +466,7 @@ pub mod testing { hotshot_events_streaming_api_url, hotshot_builder_api_url, Duration::from_millis(2000), - 15, + Duration::from_secs(60), Duration::from_millis(500), ChainConfig::default().base_fee, ) @@ -585,58 +480,6 @@ pub mod testing { } } - pub struct PermissionedBuilderTestConfig { - pub builder_context: BuilderContext, - pub fee_account: FeeAccount, - } - - impl PermissionedBuilderTestConfig { - pub async fn init_permissioned_builder( - hotshot_handle: Arc>, - node_id: u64, - state_signer: Arc>, - hotshot_builder_api_url: Url, - ) -> Self { - // setup the instance state - let node_state = NodeState::default().with_current_version(V::Base::VERSION); - - // generate builder keys - let seed = [201_u8; 32]; - let (fee_account, key_pair) = FeeAccount::generated_from_seed_indexed(seed, 2011_u64); - - // channel capacity for the builder states - let tx_channel_capacity = NonZeroUsize::new(20).unwrap(); - let event_channel_capacity = NonZeroUsize::new(500).unwrap(); - // bootstrapping view number - // A new builder can use this view number to start building blocks from this view number - let bootstrapped_view = ViewNumber::new(0); - - let builder_context = BuilderContext::init( - Arc::clone(&hotshot_handle), - state_signer, - node_id, - key_pair, - bootstrapped_view, - tx_channel_capacity, - event_channel_capacity, - node_state, - ValidatedState::default(), - hotshot_builder_api_url, - Duration::from_millis(2000), - 15, - Duration::from_millis(500), - ChainConfig::default().base_fee, - ) - .await - .unwrap(); - - Self { - builder_context, - fee_account, - } - } - } - pub fn hotshot_builder_url() -> Url { // spawn the builder api let port = @@ -778,102 +621,3 @@ pub mod testing { } } } - -#[cfg(test)] -mod test { - use async_std::stream::IntoStream; - use clap::builder; - use espresso_types::{Header, MockSequencerVersions, NodeState, Payload, ValidatedState}; - use ethers::providers::Quorum; - use futures::StreamExt; - use hotshot::types::EventType::Decide; - use hotshot_builder_api::v0_1::block_info::AvailableBlockData; - use hotshot_builder_core::service::GlobalState; - use sequencer::{ - empty_builder_commitment, - persistence::{ - no_storage::{self, NoStorage}, - sql, - }, - }; - use sequencer_utils::test_utils::setup_test; - use testing::{wait_for_decide_on_handle, HotShotTestConfig}; - use vbs::version::StaticVersion; - - use super::*; - - // Test that a non-voting hotshot node can participate in consensus and reach a certain height. - // It is enabled by keeping the node(s) in the stake table, but with a stake of 0. - // This is useful for testing that the builder(permissioned node) can participate in consensus without voting. - #[ignore] - #[async_std::test] - async fn test_non_voting_hotshot_node() { - setup_test(); - - let success_height = 5; - // Assign `config` so it isn't dropped early. - let config = HotShotTestConfig::default(); - tracing::debug!("Done with hotshot test config"); - let handles = config - .init_nodes(MockSequencerVersions::new(), no_storage::Options) - .await; - tracing::debug!("Done with init nodes"); - let total_nodes = HotShotTestConfig::total_nodes(); - - // try to listen on non-voting node handle as it is the last handle - let mut events = handles[total_nodes - 1].0.event_stream(); - for (handle, ..) in handles.iter() { - handle.hotshot.start_consensus().await; - } - - let genesis_state = NodeState::mock(); - let validated_state = ValidatedState::default(); - let mut parent = { - // TODO refactor repeated code from other tests - let (genesis_payload, genesis_ns_table) = - Payload::from_transactions([], &validated_state, &genesis_state) - .await - .expect("unable to create genesis payload"); - let builder_commitment = genesis_payload.builder_commitment(&genesis_ns_table); - let genesis_commitment = { - // TODO we should not need to collect payload bytes just to compute vid_commitment - let payload_bytes = genesis_payload.encode(); - vid_commitment(&payload_bytes, GENESIS_VID_NUM_STORAGE_NODES) - }; - Header::genesis( - &genesis_state, - genesis_commitment, - builder_commitment, - genesis_ns_table, - ) - }; - - loop { - let event = events.next().await.unwrap(); - tracing::debug!("Received event from handle: {event:?}"); - let Decide { leaf_chain, .. } = event.event else { - continue; - }; - tracing::info!("Got decide {leaf_chain:?}"); - - // Check that each successive header satisfies invariants relative to its parent: all - // the fields which should be monotonic are. - for LeafInfo { leaf, .. } in leaf_chain.iter().rev() { - let header = leaf.block_header().clone(); - if header.height() == 0 { - parent = header; - continue; - } - assert_eq!(header.height(), parent.height() + 1); - assert!(header.timestamp() >= parent.timestamp()); - assert!(header.l1_head() >= parent.l1_head()); - assert!(header.l1_finalized() >= parent.l1_finalized()); - parent = header; - } - - if parent.height() >= success_height { - break; - } - } - } -} diff --git a/builder/src/non_permissioned.rs b/builder/src/non_permissioned.rs index 5b8d9cdf9..9011f0e52 100644 --- a/builder/src/non_permissioned.rs +++ b/builder/src/non_permissioned.rs @@ -28,7 +28,6 @@ use hotshot_builder_core::{ run_non_permissioned_standalone_builder_service, GlobalState, ProxyGlobalState, ReceivedTransaction, }, - ParentBlockReferences, }; use hotshot_events_service::{ events::{Error as EventStreamApiError, Options as EventStreamingApiOptions}, @@ -43,6 +42,8 @@ use hotshot_types::{ }, utils::BuilderCommitment, }; +use marketplace_builder_shared::block::ParentBlockReferences; +use marketplace_builder_shared::utils::EventServiceStream; use sequencer::{catchup::StatePeers, L1Params, NetworkParams, SequencerApiVersion}; use surf::http::headers::ACCEPT; use surf_disco::Client; @@ -90,7 +91,7 @@ impl BuilderConfig { hotshot_events_api_url: Url, hotshot_builder_apis_url: Url, max_api_timeout_duration: Duration, - buffered_view_num_count: usize, + max_block_size_increment_period: Duration, maximize_txns_count_timeout_duration: Duration, base_fee: FeeAmount, ) -> anyhow::Result { @@ -100,7 +101,7 @@ impl BuilderConfig { %tx_channel_capacity, %event_channel_capacity, ?max_api_timeout_duration, - buffered_view_num_count, + ?instance_state.chain_config.max_block_size, ?maximize_txns_count_timeout_duration, "initializing builder", ); @@ -145,7 +146,8 @@ impl BuilderConfig { vid_commitment, bootstrapped_view, bootstrapped_view, - buffered_view_num_count as u64, + max_block_size_increment_period, + instance_state.chain_config.max_block_size.into(), ); let global_state = Arc::new(RwLock::new(global_state)); @@ -194,12 +196,17 @@ impl BuilderConfig { let events_url = hotshot_events_api_url.clone(); let global_state_clone = global_state.clone(); tracing::info!("Running permissionless builder against hotshot events API at {events_url}",); + + let event_stream = + EventServiceStream::::connect(events_url).await?; + async_spawn(async move { - let res = run_non_permissioned_standalone_builder_service::<_, SequencerApiVersion>( + let res = run_non_permissioned_standalone_builder_service::<_, SequencerApiVersion, _>( da_sender, qc_sender, decide_sender, - events_url, + event_stream, + node_count, global_state_clone, ) .await; @@ -236,10 +243,7 @@ mod test { block_info::{AvailableBlockData, AvailableBlockHeaderInput, AvailableBlockInfo}, builder::BuildError, }; - use hotshot_builder_core::service::{ - run_non_permissioned_standalone_builder_service, - run_permissioned_standalone_builder_service, - }; + use hotshot_builder_core::service::run_non_permissioned_standalone_builder_service; use hotshot_events_service::{ events::{Error as EventStreamApiError, Options as EventStreamingApiOptions}, events_source::{EventConsumer, EventsStreamer}, diff --git a/builder/src/permissioned.rs b/builder/src/permissioned.rs deleted file mode 100644 index 093943dd7..000000000 --- a/builder/src/permissioned.rs +++ /dev/null @@ -1,703 +0,0 @@ -use std::{ - alloc::System, - any, - collections::VecDeque, - fmt::{Debug, Display}, - marker::PhantomData, - mem, - net::{IpAddr, Ipv4Addr}, - num::NonZeroUsize, - str::FromStr, - thread::Builder, - time::Duration, -}; - -use anyhow::Context; -use async_broadcast::{ - broadcast, Receiver as BroadcastReceiver, RecvError, Sender as BroadcastSender, TryRecvError, -}; -use async_compatibility_layer::{ - art::{async_sleep, async_spawn}, - channel::{unbounded, UnboundedReceiver, UnboundedSender}, -}; -use async_std::{ - sync::{Arc, RwLock}, - task::{spawn, JoinHandle}, -}; -use espresso_types::{ - eth_signature_key::EthKeyPair, - v0::traits::{PersistenceOptions, SequencerPersistence, StateCatchup}, - FeeAmount, L1Client, NodeState, Payload, PubKey, SeqTypes, SolverAuctionResultsProvider, - ValidatedState, -}; -use ethers::{ - core::k256::ecdsa::SigningKey, - signers::{coins_bip39::English, MnemonicBuilder, Signer as _, Wallet}, - types::{Address, U256}, -}; -use futures::{ - future::{join_all, Future}, - stream::{Stream, StreamExt}, -}; -use hotshot::{ - traits::{ - election::static_committee::StaticCommittee, - implementations::{ - derive_libp2p_multiaddr, derive_libp2p_peer_id, CdnMetricsValue, CdnTopic, - CombinedNetworks, GossipConfig, KeyPair, Libp2pNetwork, PushCdnNetwork, - WrappedSignatureKey, - }, - BlockPayload, - }, - types::{SignatureKey, SystemContextHandle}, - HotShotInitializer, MarketplaceConfig, Memberships, SystemContext, -}; -use hotshot_builder_api::v0_1::builder::{ - BuildError, Error as BuilderApiError, Options as HotshotBuilderApiOptions, -}; -use hotshot_builder_core::{ - builder_state::{BuildBlockInfo, BuilderState, MessageType, ResponseMessage}, - service::{ - run_non_permissioned_standalone_builder_service, - run_permissioned_standalone_builder_service, GlobalState, ProxyGlobalState, - ReceivedTransaction, - }, - ParentBlockReferences, -}; -use hotshot_events_service::{ - events::{Error as EventStreamApiError, Options as EventStreamingApiOptions}, - events_source::{EventConsumer, EventsStreamer}, -}; -use hotshot_example_types::auction_results_provider_types::TestAuctionResultsProvider; -use hotshot_orchestrator::{ - client::{OrchestratorClient, ValidatorArgs}, - config::NetworkConfig, -}; -// Should move `STAKE_TABLE_CAPACITY` in the sequencer repo when we have variate stake table support -use hotshot_stake_table::config::STAKE_TABLE_CAPACITY; -use hotshot_state_prover; -use hotshot_types::{ - consensus::ConsensusMetricsValue, - data::{fake_commitment, Leaf, ViewNumber}, - event::Event, - light_client::StateKeyPair, - signature_key::{BLSPrivKey, BLSPubKey}, - traits::{ - auction_results_provider::AuctionResultsProvider, - block_contents::{vid_commitment, GENESIS_VID_NUM_STORAGE_NODES}, - election::Membership, - metrics::Metrics, - network::{ConnectedNetwork, Topic}, - node_implementation::{ConsensusTime, NodeType, Versions}, - EncodeBytes, - }, - utils::BuilderCommitment, - HotShotConfig, PeerConfig, ValidatorConfig, -}; -use jf_merkle_tree::{namespaced_merkle_tree::NamespacedMerkleTreeScheme, MerkleTreeScheme}; -use jf_signature::bls_over_bn254::VerKey; -use sequencer::{ - catchup::StatePeers, - context::{Consensus, SequencerContext}, - genesis::L1Finalized, - network::{self, libp2p::split_off_peer_id}, - state_signature::{static_stake_table_commitment, StakeTableCommitmentType, StateSigner}, - Genesis, L1Params, NetworkParams, Node, SequencerApiVersion, -}; -use surf_disco::Client; -use tide_disco::{app, method::ReadState, App, Url}; -use tracing::info; -use vbs::version::StaticVersionType; - -use crate::run_builder_api_service; - -pub struct BuilderContext, P: SequencerPersistence, V: Versions> { - /// The consensus handle - pub hotshot_handle: Arc>, - - /// Index of this sequencer node - pub node_index: u64, - - /// Context for generating state signatures. - pub state_signer: Arc>, - - /// An orchestrator to wait for before starting consensus. - pub wait_for_orchestrator: Option>, - - /// global state - pub global_state: Arc>>, - - /// hotshot builder api url - pub hotshot_builder_api_url: Url, -} - -#[allow(clippy::too_many_arguments)] -pub async fn init_node( - genesis: Genesis, - network_params: NetworkParams, - metrics: &dyn Metrics, - l1_params: L1Params, - hotshot_builder_api_url: Url, - eth_key_pair: EthKeyPair, - bootstrapped_view: ViewNumber, - tx_channel_capacity: NonZeroUsize, - event_channel_capacity: NonZeroUsize, - bind_version: V, - persistence: P, - max_api_timeout_duration: Duration, - buffered_view_num_count: usize, - is_da: bool, - maximize_txns_count_timeout_duration: Duration, -) -> anyhow::Result> { - // Orchestrator client - let orchestrator_client = OrchestratorClient::new(network_params.orchestrator_url); - let state_key_pair = StateKeyPair::from_sign_key(network_params.private_state_key); - let my_config = ValidatorConfig { - public_key: BLSPubKey::from_private(&network_params.private_staking_key), - private_key: network_params.private_staking_key, - stake_value: 1, - state_key_pair, - is_da, - }; - - // Parse the Libp2p bind and advertise addresses to multiaddresses - let libp2p_bind_address = derive_libp2p_multiaddr(&network_params.libp2p_bind_address) - .with_context(|| { - format!( - "Failed to derive Libp2p bind address of {}", - &network_params.libp2p_bind_address - ) - })?; - let libp2p_advertise_address = - derive_libp2p_multiaddr(&network_params.libp2p_advertise_address).with_context(|| { - format!( - "Failed to derive Libp2p advertise address of {}", - &network_params.libp2p_advertise_address - ) - })?; - - info!("Libp2p bind address: {}", libp2p_bind_address); - info!("Libp2p advertise address: {}", libp2p_advertise_address); - - // Derive our Libp2p public key from our private key - let libp2p_public_key = - derive_libp2p_peer_id::<::SignatureKey>(&my_config.private_key) - .with_context(|| "Failed to derive Libp2p peer ID")?; - - let mut config = NetworkConfig::get_complete_config( - &orchestrator_client, - my_config.clone(), - // Register in our Libp2p advertise address and public key so other nodes - // can contact us on startup - Some(libp2p_advertise_address), - Some(libp2p_public_key), - ) - .await? - .0; - - // If the `Libp2p` bootstrap nodes were supplied via the command line, override those - // present in the config file. - if let Some(bootstrap_nodes) = network_params.libp2p_bootstrap_nodes { - if let Some(libp2p_config) = config.libp2p_config.as_mut() { - // If the libp2p configuration is present, we can override the bootstrap nodes. - - // Split off the peer ID from the addresses - libp2p_config.bootstrap_nodes = bootstrap_nodes - .into_iter() - .map(split_off_peer_id) - .collect::, _>>() - .with_context(|| "Failed to parse peer ID from bootstrap node")?; - } else { - // If not, don't try launching with them. Eventually we may want to - // provide a default configuration here instead. - tracing::warn!("No libp2p configuration found, ignoring bootstrap nodes"); - } - } - - tracing::info!( - node_id = config.node_index, - stake_table = ?config.config.known_nodes_with_stake, - "loaded config", - ); - - let node_index = config.node_index; - - // Initialize the push CDN network (and perform the initial connection) - let cdn_network = PushCdnNetwork::new( - network_params.cdn_endpoint, - vec![CdnTopic::Global, CdnTopic::Da], - KeyPair { - public_key: WrappedSignatureKey(my_config.public_key), - private_key: my_config.private_key.clone(), - }, - CdnMetricsValue::new(metrics), - ) - .with_context(|| "Failed to create CDN network")?; - - // Configure gossipsub based on the command line options - let gossip_config = GossipConfig { - heartbeat_interval: network_params.libp2p_heartbeat_interval, - history_gossip: network_params.libp2p_history_gossip, - history_length: network_params.libp2p_history_length, - mesh_n: network_params.libp2p_mesh_n, - mesh_n_high: network_params.libp2p_mesh_n_high, - mesh_n_low: network_params.libp2p_mesh_n_low, - mesh_outbound_min: network_params.libp2p_mesh_outbound_min, - max_ihave_messages: network_params.libp2p_max_ihave_messages, - max_transmit_size: network_params.libp2p_max_transmit_size, - max_ihave_length: network_params.libp2p_max_ihave_length, - published_message_ids_cache_time: network_params.libp2p_published_message_ids_cache_time, - iwant_followup_time: network_params.libp2p_iwant_followup_time, - max_messages_per_rpc: network_params.libp2p_max_messages_per_rpc, - gossip_retransmission: network_params.libp2p_gossip_retransmission, - flood_publish: network_params.libp2p_flood_publish, - duplicate_cache_time: network_params.libp2p_duplicate_cache_time, - fanout_ttl: network_params.libp2p_fanout_ttl, - heartbeat_initial_delay: network_params.libp2p_heartbeat_initial_delay, - gossip_factor: network_params.libp2p_gossip_factor, - gossip_lazy: network_params.libp2p_gossip_lazy, - }; - - // Initialize the Libp2p network (if enabled) - #[cfg(feature = "libp2p")] - let p2p_network = Libp2pNetwork::from_config::( - config.clone(), - gossip_config, - libp2p_bind_address, - &my_config.public_key, - // We need the private key so we can derive our Libp2p keypair - // (using https://docs.rs/blake3/latest/blake3/fn.derive_key.html) - &my_config.private_key, - hotshot::traits::implementations::Libp2pMetricsValue::new(metrics), - ) - .await - .with_context(|| "Failed to create libp2p network")?; - - // Combine the communication channels - #[cfg(feature = "libp2p")] - let network = Arc::new(CombinedNetworks::new( - cdn_network, - p2p_network, - Some(Duration::from_secs(1)), - )); - - #[cfg(not(feature = "libp2p"))] - let network = Arc::from(cdn_network.clone()); - - let base_fee = genesis.max_base_fee(); - let mut genesis_state = ValidatedState { - chain_config: genesis.chain_config.into(), - ..Default::default() - }; - for (address, amount) in genesis.accounts { - tracing::warn!(%address, %amount, "Prefunding account for demo"); - genesis_state.prefund_account(address, amount); - } - - let l1_client = L1Client::new(l1_params.url, l1_params.events_max_block_range); - let l1_genesis = match genesis.l1_finalized { - L1Finalized::Block(b) => b, - L1Finalized::Number { number } => l1_client.wait_for_finalized_block(number).await, - L1Finalized::Timestamp { timestamp } => { - l1_client - .wait_for_finalized_block_with_timestamp(timestamp.unix_timestamp().into()) - .await - } - }; - - let instance_state = NodeState { - chain_config: genesis.chain_config, - l1_client, - genesis_header: genesis.header, - genesis_state: genesis_state.clone(), - l1_genesis: Some(l1_genesis), - peers: Arc::new(StatePeers::::from_urls( - network_params.state_peers, - network_params.catchup_backoff, - )), - node_id: node_index, - upgrades: Default::default(), - current_version: V::Base::VERSION, - }; - - let stake_table_commit = - static_stake_table_commitment(&config.config.known_nodes_with_stake, STAKE_TABLE_CAPACITY); - - let (hotshot_handle, state_signer) = init_hotshot( - config.config, - None, - instance_state.clone(), - network, - metrics, - node_index, - Some(network_params.state_relay_server_url), - stake_table_commit, - bind_version, - persistence, - ) - .await; - - let ctx = BuilderContext::init( - Arc::new(hotshot_handle), - Arc::new(state_signer), - node_index, - eth_key_pair, - bootstrapped_view, - tx_channel_capacity, - event_channel_capacity, - instance_state, - genesis_state, - hotshot_builder_api_url, - max_api_timeout_duration, - buffered_view_num_count, - maximize_txns_count_timeout_duration, - base_fee, - ) - .await?; - - Ok(ctx) -} - -#[allow(clippy::too_many_arguments)] -pub async fn init_hotshot, P: SequencerPersistence, V: Versions>( - config: HotShotConfig, - stake_table_entries_for_non_voting_nodes: Option< - Vec>, - >, - instance_state: NodeState, - networks: Arc, - metrics: &dyn Metrics, - node_id: u64, - state_relay_server: Option, - stake_table_commit: StakeTableCommitmentType, - _: V, - persistence: P, -) -> (Consensus, StateSigner) { - let combined_known_nodes_with_stake = match stake_table_entries_for_non_voting_nodes { - Some(stake_table_entries) => { - let combined_entries = config - .known_nodes_with_stake - .iter() - .cloned() - .chain(stake_table_entries.into_iter()) - .collect(); - combined_entries - } - None => config.known_nodes_with_stake.clone(), - }; - - let quorum_membership = StaticCommittee::new( - combined_known_nodes_with_stake.clone(), - combined_known_nodes_with_stake.clone(), - Topic::Global, - ); - let da_membership = StaticCommittee::new( - combined_known_nodes_with_stake.clone(), - combined_known_nodes_with_stake, - Topic::Da, - ); - let memberships = Memberships { - quorum_membership: quorum_membership.clone(), - da_membership: da_membership.clone(), - }; - let state_key_pair = config.my_own_validator_config.state_key_pair.clone(); - - let da_storage = Arc::new(persistence); - tracing::debug!("Before hotshot handle initialisation"); - let hotshot_handle = SystemContext::init( - config.my_own_validator_config.public_key, - config.my_own_validator_config.private_key.clone(), - node_id, - config, - memberships, - networks, - HotShotInitializer::from_genesis::(instance_state) - .await - .unwrap(), - ConsensusMetricsValue::new(metrics), - da_storage, - MarketplaceConfig { - auction_results_provider: Arc::new(SolverAuctionResultsProvider::default()), - fallback_builder_url: Url::from_str("https://some.builder").unwrap(), - }, - ) - .await - .unwrap() - .0; - - tracing::debug!("Hotshot handle initialized"); - - let mut state_signer = StateSigner::new(state_key_pair, stake_table_commit); - - if let Some(url) = state_relay_server { - state_signer = state_signer.with_relay_server(url); - } - (hotshot_handle, state_signer) -} - -impl, P: SequencerPersistence, V: Versions> BuilderContext { - /// Constructor - #[allow(clippy::too_many_arguments)] - pub async fn init( - hotshot_handle: Arc>, - state_signer: Arc>, - node_index: u64, - eth_key_pair: EthKeyPair, - bootstrapped_view: ViewNumber, - tx_channel_capacity: NonZeroUsize, - event_channel_capacity: NonZeroUsize, - instance_state: NodeState, - validated_state: ValidatedState, - hotshot_builder_api_url: Url, - max_api_timeout_duration: Duration, - buffered_view_num_count: usize, - maximize_txns_count_timeout_duration: Duration, - base_fee: FeeAmount, - ) -> anyhow::Result { - // tx channel - let (mut tx_sender, tx_receiver) = - broadcast::>>(tx_channel_capacity.get()); - tx_sender.set_overflow(true); - - // da channel - let (da_sender, da_receiver) = - broadcast::>(event_channel_capacity.get()); - - // qc channel - let (qc_sender, qc_receiver) = - broadcast::>(event_channel_capacity.get()); - - // decide channel - let (decide_sender, decide_receiver) = - broadcast::>(event_channel_capacity.get()); - - // builder api request channel - let (req_sender, req_receiver) = - broadcast::>(event_channel_capacity.get()); - - let (genesis_payload, genesis_ns_table) = - Payload::from_transactions([], &validated_state, &instance_state) - .await - .expect("genesis payload construction failed"); - - let builder_commitment = genesis_payload.builder_commitment(&genesis_ns_table); - - let vid_commitment = { - // TODO we should not need to collect payload bytes just to compute vid_commitment - let payload_bytes = genesis_payload.encode(); - vid_commitment(&payload_bytes, GENESIS_VID_NUM_STORAGE_NODES) - }; - - // create the global state - let global_state: GlobalState = GlobalState::::new( - req_sender, - tx_sender.clone(), - vid_commitment, - bootstrapped_view, - bootstrapped_view, - buffered_view_num_count as u64, - ); - - let global_state = Arc::new(RwLock::new(global_state)); - - let global_state_clone = global_state.clone(); - - let builder_state = BuilderState::::new( - ParentBlockReferences { - view_number: bootstrapped_view, - vid_commitment, - leaf_commit: fake_commitment(), - builder_commitment, - }, - decide_receiver, - da_receiver, - qc_receiver, - req_receiver, - tx_receiver, - VecDeque::new() /* tx_queue */, - global_state_clone, - NonZeroUsize::new(1).unwrap(), - maximize_txns_count_timeout_duration, - base_fee - .as_u64() - .context("the base fee exceeds the maximum amount that a builder can pay (defined by u64::MAX)")?, - Arc::new(instance_state), - Duration::from_secs(60), - Arc::new(validated_state), - ); - - let hotshot_handle_clone = Arc::clone(&hotshot_handle); - let global_state_clone = global_state.clone(); - // spawn the builder service - async_spawn(async move { - run_permissioned_standalone_builder_service( - da_sender, - qc_sender, - decide_sender, - hotshot_handle_clone, - global_state_clone, - ) - .await; - }); - - // spawn the builder event loop - async_spawn(async move { - builder_state.event_loop(); - }); - - // create the proxy global state it will server the builder apis - let proxy_global_state = ProxyGlobalState::new( - global_state.clone(), - (eth_key_pair.fee_account(), eth_key_pair), - max_api_timeout_duration, - ); - - // start the builder api service - run_builder_api_service(hotshot_builder_api_url.clone(), proxy_global_state); - - let ctx = Self { - hotshot_handle: Arc::clone(&hotshot_handle), - node_index, - state_signer, - wait_for_orchestrator: None, - global_state, - hotshot_builder_api_url, - }; - - Ok(ctx) - } - - /// Start participating in consensus. - pub async fn start_consensus(&self) { - if let Some(orchestrator_client) = &self.wait_for_orchestrator { - tracing::info!("waiting for orchestrated start"); - let peer_config = PeerConfig::to_bytes( - &self - .hotshot_handle - .hotshot - .config - .my_own_validator_config - .public_config(), - ) - .clone(); - orchestrator_client - .wait_for_all_nodes_ready(peer_config) - .await; - } - self.hotshot_handle.hotshot.start_consensus().await; - } -} - -#[cfg(test)] -mod test { - use std::time::Duration; - - use async_compatibility_layer::art::{async_sleep, async_spawn}; - use async_lock::RwLock; - use async_std::task; - - use espresso_types::{FeeAccount, MockSequencerVersions, NamespaceId, Transaction}; - use hotshot_builder_api::v0_1::{ - block_info::{AvailableBlockData, AvailableBlockHeaderInput, AvailableBlockInfo}, - builder::BuildError, - }; - use hotshot_builder_core::service::{ - run_non_permissioned_standalone_builder_service, - run_permissioned_standalone_builder_service, - }; - use hotshot_events_service::{ - events::{Error as EventStreamApiError, Options as EventStreamingApiOptions}, - events_source::{EventConsumer, EventsStreamer}, - }; - use hotshot_types::{ - signature_key::BLSPubKey, - traits::{ - block_contents::{BlockPayload, GENESIS_VID_NUM_STORAGE_NODES}, - node_implementation::NodeType, - signature_key::SignatureKey, - }, - }; - use portpicker::pick_unused_port; - use sequencer::{ - api::{ - options::HotshotEvents, - test_helpers::{TestNetwork, TestNetworkConfigBuilder}, - Options, - }, - persistence::{ - self, - no_storage::{self, NoStorage}, - }, - testing::TestConfigBuilder, - }; - use sequencer_utils::test_utils::setup_test; - use surf_disco::Client; - use tempfile::TempDir; - use vbs::version::StaticVersion; - - use super::*; - use crate::{ - non_permissioned, - testing::{ - hotshot_builder_url, test_builder_impl, HotShotTestConfig, - NonPermissionedBuilderTestConfig, PermissionedBuilderTestConfig, - }, - }; - - // TODO: Re-enable when permissioned builder accepts Arc> instead of Arc - // #[async_std::test] - // async fn test_permissioned_builder() { - // setup_test(); - - // Hotshot Test Config - // let hotshot_config = HotShotTestConfig::default(); - - // // Get the handle for all the nodes, including both the non-builder and builder nodes - // let mut handles = hotshot_config - // .init_nodes(MockSequencerVersions::new(), no_storage::Options) - // .await; - - // // Set up and start the network - // let anvil = Anvil::new().spawn(); - // let l1 = anvil.endpoint().parse().unwrap(); - // let network_config = TestConfigBuilder::default().l1_url(l1).build(); - - // let tmpdir = TempDir::new().unwrap(); - - // let config = TestNetworkConfigBuilder::default() - // .api_config( - // Options::with_port(query_port) - // .submit(Default::default()) - // .query_fs( - // Default::default(), - // persistence::fs::Options::new(tmpdir.path().to_owned()), - // ) - // .hotshot_events(HotshotEvents { - // events_service_port: event_port, - // }), - // ) - // .network_config(network_config) - // .build(); - // let network = TestNetwork::new(config, BaseVersion::instance()).await; - // let consensus_handle = network.peers[0].consensus(); - // let node_id = network.peers[0].config().node_index; - // let state_signer = network.peers[0].state_signer(); - - // let builder_config = PermissionedBuilderTestConfig::init_permissioned_builder( - // consensus_handle, - // node_id, - // state_signer, - // builder_api_url.clone(), - // ) - // .await; - - // let subscribed_events = consensus_handle.event_stream(); - - // test_builder_impl( - // builder_api_url, - // subscribed_events, - // builder_config.fee_account, - // ) - // .await; - // } -} diff --git a/marketplace-builder/Cargo.toml b/marketplace-builder/Cargo.toml index 9fd7f193c..27a8e40bf 100644 --- a/marketplace-builder/Cargo.toml +++ b/marketplace-builder/Cargo.toml @@ -32,6 +32,7 @@ hotshot-types = { workspace = true } jf-merkle-tree = { workspace = true } jf-signature = { workspace = true, features = ["bls"] } marketplace-builder-core = { workspace = true } +marketplace-builder-shared = { workspace = true } marketplace-solver = { path = "../marketplace-solver", features = ["testing"] } portpicker = { workspace = true } sequencer = { path = "../sequencer", features = ["testing"] } diff --git a/marketplace-builder/src/bin/marketplace-builder.rs b/marketplace-builder/src/bin/marketplace-builder.rs index a049521c4..da9455745 100644 --- a/marketplace-builder/src/bin/marketplace-builder.rs +++ b/marketplace-builder/src/bin/marketplace-builder.rs @@ -81,14 +81,6 @@ struct NonPermissionedBuilderOptions { )] max_api_timeout_duration: Duration, - /// The number of views to buffer before a builder garbage collects its state - #[clap( - long, - env = "ESPRESSO_BUILDER_BUFFER_VIEW_NUM_COUNT", - default_value = "15" - )] - buffer_view_num_count: usize, - /// Path to TOML file containing genesis state. #[clap(long, name = "GENESIS_FILE", env = "ESPRESSO_BUILDER_GENESIS_FILE")] genesis_file: PathBuf, @@ -185,20 +177,17 @@ async fn run( // make the txn timeout as 1/4 of the api_response_timeout_duration let txn_timeout_duration = api_response_timeout_duration / 4; - let buffer_view_num_count = opt.buffer_view_num_count; - let _builder_config = BuilderConfig::init( is_reserve, builder_key_pair, bootstrapped_view, opt.tx_channel_capacity, opt.event_channel_capacity, - instance_state, + instance_state.clone(), validated_state, opt.hotshot_event_streaming_url, builder_server_url, api_response_timeout_duration, - buffer_view_num_count, txn_timeout_duration, base_fee, bid_config, diff --git a/marketplace-builder/src/builder.rs b/marketplace-builder/src/builder.rs index d200f6947..60741b096 100644 --- a/marketplace-builder/src/builder.rs +++ b/marketplace-builder/src/builder.rs @@ -38,14 +38,15 @@ use hotshot_types::{ }, utils::BuilderCommitment, }; +use marketplace_builder_core::service::EventServiceStream; use marketplace_builder_core::{ builder_state::{BuildBlockInfo, BuilderState, MessageType, ResponseMessage}, service::{ run_builder_service, BroadcastSenders, BuilderHooks, GlobalState, ProxyGlobalState, ReceivedTransaction, }, - utils::ParentBlockReferences, }; +use marketplace_builder_shared::block::ParentBlockReferences; use marketplace_solver::SolverError; use sequencer::{catchup::StatePeers, L1Params, NetworkParams, SequencerApiVersion}; use surf::http::headers::ACCEPT; @@ -118,14 +119,14 @@ impl BuilderConfig { // spawn the builder service tracing::info!("Running builder against hotshot events API at {events_api_url}",); - let stream = marketplace_builder_core::utils::EventServiceStream::< + let stream = marketplace_builder_core::service::EventServiceStream::< SeqTypes, SequencerApiVersion, >::connect(events_api_url) .await?; async_spawn(async move { - let res = run_builder_service::(hooks, senders, stream).await; + let res = run_builder_service::(hooks, senders, stream).await; tracing::error!(?res, "Builder service exited"); if res.is_err() { panic!("Builder should restart."); @@ -147,7 +148,6 @@ impl BuilderConfig { events_api_url: Url, builder_api_url: Url, api_timeout: Duration, - buffered_view_num_count: usize, maximize_txns_count_timeout_duration: Duration, base_fee: FeeAmount, bid_config: Option, @@ -159,7 +159,7 @@ impl BuilderConfig { %tx_channel_capacity, %event_channel_capacity, ?api_timeout, - buffered_view_num_count, + ?instance_state.chain_config.max_block_size, ?maximize_txns_count_timeout_duration, "initializing builder", ); @@ -243,7 +243,7 @@ impl BuilderConfig { let namespaces_to_skip = fetch_namespaces_to_skip(solver_base_url.clone()).await; let hooks = Arc::new(hooks::EspressoFallbackHooks { solver_base_url, - namespaces_to_skip: RwLock::new(namespaces_to_skip), + namespaces_to_skip: RwLock::new(namespaces_to_skip).into(), }); Self::start_service( Arc::clone(&global_state), @@ -317,8 +317,8 @@ mod test { use marketplace_builder_core::{ builder_state::{self, RequestMessage, TransactionSource}, service::run_builder_service, - utils::BuilderStateId, }; + use marketplace_builder_shared::block::BuilderStateId; use marketplace_solver::{testing::MockSolver, SolverError}; use portpicker::pick_unused_port; use sequencer::{ @@ -636,7 +636,6 @@ mod test { urls.event.clone(), urls.builder.clone(), Duration::from_secs(2), - 5, Duration::from_secs(2), base_fee, Some(BidConfig { @@ -768,7 +767,6 @@ mod test { urls.event.clone(), urls.builder.clone(), Duration::from_secs(2), - 5, Duration::from_secs(2), base_fee, None, diff --git a/marketplace-builder/src/hooks.rs b/marketplace-builder/src/hooks.rs index 03b5c74fd..bdd9fd8fe 100644 --- a/marketplace-builder/src/hooks.rs +++ b/marketplace-builder/src/hooks.rs @@ -95,7 +95,7 @@ pub(crate) struct EspressoReserveHooks { impl BuilderHooks for EspressoReserveHooks { #[inline(always)] async fn process_transactions( - self: &Arc, + &self, mut transactions: Vec<::Transaction>, ) -> Vec<::Transaction> { transactions.retain(|txn| self.namespaces.contains(&txn.namespace())); @@ -103,22 +103,28 @@ impl BuilderHooks for EspressoReserveHooks { } #[inline(always)] - async fn handle_hotshot_event(self: &Arc, event: &Event) { + async fn handle_hotshot_event(&self, event: &Event) { let EventType::ViewFinished { view_number } = event.event else { return; }; - let self = Arc::clone(self); + let fee_account = self.bid_key_pair.fee_account(); + let bid_amount = self.bid_amount; + let namespaces = self.namespaces.iter().cloned().collect(); + let builder_api_base_url = self.builder_api_base_url.clone(); + let bid_key_pair = self.bid_key_pair.clone(); + let solver_base_url = self.solver_base_url.clone(); + async_spawn(async move { let bid_tx = match BidTxBody::new( - self.bid_key_pair.fee_account(), - self.bid_amount, + fee_account, + bid_amount, view_number + 3, // We submit a bid 3 views in advance. - self.namespaces.iter().cloned().collect(), - self.builder_api_base_url.clone(), + namespaces, + builder_api_base_url, Default::default(), ) - .signed(&self.bid_key_pair) + .signed(&bid_key_pair) { Ok(bid) => bid, Err(e) => { @@ -127,7 +133,7 @@ impl BuilderHooks for EspressoReserveHooks { } }; - let solver_client = connect_to_solver(self.solver_base_url.clone()); + let solver_client = connect_to_solver(solver_base_url); if let Err(e) = solver_client .post::<()>("submit_bid") .body_json(&bid_tx) @@ -150,14 +156,14 @@ impl BuilderHooks for EspressoReserveHooks { pub(crate) struct EspressoFallbackHooks { /// Base URL to contact the solver. pub(crate) solver_base_url: Url, - pub(crate) namespaces_to_skip: RwLock>>, + pub(crate) namespaces_to_skip: Arc>>>, } #[async_trait] impl BuilderHooks for EspressoFallbackHooks { #[inline(always)] async fn process_transactions( - self: &Arc, + &self, mut transactions: Vec<::Transaction>, ) -> Vec<::Transaction> { let namespaces_to_skip = self.namespaces_to_skip.read().await; @@ -176,7 +182,7 @@ impl BuilderHooks for EspressoFallbackHooks { } #[inline(always)] - async fn handle_hotshot_event(self: &Arc, event: &Event) { + async fn handle_hotshot_event(&self, event: &Event) { let EventType::ViewFinished { view_number } = event.event else { return; }; @@ -186,10 +192,12 @@ impl BuilderHooks for EspressoFallbackHooks { return; } - let self = Arc::clone(self); + let solver_base_url = self.solver_base_url.clone(); + let namespaces_to_skip_lock = Arc::clone(&self.namespaces_to_skip); + async_spawn(async move { - let namespaces_to_skip = fetch_namespaces_to_skip(self.solver_base_url.clone()).await; - *self.namespaces_to_skip.write().await = namespaces_to_skip; + let namespaces_to_skip = fetch_namespaces_to_skip(solver_base_url).await; + *namespaces_to_skip_lock.write().await = namespaces_to_skip; }); } } diff --git a/marketplace-builder/src/lib.rs b/marketplace-builder/src/lib.rs index 7a2336d19..90a18752c 100755 --- a/marketplace-builder/src/lib.rs +++ b/marketplace-builder/src/lib.rs @@ -38,10 +38,8 @@ use hotshot::{ use hotshot_builder_api::v0_3::builder::{ BuildError, Error as BuilderApiError, Options as HotshotBuilderApiOptions, }; -use hotshot_orchestrator::{ - client::{OrchestratorClient, ValidatorArgs}, - config::NetworkConfig, -}; +use hotshot_orchestrator::client::{OrchestratorClient, ValidatorArgs}; +use hotshot_types::network::NetworkConfig; use marketplace_builder_core::service::{BuilderHooks, GlobalState, ProxyGlobalState}; // Should move `STAKE_TABLE_CAPACITY` in the sequencer repo when we have variate stake table support use hotshot_stake_table::config::STAKE_TABLE_CAPACITY; diff --git a/node-metrics/src/api/node_validator/v0/cdn/mod.rs b/node-metrics/src/api/node_validator/v0/cdn/mod.rs index 599136480..f85be3210 100644 --- a/node-metrics/src/api/node_validator/v0/cdn/mod.rs +++ b/node-metrics/src/api/node_validator/v0/cdn/mod.rs @@ -315,7 +315,7 @@ mod test { match result { Ok(messages) => Ok(messages.clone()), Err(err) => match err { - NetworkError::ChannelSend => Err(NetworkError::ChannelSend), + NetworkError::ChannelSendError(e) => Err(NetworkError::ChannelSendError(e.clone())), _ => panic!("unexpected network error"), }, } @@ -379,7 +379,7 @@ mod test { async fn test_cdn_receive_messages_task_fails_receiving_message() { let (url_sender, url_receiver) = mpsc::channel(1); let task = CdnReceiveMessagesTask::new( - TestConnectedNetworkConsumer(Err(NetworkError::ChannelSend)), + TestConnectedNetworkConsumer(Err(NetworkError::ChannelSendError("".to_string()))), url_sender, ); @@ -530,7 +530,7 @@ mod test { ) -> Result<(), NetworkError> { let mut sender = self.0.clone(); let send_result = sender.send(message).await; - send_result.map_err(|_| NetworkError::ChannelSend) + send_result.map_err(|_| NetworkError::ChannelSendError("".to_string())) } } diff --git a/node-metrics/src/api/node_validator/v0/create_node_validator_api.rs b/node-metrics/src/api/node_validator/v0/create_node_validator_api.rs index 08c9271ff..a6e0ae75b 100644 --- a/node-metrics/src/api/node_validator/v0/create_node_validator_api.rs +++ b/node-metrics/src/api/node_validator/v0/create_node_validator_api.rs @@ -136,8 +136,8 @@ impl HotShotEventProcessingTask { } } - EventType::ExternalMessageReceived(external_message_bytes) => { - let roll_call_info = match bincode::deserialize(&external_message_bytes) { + EventType::ExternalMessageReceived { data, .. } => { + let roll_call_info = match bincode::deserialize(&data) { Ok(ExternalMessage::RollCallResponse(roll_call_info)) => roll_call_info, Err(err) => { diff --git a/sequencer/Cargo.toml b/sequencer/Cargo.toml index 566b6ef98..3f39749b4 100644 --- a/sequencer/Cargo.toml +++ b/sequencer/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [features] default = ["libp2p"] -testing = ["hotshot-testing", "marketplace-builder-core", "hotshot-builder-api"] +testing = ["hotshot-testing", "marketplace-builder-core", "marketplace-builder-shared", "hotshot-builder-api"] libp2p = [] benchmarking = [] @@ -71,6 +71,7 @@ libp2p-networking = { workspace = true } # Dependencies for feature `testing` hotshot-testing = { workspace = true, optional = true } marketplace-builder-core = { workspace = true, optional = true } +marketplace-builder-shared = { workspace = true, optional = true } hotshot-types = { workspace = true } include_dir = "0.7" diff --git a/sequencer/src/api.rs b/sequencer/src/api.rs index 386daf650..3ed59729c 100644 --- a/sequencer/src/api.rs +++ b/sequencer/src/api.rs @@ -19,13 +19,13 @@ use futures::{ use hotshot_events_service::events_source::{ EventFilterSet, EventsSource, EventsStreamer, StartupInfo, }; -use hotshot_orchestrator::config::NetworkConfig; use hotshot_query_service::data_source::ExtensibleDataSource; use hotshot_state_prover::service::light_client_genesis_from_stake_table; use hotshot_types::{ data::ViewNumber, event::Event, light_client::StateSignatureRequestBody, + network::NetworkConfig, traits::{network::ConnectedNetwork, node_implementation::Versions}, }; use jf_merkle_tree::MerkleTreeScheme; diff --git a/sequencer/src/api/data_source.rs b/sequencer/src/api/data_source.rs index bf73cdcc4..507b0b6f6 100644 --- a/sequencer/src/api/data_source.rs +++ b/sequencer/src/api/data_source.rs @@ -10,9 +10,6 @@ use espresso_types::{ }; use ethers::prelude::Address; use futures::future::Future; -use hotshot_orchestrator::config::{ - BuilderType, CombinedNetworkConfig, Libp2pConfig, NetworkConfig, RandomBuilderConfig, -}; use hotshot_query_service::{ availability::AvailabilityDataSource, data_source::{MetricsDataSource, VersionedDataSource}, @@ -20,9 +17,13 @@ use hotshot_query_service::{ node::NodeDataSource, status::StatusDataSource, }; +use hotshot_types::network::{ + BuilderType, CombinedNetworkConfig, Libp2pConfig, RandomBuilderConfig, +}; use hotshot_types::{ data::ViewNumber, light_client::StateSignatureRequestBody, + network::NetworkConfig, traits::{network::ConnectedNetwork, node_implementation::Versions}, ExecutionType, HotShotConfig, PeerConfig, ValidatorConfig, }; @@ -230,6 +231,7 @@ pub struct PublicHotShotConfig { stop_proposing_time: u64, start_voting_time: u64, stop_voting_time: u64, + epoch_height: u64, } impl From> for PublicHotShotConfig { @@ -264,6 +266,7 @@ impl From> for PublicHotShotConfig { stop_proposing_time, start_voting_time, stop_voting_time, + epoch_height, } = v; Self { @@ -293,6 +296,7 @@ impl From> for PublicHotShotConfig { stop_proposing_time, start_voting_time, stop_voting_time, + epoch_height, } } } @@ -329,6 +333,7 @@ impl PublicHotShotConfig { stop_proposing_time: self.stop_proposing_time, start_voting_time: self.start_voting_time, stop_voting_time: self.stop_voting_time, + epoch_height: self.epoch_height, } } } diff --git a/sequencer/src/bin/cdn-whitelist.rs b/sequencer/src/bin/cdn-whitelist.rs index ec6ff63d2..9ef8b449c 100644 --- a/sequencer/src/bin/cdn-whitelist.rs +++ b/sequencer/src/bin/cdn-whitelist.rs @@ -8,7 +8,8 @@ use anyhow::{Context, Result}; use cdn_broker::reexports::discovery::{DiscoveryClient, Embedded, Redis}; use clap::Parser; use espresso_types::SeqTypes; -use hotshot_orchestrator::{client::OrchestratorClient, config::NetworkConfig}; +use hotshot_orchestrator::client::OrchestratorClient; +use hotshot_types::network::NetworkConfig; use hotshot_types::traits::{node_implementation::NodeType, signature_key::SignatureKey}; use surf_disco::Url; diff --git a/sequencer/src/bin/orchestrator.rs b/sequencer/src/bin/orchestrator.rs index 0b94ee7ba..aebe45bab 100644 --- a/sequencer/src/bin/orchestrator.rs +++ b/sequencer/src/bin/orchestrator.rs @@ -4,10 +4,8 @@ use clap::Parser; use derive_more::From; use espresso_types::{parse_duration, PubKey, Ratio}; use ethers::utils::hex::{self, FromHexError}; -use hotshot_orchestrator::{ - config::{Libp2pConfig, NetworkConfig}, - run_orchestrator, -}; +use hotshot_orchestrator::run_orchestrator; +use hotshot_types::network::{Libp2pConfig, NetworkConfig}; use sequencer_utils::logging; use snafu::Snafu; use url::Url; diff --git a/sequencer/src/catchup.rs b/sequencer/src/catchup.rs index e4ee1f84a..4cdb8ac2f 100644 --- a/sequencer/src/catchup.rs +++ b/sequencer/src/catchup.rs @@ -10,7 +10,7 @@ use espresso_types::{ AccountQueryData, BackoffParams, BlockMerkleTree, FeeAccount, FeeMerkleCommitment, }; use futures::future::FutureExt; -use hotshot_orchestrator::config::NetworkConfig; +use hotshot_types::network::NetworkConfig; use hotshot_types::{ data::ViewNumber, traits::node_implementation::ConsensusTime as _, ValidatorConfig, }; diff --git a/sequencer/src/context.rs b/sequencer/src/context.rs index ed4fc55e3..992005e54 100644 --- a/sequencer/src/context.rs +++ b/sequencer/src/context.rs @@ -21,11 +21,12 @@ use hotshot::{ }; use hotshot_events_service::events_source::{EventConsumer, EventsStreamer}; -use hotshot_orchestrator::{client::OrchestratorClient, config::NetworkConfig}; +use hotshot_orchestrator::client::OrchestratorClient; use hotshot_query_service::Leaf; use hotshot_types::{ consensus::ConsensusMetricsValue, data::ViewNumber, + network::NetworkConfig, traits::{ election::Membership, metrics::Metrics, @@ -382,11 +383,8 @@ async fn handle_events( state_signer.handle_event(&event).await; // Handle external messages - if let EventType::ExternalMessageReceived(external_message_bytes) = &event.event { - if let Err(err) = external_event_handler - .handle_event(external_message_bytes) - .await - { + if let EventType::ExternalMessageReceived { data, .. } = &event.event { + if let Err(err) = external_event_handler.handle_event(data).await { tracing::warn!("Failed to handle external message: {:?}", err); }; } diff --git a/sequencer/src/lib.rs b/sequencer/src/lib.rs index 5de0772c9..cc8eeca0f 100644 --- a/sequencer/src/lib.rs +++ b/sequencer/src/lib.rs @@ -51,10 +51,12 @@ use hotshot::{ types::SignatureKey, MarketplaceConfig, }; -use hotshot_orchestrator::{client::OrchestratorClient, config::NetworkConfig}; +use hotshot_orchestrator::client::get_complete_config; +use hotshot_orchestrator::client::OrchestratorClient; use hotshot_types::{ data::ViewNumber, light_client::{StateKeyPair, StateSignKey}, + network::NetworkConfig, signature_key::{BLSPrivKey, BLSPubKey}, traits::{ metrics::Metrics, @@ -121,62 +123,6 @@ pub struct NetworkParams { /// The (optional) bootstrap node addresses for Libp2p. If supplied, these will /// override the bootstrap nodes specified in the config file. pub libp2p_bootstrap_nodes: Option>, - - /// The heartbeat interval - pub libp2p_heartbeat_interval: Duration, - - /// The number of past heartbeats to gossip about - pub libp2p_history_gossip: usize, - /// The number of past heartbeats to remember the full messages for - pub libp2p_history_length: usize, - - /// The target number of peers in the mesh - pub libp2p_mesh_n: usize, - /// The maximum number of peers in the mesh - pub libp2p_mesh_n_high: usize, - /// The minimum number of peers in the mesh - pub libp2p_mesh_n_low: usize, - /// The minimum number of mesh peers that must be outbound - pub libp2p_mesh_outbound_min: usize, - - /// The maximum gossip message size - pub libp2p_max_transmit_size: usize, - - /// The maximum number of IHAVE messages to accept from a Libp2p peer within a heartbeat - pub libp2p_max_ihave_length: usize, - - /// The maximum number of IHAVE messages to accept from a Libp2p peer within a heartbeat - pub libp2p_max_ihave_messages: usize, - - /// The time period that message hashes are stored in the cache - pub libp2p_published_message_ids_cache_time: Duration, - - /// The time to wait for a Libp2p message requested through IWANT following an IHAVE advertisement - pub libp2p_iwant_followup_time: Duration, - - /// The maximum number of Libp2p messages we will process in a given RPC - pub libp2p_max_messages_per_rpc: Option, - - /// How many times we will allow a peer to request the same message id through IWANT gossip before we start ignoring them - pub libp2p_gossip_retransmission: u32, - - /// If enabled newly created messages will always be sent to all peers that are subscribed to the topic and have a good enough score - pub libp2p_flood_publish: bool, - - /// The time period that Libp2p message hashes are stored in the cache - pub libp2p_duplicate_cache_time: Duration, - - /// Time to live for Libp2p fanout peers - pub libp2p_fanout_ttl: Duration, - - /// Initial delay in each Libp2p heartbeat - pub libp2p_heartbeat_initial_delay: Duration, - - /// How many Libp2p peers we will emit gossip to at each heartbeat - pub libp2p_gossip_factor: f64, - - /// Minimum number of Libp2p peers to emit gossip to during a heartbeat - pub libp2p_gossip_lazy: usize, } pub struct L1Params { @@ -323,7 +269,7 @@ pub async fn init_node( tracing::error!( "waiting for other nodes to connect, DO NOT RESTART until fully connected" ); - let config = NetworkConfig::get_complete_config( + let config = get_complete_config( &orchestrator_client, my_config.clone(), // Register in our Libp2p advertise address and public key so other nodes @@ -391,36 +337,12 @@ pub async fn init_node( ) .with_context(|| format!("Failed to create CDN network {node_index}"))?; - // Configure gossipsub based on the command line options - let gossip_config = GossipConfig { - heartbeat_interval: network_params.libp2p_heartbeat_interval, - history_gossip: network_params.libp2p_history_gossip, - history_length: network_params.libp2p_history_length, - mesh_n: network_params.libp2p_mesh_n, - mesh_n_high: network_params.libp2p_mesh_n_high, - mesh_n_low: network_params.libp2p_mesh_n_low, - mesh_outbound_min: network_params.libp2p_mesh_outbound_min, - max_ihave_messages: network_params.libp2p_max_ihave_messages, - max_transmit_size: network_params.libp2p_max_transmit_size, - max_ihave_length: network_params.libp2p_max_ihave_length, - published_message_ids_cache_time: network_params.libp2p_published_message_ids_cache_time, - iwant_followup_time: network_params.libp2p_iwant_followup_time, - max_messages_per_rpc: network_params.libp2p_max_messages_per_rpc, - gossip_retransmission: network_params.libp2p_gossip_retransmission, - flood_publish: network_params.libp2p_flood_publish, - duplicate_cache_time: network_params.libp2p_duplicate_cache_time, - fanout_ttl: network_params.libp2p_fanout_ttl, - heartbeat_initial_delay: network_params.libp2p_heartbeat_initial_delay, - gossip_factor: network_params.libp2p_gossip_factor, - gossip_lazy: network_params.libp2p_gossip_lazy, - }; - // Initialize the Libp2p network (if enabled) #[cfg(feature = "libp2p")] let network = { - let p2p_network = Libp2pNetwork::from_config::( + let p2p_network = Libp2pNetwork::from_config( config.clone(), - gossip_config, + GossipConfig::default(), libp2p_bind_address, &my_config.public_key, // We need the private key so we can derive our Libp2p keypair @@ -567,8 +489,8 @@ pub mod testing { use marketplace_builder_core::{ builder_state::BuilderState, service::{run_builder_service, BroadcastSenders, GlobalState, NoHooks, ProxyGlobalState}, - utils::ParentBlockReferences, }; + use marketplace_builder_shared::block::ParentBlockReferences; use portpicker::pick_unused_port; use vbs::version::Version; @@ -594,7 +516,8 @@ pub mod testing { >, ) { async_spawn(async move { - let res = run_builder_service::(self.hooks, self.senders, stream).await; + let res = + run_builder_service::(self.hooks, self.senders, stream).await; tracing::error!(?res, "Testing marketplace builder service exited"); }); } @@ -828,6 +751,7 @@ pub mod testing { start_voting_time: 0, stop_proposing_time: 0, stop_voting_time: 0, + epoch_height: 0, }; Self { diff --git a/sequencer/src/main.rs b/sequencer/src/main.rs index 2678afec6..c95b2c205 100644 --- a/sequencer/src/main.rs +++ b/sequencer/src/main.rs @@ -166,26 +166,6 @@ where state_peers: opt.state_peers, config_peers: opt.config_peers, catchup_backoff: opt.catchup_backoff, - libp2p_history_gossip: opt.libp2p_history_gossip, - libp2p_history_length: opt.libp2p_history_length, - libp2p_max_ihave_length: opt.libp2p_max_ihave_length, - libp2p_max_ihave_messages: opt.libp2p_max_ihave_messages, - libp2p_max_transmit_size: opt.libp2p_max_transmit_size, - libp2p_mesh_n: opt.libp2p_mesh_n, - libp2p_mesh_n_high: opt.libp2p_mesh_n_high, - libp2p_heartbeat_interval: opt.libp2p_heartbeat_interval, - libp2p_mesh_n_low: opt.libp2p_mesh_n_low, - libp2p_mesh_outbound_min: opt.libp2p_mesh_outbound_min, - libp2p_published_message_ids_cache_time: opt.libp2p_published_message_ids_cache_time, - libp2p_iwant_followup_time: opt.libp2p_iwant_followup_time, - libp2p_max_messages_per_rpc: opt.libp2p_max_messages_per_rpc, - libp2p_gossip_retransmission: opt.libp2p_gossip_retransmission, - libp2p_flood_publish: opt.libp2p_flood_publish, - libp2p_duplicate_cache_time: opt.libp2p_duplicate_cache_time, - libp2p_fanout_ttl: opt.libp2p_fanout_ttl, - libp2p_heartbeat_initial_delay: opt.libp2p_heartbeat_initial_delay, - libp2p_gossip_factor: opt.libp2p_gossip_factor, - libp2p_gossip_lazy: opt.libp2p_gossip_lazy, }; let marketplace_config = MarketplaceConfig { diff --git a/sequencer/src/message_compat_tests.rs b/sequencer/src/message_compat_tests.rs index c0323486b..5acb8b5b1 100755 --- a/sequencer/src/message_compat_tests.rs +++ b/sequencer/src/message_compat_tests.rs @@ -21,7 +21,7 @@ use espresso_types::{Leaf, NodeState, PubKey, ValidatedState}; use hotshot::traits::election::static_committee::StaticCommittee; use hotshot_types::{ data::{ - DaProposal, QuorumProposal, UpgradeProposal, VidDisperse, VidDisperseShare, + DaProposal, EpochNumber, QuorumProposal, UpgradeProposal, VidDisperse, VidDisperseShare, ViewChangeEvidence, ViewNumber, }, message::{ @@ -222,6 +222,7 @@ async fn test_message_compat(_ver: Ver) { ViewNumber::genesis(), vid_scheme(1).disperse(payload.encode()).unwrap(), &membership, + EpochNumber::genesis(), )) .remove(0), signature: signature.clone(), diff --git a/sequencer/src/options.rs b/sequencer/src/options.rs index 14e93e5c5..2b4a5a020 100644 --- a/sequencer/src/options.rs +++ b/sequencer/src/options.rs @@ -6,13 +6,12 @@ use std::{ fmt::{self, Formatter}, iter::once, path::PathBuf, - time::Duration, }; use anyhow::{bail, Context}; use clap::{error::ErrorKind, Args, FromArgMatches, Parser}; use derivative::Derivative; -use espresso_types::{parse_duration, BackoffParams}; +use espresso_types::BackoffParams; use hotshot_types::{light_client::StateSignKey, signature_key::BLSPrivKey}; use libp2p::Multiaddr; use url::Url; @@ -70,138 +69,6 @@ pub struct Options { )] pub libp2p_bind_address: String, - /// Time between each Libp2p heartbeat - #[clap(long, env = "ESPRESSO_SEQUENCER_LIBP2P_HEARTBEAT_INTERVAL", default_value = "1s", value_parser = parse_duration)] - pub libp2p_heartbeat_interval: Duration, - - /// Number of past heartbeats to gossip about on Libp2p - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_HISTORY_GOSSIP", - default_value = "3" - )] - pub libp2p_history_gossip: usize, - - /// Number of heartbeats to keep in the Libp2p `memcache` - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_HISTORY_LENGTH", - default_value = "5" - )] - pub libp2p_history_length: usize, - - /// Target number of peers for the Libp2p mesh network - #[clap(long, env = "ESPRESSO_SEQUENCER_LIBP2P_MESH_N", default_value = "8")] - pub libp2p_mesh_n: usize, - - /// Maximum number of peers in the Libp2p mesh network before removing some - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_MESH_N_HIGH", - default_value = "12" - )] - pub libp2p_mesh_n_high: usize, - - /// Minimum number of peers in the Libp2p mesh network before adding more - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_MESH_N_LOW", - default_value = "6" - )] - pub libp2p_mesh_n_low: usize, - - /// Minimum number of outbound Libp2p peers in the mesh network before adding more - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_MESH_OUTBOUND_MIN", - default_value = "2" - )] - pub libp2p_mesh_outbound_min: usize, - - /// The maximum number of messages to include in a Libp2p IHAVE message - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_MAX_IHAVE_LENGTH", - default_value = "5000" - )] - pub libp2p_max_ihave_length: usize, - - /// The maximum number of IHAVE messages to accept from a Libp2p peer within a heartbeat - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_MAX_IHAVE_MESSAGES", - default_value = "10" - )] - pub libp2p_max_ihave_messages: usize, - - /// Libp2p published message ids time cache duration - #[clap(long, env = "ESPRESSO_SEQUENCER_LIBP2P_PUBLISHED_MESSAGE_IDS_CACHE_TIME", default_value = "10s", value_parser = parse_duration)] - pub libp2p_published_message_ids_cache_time: Duration, - - /// Time to wait for a Libp2p message requested through IWANT following an IHAVE advertisement - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_MAX_IWANT_FOLLOWUP_TIME", - default_value = "3s", value_parser = parse_duration - )] - pub libp2p_iwant_followup_time: Duration, - - /// The maximum number of Libp2p messages we will process in a given RPC - #[clap(long, env = "ESPRESSO_SEQUENCER_LIBP2P_MAX_MESSAGES_PER_RPC")] - pub libp2p_max_messages_per_rpc: Option, - - /// How many times we will allow a Libp2p peer to request the same message id through IWANT gossip before we start ignoring them - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_GOSSIP_RETRANSMISSION", - default_value = "3" - )] - pub libp2p_gossip_retransmission: u32, - - /// If enabled newly created messages will always be sent to all peers that are subscribed to the topic and have a good enough score - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_FLOOD_PUBLISH", - default_value = "true" - )] - pub libp2p_flood_publish: bool, - - /// The time period that Libp2p message hashes are stored in the cache - #[clap(long, env = "ESPRESSO_SEQUENCER_LIBP2P_DUPLICATE_CACHE_TIME", default_value = "20m", value_parser = parse_duration)] - pub libp2p_duplicate_cache_time: Duration, - - /// Time to live for Libp2p fanout peers - #[clap(long, env = "ESPRESSO_SEQUENCER_LIBP2P_FANOUT_TTL", default_value = "60s", value_parser = parse_duration)] - pub libp2p_fanout_ttl: Duration, - - /// Initial delay in each Libp2p heartbeat - #[clap(long, env = "ESPRESSO_SEQUENCER_LIBP2P_HEARTBEAT_INITIAL_DELAY", default_value = "5s", value_parser = parse_duration)] - pub libp2p_heartbeat_initial_delay: Duration, - - /// How many Libp2p peers we will emit gossip to at each heartbeat - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_GOSSIP_FACTOR", - default_value = "0.25" - )] - pub libp2p_gossip_factor: f64, - - /// Minimum number of Libp2p peers to emit gossip to during a heartbeat - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_GOSSIP_LAZY", - default_value = "6" - )] - pub libp2p_gossip_lazy: usize, - - /// The maximum number of bytes we will send in a single Libp2p gossip message - #[clap( - long, - env = "ESPRESSO_SEQUENCER_LIBP2P_MAX_TRANSMIT_SIZE", - default_value = "2000000" - )] - pub libp2p_max_transmit_size: usize, - /// The URL we advertise to other nodes as being for our public API. /// Should be supplied in `http://host:port` form. #[clap(long, env = "ESPRESSO_SEQUENCER_PUBLIC_API_URL")] diff --git a/sequencer/src/restart_tests.rs b/sequencer/src/restart_tests.rs index 9ae3ee6d7..76c7a3665 100644 --- a/sequencer/src/restart_tests.rs +++ b/sequencer/src/restart_tests.rs @@ -16,10 +16,8 @@ use futures::{ stream::{BoxStream, StreamExt}, }; use hotshot::traits::implementations::derive_libp2p_peer_id; -use hotshot_orchestrator::{ - config::{Libp2pConfig, NetworkConfig}, - run_orchestrator, -}; +use hotshot_orchestrator::run_orchestrator; +use hotshot_types::network::{Libp2pConfig, NetworkConfig}; use hotshot_types::{ event::{Event, EventType}, light_client::StateKeyPair, diff --git a/types/src/v0/impls/auction.rs b/types/src/v0/impls/auction.rs index b58fba50c..e530c747b 100644 --- a/types/src/v0/impls/auction.rs +++ b/types/src/v0/impls/auction.rs @@ -304,7 +304,7 @@ impl AuctionResultsProvider for SolverAuctionResultsProv /// Fetch the auction results from the solver. async fn fetch_auction_result( &self, - view_number: TYPES::Time, + view_number: TYPES::View, ) -> anyhow::Result { let resp = SurfClient::new( self.url diff --git a/types/src/v0/impls/state.rs b/types/src/v0/impls/state.rs index 178372834..fc2d8fb78 100644 --- a/types/src/v0/impls/state.rs +++ b/types/src/v0/impls/state.rs @@ -682,13 +682,20 @@ impl HotShotState for ValidatedState { system_time, diff ); - return Err(BlockError::InvalidBlockHeader); + return Err(BlockError::InvalidBlockHeader(format!( + "Timestamp drift too high proposed={} system={} diff={}", + proposed_header.timestamp(), + system_time, + diff + ))); } //validate builder fee if let Err(err) = validate_builder_fee(proposed_header) { tracing::error!("invalid builder fee: {err:#}"); - return Err(BlockError::InvalidBlockHeader); + return Err(BlockError::InvalidBlockHeader(format!( + "invalid builder fee: {err:#}" + ))); } // Unwrapping here is okay as we retry in a loop @@ -722,14 +729,18 @@ impl HotShotState for ValidatedState { if finalized != proposed_finalized { tracing::error!("Invalid proposal: l1_finalized mismatch"); - return Err(BlockError::InvalidBlockHeader); + return Err(BlockError::InvalidBlockHeader( + "l1_finalized mismatch".to_string(), + )); } } // Validate `l1_head`. // TODO add test https://github.com/EspressoSystems/espresso-sequencer/issues/2100 if proposed_header.l1_head() < parent_leaf.block_header().l1_head() { tracing::error!("Invalid proposal: l1_head decreasing"); - return Err(BlockError::InvalidBlockHeader); + return Err(BlockError::InvalidBlockHeader( + "l1_head decreasing".to_string(), + )); } let _ = instance @@ -746,7 +757,7 @@ impl HotShotState for ValidatedState { &vid_common, ) { tracing::error!("Invalid proposal: {err:#}"); - return Err(BlockError::InvalidBlockHeader); + return Err(BlockError::InvalidBlockHeader(format!("{err:#}"))); } // log successful progress about once in 10 - 20 seconds, diff --git a/types/src/v0/mod.rs b/types/src/v0/mod.rs index 97d1e8a94..11dc166ab 100644 --- a/types/src/v0/mod.rs +++ b/types/src/v0/mod.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; use hotshot::traits::election::static_committee::StaticCommittee; use hotshot_types::{ - data::ViewNumber, + data::{EpochNumber, ViewNumber}, signature_key::BLSPubKey, traits::{ node_implementation::{NodeType, Versions}, @@ -126,7 +126,8 @@ reexport_unchanged_types!( pub struct SeqTypes; impl NodeType for SeqTypes { - type Time = ViewNumber; + type View = ViewNumber; + type Epoch = EpochNumber; type BlockHeader = Header; type BlockPayload = Payload; type SignatureKey = PubKey; @@ -176,7 +177,7 @@ pub type Event = hotshot::types::Event; pub type PubKey = BLSPubKey; pub type PrivKey = ::PrivateKey; -pub type NetworkConfig = hotshot_orchestrator::config::NetworkConfig; +pub type NetworkConfig = hotshot_types::network::NetworkConfig; pub use self::impls::{NodeState, SolverAuctionResultsProvider, ValidatedState}; pub use crate::v0_1::{