diff --git a/Cargo.lock b/Cargo.lock index c2e85b76..f6f2569f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1132,6 +1132,25 @@ dependencies = [ "libc", ] +[[package]] +name = "cctl-rs" +version = "0.1.0" +source = "git+https://github.com/cspr-rad/cctl-rs#da4400558ead366af9c075b5c02d16f30ddadcea" +dependencies = [ + "anyhow", + "backoff", + "casper-client", + "casper-types 3.0.0", + "clap", + "hex", + "nom", + "sd-notify", + "tempfile", + "tokio", + "tracing", + "tracing-subscriber", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -2710,6 +2729,7 @@ dependencies = [ "casper-client", "casper-hashing 2.0.0", "casper-types 3.0.0", + "cctl-rs", "chrono", "clap", "dotenvy", @@ -2773,6 +2793,7 @@ dependencies = [ "casper-event-toolkit", "casper-types 3.0.0", "casper-types 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cctl-rs", "chrono", "contract-utils", "dotenvy", @@ -2799,20 +2820,11 @@ dependencies = [ name = "kairos-test-utils" version = "0.1.0" dependencies = [ - "anyhow", "backoff", - "casper-client", "casper-types 3.0.0", - "casper-types 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "clap", - "dotenvy", - "hex", "kairos-server", - "nom", "percent-encoding", - "rand 0.8.5", "reqwest 0.12.4", - "sd-notify", "tempfile", "tokio", "tracing", diff --git a/Cargo.toml b/Cargo.toml index af3e6d16..cb11d407 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ license = "MIT OR Apache-2.0" opt-level = 3 [workspace.dependencies] +cctl-rs = { git = "https://github.com/cspr-rad/cctl-rs" } casper-client = "2.0" casper-types = "4.0" casper-client-types = { package = "casper-types", version = "3.0" } diff --git a/flake.lock b/flake.lock index 9cd53c6f..7ca4b12a 100644 --- a/flake.lock +++ b/flake.lock @@ -16,16 +16,83 @@ "type": "github" } }, + "advisory-db_2": { + "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-rs", + "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": [ + "cctl-rs", + "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" + } + }, + "agenix_3": { + "inputs": { + "darwin": "darwin_3", + "home-manager": "home-manager_3", + "nixpkgs": [ + "csprpkgs", + "nixpkgs" + ], + "systems": "systems_5" + }, "locked": { "lastModified": 1722339003, "narHash": "sha256-ZeS51uJI30ehNkcZ4uKqT4ZDARPyqrHADSKAwv5vVCU=", @@ -69,7 +136,86 @@ "type": "github" } }, + "cctl-2": { + "inputs": { + "csprpkgs": "csprpkgs_2", + "nixpkgs": [ + "cctl-rs", + "cctl-2", + "csprpkgs", + "nixpkgs" + ], + "rust-overlay": [ + "cctl-rs", + "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" + } + }, + "cctl-rs": { + "inputs": { + "advisory-db": "advisory-db_2", + "cctl": [ + "cctl" + ], + "cctl-2": "cctl-2", + "crane": "crane", + "csprpkgs": "csprpkgs_3", + "fenix": "fenix", + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs_4", + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1724679624, + "narHash": "sha256-bh/iVO+LEl88DxZIWCFlQ3fu6uMUBN3Ou5+fwCgJiDk=", + "owner": "cspr-rad", + "repo": "cctl-rs", + "rev": "da4400558ead366af9c075b5c02d16f30ddadcea", + "type": "github" + }, + "original": { + "owner": "cspr-rad", + "repo": "cctl-rs", + "type": "github" + } + }, "crane": { + "inputs": { + "nixpkgs": [ + "cctl-rs", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1724006180, + "narHash": "sha256-PVxPj0Ga2fMYMtcT9ARCthF+4U71YkOT7ZjgD/vf1Aw=", + "owner": "ipetkov", + "repo": "crane", + "rev": "7ce92819802bc583b7e82ebc08013a530f22209f", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "crane_2": { "inputs": { "nixpkgs": [ "nixpkgs" @@ -114,6 +260,46 @@ "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" + } + }, + "csprpkgs_4": { + "inputs": { + "agenix": "agenix_3", + "nixpkgs": "nixpkgs_5", + "rust-overlay": "rust-overlay_4" + }, "locked": { "lastModified": 1722882341, "narHash": "sha256-WhbUtqJLRhE58YGMhclqBzvrIQ+6j4QIzLsiPKipgCw=", @@ -129,6 +315,55 @@ } }, "darwin": { + "inputs": { + "nixpkgs": [ + "cctl-rs", + "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": [ + "cctl-rs", + "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_3": { "inputs": { "nixpkgs": [ "csprpkgs", @@ -154,10 +389,32 @@ "fenix": { "inputs": { "nixpkgs": [ + "cctl-rs", "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" + } + }, + "fenix_2": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src_2" + }, "locked": { "lastModified": 1715754333, "narHash": "sha256-u3B+RvDD/kPxMS0Dkm+x+BlzfCqghT3kdev+1UYKvis=", @@ -176,6 +433,24 @@ "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-parts_2": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_2" + }, "locked": { "lastModified": 1709336216, "narHash": "sha256-Dt/wOWeW6Sqm11Yh+2+t0dfEWxoMxGBvv3JpIocFl9E=", @@ -208,7 +483,72 @@ "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-rs", + "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": [ + "cctl-rs", + "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_3": { "inputs": { "nixpkgs": [ "csprpkgs", @@ -247,6 +587,18 @@ } }, "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-lib_2": { "locked": { "dir": "lib", "lastModified": 1709237383, @@ -265,6 +617,22 @@ } }, "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=", @@ -280,7 +648,39 @@ "type": "github" } }, - "nixpkgs_3": { + "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" + } + }, + "nixpkgs_5": { + "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_6": { "locked": { "lastModified": 1721782431, "narHash": "sha256-UNDpwjYxNXQet/g3mgRLsQ9zxrbm9j2JEvP4ijF3AWs=", @@ -300,15 +700,33 @@ "inputs": { "advisory-db": "advisory-db", "cctl": "cctl", - "crane": "crane", - "csprpkgs": "csprpkgs_2", - "fenix": "fenix", - "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs_3", - "treefmt-nix": "treefmt-nix" + "cctl-rs": "cctl-rs", + "crane": "crane_2", + "csprpkgs": "csprpkgs_4", + "fenix": "fenix_2", + "flake-parts": "flake-parts_2", + "nixpkgs": "nixpkgs_6", + "treefmt-nix": "treefmt-nix_2" } }, "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-analyzer-src_2": { "flake": false, "locked": { "lastModified": 1715714902, @@ -349,6 +767,52 @@ } }, "rust-overlay_2": { + "inputs": { + "flake-utils": "flake-utils_2", + "nixpkgs": [ + "cctl-rs", + "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": [ + "cctl-rs", + "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" + } + }, + "rust-overlay_4": { "inputs": { "nixpkgs": [ "csprpkgs", @@ -399,7 +863,73 @@ "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" + } + }, + "systems_5": { + "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": [ + "cctl-rs", + "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" + } + }, + "treefmt-nix_2": { "inputs": { "nixpkgs": [ "nixpkgs" diff --git a/flake.nix b/flake.nix index 6b3ad874..81a60514 100644 --- a/flake.nix +++ b/flake.nix @@ -29,6 +29,8 @@ advisory-db.flake = false; cctl.url = "github:casper-network/cctl/947c34b991e37476db82ccfa2bd7c0312c1a91d7"; csprpkgs.url = "github:cspr-rad/csprpkgs"; + cctl-rs.url = "github:cspr-rad/cctl-rs"; + cctl-rs.inputs.cctl.follows = "cctl"; }; outputs = inputs@{ flake-parts, treefmt-nix, ... }: @@ -211,17 +213,6 @@ cargoExtraArgs = "-p kairos-crypto --no-default-features --features crypto-casper,tx"; }); - cctld = pkgs.runCommand "cctld-wrapped" - { - buildInputs = [ pkgs.makeWrapper ]; - meta.mainProgram = "cctld"; - } - '' - mkdir -p $out/bin - makeWrapper ${self'.packages.kairos}/bin/cctld $out/bin/cctld \ - --set PATH ${pkgs.lib.makeBinPath [ cctl ]} - ''; - default = self'.packages.kairos; kairos-docs = craneLib.cargoDoc (kairosNodeAttrs // { diff --git a/kairos-cli/Cargo.toml b/kairos-cli/Cargo.toml index db8d45de..4d224fcd 100644 --- a/kairos-cli/Cargo.toml +++ b/kairos-cli/Cargo.toml @@ -26,6 +26,7 @@ tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["std", "env-filter"] } casper-client.workspace = true casper-client-types = { workspace = true, features = ["std"] } # TODO: Change `std` -> `std-fs-io` in the future version. +cctl-rs.workspace = true clap = { version = "4", features = ["derive", "deprecated"] } chrono = { version = "0.4", optional = true } hex = "0.4" diff --git a/kairos-cli/src/commands/run_cctl.rs b/kairos-cli/src/commands/run_cctl.rs index b15a9c2b..d00bb42d 100644 --- a/kairos-cli/src/commands/run_cctl.rs +++ b/kairos-cli/src/commands/run_cctl.rs @@ -1,7 +1,7 @@ use std::path::PathBuf; use casper_client_types::{runtime_args, RuntimeArgs}; -use kairos_test_utils::cctl::{CCTLNetwork, DeployableContract}; +use cctl::{CCTLNetwork, DeployableContract}; use crate::error::CliError; @@ -19,7 +19,7 @@ pub fn run() -> Result { let chainspec_path = PathBuf::from(std::env::var("CCTL_CHAINSPEC").unwrap()); let config_path = PathBuf::from(std::env::var("CCTL_CONFIG").unwrap()); - let network = CCTLNetwork::run(None, Some(contract_to_deploy), Some(chainspec_path.as_path()), Some(config_path.as_path())) + let network = CCTLNetwork::run(None, Some(contract_to_deploy), Some(chainspec_path), Some(config_path)) .await .unwrap(); diff --git a/kairos-cli/tests/cli_tests.rs b/kairos-cli/tests/cli_tests.rs index 7b1408bc..66ccbbde 100644 --- a/kairos-cli/tests/cli_tests.rs +++ b/kairos-cli/tests/cli_tests.rs @@ -5,12 +5,10 @@ use std::path::PathBuf; use casper_client::types::DeployHash; use casper_client_hashing::Digest; +use cctl::{CCTLNetwork, DeployableContract}; +use kairos_test_utils::kairos::Kairos; #[cfg(feature = "database")] use kairos_test_utils::postgres::PostgresDB; -use kairos_test_utils::{ - cctl::{CCTLNetwork, DeployableContract}, - kairos::Kairos, -}; // Helper function to get the path to a fixture file fn fixture_path(relative_path: &str) -> PathBuf { diff --git a/kairos-server/Cargo.toml b/kairos-server/Cargo.toml index 474f8ac8..916f5ca3 100644 --- a/kairos-server/Cargo.toml +++ b/kairos-server/Cargo.toml @@ -56,3 +56,4 @@ proptest = "1" axum-test = "14" kairos-test-utils = { path = "../kairos-test-utils" } casper-client-types.workspace = true +cctl-rs.workspace = true diff --git a/kairos-server/tests/transactions.rs b/kairos-server/tests/transactions.rs index 7811ccfe..96b3ce51 100644 --- a/kairos-server/tests/transactions.rs +++ b/kairos-server/tests/transactions.rs @@ -15,6 +15,7 @@ use casper_client_types::{ crypto::{PublicKey, SecretKey}, AsymmetricType, ContractHash, }; +use cctl::CCTLNetwork; #[cfg(feature = "database")] use kairos_data::new as new_pool; use kairos_server::{ @@ -22,7 +23,6 @@ use kairos_server::{ routes::deposit::DepositPath, state::{BatchStateManager, ServerStateInner}, }; -use kairos_test_utils::cctl::CCTLNetwork; #[cfg(feature = "database")] use kairos_test_utils::postgres::PostgresDB; diff --git a/kairos-test-utils/Cargo.toml b/kairos-test-utils/Cargo.toml index 4df8218e..8c5a4516 100644 --- a/kairos-test-utils/Cargo.toml +++ b/kairos-test-utils/Cargo.toml @@ -4,40 +4,21 @@ version.workspace = true edition.workspace = true license.workspace = true -[[bin]] -name = "cctld" -path = "bin/cctld.rs" -version.workspace = true -test = false -bench = false - [features] -# FIXME enable cctl-tests once this crate is factored out in a separate repository -#all-tests = ["cctl-tests"] default = ["database"] all-tests = ["database"] -cctl-tests = [] database = ["kairos-server/database"] [lib] [dependencies] -anyhow = "1" backoff = { version = "0.4", features = ["tokio", "futures"]} -clap = { version = "4", features = ["derive"] } -casper-client.workspace = true -casper-types.workspace = true casper-client-types.workspace = true -nom = "7" -hex = "0.4" percent-encoding = "2.3" -rand = "0.8" -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"] } reqwest = { version = "0.12", features = ["json"] } kairos-server = { path = "../kairos-server" } -dotenvy = "0.15" diff --git a/kairos-test-utils/bin/cctld.rs b/kairos-test-utils/bin/cctld.rs deleted file mode 100644 index 04362149..00000000 --- a/kairos-test-utils/bin/cctld.rs +++ /dev/null @@ -1,48 +0,0 @@ -use casper_client_types::{runtime_args, RuntimeArgs}; -use clap::Parser; -use kairos_test_utils::cctl; -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.as_deref(), - cli.config_path.as_deref(), - ) - .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/kairos-test-utils/src/cctl.rs b/kairos-test-utils/src/cctl.rs deleted file mode 100644 index 0814033f..00000000 --- a/kairos-test-utils/src/cctl.rs +++ /dev/null @@ -1,391 +0,0 @@ -pub mod parsers; -use anyhow::anyhow; -use backoff::{future::retry, ExponentialBackoff}; -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_client_types::{ContractHash, ExecutionResult, Key, PublicKey, RuntimeArgs, SecretKey}; -use hex::FromHex; -use std::io::{self, Write}; -use std::path::Path; -use std::path::PathBuf; -use std::process::Command; -use std::{fs, time::Instant}; -use tempfile::tempdir; - -#[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<&Path>, - config_path: Option<&Path>, - ) -> anyhow::Result { - let chainspec_path: String = chainspec_path - .map(|p| p.to_str().unwrap().to_owned()) - .unwrap_or_else(|| std::env::var("CCTL_CHAINSPEC").unwrap()); - let config_path: String = config_path - .map(|p| p.to_str().unwrap().to_owned()) - .unwrap_or_else(|| std::env::var("CCTL_CONFIG").unwrap()); - - 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); - - setup_command.arg(format!("chainspec={}", chainspec_path)); - - setup_command.arg(format!("config={}", config_path)); - - 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(); - - 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://localhost:{}/rpc", node_port); - - let start_time = Instant::now(); - tracing::info!("Waiting for network to pass genesis"); - retry(ExponentialBackoff::default(), || async { - // This prevents retrying forever even after ctrl-c - let timed_out = start_time.elapsed().as_secs() > 90; - - 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!("Running for {elapsed}s, Error: {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(()), - // _ if timed_out => Ok(()), - rs if timed_out => Err(backoff::Error::permanent(anyhow!( - "Node didn't reach the VALIDATE state before timeout: {rs:?}" - ))), - _ => 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, casper_client_types::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 this 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)?; - - tracing::info!("Waiting for successful contract initialization"); - let start = Instant::now(); - retry(ExponentialBackoff::default(), || async { - let timed_out = start.elapsed().as_secs() > 60; - - 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!("Running for {elapsed}s, Error: {err:?}"); - err - }) - .map_err(|err| match &err { - e if timed_out => backoff::Error::permanent(anyhow!("Timeout on error: {e:?}")), - 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: casper_client_types::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, casper_client_types::ContractHash), anyhow::Error>(( - hash_name.clone(), - contract_hash, - )) -} diff --git a/kairos-test-utils/src/cctl/parsers.rs b/kairos-test-utils/src/cctl/parsers.rs deleted file mode 100644 index b5699318..00000000 --- a/kairos-test-utils/src/cctl/parsers.rs +++ /dev/null @@ -1,228 +0,0 @@ -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/kairos-test-utils/src/lib.rs b/kairos-test-utils/src/lib.rs index 424bb913..0eefee5a 100644 --- a/kairos-test-utils/src/lib.rs +++ b/kairos-test-utils/src/lib.rs @@ -1,3 +1,2 @@ -pub mod cctl; pub mod kairos; pub mod postgres; diff --git a/kairos-test-utils/tests/test_cctl_deploys_a_contract_successfully.rs b/kairos-test-utils/tests/test_cctl_deploys_a_contract_successfully.rs deleted file mode 100644 index 648756fd..00000000 --- a/kairos-test-utils/tests/test_cctl_deploys_a_contract_successfully.rs +++ /dev/null @@ -1,50 +0,0 @@ -use casper_types::ContractHash; -use hex::FromHex; -use kairos_test_utils::cctl::CCTLNetwork; -use std::fs; -use std::path::PathBuf; - -use casper_client_types::{runtime_args, RuntimeArgs}; -use kairos_test_utils::cctl::DeployableContract; -use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; - -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(); -} - -#[cfg_attr(not(feature = "cctl-tests"), ignore)] -#[tokio::test] -async fn test_cctl_deploys_a_contract_successfully() { - tracing_init(); - - let contract_wasm_path = - PathBuf::from(env!("PATH_TO_WASM_BINARIES")).join("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 chainspec = PathBuf::from(std::env::var("CCTL_CHAINSPEC").unwrap()); - let config = PathBuf::from(std::env::var("CCTL_CONFIG").unwrap()); - - let network = CCTLNetwork::run( - None, - Some(contract_to_deploy), - Some(chainspec.as_path()), - Some(config.as_path()), - ) - .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/kairos-test-utils/tests/test_cctl_network_starts_and_terminates.rs b/kairos-test-utils/tests/test_cctl_network_starts_and_terminates.rs deleted file mode 100644 index 64044748..00000000 --- a/kairos-test-utils/tests/test_cctl_network_starts_and_terminates.rs +++ /dev/null @@ -1,43 +0,0 @@ -use std::path::PathBuf; - -use casper_client::{get_node_status, rpcs::results::ReactorState, JsonRpcId, Verbosity}; -use kairos_test_utils::cctl::{CCTLNetwork, NodeState}; -use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; - -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(); -} - -#[cfg_attr(not(feature = "cctl-tests"), ignore)] -#[tokio::test] -async fn test_cctl_network_starts_and_terminates() { - tracing_init(); - - let chainspec = PathBuf::from(std::env::var("CCTL_CHAINSPEC").unwrap()); - let config = PathBuf::from(std::env::var("CCTL_CONFIG").unwrap()); - - let network = CCTLNetwork::run( - None, - None, - Some(chainspec.as_path()), - Some(config.as_path()), - ) - .await - .unwrap(); - - for node in &network.nodes { - if node.state == NodeState::Running { - let node_status = get_node_status( - JsonRpcId::Number(1), - &format!("http://localhost:{}", node.port.rpc_port), - Verbosity::High, - ) - .await - .unwrap(); - assert_eq!(node_status.result.reactor_state, ReactorState::Validate); - } - } -} diff --git a/nixos/default.nix b/nixos/default.nix index 0a153cfc..f7c826af 100644 --- a/nixos/default.nix +++ b/nixos/default.nix @@ -49,7 +49,7 @@ in { inherit mkKairosHostConfig; inherit (self.packages.${pkgs.system}) kairos kairos-contracts casper-client-rs casper-node-config casper-chainspec; - cctlModule = self.nixosModules.cctl; + cctlModule = inputs.cctl-rs.nixosModules.cctl; }; }; nixosModules = { @@ -65,12 +65,6 @@ in imports = [ ./modules/kairos-prover.nix ]; services.kairos-prover.package = self.packages.${pkgs.system}.kairos-prover; }; - cctl = - { pkgs, lib, ... }: - { - imports = [ ./modules/cctl.nix ]; - services.cctl.package = self.packages.${pkgs.system}.cctld; - }; }; }; } diff --git a/nixos/modules/cctl.nix b/nixos/modules/cctl.nix deleted file mode 100644 index bef9edec..00000000 --- a/nixos/modules/cctl.nix +++ /dev/null @@ -1,158 +0,0 @@ -{ 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'; - ''; - }; - }; - }; - }; -}