diff --git a/.github/workflows/build-push-containers-all.yml b/.github/workflows/build-push-containers-all.yml index 492d22ff0..b29e0e20e 100644 --- a/.github/workflows/build-push-containers-all.yml +++ b/.github/workflows/build-push-containers-all.yml @@ -76,7 +76,11 @@ jobs: - name: Read the commit SHA id: vars - run: echo "CONTAINER_REV=${{ github.ref }}" >> .env + run: | + commit_hash=$(git rev-parse HEAD | cut -c1-7) + echo CONTAINER_REV=${commit_hash} + echo "CONTAINER_REV=${commit_hash}" >> .env + - name: Display .env file run: cat .env diff --git a/.github/workflows/checks-all.yml b/.github/workflows/checks-all.yml index 87fc54a6d..202f0cb35 100755 --- a/.github/workflows/checks-all.yml +++ b/.github/workflows/checks-all.yml @@ -65,7 +65,7 @@ jobs: -p move-rocks \ -p movement-types \ -p movement-config \ - -p movement-celestia-da-util \ + -p movement-da-util \ -p movement-signer-test movement-full-node-local: diff --git a/Cargo.lock b/Cargo.lock index 428757a59..e7318276a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -561,6 +561,23 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "alloy-signer-aws" +version = "0.1.4" +source = "git+https://github.com/alloy-rs/alloy.git?rev=83343b172585fe4e040fb104b4d1421f58cbf9a2#83343b172585fe4e040fb104b4d1421f58cbf9a2" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives 0.7.7", + "alloy-signer", + "async-trait", + "aws-sdk-kms", + "k256", + "spki 0.7.3", + "thiserror 1.0.69", + "tracing", +] + [[package]] name = "alloy-signer-local" version = "0.1.4" @@ -4275,7 +4292,7 @@ dependencies = [ "log", "parking", "polling", - "rustix 0.37.27", + "rustix 0.37.28", "slab", "socket2 0.4.10", "waker-fn", @@ -5451,7 +5468,6 @@ version = "0.0.2" dependencies = [ "anyhow", "bigdecimal", - "bridge-config", "bridge-util", "chrono", "diesel", @@ -7180,9 +7196,9 @@ checksum = "339544cc9e2c4dc3fc7149fd630c5f22263a4fdf18a98afd0075784968b5cf00" [[package]] name = "diesel" -version = "2.2.4" +version = "2.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "158fe8e2e68695bd615d7e4f3227c0727b151330d3e253b525086c348d055d5e" +checksum = "04001f23ba8843dc315804fa324000376084dfb1c30794ff68dd279e6e5696d5" dependencies = [ "bigdecimal", "bitflags 2.6.0", @@ -7505,6 +7521,7 @@ checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek 4.1.3", "ed25519 2.2.3", + "rand_core 0.6.4", "serde", "sha2 0.10.8", "signature 2.2.0", @@ -9596,9 +9613,9 @@ dependencies = [ [[package]] name = "interprocess" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f4e4a06d42fab3e85ab1b419ad32b09eab58b901d40c57935ff92db3287a13" +checksum = "894148491d817cb36b6f778017b8ac46b17408d522dd90f539d677ea938362eb" dependencies = [ "doctest-file", "futures-core", @@ -12230,6 +12247,7 @@ dependencies = [ "dotenv", "movement-signer", "tokio", + "tracing", "uuid", "vaultrs", ] @@ -12267,6 +12285,37 @@ dependencies = [ "tokio", ] +[[package]] +name = "movement-signer-test" +version = "0.0.2" +dependencies = [ + "alloy", + "alloy-consensus", + "alloy-network", + "alloy-primitives 0.7.7", + "alloy-signer", + "alloy-signer-aws", + "alloy-transport-http", + "anyhow", + "aptos-crypto", + "aptos-types", + "async-trait", + "chrono", + "ed25519-dalek 2.1.1", + "maptos-dof-execution", + "maptos-execution-util", + "movement-signer", + "movement-signer-aws-kms", + "movement-signer-loader", + "movement-signer-local", + "movement-signing-aptos", + "movement-signing-eth", + "rand 0.8.5", + "sha3 0.10.8", + "tempfile", + "tokio", +] + [[package]] name = "movement-signing-aptos" version = "0.0.2" @@ -15221,9 +15270,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.27" +version = "0.37.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6" dependencies = [ "bitflags 1.3.2", "errno", diff --git a/Cargo.toml b/Cargo.toml index c9cfdf7c3..0d0b79119 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ members = [ "util/signing/integrations/aptos", "util/signing/providers/aws-kms", "util/signing/providers/hashicorp-vault", + "util/signing/testing", "demo/hsm", "protocol-units/execution/maptos/framework/releases/*", "protocol-units/execution/maptos/framework/migrations/*", @@ -361,9 +362,9 @@ http-body-util = "0.1" tap = "1.0.1" # trying to pin diesel -diesel = { version = "2.2.4", features = ["postgres", "numeric", "r2d2"] } +diesel = { version = "2.2.7", features = ["postgres", "numeric", "r2d2"] } diesel_migrations = { version = "2.2.0" } -bigdecimal = "0.4.0" +bigdecimal = "0.3" num_cpus = "=1.16.0" ahash = "=0.8.11" diff --git a/docker/build/movement-full-node/Dockerfile b/docker/build/movement-full-node/Dockerfile index 59c794160..1455225e4 100644 --- a/docker/build/movement-full-node/Dockerfile +++ b/docker/build/movement-full-node/Dockerfile @@ -17,6 +17,9 @@ RUN rust_binary="./target/release/movement-full-node"; dest_dir="/tmp/runtime"; FROM alpine:latest +# Install dependencies: git +RUN apk add --no-cache git + # Copy the build artifact from the builder stage COPY --from=builder /tmp/build/target/release/movement-full-node /app/movement-full-node COPY --from=builder /tmp/runtime/nix/store /nix/store diff --git a/docker/compose/movement-full-node/docker-compose.follower.yml b/docker/compose/movement-full-node/docker-compose.follower.yml index 9f71c34d8..93467ebdd 100644 --- a/docker/compose/movement-full-node/docker-compose.follower.yml +++ b/docker/compose/movement-full-node/docker-compose.follower.yml @@ -12,7 +12,7 @@ services: AWS_REGION: ${AWS_REGION:?AWS_REGION is not set} AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID} AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY} - MOVEMENT_SYNC: ${MOVEMENT_SYNC:?MOVEMENT_SYNC is not set} + MOVEMENT_SYNC: ${MOVEMENT_SYNC} MAYBE_RUN_LOCAL: "false" RUST_LOG: info,aws_sdk_s3=debug volumes: diff --git a/docker/compose/movement-full-node/docker-compose.leader.yml b/docker/compose/movement-full-node/docker-compose.leader.yml index 4ec20eaa8..36d68e6d5 100644 --- a/docker/compose/movement-full-node/docker-compose.leader.yml +++ b/docker/compose/movement-full-node/docker-compose.leader.yml @@ -1,7 +1,7 @@ services: setup: environment: - MOVEMENT_SYNC: ${MOVEMENT_SYNC:?MOVEMENT_SYNC is not set} + MOVEMENT_SYNC: ${MOVEMENT_SYNC} AWS_REGION: ${AWS_REGION:?AWS_REGION is not set} AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID} AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY} diff --git a/process-compose/movement-full-node/process-compose.test-bring-up-elsa-to-biarritz-rc1.yml b/process-compose/movement-full-node/process-compose.test-bring-up-elsa-to-biarritz-rc1.yml new file mode 100644 index 000000000..0dc01da20 --- /dev/null +++ b/process-compose/movement-full-node/process-compose.test-bring-up-elsa-to-biarritz-rc1.yml @@ -0,0 +1,16 @@ +version: "3" + +processes: + + setup: + environment: + - "KNOWN_FRAMEWORK_RELEASE=elsa" + + test-migrate-elsa-to-biarritz-rc1: + command: | + cargo run --bin movement-full-node admin bring-up elsa-to-biarritz-rc1 upgrade 0x1 0x2 0x3 + depends_on: + movement-full-node: + condition: process_healthy + movement-faucet: + condition: process_healthy diff --git a/process-compose/movement-full-node/process-compose.test-migrate-elsa-to-biarritz-rc1.yml b/process-compose/movement-full-node/process-compose.test-migrate-elsa-to-biarritz-rc1.yml index 5314e50fa..bb94e900a 100644 --- a/process-compose/movement-full-node/process-compose.test-migrate-elsa-to-biarritz-rc1.yml +++ b/process-compose/movement-full-node/process-compose.test-migrate-elsa-to-biarritz-rc1.yml @@ -4,7 +4,7 @@ processes: setup: environment: - - "KNOWN_FRAMEWORK_RELEASE=biarritz-rc1" + - "KNOWN_FRAMEWORK_RELEASE=elsa" test-migrate-elsa-to-biarritz-rc1: command: | diff --git a/protocol-units/bridge/indexer-db/Cargo.toml b/protocol-units/bridge/indexer-db/Cargo.toml index 64b431228..4fa6fad03 100644 --- a/protocol-units/bridge/indexer-db/Cargo.toml +++ b/protocol-units/bridge/indexer-db/Cargo.toml @@ -10,12 +10,14 @@ publish = { workspace = true } rust-version = { workspace = true } [dependencies] -diesel = { workspace = true, features = ["postgres", "numeric", "r2d2", "chrono"] } -diesel_migrations = { workspace = true } -bigdecimal = { workspace = true } +# Use specific version different from Aptos core one. +# Could use workplace version when Aptos core will have upgrade for a more recent version. +diesel = { version = "2.2.4", features = ["postgres", "numeric", "r2d2", "chrono"] } +diesel_migrations = { version = "2.2.0" } +bigdecimal = "0.4.0" + serde = { workspace = true } bridge-util = { workspace = true } -bridge-config = { workspace = true } anyhow = { workspace = true } hex = { workspace = true } chrono = { workspace = true } diff --git a/protocol-units/bridge/indexer-db/src/client.rs b/protocol-units/bridge/indexer-db/src/client.rs index 59e0ab8de..bb97d1c65 100644 --- a/protocol-units/bridge/indexer-db/src/client.rs +++ b/protocol-units/bridge/indexer-db/src/client.rs @@ -1,7 +1,6 @@ use crate::migrations::run_migrations; use crate::models::*; use crate::schema::*; -use bridge_config::Config; use bridge_util::chains::bridge_contracts::BridgeContractEvent; use bridge_util::types::BridgeTransferId; use bridge_util::TransferActionType; @@ -23,8 +22,8 @@ impl Client { Self { conn } } - pub fn from_bridge_config(config: &Config) -> Result { - let conn = PgConnection::establish(&config.indexer.indexer_url) + pub fn build_from_db_url(db_url: &str) -> Result { + let conn = PgConnection::establish(&db_url) .map_err(|e| anyhow::anyhow!("Failed to connect to postgresql instance: {}", e))?; Ok(Self::new(conn)) } diff --git a/protocol-units/bridge/indexer-db/src/lib.rs b/protocol-units/bridge/indexer-db/src/lib.rs index 6ef47f00f..b22c72c04 100644 --- a/protocol-units/bridge/indexer-db/src/lib.rs +++ b/protocol-units/bridge/indexer-db/src/lib.rs @@ -1,5 +1,4 @@ use crate::client::Client; -use bridge_config::Config; use bridge_util::chains::bridge_contracts::BridgeContractMonitoring; use bridge_util::types::BridgeTransferId; use bridge_util::TransferActionType; @@ -16,7 +15,7 @@ pub async fn run_indexer_client< SOURCE: Send + TryFrom> + std::clone::Clone + 'static + std::fmt::Debug, TARGET: Send + TryFrom> + std::clone::Clone + 'static + std::fmt::Debug, >( - config: Config, + db_url: String, mut stream_source: impl BridgeContractMonitoring
, mut stream_target: impl BridgeContractMonitoring
, _relayer_actions: Option>, @@ -25,7 +24,7 @@ where Vec: From, Vec: From, { - let mut indexer_db_client = match Client::from_bridge_config(&config) { + let mut indexer_db_client = match Client::build_from_db_url(&db_url) { Ok(mut client) => { client.run_migrations()?; client diff --git a/protocol-units/bridge/service/bin/start_indexer.rs b/protocol-units/bridge/service/bin/start_indexer.rs index 962664fd2..637b40d97 100644 --- a/protocol-units/bridge/service/bin/start_indexer.rs +++ b/protocol-units/bridge/service/bin/start_indexer.rs @@ -62,7 +62,12 @@ async fn main() -> Result<()> { tracing::info!("Bridge Eth and Movement Inited. Starting bridge loop."); // Start indexer - let indexer_jh = tokio::spawn(run_indexer_client(bridge_config, eth_stream, mvt_stream, None)); + let indexer_jh = tokio::spawn(run_indexer_client( + bridge_config.indexer.indexer_url, + eth_stream, + mvt_stream, + None, + )); tokio::select! { res = eth_healh_check_jh => { diff --git a/protocol-units/execution/maptos/framework/releases/feature-flags/src/lib.rs b/protocol-units/execution/maptos/framework/releases/feature-flags/src/lib.rs index d5a5a97f2..814793023 100644 --- a/protocol-units/execution/maptos/framework/releases/feature-flags/src/lib.rs +++ b/protocol-units/execution/maptos/framework/releases/feature-flags/src/lib.rs @@ -8,7 +8,6 @@ use maptos_framework_release_util::{ compiler::Compiler, Release, ReleaseBundleError, ReleaseSigner, }; use std::fs; -use std::path::PathBuf; use tempfile::tempdir; use tracing::info; @@ -19,10 +18,6 @@ where R: Release + Debug, { pub wrapped_release: R, - pub repo: &'static str, - pub commit_hash: &'static str, - pub bytecode_version: u32, - pub framework_local_dir: Option, pub features: Features, } @@ -30,15 +25,8 @@ impl SetFeatureFlags where R: Release + Debug, { - pub fn new( - wrapped_release: R, - repo: &'static str, - commit_hash: &'static str, - bytecode_version: u32, - framework_local_dir: Option, - features: Features, - ) -> Self { - Self { wrapped_release, repo, commit_hash, bytecode_version, framework_local_dir, features } + pub fn new(wrapped_release: R, features: Features) -> Self { + Self { wrapped_release, features } } /// Generates the bytecode for the feature flag proposal. @@ -64,13 +52,7 @@ where println!("file: {:?}", file.path()); } - let compiler = Compiler::new( - self.repo, - self.commit_hash, - self.bytecode_version, - self.framework_local_dir.clone(), - ); - + let compiler = Compiler::movement(); let bytecode = compiler .compile_in_temp_dir_to_bytecode("feature_flags", &feature_flags_script_path) .map_err(|e| ReleaseBundleError::Build(e.into()))?; @@ -218,14 +200,7 @@ macro_rules! generate_feature_upgrade_module { let features = $features_stanza; Self { - with_features: SetFeatureFlags::new( - super::$struct_name::new(), - "null", - "null", - 6, - Some(aptos_framework_path()), // just use the path to the framework for the feature flag - features, - ), + with_features: SetFeatureFlags::new(super::$struct_name::new(), features), } } } diff --git a/protocol-units/execution/maptos/framework/releases/release-script/src/lib.rs b/protocol-units/execution/maptos/framework/releases/release-script/src/lib.rs index c280a7685..a0d302990 100644 --- a/protocol-units/execution/maptos/framework/releases/release-script/src/lib.rs +++ b/protocol-units/execution/maptos/framework/releases/release-script/src/lib.rs @@ -5,7 +5,6 @@ use maptos_framework_release_util::{ compiler::Compiler, Release, ReleaseBundleError, ReleaseSigner, }; use std::fs; -use std::path::PathBuf; use tempfile::tempdir; use tracing::info; @@ -16,10 +15,6 @@ where R: Release + Debug, { pub wrapped_release: R, - pub repo: &'static str, - pub commit_hash: &'static str, - pub bytecode_version: u32, - pub framework_local_dir: Option, pub script: String, } @@ -27,15 +22,8 @@ impl RunScript where R: Release + Debug, { - pub fn new( - wrapped_release: R, - repo: &'static str, - commit_hash: &'static str, - bytecode_version: u32, - framework_local_dir: Option, - script: String, - ) -> Self { - Self { wrapped_release, repo, commit_hash, bytecode_version, framework_local_dir, script } + pub fn new(wrapped_release: R, script: String) -> Self { + Self { wrapped_release, script } } /// Generates the bytecode for the script proposal. @@ -55,12 +43,7 @@ where println!("file: {:?}", file.path()); } - let compiler = Compiler::new( - self.repo, - self.commit_hash, - self.bytecode_version, - self.framework_local_dir.clone(), - ); + let compiler = Compiler::movement(); let bytecode = compiler .compile_in_temp_dir_to_bytecode("release_script", &release_script_script_path) @@ -207,17 +190,7 @@ macro_rules! generate_script_module { impl $struct_name { pub fn new() -> Self { let script = $script_stanza; - - Self { - with_script: RunScript::new( - super::$struct_name::new(), - "null", - "null", - 6, - Some(aptos_framework_path()), // just use the path to the framework for the script - script, - ), - } + Self { with_script: RunScript::new(super::$struct_name::new(), script) } } } diff --git a/protocol-units/execution/maptos/framework/releases/upgrade-gas/src/lib.rs b/protocol-units/execution/maptos/framework/releases/upgrade-gas/src/lib.rs index b710468eb..95bb3fada 100644 --- a/protocol-units/execution/maptos/framework/releases/upgrade-gas/src/lib.rs +++ b/protocol-units/execution/maptos/framework/releases/upgrade-gas/src/lib.rs @@ -16,10 +16,6 @@ where R: Release, { pub wrapped_release: R, - pub repo: &'static str, - pub commit_hash: &'static str, - pub bytecode_version: u32, - pub framework_local_dir: Option, pub gas_schedule: GasScheduleV2, } @@ -27,22 +23,8 @@ impl GasUpgrade where R: Release, { - pub fn new( - wrapped_release: R, - repo: &'static str, - commit_hash: &'static str, - bytecode_version: u32, - framework_local_dir: Option, - gas_schedule: GasScheduleV2, - ) -> Self { - Self { - wrapped_release, - repo, - commit_hash, - bytecode_version, - framework_local_dir, - gas_schedule, - } + pub fn new(wrapped_release: R, gas_schedule: GasScheduleV2) -> Self { + Self { wrapped_release, gas_schedule } } /// Generates the bytecode for the gas upgrade proposal. @@ -78,12 +60,7 @@ where println!("file: {:?}", file.path()); } - let compiler = Compiler::new( - self.repo, - self.commit_hash, - self.bytecode_version, - self.framework_local_dir.clone(), - ); + let compiler = Compiler::movement(); let bytecode = compiler .compile_in_temp_dir_to_bytecode("gas_upgrade", &gas_script_path) @@ -225,14 +202,7 @@ macro_rules! generate_gas_upgrade_module { let gas_schedule = $gas_stanza; Self { - with_gas_upgrade: GasUpgrade::new( - super::$struct_name::new(), - "null", - "null", - 6, - Some(aptos_framework_path()), // just use the path to the framework for the gas upgrade - gas_schedule, - ), + with_gas_upgrade: GasUpgrade::new(super::$struct_name::new(), gas_schedule), } } } diff --git a/protocol-units/execution/maptos/framework/releases/util/src/compiler.rs b/protocol-units/execution/maptos/framework/releases/util/src/compiler.rs index c305e7cc7..d50bd01a1 100644 --- a/protocol-units/execution/maptos/framework/releases/util/src/compiler.rs +++ b/protocol-units/execution/maptos/framework/releases/util/src/compiler.rs @@ -12,7 +12,8 @@ use std::path::{Path, PathBuf}; pub struct Compiler { pub repo: &'static str, - pub commit_hash: &'static str, + pub rev: &'static str, + pub subdir_path: &'static str, pub bytecode_version: u32, pub framework_local_dir: Option, } @@ -20,22 +21,34 @@ pub struct Compiler { impl Compiler { pub fn new( repo: &'static str, - commit_hash: &'static str, + rev: &'static str, + subdir_path: &'static str, bytecode_version: u32, framework_local_dir: Option, ) -> Self { - Self { repo, commit_hash, bytecode_version, framework_local_dir } + Self { repo, rev, subdir_path, bytecode_version, framework_local_dir } } - pub fn head() -> Self { + pub fn local_bytecode_6() -> Self { Self { repo: "doesn't matter", - commit_hash: "doesn't matter", + rev: "doesn't matter", + subdir_path: "doesn't matter", bytecode_version: 6, framework_local_dir: Some(aptos_framework_path()), } } + pub fn movement() -> Self { + Self { + repo: "https://github.com/movementlabsxyz/aptos-core.git", + rev: "movement", + subdir_path: "aptos-move/framework/aptos-framework", + bytecode_version: 6, + framework_local_dir: None, + } + } + /// Initializes a Move package directory with a Move.toml file for the temporary compilation. fn init_move_dir( &self, @@ -44,7 +57,6 @@ impl Compiler { addresses: BTreeMap, ) -> Result<(), anyhow::Error> { const APTOS_FRAMEWORK: &str = "AptosFramework"; - const APTOS_GIT_PATH: &str = "https://github.com/movementlabsxyz/aptos-core.git"; const SUBDIR_PATH: &str = "aptos-move/framework/aptos-framework"; let move_toml = package_dir.join(SourcePackageLayout::Manifest.path()); @@ -68,8 +80,8 @@ impl Compiler { APTOS_FRAMEWORK.to_string(), Dependency { local: None, - git: Some(APTOS_GIT_PATH.to_string()), - rev: Some(self.commit_hash.to_string()), + git: Some(self.repo.to_string()), + rev: Some(self.rev.to_string()), subdir: Some(SUBDIR_PATH.to_string()), aptos: None, address: None, diff --git a/protocol-units/execution/maptos/framework/releases/util/src/lib.rs b/protocol-units/execution/maptos/framework/releases/util/src/lib.rs index da71ba0bd..4f29b37cc 100644 --- a/protocol-units/execution/maptos/framework/releases/util/src/lib.rs +++ b/protocol-units/execution/maptos/framework/releases/util/src/lib.rs @@ -473,7 +473,7 @@ fn build_release_package_transaction_payload( ) })?; - let compiler = compiler::Compiler::head(); + let compiler = compiler::Compiler::movement(); let code = compiler .compile_in_temp_dir_to_bytecode(name, script_path.as_path()) diff --git a/protocol-units/execution/maptos/framework/releases/util/src/voter.rs b/protocol-units/execution/maptos/framework/releases/util/src/voter.rs index 57a4bfe05..2a3b2e8ce 100644 --- a/protocol-units/execution/maptos/framework/releases/util/src/voter.rs +++ b/protocol-units/execution/maptos/framework/releases/util/src/voter.rs @@ -58,12 +58,7 @@ impl Voter { println!("file: {:?}", file.path()); } - let compiler = Compiler::new( - self.repo, - self.commit_hash, - self.bytecode_version, - self.framework_local_dir.clone(), - ); + let compiler = Compiler::movement(); let bytecode = compiler .compile_in_temp_dir_to_bytecode("proposal", &gas_script_path) diff --git a/util/signing/interface/src/key/mod.rs b/util/signing/interface/src/key/mod.rs index 00abf3ac0..0ecdfd4e8 100644 --- a/util/signing/interface/src/key/mod.rs +++ b/util/signing/interface/src/key/mod.rs @@ -40,14 +40,16 @@ pub enum Environment { Prod, Dev, Staging, + Test, } impl ToCanonicalString for Environment { fn to_canonical_string(&self) -> String { match self { Environment::Prod => "prod".to_string(), - Environment::Dev => "devNet".to_string(), + Environment::Dev => "devnet".to_string(), Environment::Staging => "staging".to_string(), + Environment::Test => "testnet".to_string(), } } } @@ -56,8 +58,9 @@ impl TryFromCanonicalString for Environment { fn try_from_canonical_string(s: &str) -> Result { match s { "prod" => Ok(Environment::Prod), - "devNet" => Ok(Environment::Dev), + "devnet" => Ok(Environment::Dev), "staging" => Ok(Environment::Staging), + "testnet" => Ok(Environment::Test), _ => Err(format!("invalid environment: {}", s)), } } diff --git a/util/signing/providers/hashicorp-vault/Cargo.toml b/util/signing/providers/hashicorp-vault/Cargo.toml index 2924fbfbf..9a6a2a756 100644 --- a/util/signing/providers/hashicorp-vault/Cargo.toml +++ b/util/signing/providers/hashicorp-vault/Cargo.toml @@ -16,6 +16,7 @@ base64 = { workspace = true } anyhow = { workspace = true } async-trait = { workspace = true } uuid = { workspace = true } +tracing = { workspace = true } [dev-dependencies] tokio = { workspace = true } diff --git a/util/signing/providers/hashicorp-vault/src/hsm/key.rs b/util/signing/providers/hashicorp-vault/src/hsm/key.rs index 0b640b8d9..6ac9819f1 100644 --- a/util/signing/providers/hashicorp-vault/src/hsm/key.rs +++ b/util/signing/providers/hashicorp-vault/src/hsm/key.rs @@ -30,7 +30,8 @@ where async fn build(&self, key: Key) -> Result, SignerBuilderError> { let mut hsm = HashiCorpVault::try_from_env() .map_err(|e| SignerBuilderError::Internal(e.to_string()))?; - hsm.set_key_id(key.to_delimited_canonical_string("_")); + hsm.set_key_id(key.to_delimited_canonical_string("-")); + tracing::info!("HashiCorp Vault builder key name:{}", hsm.get_key_id()); if self.create_key { hsm = hsm .create_key() diff --git a/util/signing/providers/hashicorp-vault/src/hsm/mod.rs b/util/signing/providers/hashicorp-vault/src/hsm/mod.rs index be89e4e2e..3099b82dc 100644 --- a/util/signing/providers/hashicorp-vault/src/hsm/mod.rs +++ b/util/signing/providers/hashicorp-vault/src/hsm/mod.rs @@ -31,6 +31,11 @@ where self.key_name = key_id; } + /// Sets the key id + pub fn get_key_id(&mut self) -> String { + self.key_name.clone() + } + /// Tries to create a new HashiCorp Vault HSM from the environment pub fn try_from_env() -> Result { let address = std::env::var("VAULT_ADDRESS").context("VAULT_ADDRESS not set")?; diff --git a/util/signing/providers/local/Cargo.toml b/util/signing/providers/local/Cargo.toml index 073700bcf..64b4e54b3 100644 --- a/util/signing/providers/local/Cargo.toml +++ b/util/signing/providers/local/Cargo.toml @@ -18,7 +18,7 @@ ecdsa = { workspace = true } rand = { version = "0.8.5" } async-trait = { workspace = true } hex = { workspace = true } -ed25519-dalek = { workspace = true } +ed25519-dalek = { workspace = true, features = ["rand_core"]} [dev-dependencies] tokio = { workspace = true } diff --git a/util/signing/providers/local/src/cryptography/ed25519/mod.rs b/util/signing/providers/local/src/cryptography/ed25519/mod.rs index 5c17af843..98f3215f2 100644 --- a/util/signing/providers/local/src/cryptography/ed25519/mod.rs +++ b/util/signing/providers/local/src/cryptography/ed25519/mod.rs @@ -1,7 +1,5 @@ //! ed25519 is unimplemented for local cryptography spec -/*use crate::cryptography::LocalCryptographySpec; +use crate::cryptography::LocalCryptographyNoSpec; use movement_signer::cryptography::ed25519::Ed25519; -impl LocalCryptographySpec for Ed25519 { - type Curve = ed25519_dalek::Ed25519; -}*/ +impl LocalCryptographyNoSpec for Ed25519 {} diff --git a/util/signing/providers/local/src/cryptography/mod.rs b/util/signing/providers/local/src/cryptography/mod.rs index cdb5053bf..c8584566d 100644 --- a/util/signing/providers/local/src/cryptography/mod.rs +++ b/util/signing/providers/local/src/cryptography/mod.rs @@ -1,6 +1,13 @@ pub mod ed25519; pub mod secp256k1; +/// A marker trait for cryptography implementations that do not have a spec. +/// +/// Note: +/// In theory, we could have an exploded signer spec where one type is specified for signing and the other for getting the public key. But, this adds little utility at this point. +pub trait LocalCryptographyNoSpec {} + +/// Local cryptography specs have a curve associated with them. pub trait LocalCryptographySpec { type Curve; } diff --git a/util/signing/providers/local/src/signer/ed25519.rs b/util/signing/providers/local/src/signer/ed25519.rs new file mode 100644 index 000000000..a4f881d3d --- /dev/null +++ b/util/signing/providers/local/src/signer/ed25519.rs @@ -0,0 +1,104 @@ +use crate::signer::NoSpecLocalSigner; +use ed25519_dalek::{Signer as _, SigningKey, VerifyingKey}; +use movement_signer::Signing; +use movement_signer::{ + cryptography::{ed25519::Ed25519, Curve, TryFromBytes}, + SignerError, +}; + +pub struct Ed25519SignerInner { + signing_key: SigningKey, + verifying_key: VerifyingKey, +} + +impl Ed25519SignerInner { + /// Constructs a new [NoSpecLocalSigner] with the provided key pair. + pub fn new(signing_key: SigningKey, verifying_key: VerifyingKey) -> Self { + Self { signing_key, verifying_key } + } + + /// Constructs a new [NoSpecLocalSigner] with a random key pair. + pub fn random() -> Self { + let signing_key = SigningKey::generate(&mut rand::thread_rng()); + + let verifying_key = signing_key.verifying_key().clone(); + Self::new(signing_key, verifying_key) + } + + /// Constructs a new [NoSpecLocalSigner] from a [SigningKey]. + pub fn from_signing_key(signing_key: SigningKey) -> Self { + let verifying_key = signing_key.verifying_key().clone(); + Self::new(signing_key, verifying_key) + } + + /// Constructs a new [NoSpecLocalSigner] from a byte slice. + pub fn from_signing_key_bytes(bytes: &[u8]) -> Result { + let signing_key_bytes: &[u8; 32] = + bytes.try_into().map_err(|_| SignerError::Decode("Invalid key length".into()))?; + let signing_key = SigningKey::from_bytes(signing_key_bytes.into()); + Ok(Self::from_signing_key(signing_key)) + } + + /// Constructs a new [NoSpecLocalSigner] from a hex string. + pub fn from_signing_key_hex(hex: &str) -> Result { + let bytes = hex::decode(hex).map_err(|e| { + SignerError::Decode(format!("failed to decode hex string: {}", e).into()) + })?; + Self::from_signing_key_bytes(&bytes) + } +} + +impl NoSpecLocalSigner { + /// Constructs a new [NoSpecLocalSigner] with the provided key pair. + pub fn new(signing_key: SigningKey, verifying_key: VerifyingKey) -> Self { + Self { + inner: Ed25519SignerInner::new(signing_key, verifying_key), + __curve_marker: std::marker::PhantomData, + } + } + + /// Constructs a new [NoSpecLocalSigner] with a random key pair. + pub fn random() -> Self { + let inner = Ed25519SignerInner::random(); + + Self { inner, __curve_marker: std::marker::PhantomData } + } + + /// Constructs a new [NoSpecLocalSigner] from a [SigningKey]. + pub fn from_signing_key(signing_key: SigningKey) -> Self { + let verifying_key = signing_key.verifying_key().clone(); + Self::new(signing_key, verifying_key) + } + + /// Constructs a new [NoSpecLocalSigner] from a byte slice. + pub fn from_signing_key_bytes(bytes: &[u8]) -> Result { + let inner = Ed25519SignerInner::from_signing_key_bytes(bytes)?; + Ok(Self { inner, __curve_marker: std::marker::PhantomData }) + } + + /// Constructs a new [NoSpecLocalSigner] from a hex string. + pub fn from_signing_key_hex(hex: &str) -> Result { + let bytes = hex::decode(hex).map_err(|e| { + SignerError::Decode(format!("failed to decode hex string: {}", e).into()) + })?; + Self::from_signing_key_bytes(&bytes) + } +} + +#[async_trait::async_trait] +impl Signing for NoSpecLocalSigner { + async fn sign(&self, message: &[u8]) -> Result<::Signature, SignerError> { + let signature = self + .inner + .signing_key + .try_sign(message) + .map_err(|e| SignerError::Sign(e.into()))?; + Ok(::Signature::try_from_bytes(signature.to_vec().as_slice()) + .map_err(|e| SignerError::Sign(e.into()))?) + } + + async fn public_key(&self) -> Result<::PublicKey, SignerError> { + ::PublicKey::try_from_bytes(self.inner.verifying_key.as_bytes()) + .map_err(|e| SignerError::PublicKey(e.into())) + } +} diff --git a/util/signing/providers/local/src/signer/mod.rs b/util/signing/providers/local/src/signer/mod.rs index 5fd5baece..ed3e8de7d 100644 --- a/util/signing/providers/local/src/signer/mod.rs +++ b/util/signing/providers/local/src/signer/mod.rs @@ -1,4 +1,7 @@ -use crate::cryptography::LocalCryptographySpec; +pub mod ed25519; +pub mod secp256k1; + +use crate::cryptography::{LocalCryptographyNoSpec, LocalCryptographySpec}; use ecdsa::signature::Signer as _; use ecdsa::{ elliptic_curve::{ @@ -13,10 +16,20 @@ use ecdsa::{ SignatureSize, SigningKey, VerifyingKey, }; use movement_signer::{ - cryptography::{secp256k1::Secp256k1, Curve, TryFromBytes}, + cryptography::{Curve, TryFromBytes}, SignerError, Signing, }; +/// [NoSpecLocalSigner] is used to mark a signer tha does not have a cryptography spec, but ideally would. +/// Implementations of [Signing] for [NoSpecLocalSigner] SHALL be bespoke. +pub struct NoSpecLocalSigner +where + C: Curve + LocalCryptographyNoSpec, +{ + inner: I, + __curve_marker: std::marker::PhantomData, +} + pub struct LocalSigner where C: Curve + LocalCryptographySpec, @@ -35,47 +48,6 @@ where __curve_marker: std::marker::PhantomData, } -impl LocalSigner { - /// Constructs a new [LocalSigner] with the provided key pair. - pub fn new( - signing_key: SigningKey, - verifying_key: VerifyingKey, - ) -> Self { - Self { signing_key, verifying_key, __curve_marker: std::marker::PhantomData } - } - - /// Constructs a new [LocalSigner] with a random key pair. - pub fn random() -> Self { - let signing_key = SigningKey::::random(&mut rand::thread_rng()); - - let verifying_key = signing_key.verifying_key().clone(); - Self::new(signing_key, verifying_key) - } - - /// Constructs a new [LocalSigner] from a [SigningKey]. - pub fn from_signing_key(signing_key: SigningKey) -> Self { - let verifying_key = signing_key.verifying_key().clone(); - Self::new(signing_key, verifying_key) - } - - /// Constructs a new [LocalSigner] from a byte slice. - pub fn from_signing_key_bytes(bytes: &[u8]) -> Result { - let signing_key_bytes: &[u8; 32] = - bytes.try_into().map_err(|_| SignerError::Decode("Invalid key length".into()))?; - let signing_key = SigningKey::::from_bytes(signing_key_bytes.into()) - .map_err(|e| SignerError::Decode(e.into()))?; - Ok(Self::from_signing_key(signing_key)) - } - - /// Constructs a new [LocalSigner] from a hex string. - pub fn from_signing_key_hex(hex: &str) -> Result { - let bytes = hex::decode(hex).map_err(|e| { - SignerError::Decode(format!("failed to decode hex string: {}", e).into()) - })?; - Self::from_signing_key_bytes(&bytes) - } -} - #[async_trait::async_trait] impl Signing for LocalSigner where diff --git a/util/signing/providers/local/src/signer/secp256k1.rs b/util/signing/providers/local/src/signer/secp256k1.rs new file mode 100644 index 000000000..948b9ff4e --- /dev/null +++ b/util/signing/providers/local/src/signer/secp256k1.rs @@ -0,0 +1,44 @@ +use crate::signer::LocalSigner; +use ecdsa::{SigningKey, VerifyingKey}; +use movement_signer::{cryptography::secp256k1::Secp256k1, SignerError}; + +impl LocalSigner { + /// Constructs a new [LocalSigner] with the provided key pair. + pub fn new( + signing_key: SigningKey, + verifying_key: VerifyingKey, + ) -> Self { + Self { signing_key, verifying_key, __curve_marker: std::marker::PhantomData } + } + + /// Constructs a new [LocalSigner] with a random key pair. + pub fn random() -> Self { + let signing_key = SigningKey::::random(&mut rand::thread_rng()); + + let verifying_key = signing_key.verifying_key().clone(); + Self::new(signing_key, verifying_key) + } + + /// Constructs a new [LocalSigner] from a [SigningKey]. + pub fn from_signing_key(signing_key: SigningKey) -> Self { + let verifying_key = signing_key.verifying_key().clone(); + Self::new(signing_key, verifying_key) + } + + /// Constructs a new [LocalSigner] from a byte slice. + pub fn from_signing_key_bytes(bytes: &[u8]) -> Result { + let signing_key_bytes: &[u8; 32] = + bytes.try_into().map_err(|_| SignerError::Decode("Invalid key length".into()))?; + let signing_key = SigningKey::::from_bytes(signing_key_bytes.into()) + .map_err(|e| SignerError::Decode(e.into()))?; + Ok(Self::from_signing_key(signing_key)) + } + + /// Constructs a new [LocalSigner] from a hex string. + pub fn from_signing_key_hex(hex: &str) -> Result { + let bytes = hex::decode(hex).map_err(|e| { + SignerError::Decode(format!("failed to decode hex string: {}", e).into()) + })?; + Self::from_signing_key_bytes(&bytes) + } +} diff --git a/util/signing/util/loader/src/lib.rs b/util/signing/util/loader/src/lib.rs index e4cd039c3..f972a07b9 100644 --- a/util/signing/util/loader/src/lib.rs +++ b/util/signing/util/loader/src/lib.rs @@ -111,7 +111,17 @@ impl Load for SignerIdentifier { async fn load(&self) -> Result, LoaderError> { info!("loading an ed25519 signer {:?}", self); match self { - SignerIdentifier::Local(_local) => Err(LoaderError::InvalidCurve), + SignerIdentifier::Local(local) => { + let signer = movement_signer_local::signer::NoSpecLocalSigner::< + movement_signer_local::signer::ed25519::Ed25519SignerInner, + Ed25519, + >::from_signing_key_hex(&local.private_key_hex_bytes) + .map_err(|e| LoaderError::InvalidSigner(e.into()))?; + Ok(LoadedSigner::new( + Arc::new(signer) as Arc + Send + Sync>, + self.clone(), + )) + } SignerIdentifier::AwsKms(_aws_kms) => Err(LoaderError::InvalidCurve), SignerIdentifier::HashiCorpVault(hashi_corp_vault) => { let builder = movement_signer_hashicorp_vault::hsm::key::Builder::new()