From 94643b5098bbd9134433a3965a8f9f9e6f9ff953 Mon Sep 17 00:00:00 2001 From: Louis Thibault Date: Thu, 12 Feb 2026 19:17:15 -0500 Subject: [PATCH 01/10] Add Membrane RPC bootstrap with epoch-scoped capabilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vendor stem.capnp schema, add membrane.capnp (WetwareSession with Host + Executor), and implement WetwareMembraneServer that issues epoch-scoped sessions via graft(). EpochGuardedHost and EpochGuardedExecutor wrap existing capability impls with epoch validity checks. build_membrane_rpc() bootstraps Membrane instead of bare Host. Additive change — build_peer_rpc() is untouched and still works. --- Cargo.lock | 1732 ++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 1 + build.rs | 11 +- capnp/membrane.capnp | 12 + capnp/stem.capnp | 38 + src/lib.rs | 11 + src/rpc/membrane.rs | 456 +++++++++++ src/rpc/mod.rs | 7 +- 8 files changed, 2193 insertions(+), 75 deletions(-) create mode 100644 capnp/membrane.capnp create mode 100644 capnp/stem.capnp create mode 100644 src/rpc/membrane.rs diff --git a/Cargo.lock b/Cargo.lock index c0f8a9bb..61887452 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,82 +67,722 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "alloy" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "056f2c01b2aed86e15b43c47d109bfc8b82553dc34e66452875e51247ec31ab2" +dependencies = [ + "alloy-consensus", + "alloy-core", + "alloy-eips", + "alloy-genesis", + "alloy-provider", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-serde", + "alloy-transport-http", +] + +[[package]] +name = "alloy-chains" +version = "0.1.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28e2652684758b0d9b389d248b209ed9fd9989ef489a550265fe4bb8454fe7eb" +dependencies = [ + "alloy-primitives", + "num_enum", + "strum", +] + +[[package]] +name = "alloy-consensus" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "705687d5bfd019fee57cf9e206b27b30a9a9617535d5590a02b171e813208f8e" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "auto_impl", + "c-kzg", + "derive_more 1.0.0", + "serde", +] + +[[package]] +name = "alloy-core" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f1ab91967646311bb7dd32db4fee380c69fe624319dcd176b89fb2a420c6b5" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-rlp", + "alloy-sol-types", +] + +[[package]] +name = "alloy-dyn-abi" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf69d3061e2e908a4370bda5d8d6529d5080232776975489eec0b49ce971027e" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-type-parser", + "alloy-sol-types", + "const-hex", + "itoa", + "serde", + "serde_json", + "winnow", +] + +[[package]] +name = "alloy-eip2930" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-eip7702" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea59dc42102bc9a1905dc57901edc6dd48b9f38115df86c7d252acba70d71d04" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-eips" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ffb906284a1e1f63c4607da2068c8197458a352d0b3e9796e67353d72a9be85" +dependencies = [ + "alloy-eip2930", + "alloy-eip7702", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "c-kzg", + "derive_more 1.0.0", + "once_cell", + "serde", + "sha2", +] + +[[package]] +name = "alloy-genesis" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8429cf4554eed9b40feec7f4451113e76596086447550275e3def933faf47ce3" +dependencies = [ + "alloy-primitives", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-json-abi" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4584e3641181ff073e9d5bec5b3b8f78f9749d9fb108a1cfbc4399a4a139c72a" +dependencies = [ + "alloy-primitives", + "alloy-sol-type-parser", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-json-rpc" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fa8a1a3c4cbd221f2b8e3693aeb328fca79a757fe556ed08e47bbbc2a70db7" +dependencies = [ + "alloy-primitives", + "alloy-sol-types", + "serde", + "serde_json", + "thiserror 1.0.69", + "tracing", +] + +[[package]] +name = "alloy-network" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85fa23a6a9d612b52e402c995f2d582c25165ec03ac6edf64c861a76bc5b87cd" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "alloy-signer", + "alloy-sol-types", + "async-trait", + "auto_impl", + "futures-utils-wasm", + "thiserror 1.0.69", +] + +[[package]] +name = "alloy-network-primitives" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801492711d4392b2ccf5fc0bc69e299fa1aab15167d74dcaa9aab96a54f684bd" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-primitives" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777d58b30eb9a4db0e5f59bc30e8c2caef877fee7dc8734cf242a51a60f22e05" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more 2.1.1", + "foldhash", + "hashbrown 0.15.5", + "indexmap", + "itoa", + "k256", + "keccak-asm", + "paste", + "proptest", + "rand 0.8.5", + "ruint", + "rustc-hash", + "serde", + "sha3", + "tiny-keccak", +] + +[[package]] +name = "alloy-provider" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcfaa4ffec0af04e3555686b8aacbcdf7d13638133a0672749209069750f78a6" +dependencies = [ + "alloy-chains", + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rpc-client", + "alloy-rpc-types-eth", + "alloy-transport", + "alloy-transport-http", + "async-stream", + "async-trait", + "auto_impl", + "dashmap", + "futures", + "futures-utils-wasm", + "lru", + "pin-project", + "reqwest", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e93e50f64a77ad9c5470bf2ad0ca02f228da70c792a8f06634801e202579f35e" +dependencies = [ + "alloy-rlp-derive", + "arrayvec", + "bytes", +] + +[[package]] +name = "alloy-rlp-derive" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8849c74c9ca0f5a03da1c865e3eb6f768df816e67dd3721a398a8a7e398011" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "alloy-rpc-client" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "370143ed581aace6e663342d21d209c6b2e34ee6142f7d6675adb518deeaf0dc" +dependencies = [ + "alloy-json-rpc", + "alloy-primitives", + "alloy-transport", + "alloy-transport-http", + "futures", + "pin-project", + "reqwest", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", + "url", +] + +[[package]] +name = "alloy-rpc-types" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ffc534b7919e18f35e3aa1f507b6f3d9d92ec298463a9f6beaac112809d8d06" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-rpc-types-eth" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413f4aa3ccf2c3e4234a047c5fa4727916d7daf25a89f9b765df0ba09784fd87" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-sol-types", + "derive_more 1.0.0", + "itertools 0.13.0", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-serde" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dff0ab1cdd43ca001e324dc27ee0e8606bd2161d6623c63e0e0b8c4dfc13600" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd4e0ad79c81a27ca659be5d176ca12399141659fef2bcbfdc848da478f4504" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "elliptic-curve", + "k256", + "thiserror 1.0.69", +] + +[[package]] +name = "alloy-sol-macro" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e68b32b6fa0d09bb74b4cefe35ccc8269d711c26629bc7cd98a47eeb12fe353f" +dependencies = [ + "alloy-sol-macro-expander", + "alloy-sol-macro-input", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "alloy-sol-macro-expander" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2afe6879ac373e58fd53581636f2cce843998ae0b058ebe1e4f649195e2bd23c" +dependencies = [ + "alloy-sol-macro-input", + "const-hex", + "heck", + "indexmap", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.110", + "syn-solidity", + "tiny-keccak", +] + +[[package]] +name = "alloy-sol-macro-input" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ba01aee235a8c699d07e5be97ba215607564e71be72f433665329bec307d28" +dependencies = [ + "const-hex", + "dunce", + "heck", + "macro-string", + "proc-macro2", + "quote", + "syn 2.0.110", + "syn-solidity", +] + +[[package]] +name = "alloy-sol-type-parser" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c13fc168b97411e04465f03e632f31ef94cad1c7c8951bf799237fd7870d535" +dependencies = [ + "serde", + "winnow", +] + +[[package]] +name = "alloy-sol-types" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e960c4b52508ef2ae1e37cae5058e905e9ae099b107900067a503f8c454036f" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-macro", + "const-hex", + "serde", +] + +[[package]] +name = "alloy-transport" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ac3e97dad3d31770db0fc89bd6a63b789fbae78963086733f960cf32c483904" +dependencies = [ + "alloy-json-rpc", + "base64 0.22.1", + "futures-util", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tower", + "tracing", + "url", +] + +[[package]] +name = "alloy-transport-http" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b367dcccada5b28987c2296717ee04b9a5637aacd78eacb1726ef211678b5212" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "reqwest", + "serde_json", + "tower", + "tracing", + "url", +] + [[package]] name = "ambient-authority" version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" +checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.1", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" +dependencies = [ + "ark-ff-asm 0.5.0", + "ark-ff-macros 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "arrayvec", + "digest 0.10.7", + "educe", + "itertools 0.13.0", + "num-bigint", + "num-traits", + "paste", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" +dependencies = [ + "quote", + "syn 2.0.110", +] [[package]] -name = "android_system_properties" -version = "0.1.5" +name = "ark-ff-macros" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" dependencies = [ - "libc", + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", ] [[package]] -name = "anstream" -version = "0.6.21" +name = "ark-ff-macros" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "anstyle" -version = "1.0.13" +name = "ark-ff-macros" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.110", +] [[package]] -name = "anstyle-parse" -version = "0.2.7" +name = "ark-serialize" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" dependencies = [ - "utf8parse", + "ark-std 0.3.0", + "digest 0.9.0", ] [[package]] -name = "anstyle-query" -version = "1.1.5" +name = "ark-serialize" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" dependencies = [ - "windows-sys 0.61.2", + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint", ] [[package]] -name = "anstyle-wincon" -version = "3.0.11" +name = "ark-serialize" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" dependencies = [ - "anstyle", - "once_cell_polyfill", - "windows-sys 0.61.2", + "ark-std 0.5.0", + "arrayvec", + "digest 0.10.7", + "num-bigint", ] [[package]] -name = "anyhow" -version = "1.0.100" +name = "ark-std" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand 0.8.5", +] [[package]] -name = "arbitrary" -version = "1.4.2" +name = "ark-std" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "ark-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" +dependencies = [ + "num-traits", + "rand 0.8.5", +] [[package]] name = "arrayref" @@ -150,6 +790,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "asn1-rs" version = "0.7.1" @@ -224,6 +870,28 @@ dependencies = [ "syn 2.0.110", ] +[[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.110", +] + [[package]] name = "async-trait" version = "0.1.89" @@ -271,12 +939,23 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c7bf8143dfc3c0258df908843e169b5cc5fcf76c7718bd66135ef4a9cd558c5" dependencies = [ - "semver", + "semver 1.0.27", "serde", "serde_json", "topological-sort", ] +[[package]] +name = "auto_impl" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + [[package]] name = "autocfg" version = "1.5.0" @@ -289,6 +968,12 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base256emoji" version = "1.0.2" @@ -323,6 +1008,21 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + [[package]] name = "bitflags" version = "1.3.2" @@ -344,13 +1044,25 @@ dependencies = [ "typenum", ] +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "blake2" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] @@ -362,6 +1074,18 @@ dependencies = [ "generic-array", ] +[[package]] +name = "blst" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcdb4c7013139a150f9fc55d123186dbfaba0d912817466282c73ac49e71fb45" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + [[package]] name = "bs58" version = "0.5.1" @@ -380,6 +1104,12 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "byte-slice-cast" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" + [[package]] name = "byteorder" version = "1.5.0" @@ -391,6 +1121,24 @@ name = "bytes" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +dependencies = [ + "serde", +] + +[[package]] +name = "c-kzg" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0307f72feab3300336fb803a57134159f6e20139af1357f36c54cb90d8e8928" +dependencies = [ + "blst", + "cc", + "glob", + "hex", + "libc", + "once_cell", + "serde", +] [[package]] name = "cap-fs-ext" @@ -676,6 +1424,18 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "const-hex" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bb320cac8a0750d7f25280aa97b09c26edfe161164238ecbbb31092b079e735" +dependencies = [ + "cfg-if", + "cpufeatures", + "proptest", + "serde_core", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -688,6 +1448,35 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f421161cb492475f1661ddc9815a745a1c894592070661180fdec3d4872e9c3" +[[package]] +name = "const_format" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -918,6 +1707,18 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.7" @@ -947,9 +1748,9 @@ dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", - "digest", + "digest 0.10.7", "fiat-crypto", - "rustc_version", + "rustc_version 0.4.1", "subtle", "zeroize", ] @@ -965,6 +1766,20 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "data-encoding" version = "2.9.0" @@ -1011,26 +1826,90 @@ dependencies = [ ] [[package]] -name = "der-parser" -version = "10.0.0" +name = "der-parser" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "deranged" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl 1.0.0", +] + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl 2.1.1", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", + "unicode-xid", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ - "asn1-rs", - "displaydoc", - "nom", - "num-bigint", - "num-traits", - "rusticata-macros", + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.1", + "syn 2.0.110", + "unicode-xid", ] [[package]] -name = "deranged" -version = "0.5.5" +name = "digest" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "powerfmt", + "generic-array", ] [[package]] @@ -1040,6 +1919,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", "subtle", ] @@ -1102,6 +1982,26 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + [[package]] name = "ed25519" version = "2.2.3" @@ -1126,12 +2026,43 @@ dependencies = [ "zeroize", ] +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.110", +] + [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "embedded-io" version = "0.4.0" @@ -1171,6 +2102,26 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "enum-ordinalize" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -1199,6 +2150,28 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "fastrlp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + [[package]] name = "fd-lock" version = "4.0.4" @@ -1210,6 +2183,16 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "fiat-crypto" version = "0.2.9" @@ -1222,6 +2205,18 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand 0.8.5", + "rustc-hex", + "static_assertions", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -1285,6 +2280,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures" version = "0.3.31" @@ -1412,6 +2413,12 @@ dependencies = [ "slab", ] +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + [[package]] name = "fxprof-processed-profile" version = "0.8.1" @@ -1434,6 +2441,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1484,6 +2492,23 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "h2" version = "0.3.27" @@ -1522,6 +2547,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + [[package]] name = "hashbrown" version = "0.15.5" @@ -1620,7 +2651,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest", + "digest 0.10.7", ] [[package]] @@ -2008,6 +3039,26 @@ dependencies = [ "version_check", ] +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + [[package]] name = "indexmap" version = "2.12.0" @@ -2121,6 +3172,24 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.14.0" @@ -2176,6 +3245,38 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "keccak-asm" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b646a74e746cd25045aa0fd42f4f7f78aa6d119380182c7e63a5593c4ab8df6f" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -2366,7 +3467,7 @@ dependencies = [ "smallvec", "thiserror 2.0.17", "tracing", - "uint", + "uint 0.10.0", "web-time", ] @@ -2635,6 +3736,17 @@ dependencies = [ "libc", ] +[[package]] +name = "macro-string" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + [[package]] name = "match-lookup" version = "0.1.1" @@ -2740,7 +3852,7 @@ dependencies = [ "equivalent", "parking_lot", "portable-atomic", - "rustc_version", + "rustc_version 0.4.1", "smallvec", "tagptr", "uuid", @@ -2823,7 +3935,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d6d4752e6230d8ef7adf7bd5d8c4b1f6561c1014c5ba9a37445ccefe18aa1db" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.1.3", "proc-macro-error", "proc-macro2", "quote", @@ -3007,6 +4119,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -3019,6 +4132,27 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + [[package]] name = "object" version = "0.37.3" @@ -3102,6 +4236,34 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "parity-scale-codec" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "const_format", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "rustversion", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" +dependencies = [ + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote", + "syn 2.0.110", +] + [[package]] name = "parking" version = "2.2.1" @@ -3153,6 +4315,16 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pest" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" +dependencies = [ + "memchr", + "ucd-trie", +] + [[package]] name = "petgraph" version = "0.6.5" @@ -3313,6 +4485,17 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "uint 0.9.5", +] + [[package]] name = "proc-macro-crate" version = "1.1.3" @@ -3323,6 +4506,15 @@ dependencies = [ "toml 0.5.11", ] +[[package]] +name = "proc-macro-crate" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -3347,6 +4539,28 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.110", +] + [[package]] name = "proc-macro2" version = "1.0.103" @@ -3379,6 +4593,25 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "proptest" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37566cb3fdacef14c0737f9546df7cfeadbfbc9fef10991038bf5015d0c80532" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags 2.10.0", + "num-traits", + "rand 0.9.2", + "rand_chacha 0.9.0", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + [[package]] name = "pulley-interpreter" version = "40.0.2" @@ -3402,6 +4635,12 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quick-protobuf" version = "0.8.1" @@ -3495,6 +4734,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.8.5" @@ -3504,6 +4749,7 @@ dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", + "serde", ] [[package]] @@ -3554,6 +4800,15 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core 0.9.3", +] + [[package]] name = "rand_xoshiro" version = "0.6.0" @@ -3693,6 +4948,16 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "ring" version = "0.17.14" @@ -3707,6 +4972,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + [[package]] name = "rtnetlink" version = "0.13.1" @@ -3725,6 +5000,40 @@ dependencies = [ "tokio", ] +[[package]] +name = "ruint" +version = "1.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c141e807189ad38a07276942c6623032d3753c8859c146104ac2e4d68865945a" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "ark-ff 0.5.0", + "bytes", + "fastrlp 0.3.1", + "fastrlp 0.4.0", + "num-bigint", + "num-integer", + "num-traits", + "parity-scale-codec", + "primitive-types", + "proptest", + "rand 0.8.5", + "rand 0.9.2", + "rlp", + "ruint-macro", + "serde_core", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + [[package]] name = "rustc-demangle" version = "0.1.26" @@ -3737,13 +5046,28 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver", + "semver 1.0.27", ] [[package]] @@ -3832,6 +5156,18 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "rusty-fork" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + [[package]] name = "rw-stream-sink" version = "0.4.0" @@ -3873,6 +5209,20 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "security-framework" version = "2.11.1" @@ -3896,6 +5246,15 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.27" @@ -3906,6 +5265,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "semver-parser" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +dependencies = [ + "pest", +] + [[package]] name = "serde" version = "1.0.228" @@ -3983,6 +5351,17 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + [[package]] name = "sha2" version = "0.10.9" @@ -3991,7 +5370,27 @@ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sha3-asm" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b31139435f327c93c6038ed350ae4588e2c70a13d50599509fee6349967ba35a" +dependencies = [ + "cc", + "cfg-if", ] [[package]] @@ -4033,6 +5432,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ + "digest 0.10.7", "rand_core 0.6.4", ] @@ -4079,7 +5479,7 @@ dependencies = [ "curve25519-dalek", "rand_core 0.6.4", "ring", - "rustc_version", + "rustc_version 0.4.1", "sha2", "subtle", ] @@ -4135,12 +5535,56 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "stem" +version = "0.1.0" +dependencies = [ + "alloy", + "anyhow", + "capnp", + "capnp-rpc", + "capnpc", + "futures-util", + "hex", + "rand 0.8.5", + "reqwest", + "serde", + "serde_json", + "sha3", + "thiserror 1.0.69", + "tokio", + "tokio-tungstenite", + "tracing", + "tracing-subscriber", +] + [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.110", +] + [[package]] name = "subtle" version = "2.6.1" @@ -4169,6 +5613,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn-solidity" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab4e6eed052a117409a1a744c8bda9c3ea6934597cf7419f791cb7d590871c4c" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.110", +] + [[package]] name = "sync_wrapper" version = "1.0.2" @@ -4244,6 +5700,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "target-lexicon" version = "0.13.3" @@ -4321,6 +5783,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + [[package]] name = "time" version = "0.3.44" @@ -4352,6 +5823,15 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinystr" version = "0.8.2" @@ -4425,6 +5905,30 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite", +] + [[package]] name = "tokio-util" version = "0.7.17" @@ -4472,6 +5976,18 @@ dependencies = [ "serde_core", ] +[[package]] +name = "toml_edit" +version = "0.23.10+spec-1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + [[package]] name = "toml_parser" version = "1.0.6+spec-1.1.0" @@ -4605,12 +6121,48 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http 1.3.1", + "httparse", + "log", + "rand 0.8.5", + "sha1", + "thiserror 1.0.69", + "utf-8", +] + [[package]] name = "typenum" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "uint" version = "0.10.0" @@ -4623,6 +6175,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicase" version = "2.8.1" @@ -4635,6 +6193,12 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + [[package]] name = "unicode-width" version = "0.2.2" @@ -4693,6 +6257,12 @@ dependencies = [ "serde", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf8_iter" version = "1.0.4" @@ -4734,6 +6304,15 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -4905,7 +6484,7 @@ dependencies = [ "bitflags 2.10.0", "hashbrown 0.15.5", "indexmap", - "semver", + "semver 1.0.27", ] [[package]] @@ -4917,7 +6496,7 @@ dependencies = [ "bitflags 2.10.0", "hashbrown 0.15.5", "indexmap", - "semver", + "semver 1.0.27", "serde", ] @@ -4929,7 +6508,7 @@ checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags 2.10.0", "indexmap", - "semver", + "semver 1.0.27", ] [[package]] @@ -4973,7 +6552,7 @@ dependencies = [ "pulley-interpreter", "rayon", "rustix 1.1.2", - "semver", + "semver 1.0.27", "serde", "serde_derive", "serde_json", @@ -5016,7 +6595,7 @@ dependencies = [ "object", "postcard", "rustc-demangle", - "semver", + "semver 1.0.27", "serde", "serde_derive", "smallvec", @@ -5082,7 +6661,7 @@ dependencies = [ "cranelift-frontend", "cranelift-native", "gimli", - "itertools", + "itertools 0.14.0", "log", "object", "pulley-interpreter", @@ -5743,6 +7322,9 @@ name = "winnow" version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +dependencies = [ + "memchr", +] [[package]] name = "winreg" @@ -5865,7 +7447,7 @@ dependencies = [ "id-arena", "indexmap", "log", - "semver", + "semver 1.0.27", "serde", "serde_derive", "serde_json", @@ -5883,7 +7465,7 @@ dependencies = [ "id-arena", "indexmap", "log", - "semver", + "semver 1.0.27", "serde", "serde_derive", "serde_json", @@ -5933,6 +7515,7 @@ dependencies = [ "reqwest", "serde", "serde_json", + "stem", "tempfile", "tokio", "tokio-util", @@ -5943,6 +7526,15 @@ dependencies = [ "wasmtime-wasi-io", ] +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "x25519-dalek" version = "2.0.1" diff --git a/Cargo.toml b/Cargo.toml index 4f0e742c..d1e18a1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ wasmtime-wasi = "40.0.0" wasmtime-wasi-io = "40.0.0" capnp = "0.23.2" capnp-rpc = "0.23.0" +stem = { path = "../stem/crates/stem" } [[bin]] name = "ww" diff --git a/build.rs b/build.rs index c9f064bf..ca97490f 100644 --- a/build.rs +++ b/build.rs @@ -6,7 +6,9 @@ fn main() { let manifest_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"); let target_dir = Path::new(&manifest_dir).join("target"); let cid_file = target_dir.join("default-config.cid"); - let capnp_file = Path::new(&manifest_dir).join("capnp").join("peer.capnp"); + let capnp_dir = Path::new(&manifest_dir).join("capnp"); + let capnp_file = capnp_dir.join("peer.capnp"); + let membrane_file = capnp_dir.join("membrane.capnp"); // Read CID from the generated .cid file in target directory let cid_value = if cid_file.exists() { @@ -37,9 +39,14 @@ fn main() { println!("cargo:rustc-env=DEFAULT_KERNEL_CID={cid_value}"); println!("cargo:rerun-if-changed={}", cid_file.display()); + let stem_file = capnp_dir.join("stem.capnp"); capnpc::CompilerCommand::new() .file(&capnp_file) + .file(&membrane_file) + .file(&stem_file) .run() - .expect("failed to compile capnp schema"); + .expect("failed to compile capnp schemas"); println!("cargo:rerun-if-changed={}", capnp_file.display()); + println!("cargo:rerun-if-changed={}", membrane_file.display()); + println!("cargo:rerun-if-changed={}", stem_file.display()); } diff --git a/capnp/membrane.capnp b/capnp/membrane.capnp new file mode 100644 index 00000000..6dd7f33d --- /dev/null +++ b/capnp/membrane.capnp @@ -0,0 +1,12 @@ +@0xa59e04af26eca82f; + +using Stem = import "stem.capnp"; +using Peer = import "peer.capnp"; + +struct WetwareSession { + host @0 :Peer.Host; + executor @1 :Peer.Executor; +} + +# The bootstrap type for wetware guests is Stem.Membrane(WetwareSession). +# No new interface needed — we use stem's generic Membrane directly. diff --git a/capnp/stem.capnp b/capnp/stem.capnp new file mode 100644 index 00000000..54cb7ef3 --- /dev/null +++ b/capnp/stem.capnp @@ -0,0 +1,38 @@ +@0x9bce094a026970c4; + +struct Epoch { + seq @0 :UInt64; # Monotonic epoch sequence number (from Stem.seq). + head @1 :Data; # Opaque head bytes from the Stem contract. + adoptedBlock @2 :UInt64;# Block number at which this epoch was adopted. +} + +enum Status { + ok @0; # Operation succeeded under the current epoch. + unauthorized @1; # Caller not authorized under current policy. + internalError @2; # Unexpected internal failure. +} + +interface Signer { + sign @0 (domain :Text, nonce :UInt64) -> (sig :Data); + # Sign an arbitrary nonce under a given domain string. +} + +interface StatusPoller { + pollStatus @0 () -> (status :Status); +} + +struct Session(Extension) { + issuedEpoch @0 :Epoch; + # Epoch under which this session was minted. + + statusPoller @1 :StatusPoller; + # Capability for polling session status. Can be withheld (client receives null capability). + + extension @2 :Extension; + # Platform-specific capabilities scoped to this session. +} + +interface Membrane(SessionExt) { + graft @0 (signer :Signer) -> (session :Session(SessionExt)); + # Graft a signer to the membrane, establishing an epoch-scoped session. +} diff --git a/src/lib.rs b/src/lib.rs index 925ee4c6..c419e812 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,9 +15,20 @@ pub mod loaders; #[cfg(not(target_arch = "wasm32"))] pub mod rpc; #[cfg(not(target_arch = "wasm32"))] +#[allow(unused_parens)] pub mod peer_capnp { include!(concat!(env!("OUT_DIR"), "/capnp/peer_capnp.rs")); } +#[cfg(not(target_arch = "wasm32"))] +#[allow(unused_parens)] +pub mod membrane_capnp { + include!(concat!(env!("OUT_DIR"), "/capnp/membrane_capnp.rs")); +} +#[cfg(not(target_arch = "wasm32"))] +#[allow(unused_parens)] +pub mod stem_capnp { + include!(concat!(env!("OUT_DIR"), "/capnp/stem_capnp.rs")); +} // Modules available for both host and guest pub mod config; diff --git a/src/rpc/membrane.rs b/src/rpc/membrane.rs new file mode 100644 index 00000000..f2e0c53e --- /dev/null +++ b/src/rpc/membrane.rs @@ -0,0 +1,456 @@ +//! Membrane-based RPC bootstrap: epoch-scoped Host + Executor capabilities. +//! +//! Instead of bootstrapping a bare `Host`, the membrane provides an epoch-scoped +//! `Session(WetwareSession)` containing `Host`, `Executor`, and `StatusPoller`. +//! All capabilities fail with `staleEpoch` when the epoch advances. +//! +//! We re-implement the Membrane and StatusPoller servers here against +//! `crate::stem_capnp` (rs's own codegen) because stem's `MembraneServer` +//! implements `stem::stem_capnp::membrane::Server` — a distinct trait from +//! `crate::stem_capnp::membrane::Server` even though both are generated from +//! the same schema. We reuse stem's `Epoch` and `EpochGuard` (plain Rust types). + +use capnp::capability::Promise; +use capnp_rpc::pry; +use capnp_rpc::rpc_twoparty_capnp::Side; +use capnp_rpc::twoparty::VatNetwork; +use capnp_rpc::RpcSystem; +use stem::membrane::{Epoch, EpochGuard}; +use tokio::io::{AsyncRead, AsyncWrite}; +use tokio::sync::{mpsc, watch}; +use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}; + +use crate::host::SwarmCommand; +use crate::membrane_capnp; +use crate::peer_capnp; +use crate::stem_capnp; +use crate::rpc::{ + read_data_result, read_text_list_result, ByteStreamImpl, NetworkState, ProcessImpl, StreamMode, +}; + +use super::ProcBuilder; + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +/// Fill an epoch builder from our crate's stem_capnp (not stem's). +fn fill_epoch(builder: &mut stem_capnp::epoch::Builder<'_>, epoch: &Epoch) { + builder.set_seq(epoch.seq); + builder.set_adopted_block(epoch.adopted_block); + let head_builder = builder.reborrow().init_head(epoch.head.len() as u32); + head_builder.copy_from_slice(epoch.head.as_slice()); +} + +// --------------------------------------------------------------------------- +// StatusPoller (local impl against crate::stem_capnp) +// --------------------------------------------------------------------------- + +struct StatusPollerImpl { + guard: EpochGuard, +} + +#[allow(refining_impl_trait)] +impl stem_capnp::status_poller::Server for StatusPollerImpl { + fn poll_status( + self: capnp::capability::Rc, + _: stem_capnp::status_poller::PollStatusParams, + mut results: stem_capnp::status_poller::PollStatusResults, + ) -> Promise<(), capnp::Error> { + if let Err(e) = self.guard.check() { + return Promise::err(e); + } + results.get().set_status(stem_capnp::Status::Ok); + Promise::ok(()) + } +} + +// --------------------------------------------------------------------------- +// WetwareMembraneServer +// --------------------------------------------------------------------------- + +/// Membrane server that issues sessions containing epoch-guarded Host + Executor. +pub struct WetwareMembraneServer { + epoch_rx: watch::Receiver, + network_state: NetworkState, + swarm_cmd_tx: mpsc::Sender, + wasm_debug: bool, +} + +impl WetwareMembraneServer { + pub fn new( + epoch_rx: watch::Receiver, + network_state: NetworkState, + swarm_cmd_tx: mpsc::Sender, + wasm_debug: bool, + ) -> Self { + Self { + epoch_rx, + network_state, + swarm_cmd_tx, + wasm_debug, + } + } +} + +#[allow(refining_impl_trait)] +impl stem_capnp::membrane::Server + for WetwareMembraneServer +{ + fn graft( + self: capnp::capability::Rc, + _params: stem_capnp::membrane::GraftParams, + mut results: stem_capnp::membrane::GraftResults, + ) -> Promise<(), capnp::Error> { + let epoch = self.epoch_rx.borrow().clone(); + let guard = EpochGuard { + issued_seq: epoch.seq, + receiver: self.epoch_rx.clone(), + }; + + let mut session = results.get().init_session(); + + // Fill issued epoch + fill_epoch(&mut session.reborrow().init_issued_epoch(), &epoch); + + // Set status poller + let poller: stem_capnp::status_poller::Client = + capnp_rpc::new_client(StatusPollerImpl { + guard: guard.clone(), + }); + session.reborrow().set_status_poller(poller); + + // Fill extension (WetwareSession: Host + Executor) + let mut ext = session.reborrow().init_extension(); + let host: peer_capnp::host::Client = capnp_rpc::new_client(EpochGuardedHost::new( + self.network_state.clone(), + self.swarm_cmd_tx.clone(), + self.wasm_debug, + guard.clone(), + )); + ext.set_host(host); + + let executor: peer_capnp::executor::Client = + capnp_rpc::new_client(EpochGuardedExecutor::new( + self.network_state.clone(), + self.swarm_cmd_tx.clone(), + self.wasm_debug, + guard, + )); + ext.set_executor(executor); + + Promise::ok(()) + } +} + +// --------------------------------------------------------------------------- +// EpochGuardedHost +// --------------------------------------------------------------------------- + +/// Host capability that checks epoch validity before each RPC call. +pub struct EpochGuardedHost { + network_state: NetworkState, + swarm_cmd_tx: mpsc::Sender, + wasm_debug: bool, + guard: EpochGuard, +} + +impl EpochGuardedHost { + pub fn new( + network_state: NetworkState, + swarm_cmd_tx: mpsc::Sender, + wasm_debug: bool, + guard: EpochGuard, + ) -> Self { + Self { + network_state, + swarm_cmd_tx, + wasm_debug, + guard, + } + } +} + +#[allow(refining_impl_trait)] +impl peer_capnp::host::Server for EpochGuardedHost { + fn id( + self: capnp::capability::Rc, + _params: peer_capnp::host::IdParams, + mut results: peer_capnp::host::IdResults, + ) -> Promise<(), capnp::Error> { + pry!(self.guard.check()); + let network_state = self.network_state.clone(); + Promise::from_future(async move { + let snapshot = network_state.snapshot().await; + results.get().set_peer_id(&snapshot.local_peer_id); + Ok(()) + }) + } + + fn addrs( + self: capnp::capability::Rc, + _params: peer_capnp::host::AddrsParams, + mut results: peer_capnp::host::AddrsResults, + ) -> Promise<(), capnp::Error> { + pry!(self.guard.check()); + let network_state = self.network_state.clone(); + Promise::from_future(async move { + let snapshot = network_state.snapshot().await; + let mut list = results.get().init_addrs(snapshot.listen_addrs.len() as u32); + for (i, addr) in snapshot.listen_addrs.iter().enumerate() { + list.set(i as u32, addr); + } + Ok(()) + }) + } + + fn peers( + self: capnp::capability::Rc, + _params: peer_capnp::host::PeersParams, + mut results: peer_capnp::host::PeersResults, + ) -> Promise<(), capnp::Error> { + pry!(self.guard.check()); + let network_state = self.network_state.clone(); + Promise::from_future(async move { + let snapshot = network_state.snapshot().await; + let mut list = results.get().init_peers(snapshot.known_peers.len() as u32); + for (i, peer) in snapshot.known_peers.iter().enumerate() { + let mut entry = list.reborrow().get(i as u32); + entry.set_peer_id(&peer.peer_id); + let mut addrs = entry.init_addrs(peer.addrs.len() as u32); + for (j, addr) in peer.addrs.iter().enumerate() { + addrs.set(j as u32, addr); + } + } + Ok(()) + }) + } + + fn connect( + self: capnp::capability::Rc, + params: peer_capnp::host::ConnectParams, + _results: peer_capnp::host::ConnectResults, + ) -> Promise<(), capnp::Error> { + pry!(self.guard.check()); + let params_reader = pry!(params.get()); + let peer_id_bytes = read_data_result(params_reader.get_peer_id()); + let addrs_bytes: Vec> = match params_reader.get_addrs() { + Ok(list) => (0..list.len()) + .filter_map(|i| list.get(i).ok().map(|d| d.to_vec())) + .collect(), + Err(_) => Vec::new(), + }; + let swarm_cmd_tx = self.swarm_cmd_tx.clone(); + Promise::from_future(async move { + use libp2p::{Multiaddr, PeerId}; + + let peer_id = PeerId::from_bytes(&peer_id_bytes) + .map_err(|e| capnp::Error::failed(format!("invalid peer ID: {e}")))?; + + let addrs: Vec = addrs_bytes + .iter() + .filter_map(|bytes| Multiaddr::try_from(bytes.clone()).ok()) + .collect(); + + let (reply_tx, reply_rx) = tokio::sync::oneshot::channel(); + swarm_cmd_tx + .send(SwarmCommand::Connect { + peer_id, + addrs, + reply: reply_tx, + }) + .await + .map_err(|_| capnp::Error::failed("swarm channel closed".into()))?; + + reply_rx + .await + .map_err(|_| capnp::Error::failed("swarm reply dropped".into()))? + .map_err(|e| capnp::Error::failed(format!("connect failed: {e}")))?; + + Ok(()) + }) + } + + fn executor( + self: capnp::capability::Rc, + _params: peer_capnp::host::ExecutorParams, + mut results: peer_capnp::host::ExecutorResults, + ) -> Promise<(), capnp::Error> { + pry!(self.guard.check()); + let executor: peer_capnp::executor::Client = + capnp_rpc::new_client(EpochGuardedExecutor::new( + self.network_state.clone(), + self.swarm_cmd_tx.clone(), + self.wasm_debug, + self.guard.clone(), + )); + results.get().set_executor(executor); + Promise::ok(()) + } +} + +// --------------------------------------------------------------------------- +// EpochGuardedExecutor +// --------------------------------------------------------------------------- + +/// Executor capability that checks epoch validity before each RPC call. +pub struct EpochGuardedExecutor { + network_state: NetworkState, + swarm_cmd_tx: mpsc::Sender, + wasm_debug: bool, + guard: EpochGuard, +} + +impl EpochGuardedExecutor { + pub fn new( + network_state: NetworkState, + swarm_cmd_tx: mpsc::Sender, + wasm_debug: bool, + guard: EpochGuard, + ) -> Self { + Self { + network_state, + swarm_cmd_tx, + wasm_debug, + guard, + } + } +} + +#[allow(refining_impl_trait)] +impl peer_capnp::executor::Server for EpochGuardedExecutor { + fn echo( + self: capnp::capability::Rc, + params: peer_capnp::executor::EchoParams, + mut results: peer_capnp::executor::EchoResults, + ) -> Promise<(), capnp::Error> { + pry!(self.guard.check()); + let message = match pry!(params.get()).get_message() { + Ok(s) => s.to_string().unwrap_or_else(|_| String::new()), + Err(_) => String::new(), + }; + tracing::info!("EpochGuardedExecutor: echo request: {}", message); + Promise::from_future(async move { + let response = format!("Echo: {}", message); + results.get().set_response(&response); + Ok(()) + }) + } + + fn run_bytes( + self: capnp::capability::Rc, + params: peer_capnp::executor::RunBytesParams, + mut results: peer_capnp::executor::RunBytesResults, + ) -> Promise<(), capnp::Error> { + pry!(self.guard.check()); + let params = pry!(params.get()); + let args = read_text_list_result(params.get_args()); + let env = read_text_list_result(params.get_env()); + let wasm = read_data_result(params.get_wasm()); + let wasm_debug = self.wasm_debug; + let network_state = self.network_state.clone(); + let swarm_cmd_tx = self.swarm_cmd_tx.clone(); + Promise::from_future(async move { + use tokio::io; + + tracing::info!("EpochGuardedExecutor: run_bytes starting"); + let bytecode = wasm; + + let (host_stderr, guest_stderr) = io::duplex(64 * 1024); + let (host_stdin, guest_stdin) = io::duplex(64 * 1024); + let (host_stdout, guest_stdout) = io::duplex(64 * 1024); + + let (exit_tx, exit_rx) = tokio::sync::oneshot::channel(); + + let (builder, mut handles) = ProcBuilder::new() + .with_env(env) + .with_args(args) + .with_wasm_debug(wasm_debug) + .with_bytecode(bytecode) + .with_stdio(guest_stdin, guest_stdout, guest_stderr) + .with_data_streams(); + + let proc = builder + .build() + .await + .map_err(|err| capnp::Error::failed(err.to_string()))?; + + let (reader, writer) = handles + .take_host_split() + .ok_or_else(|| capnp::Error::failed("host stream missing".into()))?; + let child_rpc_system = super::build_peer_rpc( + reader, + writer, + network_state, + swarm_cmd_tx, + wasm_debug, + ); + + tokio::task::spawn_local(async move { + let local = tokio::task::LocalSet::new(); + local.spawn_local(futures::FutureExt::map(child_rpc_system, |_| ())); + local + .run_until(async move { + let exit_code = match proc.run().await { + Ok(()) => 0, + Err(e) => { + tracing::error!("run_bytes: child process failed: {}", e); + 1 + } + }; + let _ = exit_tx.send(exit_code); + }) + .await; + }); + + let stdin = + capnp_rpc::new_client(ByteStreamImpl::new(host_stdin, StreamMode::WriteOnly)); + let stdout = + capnp_rpc::new_client(ByteStreamImpl::new(host_stdout, StreamMode::ReadOnly)); + let stderr = + capnp_rpc::new_client(ByteStreamImpl::new(host_stderr, StreamMode::ReadOnly)); + + let process_client: peer_capnp::process::Client = + capnp_rpc::new_client(ProcessImpl::new(stdin, stdout, stderr, exit_rx)); + results.get().set_process(process_client); + + Ok(()) + }) + } +} + +// --------------------------------------------------------------------------- +// build_membrane_rpc — bootstrap Membrane instead of Host +// --------------------------------------------------------------------------- + +/// Build an RPC system that bootstraps a `Membrane(WetwareSession)` instead of +/// a bare `Host`. The membrane provides epoch-scoped sessions containing +/// `Host`, `Executor`, and `StatusPoller`. +pub fn build_membrane_rpc( + reader: R, + writer: W, + network_state: NetworkState, + swarm_cmd_tx: mpsc::Sender, + wasm_debug: bool, + epoch_rx: watch::Receiver, +) -> RpcSystem +where + R: AsyncRead + Unpin + 'static, + W: AsyncWrite + Unpin + 'static, +{ + let membrane: stem_capnp::membrane::Client = + capnp_rpc::new_client(WetwareMembraneServer::new( + epoch_rx, + network_state, + swarm_cmd_tx, + wasm_debug, + )); + + let rpc_network = VatNetwork::new( + reader.compat(), + writer.compat_write(), + Side::Server, + Default::default(), + ); + RpcSystem::new(Box::new(rpc_network), Some(membrane.client)) +} diff --git a/src/rpc/mod.rs b/src/rpc/mod.rs index 9a42d8cf..a2d05df7 100644 --- a/src/rpc/mod.rs +++ b/src/rpc/mod.rs @@ -1,6 +1,7 @@ //! Cap'n Proto RPC server for host-provided capabilities. #![cfg(not(target_arch = "wasm32"))] +pub mod membrane; pub mod server; use std::sync::Arc; @@ -86,7 +87,7 @@ impl NetworkState { } #[derive(Clone, Copy, Debug)] -enum StreamMode { +pub(crate) enum StreamMode { ReadOnly, WriteOnly, } @@ -97,7 +98,7 @@ pub struct ByteStreamImpl { } impl ByteStreamImpl { - fn new(stream: io::DuplexStream, mode: StreamMode) -> Self { + pub(crate) fn new(stream: io::DuplexStream, mode: StreamMode) -> Self { Self { stream: Arc::new(Mutex::new(stream)), mode, @@ -193,7 +194,7 @@ pub struct ProcessImpl { } impl ProcessImpl { - fn new( + pub(crate) fn new( stdin: peer_capnp::byte_stream::Client, stdout: peer_capnp::byte_stream::Client, stderr: peer_capnp::byte_stream::Client, From d18cfec3d1a2b4492f0b39602c2b50e163fee476 Mon Sep 17 00:00:00 2001 From: Louis Thibault Date: Thu, 12 Feb 2026 19:37:53 -0500 Subject: [PATCH 02/10] Use crate_provides to share stem's capnp types directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of regenerating stem_capnp in rs (which produces a distinct trait identity), use capnpc::crate_provides to reference stem's generated types. This lets rs use stem's MembraneServer directly rather than reimplementing it. Removes ~100 lines: WetwareMembraneServer, StatusPollerImpl, fill_epoch() — stem owns these. rs now only provides the SessionExtensionBuilder impl (the actual specialization point). --- build.rs | 4 +- src/lib.rs | 5 -- src/rpc/membrane.rs | 111 +++++++++----------------------------------- 3 files changed, 23 insertions(+), 97 deletions(-) diff --git a/build.rs b/build.rs index ca97490f..df7f0937 100644 --- a/build.rs +++ b/build.rs @@ -39,14 +39,12 @@ fn main() { println!("cargo:rustc-env=DEFAULT_KERNEL_CID={cid_value}"); println!("cargo:rerun-if-changed={}", cid_file.display()); - let stem_file = capnp_dir.join("stem.capnp"); capnpc::CompilerCommand::new() .file(&capnp_file) .file(&membrane_file) - .file(&stem_file) + .crate_provides("stem", [0x9bce094a026970c4_u64]) // stem.capnp types live in the stem crate .run() .expect("failed to compile capnp schemas"); println!("cargo:rerun-if-changed={}", capnp_file.display()); println!("cargo:rerun-if-changed={}", membrane_file.display()); - println!("cargo:rerun-if-changed={}", stem_file.display()); } diff --git a/src/lib.rs b/src/lib.rs index c419e812..c8df6eba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,11 +24,6 @@ pub mod peer_capnp { pub mod membrane_capnp { include!(concat!(env!("OUT_DIR"), "/capnp/membrane_capnp.rs")); } -#[cfg(not(target_arch = "wasm32"))] -#[allow(unused_parens)] -pub mod stem_capnp { - include!(concat!(env!("OUT_DIR"), "/capnp/stem_capnp.rs")); -} // Modules available for both host and guest pub mod config; diff --git a/src/rpc/membrane.rs b/src/rpc/membrane.rs index f2e0c53e..04fafffc 100644 --- a/src/rpc/membrane.rs +++ b/src/rpc/membrane.rs @@ -4,18 +4,17 @@ //! `Session(WetwareSession)` containing `Host`, `Executor`, and `StatusPoller`. //! All capabilities fail with `staleEpoch` when the epoch advances. //! -//! We re-implement the Membrane and StatusPoller servers here against -//! `crate::stem_capnp` (rs's own codegen) because stem's `MembraneServer` -//! implements `stem::stem_capnp::membrane::Server` — a distinct trait from -//! `crate::stem_capnp::membrane::Server` even though both are generated from -//! the same schema. We reuse stem's `Epoch` and `EpochGuard` (plain Rust types). +//! stem owns the Membrane server, StatusPoller, and epoch machinery. rs provides +//! only the `SessionExtensionBuilder` impl that injects wetware-specific +//! capabilities (Host + Executor) into the session, plus the epoch-guarded +//! wrappers for those capabilities. use capnp::capability::Promise; use capnp_rpc::pry; use capnp_rpc::rpc_twoparty_capnp::Side; use capnp_rpc::twoparty::VatNetwork; use capnp_rpc::RpcSystem; -use stem::membrane::{Epoch, EpochGuard}; +use stem::membrane::{Epoch, EpochGuard, MembraneServer, SessionExtensionBuilder}; use tokio::io::{AsyncRead, AsyncWrite}; use tokio::sync::{mpsc, watch}; use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}; @@ -23,7 +22,6 @@ use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}; use crate::host::SwarmCommand; use crate::membrane_capnp; use crate::peer_capnp; -use crate::stem_capnp; use crate::rpc::{ read_data_result, read_text_list_result, ByteStreamImpl, NetworkState, ProcessImpl, StreamMode, }; @@ -31,61 +29,23 @@ use crate::rpc::{ use super::ProcBuilder; // --------------------------------------------------------------------------- -// Helpers +// WetwareSessionBuilder — SessionExtensionBuilder for WetwareSession // --------------------------------------------------------------------------- -/// Fill an epoch builder from our crate's stem_capnp (not stem's). -fn fill_epoch(builder: &mut stem_capnp::epoch::Builder<'_>, epoch: &Epoch) { - builder.set_seq(epoch.seq); - builder.set_adopted_block(epoch.adopted_block); - let head_builder = builder.reborrow().init_head(epoch.head.len() as u32); - head_builder.copy_from_slice(epoch.head.as_slice()); -} - -// --------------------------------------------------------------------------- -// StatusPoller (local impl against crate::stem_capnp) -// --------------------------------------------------------------------------- - -struct StatusPollerImpl { - guard: EpochGuard, -} - -#[allow(refining_impl_trait)] -impl stem_capnp::status_poller::Server for StatusPollerImpl { - fn poll_status( - self: capnp::capability::Rc, - _: stem_capnp::status_poller::PollStatusParams, - mut results: stem_capnp::status_poller::PollStatusResults, - ) -> Promise<(), capnp::Error> { - if let Err(e) = self.guard.check() { - return Promise::err(e); - } - results.get().set_status(stem_capnp::Status::Ok); - Promise::ok(()) - } -} - -// --------------------------------------------------------------------------- -// WetwareMembraneServer -// --------------------------------------------------------------------------- - -/// Membrane server that issues sessions containing epoch-guarded Host + Executor. -pub struct WetwareMembraneServer { - epoch_rx: watch::Receiver, +/// Fills the WetwareSession extension with epoch-guarded Host and Executor. +pub struct WetwareSessionBuilder { network_state: NetworkState, swarm_cmd_tx: mpsc::Sender, wasm_debug: bool, } -impl WetwareMembraneServer { +impl WetwareSessionBuilder { pub fn new( - epoch_rx: watch::Receiver, network_state: NetworkState, swarm_cmd_tx: mpsc::Sender, wasm_debug: bool, ) -> Self { Self { - epoch_rx, network_state, swarm_cmd_tx, wasm_debug, @@ -93,53 +53,30 @@ impl WetwareMembraneServer { } } -#[allow(refining_impl_trait)] -impl stem_capnp::membrane::Server - for WetwareMembraneServer -{ - fn graft( - self: capnp::capability::Rc, - _params: stem_capnp::membrane::GraftParams, - mut results: stem_capnp::membrane::GraftResults, - ) -> Promise<(), capnp::Error> { - let epoch = self.epoch_rx.borrow().clone(); - let guard = EpochGuard { - issued_seq: epoch.seq, - receiver: self.epoch_rx.clone(), - }; - - let mut session = results.get().init_session(); - - // Fill issued epoch - fill_epoch(&mut session.reborrow().init_issued_epoch(), &epoch); - - // Set status poller - let poller: stem_capnp::status_poller::Client = - capnp_rpc::new_client(StatusPollerImpl { - guard: guard.clone(), - }); - session.reborrow().set_status_poller(poller); - - // Fill extension (WetwareSession: Host + Executor) - let mut ext = session.reborrow().init_extension(); +impl SessionExtensionBuilder for WetwareSessionBuilder { + fn build( + &self, + guard: &EpochGuard, + mut builder: membrane_capnp::wetware_session::Builder<'_>, + ) -> Result<(), capnp::Error> { let host: peer_capnp::host::Client = capnp_rpc::new_client(EpochGuardedHost::new( self.network_state.clone(), self.swarm_cmd_tx.clone(), self.wasm_debug, guard.clone(), )); - ext.set_host(host); + builder.set_host(host); let executor: peer_capnp::executor::Client = capnp_rpc::new_client(EpochGuardedExecutor::new( self.network_state.clone(), self.swarm_cmd_tx.clone(), self.wasm_debug, - guard, + guard.clone(), )); - ext.set_executor(executor); + builder.set_executor(executor); - Promise::ok(()) + Ok(()) } } @@ -438,13 +375,9 @@ where R: AsyncRead + Unpin + 'static, W: AsyncWrite + Unpin + 'static, { - let membrane: stem_capnp::membrane::Client = - capnp_rpc::new_client(WetwareMembraneServer::new( - epoch_rx, - network_state, - swarm_cmd_tx, - wasm_debug, - )); + let ext_builder = WetwareSessionBuilder::new(network_state, swarm_cmd_tx, wasm_debug); + let membrane: stem::stem_capnp::membrane::Client = + capnp_rpc::new_client(MembraneServer::new(epoch_rx, ext_builder)); let rpc_network = VatNetwork::new( reader.compat(), From a99da9e373ddc827a375073ca0d092daf2b93238 Mon Sep 17 00:00:00 2001 From: Louis Thibault Date: Thu, 12 Feb 2026 19:44:38 -0500 Subject: [PATCH 03/10] doc: document crate_provides pattern for cross-crate capnp sharing --- doc/capnp-cross-crate.md | 76 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 doc/capnp-cross-crate.md diff --git a/doc/capnp-cross-crate.md b/doc/capnp-cross-crate.md new file mode 100644 index 00000000..14fa0518 --- /dev/null +++ b/doc/capnp-cross-crate.md @@ -0,0 +1,76 @@ +# Cross-Crate Cap'n Proto Schema Sharing + +## Problem + +capnpc generates Rust trait types (e.g. `Server`, `Client`) per crate. If two +crates both compile the same `.capnp` file, their generated traits are +**distinct types** — a struct implementing crate A's `Server` trait does not +satisfy crate B's `Server` trait, even though the schema is identical. + +Concretely: `stem` compiles `stem.capnp` and exports `MembraneServer` which +implements `stem::stem_capnp::membrane::Server`. If `rs` also compiles +`stem.capnp`, it gets its own `rs::stem_capnp::membrane::Server` — and stem's +`MembraneServer` doesn't implement it. + +## Solution: `crate_provides` + +capnpc (≥ 0.17.2) has `CompilerCommand::crate_provides(crate_name, file_ids)`. +This tells the code generator: "don't generate code for these schema files; +instead, emit `use` statements that reference the named crate's generated +modules." + +```rust +// rs/build.rs +capnpc::CompilerCommand::new() + .file("capnp/peer.capnp") + .file("capnp/membrane.capnp") // imports stem.capnp + .crate_provides("stem", [0x9bce094a026970c4]) // stem.capnp file ID + .run() + .expect("failed to compile capnp schemas"); +``` + +The file ID is the `@0x...` annotation at the top of each `.capnp` file: + +```capnp +# stem.capnp +@0x9bce094a026970c4; +``` + +## Requirements + +1. **The `.capnp` file must still be on disk.** capnpc needs it for import + resolution when other schemas (e.g. `membrane.capnp`) reference it. We + vendor `stem.capnp` into `rs/capnp/` for this reason. + +2. **The providing crate must expose its generated module.** stem does this via: + ```rust + pub mod stem_capnp { + include!(concat!(env!("OUT_DIR"), "/capnp/stem_capnp.rs")); + } + ``` + +3. **The consuming crate depends on the provider normally** (via `Cargo.toml`). + No special dependency features needed. + +## How it works in this project + +- **stem** compiles `stem.capnp` → generates `stem::stem_capnp` with + `Membrane`, `Session`, `StatusPoller`, `Epoch`, etc. +- **rs** compiles `membrane.capnp` (which imports `stem.capnp`) but declares + `crate_provides("stem", ...)` for `stem.capnp`. capnpc generates code for + `membrane.capnp` only, with references like `stem::stem_capnp::membrane::*`. +- rs uses `stem::membrane::MembraneServer` directly — no trait mismatch because + both sides share the same generated `stem::stem_capnp` types. + +## What NOT to do + +Don't compile the same `.capnp` in both crates without `crate_provides`. You'll +get a confusing `E0277` error like: + +``` +the trait `stem_capnp::membrane::Server<…>` is not implemented for `MembraneServer<…>` +note: `MembraneServer<…>` implements similarly named trait + `stem::stem_capnp::membrane::Server`, but not `stem_capnp::membrane::Server<…>` +``` + +The fix is always `crate_provides` — not reimplementing the server locally. From 9d12aa8ab4e15586dacd58ca3320088e9f688ecb Mon Sep 17 00:00:00 2001 From: Louis Thibault Date: Thu, 12 Feb 2026 19:46:22 -0500 Subject: [PATCH 04/10] doc: consolidate docs/ into doc/ --- {docs => doc}/rpc-transport.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {docs => doc}/rpc-transport.md (100%) diff --git a/docs/rpc-transport.md b/doc/rpc-transport.md similarity index 100% rename from docs/rpc-transport.md rename to doc/rpc-transport.md From 07842b9653449ebe149da8c818fb14e8c9bbe99a Mon Sep 17 00:00:00 2001 From: Louis Thibault Date: Thu, 12 Feb 2026 19:47:05 -0500 Subject: [PATCH 05/10] doc: add Documentation section to README pointing to doc/ --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 92335256..5a6d7f7c 100644 --- a/README.md +++ b/README.md @@ -301,6 +301,13 @@ This ensures the application can communicate with any IPFS node in the network, - **Configuration issues**: Check `WW_IPFS` environment variable for correct IPFS endpoint - **Logging issues**: Check `RUST_LOG` and ensure tracing is properly initialized +## Documentation + +Additional design docs live in [`doc/`](doc/): + +- [**capnp-cross-crate.md**](doc/capnp-cross-crate.md) — How `crate_provides` shares Cap'n Proto types between stem and rs +- [**rpc-transport.md**](doc/rpc-transport.md) — RPC transport architecture + ## Dependencies - `libp2p`: P2P networking stack with IPFS protocol support From 28d517e0ee2e7ae3b47600ec4a320f81edfc9568 Mon Sep 17 00:00:00 2001 From: Louis Thibault Date: Thu, 12 Feb 2026 19:48:43 -0500 Subject: [PATCH 06/10] doc: rewrite README to reflect current architecture --- README.md | 363 ++++++++++++++---------------------------------------- 1 file changed, 90 insertions(+), 273 deletions(-) diff --git a/README.md b/README.md index 5a6d7f7c..3eaa3bd9 100644 --- a/README.md +++ b/README.md @@ -1,321 +1,138 @@ -# Wetware Runtime +# Wetware Runtime (`ww`) -A Rust CLI that fetches WASM components (typically from IPFS) and executes them -under WASI Preview 2. The `ww run` command wires host stdio directly to the -guest, so operators can interact with components exactly as if they were local. +Wetware is a peer-to-peer WASM sandbox. The `ww` CLI runs WASM components +under WASI Preview 2, connecting them to a libp2p swarm and exposing host +capabilities via Cap'n Proto RPC. -## Features +## Architecture -- **IPFS DHT Bootstrap**: Automatically discovers and connects to IPFS peers from local Kubo node -- **Protocol Compatibility**: Uses standard IPFS protocols (`/ipfs/kad/1.0.0`, `/ipfs/id/1.0.0`) for full network compatibility -- **RSA Key Support**: Includes RSA support for connecting to legacy IPFS peers -- **Creates libp2p Host**: Generates Ed25519 identity and listens on TCP with IPFS-compatible protocols -- **DHT Operations**: Participates in IPFS DHT operations (provide/query) after bootstrap -- **Structured Logging**: Comprehensive logging with configurable levels and performance metrics - -## Prerequisites - -1. **Kubo (IPFS) daemon running locally** - ```bash - kubo daemon - ``` - -2. **Rust toolchain** - ```bash - rustup install stable - rustup default stable - ``` - -## Usage - -The application now uses a subcommand structure. The main command is `ww` with a `run` subcommand for starting a wetware node. - -### Command Structure - -```bash -ww - -Commands: - run Run a wetware node - help Print this message or the help of the given subcommand(s) +``` + ┌──────────────────────────┐ + operator ──stdio──> │ ww run │ + │ │ + │ libp2p swarm │ + │ ├─ Kademlia DHT │ + │ ├─ Identify │ + │ └─ TCP/Noise/Yamux │ + │ │ + │ Cap'n Proto RPC │ + │ └─ Membrane bootstrap │ + │ ├─ Host │ + │ ├─ Executor │ + │ └─ StatusPoller │ + │ │ + │ Wasmtime (WASI P2) │ + │ └─ guest.wasm │ + └──────────────────────────┘ ``` -### Running a Wetware Node - -1. **Start Kubo daemon** (in a separate terminal): - ```bash - kubo daemon - ``` +**Membrane** (from [stem](https://github.com/wetware/stem)) is the RPC +bootstrap capability. Guests graft onto it and receive an epoch-scoped +**Session** containing **Host**, **Executor**, and **StatusPoller**. When the +on-chain epoch advances, all capabilities from the previous session fail with +`staleEpoch`. -2. **Run the application** using the `run` subcommand: - ```bash - # Use defaults (http://localhost:5001, ww=info) - cargo run -- run - - # Custom IPFS endpoint - cargo run -- run --ipfs http://127.0.0.1:5001 - cargo run -- run --ipfs http://192.168.1.100:5001 - - # Configure logs with RUST_LOG - RUST_LOG=ww=debug cargo run -- run - RUST_LOG=ww=trace cargo run -- run - - # Combine both - RUST_LOG=ww=debug cargo run -- run --ipfs http://192.168.1.100:5001 - - # Or use environment variables - export WW_IPFS=http://192.168.1.100:5001 - export RUST_LOG=ww=debug - cargo run -- run - ``` +### Key Modules -### Command Options +| Module | Description | +|--------|-------------| +| `cell` | WASM component loading and execution via Wasmtime | +| `host` | libp2p swarm lifecycle and peer management | +| `rpc` | Cap'n Proto RPC servers (Host, Executor, Membrane) | +| `ipfs` | Kubo API client for IPFS peer discovery | +| `loaders`| WASM bytecode loaders (filesystem, IPFS) | +| `config` | Runtime configuration and presets | -The `run` subcommand supports the following options: +### Cap'n Proto Schemas -- `--ipfs `: IPFS node HTTP API endpoint (e.g., http://127.0.0.1:5001) -- `--preset `: Use preset configuration (minimal, development, production) -- `--env-config`: Use configuration from environment variables +Schemas live in `capnp/`: -### Building and Running WASM Examples +- **peer.capnp** — Host, Executor, Process, ByteStream interfaces +- **membrane.capnp** — WetwareSession (Host + Executor extension for stem's generic Session) +- **stem.capnp** — Vendored from stem for import resolution (no code generated; see [capnp-cross-crate.md](doc/capnp-cross-crate.md)) -WASM examples are built automatically when you run `make` or `make examples`. The `default-kernel` example is included by default. +### Workspace -> **Note:** The `wasm32-wasip2` target is currently nightly-only. Inside -> `examples/default-kernel/`, run `rustup override set nightly` (once) and -> `rustup target add wasm32-wasip2` before building the guest. +The workspace includes host-side code and several WASM guest crates: -**Quick start**: -```bash -# Build everything (including examples) -make +- `.` — the `ww` host binary and library +- `guests/pid0` — init process (bootstrap guest) +- `guests/shell` — interactive shell guest +- `guests/child-echo` — echo child process for testing +- `guests/guest-runtime` — shared guest-side runtime utilities -# Run the default-kernel example -./target/release/ww run /boot --volume examples/default-kernel/target/wasm32-wasip2/release:/boot -``` - -To test `ww run` with the `default-kernel` example: - -1. **Build the WASM file** (already done if you ran `make`): - ```bash - make example-default-kernel - ``` - - Or run directly from the example directory: - ```bash - make -C examples/default-kernel build - ``` - - The example Makefile handles building and ensuring the output is named `main.wasm`. +## Prerequisites -2. **Run with local filesystem mount**: +1. **Rust toolchain** (stable + nightly for guest builds) ```bash - cargo run -- run /app \ - --volume examples/default-kernel/target/wasm32-wasip2/release:/app + rustup install stable + rustup target add wasm32-wasip2 --toolchain nightly ``` -3. **Export to IPFS and run from IPFS** (optional): +2. **Kubo (IPFS) daemon** for peer discovery ```bash - # Build and export to IPFS - make example-default-kernel-ipfs - - # Or run directly: - make -C examples/default-kernel ipfs - - # This will output an IPFS hash like: /ipfs/QmHash... - # Then run with: - cargo run -- run /ipfs/QmHash... + kubo daemon ``` -**Note**: The `ww run` command expects `{path}/main.wasm`, so when using volume mounts, ensure `main.wasm` exists in the mounted directory. The example Makefiles handle this automatically. - -## Docker Support - -The project includes a multi-stage Docker build for containerized deployment and distribution. +3. **Cap'n Proto compiler** (`capnp`) for schema compilation -### Building with Podman +## Quick Start ```bash -# Build the container image -make podman-build -# or -podman build -t wetware:latest . - -# Run the container -make podman-run -# or -podman run --rm -it wetware:latest - -# Clean up container images -make podman-clean -``` - -### Container Features +# Build everything +make -- **Multi-stage build**: Optimizes image size by separating build and runtime stages -- **Security**: Runs as non-root user (`wetware`) -- **Efficient caching**: Leverages container layer caching for faster builds -- **Minimal runtime**: Based on Debian Bookworm slim for smaller footprint +# Run with a local WASM volume +cargo run -- run /boot \ + --volume examples/default-kernel/target/wasm32-wasip2/release:/boot +``` -**Note**: When running the container, you'll need to use the `run` subcommand: -```bash -# Run the container with the run subcommand -podman run --rm -it wetware:latest run +## Usage -# With custom options -RUST_LOG=ww=debug podman run --rm -it wetware:latest run --ipfs http://host.docker.internal:5001 ``` +ww -### Podman Compose (Optional) - -Create a `docker-compose.yml` for easy development (works with both Docker and Podman): - -```yaml -version: '3.8' -services: - wetware: - build: . - ports: - - "8080:8080" - environment: - - WW_IPFS=http://host.docker.internal:5001 - - RUST_LOG=ww=info - volumes: - - ./config:/app/config - command: ["run"] # Use the run subcommand +Commands: + run Run a wetware node + help Print help ``` -## CI/CD Pipeline - -The project includes GitHub Actions workflows for automated testing, building, and publishing. - -### Workflow Features - -- **Automated Testing**: Runs on every push and pull request -- **Code Quality**: Includes formatting checks and clippy linting -- **Release Automation**: Automatically builds and publishes artifacts on releases -- **Docker Integration**: Builds and pushes Docker images to registry -- **Artifact Publishing**: Creates distributable binaries and archives +### `ww run` Options -### Triggering Releases +- `--ipfs ` — Kubo HTTP API endpoint (default: `http://localhost:5001`) +- `--preset ` — Configuration preset (`minimal`, `development`, `production`) +- `--env-config` — Load configuration from environment variables -1. **Create a GitHub release** with a semantic version tag (e.g., `v1.0.0`) -2. **Workflow automatically**: - - Builds the Rust application - - Creates release artifacts (binary + tarball) - - Builds and pushes Docker images - - Uploads artifacts to GitHub releases +### Environment Variables -### Required Secrets +- **`WW_IPFS`** — Kubo HTTP API endpoint +- **`RUST_LOG`** — Tracing filter (e.g. `ww=debug`, `ww=info,libp2p=debug`) -For Docker publishing, set these repository secrets: -- `DOCKER_USERNAME`: Your Docker Hub username -- `DOCKER_PASSWORD`: Your Docker Hub access token +## Building WASM Guests -### Manual Workflow Triggers +Guest crates target `wasm32-wasip2` (nightly-only): ```bash -# Test only -gh workflow run rust.yml --ref main +# Build all guests +make -# Build Docker image (on main branch) -gh workflow run rust.yml --ref main +# Build a specific guest +make -C examples/default-kernel build ``` -## Logging Configuration - -The application uses structured logging with the `tracing` crate. You can configure log levels using environment variables: - -### Environment Variables - -- **`WW_IPFS`**: IPFS node HTTP API endpoint (defaults to http://localhost:5001) - ```bash - # Use default localhost endpoint - export WW_IPFS=http://localhost:5001 - - # Use custom IPFS node - export WW_IPFS=http://192.168.1.100:5001 - - # Use remote IPFS node - export WW_IPFS=https://ipfs.example.com:5001 - ``` - -- **`RUST_LOG`**: Controls tracing output using standard `tracing-subscriber` filters. - ```bash - # No logs, only printed output - export RUST_LOG=off - - # Only Wetware logs - export RUST_LOG=ww=info - export RUST_LOG=ww=debug - export RUST_LOG=ww=trace - - # Debug streams + wasmtime - export RUST_LOG=ww=debug,ww::cell::streams=trace,ww::cell::proc=debug,capnp=debug,capnp_rpc=debug,wasmtime=info,wasmtime_wasi=info - - # Debug libp2p - export RUST_LOG=ww=info,libp2p=debug,libp2p_swarm=debug,libp2p_kad=debug,libp2p_gossipsub=debug - ``` - -## How It Works - -1. **Configuration**: Determines IPFS endpoint from command line, environment variable, or default -2. **Peer Discovery**: Queries the configured IPFS node's HTTP API to discover connected peers -3. **Host Creation**: Generates Ed25519 keypair and creates libp2p swarm with IPFS-compatible protocols -4. **DHT Bootstrap**: Adds discovered peers to Kademlia routing table and establishes connections -5. **Network Integration**: Joins the IPFS DHT network and participates in DHT operations -6. **DHT Operations**: Can provide content and query for providers in the IPFS network - -## DHT Bootstrap Process - -The application implements a sophisticated DHT bootstrap process: +The `ww run` command expects `{path}/main.wasm` in the mounted directory. -1. **Peer Discovery**: Queries the local Kubo node's `/api/v0/swarm/peers` endpoint to discover connected peers -2. **Routing Table Population**: Adds discovered peers to the Kademlia routing table before establishing connections -3. **Connection Establishment**: Dials discovered peers to establish TCP connections -4. **Protocol Handshake**: Performs identify and Kademlia protocol handshakes using standard IPFS protocols -5. **Bootstrap Trigger**: Triggers the Kademlia bootstrap process to populate the routing table -6. **Network Participation**: Begins participating in DHT operations (provide/query) +## Docker -This approach ensures rapid integration into the IPFS network by leveraging the local Kubo node's peer knowledge. - -## Protocol Compatibility - -The application is designed for full IPFS network compatibility: - -- **Kademlia DHT**: Uses `/ipfs/kad/1.0.0` protocol for DHT operations -- **Identify**: Uses `/ipfs/id/1.0.0` protocol for peer identification -- **Transport**: Supports TCP with Noise encryption and Yamux multiplexing -- **Key Types**: Supports both Ed25519 (modern) and RSA (legacy) key types -- **Multiaddr**: Handles standard IPFS multiaddresses with peer IDs - -This ensures the application can communicate with any IPFS node in the network, regardless of their specific configuration. - -## Troubleshooting - -- **"IPFS API file not found"**: Make sure Kubo is running (`kubo daemon`) -- **Connection errors**: Check if Kubo is listening on the expected port and endpoint -- **DHT bootstrap failures**: Ensure Kubo has peers and the API endpoint is correct -- **Protocol compatibility**: The application uses standard IPFS protocols for full compatibility -- **RSA connection errors**: RSA support is included for legacy IPFS peers -- **Configuration issues**: Check `WW_IPFS` environment variable for correct IPFS endpoint -- **Logging issues**: Check `RUST_LOG` and ensure tracing is properly initialized +```bash +make podman-build # Build image +make podman-run # Run container +make podman-clean # Clean up +``` ## Documentation -Additional design docs live in [`doc/`](doc/): +Design docs live in [`doc/`](doc/): -- [**capnp-cross-crate.md**](doc/capnp-cross-crate.md) — How `crate_provides` shares Cap'n Proto types between stem and rs +- [**capnp-cross-crate.md**](doc/capnp-cross-crate.md) — Cross-crate Cap'n Proto type sharing via `crate_provides` - [**rpc-transport.md**](doc/rpc-transport.md) — RPC transport architecture - -## Dependencies - -- `libp2p`: P2P networking stack with IPFS protocol support -- `libp2p-kad`: Kademlia DHT implementation for IPFS compatibility -- `libp2p-identify`: Peer identification protocol for IPFS compatibility -- `reqwest`: HTTP client for Kubo API integration -- `tokio`: Async runtime for concurrent operations -- `anyhow`: Error handling and propagation -- `serde`: JSON serialization/deserialization for API responses -- `tracing`: Structured logging framework with performance metrics -- `tracing-subscriber`: Logging subscriber with environment-based configuration From ec2989acceb57b1f0eb99726a5dad1e00068b92a Mon Sep 17 00:00:00 2001 From: Louis Thibault Date: Thu, 12 Feb 2026 19:49:22 -0500 Subject: [PATCH 07/10] Revert "doc: rewrite README to reflect current architecture" This reverts commit 28d517e0ee2e7ae3b47600ec4a320f81edfc9568. --- README.md | 363 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 273 insertions(+), 90 deletions(-) diff --git a/README.md b/README.md index 3eaa3bd9..5a6d7f7c 100644 --- a/README.md +++ b/README.md @@ -1,138 +1,321 @@ -# Wetware Runtime (`ww`) +# Wetware Runtime -Wetware is a peer-to-peer WASM sandbox. The `ww` CLI runs WASM components -under WASI Preview 2, connecting them to a libp2p swarm and exposing host -capabilities via Cap'n Proto RPC. +A Rust CLI that fetches WASM components (typically from IPFS) and executes them +under WASI Preview 2. The `ww run` command wires host stdio directly to the +guest, so operators can interact with components exactly as if they were local. -## Architecture +## Features -``` - ┌──────────────────────────┐ - operator ──stdio──> │ ww run │ - │ │ - │ libp2p swarm │ - │ ├─ Kademlia DHT │ - │ ├─ Identify │ - │ └─ TCP/Noise/Yamux │ - │ │ - │ Cap'n Proto RPC │ - │ └─ Membrane bootstrap │ - │ ├─ Host │ - │ ├─ Executor │ - │ └─ StatusPoller │ - │ │ - │ Wasmtime (WASI P2) │ - │ └─ guest.wasm │ - └──────────────────────────┘ -``` - -**Membrane** (from [stem](https://github.com/wetware/stem)) is the RPC -bootstrap capability. Guests graft onto it and receive an epoch-scoped -**Session** containing **Host**, **Executor**, and **StatusPoller**. When the -on-chain epoch advances, all capabilities from the previous session fail with -`staleEpoch`. +- **IPFS DHT Bootstrap**: Automatically discovers and connects to IPFS peers from local Kubo node +- **Protocol Compatibility**: Uses standard IPFS protocols (`/ipfs/kad/1.0.0`, `/ipfs/id/1.0.0`) for full network compatibility +- **RSA Key Support**: Includes RSA support for connecting to legacy IPFS peers +- **Creates libp2p Host**: Generates Ed25519 identity and listens on TCP with IPFS-compatible protocols +- **DHT Operations**: Participates in IPFS DHT operations (provide/query) after bootstrap +- **Structured Logging**: Comprehensive logging with configurable levels and performance metrics -### Key Modules +## Prerequisites -| Module | Description | -|--------|-------------| -| `cell` | WASM component loading and execution via Wasmtime | -| `host` | libp2p swarm lifecycle and peer management | -| `rpc` | Cap'n Proto RPC servers (Host, Executor, Membrane) | -| `ipfs` | Kubo API client for IPFS peer discovery | -| `loaders`| WASM bytecode loaders (filesystem, IPFS) | -| `config` | Runtime configuration and presets | +1. **Kubo (IPFS) daemon running locally** + ```bash + kubo daemon + ``` -### Cap'n Proto Schemas +2. **Rust toolchain** + ```bash + rustup install stable + rustup default stable + ``` -Schemas live in `capnp/`: +## Usage -- **peer.capnp** — Host, Executor, Process, ByteStream interfaces -- **membrane.capnp** — WetwareSession (Host + Executor extension for stem's generic Session) -- **stem.capnp** — Vendored from stem for import resolution (no code generated; see [capnp-cross-crate.md](doc/capnp-cross-crate.md)) +The application now uses a subcommand structure. The main command is `ww` with a `run` subcommand for starting a wetware node. -### Workspace +### Command Structure -The workspace includes host-side code and several WASM guest crates: +```bash +ww -- `.` — the `ww` host binary and library -- `guests/pid0` — init process (bootstrap guest) -- `guests/shell` — interactive shell guest -- `guests/child-echo` — echo child process for testing -- `guests/guest-runtime` — shared guest-side runtime utilities +Commands: + run Run a wetware node + help Print this message or the help of the given subcommand(s) +``` -## Prerequisites +### Running a Wetware Node -1. **Rust toolchain** (stable + nightly for guest builds) +1. **Start Kubo daemon** (in a separate terminal): ```bash - rustup install stable - rustup target add wasm32-wasip2 --toolchain nightly + kubo daemon ``` -2. **Kubo (IPFS) daemon** for peer discovery +2. **Run the application** using the `run` subcommand: ```bash - kubo daemon + # Use defaults (http://localhost:5001, ww=info) + cargo run -- run + + # Custom IPFS endpoint + cargo run -- run --ipfs http://127.0.0.1:5001 + cargo run -- run --ipfs http://192.168.1.100:5001 + + # Configure logs with RUST_LOG + RUST_LOG=ww=debug cargo run -- run + RUST_LOG=ww=trace cargo run -- run + + # Combine both + RUST_LOG=ww=debug cargo run -- run --ipfs http://192.168.1.100:5001 + + # Or use environment variables + export WW_IPFS=http://192.168.1.100:5001 + export RUST_LOG=ww=debug + cargo run -- run ``` -3. **Cap'n Proto compiler** (`capnp`) for schema compilation +### Command Options + +The `run` subcommand supports the following options: + +- `--ipfs `: IPFS node HTTP API endpoint (e.g., http://127.0.0.1:5001) +- `--preset `: Use preset configuration (minimal, development, production) +- `--env-config`: Use configuration from environment variables + +### Building and Running WASM Examples + +WASM examples are built automatically when you run `make` or `make examples`. The `default-kernel` example is included by default. -## Quick Start +> **Note:** The `wasm32-wasip2` target is currently nightly-only. Inside +> `examples/default-kernel/`, run `rustup override set nightly` (once) and +> `rustup target add wasm32-wasip2` before building the guest. +**Quick start**: ```bash -# Build everything +# Build everything (including examples) make -# Run with a local WASM volume -cargo run -- run /boot \ - --volume examples/default-kernel/target/wasm32-wasip2/release:/boot +# Run the default-kernel example +./target/release/ww run /boot --volume examples/default-kernel/target/wasm32-wasip2/release:/boot ``` -## Usage +To test `ww run` with the `default-kernel` example: -``` -ww +1. **Build the WASM file** (already done if you ran `make`): + ```bash + make example-default-kernel + ``` + + Or run directly from the example directory: + ```bash + make -C examples/default-kernel build + ``` + + The example Makefile handles building and ensuring the output is named `main.wasm`. -Commands: - run Run a wetware node - help Print help -``` +2. **Run with local filesystem mount**: + ```bash + cargo run -- run /app \ + --volume examples/default-kernel/target/wasm32-wasip2/release:/app + ``` + +3. **Export to IPFS and run from IPFS** (optional): + ```bash + # Build and export to IPFS + make example-default-kernel-ipfs + + # Or run directly: + make -C examples/default-kernel ipfs + + # This will output an IPFS hash like: /ipfs/QmHash... + # Then run with: + cargo run -- run /ipfs/QmHash... + ``` -### `ww run` Options +**Note**: The `ww run` command expects `{path}/main.wasm`, so when using volume mounts, ensure `main.wasm` exists in the mounted directory. The example Makefiles handle this automatically. -- `--ipfs ` — Kubo HTTP API endpoint (default: `http://localhost:5001`) -- `--preset ` — Configuration preset (`minimal`, `development`, `production`) -- `--env-config` — Load configuration from environment variables +## Docker Support -### Environment Variables +The project includes a multi-stage Docker build for containerized deployment and distribution. + +### Building with Podman -- **`WW_IPFS`** — Kubo HTTP API endpoint -- **`RUST_LOG`** — Tracing filter (e.g. `ww=debug`, `ww=info,libp2p=debug`) +```bash +# Build the container image +make podman-build +# or +podman build -t wetware:latest . + +# Run the container +make podman-run +# or +podman run --rm -it wetware:latest + +# Clean up container images +make podman-clean +``` -## Building WASM Guests +### Container Features -Guest crates target `wasm32-wasip2` (nightly-only): +- **Multi-stage build**: Optimizes image size by separating build and runtime stages +- **Security**: Runs as non-root user (`wetware`) +- **Efficient caching**: Leverages container layer caching for faster builds +- **Minimal runtime**: Based on Debian Bookworm slim for smaller footprint +**Note**: When running the container, you'll need to use the `run` subcommand: ```bash -# Build all guests -make +# Run the container with the run subcommand +podman run --rm -it wetware:latest run + +# With custom options +RUST_LOG=ww=debug podman run --rm -it wetware:latest run --ipfs http://host.docker.internal:5001 +``` -# Build a specific guest -make -C examples/default-kernel build +### Podman Compose (Optional) + +Create a `docker-compose.yml` for easy development (works with both Docker and Podman): + +```yaml +version: '3.8' +services: + wetware: + build: . + ports: + - "8080:8080" + environment: + - WW_IPFS=http://host.docker.internal:5001 + - RUST_LOG=ww=info + volumes: + - ./config:/app/config + command: ["run"] # Use the run subcommand ``` -The `ww run` command expects `{path}/main.wasm` in the mounted directory. +## CI/CD Pipeline + +The project includes GitHub Actions workflows for automated testing, building, and publishing. + +### Workflow Features -## Docker +- **Automated Testing**: Runs on every push and pull request +- **Code Quality**: Includes formatting checks and clippy linting +- **Release Automation**: Automatically builds and publishes artifacts on releases +- **Docker Integration**: Builds and pushes Docker images to registry +- **Artifact Publishing**: Creates distributable binaries and archives + +### Triggering Releases + +1. **Create a GitHub release** with a semantic version tag (e.g., `v1.0.0`) +2. **Workflow automatically**: + - Builds the Rust application + - Creates release artifacts (binary + tarball) + - Builds and pushes Docker images + - Uploads artifacts to GitHub releases + +### Required Secrets + +For Docker publishing, set these repository secrets: +- `DOCKER_USERNAME`: Your Docker Hub username +- `DOCKER_PASSWORD`: Your Docker Hub access token + +### Manual Workflow Triggers ```bash -make podman-build # Build image -make podman-run # Run container -make podman-clean # Clean up +# Test only +gh workflow run rust.yml --ref main + +# Build Docker image (on main branch) +gh workflow run rust.yml --ref main ``` +## Logging Configuration + +The application uses structured logging with the `tracing` crate. You can configure log levels using environment variables: + +### Environment Variables + +- **`WW_IPFS`**: IPFS node HTTP API endpoint (defaults to http://localhost:5001) + ```bash + # Use default localhost endpoint + export WW_IPFS=http://localhost:5001 + + # Use custom IPFS node + export WW_IPFS=http://192.168.1.100:5001 + + # Use remote IPFS node + export WW_IPFS=https://ipfs.example.com:5001 + ``` + +- **`RUST_LOG`**: Controls tracing output using standard `tracing-subscriber` filters. + ```bash + # No logs, only printed output + export RUST_LOG=off + + # Only Wetware logs + export RUST_LOG=ww=info + export RUST_LOG=ww=debug + export RUST_LOG=ww=trace + + # Debug streams + wasmtime + export RUST_LOG=ww=debug,ww::cell::streams=trace,ww::cell::proc=debug,capnp=debug,capnp_rpc=debug,wasmtime=info,wasmtime_wasi=info + + # Debug libp2p + export RUST_LOG=ww=info,libp2p=debug,libp2p_swarm=debug,libp2p_kad=debug,libp2p_gossipsub=debug + ``` + +## How It Works + +1. **Configuration**: Determines IPFS endpoint from command line, environment variable, or default +2. **Peer Discovery**: Queries the configured IPFS node's HTTP API to discover connected peers +3. **Host Creation**: Generates Ed25519 keypair and creates libp2p swarm with IPFS-compatible protocols +4. **DHT Bootstrap**: Adds discovered peers to Kademlia routing table and establishes connections +5. **Network Integration**: Joins the IPFS DHT network and participates in DHT operations +6. **DHT Operations**: Can provide content and query for providers in the IPFS network + +## DHT Bootstrap Process + +The application implements a sophisticated DHT bootstrap process: + +1. **Peer Discovery**: Queries the local Kubo node's `/api/v0/swarm/peers` endpoint to discover connected peers +2. **Routing Table Population**: Adds discovered peers to the Kademlia routing table before establishing connections +3. **Connection Establishment**: Dials discovered peers to establish TCP connections +4. **Protocol Handshake**: Performs identify and Kademlia protocol handshakes using standard IPFS protocols +5. **Bootstrap Trigger**: Triggers the Kademlia bootstrap process to populate the routing table +6. **Network Participation**: Begins participating in DHT operations (provide/query) + +This approach ensures rapid integration into the IPFS network by leveraging the local Kubo node's peer knowledge. + +## Protocol Compatibility + +The application is designed for full IPFS network compatibility: + +- **Kademlia DHT**: Uses `/ipfs/kad/1.0.0` protocol for DHT operations +- **Identify**: Uses `/ipfs/id/1.0.0` protocol for peer identification +- **Transport**: Supports TCP with Noise encryption and Yamux multiplexing +- **Key Types**: Supports both Ed25519 (modern) and RSA (legacy) key types +- **Multiaddr**: Handles standard IPFS multiaddresses with peer IDs + +This ensures the application can communicate with any IPFS node in the network, regardless of their specific configuration. + +## Troubleshooting + +- **"IPFS API file not found"**: Make sure Kubo is running (`kubo daemon`) +- **Connection errors**: Check if Kubo is listening on the expected port and endpoint +- **DHT bootstrap failures**: Ensure Kubo has peers and the API endpoint is correct +- **Protocol compatibility**: The application uses standard IPFS protocols for full compatibility +- **RSA connection errors**: RSA support is included for legacy IPFS peers +- **Configuration issues**: Check `WW_IPFS` environment variable for correct IPFS endpoint +- **Logging issues**: Check `RUST_LOG` and ensure tracing is properly initialized + ## Documentation -Design docs live in [`doc/`](doc/): +Additional design docs live in [`doc/`](doc/): -- [**capnp-cross-crate.md**](doc/capnp-cross-crate.md) — Cross-crate Cap'n Proto type sharing via `crate_provides` +- [**capnp-cross-crate.md**](doc/capnp-cross-crate.md) — How `crate_provides` shares Cap'n Proto types between stem and rs - [**rpc-transport.md**](doc/rpc-transport.md) — RPC transport architecture + +## Dependencies + +- `libp2p`: P2P networking stack with IPFS protocol support +- `libp2p-kad`: Kademlia DHT implementation for IPFS compatibility +- `libp2p-identify`: Peer identification protocol for IPFS compatibility +- `reqwest`: HTTP client for Kubo API integration +- `tokio`: Async runtime for concurrent operations +- `anyhow`: Error handling and propagation +- `serde`: JSON serialization/deserialization for API responses +- `tracing`: Structured logging framework with performance metrics +- `tracing-subscriber`: Logging subscriber with environment-based configuration From 1c442b005da5e3aed91f33d0eb7b19defca861d9 Mon Sep 17 00:00:00 2001 From: Louis Thibault Date: Thu, 12 Feb 2026 19:53:03 -0500 Subject: [PATCH 08/10] doc: document capnp schemas with postfix comments --- capnp/membrane.capnp | 15 +++++++++++++-- capnp/peer.capnp | 36 ++++++++++++++++++++++++++++++++++-- capnp/stem.capnp | 6 ++++++ 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/capnp/membrane.capnp b/capnp/membrane.capnp index 6dd7f33d..51bc5d0d 100644 --- a/capnp/membrane.capnp +++ b/capnp/membrane.capnp @@ -1,11 +1,22 @@ +# Wetware session extension for stem's generic Membrane. +# +# The RPC bootstrap capability for wetware guests is +# Stem.Membrane(WetwareSession). Guests call graft() and receive a +# Session whose extension field carries epoch-scoped Host and Executor +# capabilities. When the on-chain epoch advances, all capabilities from +# the previous session are revoked. + @0xa59e04af26eca82f; using Stem = import "stem.capnp"; +# Vendored copy; no code generated (see crate_provides in build.rs). + using Peer = import "peer.capnp"; +# Local peer interfaces: Host, Executor, Process, ByteStream. struct WetwareSession { - host @0 :Peer.Host; - executor @1 :Peer.Executor; + host @0 :Peer.Host; # Swarm-level operations (id, addrs, peers, connect). + executor @1 :Peer.Executor; # WASM execution (runBytes, echo). } # The bootstrap type for wetware guests is Stem.Membrane(WetwareSession). diff --git a/capnp/peer.capnp b/capnp/peer.capnp index 3114a705..2bcfa427 100644 --- a/capnp/peer.capnp +++ b/capnp/peer.capnp @@ -1,32 +1,64 @@ +# Wetware peer interfaces. +# +# These capabilities are surfaced to WASM guests through the Membrane's +# epoch-scoped session (see membrane.capnp). Each capability wrapper +# holds an EpochGuard and fails with a stale-epoch error once the guard +# detects the epoch has advanced. + @0xbf5147b78c0e6a2f; struct PeerInfo { - peerId @0 :Data; - addrs @1 :List(Data); + peerId @0 :Data; # libp2p peer ID, serialized. + addrs @1 :List(Data); # Multiaddrs for this peer, each serialized. } interface Host { id @0 () -> (peerId :Data); + # Return this node's libp2p peer ID. + addrs @1 () -> (addrs :List(Data)); + # Return the multiaddrs this node is listening on. + peers @2 () -> (peers :List(PeerInfo)); + # List currently connected peers. + connect @3 (peerId :Data, addrs :List(Data)) -> (); + # Dial a peer by ID and multiaddrs. + executor @4 () -> (executor :Executor); + # Obtain an Executor scoped to the same epoch as this Host. } interface Executor { runBytes @0 (wasm :Data, args :List(Text), env :List(Text)) -> (process :Process); + # Instantiate a WASM component from raw bytes and return a handle to + # its running process. + echo @1 (message :Text) -> (response :Text); + # Diagnostic echo — returns the message unmodified. } interface Process { stdin @0 () -> (stream :ByteStream); + # Writable stream connected to the guest's standard input. + stdout @1 () -> (stream :ByteStream); + # Readable stream connected to the guest's standard output. + stderr @2 () -> (stream :ByteStream); + # Readable stream connected to the guest's standard error. + wait @3 () -> (exitCode :Int32); + # Block until the process exits and return its exit code. } interface ByteStream { read @0 (maxBytes :UInt32) -> (data :Data); + # Read up to maxBytes from the stream. Returns empty data at EOF. + write @1 (data :Data) -> (); + # Write data to the stream. + close @2 () -> (); + # Close the stream. Further reads return EOF; further writes fail. } diff --git a/capnp/stem.capnp b/capnp/stem.capnp index 54cb7ef3..6d7add33 100644 --- a/capnp/stem.capnp +++ b/capnp/stem.capnp @@ -1,3 +1,9 @@ +# Vendored from github.com/wetware/stem. This file MUST stay in sync with +# stem's canonical copy. No Rust code is generated for it — build.rs uses +# capnpc::CompilerCommand::crate_provides("stem", [...]) so that downstream +# schemas can import it for type resolution while referencing the stem crate's +# generated types at compile time. See doc/capnp-cross-crate.md. + @0x9bce094a026970c4; struct Epoch { From adf335d885bd5fa5b6b0a5f6e65d9fc2c941f3ca Mon Sep 17 00:00:00 2001 From: Louis Thibault Date: Thu, 12 Feb 2026 20:26:48 -0500 Subject: [PATCH 09/10] Switch pid0 from bare Host to Membrane bootstrap pid0 now bootstraps via Membrane(WetwareSession) instead of a bare Host capability. On graft(), it receives an epoch-scoped Session containing Host + Executor through the WetwareSession extension. Host side: spawn_with_streams_rpc() creates a static epoch channel and uses build_membrane_rpc() instead of build_peer_rpc(). Guest side: build.rs compiles all three schemas (peer, membrane, stem) with src_prefix for clean output paths. lib.rs switches the bootstrap type and calls graft() to obtain the session. --- guests/pid0/build.rs | 17 ++++++--- guests/pid0/src/lib.rs | 79 ++++++++++++++++++++++++++---------------- src/cell/executor.rs | 17 +++++++-- 3 files changed, 76 insertions(+), 37 deletions(-) diff --git a/guests/pid0/build.rs b/guests/pid0/build.rs index 965901b3..b11403e8 100644 --- a/guests/pid0/build.rs +++ b/guests/pid0/build.rs @@ -3,15 +3,22 @@ use std::path::Path; fn main() { let manifest_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"); - let capnp_file = Path::new(&manifest_dir) + let capnp_dir = Path::new(&manifest_dir) .join("..") .join("..") .join("capnp") - .join("peer.capnp"); + .canonicalize() + .expect("capnp dir not found"); capnpc::CompilerCommand::new() - .file(&capnp_file) + .src_prefix(&capnp_dir) + .file(capnp_dir.join("peer.capnp")) + .file(capnp_dir.join("membrane.capnp")) + .file(capnp_dir.join("stem.capnp")) .run() - .expect("failed to compile capnp schema"); - println!("cargo:rerun-if-changed={}", capnp_file.display()); + .expect("failed to compile capnp schemas"); + + println!("cargo:rerun-if-changed={}", capnp_dir.join("peer.capnp").display()); + println!("cargo:rerun-if-changed={}", capnp_dir.join("membrane.capnp").display()); + println!("cargo:rerun-if-changed={}", capnp_dir.join("stem.capnp").display()); } diff --git a/guests/pid0/src/lib.rs b/guests/pid0/src/lib.rs index cac36497..1f96c96d 100644 --- a/guests/pid0/src/lib.rs +++ b/guests/pid0/src/lib.rs @@ -5,10 +5,17 @@ use wasip2::exports::cli::run::Guest; #[allow(dead_code)] mod peer_capnp { - include!(concat!( - env!("OUT_DIR"), - "/Users/mikel/Code/github.com/wetware/rs/capnp/peer_capnp.rs" - )); + include!(concat!(env!("OUT_DIR"), "/peer_capnp.rs")); +} + +#[allow(dead_code)] +mod stem_capnp { + include!(concat!(env!("OUT_DIR"), "/stem_capnp.rs")); +} + +#[allow(dead_code)] +mod membrane_capnp { + include!(concat!(env!("OUT_DIR"), "/membrane_capnp.rs")); } struct StderrLogger; @@ -52,32 +59,44 @@ fn run_impl() { init_logging(); log::trace!("pid0: start"); - wetware_guest::run(|host: peer_capnp::host::Client| async move { - log::trace!("pid0: rpc bootstrapped"); - const CHILD_WASM: &[u8] = - include_bytes!("../../child-echo/target/wasm32-wasip2/release/child_echo.wasm"); - - let executor = host.executor_request().send().pipeline.get_executor(); - - let mut request = executor.run_bytes_request(); - { - let mut params = request.get(); - params.set_wasm(CHILD_WASM); - params.reborrow().init_args(0); - params.reborrow().init_env(0); - } - log::trace!("pid0: runBytes sent"); - - let run_resp = request.send().promise.await?; - let process = run_resp.get()?.get_process()?; - log::trace!("pid0: got process"); - - let wait_resp = process.wait_request().send().promise.await?; - let exit_code = wait_resp.get()?.get_exit_code(); - log::trace!("pid0: child exited with code {}", exit_code); - - Ok(()) - }); + // Bootstrap a Membrane(WetwareSession) instead of a bare Host. + // The membrane provides epoch-scoped sessions with Host + Executor. + wetware_guest::run( + |membrane: stem_capnp::membrane::Client| async move { + log::trace!("pid0: rpc bootstrapped, grafting onto membrane"); + + // Graft onto the membrane to get an epoch-scoped session. + // No signer needed — stem's graft() currently ignores it. + let graft_resp = membrane.graft_request().send().promise.await?; + let session = graft_resp.get()?.get_session()?; + let ext = session.get_extension()?; + log::trace!("pid0: grafted, got session"); + + let executor = ext.get_executor()?; + + const CHILD_WASM: &[u8] = + include_bytes!("../../child-echo/target/wasm32-wasip2/release/child_echo.wasm"); + + let mut request = executor.run_bytes_request(); + { + let mut params = request.get(); + params.set_wasm(CHILD_WASM); + params.reborrow().init_args(0); + params.reborrow().init_env(0); + } + log::trace!("pid0: runBytes sent"); + + let run_resp = request.send().promise.await?; + let process = run_resp.get()?.get_process()?; + log::trace!("pid0: got process"); + + let wait_resp = process.wait_request().send().promise.await?; + let exit_code = wait_resp.get()?.get_exit_code(); + log::trace!("pid0: child exited with code {}", exit_code); + + Ok(()) + }, + ); log::trace!("pid0: cleanup complete"); } diff --git a/src/cell/executor.rs b/src/cell/executor.rs index bc1cfdf7..665574fa 100644 --- a/src/cell/executor.rs +++ b/src/cell/executor.rs @@ -203,8 +203,21 @@ impl Command { let (reader, writer) = handles .take_host_split() .ok_or_else(|| anyhow::anyhow!("host stream missing; RPC streams already consumed"))?; - let rpc_system = - crate::rpc::build_peer_rpc(reader, writer, network_state, swarm_cmd_tx, wasm_debug); + // Static epoch (never advances) — real epoch wiring is a future concern. + let initial_epoch = stem::membrane::Epoch { + seq: 0, + head: vec![], + adopted_block: 0, + }; + let (_epoch_tx, epoch_rx) = tokio::sync::watch::channel(initial_epoch); + let rpc_system = crate::rpc::membrane::build_membrane_rpc( + reader, + writer, + network_state, + swarm_cmd_tx, + wasm_debug, + epoch_rx, + ); info!("Starting streams RPC server for guest"); let local = tokio::task::LocalSet::new(); From 915c3bf035d2f05069496ee4fd760af9022c7c1c Mon Sep 17 00:00:00 2001 From: Louis Thibault Date: Thu, 12 Feb 2026 22:12:58 -0500 Subject: [PATCH 10/10] pid0: add Membrane type alias for readability --- guests/pid0/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/guests/pid0/src/lib.rs b/guests/pid0/src/lib.rs index 1f96c96d..8fa97fd2 100644 --- a/guests/pid0/src/lib.rs +++ b/guests/pid0/src/lib.rs @@ -18,6 +18,9 @@ mod membrane_capnp { include!(concat!(env!("OUT_DIR"), "/membrane_capnp.rs")); } +/// Bootstrap capability: a Membrane whose sessions carry our WetwareSession extension. +type Membrane = stem_capnp::membrane::Client; + struct StderrLogger; impl log::Log for StderrLogger { @@ -62,7 +65,7 @@ fn run_impl() { // Bootstrap a Membrane(WetwareSession) instead of a bare Host. // The membrane provides epoch-scoped sessions with Host + Executor. wetware_guest::run( - |membrane: stem_capnp::membrane::Client| async move { + |membrane: Membrane| async move { log::trace!("pid0: rpc bootstrapped, grafting onto membrane"); // Graft onto the membrane to get an epoch-scoped session.