diff --git a/Cargo.lock b/Cargo.lock index fab8c84..e53c899 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -483,6 +483,40 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "155a5a185e42c6b77ac7b88a15143d930a9e9727a5b7b77eed417404ab15c247" +[[package]] +name = "astro-float" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96034cc871c05bb65ad7fb77e6a8bebf45d8b055ed0311769e2f83a1d373c1ec" +dependencies = [ + "astro-float-macro", + "astro-float-num", +] + +[[package]] +name = "astro-float-macro" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cfe0f6df5a74fb25b9e713470ad77e091f35f798730673c8772f26ed438963" +dependencies = [ + "astro-float-num", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "astro-float-num" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86887daca11d02e0b04f37a9cb81888aae881397fb48ff66494e356aea97554a" +dependencies = [ + "itertools 0.10.5", + "lazy_static", + "rand 0.8.5", + "serde", +] + [[package]] name = "async-channel" version = "2.5.0" @@ -533,28 +567,6 @@ dependencies = [ "syn 2.0.114", ] -[[package]] -name = "async-stream" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.114", -] - [[package]] name = "async-trait" version = "0.1.89" @@ -1952,19 +1964,13 @@ dependencies = [ "futures-core", "futures-sink", "http 1.4.0", - "indexmap 2.13.0", + "indexmap", "slab", "tokio", "tokio-util", "tracing", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "hashbrown" version = "0.13.2" @@ -2579,16 +2585,6 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - [[package]] name = "indexmap" version = "2.13.0" @@ -3421,7 +3417,7 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "logos-blockchain-api-service" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "bytes", @@ -3448,7 +3444,7 @@ dependencies = [ [[package]] name = "logos-blockchain-blend" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "logos-blockchain-blend-crypto", "logos-blockchain-blend-message", @@ -3460,7 +3456,7 @@ dependencies = [ [[package]] name = "logos-blockchain-blend-crypto" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "blake2", "logos-blockchain-groth16", @@ -3474,7 +3470,7 @@ dependencies = [ [[package]] name = "logos-blockchain-blend-message" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "blake2", "derivative", @@ -3496,7 +3492,7 @@ dependencies = [ [[package]] name = "logos-blockchain-blend-network" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "either", "futures", @@ -3514,13 +3510,15 @@ dependencies = [ [[package]] name = "logos-blockchain-blend-proofs" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "ed25519-dalek", "generic-array 1.3.5", "logos-blockchain-blend-crypto", "logos-blockchain-groth16", + "logos-blockchain-pol", "logos-blockchain-poq", + "logos-blockchain-utils", "num-bigint", "serde", "thiserror 1.0.69", @@ -3529,7 +3527,7 @@ dependencies = [ [[package]] name = "logos-blockchain-blend-scheduling" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "derivative", @@ -3553,7 +3551,7 @@ dependencies = [ [[package]] name = "logos-blockchain-blend-service" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "fork_stream", @@ -3588,7 +3586,7 @@ dependencies = [ [[package]] name = "logos-blockchain-chain-broadcast-service" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "derivative", @@ -3604,7 +3602,7 @@ dependencies = [ [[package]] name = "logos-blockchain-chain-leader-service" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "futures", @@ -3632,7 +3630,7 @@ dependencies = [ [[package]] name = "logos-blockchain-chain-network-service" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "futures", @@ -3660,7 +3658,7 @@ dependencies = [ [[package]] name = "logos-blockchain-chain-service" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "bytes", @@ -3690,7 +3688,7 @@ dependencies = [ [[package]] name = "logos-blockchain-chain-service-common" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "logos-blockchain-core", "serde", @@ -3699,7 +3697,7 @@ dependencies = [ [[package]] name = "logos-blockchain-circuits-prover" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "logos-blockchain-circuits-utils", "tempfile", @@ -3708,7 +3706,7 @@ dependencies = [ [[package]] name = "logos-blockchain-circuits-utils" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "dirs", ] @@ -3716,7 +3714,7 @@ dependencies = [ [[package]] name = "logos-blockchain-common-http-client" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "futures", "hex", @@ -3736,7 +3734,7 @@ dependencies = [ [[package]] name = "logos-blockchain-core" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "ark-ff 0.4.2", "bincode", @@ -3766,9 +3764,10 @@ dependencies = [ [[package]] name = "logos-blockchain-cryptarchia-engine" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "cfg_eval", + "logos-blockchain-pol", "logos-blockchain-utils", "serde", "serde_with", @@ -3781,7 +3780,7 @@ dependencies = [ [[package]] name = "logos-blockchain-cryptarchia-sync" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "bytes", "futures", @@ -3800,7 +3799,7 @@ dependencies = [ [[package]] name = "logos-blockchain-groth16" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "ark-bn254 0.4.0", "ark-ec 0.4.2", @@ -3818,7 +3817,7 @@ dependencies = [ [[package]] name = "logos-blockchain-http-api-common" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "axum", "logos-blockchain-core", @@ -3832,7 +3831,7 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-keys" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "bytes", @@ -3857,7 +3856,7 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-macros" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "proc-macro2", "quote", @@ -3867,7 +3866,7 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-operators" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "logos-blockchain-blend-proofs", @@ -3883,7 +3882,7 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-service" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "log", @@ -3899,7 +3898,7 @@ dependencies = [ [[package]] name = "logos-blockchain-ledger" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "derivative", "logos-blockchain-blend-crypto", @@ -3923,7 +3922,7 @@ dependencies = [ [[package]] name = "logos-blockchain-libp2p" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "backon", @@ -3952,7 +3951,7 @@ dependencies = [ [[package]] name = "logos-blockchain-network-service" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "futures", @@ -3971,7 +3970,7 @@ dependencies = [ [[package]] name = "logos-blockchain-node" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "axum", @@ -4033,7 +4032,7 @@ dependencies = [ [[package]] name = "logos-blockchain-poc" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "logos-blockchain-circuits-prover", "logos-blockchain-circuits-utils", @@ -4049,11 +4048,13 @@ dependencies = [ [[package]] name = "logos-blockchain-pol" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ + "astro-float", "logos-blockchain-circuits-prover", "logos-blockchain-circuits-utils", "logos-blockchain-groth16", + "logos-blockchain-utils", "logos-blockchain-witness-generator", "num-bigint", "num-traits", @@ -4066,7 +4067,7 @@ dependencies = [ [[package]] name = "logos-blockchain-poq" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "logos-blockchain-circuits-prover", "logos-blockchain-circuits-utils", @@ -4083,7 +4084,7 @@ dependencies = [ [[package]] name = "logos-blockchain-poseidon2" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "ark-bn254 0.4.0", "ark-ff 0.4.2", @@ -4094,7 +4095,7 @@ dependencies = [ [[package]] name = "logos-blockchain-sdp-service" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "futures", @@ -4110,7 +4111,7 @@ dependencies = [ [[package]] name = "logos-blockchain-services-utils" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "futures", @@ -4125,7 +4126,7 @@ dependencies = [ [[package]] name = "logos-blockchain-storage-service" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "bytes", @@ -4143,7 +4144,7 @@ dependencies = [ [[package]] name = "logos-blockchain-system-sig-service" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-ctrlc", "async-trait", @@ -4154,7 +4155,7 @@ dependencies = [ [[package]] name = "logos-blockchain-time-service" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "cfg_eval", @@ -4176,15 +4177,15 @@ dependencies = [ [[package]] name = "logos-blockchain-tracing" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "opentelemetry", + "opentelemetry-appender-tracing", "opentelemetry-http", "opentelemetry-otlp", "opentelemetry-semantic-conventions", "opentelemetry_sdk", "rand 0.8.5", - "reqwest", "serde", "tokio", "tracing", @@ -4199,7 +4200,7 @@ dependencies = [ [[package]] name = "logos-blockchain-tracing-service" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "logos-blockchain-tracing", @@ -4213,7 +4214,7 @@ dependencies = [ [[package]] name = "logos-blockchain-tui-zone" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "clap", "hex", @@ -4230,7 +4231,7 @@ dependencies = [ [[package]] name = "logos-blockchain-tx-service" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "futures", @@ -4252,7 +4253,7 @@ dependencies = [ [[package]] name = "logos-blockchain-utils" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "blake2", @@ -4269,7 +4270,7 @@ dependencies = [ [[package]] name = "logos-blockchain-utxotree" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "ark-ff 0.4.2", "logos-blockchain-groth16", @@ -4283,7 +4284,7 @@ dependencies = [ [[package]] name = "logos-blockchain-wallet" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "logos-blockchain-core", "logos-blockchain-key-management-system-keys", @@ -4298,7 +4299,7 @@ dependencies = [ [[package]] name = "logos-blockchain-wallet-service" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "async-trait", "bytes", @@ -4323,7 +4324,7 @@ dependencies = [ [[package]] name = "logos-blockchain-witness-generator" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "tempfile", ] @@ -4331,7 +4332,7 @@ dependencies = [ [[package]] name = "logos-blockchain-zksign" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "logos-blockchain-circuits-prover", "logos-blockchain-circuits-utils", @@ -4348,7 +4349,7 @@ dependencies = [ [[package]] name = "logos-blockchain-zone-sdk" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "futures", "logos-blockchain-common-http-client", @@ -4368,7 +4369,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdc38a304f59a03e6efa3876766a48c70a766a93f88341c3fff4212834b8e327" dependencies = [ - "prost", + "prost 0.13.5", "prost-types", ] @@ -4909,23 +4910,34 @@ dependencies = [ [[package]] name = "opentelemetry" -version = "0.26.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "570074cc999d1a58184080966e5bd3bf3a9a4af650c3b05047c2621e7405cd17" +checksum = "b84bcd6ae87133e903af7ef497404dda70c60d0ea14895fc8a5e6722754fc2a0" dependencies = [ "futures-core", "futures-sink", "js-sys", - "once_cell", "pin-project-lite", - "thiserror 1.0.69", + "thiserror 2.0.18", +] + +[[package]] +name = "opentelemetry-appender-tracing" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef6a1ac5ca3accf562b8c306fa8483c85f4390f768185ab775f242f7fe8fdcc2" +dependencies = [ + "opentelemetry", + "tracing", + "tracing-core", + "tracing-subscriber 0.3.22", ] [[package]] name = "opentelemetry-http" -version = "0.26.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6351496aeaa49d7c267fb480678d85d1cd30c5edb20b497c48c56f62a8c14b99" +checksum = "d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d" dependencies = [ "async-trait", "bytes", @@ -4936,57 +4948,53 @@ dependencies = [ [[package]] name = "opentelemetry-otlp" -version = "0.26.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e1f9c8b032d4f635c730c0efcf731d5e2530ea13fa8bef7939ddc8420696bd" +checksum = "7a2366db2dca4d2ad033cad11e6ee42844fd727007af5ad04a1730f4cb8163bf" dependencies = [ - "async-trait", - "futures-core", "http 1.4.0", "opentelemetry", "opentelemetry-http", "opentelemetry-proto", "opentelemetry_sdk", - "prost", - "thiserror 1.0.69", + "prost 0.14.3", + "thiserror 2.0.18", "tokio", "tonic", ] [[package]] name = "opentelemetry-proto" -version = "0.26.1" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9d3968ce3aefdcca5c27e3c4ea4391b37547726a70893aab52d3de95d5f8b34" +checksum = "a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f" dependencies = [ "opentelemetry", "opentelemetry_sdk", - "prost", + "prost 0.14.3", "tonic", + "tonic-prost", ] [[package]] name = "opentelemetry-semantic-conventions" -version = "0.26.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db945c1eaea8ac6a9677185357480d215bb6999faa9f691d0c4d4d641eab7a09" +checksum = "e62e29dfe041afb8ed2a6c9737ab57db4907285d999ef8ad3a59092a36bdc846" [[package]] name = "opentelemetry_sdk" -version = "0.26.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c627d9f4c9cdc1f21a29ee4bfbd6028fcb8bcf2a857b43f3abdf72c9c862f3" +checksum = "e14ae4f5991976fd48df6d843de219ca6d31b01daaab2dad5af2badeded372bd" dependencies = [ - "async-trait", "futures-channel", "futures-executor", "futures-util", - "glob", - "once_cell", "opentelemetry", "percent-encoding", - "rand 0.8.5", - "thiserror 1.0.69", + "rand 0.9.2", + "thiserror 2.0.18", "tokio", "tokio-stream", ] @@ -5394,7 +5402,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" dependencies = [ "bytes", - "prost-derive", + "prost-derive 0.13.5", +] + +[[package]] +name = "prost" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" +dependencies = [ + "bytes", + "prost-derive 0.14.3", ] [[package]] @@ -5410,13 +5428,26 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "prost-derive" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" +dependencies = [ + "anyhow", + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "prost-types" version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" dependencies = [ - "prost", + "prost 0.13.5", ] [[package]] @@ -6184,7 +6215,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.13.0", + "indexmap", "itoa", "ryu", "serde", @@ -6562,7 +6593,7 @@ dependencies = [ [[package]] name = "testing_framework" version = "0.1.0" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=a4275d00eb3041ed6bfb394e0913cd1ad172224c#a4275d00eb3041ed6bfb394e0913cd1ad172224c" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=41ea1e3082526bb271e655cddb95a5b448e7de20#41ea1e3082526bb271e655cddb95a5b448e7de20" dependencies = [ "anyhow", "async-trait", @@ -6834,7 +6865,7 @@ version = "0.23.10+spec-1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" dependencies = [ - "indexmap 2.13.0", + "indexmap", "toml_datetime", "toml_parser", "winnow", @@ -6851,16 +6882,13 @@ dependencies = [ [[package]] name = "tonic" -version = "0.12.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" +checksum = "7f32a6f80051a4111560201420c7885d0082ba9efe2ab61875c587bb6b18b9a0" dependencies = [ - "async-stream", "async-trait", - "axum", "base64 0.22.1", "bytes", - "h2", "http 1.4.0", "http-body 1.0.1", "http-body-util", @@ -6869,16 +6897,26 @@ dependencies = [ "hyper-util", "percent-encoding", "pin-project", - "prost", - "socket2 0.5.10", + "sync_wrapper", "tokio", "tokio-stream", - "tower 0.4.13", + "tower 0.5.3", "tower-layer", "tower-service", "tracing", ] +[[package]] +name = "tonic-prost" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f86539c0089bfd09b1f8c0ab0239d80392af74c21bc9e0f15e1b4aca4c1647f" +dependencies = [ + "bytes", + "prost 0.14.3", + "tonic", +] + [[package]] name = "tower" version = "0.4.13" @@ -6887,11 +6925,8 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", - "indexmap 1.9.3", "pin-project", "pin-project-lite", - "rand 0.8.5", - "slab", "tokio", "tokio-util", "tower-layer", @@ -6907,11 +6942,15 @@ checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", + "indexmap", "pin-project-lite", + "slab", "sync_wrapper", "tokio", + "tokio-util", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -7091,14 +7130,12 @@ dependencies = [ [[package]] name = "tracing-opentelemetry" -version = "0.27.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc58af5d3f6c5811462cabb3289aec0093f7338e367e5a33d28c0433b3c7360b" +checksum = "1ac28f2d093c6c477eaa76b23525478f38de514fa9aeb1285738d4b97a9552fc" dependencies = [ "js-sys", - "once_cell", "opentelemetry", - "opentelemetry_sdk", "smallvec", "tracing", "tracing-core", @@ -7258,7 +7295,7 @@ version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5afb1a60e207dca502682537fefcfd9921e71d0b83e9576060f09abc6efab23" dependencies = [ - "indexmap 2.13.0", + "indexmap", "serde", "serde_json", "utoipa-gen", @@ -8066,7 +8103,7 @@ dependencies = [ "crossbeam-utils", "displaydoc", "flate2", - "indexmap 2.13.0", + "indexmap", "num_enum", "thiserror 1.0.69", ] diff --git a/Cargo.toml b/Cargo.toml index 528db3a..1fcc636 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ all = "allow" # Local testing framework crates cfgsync-core = { default-features = false, path = "testing-framework/tools/cfgsync-core" } lb-ext = { default-features = false, path = "logos/runtime/ext" } -lb-framework = { default-features = false, package = "testing_framework", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } +lb-framework = { default-features = false, package = "testing_framework", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } lb-workloads = { default-features = false, path = "logos/runtime/workloads" } testing-framework-core = { default-features = false, path = "testing-framework/core" } testing-framework-env = { default-features = false, path = "logos/runtime/env" } @@ -42,44 +42,44 @@ testing-framework-runner-k8s = { default-features = false, path = "testing-f testing-framework-runner-local = { default-features = false, path = "testing-framework/deployers/local" } # Logos dependencies (from logos-blockchain master @ deccbb2d2) -broadcast-service = { default-features = false, package = "logos-blockchain-chain-broadcast-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } +broadcast-service = { default-features = false, package = "logos-blockchain-chain-broadcast-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } cfgsync_runtime = { default-features = false, package = "cfgsync-runtime", path = "testing-framework/tools/cfgsync-runtime" } chain-leader = { default-features = false, features = [ "pol-dev-mode", -], package = "logos-blockchain-chain-leader-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -chain-network = { default-features = false, package = "logos-blockchain-chain-network-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -chain-service = { default-features = false, package = "logos-blockchain-chain-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -common-http-client = { default-features = false, package = "logos-blockchain-common-http-client", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -cryptarchia-engine = { default-features = false, package = "logos-blockchain-cryptarchia-engine", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -cryptarchia-sync = { default-features = false, package = "logos-blockchain-cryptarchia-sync", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -groth16 = { default-features = false, package = "logos-blockchain-groth16", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -key-management-system-service = { default-features = false, package = "logos-blockchain-key-management-system-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -nomos-api = { default-features = false, package = "logos-blockchain-api-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -nomos-blend-message = { default-features = false, package = "logos-blockchain-blend-message", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -nomos-blend-service = { default-features = false, package = "logos-blockchain-blend-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -nomos-core = { default-features = false, package = "logos-blockchain-core", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -nomos-http-api-common = { default-features = false, package = "logos-blockchain-http-api-common", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -nomos-ledger = { default-features = false, package = "logos-blockchain-ledger", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -nomos-libp2p = { default-features = false, package = "logos-blockchain-libp2p", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -nomos-network = { default-features = false, package = "logos-blockchain-network-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } +], package = "logos-blockchain-chain-leader-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +chain-network = { default-features = false, package = "logos-blockchain-chain-network-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +chain-service = { default-features = false, package = "logos-blockchain-chain-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +common-http-client = { default-features = false, package = "logos-blockchain-common-http-client", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +cryptarchia-engine = { default-features = false, package = "logos-blockchain-cryptarchia-engine", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +cryptarchia-sync = { default-features = false, package = "logos-blockchain-cryptarchia-sync", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +groth16 = { default-features = false, package = "logos-blockchain-groth16", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +key-management-system-service = { default-features = false, package = "logos-blockchain-key-management-system-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +nomos-api = { default-features = false, package = "logos-blockchain-api-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +nomos-blend-message = { default-features = false, package = "logos-blockchain-blend-message", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +nomos-blend-service = { default-features = false, package = "logos-blockchain-blend-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +nomos-core = { default-features = false, package = "logos-blockchain-core", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +nomos-http-api-common = { default-features = false, package = "logos-blockchain-http-api-common", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +nomos-ledger = { default-features = false, package = "logos-blockchain-ledger", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +nomos-libp2p = { default-features = false, package = "logos-blockchain-libp2p", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +nomos-network = { default-features = false, package = "logos-blockchain-network-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } nomos-node = { default-features = false, features = [ "testing", -], package = "logos-blockchain-node", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -nomos-sdp = { default-features = false, package = "logos-blockchain-sdp-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -nomos-time = { default-features = false, package = "logos-blockchain-time-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -nomos-tracing = { default-features = false, package = "logos-blockchain-tracing", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -nomos-tracing-service = { default-features = false, package = "logos-blockchain-tracing-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -nomos-utils = { default-features = false, package = "logos-blockchain-utils", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -nomos-wallet = { default-features = false, package = "logos-blockchain-wallet-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -poc = { default-features = false, package = "logos-blockchain-poc", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -pol = { default-features = false, package = "logos-blockchain-pol", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -tx-service = { default-features = false, package = "logos-blockchain-tx-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -wallet = { default-features = false, package = "logos-blockchain-wallet", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -zksign = { default-features = false, package = "logos-blockchain-zksign", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } +], package = "logos-blockchain-node", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +nomos-sdp = { default-features = false, package = "logos-blockchain-sdp-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +nomos-time = { default-features = false, package = "logos-blockchain-time-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +nomos-tracing = { default-features = false, package = "logos-blockchain-tracing", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +nomos-tracing-service = { default-features = false, package = "logos-blockchain-tracing-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +nomos-utils = { default-features = false, package = "logos-blockchain-utils", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +nomos-wallet = { default-features = false, package = "logos-blockchain-wallet-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +poc = { default-features = false, package = "logos-blockchain-poc", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +pol = { default-features = false, package = "logos-blockchain-pol", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +tx-service = { default-features = false, package = "logos-blockchain-tx-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +wallet = { default-features = false, package = "logos-blockchain-wallet", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +zksign = { default-features = false, package = "logos-blockchain-zksign", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } # lb_* aliases (nomos-node repo naming) -lb_http_api_common = { default-features = false, package = "logos-blockchain-http-api-common", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -lb_tracing = { default-features = false, package = "logos-blockchain-tracing", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } -lb_tracing_service = { default-features = false, package = "logos-blockchain-tracing-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "a4275d00eb3041ed6bfb394e0913cd1ad172224c" } +lb_http_api_common = { default-features = false, package = "logos-blockchain-http-api-common", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +lb_tracing = { default-features = false, package = "logos-blockchain-tracing", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } +lb_tracing_service = { default-features = false, package = "logos-blockchain-tracing-service", git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "41ea1e3082526bb271e655cddb95a5b448e7de20" } # External crates async-trait = { default-features = false, version = "0.1" } bytes = { default-features = false, version = "1.3" } diff --git a/docs/external-network-architecture.md b/docs/external-network-architecture.md index b1e9351..0f1cfdc 100644 --- a/docs/external-network-architecture.md +++ b/docs/external-network-architecture.md @@ -17,11 +17,11 @@ flowchart TD BO[Bootstrap Orchestrator] A --> B[Managed Nodes Spec\ncount/config/patches] - A --> C[Attach Spec\nprovider + selector] + A --> C[Attach Spec\ntyped k8s/compose source] A --> D[External Nodes Spec\nstatic endpoints] B --> E[Deployer\nlocal/docker/k8s] - C --> F[AttachProvider\nstatic/k8s/compose/...] + C --> F[AttachProvider\nk8s/compose/...] D --> BO E --> G[Managed Node Handles\norigin=Managed, ownership=Owned] @@ -147,7 +147,7 @@ This keeps scenario logic reusable while preserving explicit safety boundaries. - **Node identity**: use `peer_id` as canonical key; fallback to `(host, port)` only when peer id is unavailable. - **Dedup merge**: if same canonical identity appears from multiple sources, keep one handle and record all origins for diagnostics. - **Bootstrap peers**: every managed node gets at least 2 seed peers from distinct origins when possible. -- **Readiness gate**: default to quorum (`>= 2` or `>= 50%`, whichever is greater); allow strict-all via scenario override. +- **Readiness gate**: phase 1 default is `AllReady` (all known nodes must pass readiness). Keep policy extensible for `Quorum` and future `SourceAware` readiness. - **Borrowed node safety**: lifecycle and config patch disabled by default for borrowed nodes; explicit opt-in required. - **Compatibility preflight**: enforce matching chain/network id + protocol version before scenario start. - **Failure handling**: @@ -156,6 +156,20 @@ This keeps scenario logic reusable while preserving explicit safety boundaries. - partial attach discovery: warn + continue only if readiness quorum still satisfiable - **Cleanup**: delete owned artifacts only; never mutate or delete borrowed node resources. +## Source Combination Modes + +Use a typed source enum so invalid combinations are unrepresentable: + +- `Managed { external }`: deployer-managed nodes with optional external overlays. +- `Attached { attach, external }`: attached cluster with optional external overlays. +- `ExternalOnly { external }`: explicit external-only mode. + +Validation rules: + +- `Managed` requires managed deployment to produce nodes (`managed_count > 0`). +- `Attached` requires managed deployment to produce zero nodes (`managed + attached` is disallowed). +- `ExternalOnly` requires non-empty `external` and zero managed nodes. + ## Clean Codebase Layout (Recommended) Use a layered module structure so responsibilities stay isolated. @@ -220,3 +234,17 @@ These changes help future external-network support while preserving current publ - Add internal node metadata (`origin`, `ownership`, `capabilities`) defaulted to managed semantics. - Standardize node identity and dedup helpers (`peer_id` preferred, endpoint fallback). - Keep current env vars/flags intact, but parse via a single typed config layer. +- Add a single source-orchestration match path (`ScenarioSources`) inside deployers; unsupported source modes fail fast with typed errors until attach/external registration lands. + +## Open Risks and Required Clarifications + +Before full rollout, lock these semantics explicitly: + +- **Source enum precedence**: typed `ScenarioSources` variants are the primary control plane. Runtime counts validate, but never redefine, source intent. +- **Ownership conflict resolution**: define behavior when a deduped node appears from multiple sources with different ownership (for example, fail-fast by default; optional override if needed). +- **Source-aware readiness**: avoid quorum rules that can hide managed deployment failures. Require per-source readiness constraints (for example, minimum managed-ready + global quorum). +- **Readiness rollout**: phase 1 uses `AllReady`; later rollout can add `SourceAware` constraints once mixed-source behavior is validated. +- **Bootstrap mutation boundary**: peer/bootstrap policy mutates managed nodes only unless an attach provider explicitly supports controlled mutation. +- **Compatibility contract expansion**: preflight checks should include API/auth/genesis compatibility class, not only network/protocol identifiers. +- **Deterministic membership policy**: define strict vs degradable attach behavior so partial discovery does not silently change scenario semantics. +- **Step migration boundary**: after `NodeInventory` handoff, scenario steps must not read deployer-specific state directly. diff --git a/testing-framework/core/src/env.rs b/testing-framework/core/src/env.rs index e8b59e0..82cea91 100644 --- a/testing-framework/core/src/env.rs +++ b/testing-framework/core/src/env.rs @@ -16,6 +16,18 @@ pub trait Application: Send + Sync + 'static { type FeedRuntime: FeedRuntime; + /// Optional stable node identity (for example a peer id) used for + /// deduplication when nodes are discovered from multiple sources. + fn node_peer_identity(_client: &Self::NodeClient) -> Option { + None + } + + /// Optional endpoint identity used as a dedup fallback when no peer id is + /// available. + fn node_endpoint_identity(_client: &Self::NodeClient) -> Option { + None + } + async fn prepare_feed( client: Self::NodeClient, ) -> Result<(::Feed, Self::FeedRuntime), DynError>; diff --git a/testing-framework/core/src/scenario/definition.rs b/testing-framework/core/src/scenario/definition.rs index a34ccc4..f487eb2 100644 --- a/testing-framework/core/src/scenario/definition.rs +++ b/testing-framework/core/src/scenario/definition.rs @@ -4,9 +4,16 @@ use thiserror::Error; use tracing::{debug, info}; use super::{ - Application, DeploymentPolicy, DynError, HttpReadinessRequirement, NodeControlCapability, - ObservabilityCapability, builder_ops::CoreBuilderAccess, expectation::Expectation, - runtime::context::RunMetrics, workload::Workload, + Application, AttachSource, DeploymentPolicy, DynError, ExternalNodeSource, + HttpReadinessRequirement, NodeControlCapability, ObservabilityCapability, ScenarioSources, + SourceReadinessPolicy, + builder_ops::CoreBuilderAccess, + expectation::Expectation, + runtime::{ + context::RunMetrics, + orchestration::{SourceModeName, SourceOrchestrationPlan, SourceOrchestrationPlanError}, + }, + workload::Workload, }; use crate::topology::{DeploymentDescriptor, DeploymentProvider, DeploymentSeed, DynTopologyError}; @@ -21,6 +28,10 @@ pub enum ScenarioBuildError { WorkloadInit { name: String, source: DynError }, #[error("expectation '{name}' failed to initialize")] ExpectationInit { name: String, source: DynError }, + #[error("invalid scenario source configuration: {message}")] + SourceConfiguration { message: String }, + #[error("scenario source mode '{mode}' is not wired into deployers yet")] + SourceModeNotWiredYet { mode: &'static str }, } /// Immutable scenario definition used by the runner, workloads, and @@ -32,6 +43,8 @@ pub struct Scenario { duration: Duration, expectation_cooldown: Duration, deployment_policy: DeploymentPolicy, + sources: ScenarioSources, + source_readiness_policy: SourceReadinessPolicy, capabilities: Caps, } @@ -43,6 +56,8 @@ impl Scenario { duration: Duration, expectation_cooldown: Duration, deployment_policy: DeploymentPolicy, + sources: ScenarioSources, + source_readiness_policy: SourceReadinessPolicy, capabilities: Caps, ) -> Self { Self { @@ -52,6 +67,8 @@ impl Scenario { duration, expectation_cooldown, deployment_policy, + sources, + source_readiness_policy, capabilities, } } @@ -96,6 +113,20 @@ impl Scenario { self.deployment_policy } + #[must_use] + /// Selected source readiness policy. + /// + /// This is currently reserved for future mixed-source orchestration and + /// does not change runtime behavior yet. + pub const fn source_readiness_policy(&self) -> SourceReadinessPolicy { + self.source_readiness_policy + } + + #[must_use] + pub fn sources(&self) -> &ScenarioSources { + &self.sources + } + #[must_use] pub const fn capabilities(&self) -> &Caps { &self.capabilities @@ -111,6 +142,8 @@ pub struct Builder { duration: Duration, expectation_cooldown: Option, deployment_policy: DeploymentPolicy, + sources: ScenarioSources, + source_readiness_policy: SourceReadinessPolicy, capabilities: Caps, } @@ -205,6 +238,26 @@ macro_rules! impl_common_builder_methods { self.map_core_builder(|builder| builder.with_deployment_policy(policy)) } + #[must_use] + pub fn with_attach_source(self, attach: AttachSource) -> Self { + self.map_core_builder(|builder| builder.with_attach_source(attach)) + } + + #[must_use] + pub fn with_external_node(self, node: ExternalNodeSource) -> Self { + self.map_core_builder(|builder| builder.with_external_node(node)) + } + + #[must_use] + pub fn with_source_readiness_policy(self, policy: SourceReadinessPolicy) -> Self { + self.map_core_builder(|builder| builder.with_source_readiness_policy(policy)) + } + + #[must_use] + pub fn with_external_only_sources(self) -> Self { + self.map_core_builder(|builder| builder.with_external_only_sources()) + } + #[must_use] pub fn run_duration(&self) -> Duration { self.core_builder_ref().run_duration() @@ -288,6 +341,8 @@ impl Builder { duration: Duration::ZERO, expectation_cooldown: None, deployment_policy: DeploymentPolicy::default(), + sources: ScenarioSources::default(), + source_readiness_policy: SourceReadinessPolicy::default(), capabilities: Caps::default(), } } @@ -389,6 +444,8 @@ impl Builder { duration, expectation_cooldown, deployment_policy, + sources, + source_readiness_policy, .. } = self; @@ -400,6 +457,8 @@ impl Builder { duration, expectation_cooldown, deployment_policy, + sources, + source_readiness_policy, capabilities, } } @@ -500,6 +559,34 @@ impl Builder { self } + #[must_use] + pub fn with_attach_source(mut self, attach: AttachSource) -> Self { + self.sources.set_attach(attach); + self + } + + #[must_use] + pub fn with_external_node(mut self, node: ExternalNodeSource) -> Self { + self.sources.add_external_node(node); + self + } + + #[must_use] + /// Configure source readiness policy metadata. + /// + /// This is currently reserved for future mixed-source orchestration and + /// does not change runtime behavior yet. + pub fn with_source_readiness_policy(mut self, policy: SourceReadinessPolicy) -> Self { + self.source_readiness_policy = policy; + self + } + + #[must_use] + pub fn with_external_only_sources(mut self) -> Self { + self.sources.set_external_only(); + self + } + fn add_workload(&mut self, workload: Box>) { self.expectations.extend(workload.expectations()); self.workloads.push(workload); @@ -517,6 +604,11 @@ impl Builder { let descriptors = parts.resolve_deployment()?; let run_plan = parts.run_plan(); let run_metrics = RunMetrics::new(run_plan.duration); + let _source_plan = build_source_orchestration_plan( + parts.sources(), + descriptors.node_count(), + parts.source_readiness_policy, + )?; initialize_components( &descriptors, @@ -542,6 +634,8 @@ impl Builder { run_plan.duration, run_plan.expectation_cooldown, parts.deployment_policy, + parts.sources, + parts.source_readiness_policy, parts.capabilities, )) } @@ -560,6 +654,8 @@ struct BuilderParts { duration: Duration, expectation_cooldown: Option, deployment_policy: DeploymentPolicy, + sources: ScenarioSources, + source_readiness_policy: SourceReadinessPolicy, capabilities: Caps, } @@ -573,6 +669,8 @@ impl BuilderParts { duration, expectation_cooldown, deployment_policy, + sources, + source_readiness_policy, capabilities, .. } = builder; @@ -585,6 +683,8 @@ impl BuilderParts { duration, expectation_cooldown, deployment_policy, + sources, + source_readiness_policy, capabilities, } } @@ -601,6 +701,40 @@ impl BuilderParts { expectation_cooldown: expectation_cooldown_for(self.expectation_cooldown), } } + + fn sources(&self) -> &ScenarioSources { + &self.sources + } +} + +fn build_source_orchestration_plan( + sources: &ScenarioSources, + managed_node_count: usize, + readiness_policy: SourceReadinessPolicy, +) -> Result { + SourceOrchestrationPlan::try_from_sources(sources, managed_node_count, readiness_policy) + .map_err(source_plan_error_to_build_error) +} + +fn source_plan_error_to_build_error(error: SourceOrchestrationPlanError) -> ScenarioBuildError { + match error { + SourceOrchestrationPlanError::ManagedNodesMissing => ScenarioBuildError::SourceConfiguration { + message: + "managed source selected but deployment produced 0 managed nodes; choose a deployment provider/configuration that yields managed nodes".to_string(), + }, + SourceOrchestrationPlanError::SourceModeNotWiredYet { mode } => { + ScenarioBuildError::SourceModeNotWiredYet { + mode: source_mode_name(mode), + } + } + } +} + +const fn source_mode_name(mode: SourceModeName) -> &'static str { + match mode { + SourceModeName::Attached => "Attached", + SourceModeName::ExternalOnly => "ExternalOnly", + } } impl Builder { diff --git a/testing-framework/core/src/scenario/mod.rs b/testing-framework/core/src/scenario/mod.rs index 9867694..29db468 100644 --- a/testing-framework/core/src/scenario/mod.rs +++ b/testing-framework/core/src/scenario/mod.rs @@ -12,6 +12,7 @@ mod deployment_policy; mod expectation; mod observability; mod runtime; +mod sources; mod workload; pub type DynError = Box; @@ -36,8 +37,9 @@ pub use deployment_policy::{CleanupPolicy, DeploymentPolicy, RetryPolicy}; pub use expectation::Expectation; pub use observability::{ObservabilityCapabilityProvider, ObservabilityInputs}; pub use runtime::{ - CleanupGuard, Deployer, Feed, FeedHandle, FeedRuntime, HttpReadinessRequirement, NodeClients, - ReadinessError, RunContext, RunHandle, RunMetrics, Runner, ScenarioError, StabilizationConfig, + BorrowedNode, BorrowedOrigin, CleanupGuard, Deployer, Feed, FeedHandle, FeedRuntime, + HttpReadinessRequirement, ManagedNode, NodeClients, NodeHandle, NodeInventory, ReadinessError, + RunContext, RunHandle, RunMetrics, Runner, ScenarioError, StabilizationConfig, metrics::{ CONSENSUS_PROCESSED_BLOCKS, CONSENSUS_TRANSACTIONS_TOTAL, Metrics, MetricsError, PrometheusEndpoint, PrometheusInstantSample, @@ -46,6 +48,7 @@ pub use runtime::{ wait_for_http_ports_with_host_and_requirement, wait_for_http_ports_with_requirement, wait_http_readiness, wait_until_stable, }; +pub use sources::{AttachSource, ExternalNodeSource, ScenarioSources, SourceReadinessPolicy}; pub use workload::Workload; pub use crate::env::Application; diff --git a/testing-framework/core/src/scenario/runtime/context.rs b/testing-framework/core/src/scenario/runtime/context.rs index 441d608..8e26133 100644 --- a/testing-framework/core/src/scenario/runtime/context.rs +++ b/testing-framework/core/src/scenario/runtime/context.rs @@ -1,7 +1,7 @@ use std::{sync::Arc, time::Duration}; use super::{metrics::Metrics, node_clients::ClusterClient}; -use crate::scenario::{Application, NodeClients, NodeControlHandle}; +use crate::scenario::{Application, BorrowedNode, ManagedNode, NodeClients, NodeControlHandle}; /// Shared runtime context available to workloads and expectations. pub struct RunContext { @@ -54,6 +54,26 @@ impl RunContext { self.node_clients.random_client() } + #[must_use] + pub fn managed_nodes(&self) -> Vec> { + self.node_clients.managed_nodes() + } + + #[must_use] + pub fn borrowed_nodes(&self) -> Vec> { + self.node_clients.borrowed_nodes() + } + + #[must_use] + pub fn find_managed_node(&self, identity: &str) -> Option> { + self.node_clients.find_managed(identity) + } + + #[must_use] + pub fn find_borrowed_node(&self, identity: &str) -> Option> { + self.node_clients.find_borrowed(identity) + } + #[must_use] pub fn feed(&self) -> ::Feed { self.feed.clone() diff --git a/testing-framework/core/src/scenario/runtime/inventory/mod.rs b/testing-framework/core/src/scenario/runtime/inventory/mod.rs new file mode 100644 index 0000000..6bc0334 --- /dev/null +++ b/testing-framework/core/src/scenario/runtime/inventory/mod.rs @@ -0,0 +1,3 @@ +mod node_inventory; + +pub use node_inventory::{BorrowedNode, BorrowedOrigin, ManagedNode, NodeHandle, NodeInventory}; diff --git a/testing-framework/core/src/scenario/runtime/inventory/node_inventory.rs b/testing-framework/core/src/scenario/runtime/inventory/node_inventory.rs new file mode 100644 index 0000000..18215e7 --- /dev/null +++ b/testing-framework/core/src/scenario/runtime/inventory/node_inventory.rs @@ -0,0 +1,342 @@ +use std::{collections::HashMap, sync::Arc}; + +use parking_lot::RwLock; + +use crate::scenario::{Application, DynError, NodeControlHandle, StartNodeOptions, StartedNode}; + +/// Origin for borrowed (non-managed) nodes in the runtime inventory. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum BorrowedOrigin { + /// Node discovered from an attached cluster provider. + Attached, + /// Node provided explicitly as an external endpoint. + External, +} + +/// Managed node handle with full lifecycle capabilities. +pub struct ManagedNode { + /// Canonical node identity used for deduplication and lookups. + pub identity: String, + /// Application-specific API client for this node. + pub client: E::NodeClient, +} + +/// Borrowed node handle (attached or external), query-only by default. +pub struct BorrowedNode { + /// Canonical node identity used for deduplication and lookups. + pub identity: String, + /// Application-specific API client for this node. + pub client: E::NodeClient, + /// Borrowed source kind used for diagnostics and selection. + pub origin: BorrowedOrigin, +} + +/// Unified node handle variant used by runtime inventory snapshots. +pub enum NodeHandle { + /// Managed node variant. + Managed(ManagedNode), + /// Borrowed node variant. + Borrowed(BorrowedNode), +} + +impl Clone for ManagedNode { + fn clone(&self) -> Self { + Self { + identity: self.identity.clone(), + client: self.client.clone(), + } + } +} + +impl Clone for BorrowedNode { + fn clone(&self) -> Self { + Self { + identity: self.identity.clone(), + client: self.client.clone(), + origin: self.origin, + } + } +} + +impl Clone for NodeHandle { + fn clone(&self) -> Self { + match self { + Self::Managed(node) => Self::Managed(node.clone()), + Self::Borrowed(node) => Self::Borrowed(node.clone()), + } + } +} + +/// Thread-safe node inventory with identity-based upsert semantics. +pub struct NodeInventory { + inner: Arc>>, +} + +struct NodeInventoryInner { + nodes: Vec>, + indices_by_identity: HashMap, + next_synthetic_id: usize, +} + +impl Default for NodeInventory { + fn default() -> Self { + Self { + inner: Arc::new(RwLock::new(NodeInventoryInner { + nodes: Vec::new(), + indices_by_identity: HashMap::new(), + next_synthetic_id: 0, + })), + } + } +} + +impl Clone for NodeInventory { + fn clone(&self) -> Self { + Self { + inner: Arc::clone(&self.inner), + } + } +} + +impl NodeInventory { + #[must_use] + /// Builds an inventory from managed clients. + pub fn from_managed_clients(clients: Vec) -> Self { + let inventory = Self::default(); + + for client in clients { + inventory.add_managed_node(client, None); + } + + inventory + } + + #[must_use] + /// Returns a cloned snapshot of all node clients. + pub fn snapshot_clients(&self) -> Vec { + self.inner.read().nodes.iter().map(clone_client).collect() + } + + #[must_use] + /// Returns cloned managed node handles from the current inventory. + pub fn managed_nodes(&self) -> Vec> { + self.inner + .read() + .nodes + .iter() + .filter_map(|handle| match handle { + NodeHandle::Managed(node) => Some(node.clone()), + NodeHandle::Borrowed(_) => None, + }) + .collect() + } + + #[must_use] + /// Returns cloned borrowed node handles from the current inventory. + pub fn borrowed_nodes(&self) -> Vec> { + self.inner + .read() + .nodes + .iter() + .filter_map(|handle| match handle { + NodeHandle::Managed(_) => None, + NodeHandle::Borrowed(node) => Some(node.clone()), + }) + .collect() + } + + #[must_use] + /// Finds a managed node by canonical identity. + pub fn find_managed(&self, identity: &str) -> Option> { + let guard = self.inner.read(); + match node_by_identity(&guard, identity)? { + NodeHandle::Managed(node) => Some(node.clone()), + NodeHandle::Borrowed(_) => None, + } + } + + #[must_use] + /// Finds a borrowed node by canonical identity. + pub fn find_borrowed(&self, identity: &str) -> Option> { + let guard = self.inner.read(); + match node_by_identity(&guard, identity)? { + NodeHandle::Managed(_) => None, + NodeHandle::Borrowed(node) => Some(node.clone()), + } + } + + #[must_use] + /// Finds any node handle by canonical identity. + pub fn find_node(&self, identity: &str) -> Option> { + let guard = self.inner.read(); + node_by_identity(&guard, identity).cloned() + } + + #[must_use] + /// Returns current number of nodes in inventory. + pub fn len(&self) -> usize { + self.inner.read().nodes.len() + } + + #[must_use] + /// Returns true when no nodes are registered. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Clears all nodes and identity indexes. + pub fn clear(&self) { + let mut guard = self.inner.write(); + guard.nodes.clear(); + guard.indices_by_identity.clear(); + guard.next_synthetic_id = 0; + } + + /// Adds or replaces a managed node entry using canonical identity + /// resolution. Re-adding the same node identity updates the stored handle. + pub fn add_managed_node(&self, client: E::NodeClient, identity_hint: Option) { + let mut guard = self.inner.write(); + let identity = canonical_identity::(&client, identity_hint, &mut guard); + let handle = NodeHandle::Managed(ManagedNode { + identity: identity.clone(), + client, + }); + upsert_node(&mut guard, identity, handle); + } + + /// Adds or replaces an attached node entry. + pub fn add_attached_node(&self, client: E::NodeClient, identity_hint: Option) { + self.add_borrowed_node(client, BorrowedOrigin::Attached, identity_hint); + } + + /// Adds or replaces an external static node entry. + pub fn add_external_node(&self, client: E::NodeClient, identity_hint: Option) { + self.add_borrowed_node(client, BorrowedOrigin::External, identity_hint); + } + + /// Executes a synchronous read over a cloned client slice. + pub fn with_clients(&self, f: impl FnOnce(&[E::NodeClient]) -> R) -> R { + let guard = self.inner.read(); + let clients = guard.nodes.iter().map(clone_client).collect::>(); + f(&clients) + } + + fn add_borrowed_node( + &self, + client: E::NodeClient, + origin: BorrowedOrigin, + identity_hint: Option, + ) { + let mut guard = self.inner.write(); + let identity = canonical_identity::(&client, identity_hint, &mut guard); + let handle = NodeHandle::Borrowed(BorrowedNode { + identity: identity.clone(), + client, + origin, + }); + upsert_node(&mut guard, identity, handle); + } +} + +impl ManagedNode { + #[must_use] + /// Returns the node client. + pub const fn client(&self) -> &E::NodeClient { + &self.client + } + + /// Delegates restart to the deployer's control surface for this node name. + pub async fn restart( + &self, + control: &dyn NodeControlHandle, + node_name: &str, + ) -> Result<(), DynError> { + control.restart_node(node_name).await + } + + /// Delegates stop to the deployer's control surface for this node name. + pub async fn stop( + &self, + control: &dyn NodeControlHandle, + node_name: &str, + ) -> Result<(), DynError> { + control.stop_node(node_name).await + } + + /// Delegates dynamic node start with options to the control surface. + pub async fn start_with( + &self, + control: &dyn NodeControlHandle, + node_name: &str, + options: StartNodeOptions, + ) -> Result, DynError> { + control.start_node_with(node_name, options).await + } + + #[must_use] + /// Returns process id if the backend can expose it for this node name. + pub fn pid(&self, control: &dyn NodeControlHandle, node_name: &str) -> Option { + control.node_pid(node_name) + } +} + +impl BorrowedNode { + #[must_use] + /// Returns the node client. + pub const fn client(&self) -> &E::NodeClient { + &self.client + } +} + +fn upsert_node( + inner: &mut NodeInventoryInner, + identity: String, + handle: NodeHandle, +) { + if let Some(existing_index) = inner.indices_by_identity.get(&identity).copied() { + inner.nodes[existing_index] = handle; + return; + } + + let index = inner.nodes.len(); + inner.nodes.push(handle); + inner.indices_by_identity.insert(identity, index); +} + +fn canonical_identity( + client: &E::NodeClient, + identity_hint: Option, + inner: &mut NodeInventoryInner, +) -> String { + // Priority: explicit hint -> app-provided peer id -> endpoint -> synthetic. + if let Some(identity) = identity_hint.filter(|value| !value.trim().is_empty()) { + return identity; + } + + if let Some(identity) = E::node_peer_identity(client) { + return format!("peer:{identity}"); + } + + if let Some(identity) = E::node_endpoint_identity(client) { + return format!("endpoint:{identity}"); + } + + let synthetic = format!("node:{}", inner.next_synthetic_id); + inner.next_synthetic_id += 1; + synthetic +} + +fn clone_client(handle: &NodeHandle) -> E::NodeClient { + match handle { + NodeHandle::Managed(node) => node.client.clone(), + NodeHandle::Borrowed(node) => node.client.clone(), + } +} + +fn node_by_identity<'a, E: Application>( + inner: &'a NodeInventoryInner, + identity: &str, +) -> Option<&'a NodeHandle> { + let index = *inner.indices_by_identity.get(identity)?; + inner.nodes.get(index) +} diff --git a/testing-framework/core/src/scenario/runtime/metrics.rs b/testing-framework/core/src/scenario/runtime/metrics.rs index d94d4cb..e72741f 100644 --- a/testing-framework/core/src/scenario/runtime/metrics.rs +++ b/testing-framework/core/src/scenario/runtime/metrics.rs @@ -77,7 +77,7 @@ impl Metrics { fn require_prometheus(&self) -> Result, MetricsError> { self.prometheus() - .ok_or_else(|| MetricsError::new("prometheus endpoint unavailable")) + .ok_or_else(|| MetricsError::new("prometheus endpoint unavailable".to_string())) } } @@ -122,8 +122,8 @@ pub enum MetricsError { impl MetricsError { #[must_use] - pub fn new(message: impl Into) -> Self { - Self::Store(message.into()) + pub fn new(message: String) -> Self { + Self::Store(message) } } @@ -188,7 +188,7 @@ fn query_prometheus(client: PrometheusClient, query: String) -> Result Vec { diff --git a/testing-framework/core/src/scenario/runtime/mod.rs b/testing-framework/core/src/scenario/runtime/mod.rs index 6b969c7..18147de 100644 --- a/testing-framework/core/src/scenario/runtime/mod.rs +++ b/testing-framework/core/src/scenario/runtime/mod.rs @@ -1,13 +1,17 @@ pub mod context; mod deployer; +pub mod inventory; pub mod metrics; mod node_clients; +pub(crate) mod orchestration; +pub(crate) mod providers; pub mod readiness; mod runner; use async_trait::async_trait; pub use context::{CleanupGuard, RunContext, RunHandle, RunMetrics}; pub use deployer::{Deployer, ScenarioError}; +pub use inventory::{BorrowedNode, BorrowedOrigin, ManagedNode, NodeHandle, NodeInventory}; pub use node_clients::NodeClients; pub use readiness::{ HttpReadinessRequirement, ReadinessError, StabilizationConfig, wait_for_http_ports, diff --git a/testing-framework/core/src/scenario/runtime/node_clients.rs b/testing-framework/core/src/scenario/runtime/node_clients.rs index 9f31122..363e80d 100644 --- a/testing-framework/core/src/scenario/runtime/node_clients.rs +++ b/testing-framework/core/src/scenario/runtime/node_clients.rs @@ -1,23 +1,17 @@ -use std::sync::Arc; - -use parking_lot::RwLock; use rand::{seq::SliceRandom as _, thread_rng}; +use super::inventory::{BorrowedNode, ManagedNode, NodeInventory}; use crate::scenario::{Application, DynError}; /// Collection of API clients for the node set. pub struct NodeClients { - inner: Arc>>, -} - -struct NodeClientsInner { - nodes: Vec, + inventory: NodeInventory, } impl Default for NodeClients { fn default() -> Self { Self { - inner: Arc::new(RwLock::new(NodeClientsInner { nodes: Vec::new() })), + inventory: NodeInventory::default(), } } } @@ -25,7 +19,7 @@ impl Default for NodeClients { impl Clone for NodeClients { fn clone(&self) -> Self { Self { - inner: Arc::clone(&self.inner), + inventory: self.inventory.clone(), } } } @@ -35,7 +29,7 @@ impl NodeClients { /// Build clients from preconstructed vectors. pub fn new(nodes: Vec) -> Self { Self { - inner: Arc::new(RwLock::new(NodeClientsInner { nodes })), + inventory: NodeInventory::from_managed_clients(nodes), } } @@ -45,15 +39,14 @@ impl NodeClients { /// This clones the current vector so callers can iterate across `.await` /// boundaries without holding the internal lock. pub fn snapshot(&self) -> Vec { - self.inner.read().nodes.clone() + self.inventory.snapshot_clients() } /// Execute a synchronous read against the current client slice. /// /// Prefer this over `snapshot()` when no async boundary is involved. pub fn with_clients(&self, f: impl FnOnce(&[E::NodeClient]) -> R) -> R { - let guard = self.inner.read(); - f(&guard.nodes) + self.inventory.with_clients(f) } #[must_use] @@ -64,12 +57,12 @@ impl NodeClients { #[must_use] pub fn len(&self) -> usize { - self.inner.read().nodes.len() + self.inventory.len() } #[must_use] pub fn is_empty(&self) -> bool { - self.len() == 0 + self.inventory.is_empty() } #[must_use] @@ -79,13 +72,35 @@ impl NodeClients { } pub fn add_node(&self, client: E::NodeClient) { - let mut guard = self.inner.write(); - guard.nodes.push(client); + self.inventory.add_managed_node(client, None); } pub fn clear(&self) { - let mut guard = self.inner.write(); - guard.nodes.clear(); + self.inventory.clear(); + } + + #[must_use] + /// Returns a cloned snapshot of managed node handles. + pub fn managed_nodes(&self) -> Vec> { + self.inventory.managed_nodes() + } + + #[must_use] + /// Returns a cloned snapshot of borrowed node handles. + pub fn borrowed_nodes(&self) -> Vec> { + self.inventory.borrowed_nodes() + } + + #[must_use] + /// Finds a managed node by canonical identity. + pub fn find_managed(&self, identity: &str) -> Option> { + self.inventory.find_managed(identity) + } + + #[must_use] + /// Finds a borrowed node by canonical identity. + pub fn find_borrowed(&self, identity: &str) -> Option> { + self.inventory.find_borrowed(identity) } fn shuffled_snapshot(&self) -> Vec { diff --git a/testing-framework/core/src/scenario/runtime/orchestration/mod.rs b/testing-framework/core/src/scenario/runtime/orchestration/mod.rs new file mode 100644 index 0000000..a2da548 --- /dev/null +++ b/testing-framework/core/src/scenario/runtime/orchestration/mod.rs @@ -0,0 +1,6 @@ +#[allow(dead_code)] +mod source_orchestration_plan; + +pub(crate) use source_orchestration_plan::{ + SourceModeName, SourceOrchestrationPlan, SourceOrchestrationPlanError, +}; diff --git a/testing-framework/core/src/scenario/runtime/orchestration/source_orchestration_plan.rs b/testing-framework/core/src/scenario/runtime/orchestration/source_orchestration_plan.rs new file mode 100644 index 0000000..f11b831 --- /dev/null +++ b/testing-framework/core/src/scenario/runtime/orchestration/source_orchestration_plan.rs @@ -0,0 +1,130 @@ +use std::fmt; + +use crate::scenario::{AttachSource, ExternalNodeSource, ScenarioSources, SourceReadinessPolicy}; + +/// Explicit descriptor for managed node sourcing. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum ManagedSource { + /// Nodes are provisioned by the configured deployer. + DeployerManaged, +} + +/// Internal source-orchestration mode derived from scenario source +/// configuration. +/// +/// This is scaffolding-only and is intentionally not executed by deployers +/// yet. +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum SourceOrchestrationMode { + Managed { + managed: ManagedSource, + external: Vec, + }, + Attached { + attach: AttachSource, + external: Vec, + }, + ExternalOnly { + external: Vec, + }, +} + +/// Internal source-orchestration plan used to prepare future deployer wiring. +/// +/// This captures only mapping-time source intent and readiness policy. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct SourceOrchestrationPlan { + pub mode: SourceOrchestrationMode, + pub readiness_policy: SourceReadinessPolicy, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum SourceModeName { + Attached, + ExternalOnly, +} + +impl fmt::Display for SourceModeName { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Attached => f.write_str("Attached"), + Self::ExternalOnly => f.write_str("ExternalOnly"), + } + } +} + +/// Validation failure while building orchestration plan from sources. +#[derive(Debug, thiserror::Error)] +pub enum SourceOrchestrationPlanError { + #[error("managed source selected but deployment produced 0 managed nodes")] + ManagedNodesMissing, + #[error("source mode '{mode}' is not wired into deployers yet")] + SourceModeNotWiredYet { mode: SourceModeName }, +} + +impl SourceOrchestrationPlan { + pub fn try_from_sources( + sources: &ScenarioSources, + managed_node_count: usize, + readiness_policy: SourceReadinessPolicy, + ) -> Result { + ensure_managed_sources_have_nodes(sources, managed_node_count)?; + let mode = mode_from_sources(sources); + + let plan = Self { + mode, + readiness_policy, + }; + + plan.ensure_currently_wired()?; + Ok(plan) + } + + #[must_use] + pub fn external_sources(&self) -> &[ExternalNodeSource] { + match &self.mode { + SourceOrchestrationMode::Managed { external, .. } + | SourceOrchestrationMode::Attached { external, .. } + | SourceOrchestrationMode::ExternalOnly { external } => external, + } + } + + fn ensure_currently_wired(&self) -> Result<(), SourceOrchestrationPlanError> { + match self.mode { + SourceOrchestrationMode::Managed { .. } => Ok(()), + SourceOrchestrationMode::Attached { .. } => not_wired(SourceModeName::Attached), + SourceOrchestrationMode::ExternalOnly { .. } => not_wired(SourceModeName::ExternalOnly), + } + } +} + +fn ensure_managed_sources_have_nodes( + sources: &ScenarioSources, + managed_node_count: usize, +) -> Result<(), SourceOrchestrationPlanError> { + if matches!(sources, ScenarioSources::Managed { .. }) && managed_node_count == 0 { + return Err(SourceOrchestrationPlanError::ManagedNodesMissing); + } + + Ok(()) +} + +fn mode_from_sources(sources: &ScenarioSources) -> SourceOrchestrationMode { + match sources { + ScenarioSources::Managed { external } => SourceOrchestrationMode::Managed { + managed: ManagedSource::DeployerManaged, + external: external.clone(), + }, + ScenarioSources::Attached { attach, external } => SourceOrchestrationMode::Attached { + attach: attach.clone(), + external: external.clone(), + }, + ScenarioSources::ExternalOnly { external } => SourceOrchestrationMode::ExternalOnly { + external: external.clone(), + }, + } +} + +fn not_wired(mode: SourceModeName) -> Result<(), SourceOrchestrationPlanError> { + Err(SourceOrchestrationPlanError::SourceModeNotWiredYet { mode }) +} diff --git a/testing-framework/core/src/scenario/runtime/providers/attach_provider.rs b/testing-framework/core/src/scenario/runtime/providers/attach_provider.rs new file mode 100644 index 0000000..d31bd78 --- /dev/null +++ b/testing-framework/core/src/scenario/runtime/providers/attach_provider.rs @@ -0,0 +1,53 @@ +use async_trait::async_trait; + +use crate::scenario::{Application, AttachSource, DynError}; + +/// Attached node discovered from an existing external cluster source. +#[derive(Clone, Debug)] +pub struct AttachedNode { + /// Optional stable identity hint used by runtime inventory dedup logic. + pub identity_hint: Option, + /// Application-specific client for the discovered node. + pub client: E::NodeClient, +} + +/// Errors returned by attach providers while discovering attached nodes. +#[derive(Debug, thiserror::Error)] +pub enum AttachProviderError { + #[error("attach source is not supported by this provider: {attach_source:?}")] + UnsupportedSource { attach_source: AttachSource }, + #[error("attach discovery failed: {source}")] + Discovery { + #[source] + source: DynError, + }, +} + +/// Internal adapter interface for discovering pre-existing nodes. +/// +/// This is scaffolding-only in phase 1 and is intentionally not wired into +/// deployer runtime orchestration yet. +#[async_trait] +pub trait AttachProvider: Send + Sync { + /// Discovers node clients for the requested attach source. + async fn discover( + &self, + source: &AttachSource, + ) -> Result>, AttachProviderError>; +} + +/// Default attach provider stub used while attach wiring is not implemented. +#[derive(Clone, Copy, Debug, Default)] +pub struct NoopAttachProvider; + +#[async_trait] +impl AttachProvider for NoopAttachProvider { + async fn discover( + &self, + source: &AttachSource, + ) -> Result>, AttachProviderError> { + Err(AttachProviderError::UnsupportedSource { + attach_source: source.clone(), + }) + } +} diff --git a/testing-framework/core/src/scenario/runtime/providers/external_provider.rs b/testing-framework/core/src/scenario/runtime/providers/external_provider.rs new file mode 100644 index 0000000..98578a3 --- /dev/null +++ b/testing-framework/core/src/scenario/runtime/providers/external_provider.rs @@ -0,0 +1,52 @@ +use crate::scenario::{Application, DynError, ExternalNodeSource}; + +/// External node client prepared from a static external source endpoint. +#[derive(Clone, Debug)] +pub struct ExternalNode { + /// Optional stable identity hint used by runtime inventory dedup logic. + pub identity_hint: Option, + /// Application-specific client for the external node endpoint. + pub client: E::NodeClient, +} + +/// Errors returned while constructing node clients from external sources. +#[derive(Debug, thiserror::Error)] +pub enum ExternalProviderError { + #[error("external source is not supported by this provider: {external_source:?}")] + UnsupportedSource { external_source: ExternalNodeSource }, + #[error("failed to build external node from source {source_label}: {source}")] + Build { + source_label: String, + #[source] + source: DynError, + }, +} + +/// Internal adapter interface for constructing node clients from static +/// external endpoint sources. +/// +/// This is scaffolding-only in phase 1 and is intentionally not wired into +/// deployer runtime orchestration yet. +pub trait ExternalProvider: Send + Sync { + /// Builds one external node handle from one external source descriptor. + fn build_node( + &self, + source: &ExternalNodeSource, + ) -> Result, ExternalProviderError>; +} + +/// Default external provider stub used while external wiring is not +/// implemented. +#[derive(Clone, Copy, Debug, Default)] +pub struct NoopExternalProvider; + +impl ExternalProvider for NoopExternalProvider { + fn build_node( + &self, + source: &ExternalNodeSource, + ) -> Result, ExternalProviderError> { + Err(ExternalProviderError::UnsupportedSource { + external_source: source.clone(), + }) + } +} diff --git a/testing-framework/core/src/scenario/runtime/providers/mod.rs b/testing-framework/core/src/scenario/runtime/providers/mod.rs new file mode 100644 index 0000000..a47d7f7 --- /dev/null +++ b/testing-framework/core/src/scenario/runtime/providers/mod.rs @@ -0,0 +1,4 @@ +#[allow(dead_code)] +mod attach_provider; +#[allow(dead_code)] +mod external_provider; diff --git a/testing-framework/core/src/scenario/sources/mod.rs b/testing-framework/core/src/scenario/sources/mod.rs new file mode 100644 index 0000000..3585d8a --- /dev/null +++ b/testing-framework/core/src/scenario/sources/mod.rs @@ -0,0 +1,3 @@ +mod model; + +pub use model::{AttachSource, ExternalNodeSource, ScenarioSources, SourceReadinessPolicy}; diff --git a/testing-framework/core/src/scenario/sources/model.rs b/testing-framework/core/src/scenario/sources/model.rs new file mode 100644 index 0000000..0e14091 --- /dev/null +++ b/testing-framework/core/src/scenario/sources/model.rs @@ -0,0 +1,168 @@ +/// Typed attach source for existing clusters. +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum AttachSource { + K8s { + namespace: Option, + label_selector: String, + }, + Compose { + project: Option, + services: Vec, + }, +} + +impl AttachSource { + #[must_use] + pub fn k8s(label_selector: String) -> Self { + Self::K8s { + namespace: None, + label_selector, + } + } + + #[must_use] + pub fn with_namespace(self, namespace: String) -> Self { + match self { + Self::K8s { label_selector, .. } => Self::K8s { + namespace: Some(namespace), + label_selector, + }, + other => other, + } + } + + #[must_use] + pub fn compose(services: Vec) -> Self { + Self::Compose { + project: None, + services, + } + } + + #[must_use] + pub fn with_project(self, project: String) -> Self { + match self { + Self::Compose { services, .. } => Self::Compose { + project: Some(project), + services, + }, + other => other, + } + } +} + +/// Static external node endpoint that should be included in the runtime +/// inventory. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ExternalNodeSource { + pub label: String, + pub endpoint: String, +} + +impl ExternalNodeSource { + #[must_use] + pub fn new(label: String, endpoint: String) -> Self { + Self { label, endpoint } + } +} + +/// Planned readiness strategy for mixed managed/attached/external sources. +#[derive(Clone, Copy, Debug, Eq, PartialEq, Default)] +pub enum SourceReadinessPolicy { + /// Phase 1 default: require every known node to pass readiness checks. + #[default] + AllReady, + /// Optional relaxed policy for large/partial environments. + Quorum, + /// Future policy for per-source constraints (for example managed minimum + /// plus overall quorum). + SourceAware, +} + +/// Source model that makes invalid managed+attached combinations +/// unrepresentable by type. +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum ScenarioSources { + Managed { + external: Vec, + }, + Attached { + attach: AttachSource, + external: Vec, + }, + ExternalOnly { + external: Vec, + }, +} + +impl Default for ScenarioSources { + fn default() -> Self { + Self::Managed { + external: Vec::new(), + } + } +} + +impl ScenarioSources { + #[must_use] + pub const fn managed() -> Self { + Self::Managed { + external: Vec::new(), + } + } + + #[must_use] + pub fn attached(attach: AttachSource) -> Self { + Self::Attached { + attach, + external: Vec::new(), + } + } + + #[must_use] + pub fn external_only(external: Vec) -> Self { + Self::ExternalOnly { external } + } + + pub fn add_external_node(&mut self, node: ExternalNodeSource) { + match self { + Self::Managed { external } + | Self::Attached { external, .. } + | Self::ExternalOnly { external } => external.push(node), + } + } + + pub fn set_attach(&mut self, attach: AttachSource) { + let external = self.external_nodes().to_vec(); + *self = Self::Attached { attach, external }; + } + + pub fn set_external_only(&mut self) { + let external = self.external_nodes().to_vec(); + *self = Self::ExternalOnly { external }; + } + + #[must_use] + pub fn external_nodes(&self) -> &[ExternalNodeSource] { + match self { + Self::Managed { external } + | Self::Attached { external, .. } + | Self::ExternalOnly { external } => external, + } + } + + #[must_use] + pub const fn is_managed(&self) -> bool { + matches!(self, Self::Managed { .. }) + } + + #[must_use] + pub const fn is_attached(&self) -> bool { + matches!(self, Self::Attached { .. }) + } + + #[must_use] + pub const fn is_external_only(&self) -> bool { + matches!(self, Self::ExternalOnly { .. }) + } +} diff --git a/testing-framework/deployers/compose/src/deployer/orchestrator.rs b/testing-framework/deployers/compose/src/deployer/orchestrator.rs index 1e25b03..206df6f 100644 --- a/testing-framework/deployers/compose/src/deployer/orchestrator.rs +++ b/testing-framework/deployers/compose/src/deployer/orchestrator.rs @@ -222,6 +222,10 @@ async fn build_compose_runtime( input: RuntimeBuildInput<'_, E>, ) -> Result, ComposeRunnerError> { let node_clients = input.deployed.node_clients.clone(); + if node_clients.is_empty() { + return Err(ComposeRunnerError::RuntimePreflight); + } + let (feed, feed_task) = input .deployed .client_builder diff --git a/testing-framework/deployers/compose/src/errors.rs b/testing-framework/deployers/compose/src/errors.rs index 28b222b..8383b33 100644 --- a/testing-framework/deployers/compose/src/errors.rs +++ b/testing-framework/deployers/compose/src/errors.rs @@ -33,6 +33,8 @@ pub enum ComposeRunnerError { Telemetry(#[from] MetricsError), #[error("feed requires at least one node client")] BlockFeedMissing, + #[error("runtime preflight failed: no node clients available")] + RuntimePreflight, #[error("failed to start feed: {source}")] BlockFeed { #[source] diff --git a/testing-framework/deployers/k8s/src/deployer/orchestrator.rs b/testing-framework/deployers/k8s/src/deployer/orchestrator.rs index f784777..b955a4c 100644 --- a/testing-framework/deployers/k8s/src/deployer/orchestrator.rs +++ b/testing-framework/deployers/k8s/src/deployer/orchestrator.rs @@ -92,6 +92,8 @@ pub enum K8sRunnerError { InternalInvariant { message: String }, #[error("k8s runner requires at least one node client for feed data")] BlockFeedMissing, + #[error("runtime preflight failed: no node clients available")] + RuntimePreflight, #[error("failed to initialize feed: {source}")] BlockFeed { #[source] @@ -344,6 +346,15 @@ async fn build_runtime_artifacts( ) -> Result, K8sRunnerError> { info!("building node clients"); let node_clients = build_node_clients_or_fail::(cluster).await?; + if node_clients.is_empty() { + fail_cluster( + cluster, + "runtime preflight failed: no node clients available", + ) + .await; + return Err(K8sRunnerError::RuntimePreflight); + } + let telemetry = build_telemetry_or_fail(cluster, observability).await?; let (feed, feed_task) = spawn_block_feed_or_fail::(cluster, &node_clients).await?; diff --git a/testing-framework/deployers/local/src/deployer/mod.rs b/testing-framework/deployers/local/src/deployer/mod.rs new file mode 100644 index 0000000..d5d75ad --- /dev/null +++ b/testing-framework/deployers/local/src/deployer/mod.rs @@ -0,0 +1,3 @@ +mod orchestrator; + +pub use orchestrator::{ProcessDeployer, ProcessDeployerError}; diff --git a/testing-framework/deployers/local/src/deployer.rs b/testing-framework/deployers/local/src/deployer/orchestrator.rs similarity index 97% rename from testing-framework/deployers/local/src/deployer.rs rename to testing-framework/deployers/local/src/deployer/orchestrator.rs index 972769d..45044cb 100644 --- a/testing-framework/deployers/local/src/deployer.rs +++ b/testing-framework/deployers/local/src/deployer/orchestrator.rs @@ -84,6 +84,8 @@ pub enum ProcessDeployerError { #[source] source: DynError, }, + #[error("runtime preflight failed: no node clients available")] + RuntimePreflight, #[error("expectations failed: {source}")] ExpectationsFailed { #[source] @@ -421,10 +423,8 @@ async fn spawn_feed_with( .map_err(workload_error) } -fn workload_error(source: impl Into) -> ProcessDeployerError { - ProcessDeployerError::WorkloadFailed { - source: source.into(), - } +fn workload_error(source: DynError) -> ProcessDeployerError { + ProcessDeployerError::WorkloadFailed { source } } fn log_local_deploy_start(node_count: usize, policy: DeploymentPolicy, has_node_control: bool) { @@ -449,6 +449,10 @@ async fn run_context_for( expectation_cooldown: Duration, node_control: Option>>, ) -> Result, ProcessDeployerError> { + if node_clients.is_empty() { + return Err(ProcessDeployerError::RuntimePreflight); + } + let (feed, feed_task) = spawn_feed_with::(&node_clients).await?; let context = RunContext::new( descriptors, diff --git a/versions.env b/versions.env index 8080783..bd56449 100644 --- a/versions.env +++ b/versions.env @@ -1,7 +1,7 @@ VERSION=v0.4.1 LOGOS_BLOCKCHAIN_BUNDLE_VERSION=v4 # Pinned logos-blockchain-node revision used for CI builds and binary bundles. -LOGOS_BLOCKCHAIN_NODE_REV=a4275d00eb3041ed6bfb394e0913cd1ad172224c +LOGOS_BLOCKCHAIN_NODE_REV=41ea1e3082526bb271e655cddb95a5b448e7de20 # Local logos-blockchain-node checkout override. -# LOGOS_BLOCKCHAIN_NODE_PATH=/path/to/local/nomos-node +# LOGOS_BLOCKCHAIN_NODE_PATH=