From 0e2e700aef3ef15f53240867143d4eeb93d4d0a0 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Wed, 27 Mar 2024 21:30:33 +0000 Subject: [PATCH 01/34] initial rust commit --- .gitignore | 5 + Cargo.lock | 1665 +++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 18 + src/main.rs | 159 +++++ 4 files changed, 1847 insertions(+) create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore index 54b2e7c75..c7aa45d49 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,8 @@ __pycache__ warnet.egg-info .python-version .env + + +# Added by cargo + +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 000000000..3b70c7e7e --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1665 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "anstream" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" + +[[package]] +name = "async-lock" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-trait" +version = "0.1.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cc" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "concurrent-queue" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "event-listener" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" +dependencies = [ + "gloo-timers", + "send_wrapper", +] + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "gloo-net" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43aaa242d1239a8822c15c645f02166398da4f8b5c4bae795c1f5b44e9eee173" +dependencies = [ + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils", + "http", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "gloo-utils" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "h2" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http", + "hyper", + "log", + "rustls 0.21.10", + "rustls-native-certs 0.6.3", + "tokio", + "tokio-rustls 0.24.1", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jsonrpsee" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cdbb7cb6f3ba28f5b212dd250ab4483105efc3e381f5c8bb90340f14f0a2cc3" +dependencies = [ + "jsonrpsee-client-transport", + "jsonrpsee-core", + "jsonrpsee-http-client", + "jsonrpsee-types", + "jsonrpsee-wasm-client", + "jsonrpsee-ws-client", +] + +[[package]] +name = "jsonrpsee-client-transport" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ab2e14e727d2faf388c99d9ca5210566ed3b044f07d92c29c3611718d178380" +dependencies = [ + "futures-channel", + "futures-util", + "gloo-net", + "http", + "jsonrpsee-core", + "pin-project", + "rustls-native-certs 0.7.0", + "rustls-pki-types", + "soketto", + "thiserror", + "tokio", + "tokio-rustls 0.25.0", + "tokio-util", + "tracing", + "url", + "webpki-roots", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71962a1c49af43adf81d337e4ebc93f3c915faf6eccaa14d74e255107dfd7723" +dependencies = [ + "anyhow", + "async-lock", + "async-trait", + "beef", + "futures-timer", + "futures-util", + "hyper", + "jsonrpsee-types", + "pin-project", + "rustc-hash", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-stream", + "tracing", + "wasm-bindgen-futures", +] + +[[package]] +name = "jsonrpsee-http-client" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c13987da51270bda2c1c9b40c19be0fe9b225c7a0553963d8f17e683a50ce84" +dependencies = [ + "async-trait", + "hyper", + "hyper-rustls", + "jsonrpsee-core", + "jsonrpsee-types", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "tracing", + "url", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e53c72de6cd2ad6ac1aa6e848206ef8b736f92ed02354959130373dfa5b3cbd" +dependencies = [ + "anyhow", + "beef", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "jsonrpsee-wasm-client" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae2c3f2411052b4a831cb7a34cd1498e0d8b9309bd49fca67567634ff64023d" +dependencies = [ + "jsonrpsee-client-transport", + "jsonrpsee-core", + "jsonrpsee-types", +] + +[[package]] +name = "jsonrpsee-ws-client" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8a07ab8da9a283b906f6735ddd17d3680158bb72259e853441d1dd0167079ec" +dependencies = [ + "http", + "jsonrpsee-client-transport", + "jsonrpsee-core", + "jsonrpsee-types", + "url", +] + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustls" +version = "0.21.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", +] + +[[package]] +name = "rustls" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99008d7ad0bbbea527ec27bddbc0e432c5b87d8175178cee68d2eec9c4a1813c" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.2", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile 1.0.4", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.1.1", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f48172685e6ff52a556baa527774f61fcaa884f59daf3375c62a3f1cd2549dab" +dependencies = [ + "base64 0.21.7", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "send_wrapper" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "socket2" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "soketto" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" +dependencies = [ + "base64 0.13.1", + "bytes", + "futures", + "httparse", + "log", + "rand", + "sha-1", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "strsim" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "2.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.10", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls 0.22.3", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "warnet" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "jsonrpsee", + "serde", + "serde_json", + "tokio", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.4", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..d7799d75c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "warnet" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.81" +clap = { version = "4.5.4", features = ["derive"] } +jsonrpsee = { version = "0.22.3", features = ["http-client", "client"] } +serde = { version = "1.0.197", features = ["derive"] } +serde_json = "1.0.115" +tokio = { version = "1.36.0", features = ["rt-multi-thread"] } + +[[bin]] +name = "warcli" +path = "src/main.rs" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 000000000..e35726d1a --- /dev/null +++ b/src/main.rs @@ -0,0 +1,159 @@ +use clap::{Parser, Subcommand}; +use jsonrpsee::core::client::ClientT; +use jsonrpsee::http_client::HttpClientBuilder; +use jsonrpsee::rpc_params; +use serde_json::Value; +use std::path::PathBuf; + +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +struct Cli { + #[arg(long, default_value = "warnet")] + network: Option, + + #[command(subcommand)] + command: Option, +} + +#[derive(Subcommand, Debug)] +enum Commands { + /// Network commands + Network { + #[command(subcommand)] + command: Option, + }, + /// Debug commands + Debug { + #[command(subcommand)] + command: Option, + }, +} + +#[derive(Subcommand, Debug)] +enum NetworkCommands { + /// Start a network from a + Start { + graph_file: PathBuf, + #[arg(long, short)] + force: bool, + }, + /// Bring a network back up + Up {}, + /// Take a network down + Down {}, + /// Get network info + Info {}, + /// Shows the status of a network + Status {}, + /// Return if network is connected + Connected {}, + /// Export network details for sim-ln + Export {}, +} + +#[derive(Subcommand, Debug)] +enum DebugCommands { + /// Generate the docker-compose file for a given and return it. + GenerateCompose { graph_file: PathBuf }, +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let cli = Cli::parse(); + let mut request = ""; + let mut params = rpc_params![]; + + // Create request + match &cli.command { + Some(Commands::Network { command }) => match command { + Some(NetworkCommands::Start { graph_file, force }) => { + request = "network_from_file"; + params.insert(graph_file)?; + params.insert(force)?; + } + Some(NetworkCommands::Up {}) => { + request = "network_up"; + } + Some(NetworkCommands::Down {}) => { + request = "network_down"; + } + Some(NetworkCommands::Info {}) => { + request = "network_info"; + } + Some(NetworkCommands::Status {}) => { + request = "network_status"; + } + Some(NetworkCommands::Connected {}) => { + request = "network_connected"; + } + Some(NetworkCommands::Export {}) => { + request = "network_export"; + } + _ => println!("Unknown Network command"), + }, + + Some(Commands::Debug { command }) => match command { + Some(DebugCommands::GenerateCompose { graph_file: _ }) => { + request = "generate_compose"; + } + _ => println!("Unknown Debug command"), + }, + None => { + println!("No command provided"); + } + } + if request.is_empty() { + return Err(anyhow::Error::msg("No command specified")); + }; + + let url = "http://127.0.0.1:9276/api"; + let client = HttpClientBuilder::default().build(url)?; + let response = client.request::(request, params).await; + + if let Err(error) = response { + println!("Error decoding json: {:?}", error); + return Err(anyhow::Error::new(error)); + } + let data = response.unwrap(); + // println!("Got data:\n{}", data); + + // Custom response handling + match &cli.command { + Some(Commands::Network { command }) => match command { + Some(NetworkCommands::Start { + graph_file: _, + force: _, + }) => {} + Some(NetworkCommands::Up {}) => {} + Some(NetworkCommands::Down {}) => {} + Some(NetworkCommands::Info {}) => {} + Some(NetworkCommands::Status {}) => { + if let serde_json::Value::Array(items) = &data { + for item in items { + if let (Some(tank_index), Some(bitcoin_status)) = ( + item.get("tank_index").and_then(|v| v.as_i64()), + item.get("bitcoin_status").and_then(|v| v.as_str()), + ) { + println!("Tank: {:<6} Bitcoin: {}", tank_index, bitcoin_status); + } else { + println!("Error: Response item is missing expected fields"); + } + } + } else { + println!("Error: Expected an array in the response"); + } + } + Some(NetworkCommands::Connected {}) => {} + Some(NetworkCommands::Export {}) => {} + _ => return Ok(()), + }, + + Some(Commands::Debug { command }) => match command { + Some(DebugCommands::GenerateCompose { graph_file: _ }) => {} + _ => return Ok(()), + }, + None => return Ok(()), + } + + Ok(()) +} From cc20d8b63c2714b7a559fc798cbe6dfdd64d83a0 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Thu, 28 Mar 2024 12:12:29 +0000 Subject: [PATCH 02/34] split into logical modules --- Cargo.lock | 7 +++ Cargo.toml | 1 + src/debug.rs | 23 +++++++++ src/main.rs | 135 +++++------------------------------------------- src/network.rs | 74 ++++++++++++++++++++++++++ src/rpc_call.rs | 12 +++++ 6 files changed, 131 insertions(+), 121 deletions(-) create mode 100644 src/debug.rs create mode 100644 src/network.rs create mode 100644 src/rpc_call.rs diff --git a/Cargo.lock b/Cargo.lock index 3b70c7e7e..081c73694 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -126,6 +126,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" + [[package]] name = "beef" version = "0.5.2" @@ -1428,6 +1434,7 @@ name = "warnet" version = "0.1.0" dependencies = [ "anyhow", + "base64 0.22.0", "clap", "jsonrpsee", "serde", diff --git a/Cargo.toml b/Cargo.toml index d7799d75c..65cd21c41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] anyhow = "1.0.81" +base64 = "0.22.0" clap = { version = "4.5.4", features = ["derive"] } jsonrpsee = { version = "0.22.3", features = ["http-client", "client"] } serde = { version = "1.0.197", features = ["derive"] } diff --git a/src/debug.rs b/src/debug.rs new file mode 100644 index 000000000..eb19988a3 --- /dev/null +++ b/src/debug.rs @@ -0,0 +1,23 @@ +use std::path::PathBuf; + +use clap::Subcommand; +use jsonrpsee::rpc_params; + +use crate::rpc_call::make_rpc_call; + +#[derive(Subcommand, Debug)] +pub enum DebugCommands { + /// Generate the docker-compose file for a given and return it. + GenerateCompose { graph_file: PathBuf }, +} + +pub async fn handle_debug_command(command: &DebugCommands) -> anyhow::Result<()> { + match command { + DebugCommands::GenerateCompose { graph_file } => { + let params = rpc_params![graph_file.to_string_lossy()]; + let data = make_rpc_call("generate_compose", params).await?; + println!("Docker-compose file generated: {:?}", data); + } + } + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index e35726d1a..37e2e9518 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,10 @@ use clap::{Parser, Subcommand}; -use jsonrpsee::core::client::ClientT; -use jsonrpsee::http_client::HttpClientBuilder; -use jsonrpsee::rpc_params; -use serde_json::Value; -use std::path::PathBuf; + +use crate::debug::{handle_debug_command, DebugCommands}; +use crate::network::{handle_network_command, NetworkCommands}; +mod debug; +mod network; +mod rpc_call; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] @@ -29,130 +30,22 @@ enum Commands { }, } -#[derive(Subcommand, Debug)] -enum NetworkCommands { - /// Start a network from a - Start { - graph_file: PathBuf, - #[arg(long, short)] - force: bool, - }, - /// Bring a network back up - Up {}, - /// Take a network down - Down {}, - /// Get network info - Info {}, - /// Shows the status of a network - Status {}, - /// Return if network is connected - Connected {}, - /// Export network details for sim-ln - Export {}, -} - -#[derive(Subcommand, Debug)] -enum DebugCommands { - /// Generate the docker-compose file for a given and return it. - GenerateCompose { graph_file: PathBuf }, -} - #[tokio::main] async fn main() -> anyhow::Result<()> { let cli = Cli::parse(); - let mut request = ""; - let mut params = rpc_params![]; - // Create request match &cli.command { - Some(Commands::Network { command }) => match command { - Some(NetworkCommands::Start { graph_file, force }) => { - request = "network_from_file"; - params.insert(graph_file)?; - params.insert(force)?; - } - Some(NetworkCommands::Up {}) => { - request = "network_up"; - } - Some(NetworkCommands::Down {}) => { - request = "network_down"; - } - Some(NetworkCommands::Info {}) => { - request = "network_info"; - } - Some(NetworkCommands::Status {}) => { - request = "network_status"; + Some(Commands::Network { command }) => { + if let Some(command) = command { + handle_network_command(command).await?; } - Some(NetworkCommands::Connected {}) => { - request = "network_connected"; - } - Some(NetworkCommands::Export {}) => { - request = "network_export"; - } - _ => println!("Unknown Network command"), - }, - - Some(Commands::Debug { command }) => match command { - Some(DebugCommands::GenerateCompose { graph_file: _ }) => { - request = "generate_compose"; - } - _ => println!("Unknown Debug command"), - }, - None => { - println!("No command provided"); } - } - if request.is_empty() { - return Err(anyhow::Error::msg("No command specified")); - }; - - let url = "http://127.0.0.1:9276/api"; - let client = HttpClientBuilder::default().build(url)?; - let response = client.request::(request, params).await; - - if let Err(error) = response { - println!("Error decoding json: {:?}", error); - return Err(anyhow::Error::new(error)); - } - let data = response.unwrap(); - // println!("Got data:\n{}", data); - - // Custom response handling - match &cli.command { - Some(Commands::Network { command }) => match command { - Some(NetworkCommands::Start { - graph_file: _, - force: _, - }) => {} - Some(NetworkCommands::Up {}) => {} - Some(NetworkCommands::Down {}) => {} - Some(NetworkCommands::Info {}) => {} - Some(NetworkCommands::Status {}) => { - if let serde_json::Value::Array(items) = &data { - for item in items { - if let (Some(tank_index), Some(bitcoin_status)) = ( - item.get("tank_index").and_then(|v| v.as_i64()), - item.get("bitcoin_status").and_then(|v| v.as_str()), - ) { - println!("Tank: {:<6} Bitcoin: {}", tank_index, bitcoin_status); - } else { - println!("Error: Response item is missing expected fields"); - } - } - } else { - println!("Error: Expected an array in the response"); - } + Some(Commands::Debug { command }) => { + if let Some(command) = command { + handle_debug_command(command).await?; } - Some(NetworkCommands::Connected {}) => {} - Some(NetworkCommands::Export {}) => {} - _ => return Ok(()), - }, - - Some(Commands::Debug { command }) => match command { - Some(DebugCommands::GenerateCompose { graph_file: _ }) => {} - _ => return Ok(()), - }, - None => return Ok(()), + } + None => println!("No command provided"), } Ok(()) diff --git a/src/network.rs b/src/network.rs new file mode 100644 index 000000000..3b07110c4 --- /dev/null +++ b/src/network.rs @@ -0,0 +1,74 @@ +use base64::{engine::general_purpose, Engine as _}; +use clap::Subcommand; +use jsonrpsee::rpc_params; +use std::path::PathBuf; + +use crate::rpc_call::make_rpc_call; + +#[derive(Subcommand, Debug)] +pub enum NetworkCommands { + /// Start a network from a + Start { + graph_file: PathBuf, + #[arg(long, short)] + force: bool, + }, + /// Bring a network back up + Up {}, + /// Take a network down + Down {}, + /// Get network info + Info {}, + /// Shows the status of a network + Status {}, + /// Return if network is connected + Connected {}, + /// Export network details for sim-ln + Export {}, +} + +pub async fn handle_network_command(command: &NetworkCommands) -> anyhow::Result<()> { + let (request, params) = match command { + NetworkCommands::Start { graph_file, force } => { + let file_contents = std::fs::read(graph_file) + .map_err(|e| anyhow::Error::new(e).context("Failed to read graph file"))?; + // base64 encode + let graph_file_base64 = general_purpose::STANDARD.encode(file_contents); + ("network_from_file", rpc_params![graph_file_base64, *force]) + } + NetworkCommands::Up {} => ("network_up", rpc_params![]), + NetworkCommands::Down {} => ("network_down", rpc_params![]), + NetworkCommands::Info {} => ("network_info", rpc_params![]), + NetworkCommands::Status {} => ("network_status", rpc_params![]), + NetworkCommands::Connected {} => ("network_connected", rpc_params![]), + NetworkCommands::Export {} => ("network_export", rpc_params![]), + }; + + let data = make_rpc_call(request, params).await?; + match request { + "network_status" => { + if let serde_json::Value::Array(items) = &data { + for item in items { + if let (Some(tank_index), Some(bitcoin_status)) = ( + item.get("tank_index").and_then(|v| v.as_i64()), + item.get("bitcoin_status").and_then(|v| v.as_str()), + ) { + println!("Tank: {:<6} Bitcoin: {}", tank_index, bitcoin_status); + } else { + println!("Error: Response item is missing expected fields"); + } + } + } else { + println!("Error: Expected an array in the response"); + } + } + "network_start" => { + println!("Got response: {}", data); + } + _ => { + println!("Got response: {}", data) + } + } + // TODO: add response handling for other network commands + Ok(()) +} diff --git a/src/rpc_call.rs b/src/rpc_call.rs new file mode 100644 index 000000000..e5c41096d --- /dev/null +++ b/src/rpc_call.rs @@ -0,0 +1,12 @@ +use jsonrpsee::{core::client::ClientT, http_client::HttpClientBuilder}; +use serde_json::Value; + +pub async fn make_rpc_call( + request: &str, + params: jsonrpsee::core::params::ArrayParams, +) -> anyhow::Result { + let url = "http://127.0.0.1:9276/api"; + let client = HttpClientBuilder::default().build(url)?; + let response = client.request::(request, params).await?; + Ok(response) +} From 6724739e98b069d91247003fc8201c71599a31e6 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Thu, 28 Mar 2024 16:09:24 +0000 Subject: [PATCH 03/34] use anyhow, and pass network arg --- src/debug.rs | 13 ++++++++----- src/main.rs | 6 +++--- src/network.rs | 29 ++++++++++++++++------------- src/rpc_call.rs | 3 ++- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/debug.rs b/src/debug.rs index eb19988a3..990a8da37 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -1,20 +1,23 @@ +use jsonrpsee::core::params::ObjectParams; use std::path::PathBuf; +use anyhow::Context; use clap::Subcommand; -use jsonrpsee::rpc_params; use crate::rpc_call::make_rpc_call; #[derive(Subcommand, Debug)] pub enum DebugCommands { /// Generate the docker-compose file for a given and return it. - GenerateCompose { graph_file: PathBuf }, + GenerateCompose { graph_file_path: PathBuf }, } -pub async fn handle_debug_command(command: &DebugCommands) -> anyhow::Result<()> { +pub async fn handle_debug_command(command: &DebugCommands, network: &String) -> anyhow::Result<()> { + let mut params = ObjectParams::new(); + params.insert("network", network).context("Add network to params")?; match command { - DebugCommands::GenerateCompose { graph_file } => { - let params = rpc_params![graph_file.to_string_lossy()]; + DebugCommands::GenerateCompose { graph_file_path } => { + params.insert("graph_file", graph_file_path.to_str()).context("Add graph file path to params")?; let data = make_rpc_call("generate_compose", params).await?; println!("Docker-compose file generated: {:?}", data); } diff --git a/src/main.rs b/src/main.rs index 37e2e9518..81a93d4cb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ mod rpc_call; #[command(version, about, long_about = None)] struct Cli { #[arg(long, default_value = "warnet")] - network: Option, + network: String, #[command(subcommand)] command: Option, @@ -37,12 +37,12 @@ async fn main() -> anyhow::Result<()> { match &cli.command { Some(Commands::Network { command }) => { if let Some(command) = command { - handle_network_command(command).await?; + handle_network_command(command, &cli.network).await?; } } Some(Commands::Debug { command }) => { if let Some(command) = command { - handle_debug_command(command).await?; + handle_debug_command(command, &cli.network).await?; } } None => println!("No command provided"), diff --git a/src/network.rs b/src/network.rs index 3b07110c4..ee014e02a 100644 --- a/src/network.rs +++ b/src/network.rs @@ -1,7 +1,8 @@ use base64::{engine::general_purpose, Engine as _}; use clap::Subcommand; -use jsonrpsee::rpc_params; +use jsonrpsee::core::params::ObjectParams; use std::path::PathBuf; +use anyhow::Context; use crate::rpc_call::make_rpc_call; @@ -27,21 +28,23 @@ pub enum NetworkCommands { Export {}, } -pub async fn handle_network_command(command: &NetworkCommands) -> anyhow::Result<()> { +pub async fn handle_network_command(command: &NetworkCommands, network: &String) -> anyhow::Result<()> { + let mut params = ObjectParams::new(); + params.insert("network", network).context("Add network to params")?; let (request, params) = match command { NetworkCommands::Start { graph_file, force } => { - let file_contents = std::fs::read(graph_file) - .map_err(|e| anyhow::Error::new(e).context("Failed to read graph file"))?; - // base64 encode + let file_contents = std::fs::read(graph_file).context("Failed to read graph file")?; let graph_file_base64 = general_purpose::STANDARD.encode(file_contents); - ("network_from_file", rpc_params![graph_file_base64, *force]) + params.insert("graph_file", graph_file_base64).context("Add base64 graph file to params")?; + params.insert("force", *force).context("Add force bool to params")?; + ("network_from_file", params) } - NetworkCommands::Up {} => ("network_up", rpc_params![]), - NetworkCommands::Down {} => ("network_down", rpc_params![]), - NetworkCommands::Info {} => ("network_info", rpc_params![]), - NetworkCommands::Status {} => ("network_status", rpc_params![]), - NetworkCommands::Connected {} => ("network_connected", rpc_params![]), - NetworkCommands::Export {} => ("network_export", rpc_params![]), + NetworkCommands::Up {} => ("network_up", params), + NetworkCommands::Down {} => ("network_down", params), + NetworkCommands::Info {} => ("network_info", params), + NetworkCommands::Status {} => ("network_status", params), + NetworkCommands::Connected {} => ("network_connected", params), + NetworkCommands::Export {} => ("network_export", params), }; let data = make_rpc_call(request, params).await?; @@ -66,7 +69,7 @@ pub async fn handle_network_command(command: &NetworkCommands) -> anyhow::Result println!("Got response: {}", data); } _ => { - println!("Got response: {}", data) + println!("{}", data) } } // TODO: add response handling for other network commands diff --git a/src/rpc_call.rs b/src/rpc_call.rs index e5c41096d..814d34734 100644 --- a/src/rpc_call.rs +++ b/src/rpc_call.rs @@ -1,9 +1,10 @@ use jsonrpsee::{core::client::ClientT, http_client::HttpClientBuilder}; + use serde_json::Value; pub async fn make_rpc_call( request: &str, - params: jsonrpsee::core::params::ArrayParams, + params: jsonrpsee::core::params::ObjectParams, ) -> anyhow::Result { let url = "http://127.0.0.1:9276/api"; let client = HttpClientBuilder::default().build(url)?; From cf7f3ce8c768d38bbd922ece97c8c5934422b707 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Thu, 28 Mar 2024 16:12:54 +0000 Subject: [PATCH 04/34] move to rust-cli subdir --- Cargo.toml | 2 +- src/{ => rust-cli}/debug.rs | 0 src/{ => rust-cli}/main.rs | 0 src/{ => rust-cli}/network.rs | 0 src/{ => rust-cli}/rpc_call.rs | 0 5 files changed, 1 insertion(+), 1 deletion(-) rename src/{ => rust-cli}/debug.rs (100%) rename src/{ => rust-cli}/main.rs (100%) rename src/{ => rust-cli}/network.rs (100%) rename src/{ => rust-cli}/rpc_call.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 65cd21c41..e3d9da08a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,4 +16,4 @@ tokio = { version = "1.36.0", features = ["rt-multi-thread"] } [[bin]] name = "warcli" -path = "src/main.rs" +path = "src/rust-cli/main.rs" diff --git a/src/debug.rs b/src/rust-cli/debug.rs similarity index 100% rename from src/debug.rs rename to src/rust-cli/debug.rs diff --git a/src/main.rs b/src/rust-cli/main.rs similarity index 100% rename from src/main.rs rename to src/rust-cli/main.rs diff --git a/src/network.rs b/src/rust-cli/network.rs similarity index 100% rename from src/network.rs rename to src/rust-cli/network.rs diff --git a/src/rpc_call.rs b/src/rust-cli/rpc_call.rs similarity index 100% rename from src/rpc_call.rs rename to src/rust-cli/rpc_call.rs From c2f7cdd2a77959a93f17eeea0f66fb15924616d1 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Thu, 28 Mar 2024 16:21:11 +0000 Subject: [PATCH 05/34] add scenarios & available --- Cargo.lock | 164 +++++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + src/rust-cli/main.rs | 14 +++- src/rust-cli/scenarios.rs | 39 +++++++++ src/warnet/server.py | 2 +- 5 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 src/rust-cli/scenarios.rs diff --git a/Cargo.lock b/Cargo.lock index 081c73694..808343581 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -147,6 +147,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + [[package]] name = "block-buffer" version = "0.9.0" @@ -266,6 +272,27 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +[[package]] +name = "csv" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", +] + [[package]] name = "digest" version = "0.9.0" @@ -275,6 +302,33 @@ dependencies = [ "generic-array", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "equivalent" version = "1.0.1" @@ -596,6 +650,17 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "is-terminal" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "itoa" version = "1.0.11" @@ -731,12 +796,29 @@ dependencies = [ "url", ] +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.5.0", + "libc", + "redox_syscall", +] + [[package]] name = "log" version = "0.4.21" @@ -856,6 +938,20 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "prettytable-rs" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a" +dependencies = [ + "csv", + "encode_unicode", + "is-terminal", + "lazy_static", + "term", + "unicode-width", +] + [[package]] name = "proc-macro2" version = "1.0.79" @@ -904,6 +1000,26 @@ dependencies = [ "getrandom", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "ring" version = "0.17.8" @@ -1028,6 +1144,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "ryu" version = "1.0.17" @@ -1059,7 +1181,7 @@ version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -1189,6 +1311,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + [[package]] name = "thiserror" version = "1.0.58" @@ -1391,6 +1524,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + [[package]] name = "untrusted" version = "0.9.0" @@ -1437,6 +1576,7 @@ dependencies = [ "base64 0.22.0", "clap", "jsonrpsee", + "prettytable-rs", "serde", "serde_json", "tokio", @@ -1533,6 +1673,28 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index e3d9da08a..f129629f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ anyhow = "1.0.81" base64 = "0.22.0" clap = { version = "4.5.4", features = ["derive"] } jsonrpsee = { version = "0.22.3", features = ["http-client", "client"] } +prettytable-rs = "0.10.0" serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" tokio = { version = "1.36.0", features = ["rt-multi-thread"] } diff --git a/src/rust-cli/main.rs b/src/rust-cli/main.rs index 81a93d4cb..f755aab81 100644 --- a/src/rust-cli/main.rs +++ b/src/rust-cli/main.rs @@ -2,9 +2,11 @@ use clap::{Parser, Subcommand}; use crate::debug::{handle_debug_command, DebugCommands}; use crate::network::{handle_network_command, NetworkCommands}; +use crate::scenarios::{handle_scenario_command, ScenarioCommands}; mod debug; mod network; mod rpc_call; +mod scenarios; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] @@ -23,11 +25,16 @@ enum Commands { #[command(subcommand)] command: Option, }, - /// Debug commands + /// Debug commands [[deprecated]] Debug { #[command(subcommand)] command: Option, }, + /// Scenario commands + Scenarios { + #[command(subcommand)] + command: Option, + }, } #[tokio::main] @@ -45,6 +52,11 @@ async fn main() -> anyhow::Result<()> { handle_debug_command(command, &cli.network).await?; } } + Some(Commands::Scenarios { command }) => { + if let Some(command) = command { + handle_scenario_command(command, &cli.network).await?; + } + } None => println!("No command provided"), } diff --git a/src/rust-cli/scenarios.rs b/src/rust-cli/scenarios.rs new file mode 100644 index 000000000..2c1c8978e --- /dev/null +++ b/src/rust-cli/scenarios.rs @@ -0,0 +1,39 @@ +use prettytable::{Table, row}; +use anyhow::Context; +use jsonrpsee::core::params::ObjectParams; +use clap::Subcommand; +use crate::rpc_call::make_rpc_call; + +#[derive(Subcommand, Debug)] +pub enum ScenarioCommands { + /// List available scenarios in the Warnet Test Framework + Available {}, +} + +pub async fn handle_scenario_command(command: &ScenarioCommands, network: &String) -> anyhow::Result<()> { + let mut params = ObjectParams::new(); + params.insert("network", network).context("Add network to params")?; + + match command { + ScenarioCommands::Available {} => { + let data = make_rpc_call("scenarios_available", params).await?; + if let serde_json::Value::Array(scenarios) = data { + let mut table = Table::new(); + table.add_row(row!["Scenario", "Description"]); + for scenario in scenarios { + if let serde_json::Value::Array(details) = scenario { + if details.len() == 2 { + let name = details[0].as_str().unwrap_or("Unknown"); + let description = details[1].as_str().unwrap_or("No description"); + table.add_row(row![name, description]); + } + } + } + table.printstd(); + } else { + println!("Unexpected response format."); + } + } + } + Ok(()) +} diff --git a/src/warnet/server.py b/src/warnet/server.py index f6e507215..d00be81a6 100644 --- a/src/warnet/server.py +++ b/src/warnet/server.py @@ -283,7 +283,7 @@ def network_export(self, network: str) -> str: self.logger.error(msg) raise ServerError(message=msg) from e - def scenarios_available(self) -> list[tuple]: + def scenarios_available(self, network: str) -> list[tuple]: """ List available scenarios in the Warnet Test Framework """ From 8e12b7254243046317149ba7aaea07a2b3000f45 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Thu, 28 Mar 2024 16:41:35 +0000 Subject: [PATCH 06/34] add more scenarios --- src/rust-cli/debug.rs | 10 +++-- src/rust-cli/network.rs | 19 ++++++--- src/rust-cli/scenarios.rs | 82 ++++++++++++++++++++++++++++++++++++--- src/warnet/server.py | 4 +- 4 files changed, 99 insertions(+), 16 deletions(-) diff --git a/src/rust-cli/debug.rs b/src/rust-cli/debug.rs index 990a8da37..4682790ef 100644 --- a/src/rust-cli/debug.rs +++ b/src/rust-cli/debug.rs @@ -1,6 +1,6 @@ +use anyhow::Context; use jsonrpsee::core::params::ObjectParams; use std::path::PathBuf; -use anyhow::Context; use clap::Subcommand; @@ -14,10 +14,14 @@ pub enum DebugCommands { pub async fn handle_debug_command(command: &DebugCommands, network: &String) -> anyhow::Result<()> { let mut params = ObjectParams::new(); - params.insert("network", network).context("Add network to params")?; + params + .insert("network", network) + .context("Add network to params")?; match command { DebugCommands::GenerateCompose { graph_file_path } => { - params.insert("graph_file", graph_file_path.to_str()).context("Add graph file path to params")?; + params + .insert("graph_file", graph_file_path.to_str()) + .context("Add graph file path to params")?; let data = make_rpc_call("generate_compose", params).await?; println!("Docker-compose file generated: {:?}", data); } diff --git a/src/rust-cli/network.rs b/src/rust-cli/network.rs index ee014e02a..ddcc2ce3b 100644 --- a/src/rust-cli/network.rs +++ b/src/rust-cli/network.rs @@ -1,8 +1,8 @@ +use anyhow::Context; use base64::{engine::general_purpose, Engine as _}; use clap::Subcommand; use jsonrpsee::core::params::ObjectParams; use std::path::PathBuf; -use anyhow::Context; use crate::rpc_call::make_rpc_call; @@ -28,15 +28,24 @@ pub enum NetworkCommands { Export {}, } -pub async fn handle_network_command(command: &NetworkCommands, network: &String) -> anyhow::Result<()> { +pub async fn handle_network_command( + command: &NetworkCommands, + network: &String, +) -> anyhow::Result<()> { let mut params = ObjectParams::new(); - params.insert("network", network).context("Add network to params")?; + params + .insert("network", network) + .context("Add network to params")?; let (request, params) = match command { NetworkCommands::Start { graph_file, force } => { let file_contents = std::fs::read(graph_file).context("Failed to read graph file")?; let graph_file_base64 = general_purpose::STANDARD.encode(file_contents); - params.insert("graph_file", graph_file_base64).context("Add base64 graph file to params")?; - params.insert("force", *force).context("Add force bool to params")?; + params + .insert("graph_file", graph_file_base64) + .context("Add base64 graph file to params")?; + params + .insert("force", *force) + .context("Add force bool to params")?; ("network_from_file", params) } NetworkCommands::Up {} => ("network_up", params), diff --git a/src/rust-cli/scenarios.rs b/src/rust-cli/scenarios.rs index 2c1c8978e..690d7539a 100644 --- a/src/rust-cli/scenarios.rs +++ b/src/rust-cli/scenarios.rs @@ -1,22 +1,37 @@ -use prettytable::{Table, row}; +use crate::rpc_call::make_rpc_call; use anyhow::Context; -use jsonrpsee::core::params::ObjectParams; use clap::Subcommand; -use crate::rpc_call::make_rpc_call; +use jsonrpsee::core::params::ObjectParams; +use prettytable::{row, Table}; #[derive(Subcommand, Debug)] pub enum ScenarioCommands { /// List available scenarios in the Warnet Test Framework Available {}, + Run { + scenario: String, + additional_args: Vec, + }, + Active {}, + Stop { + pid: u64, + }, } -pub async fn handle_scenario_command(command: &ScenarioCommands, network: &String) -> anyhow::Result<()> { +pub async fn handle_scenario_command( + command: &ScenarioCommands, + network: &String, +) -> anyhow::Result<()> { let mut params = ObjectParams::new(); - params.insert("network", network).context("Add network to params")?; + params + .insert("network", network) + .context("Add network to params")?; match command { ScenarioCommands::Available {} => { - let data = make_rpc_call("scenarios_available", params).await?; + let data = make_rpc_call("scenarios_available", params) + .await + .context("Failed to fetch available scenarios")?; if let serde_json::Value::Array(scenarios) = data { let mut table = Table::new(); table.add_row(row!["Scenario", "Description"]); @@ -34,6 +49,61 @@ pub async fn handle_scenario_command(command: &ScenarioCommands, network: &Strin println!("Unexpected response format."); } } + ScenarioCommands::Run { + scenario, + additional_args, + } => { + params + .insert("scenario", scenario) + .context("Add scenario to params")?; + params + .insert("additional_args", additional_args) + .context("Add additional_args to params")?; + let data = make_rpc_call("scenarios_run", params) + .await + .context("Failed to run scenario")?; + println!("{:?}", data); + } + ScenarioCommands::Active {} => { + let data = make_rpc_call("scenarios_list_running", params) + .await + .context("Failed to list running scenarios")?; + if let serde_json::Value::Array(scenarios) = data { + let mut table = Table::new(); + table.add_row(row!["PID", "Command", "Network", "Active"]); + for scenario in scenarios { + if let serde_json::Value::Object(details) = scenario { + let pid = details + .get("pid") + .and_then(|v| v.as_i64()) + .map_or_else(|| "Unknown".to_string(), |v| v.to_string()); + let cmd = details + .get("cmd") + .and_then(|v| v.as_str()) + .unwrap_or("Unknown"); + let network = details + .get("network") + .and_then(|v| v.as_str()) + .unwrap_or("Unknown"); + let active = details + .get("active") + .and_then(|v| v.as_bool()) + .map_or_else(|| "Unknown".to_string(), |v| v.to_string()); + table.add_row(row![pid, cmd, network, active]); + } + } + table.printstd(); + } else { + println!("Unexpected response format."); + } + } + ScenarioCommands::Stop { pid } => { + params.insert("pid", pid).context("Add pid to params")?; + let data = make_rpc_call("scenarios_stop", params) + .await + .context("Failed to stop running scenario")?; + println!("{:?}", data); + } } Ok(()) } diff --git a/src/warnet/server.py b/src/warnet/server.py index d00be81a6..514515f36 100644 --- a/src/warnet/server.py +++ b/src/warnet/server.py @@ -403,7 +403,7 @@ def proc_logger(): self.logger.error(msg) raise ServerError(message=msg) from e - def scenarios_stop(self, pid: int) -> str: + def scenarios_stop(self, pid: int, network: str = "warnet") -> str: matching_scenarios = [sc for sc in self.running_scenarios if sc["pid"] == pid] if matching_scenarios: matching_scenarios[0]["proc"].terminate() # sends SIGTERM @@ -415,7 +415,7 @@ def scenarios_stop(self, pid: int) -> str: self.logger.error(msg) raise ServerError(message=msg) - def scenarios_list_running(self) -> list[dict]: + def scenarios_list_running(self, network: str) -> list[dict]: running = [ { "pid": sc["pid"], From 8df6caae479343344dc7e6b91838880176be90d1 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Thu, 28 Mar 2024 16:48:13 +0000 Subject: [PATCH 07/34] add run_file command --- src/rust-cli/scenarios.rs | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/src/rust-cli/scenarios.rs b/src/rust-cli/scenarios.rs index 690d7539a..0d36f32c5 100644 --- a/src/rust-cli/scenarios.rs +++ b/src/rust-cli/scenarios.rs @@ -1,21 +1,29 @@ use crate::rpc_call::make_rpc_call; use anyhow::Context; +use base64::{engine::general_purpose, Engine as _}; use clap::Subcommand; use jsonrpsee::core::params::ObjectParams; use prettytable::{row, Table}; +use std::path::PathBuf; #[derive(Subcommand, Debug)] pub enum ScenarioCommands { /// List available scenarios in the Warnet Test Framework Available {}, + /// Run a scenario from remote repository with Run { scenario: String, additional_args: Vec, }, - Active {}, - Stop { - pid: u64, + /// Run a local scenario by sending it to the server + RunFile { + scenario_path: PathBuf, + additional_args: Vec, }, + /// List active scenarios + Active {}, + /// Stop a scenario with + Stop { pid: u64 }, } pub async fn handle_scenario_command( @@ -64,6 +72,25 @@ pub async fn handle_scenario_command( .context("Failed to run scenario")?; println!("{:?}", data); } + + ScenarioCommands::RunFile { + scenario_path, + additional_args, + } => { + let file_contents = + std::fs::read(scenario_path).context("Failed to read scenario file")?; + let scenario_base64 = general_purpose::STANDARD.encode(file_contents); + params + .insert("scenario_base64", scenario_base64) + .context("Add scenario to params")?; + params + .insert("additional_args", additional_args) + .context("Add additional_args to params")?; + let data = make_rpc_call("scenarios_run_file", params) + .await + .context("Failed to run scenario")?; + println!("{:?}", data); + } ScenarioCommands::Active {} => { let data = make_rpc_call("scenarios_list_running", params) .await @@ -102,7 +129,11 @@ pub async fn handle_scenario_command( let data = make_rpc_call("scenarios_stop", params) .await .context("Failed to stop running scenario")?; - println!("{:?}", data); + if let serde_json::Value::String(message) = data { + println!("{}", message); + } else { + println!("Unexpected response format."); + } } } Ok(()) From 0182834c98ff6b2d21ee8adf1d5b050b21600e93 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Thu, 28 Mar 2024 19:59:13 +0000 Subject: [PATCH 08/34] add rpc command --- src/rust-cli/debug.rs | 6 +++--- src/rust-cli/general.rs | 38 ++++++++++++++++++++++++++++++++++++++ src/rust-cli/main.rs | 27 +++++++++++++++++++++------ src/rust-cli/network.rs | 20 ++++++++++---------- src/rust-cli/scenarios.rs | 14 +++++++------- 5 files changed, 79 insertions(+), 26 deletions(-) create mode 100644 src/rust-cli/general.rs diff --git a/src/rust-cli/debug.rs b/src/rust-cli/debug.rs index 4682790ef..daf60e1c1 100644 --- a/src/rust-cli/debug.rs +++ b/src/rust-cli/debug.rs @@ -7,18 +7,18 @@ use clap::Subcommand; use crate::rpc_call::make_rpc_call; #[derive(Subcommand, Debug)] -pub enum DebugCommands { +pub enum DebugCommand { /// Generate the docker-compose file for a given and return it. GenerateCompose { graph_file_path: PathBuf }, } -pub async fn handle_debug_command(command: &DebugCommands, network: &String) -> anyhow::Result<()> { +pub async fn handle_debug_command(command: &DebugCommand, network: &String) -> anyhow::Result<()> { let mut params = ObjectParams::new(); params .insert("network", network) .context("Add network to params")?; match command { - DebugCommands::GenerateCompose { graph_file_path } => { + DebugCommand::GenerateCompose { graph_file_path } => { params .insert("graph_file", graph_file_path.to_str()) .context("Add graph file path to params")?; diff --git a/src/rust-cli/general.rs b/src/rust-cli/general.rs new file mode 100644 index 000000000..3ec26d0ff --- /dev/null +++ b/src/rust-cli/general.rs @@ -0,0 +1,38 @@ +use crate::rpc_call::make_rpc_call; +use anyhow::Context; +use jsonrpsee::core::params::ObjectParams; +use serde_json::Value; + +pub fn pretty_print_value(value: &Value) -> anyhow::Result<()> { + // If `value` is a JSON Value, pretty print it + if let Value::String(inner_json) = &value { + let parsed_inner: Value = serde_json::from_str(inner_json).context("Failed to parse inner JSON")?; + println!("{}", serde_json::to_string_pretty(&parsed_inner).context("Failed to pretty print inner JSON")?); + } else { + // If `value` is not a string containing JSON, print it directly. + println!("{}", serde_json::to_string_pretty(&value).context("Failed to pretty print JSON")?); + } + Ok(()) +} + +pub async fn handle_rpc_command( + node: &u64, + method: &String, + params: &Option>, + network: &String, +) -> anyhow::Result<()> { + let mut rpc_params = ObjectParams::new(); + rpc_params.insert("node", node).context("add node param")?; + rpc_params + .insert("method", method) + .context("add method param")?; + if let Some(p) = params { + rpc_params.insert("params", p).context("add rpc params")?; + } + rpc_params + .insert("network", network) + .context("add network param")?; + let data = make_rpc_call("tank_bcli", rpc_params).await.context("Failed to make RPC call")?; + pretty_print_value(&data).context("pretty print result")?; + Ok(()) +} diff --git a/src/rust-cli/main.rs b/src/rust-cli/main.rs index f755aab81..3d515bc29 100644 --- a/src/rust-cli/main.rs +++ b/src/rust-cli/main.rs @@ -1,12 +1,14 @@ use clap::{Parser, Subcommand}; -use crate::debug::{handle_debug_command, DebugCommands}; -use crate::network::{handle_network_command, NetworkCommands}; -use crate::scenarios::{handle_scenario_command, ScenarioCommands}; mod debug; +mod general; mod network; mod rpc_call; mod scenarios; +use crate::debug::{handle_debug_command, DebugCommand}; +use crate::general::handle_rpc_command; +use crate::network::{handle_network_command, NetworkCommand}; +use crate::scenarios::{handle_scenario_command, ScenarioCommand}; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] @@ -23,17 +25,23 @@ enum Commands { /// Network commands Network { #[command(subcommand)] - command: Option, + command: Option, }, /// Debug commands [[deprecated]] Debug { #[command(subcommand)] - command: Option, + command: Option, }, /// Scenario commands Scenarios { #[command(subcommand)] - command: Option, + command: Option, + }, + /// Call bitcoin-cli [params] on in [network] + Rpc { + node: u64, + method: String, + params: Option>, }, } @@ -57,6 +65,13 @@ async fn main() -> anyhow::Result<()> { handle_scenario_command(command, &cli.network).await?; } } + Some(Commands::Rpc { + node, + method, + params, + }) => { + handle_rpc_command(node, method, params, &cli.network).await?; + } None => println!("No command provided"), } diff --git a/src/rust-cli/network.rs b/src/rust-cli/network.rs index ddcc2ce3b..a01912413 100644 --- a/src/rust-cli/network.rs +++ b/src/rust-cli/network.rs @@ -7,7 +7,7 @@ use std::path::PathBuf; use crate::rpc_call::make_rpc_call; #[derive(Subcommand, Debug)] -pub enum NetworkCommands { +pub enum NetworkCommand { /// Start a network from a Start { graph_file: PathBuf, @@ -29,7 +29,7 @@ pub enum NetworkCommands { } pub async fn handle_network_command( - command: &NetworkCommands, + command: &NetworkCommand, network: &String, ) -> anyhow::Result<()> { let mut params = ObjectParams::new(); @@ -37,7 +37,7 @@ pub async fn handle_network_command( .insert("network", network) .context("Add network to params")?; let (request, params) = match command { - NetworkCommands::Start { graph_file, force } => { + NetworkCommand::Start { graph_file, force } => { let file_contents = std::fs::read(graph_file).context("Failed to read graph file")?; let graph_file_base64 = general_purpose::STANDARD.encode(file_contents); params @@ -48,12 +48,12 @@ pub async fn handle_network_command( .context("Add force bool to params")?; ("network_from_file", params) } - NetworkCommands::Up {} => ("network_up", params), - NetworkCommands::Down {} => ("network_down", params), - NetworkCommands::Info {} => ("network_info", params), - NetworkCommands::Status {} => ("network_status", params), - NetworkCommands::Connected {} => ("network_connected", params), - NetworkCommands::Export {} => ("network_export", params), + NetworkCommand::Up {} => ("network_up", params), + NetworkCommand::Down {} => ("network_down", params), + NetworkCommand::Info {} => ("network_info", params), + NetworkCommand::Status {} => ("network_status", params), + NetworkCommand::Connected {} => ("network_connected", params), + NetworkCommand::Export {} => ("network_export", params), }; let data = make_rpc_call(request, params).await?; @@ -75,7 +75,7 @@ pub async fn handle_network_command( } } "network_start" => { - println!("Got response: {}", data); + todo!("Format this {:?}", data); } _ => { println!("{}", data) diff --git a/src/rust-cli/scenarios.rs b/src/rust-cli/scenarios.rs index 0d36f32c5..50deeb203 100644 --- a/src/rust-cli/scenarios.rs +++ b/src/rust-cli/scenarios.rs @@ -7,7 +7,7 @@ use prettytable::{row, Table}; use std::path::PathBuf; #[derive(Subcommand, Debug)] -pub enum ScenarioCommands { +pub enum ScenarioCommand { /// List available scenarios in the Warnet Test Framework Available {}, /// Run a scenario from remote repository with @@ -27,7 +27,7 @@ pub enum ScenarioCommands { } pub async fn handle_scenario_command( - command: &ScenarioCommands, + command: &ScenarioCommand, network: &String, ) -> anyhow::Result<()> { let mut params = ObjectParams::new(); @@ -36,7 +36,7 @@ pub async fn handle_scenario_command( .context("Add network to params")?; match command { - ScenarioCommands::Available {} => { + ScenarioCommand::Available {} => { let data = make_rpc_call("scenarios_available", params) .await .context("Failed to fetch available scenarios")?; @@ -57,7 +57,7 @@ pub async fn handle_scenario_command( println!("Unexpected response format."); } } - ScenarioCommands::Run { + ScenarioCommand::Run { scenario, additional_args, } => { @@ -73,7 +73,7 @@ pub async fn handle_scenario_command( println!("{:?}", data); } - ScenarioCommands::RunFile { + ScenarioCommand::RunFile { scenario_path, additional_args, } => { @@ -91,7 +91,7 @@ pub async fn handle_scenario_command( .context("Failed to run scenario")?; println!("{:?}", data); } - ScenarioCommands::Active {} => { + ScenarioCommand::Active {} => { let data = make_rpc_call("scenarios_list_running", params) .await .context("Failed to list running scenarios")?; @@ -124,7 +124,7 @@ pub async fn handle_scenario_command( println!("Unexpected response format."); } } - ScenarioCommands::Stop { pid } => { + ScenarioCommand::Stop { pid } => { params.insert("pid", pid).context("Add pid to params")?; let data = make_rpc_call("scenarios_stop", params) .await From 4c707e216bac8734981736e2855d578ffb8c8efe Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Thu, 28 Mar 2024 20:07:01 +0000 Subject: [PATCH 09/34] move pretty_print into util --- src/rust-cli/general.rs | 17 ++++------------- src/rust-cli/main.rs | 1 + src/rust-cli/util.rs | 30 ++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 13 deletions(-) create mode 100644 src/rust-cli/util.rs diff --git a/src/rust-cli/general.rs b/src/rust-cli/general.rs index 3ec26d0ff..e681b3f58 100644 --- a/src/rust-cli/general.rs +++ b/src/rust-cli/general.rs @@ -1,19 +1,8 @@ use crate::rpc_call::make_rpc_call; use anyhow::Context; use jsonrpsee::core::params::ObjectParams; -use serde_json::Value; -pub fn pretty_print_value(value: &Value) -> anyhow::Result<()> { - // If `value` is a JSON Value, pretty print it - if let Value::String(inner_json) = &value { - let parsed_inner: Value = serde_json::from_str(inner_json).context("Failed to parse inner JSON")?; - println!("{}", serde_json::to_string_pretty(&parsed_inner).context("Failed to pretty print inner JSON")?); - } else { - // If `value` is not a string containing JSON, print it directly. - println!("{}", serde_json::to_string_pretty(&value).context("Failed to pretty print JSON")?); - } - Ok(()) -} +use crate::util::pretty_print_value; pub async fn handle_rpc_command( node: &u64, @@ -32,7 +21,9 @@ pub async fn handle_rpc_command( rpc_params .insert("network", network) .context("add network param")?; - let data = make_rpc_call("tank_bcli", rpc_params).await.context("Failed to make RPC call")?; + let data = make_rpc_call("tank_bcli", rpc_params) + .await + .context("Failed to make RPC call")?; pretty_print_value(&data).context("pretty print result")?; Ok(()) } diff --git a/src/rust-cli/main.rs b/src/rust-cli/main.rs index 3d515bc29..8e777f951 100644 --- a/src/rust-cli/main.rs +++ b/src/rust-cli/main.rs @@ -5,6 +5,7 @@ mod general; mod network; mod rpc_call; mod scenarios; +mod util; use crate::debug::{handle_debug_command, DebugCommand}; use crate::general::handle_rpc_command; use crate::network::{handle_network_command, NetworkCommand}; diff --git a/src/rust-cli/util.rs b/src/rust-cli/util.rs new file mode 100644 index 000000000..7a3e97bfe --- /dev/null +++ b/src/rust-cli/util.rs @@ -0,0 +1,30 @@ +use anyhow::Context; +use serde_json::Value; + +pub fn pretty_print_value(value: &Value) -> anyhow::Result<()> { + match value { + Value::String(inner_json) => { + // Attempt to parse the string as JSON + match serde_json::from_str::(inner_json) { + Ok(parsed_inner) => { + // If parsing succeeds, pretty print the JSON + println!( + "{}", + serde_json::to_string_pretty(&parsed_inner) + .context("Failed to pretty print inner JSON")? + ); + } + Err(_) => { + // If parsing fails, it's not valid JSON, so just print the string itself + println!("{}", inner_json); + } + } + } + // If `value` is not a string (i.e., already a JSON Value), pretty print it directly + _ => println!( + "{}", + serde_json::to_string_pretty(&value).context("Failed to pretty print JSON")? + ), + } + Ok(()) +} From 493820304eb28a46a525d5343968bacbcdff0884 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Thu, 28 Mar 2024 20:16:07 +0000 Subject: [PATCH 10/34] add lncli command --- src/rust-cli/general.rs | 25 +++++++++++++++++++------ src/rust-cli/main.rs | 17 +++++++++++++++-- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/rust-cli/general.rs b/src/rust-cli/general.rs index e681b3f58..83e74979a 100644 --- a/src/rust-cli/general.rs +++ b/src/rust-cli/general.rs @@ -4,14 +4,22 @@ use jsonrpsee::core::params::ObjectParams; use crate::util::pretty_print_value; -pub async fn handle_rpc_command( - node: &u64, +pub enum NodeType { + LnCli, + BitcoinCli, +} + +pub async fn handle_rpc_commands( + node_type: NodeType, + node_index: &u64, method: &String, params: &Option>, network: &String, ) -> anyhow::Result<()> { let mut rpc_params = ObjectParams::new(); - rpc_params.insert("node", node).context("add node param")?; + rpc_params + .insert("node", node_index) + .context("add node_index param")?; rpc_params .insert("method", method) .context("add method param")?; @@ -21,9 +29,14 @@ pub async fn handle_rpc_command( rpc_params .insert("network", network) .context("add network param")?; - let data = make_rpc_call("tank_bcli", rpc_params) - .await - .context("Failed to make RPC call")?; + let data = match node_type { + NodeType::LnCli => make_rpc_call("tank_bcli", rpc_params) + .await + .context("Failed to make RPC call LnCli")?, + NodeType::BitcoinCli => make_rpc_call("tank_bcli", rpc_params) + .await + .context("Failed to make RPC call BitcoinCli")?, + }; pretty_print_value(&data).context("pretty print result")?; Ok(()) } diff --git a/src/rust-cli/main.rs b/src/rust-cli/main.rs index 8e777f951..7689496cb 100644 --- a/src/rust-cli/main.rs +++ b/src/rust-cli/main.rs @@ -7,7 +7,7 @@ mod rpc_call; mod scenarios; mod util; use crate::debug::{handle_debug_command, DebugCommand}; -use crate::general::handle_rpc_command; +use crate::general::{handle_rpc_commands, NodeType}; use crate::network::{handle_network_command, NetworkCommand}; use crate::scenarios::{handle_scenario_command, ScenarioCommand}; @@ -44,6 +44,12 @@ enum Commands { method: String, params: Option>, }, + /// Call lncli [params] on in [network] + LnCli { + node: u64, + method: String, + params: Option>, + }, } #[tokio::main] @@ -71,7 +77,14 @@ async fn main() -> anyhow::Result<()> { method, params, }) => { - handle_rpc_command(node, method, params, &cli.network).await?; + handle_rpc_commands(NodeType::BitcoinCli, node, method, params, &cli.network).await?; + } + Some(Commands::LnCli { + node, + method, + params, + }) => { + handle_rpc_commands(NodeType::LnCli, node, method, params, &cli.network).await?; } None => println!("No command provided"), } From 0ad7e147b674720727f3acdee59340ce1ad4f5ab Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Thu, 28 Mar 2024 20:21:19 +0000 Subject: [PATCH 11/34] add debug-log command --- src/rust-cli/general.rs | 16 ++++++++++++++++ src/rust-cli/main.rs | 9 ++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/rust-cli/general.rs b/src/rust-cli/general.rs index 83e74979a..e189356c4 100644 --- a/src/rust-cli/general.rs +++ b/src/rust-cli/general.rs @@ -40,3 +40,19 @@ pub async fn handle_rpc_commands( pretty_print_value(&data).context("pretty print result")?; Ok(()) } + +pub async fn handle_debug_log_command(node: &u64, network: &String) -> anyhow::Result<()> { + let mut rpc_params = ObjectParams::new(); + rpc_params + .insert("node", node) + .context("add node_index param")?; + rpc_params + .insert("network", network) + .context("add network param")?; + let data = make_rpc_call("tank_debug_log", rpc_params) + .await + .context("Failed to make RPC call tank_debug_log")?; + pretty_print_value(&data).context("pretty print result")?; + Ok(()) + +} diff --git a/src/rust-cli/main.rs b/src/rust-cli/main.rs index 7689496cb..1b0640018 100644 --- a/src/rust-cli/main.rs +++ b/src/rust-cli/main.rs @@ -7,7 +7,7 @@ mod rpc_call; mod scenarios; mod util; use crate::debug::{handle_debug_command, DebugCommand}; -use crate::general::{handle_rpc_commands, NodeType}; +use crate::general::*; use crate::network::{handle_network_command, NetworkCommand}; use crate::scenarios::{handle_scenario_command, ScenarioCommand}; @@ -50,6 +50,10 @@ enum Commands { method: String, params: Option>, }, + /// Fetch the Bitcoin Core debug log from in [network] + DebugLog { + node: u64, + }, } #[tokio::main] @@ -86,6 +90,9 @@ async fn main() -> anyhow::Result<()> { }) => { handle_rpc_commands(NodeType::LnCli, node, method, params, &cli.network).await?; } + Some(Commands::DebugLog { node }) => { + handle_debug_log_command(node, &cli.network).await?; + } None => println!("No command provided"), } From 726b331588435623a686b9c61d54644c87b889fc Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Thu, 28 Mar 2024 20:24:25 +0000 Subject: [PATCH 12/34] add messages command --- src/rust-cli/general.rs | 19 +++++++++++++++++++ src/rust-cli/main.rs | 8 ++++++++ 2 files changed, 27 insertions(+) diff --git a/src/rust-cli/general.rs b/src/rust-cli/general.rs index e189356c4..ea5ff0589 100644 --- a/src/rust-cli/general.rs +++ b/src/rust-cli/general.rs @@ -56,3 +56,22 @@ pub async fn handle_debug_log_command(node: &u64, network: &String) -> anyhow::R Ok(()) } + +pub async fn handle_messages_command(node_a: &u64, node_b: &u64, network: &String) -> anyhow::Result<()> { + let mut rpc_params = ObjectParams::new(); + rpc_params + .insert("node_a", node_a) + .context("add node_b param")?; + rpc_params + .insert("node_b", node_b) + .context("add node_b param")?; + rpc_params + .insert("network", network) + .context("add network param")?; + let data = make_rpc_call("tank_messages", rpc_params) + .await + .context("Failed to make RPC call tank_messages")?; + pretty_print_value(&data).context("pretty print result")?; + Ok(()) + +} diff --git a/src/rust-cli/main.rs b/src/rust-cli/main.rs index 1b0640018..0cd6d9508 100644 --- a/src/rust-cli/main.rs +++ b/src/rust-cli/main.rs @@ -54,6 +54,11 @@ enum Commands { DebugLog { node: u64, }, + /// Fetch messages sent between and in [network] + Messages { + node_a: u64, + node_b: u64, + }, } #[tokio::main] @@ -93,6 +98,9 @@ async fn main() -> anyhow::Result<()> { Some(Commands::DebugLog { node }) => { handle_debug_log_command(node, &cli.network).await?; } + Some(Commands::Messages { node_a, node_b }) => { + handle_messages_command(node_a, node_b, &cli.network).await?; + } None => println!("No command provided"), } From 04699f42e071548cf6fb2eaeb402150709dad9c0 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Thu, 28 Mar 2024 20:33:40 +0000 Subject: [PATCH 13/34] pass in params --- src/rust-cli/debug.rs | 10 +++------- src/rust-cli/general.rs | 42 ++++++++++++++------------------------- src/rust-cli/main.rs | 19 +++++++++++------- src/rust-cli/network.rs | 6 +----- src/rust-cli/scenarios.rs | 7 +------ 5 files changed, 32 insertions(+), 52 deletions(-) diff --git a/src/rust-cli/debug.rs b/src/rust-cli/debug.rs index daf60e1c1..1ea0e3b26 100644 --- a/src/rust-cli/debug.rs +++ b/src/rust-cli/debug.rs @@ -12,17 +12,13 @@ pub enum DebugCommand { GenerateCompose { graph_file_path: PathBuf }, } -pub async fn handle_debug_command(command: &DebugCommand, network: &String) -> anyhow::Result<()> { - let mut params = ObjectParams::new(); - params - .insert("network", network) - .context("Add network to params")?; +pub async fn handle_debug_command(command: &DebugCommand, mut rpc_params: ObjectParams) -> anyhow::Result<()> { match command { DebugCommand::GenerateCompose { graph_file_path } => { - params + rpc_params .insert("graph_file", graph_file_path.to_str()) .context("Add graph file path to params")?; - let data = make_rpc_call("generate_compose", params).await?; + let data = make_rpc_call("generate_compose", rpc_params).await?; println!("Docker-compose file generated: {:?}", data); } } diff --git a/src/rust-cli/general.rs b/src/rust-cli/general.rs index ea5ff0589..22c6be751 100644 --- a/src/rust-cli/general.rs +++ b/src/rust-cli/general.rs @@ -13,27 +13,23 @@ pub async fn handle_rpc_commands( node_type: NodeType, node_index: &u64, method: &String, - params: &Option>, - network: &String, + rpc_params: &Option>, + mut params: ObjectParams, ) -> anyhow::Result<()> { - let mut rpc_params = ObjectParams::new(); - rpc_params + params .insert("node", node_index) .context("add node_index param")?; - rpc_params + params .insert("method", method) .context("add method param")?; - if let Some(p) = params { - rpc_params.insert("params", p).context("add rpc params")?; + if let Some(p) = rpc_params { + params.insert("params", p).context("add rpc params")?; } - rpc_params - .insert("network", network) - .context("add network param")?; let data = match node_type { - NodeType::LnCli => make_rpc_call("tank_bcli", rpc_params) + NodeType::LnCli => make_rpc_call("tank_bcli", params) .await .context("Failed to make RPC call LnCli")?, - NodeType::BitcoinCli => make_rpc_call("tank_bcli", rpc_params) + NodeType::BitcoinCli => make_rpc_call("tank_bcli", params) .await .context("Failed to make RPC call BitcoinCli")?, }; @@ -41,15 +37,11 @@ pub async fn handle_rpc_commands( Ok(()) } -pub async fn handle_debug_log_command(node: &u64, network: &String) -> anyhow::Result<()> { - let mut rpc_params = ObjectParams::new(); - rpc_params +pub async fn handle_debug_log_command(node: &u64, mut params: ObjectParams) -> anyhow::Result<()> { + params .insert("node", node) .context("add node_index param")?; - rpc_params - .insert("network", network) - .context("add network param")?; - let data = make_rpc_call("tank_debug_log", rpc_params) + let data = make_rpc_call("tank_debug_log", params) .await .context("Failed to make RPC call tank_debug_log")?; pretty_print_value(&data).context("pretty print result")?; @@ -57,18 +49,14 @@ pub async fn handle_debug_log_command(node: &u64, network: &String) -> anyhow::R } -pub async fn handle_messages_command(node_a: &u64, node_b: &u64, network: &String) -> anyhow::Result<()> { - let mut rpc_params = ObjectParams::new(); - rpc_params +pub async fn handle_messages_command(node_a: &u64, node_b: &u64, mut params: ObjectParams) -> anyhow::Result<()> { + params .insert("node_a", node_a) .context("add node_b param")?; - rpc_params + params .insert("node_b", node_b) .context("add node_b param")?; - rpc_params - .insert("network", network) - .context("add network param")?; - let data = make_rpc_call("tank_messages", rpc_params) + let data = make_rpc_call("tank_messages", params) .await .context("Failed to make RPC call tank_messages")?; pretty_print_value(&data).context("pretty print result")?; diff --git a/src/rust-cli/main.rs b/src/rust-cli/main.rs index 0cd6d9508..f9b8fb9a1 100644 --- a/src/rust-cli/main.rs +++ b/src/rust-cli/main.rs @@ -1,4 +1,5 @@ use clap::{Parser, Subcommand}; +use anyhow::Context; mod debug; mod general; @@ -64,21 +65,25 @@ enum Commands { #[tokio::main] async fn main() -> anyhow::Result<()> { let cli = Cli::parse(); + let mut rpc_params = jsonrpsee::core::params::ObjectParams::new(); + rpc_params + .insert("network", &cli.network) + .context("add network param")?; match &cli.command { Some(Commands::Network { command }) => { if let Some(command) = command { - handle_network_command(command, &cli.network).await?; + handle_network_command(command, rpc_params).await?; } } Some(Commands::Debug { command }) => { if let Some(command) = command { - handle_debug_command(command, &cli.network).await?; + handle_debug_command(command, rpc_params).await?; } } Some(Commands::Scenarios { command }) => { if let Some(command) = command { - handle_scenario_command(command, &cli.network).await?; + handle_scenario_command(command, rpc_params).await?; } } Some(Commands::Rpc { @@ -86,20 +91,20 @@ async fn main() -> anyhow::Result<()> { method, params, }) => { - handle_rpc_commands(NodeType::BitcoinCli, node, method, params, &cli.network).await?; + handle_rpc_commands(NodeType::BitcoinCli, node, method, params, rpc_params).await?; } Some(Commands::LnCli { node, method, params, }) => { - handle_rpc_commands(NodeType::LnCli, node, method, params, &cli.network).await?; + handle_rpc_commands(NodeType::LnCli, node, method, params, rpc_params).await?; } Some(Commands::DebugLog { node }) => { - handle_debug_log_command(node, &cli.network).await?; + handle_debug_log_command(node, rpc_params).await?; } Some(Commands::Messages { node_a, node_b }) => { - handle_messages_command(node_a, node_b, &cli.network).await?; + handle_messages_command(node_a, node_b, rpc_params).await?; } None => println!("No command provided"), } diff --git a/src/rust-cli/network.rs b/src/rust-cli/network.rs index a01912413..36e56e0b4 100644 --- a/src/rust-cli/network.rs +++ b/src/rust-cli/network.rs @@ -30,12 +30,8 @@ pub enum NetworkCommand { pub async fn handle_network_command( command: &NetworkCommand, - network: &String, + mut params: ObjectParams, ) -> anyhow::Result<()> { - let mut params = ObjectParams::new(); - params - .insert("network", network) - .context("Add network to params")?; let (request, params) = match command { NetworkCommand::Start { graph_file, force } => { let file_contents = std::fs::read(graph_file).context("Failed to read graph file")?; diff --git a/src/rust-cli/scenarios.rs b/src/rust-cli/scenarios.rs index 50deeb203..5ddeb7c30 100644 --- a/src/rust-cli/scenarios.rs +++ b/src/rust-cli/scenarios.rs @@ -28,13 +28,8 @@ pub enum ScenarioCommand { pub async fn handle_scenario_command( command: &ScenarioCommand, - network: &String, + mut params: ObjectParams, ) -> anyhow::Result<()> { - let mut params = ObjectParams::new(); - params - .insert("network", network) - .context("Add network to params")?; - match command { ScenarioCommand::Available {} => { let data = make_rpc_call("scenarios_available", params) From beb31f12e0af423f9025700bf2f9b9757d2312dc Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Thu, 28 Mar 2024 20:36:51 +0000 Subject: [PATCH 14/34] add grep-logs command --- src/rust-cli/general.rs | 12 ++++++++++++ src/rust-cli/main.rs | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/src/rust-cli/general.rs b/src/rust-cli/general.rs index 22c6be751..73eaacaf7 100644 --- a/src/rust-cli/general.rs +++ b/src/rust-cli/general.rs @@ -63,3 +63,15 @@ pub async fn handle_messages_command(node_a: &u64, node_b: &u64, mut params: Obj Ok(()) } + +pub async fn handle_grep_logs_command(pattern: &String, mut params: ObjectParams) -> anyhow::Result<()> { + params + .insert("pattern", pattern) + .context("add pattern param")?; + let data = make_rpc_call("logs_grep", params) + .await + .context("Failed to make RPC call tank_messages")?; + pretty_print_value(&data).context("pretty print result")?; + Ok(()) + +} diff --git a/src/rust-cli/main.rs b/src/rust-cli/main.rs index f9b8fb9a1..2a50bca2b 100644 --- a/src/rust-cli/main.rs +++ b/src/rust-cli/main.rs @@ -60,6 +60,10 @@ enum Commands { node_a: u64, node_b: u64, }, + /// Grep combined logs via fluentd using regex + GrepLogs { + pattern: String, + }, } #[tokio::main] @@ -106,6 +110,9 @@ async fn main() -> anyhow::Result<()> { Some(Commands::Messages { node_a, node_b }) => { handle_messages_command(node_a, node_b, rpc_params).await?; } + Some(Commands::GrepLogs { pattern }) => { + handle_grep_logs_command(pattern, rpc_params).await?; + } None => println!("No command provided"), } From 0ba1762aa96ac85691547682eb231c95186793df Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Thu, 28 Mar 2024 20:40:00 +0000 Subject: [PATCH 15/34] add stop command --- src/rust-cli/general.rs | 9 +++++++++ src/rust-cli/main.rs | 5 +++++ src/warnet/server.py | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/rust-cli/general.rs b/src/rust-cli/general.rs index 73eaacaf7..402833003 100644 --- a/src/rust-cli/general.rs +++ b/src/rust-cli/general.rs @@ -75,3 +75,12 @@ pub async fn handle_grep_logs_command(pattern: &String, mut params: ObjectParams Ok(()) } + +pub async fn handle_stop_command(params: ObjectParams) -> anyhow::Result<()> { + let data = make_rpc_call("server_stop", params) + .await + .context("Failed to make RPC call server_stop")?; + pretty_print_value(&data).context("pretty print result")?; + Ok(()) + +} diff --git a/src/rust-cli/main.rs b/src/rust-cli/main.rs index 2a50bca2b..53d1523ef 100644 --- a/src/rust-cli/main.rs +++ b/src/rust-cli/main.rs @@ -64,6 +64,8 @@ enum Commands { GrepLogs { pattern: String, }, + /// Stop warnet + Stop {}, } #[tokio::main] @@ -113,6 +115,9 @@ async fn main() -> anyhow::Result<()> { Some(Commands::GrepLogs { pattern }) => { handle_grep_logs_command(pattern, rpc_params).await?; } + Some(Commands::Stop { }) => { + handle_stop_command(rpc_params).await?; + } None => println!("No command provided"), } diff --git a/src/warnet/server.py b/src/warnet/server.py index 514515f36..6dcb7d355 100644 --- a/src/warnet/server.py +++ b/src/warnet/server.py @@ -567,7 +567,7 @@ def generate_deployment(self, graph_file: str, network: str = "warnet") -> str: self.logger.error(msg) raise ServerError(message=msg) from e - def server_stop(self) -> None: + def server_stop(self, network: str = "warnet") -> None: """ Stop warnet. """ From 24f5584fa5b0e9435560eaeac997055512342f9d Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Thu, 28 Mar 2024 22:31:18 +0000 Subject: [PATCH 16/34] fixup formatting --- src/rust-cli/debug.rs | 5 ++++- src/rust-cli/general.rs | 39 +++++++++++++++++++++------------------ 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/rust-cli/debug.rs b/src/rust-cli/debug.rs index 1ea0e3b26..dece6925e 100644 --- a/src/rust-cli/debug.rs +++ b/src/rust-cli/debug.rs @@ -12,7 +12,10 @@ pub enum DebugCommand { GenerateCompose { graph_file_path: PathBuf }, } -pub async fn handle_debug_command(command: &DebugCommand, mut rpc_params: ObjectParams) -> anyhow::Result<()> { +pub async fn handle_debug_command( + command: &DebugCommand, + mut rpc_params: ObjectParams, +) -> anyhow::Result<()> { match command { DebugCommand::GenerateCompose { graph_file_path } => { rpc_params diff --git a/src/rust-cli/general.rs b/src/rust-cli/general.rs index 402833003..d4e30e49c 100644 --- a/src/rust-cli/general.rs +++ b/src/rust-cli/general.rs @@ -41,46 +41,49 @@ pub async fn handle_debug_log_command(node: &u64, mut params: ObjectParams) -> a params .insert("node", node) .context("add node_index param")?; - let data = make_rpc_call("tank_debug_log", params) - .await - .context("Failed to make RPC call tank_debug_log")?; + let data = make_rpc_call("tank_debug_log", params) + .await + .context("Failed to make RPC call tank_debug_log")?; pretty_print_value(&data).context("pretty print result")?; Ok(()) - } -pub async fn handle_messages_command(node_a: &u64, node_b: &u64, mut params: ObjectParams) -> anyhow::Result<()> { +pub async fn handle_messages_command( + node_a: &u64, + node_b: &u64, + mut params: ObjectParams, +) -> anyhow::Result<()> { params .insert("node_a", node_a) .context("add node_b param")?; params .insert("node_b", node_b) .context("add node_b param")?; - let data = make_rpc_call("tank_messages", params) - .await - .context("Failed to make RPC call tank_messages")?; + let data = make_rpc_call("tank_messages", params) + .await + .context("Failed to make RPC call tank_messages")?; pretty_print_value(&data).context("pretty print result")?; Ok(()) - } -pub async fn handle_grep_logs_command(pattern: &String, mut params: ObjectParams) -> anyhow::Result<()> { +pub async fn handle_grep_logs_command( + pattern: &String, + mut params: ObjectParams, +) -> anyhow::Result<()> { params .insert("pattern", pattern) .context("add pattern param")?; - let data = make_rpc_call("logs_grep", params) - .await - .context("Failed to make RPC call tank_messages")?; + let data = make_rpc_call("logs_grep", params) + .await + .context("Failed to make RPC call tank_messages")?; pretty_print_value(&data).context("pretty print result")?; Ok(()) - } pub async fn handle_stop_command(params: ObjectParams) -> anyhow::Result<()> { - let data = make_rpc_call("server_stop", params) - .await - .context("Failed to make RPC call server_stop")?; + let data = make_rpc_call("server_stop", params) + .await + .context("Failed to make RPC call server_stop")?; pretty_print_value(&data).context("pretty print result")?; Ok(()) - } From d6485116a5fa2de394005610458ef5decaa91527 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Thu, 28 Mar 2024 22:31:31 +0000 Subject: [PATCH 17/34] add graph create --- Cargo.lock | 295 +++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 5 + src/rust-cli/graph.rs | 181 ++++++++++++++++++++++++++ src/rust-cli/main.rs | 37 +++--- src/rust-cli/util.rs | 30 +++++ 5 files changed, 530 insertions(+), 18 deletions(-) create mode 100644 src/rust-cli/graph.rs diff --git a/Cargo.lock b/Cargo.lock index 808343581..4fbc340ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,25 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "anstream" version = "0.6.13" @@ -241,6 +260,26 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom", + "once_cell", + "tiny-keccak", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -266,12 +305,37 @@ dependencies = [ "libc", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "csv" version = "1.3.0" @@ -323,6 +387,21 @@ dependencies = [ "winapi", ] +[[package]] +name = "dlv-list" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" +dependencies = [ + "const-random", +] + +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + [[package]] name = "encode_unicode" version = "1.0.0" @@ -356,6 +435,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "fnv" version = "1.0.7" @@ -531,18 +616,29 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", "tracing", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", + "rayon", +] [[package]] name = "heck" @@ -640,6 +736,16 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + [[package]] name = "indexmap" version = "2.2.6" @@ -647,7 +753,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.3", + "rayon", ] [[package]] @@ -661,6 +768,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -851,6 +967,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + [[package]] name = "num_cpus" version = "1.16.0" @@ -888,6 +1013,16 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "ordered-multimap" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4d6a8c22fc714f0c2373e6091bf6f5e9b37b1bc0b1184874b7e0a4e303d318f" +dependencies = [ + "dlv-list", + "hashbrown 0.14.3", +] + [[package]] name = "parking" version = "2.2.0" @@ -900,6 +1035,26 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "petgraph" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +dependencies = [ + "fixedbitset", + "indexmap 2.2.6", +] + +[[package]] +name = "petgraph-graphml" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f99237d858a7675759c308324348d81742553ed1d65ddce0854a55688e8487b" +dependencies = [ + "petgraph", + "xml-rs", +] + [[package]] name = "pin-project" version = "1.1.5" @@ -952,6 +1107,16 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "priority-queue" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0bda9164fe05bc9225752d54aae413343c36f684380005398a6a8fde95fe785" +dependencies = [ + "autocfg", + "indexmap 1.9.3", +] + [[package]] name = "proc-macro2" version = "1.0.79" @@ -1000,6 +1165,46 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rand_pcg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-cond" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "059f538b55efd2309c9794130bc149c6a553db90e9d99c2030785c82f0bd7df9" +dependencies = [ + "either", + "itertools", + "rayon", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -1035,6 +1240,17 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rust-ini" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d625ed57d8f49af6cfa514c42e1a71fadcff60eb0b1c517ff82fe41aa025b41" +dependencies = [ + "cfg-if", + "ordered-multimap", + "trim-in-place", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -1150,6 +1366,25 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +[[package]] +name = "rustworkx-core" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "529027dfaa8125aa61bb7736ae9484f41e8544f448af96918c8da6b1def7f57b" +dependencies = [ + "ahash", + "fixedbitset", + "hashbrown 0.14.3", + "indexmap 2.2.6", + "num-traits", + "petgraph", + "priority-queue", + "rand", + "rand_pcg", + "rayon", + "rayon-cond", +] + [[package]] name = "ryu" version = "1.0.17" @@ -1342,6 +1577,15 @@ dependencies = [ "syn", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -1491,6 +1735,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "trim-in-place" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343e926fc669bc8cde4fa3129ab681c63671bae288b1f1081ceee6d9d37904fc" + [[package]] name = "try-lock" version = "0.2.5" @@ -1576,10 +1826,15 @@ dependencies = [ "base64 0.22.0", "clap", "jsonrpsee", + "petgraph-graphml", "prettytable-rs", + "rand", + "rust-ini", + "rustworkx-core", "serde", "serde_json", "tokio", + "xmltree", ] [[package]] @@ -1827,6 +2082,42 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +[[package]] +name = "xml-rs" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" + +[[package]] +name = "xmltree" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7d8a75eaf6557bb84a65ace8609883db44a29951042ada9b393151532e41fcb" +dependencies = [ + "indexmap 1.9.3", + "xml-rs", +] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zeroize" version = "1.7.0" diff --git a/Cargo.toml b/Cargo.toml index f129629f0..1a10e92cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,10 +10,15 @@ anyhow = "1.0.81" base64 = "0.22.0" clap = { version = "4.5.4", features = ["derive"] } jsonrpsee = { version = "0.22.3", features = ["http-client", "client"] } +petgraph-graphml = "3.0.0" prettytable-rs = "0.10.0" +rand = "0.8.5" +rust-ini = "0.21.0" +rustworkx-core = "0.14.2" serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" tokio = { version = "1.36.0", features = ["rt-multi-thread"] } +xmltree = { version = "0.10.3", features = ["indexmap"] } [[bin]] name = "warcli" diff --git a/src/rust-cli/graph.rs b/src/rust-cli/graph.rs new file mode 100644 index 000000000..3cb6028ea --- /dev/null +++ b/src/rust-cli/graph.rs @@ -0,0 +1,181 @@ +use anyhow::Context; +use clap::Subcommand; +use petgraph_graphml::GraphMl; +use rustworkx_core::generators::cycle_graph; +use rustworkx_core::petgraph; +use std::borrow::Cow; +use std::fs::File; +use std::io::Cursor; +use std::path::{Path, PathBuf}; +use xmltree::{Element, EmitterConfig, XMLNode}; + +use crate::util::{dump_bitcoin_conf, parse_bitcoin_conf}; +use rand::seq::SliceRandom; +use rand::thread_rng; + +#[derive(Subcommand, Debug)] +pub enum GraphCommand { + /// Create a cycle graph with nodes, and include 7 extra random outbounds per node. + /// Returns XML file as string with or without --outfile option + Create { + number: usize, + #[arg(short, long)] + outfile: Option, + #[arg(short, long)] + version: Option, + #[arg(short, long)] + bitcoin_conf: Option, + }, +} + +fn create_graph(number: usize) -> anyhow::Result> { + // Create initial cycle graph + let mut graph: petgraph::graph::DiGraph<(), ()> = + cycle_graph(Some(number), None, || {}, || {}, false) + .context("Create initial cycle graph")?; + + // Add more outbound connections to each node + for node in graph.node_indices() { + let mut candidates = Vec::new(); + for potential_target in graph.node_indices() { + if node != potential_target && !graph.contains_edge(node, potential_target) { + candidates.push(potential_target); + } + } + // Add 7 extra outbounds + for _ in 0..7 { + if let Some(&random_target) = candidates.choose(&mut thread_rng()) { + graph.add_edge(node, random_target, ()); + // Remove the selected target from candidates to avoid trying to add it again + candidates.retain(|&x| x != random_target); + } + } + } + Ok(graph) +} + +fn handle_bitcoin_conf(bitcoin_conf: Option<&Path>) -> String { + // handle custom bitcoin.conf + let mut conf_contents: String = String::new(); + if bitcoin_conf.is_some() { + let conf = parse_bitcoin_conf(bitcoin_conf); + // Iterate over sections and their properties + for (section, prop) in &conf { + println!("[{:?}]", section); + for (key, value) in prop.iter() { + println!("{}={}", key, value); + } + } + conf_contents += &dump_bitcoin_conf(&conf); + }; + conf_contents +} + +pub async fn handle_graph_command(command: &GraphCommand) -> anyhow::Result<()> { + match command { + GraphCommand::Create { + number, + outfile, + version, + bitcoin_conf, + } => { + let version_str = version.as_deref().unwrap_or("26.0"); + let graph = create_graph(*number).context("creating graph")?; + let bitcoin_conf = handle_bitcoin_conf(bitcoin_conf.as_deref()); + + // Convert to graphml + let graphml = GraphMl::new(&graph).pretty_print(true); + let mut buf = Vec::new(); + graphml + .to_writer(&mut buf) + .expect("Failed to write GraphML data"); + + let cursor = Cursor::new(buf); + let mut graphml_element = Element::parse(cursor).unwrap(); + + let keys = vec![ + ("version", "string"), + ("bitcoin_config", "string"), + ("tc_netem", "string"), + ("build_args", "string"), + ("exporter", "boolean"), + ("collect_logs", "boolean"), + ("image", "string"), + ]; + for (attr_name, attr_type) in keys { + let mut key_element = Element::new("key"); + key_element + .attributes + .insert("attr.name".to_string(), attr_name.to_string()); + key_element + .attributes + .insert("attr.type".to_string(), attr_type.to_string()); + key_element + .attributes + .insert("for".to_string(), "node".to_string()); + key_element + .attributes + .insert("id".to_string(), attr_name.to_string()); + + graphml_element.children.push(XMLNode::Element(key_element)); + } + // Find the element first + if let Some(XMLNode::Element(graph_el)) = graphml_element + .children + .iter_mut() + .find(|e| matches!(e, XMLNode::Element(el) if el.name == "graph")) + { + // iterate over the children of the element to find elements + for node in graph_el.children.iter_mut() { + if let XMLNode::Element(ref mut el) = node { + if el.name == "node" { + let data_elements = vec![ + ("version", version_str), + ("bitcoin_config", bitcoin_conf.as_str()), + ("tc_netem", ""), + ("build_args", ""), + ("exporter", "false"), + ("collect_logs", "false"), + ("image", ""), + ]; + for (key, value) in data_elements { + let mut data_element = Element::new("data"); + data_element + .attributes + .insert("key".to_string(), key.to_string()); + data_element.children.push(XMLNode::Text(value.to_string())); + el.children.push(XMLNode::Element(data_element)); + } + } + } + } + } + + let config = EmitterConfig { + write_document_declaration: true, + perform_indent: true, + indent_string: Cow::Borrowed(" "), + line_separator: Cow::Borrowed("\n"), + ..Default::default() // Keep other defaults + }; + + let mut buf_after = Vec::new(); + graphml_element + .write_with_config(&mut buf_after, config.clone()) + .expect("Failed to write modified GraphML data"); + match outfile { + Some(path) => { + let file = File::create(path).context("Writing final graphml file")?; + graphml_element.write_with_config(file, config)?; + } + None => { + // Write to stdout + let stdout = std::io::stdout(); + let handle = stdout.lock(); + graphml_element.write_with_config(handle, config)?; + } + } + } + } + Ok(()) +} diff --git a/src/rust-cli/main.rs b/src/rust-cli/main.rs index 53d1523ef..53bdec591 100644 --- a/src/rust-cli/main.rs +++ b/src/rust-cli/main.rs @@ -1,14 +1,16 @@ -use clap::{Parser, Subcommand}; use anyhow::Context; +use clap::{Parser, Subcommand}; mod debug; mod general; +mod graph; mod network; mod rpc_call; mod scenarios; mod util; use crate::debug::{handle_debug_command, DebugCommand}; use crate::general::*; +use crate::graph::{handle_graph_command, GraphCommand}; use crate::network::{handle_network_command, NetworkCommand}; use crate::scenarios::{handle_scenario_command, ScenarioCommand}; @@ -34,6 +36,11 @@ enum Commands { #[command(subcommand)] command: Option, }, + /// Graph commands + Graph { + #[command(subcommand)] + command: Option, + }, /// Scenario commands Scenarios { #[command(subcommand)] @@ -52,18 +59,11 @@ enum Commands { params: Option>, }, /// Fetch the Bitcoin Core debug log from in [network] - DebugLog { - node: u64, - }, + DebugLog { node: u64 }, /// Fetch messages sent between and in [network] - Messages { - node_a: u64, - node_b: u64, - }, + Messages { node_a: u64, node_b: u64 }, /// Grep combined logs via fluentd using regex - GrepLogs { - pattern: String, - }, + GrepLogs { pattern: String }, /// Stop warnet Stop {}, } @@ -77,14 +77,19 @@ async fn main() -> anyhow::Result<()> { .context("add network param")?; match &cli.command { - Some(Commands::Network { command }) => { + Some(Commands::Debug { command }) => { if let Some(command) = command { - handle_network_command(command, rpc_params).await?; + handle_debug_command(command, rpc_params).await?; } } - Some(Commands::Debug { command }) => { + Some(Commands::Graph { command }) => { if let Some(command) = command { - handle_debug_command(command, rpc_params).await?; + handle_graph_command(command).await?; + } + } + Some(Commands::Network { command }) => { + if let Some(command) = command { + handle_network_command(command, rpc_params).await?; } } Some(Commands::Scenarios { command }) => { @@ -115,7 +120,7 @@ async fn main() -> anyhow::Result<()> { Some(Commands::GrepLogs { pattern }) => { handle_grep_logs_command(pattern, rpc_params).await?; } - Some(Commands::Stop { }) => { + Some(Commands::Stop {}) => { handle_stop_command(rpc_params).await?; } None => println!("No command provided"), diff --git a/src/rust-cli/util.rs b/src/rust-cli/util.rs index 7a3e97bfe..56677aacb 100644 --- a/src/rust-cli/util.rs +++ b/src/rust-cli/util.rs @@ -1,5 +1,7 @@ use anyhow::Context; +use ini::Ini; use serde_json::Value; +use std::path::{Path, PathBuf}; pub fn pretty_print_value(value: &Value) -> anyhow::Result<()> { match value { @@ -28,3 +30,31 @@ pub fn pretty_print_value(value: &Value) -> anyhow::Result<()> { } Ok(()) } + +pub fn parse_bitcoin_conf(file_path: Option<&Path>) -> Ini { + Ini::load_from_file(file_path.unwrap()).expect("Failed to load or parse the file") +} + +pub fn dump_bitcoin_conf(conf: &Ini) -> String { + let mut entries = Vec::new(); + + // Global section + let global = conf.general_section(); + for (key, value) in global.iter() { + entries.push(format!("{}={}", key, value)); + } + + // named sections (networks) + for (section, properties) in conf.iter() { + if let Some(section_name) = section { + // Add section name as part of the output for non-global sections + // Skip or handle differently if your format does not require section names + entries.push(format!("[{}]", section_name)); + for (key, value) in properties.iter() { + entries.push(format!("{}={}", key, value)); + } + } + } + + entries.join(",") +} From c7afb19e010dc796a1ca5707bcc240d1cc3fa383 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Fri, 29 Mar 2024 07:58:41 +0000 Subject: [PATCH 18/34] convert node ids to ints --- src/warnet/warnet.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/warnet/warnet.py b/src/warnet/warnet.py index b912242d1..73737e7e4 100644 --- a/src/warnet/warnet.py +++ b/src/warnet/warnet.py @@ -106,7 +106,8 @@ def from_graph_file( with open(destination, "wb") as f: f.write(graph_file) self.network_name = network - self.graph = networkx.parse_graphml(graph_file.decode("utf-8"), node_type=int, force_multigraph=True) + self.graph = networkx.parse_graphml(graph_file.decode("utf-8"), node_type=str, force_multigraph=True) + self.graph = networkx.convert_node_labels_to_integers(self.graph) validate_graph_schema(self.graph) self.tanks_from_graph() logger.info(f"Created Warnet using directory {self.config_dir}") @@ -127,7 +128,8 @@ def from_network(cls, network_name, backend="compose"): self = cls(config_dir, backend, network_name) self.network_name = network_name # Get network graph edges from graph file (required for network restarts) - self.graph = networkx.read_graphml(Path(self.config_dir / self.graph_name), node_type=int, force_multigraph=True) + self.graph = networkx.read_graphml(Path(self.config_dir / self.graph_name), node_type=str, force_multigraph=True) + self.graph = networkx.convert_node_labels_to_integers(self.graph) validate_graph_schema(self.graph) self.tanks_from_graph() for tank in self.tanks: From 925d54676e5c6a77e63b9fb118dc41cf01ca8667 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Fri, 29 Mar 2024 08:18:29 +0000 Subject: [PATCH 19/34] refactor graph create --- src/rust-cli/graph.rs | 176 +++++++++++++++++++++++------------------- 1 file changed, 97 insertions(+), 79 deletions(-) diff --git a/src/rust-cli/graph.rs b/src/rust-cli/graph.rs index 3cb6028ea..fcd7ce886 100644 --- a/src/rust-cli/graph.rs +++ b/src/rust-cli/graph.rs @@ -71,6 +71,83 @@ fn handle_bitcoin_conf(bitcoin_conf: Option<&Path>) -> String { conf_contents } +fn convert_to_graphml(graph: &petgraph::graph::DiGraph<(), ()>) -> anyhow::Result> { + let graphml = GraphMl::new(graph).pretty_print(true); + let mut buf = Vec::new(); + graphml + .to_writer(&mut buf) + .expect("Failed to write GraphML data"); + Ok(buf) +} + +fn add_custom_attributes( + graphml_buf: Vec, + version_str: &str, + bitcoin_conf: &str, +) -> xmltree::Element { + let cursor = Cursor::new(graphml_buf); + let mut graphml_element = Element::parse(cursor).unwrap(); + + let keys = vec![ + ("version", "string"), + ("bitcoin_config", "string"), + ("tc_netem", "string"), + ("build_args", "string"), + ("exporter", "boolean"), + ("collect_logs", "boolean"), + ("image", "string"), + ]; + for (attr_name, attr_type) in keys { + let mut key_element = Element::new("key"); + key_element + .attributes + .insert("attr.name".to_string(), attr_name.to_string()); + key_element + .attributes + .insert("attr.type".to_string(), attr_type.to_string()); + key_element + .attributes + .insert("for".to_string(), "node".to_string()); + key_element + .attributes + .insert("id".to_string(), attr_name.to_string()); + + graphml_element.children.push(XMLNode::Element(key_element)); + } + // Find the element first + if let Some(XMLNode::Element(graph_el)) = graphml_element + .children + .iter_mut() + .find(|e| matches!(e, XMLNode::Element(el) if el.name == "graph")) + { + // Iterate over the children of the element to find elements + for node in graph_el.children.iter_mut() { + if let XMLNode::Element(ref mut el) = node { + if el.name == "node" { + let data_elements = vec![ + ("version", version_str), + ("bitcoin_config", bitcoin_conf), + ("tc_netem", ""), + ("build_args", ""), + ("exporter", "false"), + ("collect_logs", "false"), + ("image", ""), + ]; + for (key, value) in data_elements { + let mut data_element = Element::new("data"); + data_element + .attributes + .insert("key".to_string(), key.to_string()); + data_element.children.push(XMLNode::Text(value.to_string())); + el.children.push(XMLNode::Element(data_element)); + } + } + } + } + } + graphml_element +} + pub async fn handle_graph_command(command: &GraphCommand) -> anyhow::Result<()> { match command { GraphCommand::Create { @@ -79,79 +156,20 @@ pub async fn handle_graph_command(command: &GraphCommand) -> anyhow::Result<()> version, bitcoin_conf, } => { - let version_str = version.as_deref().unwrap_or("26.0"); - let graph = create_graph(*number).context("creating graph")?; - let bitcoin_conf = handle_bitcoin_conf(bitcoin_conf.as_deref()); - - // Convert to graphml - let graphml = GraphMl::new(&graph).pretty_print(true); - let mut buf = Vec::new(); - graphml - .to_writer(&mut buf) - .expect("Failed to write GraphML data"); - - let cursor = Cursor::new(buf); - let mut graphml_element = Element::parse(cursor).unwrap(); - - let keys = vec![ - ("version", "string"), - ("bitcoin_config", "string"), - ("tc_netem", "string"), - ("build_args", "string"), - ("exporter", "boolean"), - ("collect_logs", "boolean"), - ("image", "string"), - ]; - for (attr_name, attr_type) in keys { - let mut key_element = Element::new("key"); - key_element - .attributes - .insert("attr.name".to_string(), attr_name.to_string()); - key_element - .attributes - .insert("attr.type".to_string(), attr_type.to_string()); - key_element - .attributes - .insert("for".to_string(), "node".to_string()); - key_element - .attributes - .insert("id".to_string(), attr_name.to_string()); - - graphml_element.children.push(XMLNode::Element(key_element)); - } - // Find the element first - if let Some(XMLNode::Element(graph_el)) = graphml_element - .children - .iter_mut() - .find(|e| matches!(e, XMLNode::Element(el) if el.name == "graph")) - { - // iterate over the children of the element to find elements - for node in graph_el.children.iter_mut() { - if let XMLNode::Element(ref mut el) = node { - if el.name == "node" { - let data_elements = vec![ - ("version", version_str), - ("bitcoin_config", bitcoin_conf.as_str()), - ("tc_netem", ""), - ("build_args", ""), - ("exporter", "false"), - ("collect_logs", "false"), - ("image", ""), - ]; - for (key, value) in data_elements { - let mut data_element = Element::new("data"); - data_element - .attributes - .insert("key".to_string(), key.to_string()); - data_element.children.push(XMLNode::Text(value.to_string())); - el.children.push(XMLNode::Element(data_element)); - } - } - } - } - } + let version_str: &str = version.as_deref().unwrap_or("26.0"); + + // Create empty graph + let graph: petgraph::graph::DiGraph<(), ()> = + create_graph(*number).context("creating graph")?; + + // Parse any bitcoin conf arg + let bitcoin_conf: String = handle_bitcoin_conf(bitcoin_conf.as_deref()); - let config = EmitterConfig { + // Dump graph to graphml format + let graphml_buf: Vec = convert_to_graphml(&graph).context("Convert to graphml")?; + + // Graphml output settings + let graphml_config = EmitterConfig { write_document_declaration: true, perform_indent: true, indent_string: Cow::Borrowed(" "), @@ -159,20 +177,20 @@ pub async fn handle_graph_command(command: &GraphCommand) -> anyhow::Result<()> ..Default::default() // Keep other defaults }; - let mut buf_after = Vec::new(); - graphml_element - .write_with_config(&mut buf_after, config.clone()) - .expect("Failed to write modified GraphML data"); + // Add custom elements + let modified_graphml: xmltree::Element = + add_custom_attributes(graphml_buf, version_str, bitcoin_conf.as_str()); + + // Write either to outfile or stdout match outfile { Some(path) => { let file = File::create(path).context("Writing final graphml file")?; - graphml_element.write_with_config(file, config)?; + modified_graphml.write_with_config(file, graphml_config)?; } None => { - // Write to stdout let stdout = std::io::stdout(); let handle = stdout.lock(); - graphml_element.write_with_config(handle, config)?; + modified_graphml.write_with_config(handle, graphml_config)?; } } } From 43242b4b524111272dc54e5e4680238e7f07ad31 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Fri, 29 Mar 2024 08:27:02 +0000 Subject: [PATCH 20/34] use petgraph directly --- Cargo.lock | 159 +----------------------------------------- Cargo.toml | 2 +- src/rust-cli/graph.rs | 37 ++++++---- src/rust-cli/util.rs | 2 +- 4 files changed, 28 insertions(+), 172 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4fbc340ea..34b8c647d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,25 +17,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "getrandom", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "allocator-api2" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" - [[package]] name = "anstream" version = "0.6.13" @@ -305,25 +286,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "crossbeam-utils" version = "0.8.19" @@ -396,12 +358,6 @@ dependencies = [ "const-random", ] -[[package]] -name = "either" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" - [[package]] name = "encode_unicode" version = "1.0.0" @@ -634,11 +590,6 @@ name = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" -dependencies = [ - "ahash", - "allocator-api2", - "rayon", -] [[package]] name = "heck" @@ -754,7 +705,6 @@ checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.3", - "rayon", ] [[package]] @@ -768,15 +718,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.11" @@ -967,15 +908,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "num-traits" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" -dependencies = [ - "autocfg", -] - [[package]] name = "num_cpus" version = "1.16.0" @@ -1107,16 +1039,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "priority-queue" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0bda9164fe05bc9225752d54aae413343c36f684380005398a6a8fde95fe785" -dependencies = [ - "autocfg", - "indexmap 1.9.3", -] - [[package]] name = "proc-macro2" version = "1.0.79" @@ -1165,46 +1087,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_pcg" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-cond" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "059f538b55efd2309c9794130bc149c6a553db90e9d99c2030785c82f0bd7df9" -dependencies = [ - "either", - "itertools", - "rayon", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -1366,25 +1248,6 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" -[[package]] -name = "rustworkx-core" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "529027dfaa8125aa61bb7736ae9484f41e8544f448af96918c8da6b1def7f57b" -dependencies = [ - "ahash", - "fixedbitset", - "hashbrown 0.14.3", - "indexmap 2.2.6", - "num-traits", - "petgraph", - "priority-queue", - "rand", - "rand_pcg", - "rayon", - "rayon-cond", -] - [[package]] name = "ryu" version = "1.0.17" @@ -1826,11 +1689,11 @@ dependencies = [ "base64 0.22.0", "clap", "jsonrpsee", + "petgraph", "petgraph-graphml", "prettytable-rs", "rand", "rust-ini", - "rustworkx-core", "serde", "serde_json", "tokio", @@ -2098,26 +1961,6 @@ dependencies = [ "xml-rs", ] -[[package]] -name = "zerocopy" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "zeroize" version = "1.7.0" diff --git a/Cargo.toml b/Cargo.toml index 1a10e92cc..3a908c079 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,11 +10,11 @@ anyhow = "1.0.81" base64 = "0.22.0" clap = { version = "4.5.4", features = ["derive"] } jsonrpsee = { version = "0.22.3", features = ["http-client", "client"] } +petgraph = "0.6.4" petgraph-graphml = "3.0.0" prettytable-rs = "0.10.0" rand = "0.8.5" rust-ini = "0.21.0" -rustworkx-core = "0.14.2" serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" tokio = { version = "1.36.0", features = ["rt-multi-thread"] } diff --git a/src/rust-cli/graph.rs b/src/rust-cli/graph.rs index fcd7ce886..651295106 100644 --- a/src/rust-cli/graph.rs +++ b/src/rust-cli/graph.rs @@ -1,8 +1,7 @@ use anyhow::Context; use clap::Subcommand; +use petgraph::graph::{DiGraph, NodeIndex}; use petgraph_graphml::GraphMl; -use rustworkx_core::generators::cycle_graph; -use rustworkx_core::petgraph; use std::borrow::Cow; use std::fs::File; use std::io::Cursor; @@ -28,11 +27,27 @@ pub enum GraphCommand { }, } -fn create_graph(number: usize) -> anyhow::Result> { +fn create_graph(number: usize) -> anyhow::Result> { // Create initial cycle graph - let mut graph: petgraph::graph::DiGraph<(), ()> = - cycle_graph(Some(number), None, || {}, || {}, false) - .context("Create initial cycle graph")?; + let mut graph = DiGraph::new(); + let mut last_node: Option = None; + let mut first_node: Option = None; + + for _ in 0..number { + let new_node = graph.add_node(()); + if let Some(ln) = last_node { + graph.add_edge(ln, new_node, ()); // Add an edge from the last node to the new one + } else { + first_node = Some(new_node); + } + last_node = Some(new_node); + } + + if number > 0 { + if let (Some(first), Some(last)) = (first_node, last_node) { + graph.add_edge(last, first, ()); // Connect the last node to the first to complete the cycle + } + } // Add more outbound connections to each node for node in graph.node_indices() { @@ -55,7 +70,6 @@ fn create_graph(number: usize) -> anyhow::Result) -> String { - // handle custom bitcoin.conf let mut conf_contents: String = String::new(); if bitcoin_conf.is_some() { let conf = parse_bitcoin_conf(bitcoin_conf); @@ -159,16 +173,15 @@ pub async fn handle_graph_command(command: &GraphCommand) -> anyhow::Result<()> let version_str: &str = version.as_deref().unwrap_or("26.0"); // Create empty graph - let graph: petgraph::graph::DiGraph<(), ()> = - create_graph(*number).context("creating graph")?; + let graph: DiGraph<(), ()> = create_graph(*number).context("creating graph")?; - // Parse any bitcoin conf arg + // Parse any custom bitcoin conf let bitcoin_conf: String = handle_bitcoin_conf(bitcoin_conf.as_deref()); // Dump graph to graphml format let graphml_buf: Vec = convert_to_graphml(&graph).context("Convert to graphml")?; - // Graphml output settings + // Configure graphml output settings let graphml_config = EmitterConfig { write_document_declaration: true, perform_indent: true, @@ -177,7 +190,7 @@ pub async fn handle_graph_command(command: &GraphCommand) -> anyhow::Result<()> ..Default::default() // Keep other defaults }; - // Add custom elements + // Add custom elements to graph let modified_graphml: xmltree::Element = add_custom_attributes(graphml_buf, version_str, bitcoin_conf.as_str()); diff --git a/src/rust-cli/util.rs b/src/rust-cli/util.rs index 56677aacb..2e153ac76 100644 --- a/src/rust-cli/util.rs +++ b/src/rust-cli/util.rs @@ -1,7 +1,7 @@ use anyhow::Context; use ini::Ini; use serde_json::Value; -use std::path::{Path, PathBuf}; +use std::path::Path; pub fn pretty_print_value(value: &Value) -> anyhow::Result<()> { match value { From 53072656b339f3e5304aa80d9bc65aeced7eeada Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Fri, 29 Mar 2024 09:27:23 +0000 Subject: [PATCH 21/34] WIP: add graph validataion --- Cargo.lock | 496 +++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 2 + src/rust-cli/graph.rs | 60 ++++- 3 files changed, 548 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 34b8c647d..54ef9f0c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,29 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "serde", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "anstream" version = "0.6.13" @@ -141,6 +164,21 @@ dependencies = [ "serde", ] +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.3.2" @@ -168,6 +206,12 @@ version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +[[package]] +name = "bytecount" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" + [[package]] name = "bytes" version = "1.6.0" @@ -319,6 +363,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "digest" version = "0.9.0" @@ -364,6 +417,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -391,6 +453,16 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "fancy-regex" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" +dependencies = [ + "bit-set", + "regex", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -412,6 +484,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fraction" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3027ae1df8d41b4bed2241c8fdad4acc1e7af60c8e17743534b545e77182d678" +dependencies = [ + "lazy_static", + "num", +] + [[package]] name = "futures" version = "0.3.30" @@ -504,8 +586,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -707,6 +791,12 @@ dependencies = [ "hashbrown 0.14.3", ] +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + [[package]] name = "is-terminal" version = "0.4.12" @@ -718,6 +808,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "iso8601" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924e5d73ea28f59011fec52a0d12185d496a9b075d360657aed2a5707f701153" +dependencies = [ + "nom", +] + [[package]] name = "itoa" version = "1.0.11" @@ -853,6 +952,36 @@ dependencies = [ "url", ] +[[package]] +name = "jsonschema" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a071f4f7efc9a9118dfb627a0a94ef247986e1ab8606a4c806ae2b3aa3b6978" +dependencies = [ + "ahash", + "anyhow", + "base64 0.21.7", + "bytecount", + "clap", + "fancy-regex", + "fraction", + "getrandom", + "iso8601", + "itoa", + "memchr", + "num-cmp", + "once_cell", + "parking_lot", + "percent-encoding", + "regex", + "reqwest", + "serde", + "serde_json", + "time", + "url", + "uuid", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -876,6 +1005,16 @@ dependencies = [ "redox_syscall", ] +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.21" @@ -888,6 +1027,27 @@ version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minidom" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe549115a674f5ec64c754d85e37d6f42664bd0ef4ffb62b619489ad99c6cb1a" +dependencies = [ + "quick-xml", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.2" @@ -908,6 +1068,103 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-cmp" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63335b2e2c34fae2fb0aa2cecfd9f0832a1e24b3b32ecec612c3426d46dc8aaa" + +[[package]] +name = "num-complex" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + [[package]] name = "num_cpus" version = "1.16.0" @@ -961,6 +1218,29 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -1019,6 +1299,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1048,6 +1334,28 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quick-xml" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe1e430bdcf30c9fdc25053b9c459bb1a4672af4617b6c783d7d91dc17c6bbb0" +dependencies = [ + "memchr", +] + +[[package]] +name = "quickxml_to_serde" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "286b05c7a00b356ff6ac5218e10d628e0a3be02e777d067ca7286d353c3c407e" +dependencies = [ + "minidom", + "regex", + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "quote" version = "1.0.35" @@ -1107,6 +1415,71 @@ dependencies = [ "thiserror", ] +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + [[package]] name = "ring" version = "0.17.8" @@ -1263,6 +1636,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "sct" version = "0.7.1" @@ -1333,6 +1712,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "sha-1" version = "0.9.8" @@ -1355,6 +1746,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "socket2" version = "0.5.6" @@ -1409,6 +1806,33 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "term" version = "0.7.0" @@ -1440,6 +1864,36 @@ dependencies = [ "syn", ] +[[package]] +name = "time" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tiny-keccak" version = "2.0.2" @@ -1466,9 +1920,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.36.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -1666,6 +2120,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "uuid" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" + [[package]] name = "version_check" version = "0.9.4" @@ -1689,9 +2149,11 @@ dependencies = [ "base64 0.22.0", "clap", "jsonrpsee", + "jsonschema", "petgraph", "petgraph-graphml", "prettytable-rs", + "quickxml_to_serde", "rand", "rust-ini", "serde", @@ -1945,6 +2407,16 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "xml-rs" version = "0.8.19" @@ -1961,6 +2433,26 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zeroize" version = "1.7.0" diff --git a/Cargo.toml b/Cargo.toml index 3a908c079..84a569c1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,9 +10,11 @@ anyhow = "1.0.81" base64 = "0.22.0" clap = { version = "4.5.4", features = ["derive"] } jsonrpsee = { version = "0.22.3", features = ["http-client", "client"] } +jsonschema = "0.17.1" petgraph = "0.6.4" petgraph-graphml = "3.0.0" prettytable-rs = "0.10.0" +quickxml_to_serde = "0.6.0" rand = "0.8.5" rust-ini = "0.21.0" serde = { version = "1.0.197", features = ["derive"] } diff --git a/src/rust-cli/graph.rs b/src/rust-cli/graph.rs index 651295106..7fc0a9cff 100644 --- a/src/rust-cli/graph.rs +++ b/src/rust-cli/graph.rs @@ -1,16 +1,18 @@ -use anyhow::Context; -use clap::Subcommand; -use petgraph::graph::{DiGraph, NodeIndex}; -use petgraph_graphml::GraphMl; +use rand::seq::SliceRandom; +use rand::thread_rng; use std::borrow::Cow; use std::fs::File; -use std::io::Cursor; +use std::io::{BufReader, Cursor, Read}; use std::path::{Path, PathBuf}; -use xmltree::{Element, EmitterConfig, XMLNode}; use crate::util::{dump_bitcoin_conf, parse_bitcoin_conf}; -use rand::seq::SliceRandom; -use rand::thread_rng; +use anyhow::Context; +use clap::Subcommand; +use jsonschema::JSONSchema; +use petgraph::graph::{DiGraph, NodeIndex}; +use petgraph_graphml::GraphMl; +use quickxml_to_serde::{xml_string_to_json, Config}; +use xmltree::{Element, EmitterConfig, XMLNode}; #[derive(Subcommand, Debug)] pub enum GraphCommand { @@ -25,6 +27,9 @@ pub enum GraphCommand { #[arg(short, long)] bitcoin_conf: Option, }, + Validate { + graph: PathBuf, + }, } fn create_graph(number: usize) -> anyhow::Result> { @@ -162,6 +167,41 @@ fn add_custom_attributes( graphml_element } +fn validate_schema(graph: &PathBuf) -> anyhow::Result<()> { + let f = + File::open("src/schema/graph_schema.json").context("Read schema file from source dir")?; + let reader = BufReader::new(f); + let schema: serde_json::Value = + serde_json::from_reader(reader).context("Read schema into serde_json Value")?; + // TODO: this hack needing a static lifetime seems wrong. Try and fix it + let schema_static: &'static serde_json::Value = Box::leak(Box::new(schema)); + let compiled_schema = + JSONSchema::compile(schema_static).context("compile schema into JSONSchema")?; + + // Parse graph into serde_json::Value + let f = File::open(graph).context("Read xml graph from disk")?; + let mut reader = BufReader::new(f); + let mut xml_string = String::new(); + reader.read_to_string(&mut xml_string)?; + let conf = Config::new_with_defaults(); + let json = xml_string_to_json(xml_string, &conf).context("Convert xml string to JSON")?; + println!("{}", json); + + // Validate schema + // TODO: THIS IS NOT WORKING + // We need to iterate over nodes and edges and call validate on each one, I think? + let result = compiled_schema.validate(&json); + if let Err(errors) = result { + for error in errors { + println!("Validation error: {}", error); + println!("Instance path: {}", error.instance_path); + } + } + println!("Schema validated successfully!"); + + Ok(()) +} + pub async fn handle_graph_command(command: &GraphCommand) -> anyhow::Result<()> { match command { GraphCommand::Create { @@ -207,6 +247,10 @@ pub async fn handle_graph_command(command: &GraphCommand) -> anyhow::Result<()> } } } + + GraphCommand::Validate { graph } => { + let _ = validate_schema(graph); + } } Ok(()) } From 94c88a1751c71db33bb2f60d32211841d33070a1 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Fri, 29 Mar 2024 09:38:55 +0000 Subject: [PATCH 22/34] cleanup network fns --- src/rust-cli/network.rs | 44 +++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/rust-cli/network.rs b/src/rust-cli/network.rs index 36e56e0b4..2b2e3ba9d 100644 --- a/src/rust-cli/network.rs +++ b/src/rust-cli/network.rs @@ -28,16 +28,37 @@ pub enum NetworkCommand { Export {}, } +fn graph_file_to_b64(graph_file: &PathBuf) -> anyhow::Result { + let file_contents = std::fs::read(graph_file).context("Failed to read graph file")?; + Ok(general_purpose::STANDARD.encode(file_contents)) +} + +fn handle_network_status_response(data: serde_json::Value) { + if let serde_json::Value::Array(items) = &data { + for item in items { + if let (Some(tank_index), Some(bitcoin_status)) = ( + item.get("tank_index").and_then(|v| v.as_i64()), + item.get("bitcoin_status").and_then(|v| v.as_str()), + ) { + println!("Tank: {:<6} Bitcoin: {}", tank_index, bitcoin_status); + } else { + println!("Error: Response item is missing expected fields"); + } + } + } else { + println!("Error: Expected an array in the response"); + } +} + pub async fn handle_network_command( command: &NetworkCommand, mut params: ObjectParams, ) -> anyhow::Result<()> { let (request, params) = match command { NetworkCommand::Start { graph_file, force } => { - let file_contents = std::fs::read(graph_file).context("Failed to read graph file")?; - let graph_file_base64 = general_purpose::STANDARD.encode(file_contents); + let b64_graph = graph_file_to_b64(graph_file).context("Read graph file")?; params - .insert("graph_file", graph_file_base64) + .insert("graph_file", b64_graph) .context("Add base64 graph file to params")?; params .insert("force", *force) @@ -54,22 +75,7 @@ pub async fn handle_network_command( let data = make_rpc_call(request, params).await?; match request { - "network_status" => { - if let serde_json::Value::Array(items) = &data { - for item in items { - if let (Some(tank_index), Some(bitcoin_status)) = ( - item.get("tank_index").and_then(|v| v.as_i64()), - item.get("bitcoin_status").and_then(|v| v.as_str()), - ) { - println!("Tank: {:<6} Bitcoin: {}", tank_index, bitcoin_status); - } else { - println!("Error: Response item is missing expected fields"); - } - } - } else { - println!("Error: Expected an array in the response"); - } - } + "network_status" => handle_network_status_response(data), "network_start" => { todo!("Format this {:?}", data); } From a99d0dc5b183c22f94cd7c0001d178bc57ec4d71 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Fri, 29 Mar 2024 09:54:27 +0000 Subject: [PATCH 23/34] cleanup scenarios fns --- src/rust-cli/scenarios.rs | 199 +++++++++++++++++++++++--------------- 1 file changed, 120 insertions(+), 79 deletions(-) diff --git a/src/rust-cli/scenarios.rs b/src/rust-cli/scenarios.rs index 5ddeb7c30..271a2b549 100644 --- a/src/rust-cli/scenarios.rs +++ b/src/rust-cli/scenarios.rs @@ -25,111 +25,152 @@ pub enum ScenarioCommand { /// Stop a scenario with Stop { pid: u64 }, } +async fn handle_available(params: ObjectParams) -> anyhow::Result<()> { + let data = make_rpc_call("scenarios_available", params) + .await + .context("Failed to fetch available scenarios")?; + if let serde_json::Value::Array(scenarios) = data { + let mut table = Table::new(); + table.add_row(row!["Scenario", "Description"]); + for scenario in scenarios { + if let serde_json::Value::Array(details) = scenario { + if details.len() == 2 { + let name = details[0].as_str().unwrap_or("Unknown"); + let description = details[1].as_str().unwrap_or("No description"); + table.add_row(row![name, description]); + } + } + } + table.printstd(); + } else { + println!("Unexpected response format."); + } + Ok(()) +} + +async fn handle_run( + mut params: ObjectParams, + scenario: &str, + additional_args: &Vec, +) -> anyhow::Result<()> { + params + .insert("scenario", scenario) + .context("Add scenario to params")?; + params + .insert("additional_args", additional_args) + .context("Add additional_args to params")?; + let data = make_rpc_call("scenarios_run", params) + .await + .context("Failed to run scenario")?; + println!("{:?}", data); + Ok(()) +} + +async fn handle_run_file( + mut params: ObjectParams, + scenario_path: &PathBuf, + additional_args: &Vec, +) -> anyhow::Result<()> { + let file_contents = std::fs::read(scenario_path).context("Failed to read scenario file")?; + let scenario_base64 = general_purpose::STANDARD.encode(file_contents); + params + .insert("scenario_base64", scenario_base64) + .context("Add scenario to params")?; + params + .insert("additional_args", additional_args) + .context("Add additional_args to params")?; + let data = make_rpc_call("scenarios_run_file", params) + .await + .context("Failed to run scenario")?; + println!("{:?}", data); + Ok(()) +} + +async fn handle_active(params: ObjectParams) -> anyhow::Result<()> { + let data = make_rpc_call("scenarios_list_running", params) + .await + .context("Failed to list running scenarios")?; + if let serde_json::Value::Array(scenarios) = data { + let mut table = Table::new(); + table.add_row(row!["PID", "Command", "Network", "Active"]); + for scenario in scenarios { + if let serde_json::Value::Object(details) = scenario { + let pid = details + .get("pid") + .and_then(|v| v.as_i64()) + .map_or_else(|| "Unknown".to_string(), |v| v.to_string()); + let cmd = details + .get("cmd") + .and_then(|v| v.as_str()) + .unwrap_or("Unknown"); + let network = details + .get("network") + .and_then(|v| v.as_str()) + .unwrap_or("Unknown"); + let active = details + .get("active") + .and_then(|v| v.as_bool()) + .map_or_else(|| "Unknown".to_string(), |v| v.to_string()); + table.add_row(row![pid, cmd, network, active]); + } + } + table.printstd(); + } else { + println!("Unexpected response format."); + } + Ok(()) +} + +async fn handle_stop(mut params: ObjectParams, pid: &u64) -> anyhow::Result<()> { + params.insert("pid", pid).context("Add pid to params")?; + let data = make_rpc_call("scenarios_stop", params) + .await + .context("Failed to stop running scenario")?; + if let serde_json::Value::String(message) = data { + println!("{}", message); + } else { + println!("Unexpected response format."); + } + Ok(()) +} pub async fn handle_scenario_command( command: &ScenarioCommand, - mut params: ObjectParams, + params: ObjectParams, ) -> anyhow::Result<()> { match command { ScenarioCommand::Available {} => { - let data = make_rpc_call("scenarios_available", params) + handle_available(params) .await - .context("Failed to fetch available scenarios")?; - if let serde_json::Value::Array(scenarios) = data { - let mut table = Table::new(); - table.add_row(row!["Scenario", "Description"]); - for scenario in scenarios { - if let serde_json::Value::Array(details) = scenario { - if details.len() == 2 { - let name = details[0].as_str().unwrap_or("Unknown"); - let description = details[1].as_str().unwrap_or("No description"); - table.add_row(row![name, description]); - } - } - } - table.printstd(); - } else { - println!("Unexpected response format."); - } + .context("List available scenarios")?; } ScenarioCommand::Run { scenario, additional_args, } => { - params - .insert("scenario", scenario) - .context("Add scenario to params")?; - params - .insert("additional_args", additional_args) - .context("Add additional_args to params")?; - let data = make_rpc_call("scenarios_run", params) + handle_run(params, scenario, additional_args) .await - .context("Failed to run scenario")?; - println!("{:?}", data); + .context("Run scenario from remote")?; } ScenarioCommand::RunFile { scenario_path, additional_args, } => { - let file_contents = - std::fs::read(scenario_path).context("Failed to read scenario file")?; - let scenario_base64 = general_purpose::STANDARD.encode(file_contents); - params - .insert("scenario_base64", scenario_base64) - .context("Add scenario to params")?; - params - .insert("additional_args", additional_args) - .context("Add additional_args to params")?; - let data = make_rpc_call("scenarios_run_file", params) + handle_run_file(params, scenario_path, additional_args) .await - .context("Failed to run scenario")?; - println!("{:?}", data); + .context("Run scenario file from path")?; } ScenarioCommand::Active {} => { - let data = make_rpc_call("scenarios_list_running", params) + handle_active(params) .await - .context("Failed to list running scenarios")?; - if let serde_json::Value::Array(scenarios) = data { - let mut table = Table::new(); - table.add_row(row!["PID", "Command", "Network", "Active"]); - for scenario in scenarios { - if let serde_json::Value::Object(details) = scenario { - let pid = details - .get("pid") - .and_then(|v| v.as_i64()) - .map_or_else(|| "Unknown".to_string(), |v| v.to_string()); - let cmd = details - .get("cmd") - .and_then(|v| v.as_str()) - .unwrap_or("Unknown"); - let network = details - .get("network") - .and_then(|v| v.as_str()) - .unwrap_or("Unknown"); - let active = details - .get("active") - .and_then(|v| v.as_bool()) - .map_or_else(|| "Unknown".to_string(), |v| v.to_string()); - table.add_row(row![pid, cmd, network, active]); - } - } - table.printstd(); - } else { - println!("Unexpected response format."); - } + .context("List active scenarios")?; } ScenarioCommand::Stop { pid } => { - params.insert("pid", pid).context("Add pid to params")?; - let data = make_rpc_call("scenarios_stop", params) + handle_stop(params, pid) .await - .context("Failed to stop running scenario")?; - if let serde_json::Value::String(message) = data { - println!("{}", message); - } else { - println!("Unexpected response format."); - } + .context(format!("Stop running scenario with pid: {}", pid))?; } - } + }; Ok(()) } From 1db7bc4d96d224fb45d2c6c620ab38b65b842f84 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Fri, 29 Mar 2024 10:01:23 +0000 Subject: [PATCH 24/34] cleanup graph fns --- src/rust-cli/graph.rs | 85 ++++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/src/rust-cli/graph.rs b/src/rust-cli/graph.rs index 7fc0a9cff..20b3d7faf 100644 --- a/src/rust-cli/graph.rs +++ b/src/rust-cli/graph.rs @@ -202,51 +202,60 @@ fn validate_schema(graph: &PathBuf) -> anyhow::Result<()> { Ok(()) } -pub async fn handle_graph_command(command: &GraphCommand) -> anyhow::Result<()> { - match command { - GraphCommand::Create { - number, - outfile, - version, - bitcoin_conf, - } => { - let version_str: &str = version.as_deref().unwrap_or("26.0"); +fn handle_create_command( + number: &usize, + outfile: &Option, + version: &Option, + bitcoin_conf: &Option, +) -> anyhow::Result<()> { + let version_str: &str = version.as_deref().unwrap_or("26.0"); - // Create empty graph - let graph: DiGraph<(), ()> = create_graph(*number).context("creating graph")?; + // Create empty graph + let graph: DiGraph<(), ()> = create_graph(*number).context("creating graph")?; - // Parse any custom bitcoin conf - let bitcoin_conf: String = handle_bitcoin_conf(bitcoin_conf.as_deref()); + // Parse any custom bitcoin conf + let bitcoin_conf: String = handle_bitcoin_conf(bitcoin_conf.as_deref()); - // Dump graph to graphml format - let graphml_buf: Vec = convert_to_graphml(&graph).context("Convert to graphml")?; + // Dump graph to graphml format + let graphml_buf: Vec = convert_to_graphml(&graph).context("Convert to graphml")?; - // Configure graphml output settings - let graphml_config = EmitterConfig { - write_document_declaration: true, - perform_indent: true, - indent_string: Cow::Borrowed(" "), - line_separator: Cow::Borrowed("\n"), - ..Default::default() // Keep other defaults - }; + // Configure graphml output settings + let graphml_config = EmitterConfig { + write_document_declaration: true, + perform_indent: true, + indent_string: Cow::Borrowed(" "), + line_separator: Cow::Borrowed("\n"), + ..Default::default() // Keep other defaults + }; - // Add custom elements to graph - let modified_graphml: xmltree::Element = - add_custom_attributes(graphml_buf, version_str, bitcoin_conf.as_str()); + // Add custom elements to graph + let modified_graphml: xmltree::Element = + add_custom_attributes(graphml_buf, version_str, bitcoin_conf.as_str()); - // Write either to outfile or stdout - match outfile { - Some(path) => { - let file = File::create(path).context("Writing final graphml file")?; - modified_graphml.write_with_config(file, graphml_config)?; - } - None => { - let stdout = std::io::stdout(); - let handle = stdout.lock(); - modified_graphml.write_with_config(handle, graphml_config)?; - } - } + // Write either to outfile or stdout + match outfile { + Some(path) => { + let file = File::create(path).context("Writing final graphml file")?; + modified_graphml.write_with_config(file, graphml_config)?; + } + None => { + let stdout = std::io::stdout(); + let handle = stdout.lock(); + modified_graphml.write_with_config(handle, graphml_config)?; } + } + Ok(()) +} + +pub async fn handle_graph_command(command: &GraphCommand) -> anyhow::Result<()> { + match command { + GraphCommand::Create { + number, + outfile, + version, + bitcoin_conf, + } => handle_create_command(number, outfile, version, bitcoin_conf) + .context("Create a graph")?, GraphCommand::Validate { graph } => { let _ = validate_schema(graph); From 76d44ede935e6510479667805929e5f395588dc7 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Fri, 29 Mar 2024 11:27:12 +0000 Subject: [PATCH 25/34] use argparse in tests --- .github/workflows/test.yml | 10 +++++----- src/warnet/server.py | 8 ++++---- test/rpc_test.py | 2 +- test/test_base.py | 24 +++++++++++++++--------- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 136cd2fe2..5e8e56d4b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,7 +27,7 @@ jobs: just start kubectl wait --for=condition=Ready --timeout=2m pod rpc-0 kubectl port-forward svc/rpc 9276:9276 & - - run: ./test/scenarios_test.py ${{matrix.backend}} + - run: ./test/scenarios_test.py --backend=${{matrix.backend}} rpc: runs-on: ubuntu-latest strategy: @@ -48,7 +48,7 @@ jobs: just start kubectl wait --for=condition=Ready --timeout=2m pod rpc-0 kubectl port-forward svc/rpc 9276:9276 & - - run: ./test/rpc_test.py ${{matrix.backend}} + - run: ./test/rpc_test.py --backend=${{matrix.backend}} graph: runs-on: ubuntu-latest strategy: @@ -69,7 +69,7 @@ jobs: just start kubectl wait --for=condition=Ready --timeout=2m pod rpc-0 kubectl port-forward svc/rpc 9276:9276 & - - run: ./test/graph_test.py ${{matrix.backend}} + - run: ./test/graph_test.py --backend=${{matrix.backend}} ln: runs-on: ubuntu-latest strategy: @@ -90,7 +90,7 @@ jobs: just start kubectl wait --for=condition=Ready --timeout=2m pod rpc-0 kubectl port-forward svc/rpc 9276:9276 & - - run: ./test/ln_test.py ${{matrix.backend}} + - run: ./test/ln_test.py --backend=${{matrix.backend}} build: needs: [scenarios, rpc, graph, ln] # Only run if the others complete successfully as it's slow runs-on: ubuntu-latest @@ -112,4 +112,4 @@ jobs: just start kubectl wait --for=condition=Ready --timeout=2m pod rpc-0 kubectl port-forward svc/rpc 9276:9276 & - - run: ./test/build_branch_test.py ${{matrix.backend}} + - run: ./test/build_branch_test.py --backend=${{matrix.backend}} diff --git a/src/warnet/server.py b/src/warnet/server.py index 6dcb7d355..58ef2437b 100644 --- a/src/warnet/server.py +++ b/src/warnet/server.py @@ -169,7 +169,7 @@ def setup_rpc(self): # Logs self.jsonrpc.register(self.logs_grep) - def get_warnet(self, network: str) -> Warnet: + def get_warnet(self, network: str = "warnet") -> Warnet: """ Will get a warnet from the cache if it exists. Otherwise it will create the network using from_network() and save it @@ -268,7 +268,7 @@ def tank_messages(self, network: str, node_a: int, node_b: int) -> str: self.logger.error(msg) raise ServerError(message=msg) from e - def network_export(self, network: str) -> str: + def network_export(self, network: str = "warnet") -> str: """ Export all data for sim-ln to subdirectory """ @@ -283,7 +283,7 @@ def network_export(self, network: str) -> str: self.logger.error(msg) raise ServerError(message=msg) from e - def scenarios_available(self, network: str) -> list[tuple]: + def scenarios_available(self, network: str = "warnet") -> list[tuple]: """ List available scenarios in the Warnet Test Framework """ @@ -415,7 +415,7 @@ def scenarios_stop(self, pid: int, network: str = "warnet") -> str: self.logger.error(msg) raise ServerError(message=msg) - def scenarios_list_running(self, network: str) -> list[dict]: + def scenarios_list_running(self, network: str = "warnet") -> list[dict]: running = [ { "pid": sc["pid"], diff --git a/test/rpc_test.py b/test/rpc_test.py index 9b8a6a577..ac8acddeb 100755 --- a/test/rpc_test.py +++ b/test/rpc_test.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 - import os from pathlib import Path @@ -7,6 +6,7 @@ graph_file_path = Path(os.path.dirname(__file__)) / "data" / "v25_x_12.graphml" + base = TestBase() base.start_server() print(base.warcli(f"network start {graph_file_path}")) diff --git a/test/test_base.py b/test/test_base.py index da8aee186..35a68629c 100644 --- a/test/test_base.py +++ b/test/test_base.py @@ -1,3 +1,4 @@ +import argparse import atexit import os import sys @@ -11,6 +12,11 @@ from warnet.utils import exponential_backoff from warnet.warnet import Warnet +parser = argparse.ArgumentParser(description="TestBase args") +parser.add_argument("--backend", type=str, default="compose", help="Use compose or k8s backend") +parser.add_argument("--rust_cli", action="store_true", help="Use experimental Rust CLI") +args = parser.parse_args() + class TestBase: def __init__(self): @@ -31,15 +37,11 @@ def __init__(self): self.server_thread = None self.stop_threads = threading.Event() self.network = True + self.rust_cli = args.rust_cli atexit.register(self.cleanup) - # Default backend - self.backend = "compose" - # CLI arg overrides env - if len(sys.argv) > 1: - self.backend = sys.argv[1] - + self.backend = args.backend if self.backend not in ["compose", "k8s"]: print(f"Invalid backend {self.backend}") sys.exit(1) @@ -78,9 +80,13 @@ def cleanup(self, signum=None, frame=None): # Execute a warcli RPC using command line (always returns string) def warcli(self, str, network=True): - cmd = ["warcli"] + str.split() - if network: - cmd += ["--network", self.network_name] + if not self.rust_cli: + print("Not using rust cli") + cmd = ["warcli"] + str.split() + if network: + cmd += ["--network", self.network_name] + else: + cmd = ["target/debug/warcli"] + str.split() proc = run(cmd, capture_output=True) if proc.stderr: From 2d51140d02ee3a907aa817a35c364870fe831861 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Fri, 29 Mar 2024 11:31:04 +0000 Subject: [PATCH 26/34] add rust cli to rpc test matrix --- .github/workflows/test.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5e8e56d4b..c831c3abf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -33,6 +33,7 @@ jobs: strategy: matrix: backend: [compose, k8s] + cli: [--rust_cli, ""] steps: - uses: actions/checkout@v4 - if: matrix.backend == 'compose' @@ -41,6 +42,9 @@ jobs: uses: extractions/setup-just@v1 - if: matrix.backend == 'k8s' uses: medyagh/setup-minikube@master + - if: matrix.cli == '--rust_cli' + run: | + cargo build - if: matrix.backend == 'k8s' run: | pip install --upgrade pip @@ -48,7 +52,7 @@ jobs: just start kubectl wait --for=condition=Ready --timeout=2m pod rpc-0 kubectl port-forward svc/rpc 9276:9276 & - - run: ./test/rpc_test.py --backend=${{matrix.backend}} + - run: ./test/rpc_test.py --backend=${{matrix.backend}} ${{matrix.cli}} graph: runs-on: ubuntu-latest strategy: From b3f3c3a195fd63f105153477d3bef36aa525f987 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Fri, 29 Mar 2024 16:34:38 +0000 Subject: [PATCH 27/34] fixup arg passing in rpc test_base.py --- src/rust-cli/main.rs | 4 ++-- test/test_base.py | 24 ++++++++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/rust-cli/main.rs b/src/rust-cli/main.rs index 53bdec591..571498356 100644 --- a/src/rust-cli/main.rs +++ b/src/rust-cli/main.rs @@ -17,8 +17,8 @@ use crate::scenarios::{handle_scenario_command, ScenarioCommand}; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] struct Cli { - #[arg(long, default_value = "warnet")] - network: String, + #[arg(long)] + network: Option, #[command(subcommand)] command: Option, diff --git a/test/test_base.py b/test/test_base.py index 35a68629c..f60ab78fc 100644 --- a/test/test_base.py +++ b/test/test_base.py @@ -1,6 +1,7 @@ import argparse import atexit import os +import shlex import sys import threading from pathlib import Path @@ -79,14 +80,25 @@ def cleanup(self, signum=None, frame=None): self.server = None # Execute a warcli RPC using command line (always returns string) - def warcli(self, str, network=True): - if not self.rust_cli: - print("Not using rust cli") - cmd = ["warcli"] + str.split() + def warcli(self, commands, network=True): + cmd = "" + cmd_args = ' '.join(commands.split()) + if self.rust_cli: + # a temporary hack to fetch the path of the debug binary + script_path = Path(__file__).resolve() + project_root = script_path.parent.parent + warcli_relative_path = Path("target/debug/warcli") + warcli_absolute_path = project_root / warcli_relative_path + cmd += f"{warcli_absolute_path} " if network: - cmd += ["--network", self.network_name] + cmd += f"--network {self.network_name} " + cmd += cmd_args else: - cmd = ["target/debug/warcli"] + str.split() + cmd += "warcli " + cmd += cmd_args + if network: + cmd += f" --network {self.network_name} " + cmd = shlex.split(cmd) proc = run(cmd, capture_output=True) if proc.stderr: From 62625118260337b88b33940017b89ec7f68ea260 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Fri, 29 Mar 2024 20:24:54 +0000 Subject: [PATCH 28/34] only add network param if provided --- src/rust-cli/main.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/rust-cli/main.rs b/src/rust-cli/main.rs index 571498356..81380916f 100644 --- a/src/rust-cli/main.rs +++ b/src/rust-cli/main.rs @@ -72,9 +72,11 @@ enum Commands { async fn main() -> anyhow::Result<()> { let cli = Cli::parse(); let mut rpc_params = jsonrpsee::core::params::ObjectParams::new(); - rpc_params - .insert("network", &cli.network) - .context("add network param")?; + if let Some(network_value) = &cli.network { + rpc_params + .insert("network", network_value) + .context("add network param")?; + } match &cli.command { Some(Commands::Debug { command }) => { From e4870635bb2a6e67080c7b31e7c2ed76bbb9138f Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Fri, 29 Mar 2024 21:26:16 +0000 Subject: [PATCH 29/34] allow hyphen values on rpc methods --- src/rust-cli/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rust-cli/main.rs b/src/rust-cli/main.rs index 81380916f..e978a2ef7 100644 --- a/src/rust-cli/main.rs +++ b/src/rust-cli/main.rs @@ -49,6 +49,7 @@ enum Commands { /// Call bitcoin-cli [params] on in [network] Rpc { node: u64, + #[arg(allow_hyphen_values=true)] method: String, params: Option>, }, From f2e1924fe214127a1d079287ff51cb38624f9395 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Mon, 1 Apr 2024 15:25:19 +0100 Subject: [PATCH 30/34] pretty print network start responses --- src/rust-cli/network.rs | 65 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/src/rust-cli/network.rs b/src/rust-cli/network.rs index 2b2e3ba9d..dd97a9ce8 100644 --- a/src/rust-cli/network.rs +++ b/src/rust-cli/network.rs @@ -2,6 +2,8 @@ use anyhow::Context; use base64::{engine::general_purpose, Engine as _}; use clap::Subcommand; use jsonrpsee::core::params::ObjectParams; +use prettytable::{cell, Row, Table}; +use serde_json::Value; use std::path::PathBuf; use crate::rpc_call::make_rpc_call; @@ -50,6 +52,65 @@ fn handle_network_status_response(data: serde_json::Value) { } } +fn handle_network_start_response(data: serde_json::Value) -> anyhow::Result<()> { + // warnet table + if let Some(warnet_headers) = data["warnet_headers"].as_array() { + let mut table = Table::new(); + let headers: Vec<_> = warnet_headers + .iter() + .map(|header| header.as_str().unwrap_or("")) + .collect(); + table.add_row(Row::new( + headers.into_iter().map(|header| cell!(header)).collect(), + )); + // just used as fallback if warnet or its array content is missing + let v: Vec = vec![Value::Null]; + + if let Some(warnet) = data["warnet"].as_array().and_then(|row| row.first()) { + let row_data: Vec<_> = match warnet.as_array() { + Some(array) => array, + None => &v, + } + .iter() + .map(|item| item.as_str().unwrap_or("")) + .collect(); + table.add_row(Row::new( + row_data.into_iter().map(|row| cell!(row)).collect(), + )); + } + table.printstd(); + } + // tanks table + if let Some(tank_headers) = data["tank_headers"].as_array() { + let mut table = Table::new(); + let headers: Vec<_> = tank_headers + .iter() + .map(|header| header.as_str().unwrap_or("")) + .collect(); + table.add_row(Row::new( + headers.into_iter().map(|header| cell!(header)).collect(), + )); + + let v: Vec = vec![Value::Null]; + if let Some(tanks) = data["tanks"].as_array() { + for tank in tanks { + let row_data: Vec<_> = match tank.as_array() { + Some(array) => array, + None => &v, + } + .iter() + .map(|item| item.as_str().unwrap_or("")) + .collect(); + table.add_row(Row::new( + row_data.into_iter().map(|row| cell!(row)).collect(), + )); + } + } + table.printstd(); + } + Ok(()) +} + pub async fn handle_network_command( command: &NetworkCommand, mut params: ObjectParams, @@ -76,8 +137,8 @@ pub async fn handle_network_command( let data = make_rpc_call(request, params).await?; match request { "network_status" => handle_network_status_response(data), - "network_start" => { - todo!("Format this {:?}", data); + "network_from_file" => { + handle_network_start_response(data.clone())?; } _ => { println!("{}", data) From 8b00aae4d10a3d00827530c67d3ed28ef7e04c8e Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Mon, 1 Apr 2024 20:22:16 +0100 Subject: [PATCH 31/34] add image build command --- src/rust-cli/image.rs | 155 ++++++++++++++++++++++++++++++++++++++++++ src/rust-cli/main.rs | 55 +++++++++------ 2 files changed, 189 insertions(+), 21 deletions(-) create mode 100644 src/rust-cli/image.rs diff --git a/src/rust-cli/image.rs b/src/rust-cli/image.rs new file mode 100644 index 000000000..8bfd33999 --- /dev/null +++ b/src/rust-cli/image.rs @@ -0,0 +1,155 @@ +use anyhow::anyhow; +use clap::Subcommand; +use std::fs; +use std::process::{Command, Stdio}; + +#[derive(Subcommand, Debug)] +pub enum ImageCommand { + /// Build bitcoind and bitcoin-cli from / as :. + /// Optionally deploy to remote registry using --action=push, otherwise image is loaded to local registry. + Build { + #[arg(long)] + repo: String, + #[arg(long)] + branch: String, + #[arg(long)] + registry: String, + #[arg(long)] + tag: String, + #[arg(long)] + build_args: Option, + #[arg(long)] + arches: Option, + #[arg(long)] + action: Option, + }, +} + +const ARCHES: [&str; 3] = ["amd64", "arm64", "armv7"]; + +fn run_command(command: &str) -> anyhow::Result { + println!("Executing: {}", command); + let mut child = Command::new("bash") + .arg("-c") + .arg(command) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()) + .spawn()?; + + let output = child.wait()?; + + if output.success() { + Ok(true) + } else { + Err(anyhow!("Command failed")) + } +} + +fn build_image( + repo: &String, + branch: &String, + docker_registry: &String, + tag: &String, + build_args: &Option, + arches: &Option, + action: &Option, +) -> anyhow::Result<()> { + let build_args = match build_args { + Some(args) => format!("\"{}\"", args), + None => "\"--disable-tests --without-gui --disable-bench --disable-fuzz-binary --enable-suppress-external-warnings \"".to_string(), + }; + + let mut build_arches = vec![]; + match arches { + Some(a) => build_arches.extend(a.split(',').map(String::from)), + None => build_arches.push("amd64".to_string()), + } + + for arch in &build_arches { + if !ARCHES.contains(&arch.as_str()) { + println!("Error: {} is not a supported architecture", arch); + return Err(anyhow!("Unsupported architecture: {}", arch)); + } + } + + println!("repo={}", repo); + println!("branch={}", branch); + println!("docker_registry={}", docker_registry); + println!("tag={}", tag); + println!("build_args={}", build_args); + println!("build_arches={:?}", build_arches); + + if !fs::metadata("src/templates") + .map(|m| m.is_dir()) + .unwrap_or(false) + { + println!("Directory src/templates does not exist."); + println!("Please run this script from the project root."); + return Err(anyhow!("src/templates directory not found")); + } + + let builder_name = "bitcoind-builder"; + let create_builder_cmd = format!("docker buildx create --name {} --use", builder_name); + let creat_builder_res = run_command(&create_builder_cmd); + if creat_builder_res.is_err() { + let use_builder_cmd = format!("docker buildx use {}", builder_name); + run_command(&use_builder_cmd)?; + } + + let image_full_name = format!("{}:{}", docker_registry, tag); + println!("image_full_name={}", image_full_name); + + let platforms = build_arches + .iter() + .map(|arch| format!("linux/{}", arch)) + .collect::>() + .join(","); + + let action = match action { + Some(action) => action, + None => "load", + }; + let build_command = format!( + "docker buildx build --platform {} --build-arg REPO={} --build-arg BRANCH={} --build-arg BUILD_ARGS={} --tag {} --file src/templates/Dockerfile . --{}", + platforms, repo, branch, build_args, image_full_name, action + ); + + println!("Using build_command={}", build_command); + + let res = run_command(&build_command); + if res.is_ok() { + println!("Build completed"); + } else { + println!("Build failed."); + } + + let cleanup_builder_cmd = format!("docker buildx rm {}", builder_name); + let cleanup_res = run_command(&cleanup_builder_cmd); + if cleanup_res.is_ok() { + println!("Buildx builder removed successfully."); + } else { + println!("Warning: Failed to remove the buildx builder."); + } + + match res { + Ok(true) => Ok(()), + Ok(false) => Err(anyhow!( + "Build command failed, but no specific error was provided." + )), + Err(e) => Err(anyhow!("Build command failed with error: {}", e)), + } +} + +pub async fn handle_image_command(command: &ImageCommand) -> anyhow::Result<()> { + match command { + ImageCommand::Build { + repo, + branch, + registry, + tag, + build_args, + arches, + action, + } => build_image(repo, branch, registry, tag, build_args, arches, action), + } +} diff --git a/src/rust-cli/main.rs b/src/rust-cli/main.rs index e978a2ef7..6b9b054d0 100644 --- a/src/rust-cli/main.rs +++ b/src/rust-cli/main.rs @@ -4,6 +4,7 @@ use clap::{Parser, Subcommand}; mod debug; mod general; mod graph; +mod image; mod network; mod rpc_call; mod scenarios; @@ -11,6 +12,7 @@ mod util; use crate::debug::{handle_debug_command, DebugCommand}; use crate::general::*; use crate::graph::{handle_graph_command, GraphCommand}; +use crate::image::{handle_image_command, ImageCommand}; use crate::network::{handle_network_command, NetworkCommand}; use crate::scenarios::{handle_scenario_command, ScenarioCommand}; @@ -18,6 +20,7 @@ use crate::scenarios::{handle_scenario_command, ScenarioCommand}; #[command(version, about, long_about = None)] struct Cli { #[arg(long)] + /// The warnet network command corresponds to network: Option, #[command(subcommand)] @@ -26,32 +29,24 @@ struct Cli { #[derive(Subcommand, Debug)] enum Commands { - /// Network commands - Network { - #[command(subcommand)] - command: Option, - }, - /// Debug commands [[deprecated]] + /// Debug commands (deprecated) Debug { #[command(subcommand)] command: Option, }, + /// Fetch the Bitcoin Core debug log from in [network] + DebugLog { node: u64 }, /// Graph commands Graph { #[command(subcommand)] command: Option, }, - /// Scenario commands - Scenarios { + /// Grep combined logs via fluentd using regex + GrepLogs { pattern: String }, + /// Build a warnet-ready bitcoind docker image from a github branch + Image { #[command(subcommand)] - command: Option, - }, - /// Call bitcoin-cli [params] on in [network] - Rpc { - node: u64, - #[arg(allow_hyphen_values=true)] - method: String, - params: Option>, + command: Option, }, /// Call lncli [params] on in [network] LnCli { @@ -59,13 +54,26 @@ enum Commands { method: String, params: Option>, }, - /// Fetch the Bitcoin Core debug log from in [network] - DebugLog { node: u64 }, /// Fetch messages sent between and in [network] Messages { node_a: u64, node_b: u64 }, - /// Grep combined logs via fluentd using regex - GrepLogs { pattern: String }, - /// Stop warnet + /// Network commands + Network { + #[command(subcommand)] + command: Option, + }, + /// Call bitcoin-cli [params] on in [network] + Rpc { + node: u64, + #[arg(allow_hyphen_values = true)] + method: String, + params: Option>, + }, + /// Scenario commands + Scenarios { + #[command(subcommand)] + command: Option, + }, + /// Stop warnet server Stop {}, } @@ -117,6 +125,11 @@ async fn main() -> anyhow::Result<()> { Some(Commands::DebugLog { node }) => { handle_debug_log_command(node, rpc_params).await?; } + Some(Commands::Image { command }) => { + if let Some(command) = command { + handle_image_command(command).await?; + } + } Some(Commands::Messages { node_a, node_b }) => { handle_messages_command(node_a, node_b, rpc_params).await?; } From 8845a50b7ffed7240b375f15698555ef692eb187 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Mon, 1 Apr 2024 20:40:13 +0100 Subject: [PATCH 32/34] tidy up help strings --- src/rust-cli/debug.rs | 7 +++++-- src/rust-cli/graph.rs | 9 +++++++-- src/rust-cli/image.rs | 9 ++++++++- src/rust-cli/main.rs | 33 +++++++++++++++++++++++++-------- src/rust-cli/network.rs | 4 +++- src/rust-cli/scenarios.rs | 15 +++++++++++---- 6 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/rust-cli/debug.rs b/src/rust-cli/debug.rs index dece6925e..7597f7c7f 100644 --- a/src/rust-cli/debug.rs +++ b/src/rust-cli/debug.rs @@ -8,8 +8,11 @@ use crate::rpc_call::make_rpc_call; #[derive(Subcommand, Debug)] pub enum DebugCommand { - /// Generate the docker-compose file for a given and return it. - GenerateCompose { graph_file_path: PathBuf }, + /// Generate the docker-compose file for a given graph_file + GenerateCompose { + /// Path to graph file to generate from + graph_file_path: PathBuf, + }, } pub async fn handle_debug_command( diff --git a/src/rust-cli/graph.rs b/src/rust-cli/graph.rs index 20b3d7faf..7076d7040 100644 --- a/src/rust-cli/graph.rs +++ b/src/rust-cli/graph.rs @@ -16,18 +16,23 @@ use xmltree::{Element, EmitterConfig, XMLNode}; #[derive(Subcommand, Debug)] pub enum GraphCommand { - /// Create a cycle graph with nodes, and include 7 extra random outbounds per node. - /// Returns XML file as string with or without --outfile option + /// Create a cycle graph with 7 extra random outbounds per node. Create { + /// Number of nodes in the graph number: usize, + /// Write graph to a this file path #[arg(short, long)] outfile: Option, + /// Bitcoin Core version to set on nodes #[arg(short, long)] version: Option, + /// config values to add to bitcoin.conf #[arg(short, long)] bitcoin_conf: Option, }, + /// (broken) Validate a *.graphml file against the graph schema Validate { + /// Path to graph file graph: PathBuf, }, } diff --git a/src/rust-cli/image.rs b/src/rust-cli/image.rs index 8bfd33999..29a6432f5 100644 --- a/src/rust-cli/image.rs +++ b/src/rust-cli/image.rs @@ -5,21 +5,28 @@ use std::process::{Command, Stdio}; #[derive(Subcommand, Debug)] pub enum ImageCommand { - /// Build bitcoind and bitcoin-cli from / as :. + /// Build a bitcoind/bitcoin-cli docker image. /// Optionally deploy to remote registry using --action=push, otherwise image is loaded to local registry. Build { + /// Github repo e.g. bitcoin/bitcoin #[arg(long)] repo: String, + /// Branch e.g. v27.0 #[arg(long)] branch: String, + /// docker registry e.g. user/repo #[arg(long)] registry: String, + /// docker image tag(s) to apply e.g. 27.0-warnet #[arg(long)] tag: String, + /// Custom Bitcoin Core build args to use #[arg(long)] build_args: Option, + /// Arches to build for (multiple arches only supported with action=push) #[arg(long)] arches: Option, + /// Load (to local) or push (to remote) registry #[arg(long)] action: Option, }, diff --git a/src/rust-cli/main.rs b/src/rust-cli/main.rs index 6b9b054d0..f02d2c939 100644 --- a/src/rust-cli/main.rs +++ b/src/rust-cli/main.rs @@ -34,38 +34,55 @@ enum Commands { #[command(subcommand)] command: Option, }, - /// Fetch the Bitcoin Core debug log from in [network] - DebugLog { node: u64 }, + /// Fetch the Bitcoin Core debug log from a node + DebugLog { + /// Node index (integer) + node: u64, + }, /// Graph commands Graph { #[command(subcommand)] command: Option, }, - /// Grep combined logs via fluentd using regex - GrepLogs { pattern: String }, + /// Grep combined logs using regex + GrepLogs { + /// Pattern to search for (as regex) + pattern: String, + }, /// Build a warnet-ready bitcoind docker image from a github branch Image { #[command(subcommand)] command: Option, }, - /// Call lncli [params] on in [network] + /// Call "lncli ..." on a node LnCli { + /// Node index (integer) node: u64, + /// lncli method method: String, + /// Optional arguments to method params: Option>, }, - /// Fetch messages sent between and in [network] - Messages { node_a: u64, node_b: u64 }, + /// Fetch bitcoin P2P messages sent between two nodes + Messages { + /// First node + node_a: u64, + /// Second node + node_b: u64, + }, /// Network commands Network { #[command(subcommand)] command: Option, }, - /// Call bitcoin-cli [params] on in [network] + /// Call "bitcoin-cli ..." on a node Rpc { + /// Node index (integer) node: u64, + /// bitcoin-cli method #[arg(allow_hyphen_values = true)] method: String, + /// Optional arguments to method params: Option>, }, /// Scenario commands diff --git a/src/rust-cli/network.rs b/src/rust-cli/network.rs index dd97a9ce8..2d074ef91 100644 --- a/src/rust-cli/network.rs +++ b/src/rust-cli/network.rs @@ -10,9 +10,11 @@ use crate::rpc_call::make_rpc_call; #[derive(Subcommand, Debug)] pub enum NetworkCommand { - /// Start a network from a + /// Start a network from a graph_file Start { + /// Path to graph file graph_file: PathBuf, + /// Force overwite config dir if already exists #[arg(long, short)] force: bool, }, diff --git a/src/rust-cli/scenarios.rs b/src/rust-cli/scenarios.rs index 271a2b549..cd1247982 100644 --- a/src/rust-cli/scenarios.rs +++ b/src/rust-cli/scenarios.rs @@ -10,20 +10,27 @@ use std::path::PathBuf; pub enum ScenarioCommand { /// List available scenarios in the Warnet Test Framework Available {}, - /// Run a scenario from remote repository with + /// Run a scenario file from remote repository (on warnet server) Run { + /// Scenario name scenario: String, + /// Arguments to scenario additional_args: Vec, }, - /// Run a local scenario by sending it to the server + /// Run a local scenario file by sending it to the server RunFile { + /// Path to scenario file scenario_path: PathBuf, + /// Arguments to scenario additional_args: Vec, }, /// List active scenarios Active {}, - /// Stop a scenario with - Stop { pid: u64 }, + /// Stop a scenario + Stop { + /// PID of scenario to stop + pid: u64, + }, } async fn handle_available(params: ObjectParams) -> anyhow::Result<()> { let data = make_rpc_call("scenarios_available", params) From 22728cf714583fcfeed7f0b904e6d306bf6b7f10 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Mon, 1 Apr 2024 21:17:53 +0100 Subject: [PATCH 33/34] use bail! macro. Fix lncli RPC call --- src/rust-cli/debug.rs | 6 ++++-- src/rust-cli/general.rs | 10 +++++----- src/rust-cli/graph.rs | 4 ++-- src/rust-cli/image.rs | 14 ++++++-------- src/rust-cli/main.rs | 2 +- src/rust-cli/network.rs | 25 +++++++++++++++++-------- src/rust-cli/scenarios.rs | 22 +++++++++++----------- 7 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/rust-cli/debug.rs b/src/rust-cli/debug.rs index 7597f7c7f..4fdbb0af0 100644 --- a/src/rust-cli/debug.rs +++ b/src/rust-cli/debug.rs @@ -23,8 +23,10 @@ pub async fn handle_debug_command( DebugCommand::GenerateCompose { graph_file_path } => { rpc_params .insert("graph_file", graph_file_path.to_str()) - .context("Add graph file path to params")?; - let data = make_rpc_call("generate_compose", rpc_params).await?; + .context("Adding graph_file_path to rpc params")?; + let data = make_rpc_call("generate_compose", rpc_params) + .await + .context("Calling generate_compose RPC")?; println!("Docker-compose file generated: {:?}", data); } } diff --git a/src/rust-cli/general.rs b/src/rust-cli/general.rs index d4e30e49c..9209d3722 100644 --- a/src/rust-cli/general.rs +++ b/src/rust-cli/general.rs @@ -26,14 +26,14 @@ pub async fn handle_rpc_commands( params.insert("params", p).context("add rpc params")?; } let data = match node_type { - NodeType::LnCli => make_rpc_call("tank_bcli", params) + NodeType::LnCli => make_rpc_call("tank_lncli", params) .await - .context("Failed to make RPC call LnCli")?, + .context("make RPC call lncli")?, NodeType::BitcoinCli => make_rpc_call("tank_bcli", params) .await - .context("Failed to make RPC call BitcoinCli")?, + .context("make RPC call bitcoin-cli")?, }; - pretty_print_value(&data).context("pretty print result")?; + pretty_print_value(&data).context("Pretty print the result")?; Ok(()) } @@ -43,7 +43,7 @@ pub async fn handle_debug_log_command(node: &u64, mut params: ObjectParams) -> a .context("add node_index param")?; let data = make_rpc_call("tank_debug_log", params) .await - .context("Failed to make RPC call tank_debug_log")?; + .context("make RPC call tank_debug_log")?; pretty_print_value(&data).context("pretty print result")?; Ok(()) } diff --git a/src/rust-cli/graph.rs b/src/rust-cli/graph.rs index 7076d7040..70dbf88c8 100644 --- a/src/rust-cli/graph.rs +++ b/src/rust-cli/graph.rs @@ -20,7 +20,7 @@ pub enum GraphCommand { Create { /// Number of nodes in the graph number: usize, - /// Write graph to a this file path + /// Write graph to this file path #[arg(short, long)] outfile: Option, /// Bitcoin Core version to set on nodes @@ -263,7 +263,7 @@ pub async fn handle_graph_command(command: &GraphCommand) -> anyhow::Result<()> .context("Create a graph")?, GraphCommand::Validate { graph } => { - let _ = validate_schema(graph); + let _ = validate_schema(graph).context("Validating graph schema"); } } Ok(()) diff --git a/src/rust-cli/image.rs b/src/rust-cli/image.rs index 29a6432f5..86a5413ed 100644 --- a/src/rust-cli/image.rs +++ b/src/rust-cli/image.rs @@ -1,4 +1,4 @@ -use anyhow::anyhow; +use anyhow::bail; use clap::Subcommand; use std::fs; use std::process::{Command, Stdio}; @@ -48,7 +48,7 @@ fn run_command(command: &str) -> anyhow::Result { if output.success() { Ok(true) } else { - Err(anyhow!("Command failed")) + bail!("Command failed") } } @@ -75,7 +75,7 @@ fn build_image( for arch in &build_arches { if !ARCHES.contains(&arch.as_str()) { println!("Error: {} is not a supported architecture", arch); - return Err(anyhow!("Unsupported architecture: {}", arch)); + bail!("Unsupported architecture: {}", arch); } } @@ -92,7 +92,7 @@ fn build_image( { println!("Directory src/templates does not exist."); println!("Please run this script from the project root."); - return Err(anyhow!("src/templates directory not found")); + bail!("src/templates directory not found"); } let builder_name = "bitcoind-builder"; @@ -140,10 +140,8 @@ fn build_image( match res { Ok(true) => Ok(()), - Ok(false) => Err(anyhow!( - "Build command failed, but no specific error was provided." - )), - Err(e) => Err(anyhow!("Build command failed with error: {}", e)), + Ok(false) => bail!("Build command failed, but no specific error was provided."), + Err(e) => bail!("Build command failed with error: {}", e), } } diff --git a/src/rust-cli/main.rs b/src/rust-cli/main.rs index f02d2c939..548ded168 100644 --- a/src/rust-cli/main.rs +++ b/src/rust-cli/main.rs @@ -101,7 +101,7 @@ async fn main() -> anyhow::Result<()> { if let Some(network_value) = &cli.network { rpc_params .insert("network", network_value) - .context("add network param")?; + .context("Adding --network to rpc_params")?; } match &cli.command { diff --git a/src/rust-cli/network.rs b/src/rust-cli/network.rs index 2d074ef91..edb04d515 100644 --- a/src/rust-cli/network.rs +++ b/src/rust-cli/network.rs @@ -1,4 +1,4 @@ -use anyhow::Context; +use anyhow::{bail, Context}; use base64::{engine::general_purpose, Engine as _}; use clap::Subcommand; use jsonrpsee::core::params::ObjectParams; @@ -33,11 +33,11 @@ pub enum NetworkCommand { } fn graph_file_to_b64(graph_file: &PathBuf) -> anyhow::Result { - let file_contents = std::fs::read(graph_file).context("Failed to read graph file")?; + let file_contents = std::fs::read(graph_file).context("Failed to read graph file from fs")?; Ok(general_purpose::STANDARD.encode(file_contents)) } -fn handle_network_status_response(data: serde_json::Value) { +fn handle_network_status_response(data: serde_json::Value) -> anyhow::Result<()> { if let serde_json::Value::Array(items) = &data { for item in items { if let (Some(tank_index), Some(bitcoin_status)) = ( @@ -46,12 +46,13 @@ fn handle_network_status_response(data: serde_json::Value) { ) { println!("Tank: {:<6} Bitcoin: {}", tank_index, bitcoin_status); } else { - println!("Error: Response item is missing expected fields"); + bail!("Error: Response item is missing expected fields"); } } } else { - println!("Error: Expected an array in the response"); + bail!("Error: Expected an array in the response"); } + Ok(()) } fn handle_network_start_response(data: serde_json::Value) -> anyhow::Result<()> { @@ -81,6 +82,8 @@ fn handle_network_start_response(data: serde_json::Value) -> anyhow::Result<()> )); } table.printstd(); + } else { + bail!("No warnet table headers found in response") } // tanks table if let Some(tank_headers) = data["tank_headers"].as_array() { @@ -109,6 +112,8 @@ fn handle_network_start_response(data: serde_json::Value) -> anyhow::Result<()> } } table.printstd(); + } else { + bail!("no tank headers found in response") } Ok(()) } @@ -119,7 +124,8 @@ pub async fn handle_network_command( ) -> anyhow::Result<()> { let (request, params) = match command { NetworkCommand::Start { graph_file, force } => { - let b64_graph = graph_file_to_b64(graph_file).context("Read graph file")?; + let b64_graph = + graph_file_to_b64(graph_file).context("Reading graph file to base 64")?; params .insert("graph_file", b64_graph) .context("Add base64 graph file to params")?; @@ -138,9 +144,12 @@ pub async fn handle_network_command( let data = make_rpc_call(request, params).await?; match request { - "network_status" => handle_network_status_response(data), + "network_status" => { + handle_network_status_response(data).context("Handling network status response")? + } "network_from_file" => { - handle_network_start_response(data.clone())?; + handle_network_start_response(data.clone()) + .context("Handling network start response")?; } _ => { println!("{}", data) diff --git a/src/rust-cli/scenarios.rs b/src/rust-cli/scenarios.rs index cd1247982..daf3dbfb8 100644 --- a/src/rust-cli/scenarios.rs +++ b/src/rust-cli/scenarios.rs @@ -1,5 +1,5 @@ use crate::rpc_call::make_rpc_call; -use anyhow::Context; +use anyhow::{bail, Context}; use base64::{engine::general_purpose, Engine as _}; use clap::Subcommand; use jsonrpsee::core::params::ObjectParams; @@ -35,7 +35,7 @@ pub enum ScenarioCommand { async fn handle_available(params: ObjectParams) -> anyhow::Result<()> { let data = make_rpc_call("scenarios_available", params) .await - .context("Failed to fetch available scenarios")?; + .context("Making RPC to fetch available scenarios")?; if let serde_json::Value::Array(scenarios) = data { let mut table = Table::new(); table.add_row(row!["Scenario", "Description"]); @@ -50,7 +50,7 @@ async fn handle_available(params: ObjectParams) -> anyhow::Result<()> { } table.printstd(); } else { - println!("Unexpected response format."); + bail!("Unexpected response format."); } Ok(()) } @@ -68,7 +68,7 @@ async fn handle_run( .context("Add additional_args to params")?; let data = make_rpc_call("scenarios_run", params) .await - .context("Failed to run scenario")?; + .context("Making RPC call to run scenario with remote file")?; println!("{:?}", data); Ok(()) } @@ -82,13 +82,13 @@ async fn handle_run_file( let scenario_base64 = general_purpose::STANDARD.encode(file_contents); params .insert("scenario_base64", scenario_base64) - .context("Add scenario to params")?; + .context("Adding scenario to params")?; params .insert("additional_args", additional_args) - .context("Add additional_args to params")?; + .context("Adding additional_args to params")?; let data = make_rpc_call("scenarios_run_file", params) .await - .context("Failed to run scenario")?; + .context("Making RPC call to run scenario with local file")?; println!("{:?}", data); Ok(()) } @@ -96,7 +96,7 @@ async fn handle_run_file( async fn handle_active(params: ObjectParams) -> anyhow::Result<()> { let data = make_rpc_call("scenarios_list_running", params) .await - .context("Failed to list running scenarios")?; + .context("Making RPC call to list running scenarios")?; if let serde_json::Value::Array(scenarios) = data { let mut table = Table::new(); table.add_row(row!["PID", "Command", "Network", "Active"]); @@ -123,7 +123,7 @@ async fn handle_active(params: ObjectParams) -> anyhow::Result<()> { } table.printstd(); } else { - println!("Unexpected response format."); + bail!("Unexpected response format."); } Ok(()) } @@ -132,11 +132,11 @@ async fn handle_stop(mut params: ObjectParams, pid: &u64) -> anyhow::Result<()> params.insert("pid", pid).context("Add pid to params")?; let data = make_rpc_call("scenarios_stop", params) .await - .context("Failed to stop running scenario")?; + .context("Making RPC call to stop running scenario")?; if let serde_json::Value::String(message) = data { println!("{}", message); } else { - println!("Unexpected response format."); + bail!("Unexpected response format."); } Ok(()) } From b87d36f1c3031fe8ae4c1e0a02eea284e33dbbfa Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Fri, 29 Mar 2024 21:52:09 +0000 Subject: [PATCH 34/34] doc: add rust cli docs --- docs/install.md | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/docs/install.md b/docs/install.md index 8f2fea085..a5211e56e 100644 --- a/docs/install.md +++ b/docs/install.md @@ -70,14 +70,27 @@ cd warnet ## Install Warnet -### Optional: use a virtual Python environment such as `venv` +The Warnet server and cli tool need to be installed using PIP: -```bash -python3 -m venv .venv # Use alternative venv manager if desired -source .venv/bin/activate -``` +> [!TIP] +> Use a python virtual environment such as venv +> ```bash +> python3 -m venv .venv # Use alternative venv manager if desired +> source .venv/bin/activate +> ``` ```bash pip install --upgrade pip pip install -e . ``` + +### Experimental Rust cli tool + +There is an experimental Rust cli tool which can be built using `cargo`: + +```bash +# build +cargo build +# Run +./target/debug/warcli help +```