diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 0000000..9cb476b --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,34 @@ +name: check +on: + pull_request: + branches: [main] + push: + branches: [main] + +jobs: + check: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [macos-latest, macos-14] + steps: + - uses: actions/checkout@main + - uses: DeterminateSystems/nix-installer-action@main + - uses: cachix/cachix-action@main + with: + name: cspr + authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' + + - name: System Info + run: | + uname -a + nix --version + + - name: cctl-rs (x86_64-darwin) + if: matrix.os == 'macos-latest' + run: nix build -L --no-link --show-trace .#packages.x86_64-darwin.cctld + + - name: cctl-rs (aarch64-darwin) + if: matrix.os == 'macos-14' + run: nix build -L --no-link --show-trace .#packages.aarch64-darwin.cctld diff --git a/.github/workflows/pre-check.yml b/.github/workflows/pre-check.yml new file mode 100644 index 0000000..1b77ecb --- /dev/null +++ b/.github/workflows/pre-check.yml @@ -0,0 +1,11 @@ +name: pre-check +on: + pull_request: + branches: [main] + +jobs: + check-signed-commits: + runs-on: ubuntu-latest + steps: + - name: check signed commits + uses: 1Password/check-signed-commits-action@v1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3735805 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +result +.direnv +.envrc +target +.tmp +.nixos-test-history diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..7b1cb4e --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2613 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[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.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "async-trait" +version = "0.1.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backoff" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" +dependencies = [ + "futures-core", + "getrandom", + "instant", + "pin-project-lite", + "rand 0.8.5", + "tokio", +] + +[[package]] +name = "backtrace" +version = "0.3.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base16" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d27c3610c36aee21ce8ac510e6224498de4228ad772a171ed65643a24693a5a8" + +[[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 = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bitvec" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98fcd36dda4e17b7d7abc64cb549bf0201f4ab71e00700c798ca7e62ed3761fa" +dependencies = [ + "funty", + "radium", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a4e37d16930f5459780f5621038b6382b9bb37c19016f39fb6b5808d831f174" +dependencies = [ + "crypto-mac 0.8.0", + "digest", + "opaque-debug", +] + +[[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.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" + +[[package]] +name = "casper-client" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7aee479ac95ca2100bef1654621fcaac122af56d7bac8bdb1f0384e088c9914" +dependencies = [ + "async-trait", + "base16", + "base64 0.13.1", + "casper-hashing", + "casper-types", + "clap", + "clap_complete", + "derp", + "ed25519-dalek", + "getrandom", + "hex-buffer-serde 0.4.0", + "humantime", + "itertools", + "jsonrpc-lite", + "k256", + "num-traits", + "once_cell", + "pem 1.1.1", + "rand 0.8.5", + "reqwest", + "schemars", + "serde", + "serde_json", + "signature", + "tempfile", + "thiserror", + "tokio", + "uint", + "untrusted 0.9.0", + "vergen", +] + +[[package]] +name = "casper-hashing" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9cafc15f22892b417888b9eafc63a07e8233c5c51ffb15e420b1e2fe7ea9293" +dependencies = [ + "base16", + "blake2", + "casper-types", + "datasize", + "hex", + "hex-buffer-serde 0.3.0", + "hex_fmt", + "itertools", + "once_cell", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "casper-types" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d65faf6ea346ce733206a51822cb4da2a76cee29308b0ee4c1f3cba756bdee5" +dependencies = [ + "base16", + "base64 0.13.1", + "bitflags 1.3.2", + "blake2", + "datasize", + "derp", + "ed25519-dalek", + "getrandom", + "hex", + "hex_fmt", + "humantime", + "k256", + "num", + "num-derive", + "num-integer", + "num-rational", + "num-traits", + "once_cell", + "pem 0.8.3", + "rand 0.8.5", + "serde", + "serde_bytes", + "serde_json", + "thiserror", + "uint", + "untrusted 0.7.1", +] + +[[package]] +name = "cc" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cctl-rs" +version = "0.1.0" +dependencies = [ + "anyhow", + "backoff", + "casper-client", + "casper-types", + "clap", + "hex", + "nom", + "sd-notify", + "tempfile", + "tokio", + "tracing", + "tracing-subscriber", +] + +[[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.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", + "terminal_size", +] + +[[package]] +name = "clap_complete" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee158892bd7ce77aa15c208abbdb73e155d191c287a659b57abd5adb92feb03" +dependencies = [ + "clap", +] + +[[package]] +name = "clap_derive" +version = "4.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + +[[package]] +name = "const-oid" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f6b64db6932c7e49332728e3a6bd82c6b7e16016607d20923b537c3bc4c0d5f" + +[[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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +dependencies = [ + "libc", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "crypto-mac" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "datasize" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e65c07d59e45d77a8bda53458c24a828893a99ac6cdd9c84111e09176ab739a2" +dependencies = [ + "datasize_derive", +] + +[[package]] +name = "datasize_derive" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613e4ee15899913285b7612004bbd490abd605be7b11d35afada5902fb6b91d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "der" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f59c66c30bb7445c8320a5f9233e437e3572368099f25532a59054328899b4" +dependencies = [ + "const-oid", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derp" +version = "0.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9b84cfd9b6fa437e498215e5625e9e3ae3bf9bb54d623028a181c40820db169" +dependencies = [ + "untrusted 0.7.1", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "ecdsa" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fbdb4ff710acb4db8ca29f93b897529ea6d6a45626d5183b47e012aa6ae7e4" +dependencies = [ + "elliptic-curve", + "hmac", + "signature", +] + +[[package]] +name = "ed25519" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4620d40f6d2601794401d6dd95a5cf69b6c157852539470eeda433a99b3c0efc" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand 0.7.3", + "sha2", + "zeroize", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "elliptic-curve" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2db227e61a43a34915680bdda462ec0e212095518020a88a1f91acd16092c39" +dependencies = [ + "bitvec", + "digest", + "ff", + "funty", + "generic-array", + "group", + "pkcs8", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum-iterator" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fd242f399be1da0a5354aa462d57b4ab2b4ee0683cc552f7c007d2d12d36e94" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ab991c1362ac86c61ab6f556cff143daa22e5a15e4e189df818b2fd19fe65b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + +[[package]] +name = "ff" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01646e077d4ebda82b73f1bca002ea1e91561a77df2431a9e79729bcc31950ef" +dependencies = [ + "bitvec", + "rand_core 0.5.1", + "subtle", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[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 = "funty" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[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-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[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.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getset" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] +name = "git2" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2994bee4a3a6a51eb90c218523be382fd7ea09b16380b9312e9dbe955ff7c7d1" +dependencies = [ + "bitflags 1.3.2", + "libc", + "libgit2-sys", + "log", + "url", +] + +[[package]] +name = "group" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc11f9f5fbf1943b48ae7c2bf6846e7d827a512d1be4f23af708f5ca5d01dde1" +dependencies = [ + "ff", + "rand_core 0.5.1", + "subtle", +] + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 2.4.0", + "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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[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 = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hex-buffer-serde" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f52012c160668b4494727f3588045aa00429849fcae51de70d68fa98228039" +dependencies = [ + "hex", + "serde", +] + +[[package]] +name = "hex-buffer-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e84645a601cf4a58f40673d51c111d1b5f847b711559c076ebcb779606a6d0" +dependencies = [ + "hex", + "serde", +] + +[[package]] +name = "hex_fmt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" + +[[package]] +name = "hmac" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" +dependencies = [ + "crypto-mac 0.10.1", + "digest", +] + +[[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.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "0.14.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +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-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[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 = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jsonrpc-lite" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4128aba82294c14af2998831c4df3c843940e92b5cfc41bac1229d1e63b88c" +dependencies = [ + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "k256" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4476a0808212a9e81ce802eb1a0cfc60e73aea296553bacc0fac7e1268bc572a" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "sha2", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "libgit2-sys" +version = "0.14.2+1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f3d95f6b51075fe9810a7ae22c7095f12b98005ab364d8544797a825ce946a4" +dependencies = [ + "cc", + "libc", + "libz-sys", + "pkg-config", +] + +[[package]] +name = "libz-sys" +version = "1.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc53a7799a7496ebc9fd29f31f7df80e83c9bda5299768af5f9e59eeea74647" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[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 = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +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-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[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.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.36.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +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" +version = "0.10.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "pem" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb" +dependencies = [ + "base64 0.13.1", + "once_cell", + "regex", +] + +[[package]] +name = "pem" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +dependencies = [ + "base64 0.13.1", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4839a901843f3942576e65857f0ebf2e190ef7024d3c62a94099ba3f819ad1d" +dependencies = [ + "der", +] + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[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.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[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 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "redox_syscall" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[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", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[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 = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[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 = "schemars" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b82485a532ef0af18878ad4281f73e58161cdba1db7918176e9294f0ca5498a5" +dependencies = [ + "dyn-clone", + "indexmap 1.9.3", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791c2c848cff1abaeae34fef7e70da5f93171d9eea81ce0fe969a1df627a61a8" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sd-notify" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4646d6f919800cd25c50edb49438a1381e2cd4833c027e75e8897981c50b8b5e" + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.208" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.208" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "serde_derive_internals" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dbab34ca63057a1f15280bdf3c39f2b1eb1b54c17e98360e511637aef7418c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "serde_json" +version = "1.0.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" +dependencies = [ + "indexmap 2.4.0", + "itoa", + "memchr", + "ryu", + "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 = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29f060a7d147e33490ec10da418795238fd7545bba241504d6b31a409f2e6210" +dependencies = [ + "digest", + "rand_core 0.5.1", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +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.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +dependencies = [ + "proc-macro2", + "quote", + "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 = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "terminal_size" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +dependencies = [ + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "thiserror" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1b05ca9d106ba7d2e31a9dab4a64e7be2cce415321966ea3132c49a656e252" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8f2591983642de85c921015f3f070c665a197ed69e417af436115e3a1407487" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "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.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +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.39.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "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 2.0.75", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[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 = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "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.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "vergen" +version = "7.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "571b69f690c855821462709b6f41d42ceccc316fbd17b60bd06d06928cfe6a99" +dependencies = [ + "anyhow", + "cfg-if", + "enum-iterator", + "getset", + "git2", + "rustversion", + "thiserror", + "time", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[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.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.75", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[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" +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.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[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 = "wyz" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..39ba943 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "cctl-rs" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" + +[[bin]] +name = "cctld" +path = "bin/cctld.rs" +version = "0.1.0" +test = false +bench = false + +[lib] +name = "cctl" +path = "src/lib.rs" + +[dependencies] + +anyhow = "1" +backoff = { version = "0.4", features = ["tokio", "futures"]} +clap = { version = "4", features = ["derive"] } +casper-client = "2.0" +casper-types = "3.0" +nom = "7" +hex = "0.4" +sd-notify = "0.4" +tokio = { version = "1", features = [ "full", "tracing", "macros" ] } +tempfile = "3" +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = ["std", "env-filter"] } diff --git a/bin/cctld.rs b/bin/cctld.rs new file mode 100644 index 0000000..a7b0c96 --- /dev/null +++ b/bin/cctld.rs @@ -0,0 +1,48 @@ +use casper_types::{runtime_args, RuntimeArgs}; +use cctl::cctl; +use clap::Parser; +use sd_notify::NotifyState; +use std::path::PathBuf; +use tokio::signal; + +use crate::cctl::DeployableContract; + +#[derive(Parser)] +pub struct Cli { + #[arg(short, long)] + pub working_dir: Option, + #[arg(short, long)] + pub deploy_contract: Option, + #[arg(short, long)] + pub chainspec_path: Option, + #[arg(short, long)] + pub config_path: Option, +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + let cli = Cli::parse(); + let deploy_contract = cli.deploy_contract.map(|deploy_contracts_arg| { + match deploy_contracts_arg.split_once(':') { + Some((hash_name, path)) => DeployableContract { + hash_name: hash_name.to_string(), + // FIXME at some point we want to make this parametrizable + runtime_args: runtime_args! { "initial_trie_root" => Option::<[u8; 32]>::None }, + path: PathBuf::from(&path), + }, + None => panic!("Error parsing the provided deploy contracts argument."), + } + }); + let _network = cctl::CCTLNetwork::run( + cli.working_dir, + deploy_contract, + cli.chainspec_path, + cli.config_path, + ) + .await + .expect("An error occured while starting the CCTL network"); + + let _ = sd_notify::notify(true, &[NotifyState::Ready]); + signal::ctrl_c().await?; + Ok(()) +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..6a036a0 --- /dev/null +++ b/flake.lock @@ -0,0 +1,627 @@ +{ + "nodes": { + "advisory-db": { + "flake": false, + "locked": { + "lastModified": 1723840407, + "narHash": "sha256-AZI593yLh4lcKJdAnnjyLMKUm5PMDpFy1APIYFURLyI=", + "owner": "rustsec", + "repo": "advisory-db", + "rev": "201638b35a3e85b7794e84cc73f876d7a2b7ad51", + "type": "github" + }, + "original": { + "owner": "rustsec", + "repo": "advisory-db", + "type": "github" + } + }, + "agenix": { + "inputs": { + "darwin": "darwin", + "home-manager": "home-manager", + "nixpkgs": [ + "cctl-2", + "csprpkgs", + "nixpkgs" + ], + "systems": "systems_2" + }, + "locked": { + "lastModified": 1712079060, + "narHash": "sha256-/JdiT9t+zzjChc5qQiF+jhrVhRt8figYH29rZO7pFe4=", + "owner": "ryantm", + "repo": "agenix", + "rev": "1381a759b205dff7a6818733118d02253340fd5e", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, + "agenix_2": { + "inputs": { + "darwin": "darwin_2", + "home-manager": "home-manager_2", + "nixpkgs": [ + "csprpkgs", + "nixpkgs" + ], + "systems": "systems_4" + }, + "locked": { + "lastModified": 1722339003, + "narHash": "sha256-ZeS51uJI30ehNkcZ4uKqT4ZDARPyqrHADSKAwv5vVCU=", + "owner": "ryantm", + "repo": "agenix", + "rev": "3f1dae074a12feb7327b4bf43cbac0d124488bb7", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, + "cctl": { + "inputs": { + "csprpkgs": "csprpkgs", + "nixpkgs": [ + "cctl", + "csprpkgs", + "nixpkgs" + ], + "rust-overlay": [ + "cctl", + "csprpkgs", + "rust-overlay" + ] + }, + "locked": { + "lastModified": 1717998887, + "narHash": "sha256-0i3xRAkHI+NPwxGWC3vtJeQyAxfuxr//W7gBT6iuFuk=", + "owner": "casper-network", + "repo": "cctl", + "rev": "947c34b991e37476db82ccfa2bd7c0312c1a91d7", + "type": "github" + }, + "original": { + "owner": "casper-network", + "repo": "cctl", + "rev": "947c34b991e37476db82ccfa2bd7c0312c1a91d7", + "type": "github" + } + }, + "cctl-2": { + "inputs": { + "csprpkgs": "csprpkgs_2", + "nixpkgs": [ + "cctl-2", + "csprpkgs", + "nixpkgs" + ], + "rust-overlay": [ + "cctl-2", + "csprpkgs", + "rust-overlay" + ] + }, + "locked": { + "lastModified": 1723558192, + "narHash": "sha256-Y9Ct935VyCdOIYfl+QDNAE2bMCnDJOu2HCwZnm/mbsI=", + "owner": "casper-network", + "repo": "cctl", + "rev": "2da83ec5e50c64bd8d7f9c6c986c1da375465678", + "type": "github" + }, + "original": { + "owner": "casper-network", + "repo": "cctl", + "type": "github" + } + }, + "crane": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1724006180, + "narHash": "sha256-PVxPj0Ga2fMYMtcT9ARCthF+4U71YkOT7ZjgD/vf1Aw=", + "owner": "ipetkov", + "repo": "crane", + "rev": "7ce92819802bc583b7e82ebc08013a530f22209f", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "csprpkgs": { + "inputs": { + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + }, + "locked": { + "lastModified": 1712271889, + "narHash": "sha256-5t8QSUeIyDpHCOB+PnS3wtFqAjNf07X0wZhxZb+J/qk=", + "owner": "cspr-rad", + "repo": "csprpkgs", + "rev": "9d01d5c63ff179ee8c42cdcbf8cf892c96c0a0b1", + "type": "github" + }, + "original": { + "owner": "cspr-rad", + "repo": "csprpkgs", + "type": "github" + } + }, + "csprpkgs_2": { + "inputs": { + "agenix": "agenix", + "nixpkgs": "nixpkgs_2", + "rust-overlay": "rust-overlay_2" + }, + "locked": { + "lastModified": 1722410860, + "narHash": "sha256-aL5bf+/X3YR+uqVgD6t1tT23Xw47XJDfE2tXQ2uF6uw=", + "owner": "cspr-rad", + "repo": "csprpkgs", + "rev": "ba58f48daf43bfc84467261969b2388ab779b2de", + "type": "github" + }, + "original": { + "owner": "cspr-rad", + "repo": "csprpkgs", + "type": "github" + } + }, + "csprpkgs_3": { + "inputs": { + "agenix": "agenix_2", + "nixpkgs": "nixpkgs_3", + "rust-overlay": "rust-overlay_3" + }, + "locked": { + "lastModified": 1723826679, + "narHash": "sha256-ZL9tppGgOsJi0Z49Lc77mfy3GakX/QbI1CIIKGt4gjs=", + "owner": "cspr-rad", + "repo": "csprpkgs", + "rev": "2e3b082f9bf3b0239f12dec7246b4d19534b811e", + "type": "github" + }, + "original": { + "owner": "cspr-rad", + "repo": "csprpkgs", + "type": "github" + } + }, + "darwin": { + "inputs": { + "nixpkgs": [ + "cctl-2", + "csprpkgs", + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1700795494, + "narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=", + "owner": "lnl7", + "repo": "nix-darwin", + "rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d", + "type": "github" + }, + "original": { + "owner": "lnl7", + "ref": "master", + "repo": "nix-darwin", + "type": "github" + } + }, + "darwin_2": { + "inputs": { + "nixpkgs": [ + "csprpkgs", + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1700795494, + "narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=", + "owner": "lnl7", + "repo": "nix-darwin", + "rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d", + "type": "github" + }, + "original": { + "owner": "lnl7", + "ref": "master", + "repo": "nix-darwin", + "type": "github" + } + }, + "fenix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, + "locked": { + "lastModified": 1724049063, + "narHash": "sha256-aTnh9Ar40OaT2MTULeJMR9EIrylKeKUYWP61QEZBu0Q=", + "owner": "nix-community", + "repo": "fenix", + "rev": "94c18bf5acb3966b07cc863bd00f4f959c0c5ec4", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1722555600, + "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "8471fe90ad337a8074e957b69ca4d0089218391d", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1705309234, + "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_3" + }, + "locked": { + "lastModified": 1705309234, + "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "cctl-2", + "csprpkgs", + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1703113217, + "narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_2": { + "inputs": { + "nixpkgs": [ + "csprpkgs", + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1703113217, + "narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1712192574, + "narHash": "sha256-LbbVOliJKTF4Zl2b9salumvdMXuQBr2kuKP5+ZwbYq4=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "f480f9d09e4b4cf87ee6151eba068197125714de", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1722555339, + "narHash": "sha256-uFf2QeW7eAHlYXuDktm9c25OxOyCoUOQmh5SZ9amE5Q=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/a5d394176e64ab29c852d03346c1fc9b0b7d33eb.tar.gz" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1712192574, + "narHash": "sha256-LbbVOliJKTF4Zl2b9salumvdMXuQBr2kuKP5+ZwbYq4=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "f480f9d09e4b4cf87ee6151eba068197125714de", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1722730825, + "narHash": "sha256-X6U+w8qFBuGPCYrZzc9mpN34aRjQ8604MonpBUkj908=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "f3834de3782b82bfc666abf664f946d0e7d1f116", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1724015816, + "narHash": "sha256-hVESnM7Eiz93+4DeiE0a1TwMeaeph1ytRJ5QtqxYRWg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9aa35efbea27d320d0cdc5f922f0890812affb60", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "advisory-db": "advisory-db", + "cctl": "cctl", + "cctl-2": "cctl-2", + "crane": "crane", + "csprpkgs": "csprpkgs_3", + "fenix": "fenix", + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs_4", + "treefmt-nix": "treefmt-nix" + } + }, + "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1723915239, + "narHash": "sha256-x/RXN/ougJ1IEoBKrY0UijB530OfOfICK4KPa3Kj9Bk=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "fa003262474185fd62168379500fe906b331824b", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "rust-overlay": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "cctl", + "csprpkgs", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1706753617, + "narHash": "sha256-ZKqTFzhFwSWFEpQTJ0uXnfJBs5Y/po9/8TK4bzssdbs=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "58be43ae223034217ea1bd58c73210644031b687", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "rust-overlay_2": { + "inputs": { + "flake-utils": "flake-utils_2", + "nixpkgs": [ + "cctl-2", + "csprpkgs", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1706753617, + "narHash": "sha256-ZKqTFzhFwSWFEpQTJ0uXnfJBs5Y/po9/8TK4bzssdbs=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "58be43ae223034217ea1bd58c73210644031b687", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "rust-overlay_3": { + "inputs": { + "nixpkgs": [ + "csprpkgs", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1722824458, + "narHash": "sha256-2k3/geD5Yh8JT1nrGaRycje5kB0DkvQA/OUZoel1bIU=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "a8a937c304e62a5098c6276c9cdf65c19a43b1a5", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1723808491, + "narHash": "sha256-rhis3qNuGmJmYC/okT7Dkc4M8CeUuRCSvW6kC2f3hBc=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "1d07739554fdc4f8481068f1b11d6ab4c1a4167a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..6fa208c --- /dev/null +++ b/flake.nix @@ -0,0 +1,145 @@ +{ + description = "cctl-rs"; + + nixConfig = { + extra-substituters = [ + "https://crane.cachix.org" + "https://nix-community.cachix.org" + "https://casper-cache.marijan.pro" + "https://cspr.cachix.org" + ]; + extra-trusted-public-keys = [ + "crane.cachix.org-1:8Scfpmn9w+hGdXH/Q9tTLiYAE/2dnJYRJP7kl80GuRk=" + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + "casper-cache.marijan.pro:XIDjpzFQTEuWbnRu47IqSOy6IqyZlunVGvukNROL850=" + "cspr.cachix.org-1:vEZlmbOsmTXkmEi4DSdqNVyq25VPNpmSm6qCs4IuTgE=" + ]; + }; + + inputs = { + flake-parts.url = "github:hercules-ci/flake-parts"; + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + treefmt-nix.url = "github:numtide/treefmt-nix"; + treefmt-nix.inputs.nixpkgs.follows = "nixpkgs"; + fenix.url = "github:nix-community/fenix"; + fenix.inputs.nixpkgs.follows = "nixpkgs"; + crane.url = "github:ipetkov/crane"; + crane.inputs.nixpkgs.follows = "nixpkgs"; + advisory-db.url = "github:rustsec/advisory-db"; + advisory-db.flake = false; + cctl.url = "github:casper-network/cctl/947c34b991e37476db82ccfa2bd7c0312c1a91d7"; + cctl-2.url = "github:casper-network/cctl"; + csprpkgs.url = "github:cspr-rad/csprpkgs"; + }; + + outputs = inputs@{ flake-parts, treefmt-nix, ... }: + flake-parts.lib.mkFlake { inherit inputs; } { + systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; + imports = [ + treefmt-nix.flakeModule + ./nixos + ]; + perSystem = { self', inputs', pkgs, lib, ... }: + let + rustToolchain = inputs'.fenix.packages.stable.toolchain; + craneLib = (inputs.crane.mkLib pkgs).overrideToolchain rustToolchain; + + cctl = inputs'.cctl.packages.cctl.override { casper-node = inputs'.csprpkgs.packages.casper-node; }; + + cctlAttrs = { + pname = "cctl-rs"; + + src = lib.fileset.toSource { + root = ./.; + fileset = lib.fileset.unions [ + ./Cargo.toml + ./Cargo.lock + ./bin + ./src + ./tests + ./test-resources + ]; + }; + + nativeBuildInputs = [ pkgs.pkg-config ]; + buildInputs = with pkgs; [ + openssl.dev + ] ++ lib.optionals stdenv.isDarwin [ + darwin.apple_sdk.frameworks.Security + ]; + + # the coverage report will run the tests + doCheck = false; + + checkInputs = [ + cctl + ]; + }; + in + { + devShells.default = pkgs.mkShell { + inputsFrom = [ self'.packages.cctld ]; + packages = [ cctl ]; + }; + + packages = { + cctl-rs-deps = craneLib.buildDepsOnly (cctlAttrs // { + pname = "cctl-rs-deps"; + }); + + cctl-rs-docs = craneLib.cargoDoc (cctlAttrs // { + pname = "cctl-rs-docs"; + cargoArtifacts = self'.packages.cctl-rs-deps; + }); + + cctld = craneLib.buildPackage (cctlAttrs // { + pname = "cctld"; + cargoArtifacts = self'.packages.cctl-rs-deps; + + nativeBuildInputs = cctlAttrs.nativeBuildInputs ++ [ + pkgs.makeWrapper + ]; + + postInstall = '' + wrapProgram $out/bin/cctld \ + --set PATH ${pkgs.lib.makeBinPath [ cctl ]} + ''; + + meta.mainProgram = "cctld"; + }); + + default = self'.packages.cctld; + }; + + checks = { + lint = craneLib.cargoClippy (cctlAttrs // { + cargoArtifacts = self'.packages.cctl-rs-deps; + cargoClippyExtraArgs = "--all-targets -- --deny warnings"; + }); + + coverage-report = craneLib.cargoTarpaulin (cctlAttrs // { + pname = "cctl-rs-coverage-report"; + cargoArtifacts = self'.packages.cctl-rs-deps; + # Default values from https://crane.dev/API.html?highlight=tarpau#cranelibcargotarpaulin + # --avoid-cfg-tarpaulin fixes nom/bitvec issue https://github.com/xd009642/tarpaulin/issues/756#issuecomment-838769320 + cargoTarpaulinExtraArgs = "--skip-clean --out xml --output-dir $out --avoid-cfg-tarpaulin"; + # cargoTarpaulin runs the tests in the buildPhase + buildInputs = cctlAttrs.buildInputs ++ [ + cctl + ]; + }); + }; + + treefmt = { + projectRootFile = ".git/config"; + programs.nixpkgs-fmt.enable = true; + programs.rustfmt.enable = true; + programs.rustfmt.package = craneLib.rustfmt; + settings.formatter = { }; + }; + }; + flake = { + herculesCI.ciSystems = [ "x86_64-linux" "aarch64-linux" ]; + }; + }; +} diff --git a/nixos/default.nix b/nixos/default.nix new file mode 100644 index 0000000..0b77a9f --- /dev/null +++ b/nixos/default.nix @@ -0,0 +1,26 @@ +{ self, inputs, ... }: +{ + flake = { + checks."x86_64-linux" = + let pkgs = inputs.nixpkgs.legacyPackages."x86_64-linux"; + in + { + verify-cctl-service = + pkgs.callPackage + ./tests/verify-cctl-service.nix + { + inherit (inputs.csprpkgs.packages.${pkgs.system}) casper-client-rs; + cctlModule = self.nixosModules.cctl; + contractWasm = ../test-resources/demo-contract-optimized.wasm; + }; + }; + nixosModules = { + cctl = + { pkgs, ... }: + { + imports = [ ./modules/cctl.nix ]; + services.cctl.package = self.packages.${pkgs.system}.cctld; + }; + }; + }; +} diff --git a/nixos/modules/cctl.nix b/nixos/modules/cctl.nix new file mode 100644 index 0000000..bef9ede --- /dev/null +++ b/nixos/modules/cctl.nix @@ -0,0 +1,158 @@ +{ lib, config, ... }: +let + inherit (lib) + types + mkOption + mkIf + mkMerge + mkEnableOption + escapeShellArgs + optionals + ; + cfg = config.services.cctl; +in +{ + options.services.cctl = { + + enable = mkEnableOption "cctl"; + + package = mkOption { + type = types.package; + }; + + port = mkOption { + type = types.port; + default = 11101; + example = 60000; + description = '' + Port to listen on. + TODO make port configurable in cctl + ''; + }; + + workingDirectory = mkOption { + type = types.path; + default = "/var/lib/cctl"; + description = '' + The working directory path where cctl will put its assets and resources. + ''; + }; + + chainspec = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + The path to a chainspec.toml. + ''; + }; + + config = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + The path to a casper node config.toml. + ''; + }; + + logLevel = mkOption { + type = types.str; + default = "info"; + description = '' + The log-level that should be used. + ''; + }; + + contract = mkOption { + type = types.nullOr (types.attrsOf types.path); + default = null; + example = { "contract hash name" = "/path/to/contract.wasm"; }; + description = '' + The wasm compiled contract that should be deployed once the network is up and ready. + The name of the attribute should correspond to the contracts hash name when calling + https://docs.rs/casper-contract/latest/casper_contract/contract_api/storage/fn.new_locked_contract.html + ''; + }; + + }; + + config = mkIf cfg.enable { + + systemd.services.cctl = + let + args = escapeShellArgs ([ + "--working-dir" + cfg.workingDirectory + ] + ++ optionals (!builtins.isNull cfg.contract) ([ + "--deploy-contract" + ] ++ (lib.mapAttrsToList (hash_name: contract_path: "${hash_name}:${contract_path}") cfg.contract)) + ++ optionals (!builtins.isNull cfg.chainspec) [ + "--chainspec-path" + cfg.chainspec + ] + ++ optionals (!builtins.isNull cfg.config) [ + "--config-path" + cfg.config + ]); + in + { + description = "cctl"; + documentation = [ "" ]; + wantedBy = [ "multi-user.target" ]; + after = [ "network-online.target" ]; + requires = [ "network-online.target" ]; + environment = { + RUST_LOG = cfg.logLevel; + }; + serviceConfig = + mkMerge [ + { + ExecStart = "${lib.getExe cfg.package} ${args}"; + Type = "notify"; + Restart = "no"; + User = "cctl"; + Group = "cctl"; + TimeoutStartSec = 1000; + StateDirectory = builtins.baseNameOf cfg.workingDirectory; + WorkingDirectory = cfg.workingDirectory; + ReadWritePaths = [ + cfg.workingDirectory + ]; + } + ]; + }; + + users.users.cctl = { + name = "cctl"; + group = "cctl"; + isSystemUser = true; + }; + users.groups.cctl = { }; + + # Allows nginx to have read access to the working directory of cctl + users.users.${config.services.nginx.user}.extraGroups = [ "cctl" ]; + + # Since cctl is usually ran on the same machine as the application that is subject to be tested, + # we need to serve the generated users directory to make it available for client machines + # when testing + services.nginx = { + enable = true; + virtualHosts."${config.networking.hostName}".locations = { + "/cctl/users/" = { + alias = "${cfg.workingDirectory}/assets/users/"; + extraConfig = '' + autoindex on; + add_header Content-Type 'text/plain charset=UTF-8'; + ''; + }; + "/cctl/contracts/" = { + alias = "${cfg.workingDirectory}/contracts/"; + extraConfig = '' + autoindex on; + add_header Content-Type 'text/plain charset=UTF-8'; + ''; + }; + }; + }; + }; +} diff --git a/nixos/tests/verify-cctl-service.nix b/nixos/tests/verify-cctl-service.nix new file mode 100644 index 0000000..07d3baa --- /dev/null +++ b/nixos/tests/verify-cctl-service.nix @@ -0,0 +1,46 @@ +{ nixosTest +, casper-client-rs +, cctlModule +, contractWasm +}: +nixosTest { + name = "verify-cctl-service"; + + nodes = { + server = { config, ... }: { + imports = [ + cctlModule + ]; + services.cctl = { + enable = true; + contract = { "kairos_contract_package_hash" = contractWasm; }; + }; + networking.firewall.allowedTCPPorts = [ 80 config.services.cctl.port ]; + }; + client = { pkgs, ... }: { + environment.systemPackages = [ pkgs.wget casper-client-rs ]; + }; + }; + + testScript = { nodes }: + let + casperNodeAddress = "http://server:${builtins.toString nodes.server.config.services.cctl.port}"; + # This is the directory wget will copy to, see script below + clientUsersDirectory = "server/cctl/users"; + in + '' + import json + + start_all() + server.wait_for_unit("cctl.service") + + # verify that the cctl network is running and reached the validate state + response = client.succeed("casper-client get-node-status --node-address ${casperNodeAddress}") + response_json = json.loads(response) + assert "result" in response_json and "Validate" in response_json["result"].get("reactor_state"), "The node didn't reach the VALIDATE state. The status response was {}".format(response) + + # verify that the generated cctl test accounts are being served + client.succeed("wget --no-parent -r http://server/cctl/users/") + client.succeed("cat ${clientUsersDirectory}/user-1/public_key_hex") + ''; +} diff --git a/src/cctl.rs b/src/cctl.rs new file mode 100644 index 0000000..b7d7616 --- /dev/null +++ b/src/cctl.rs @@ -0,0 +1,401 @@ +pub mod parsers; + +use anyhow::anyhow; +use backoff::{future::retry, ExponentialBackoff}; +use hex::FromHex; +use std::env; +use std::io::{self, Write}; +use std::path::PathBuf; +use std::process::Command; +use std::{ + fs, + time::{Duration, Instant}, +}; +use tempfile::tempdir; + +use casper_client::{ + get_account, get_deploy, get_node_status, get_state_root_hash, put_deploy, query_global_state, + rpcs::results::ReactorState, + types::{DeployBuilder, ExecutableDeployItem, StoredValue, TimeDiff, Timestamp}, + Error, JsonRpcId, Verbosity, +}; +use casper_types::{ContractHash, ExecutionResult, Key, PublicKey, RuntimeArgs, SecretKey}; + +#[derive(Debug, PartialEq, Clone, Copy)] +pub enum NodeState { + Running, + Stopped, +} + +#[derive(Debug, PartialEq, Clone, Copy)] +pub struct CasperNodePorts { + pub consensus_port: u16, + pub rpc_port: u16, + pub rest_port: u16, + pub sse_port: u16, + pub speculative_exec_port: u16, +} + +pub struct CasperNode { + pub id: u8, + pub validator_group_id: u8, + pub state: NodeState, + pub port: CasperNodePorts, +} + +pub struct CCTLNetwork { + pub working_dir: PathBuf, + pub nodes: Vec, +} + +pub struct DeployableContract { + /// This is the named key under which the contract hash is located + pub hash_name: String, + pub runtime_args: RuntimeArgs, + pub path: PathBuf, +} + +pub fn casper_client_verbosity() -> Verbosity { + if tracing::enabled!(tracing::Level::TRACE) { + Verbosity::High + } else if tracing::enabled!(tracing::Level::DEBUG) { + Verbosity::Medium + } else { + Verbosity::Low + } +} + +// max amount allowed to be used on gas fees +pub const MAX_GAS_FEE_PAYMENT_AMOUNT: u64 = 10_000_000_000_000; + +impl CCTLNetwork { + /// Spins up a CCTL network, and deploys a contract if provided + /// + /// If a chain spec and config path are not provided, the environment variables `CCTL_CHAINSPEC` and `CCTL_CONFIG` are used. + /// + /// WARNING: do not use this function in unit tests, only sequentially executed integration tests. + /// Ensure that two instances of this function are not running at the same time even in different processes. + pub async fn run( + working_dir: Option, + contract_to_deploy: Option, + chainspec_path: Option, + config_path: Option, + ) -> anyhow::Result { + let chainspec_path: Option = + chainspec_path.or_else(|| env::var("CCTL_CASPER_CHAINSPEC").ok().map(PathBuf::from)); + let config_path = + config_path.or_else(|| env::var("CCTL_CASPER_NODE_CONFIG").ok().map(PathBuf::from)); + + let working_dir = working_dir + .map(|dir| { + std::fs::create_dir_all(&dir) + .expect("Failed to create the provided working directory"); + dir + }) + .unwrap_or(tempdir()?.into_path()); + let assets_dir = working_dir.join("assets"); + tracing::info!("Working directory: {:?}", working_dir); + + let mut setup_command = Command::new("cctl-infra-net-setup"); + setup_command.env("CCTL_ASSETS", &assets_dir); + + if let Some(chainspec_path) = chainspec_path { + setup_command.arg(format!("chainspec={}", chainspec_path.to_str().unwrap())); + }; + + if let Some(config_path) = config_path { + setup_command.arg(format!("config={}", config_path.to_str().unwrap())); + }; + + tracing::info!("Setting up network configuration"); + let output = setup_command + .output() + .expect("Failed to setup network configuration"); + let output = std::str::from_utf8(output.stdout.as_slice()).unwrap(); + tracing::info!("{}", output); + + let output = Command::new("cctl-infra-net-start") + .env("CCTL_ASSETS", &assets_dir) + .output() + .expect("Failed to start network"); + let output = std::str::from_utf8(output.stdout.as_slice()).unwrap(); + tracing::info!("{}", output); + let (_, nodes) = parsers::parse_cctl_infra_net_start_lines(output).unwrap(); + + tracing::info!("Fetching the networks node ports"); + let output = Command::new("cctl-infra-node-view-ports") + .env("CCTL_ASSETS", &assets_dir) + .output() + .expect("Failed to get the networks node ports"); + let output = std::str::from_utf8(output.stdout.as_slice()).unwrap(); + tracing::info!("{}", output); + let (_, node_ports) = parsers::parse_cctl_infra_node_view_port_lines(output).unwrap(); + + // Match the started nodes with their respective ports + let nodes: Vec = nodes + .into_iter() + .map(|(validator_group_id, node_id, state)| { + if let Some(&(_, port)) = node_ports + .iter() + .find(|(node_id_ports, _)| *node_id_ports == node_id) + { + CasperNode { + validator_group_id, + state, + id: node_id, + port, + } + } else { + panic!("Can't find ports for node with id {}", node_id) + } + }) + .collect(); + + let node_port = nodes.first().unwrap().port.rpc_port; + let casper_node_rpc_url = format!("http://0.0.0.0:{node_port}/rpc"); + const MAX_GENESIS_WAIT_TIME: Duration = Duration::from_secs(90); + + let start_time = Instant::now(); + tracing::info!("Waiting {MAX_GENESIS_WAIT_TIME:?} for the network to pass genesis"); + retry(ExponentialBackoff::default(), || async { + // This prevents retrying forever even after ctrl-c + let timed_out = start_time.elapsed() > MAX_GENESIS_WAIT_TIME; + + get_node_status( + JsonRpcId::Number(1), + &casper_node_rpc_url, + casper_client_verbosity(), + ) + .await + .map_err(|err| { + let elapsed = start_time.elapsed().as_secs(); + tracing::info!( + "Waited for {elapsed}s to pass genesis, the last reported error was: {err:?}" + ); + err + }) + .map_err(|err| match &err { + err if timed_out => backoff::Error::permanent(anyhow!("Timeout on error: {err:?}")), + Error::ResponseIsHttpError { .. } | Error::FailedToGetResponse { .. } => { + backoff::Error::transient(anyhow!(err)) + } + _ => backoff::Error::permanent(anyhow!(err)), + }) + .map(|success| match success.result.reactor_state { + ReactorState::Validate => Ok(()), + reactor_state if timed_out => Err(backoff::Error::permanent(anyhow!( + "Node didn't reach the VALIDATE state before timeout: {reactor_state:?}" + ))), + _ => Err(backoff::Error::transient(anyhow!( + "Node didn't reach the VALIDATE state yet" + ))), + })? + }) + .await + .expect("Waiting for network to pass genesis failed"); + + tracing::info!("Waiting for block 1"); + let output = Command::new("cctl-chain-await-until-block-n") + .env("CCTL_ASSETS", &assets_dir) + .arg("height=1") + .output() + .expect("Waiting for network to start processing blocks failed"); + let output = std::str::from_utf8(output.stdout.as_slice()).unwrap(); + tracing::info!("{}", output); + + if let Some(contract_to_deploy) = contract_to_deploy { + let deployer_skey = + SecretKey::from_file(working_dir.join("assets/users/user-1/secret_key.pem"))?; + let deployer_pkey = + PublicKey::from_file(working_dir.join("assets/users/user-1/public_key.pem"))?; + + let (hash_name, contract_hash) = deploy_contract( + &casper_node_rpc_url, + &deployer_skey, + &deployer_pkey, + &contract_to_deploy, + ) + .await?; + let contracts_dir = working_dir.join("contracts"); + fs::create_dir_all(&contracts_dir)?; + fs::write( + contracts_dir.join(hash_name), + // For a ContractHash contract- will always be the prefix + contract_hash + .to_formatted_string() + .strip_prefix("contract-") + .unwrap(), + )? + } + Ok(CCTLNetwork { working_dir, nodes }) + } + /// Get the deployed contract hash for a hash_name that was passed to new_contract + /// https://docs.rs/casper-contract/latest/casper_contract/contract_api/storage/fn.new_contract.html + pub fn get_contract_hash_for(&self, hash_name: &str) -> ContractHash { + let contract_hash_path = self.working_dir.join("contracts").join(hash_name); + let contract_hash_string = fs::read_to_string(contract_hash_path).unwrap(); + let contract_hash_bytes = <[u8; 32]>::from_hex(contract_hash_string).unwrap(); + ContractHash::new(contract_hash_bytes) + } +} + +impl Drop for CCTLNetwork { + fn drop(&mut self) { + let output = Command::new("cctl-infra-net-stop") + .env("CCTL_ASSETS", self.working_dir.join("assets")) + .output() + .expect("Failed to stop the network"); + io::stdout().write_all(&output.stdout).unwrap(); + io::stderr().write_all(&output.stderr).unwrap(); + } +} + +/// Deploys a contract as the given user for the contract's defined hash name located at the path. +/// The hash name should be equal to the hash name passed to https://docs.rs/casper-contract/latest/casper_contract/contract_api/storage/fn.new_locked_contract.html +async fn deploy_contract( + casper_node_rpc_url: &str, + contract_deployer_skey: &SecretKey, + contract_deployer_pkey: &PublicKey, + DeployableContract { + hash_name, + runtime_args, + path, + }: &DeployableContract, +) -> anyhow::Result<(String, ContractHash)> { + tracing::info!( + "Deploying contract {}: {}", + &hash_name, + path.to_str().unwrap() + ); + + let casper_client_verbosity = casper_client_verbosity(); + + let contract_bytes = fs::read(path)?; + let contract = + ExecutableDeployItem::new_module_bytes(contract_bytes.into(), runtime_args.clone()); + let deploy = DeployBuilder::new( + // TODO ideally make the chain-name configurable + "cspr-dev-cctl", + contract, + contract_deployer_skey, + ) + .with_standard_payment(MAX_GAS_FEE_PAYMENT_AMOUNT) // max amount allowed to be used on gas fees + .with_timestamp(Timestamp::now()) + .with_ttl(TimeDiff::from_millis(60_000)) // 1 min + .build()?; + + tracing::info!("Submitting contract deploy"); + let deploy_hash = put_deploy( + JsonRpcId::Number(1), + casper_node_rpc_url, + casper_client_verbosity, + deploy, + ) + .await + .map_err(Into::::into) + .map(|response| response.result.deploy_hash)?; + + const MAX_CONTRACT_INIT_WAIT_TIME: Duration = Duration::from_secs(60); + tracing::info!( + "Waiting {MAX_CONTRACT_INIT_WAIT_TIME:?} for successful contract initialization" + ); + let start = Instant::now(); + retry(ExponentialBackoff::default(), || async { + let timed_out = start.elapsed() > MAX_CONTRACT_INIT_WAIT_TIME; + + let response = get_deploy( + JsonRpcId::Number(1), + casper_node_rpc_url, + casper_client_verbosity, + deploy_hash, + false, + ) + .await + .map_err(|err| { + let elapsed = start.elapsed().as_secs(); + tracing::info!("Waited {elapsed}s for successful contract initialization, the last reported error was: {err:?}"); + err + }) + .map_err(|err| match &err { + err if timed_out => backoff::Error::permanent(anyhow!("Timeout on error: {err:?}")), + Error::ResponseIsHttpError { .. } | Error::FailedToGetResponse { .. } => { + backoff::Error::transient(anyhow!(err)) + } + _ => backoff::Error::permanent(anyhow!(err)), + })?; + + match response.result.execution_results.first() { + Some(result) => match &result.result { + ExecutionResult::Failure { error_message, .. } => { + Err(backoff::Error::permanent(anyhow!(error_message.clone()))) + } + ExecutionResult::Success { .. } => Ok(()), + }, + None if timed_out => Err(backoff::Error::permanent(anyhow!( + "Timeout on error: No execution results" + ))), + None => Err(backoff::Error::transient(anyhow!( + "No execution results there yet" + ))), + } + }) + .await?; + tracing::info!("Contract was deployed successfully"); + + tracing::info!("Fetching deployed contract hash"); + // Query global state + let state_root_hash = get_state_root_hash( + JsonRpcId::Number(1), + casper_node_rpc_url, + casper_client_verbosity, + Option::None, + ) + .await + .map_err(Into::::into) + .and_then(|response| { + response + .result + .state_root_hash + .ok_or(anyhow!("No state root hash present in response")) + })?; + + let account = get_account( + JsonRpcId::Number(1), + casper_node_rpc_url, + casper_client_verbosity, + Option::None, + contract_deployer_pkey.clone(), + ) + .await + .map_err(Into::::into) + .map(|response| response.result.account)?; + + let account_key = Key::Account(*account.account_hash()); + let contract_hash: ContractHash = query_global_state( + JsonRpcId::Number(1), + casper_node_rpc_url, + casper_client_verbosity, + casper_client::rpcs::GlobalStateIdentifier::StateRootHash(state_root_hash), // fetches recent blocks state root hash + account_key, + vec![hash_name.clone()], + ) + .await + .map_err(Into::::into) + .and_then(|response| match response.result.stored_value { + StoredValue::ContractPackage(contract_package) => Ok(*contract_package + .versions() + .next() + .expect("Expected at least one contract version") + .contract_hash()), + other => Err(anyhow!( + "Unexpected result type, type is not a CLValue: {:?}", + other + )), + })?; + tracing::info!( + "Successfully fetched the contract hash for {}: {}", + &hash_name, + &contract_hash + ); + Ok::<(String, ContractHash), anyhow::Error>((hash_name.clone(), contract_hash)) +} diff --git a/src/cctl/parsers.rs b/src/cctl/parsers.rs new file mode 100644 index 0000000..b569931 --- /dev/null +++ b/src/cctl/parsers.rs @@ -0,0 +1,228 @@ +use super::{CasperNodePorts, NodeState}; + +use nom::{ + branch::alt, + bytes::complete::tag, + character::complete::{multispace0, not_line_ending, space1}, + combinator::map, + multi::separated_list0, + sequence::tuple, + IResult, +}; + +pub fn parse_node_state(input: &str) -> IResult<&str, NodeState> { + alt(( + map(tag("RUNNING"), |_| NodeState::Running), + map(tag("STOPPED"), |_| NodeState::Stopped), + ))(input) +} + +pub fn parse_cctl_infra_net_start_line(input: &str) -> IResult<&str, (u8, u8, NodeState)> { + let (remainder, (_, _, group_id, _, node_id, _, status, _)) = tuple(( + multispace0, + tag("validator-group-"), + nom::character::complete::u8, + tag(":cctl-node-"), + nom::character::complete::u8, + space1, + parse_node_state, + not_line_ending, + ))(input)?; + + Ok((remainder, (group_id, node_id, status))) +} + +pub fn parse_cctl_infra_net_start_lines(input: &str) -> IResult<&str, Vec<(u8, u8, NodeState)>> { + let (remainder, _) = nom::bytes::complete::take_until("validator-group")(input)?; + separated_list0(tag("\n"), parse_cctl_infra_net_start_line)(remainder) +} + +pub fn parse_cctl_infra_node_view_port_line(input: &str) -> IResult<&str, (u8, CasperNodePorts)> { + let ( + remainder, + ( + _, + _, + group_id, + _, + consensus_port, + _, + rpc_port, + _, + rest_port, + _, + sse_port, + _, + speculative_exec_port, + _, + ), + ) = tuple(( + nom::bytes::complete::take_until("node-"), + tag("node-"), + nom::character::complete::u8, + tag(" -> CONSENSUS @ "), + nom::character::complete::u16, + tag(" :: RPC @ "), + nom::character::complete::u16, + tag(" :: REST @ "), + nom::character::complete::u16, + tag(" :: SSE @ "), + nom::character::complete::u16, + tag(" :: SPECULATIVE_EXEC @ "), + nom::character::complete::u16, + not_line_ending, + ))(input)?; + + Ok(( + remainder, + ( + group_id, + CasperNodePorts { + consensus_port, + rpc_port, + rest_port, + sse_port, + speculative_exec_port, + }, + ), + )) +} + +pub fn parse_cctl_infra_node_view_port_lines( + input: &str, +) -> IResult<&str, Vec<(u8, CasperNodePorts)>> { + separated_list0(tag("\n"), parse_cctl_infra_node_view_port_line)(input) +} + +#[cfg(test)] +mod tests { + use super::*; + use anyhow::Error; + #[test] + fn test_parse_cctl_infra_net_start_line() -> Result<(), Error> { + let input = "validator-group-1:cctl-node-1 RUNNING pid 428229, uptime 0:09:06\n"; + let (_, parsed) = parse_cctl_infra_net_start_line(input)?; + Ok(assert_eq!((1, 1, NodeState::Running), parsed)) + } + #[test] + fn test_parse_cctl_infra_net_start_lines() -> Result<(), Error> { + let input = r#" + 2024-02-06T14:06:43.332420 [INFO] [431123] CCTL :: network spin up begins ... please wait + 2024-02-06T14:06:43.334599 [INFO] [431123] CCTL :: ... starting network + 2024-02-06T14:06:43.337054 [INFO] [431123] CCTL :: ... ... genesis bootstrap nodes + 2024-02-06T14:06:44.445527 [INFO] [431123] CCTL :: ... ... genesis non-bootstrap nodes + validator-group-1:cctl-node-1 RUNNING pid 428229, uptime 0:09:06 + validator-group-1:cctl-node-2 RUNNING pid 428230, uptime 0:09:06 + validator-group-1:cctl-node-3 RUNNING pid 428231, uptime 0:09:06 + validator-group-2:cctl-node-4 RUNNING pid 428296, uptime 0:09:05 + validator-group-2:cctl-node-5 RUNNING pid 428297, uptime 0:09:05 + validator-group-3:cctl-node-10 STOPPED Not started + validator-group-3:cctl-node-6 STOPPED Not started + validator-group-3:cctl-node-7 STOPPED Not started + validator-group-3:cctl-node-8 STOPPED Not started + validator-group-3:cctl-node-9 STOPPED Not started + "#; + let (_, parsed) = parse_cctl_infra_net_start_lines(input)?; + let expected = vec![ + (1, 1, NodeState::Running), + (1, 2, NodeState::Running), + (1, 3, NodeState::Running), + (2, 4, NodeState::Running), + (2, 5, NodeState::Running), + (3, 10, NodeState::Stopped), + (3, 6, NodeState::Stopped), + (3, 7, NodeState::Stopped), + (3, 8, NodeState::Stopped), + (3, 9, NodeState::Stopped), + ]; + Ok(assert_eq!(expected, parsed)) + } + #[test] + fn test_parse_cctl_infra_node_view_port_line() -> Result<(), Error> { + let input = "2024-02-06T17:28:10.731821 [INFO] [514427] CCTL :: node-1 -> CONSENSUS @ 22101 :: RPC @ 11101 :: REST @ 14101 :: SSE @ 18101 :: SPECULATIVE_EXEC @ 25101"; + let (_, parsed) = parse_cctl_infra_node_view_port_line(input)?; + Ok(assert_eq!( + ( + 1, + CasperNodePorts { + consensus_port: 22101, + rpc_port: 11101, + rest_port: 14101, + sse_port: 18101, + speculative_exec_port: 25101 + } + ), + parsed + )) + } + #[test] + fn test_parse_cctl_infra_node_view_port_lines() -> Result<(), Error> { + let input = r#" + 2024-02-06T17:28:10.728367 [INFO] [514427] CCTL :: ------------------------------------------------------------------------------------------------------ + 2024-02-06T17:28:10.731821 [INFO] [514427] CCTL :: node-1 -> CONSENSUS @ 22101 :: RPC @ 11101 :: REST @ 14101 :: SSE @ 18101 :: SPECULATIVE_EXEC @ 25101 + 2024-02-06T17:28:10.732997 [INFO] [514427] CCTL :: ------------------------------------------------------------------------------------------------------ + 2024-02-06T17:28:10.737211 [INFO] [514427] CCTL :: node-2 -> CONSENSUS @ 22102 :: RPC @ 11102 :: REST @ 14102 :: SSE @ 18102 :: SPECULATIVE_EXEC @ 25102 + 2024-02-06T17:28:10.738952 [INFO] [514427] CCTL :: ------------------------------------------------------------------------------------------------------ + 2024-02-06T17:28:10.742946 [INFO] [514427] CCTL :: node-3 -> CONSENSUS @ 22103 :: RPC @ 11103 :: REST @ 14103 :: SSE @ 18103 :: SPECULATIVE_EXEC @ 25103 + 2024-02-06T17:28:10.744218 [INFO] [514427] CCTL :: ------------------------------------------------------------------------------------------------------ + 2024-02-06T17:28:10.748632 [INFO] [514427] CCTL :: node-4 -> CONSENSUS @ 22104 :: RPC @ 11104 :: REST @ 14104 :: SSE @ 18104 :: SPECULATIVE_EXEC @ 25104 + 2024-02-06T17:28:10.749922 [INFO] [514427] CCTL :: ------------------------------------------------------------------------------------------------------ + 2024-02-06T17:28:10.754162 [INFO] [514427] CCTL :: node-5 -> CONSENSUS @ 22105 :: RPC @ 11105 :: REST @ 14105 :: SSE @ 18105 :: SPECULATIVE_EXEC @ 25105 + 2024-02-06T17:28:10.755567 [INFO] [514427] CCTL :: ------------------------------------------------------------------------------------------------------ + "#; + let (_, parsed) = parse_cctl_infra_node_view_port_lines(input)?; + let expected = vec![ + ( + 1, + CasperNodePorts { + consensus_port: 22101, + rpc_port: 11101, + rest_port: 14101, + sse_port: 18101, + speculative_exec_port: 25101, + }, + ), + ( + 2, + CasperNodePorts { + consensus_port: 22102, + rpc_port: 11102, + rest_port: 14102, + sse_port: 18102, + speculative_exec_port: 25102, + }, + ), + ( + 3, + CasperNodePorts { + consensus_port: 22103, + rpc_port: 11103, + rest_port: 14103, + sse_port: 18103, + speculative_exec_port: 25103, + }, + ), + ( + 4, + CasperNodePorts { + consensus_port: 22104, + rpc_port: 11104, + rest_port: 14104, + sse_port: 18104, + speculative_exec_port: 25104, + }, + ), + ( + 5, + CasperNodePorts { + consensus_port: 22105, + rpc_port: 11105, + rest_port: 14105, + sse_port: 18105, + speculative_exec_port: 25105, + }, + ), + ]; + Ok(assert_eq!(expected, parsed)) + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..48a35ad --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +pub mod cctl; diff --git a/test-resources/demo-contract-optimized.wasm b/test-resources/demo-contract-optimized.wasm new file mode 100644 index 0000000..2d382b6 Binary files /dev/null and b/test-resources/demo-contract-optimized.wasm differ diff --git a/tests/test_cctl_deploys_a_contract_successfully.rs b/tests/test_cctl_deploys_a_contract_successfully.rs new file mode 100644 index 0000000..b93c125 --- /dev/null +++ b/tests/test_cctl_deploys_a_contract_successfully.rs @@ -0,0 +1,40 @@ +use hex::FromHex; +use std::env; +use std::fs; +use std::path::PathBuf; +use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; + +use casper_types::{runtime_args, ContractHash, RuntimeArgs}; +use cctl::cctl::{CCTLNetwork, DeployableContract}; + +fn tracing_init() { + let _ = tracing_subscriber::registry() + .with(EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into())) + .with(tracing_subscriber::fmt::layer()) + .try_init(); +} + +#[tokio::test] +async fn test_cctl_deploys_a_contract_successfully() { + tracing_init(); + + let contract_wasm_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("test-resources/demo-contract-optimized.wasm"); + let hash_name = "kairos_contract_package_hash"; + let contract_to_deploy = DeployableContract { + hash_name: hash_name.to_string(), + runtime_args: runtime_args! { "initial_trie_root" => Option::<[u8; 32]>::None }, + path: contract_wasm_path, + }; + + let network = CCTLNetwork::run(None, Some(contract_to_deploy), None, None) + .await + .unwrap(); + let expected_contract_hash_path = network.working_dir.join("contracts").join(hash_name); + assert!(expected_contract_hash_path.exists()); + + let hash_string = fs::read_to_string(expected_contract_hash_path).unwrap(); + let contract_hash_bytes = <[u8; 32]>::from_hex(hash_string).unwrap(); + let contract_hash = ContractHash::new(contract_hash_bytes); + assert!(contract_hash.to_formatted_string().starts_with("contract-")) +} diff --git a/tests/test_cctl_network_starts_and_terminates.rs b/tests/test_cctl_network_starts_and_terminates.rs new file mode 100644 index 0000000..cb7fe7e --- /dev/null +++ b/tests/test_cctl_network_starts_and_terminates.rs @@ -0,0 +1,31 @@ +use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; + +use casper_client::{get_node_status, rpcs::results::ReactorState, JsonRpcId, Verbosity}; +use cctl::cctl::{CCTLNetwork, NodeState}; + +fn tracing_init() { + let _ = tracing_subscriber::registry() + .with(EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into())) + .with(tracing_subscriber::fmt::layer()) + .try_init(); +} + +#[tokio::test] +async fn test_cctl_network_starts_and_terminates() { + tracing_init(); + + let network = CCTLNetwork::run(None, None, None, None).await.unwrap(); + + for node in &network.nodes { + if node.state == NodeState::Running { + let node_status = get_node_status( + JsonRpcId::Number(1), + &format!("http://0.0.0.0:{}", node.port.rpc_port), + Verbosity::High, + ) + .await + .unwrap(); + assert_eq!(node_status.result.reactor_state, ReactorState::Validate); + } + } +}