From ce04dcfc8b3195b43b08ab7908217c4598964f8d Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 21:15:19 -0700 Subject: [PATCH 01/24] Renamed chain-signature MPC_RECOVERY_* env vars to MPC_* --- chain-signatures/node/src/cli.rs | 30 ++++----- chain-signatures/node/src/indexer.rs | 8 +-- chain-signatures/node/src/storage/mod.rs | 10 +-- chain-signatures/node/src/util.rs | 2 +- infra/modules/multichain/main.tf | 34 +++++----- infra/multichain-dev/main.tf | 18 ++--- infra/multichain-dev/variables.tf | 30 ++++----- infra/multichain-mainnet-dev/main.tf | 48 ++++++------- infra/multichain-mainnet-dev/variables.tf | 34 +++++----- infra/multichain-testnet/main.tf | 20 +++--- infra/multichain-testnet/variables.tf | 12 ++-- infra/partner-mainnet/main.tf | 82 +++++++++++------------ infra/partner-mainnet/variables.tf | 24 +++---- infra/partner-testnet/main.tf | 52 +++++++------- infra/partner-testnet/variables.tf | 20 +++--- 15 files changed, 212 insertions(+), 212 deletions(-) diff --git a/chain-signatures/node/src/cli.rs b/chain-signatures/node/src/cli.rs index b0fb86cae..2a7cbe294 100644 --- a/chain-signatures/node/src/cli.rs +++ b/chain-signatures/node/src/cli.rs @@ -22,57 +22,57 @@ pub enum Cli { /// NEAR RPC address #[arg( long, - env("MPC_RECOVERY_NEAR_RPC"), + env("MPC_NEAR_RPC"), default_value("https://rpc.testnet.near.org") )] near_rpc: String, /// MPC contract id #[arg( long, - env("MPC_RECOVERY_CONTRACT_ID"), + env("MPC_CONTRACT_ID"), default_value("v5.multichain-mpc-dev.testnet") )] mpc_contract_id: AccountId, /// This node's account id - #[arg(long, env("MPC_RECOVERY_ACCOUNT_ID"))] + #[arg(long, env("MPC_ACCOUNT_ID"))] account_id: AccountId, /// This node's account ed25519 secret key - #[arg(long, env("MPC_RECOVERY_ACCOUNT_SK"))] + #[arg(long, env("MPC_ACCOUNT_SK"))] account_sk: SecretKey, /// The web port for this server - #[arg(long, env("MPC_RECOVERY_WEB_PORT"))] + #[arg(long, env("MPC_WEB_PORT"))] web_port: u16, // TODO: need to add in CipherPK type for parsing. /// The cipher public key used to encrypt messages between nodes. - #[arg(long, env("MPC_RECOVERY_CIPHER_PK"))] + #[arg(long, env("MPC_CIPHER_PK"))] cipher_pk: String, /// The cipher secret key used to decrypt messages between nodes. - #[arg(long, env("MPC_RECOVERY_CIPHER_SK"))] + #[arg(long, env("MPC_CIPHER_SK"))] cipher_sk: String, /// The secret key used to sign messages to be sent between nodes. - #[arg(long, env("MPC_RECOVERY_SIGN_SK"))] + #[arg(long, env("MPC_SIGN_SK"))] sign_sk: Option, /// NEAR Lake Indexer options #[clap(flatten)] indexer_options: indexer::Options, /// Local address that other peers can use to message this node. - #[arg(long, env("MPC_RECOVERY_LOCAL_ADDRESS"))] + #[arg(long, env("MPC_LOCAL_ADDRESS"))] my_address: Option, /// Storage options #[clap(flatten)] storage_options: storage::Options, /// At minimum, how many triples to stockpile on this node. - #[arg(long, env("MPC_RECOVERY_MIN_TRIPLES"), default_value("20"))] + #[arg(long, env("MPC_MIN_TRIPLES"), default_value("20"))] min_triples: usize, /// At maximum, how many triples to stockpile on this node. - #[arg(long, env("MPC_RECOVERY_MAX_TRIPLES"), default_value("640"))] + #[arg(long, env("MPC_MAX_TRIPLES"), default_value("640"))] max_triples: usize, /// At maximum, how many triple protocols can this current node introduce /// at the same time. This should be something like `max_concurrent_gen / num_nodes` #[arg( long, - env("MPC_RECOVERY_MAX_CONCURRENT_INTRODUCTION"), + env("MPC_MAX_CONCURRENT_INTRODUCTION"), default_value("2") )] max_concurrent_introduction: usize, @@ -81,17 +81,17 @@ pub enum Cli { /// at the same time. The rest will be queued up. #[arg( long, - env("MPC_RECOVERY_MAX_CONCURRENT_GENERATION"), + env("MPC_MAX_CONCURRENT_GENERATION"), default_value("16") )] max_concurrent_generation: usize, /// At minimum, how many presignatures to stockpile on this node. - #[arg(long, env("MPC_RECOVERY_MIN_PRESIGNATURES"), default_value("10"))] + #[arg(long, env("MPC_MIN_PRESIGNATURES"), default_value("10"))] min_presignatures: usize, /// At maximum, how many presignatures to stockpile on the network. - #[arg(long, env("MPC_RECOVERY_MAX_PRESIGNATURES"), default_value("320"))] + #[arg(long, env("MPC_MAX_PRESIGNATURES"), default_value("320"))] max_presignatures: usize, }, } diff --git a/chain-signatures/node/src/indexer.rs b/chain-signatures/node/src/indexer.rs index 8f9de304b..bea18337a 100644 --- a/chain-signatures/node/src/indexer.rs +++ b/chain-signatures/node/src/indexer.rs @@ -25,7 +25,7 @@ pub struct Options { /// AWS S3 bucket name for NEAR Lake Indexer #[clap( long, - env("MPC_RECOVERY_INDEXER_S3_BUCKET"), + env("MPC_INDEXER_S3_BUCKET"), default_value = "near-lake-data-testnet" )] pub s3_bucket: String, @@ -33,20 +33,20 @@ pub struct Options { /// AWS S3 region name for NEAR Lake Indexer #[clap( long, - env("MPC_RECOVERY_INDEXER_S3_REGION"), + env("MPC_INDEXER_S3_REGION"), default_value = "eu-central-1" )] pub s3_region: String, /// AWS S3 URL for NEAR Lake Indexer (can be used to point to LocalStack) - #[clap(long, env("MPC_RECOVERY_INDEXER_S3_URL"))] + #[clap(long, env("MPC_INDEXER_S3_URL"))] pub s3_url: Option, /// The block height to start indexing from. // Defaults to the latest block on 2023-11-14 07:40:22 AM UTC #[clap( long, - env("MPC_RECOVERY_INDEXER_START_BLOCK_HEIGHT"), + env("MPC_INDEXER_START_BLOCK_HEIGHT"), default_value = "145964826" )] pub start_block_height: u64, diff --git a/chain-signatures/node/src/storage/mod.rs b/chain-signatures/node/src/storage/mod.rs index 6550797f4..393356c03 100644 --- a/chain-signatures/node/src/storage/mod.rs +++ b/chain-signatures/node/src/storage/mod.rs @@ -6,19 +6,19 @@ pub mod triple_storage; #[group(id = "storage_options")] pub struct Options { /// env used to suffix datastore table names to differentiate among environments. - #[clap(long, env("MPC_RECOVERY_ENV"))] + #[clap(long, env("MPC_ENV"))] pub env: String, /// GCP project ID. - #[clap(long, env("MPC_RECOVERY_GCP_PROJECT_ID"))] + #[clap(long, env("MPC_GCP_PROJECT_ID"))] pub gcp_project_id: String, /// GCP Secret Manager ID that will be used to load/store the node's secret key share. - #[clap(long, env("MPC_RECOVERY_SK_SHARE_SECRET_ID"), requires_all=["gcp_project_id"])] + #[clap(long, env("MPC_SK_SHARE_SECRET_ID"), requires_all=["gcp_project_id"])] pub sk_share_secret_id: Option, /// Mostly for integration tests. /// GCP Datastore URL that will be used to load/store the node's triples and presignatures. - #[arg(long, env("MPC_RECOVERY_GCP_DATASTORE_URL"))] + #[arg(long, env("MPC_GCP_DATASTORE_URL"))] pub gcp_datastore_url: Option, - #[arg(long, env("MPC_RECOVERY_SK_SHARE_LOCAL_PATH"))] + #[arg(long, env("MPC_SK_SHARE_LOCAL_PATH"))] pub sk_share_local_path: Option, } diff --git a/chain-signatures/node/src/util.rs b/chain-signatures/node/src/util.rs index 8aceb5b2e..1f7b9874f 100644 --- a/chain-signatures/node/src/util.rs +++ b/chain-signatures/node/src/util.rs @@ -65,7 +65,7 @@ impl AffinePointExt for AffinePoint { } pub fn get_triple_timeout() -> Duration { - env::var("MPC_RECOVERY_TRIPLE_TIMEOUT_SEC") + env::var("MPC_TRIPLE_TIMEOUT_SEC") .map(|val| val.parse::().ok().map(Duration::from_secs)) .unwrap_or_default() .unwrap_or(crate::types::PROTOCOL_TRIPLE_TIMEOUT) diff --git a/infra/modules/multichain/main.tf b/infra/modules/multichain/main.tf index b67ba8c38..c7dad4678 100644 --- a/infra/modules/multichain/main.tf +++ b/infra/modules/multichain/main.tf @@ -18,51 +18,51 @@ resource "google_cloud_run_v2_service" "node" { args = ["start"] env { - name = "MPC_RECOVERY_NODE_ID" + name = "MPC_NODE_ID" value = var.node_id } env { - name = "MPC_RECOVERY_NEAR_RPC" + name = "MPC_NEAR_RPC" value = var.near_rpc } env { - name = "MPC_RECOVERY_CONTRACT_ID" + name = "MPC_CONTRACT_ID" value = var.mpc_contract_id } env { - name = "MPC_RECOVERY_ACCOUNT_ID" + name = "MPC_ACCOUNT_ID" value = var.account_id } env { - name = "MPC_RECOVERY_CIPHER_PK" + name = "MPC_CIPHER_PK" value = var.cipher_pk } env { - name = "MPC_RECOVERY_LOCAL_ADDRESS" + name = "MPC_LOCAL_ADDRESS" value = var.my_address } env { - name = "MPC_RECOVERY_INDEXER_S3_BUCKET" + name = "MPC_INDEXER_S3_BUCKET" value = var.indexer_options.s3_bucket } env { - name = "MPC_RECOVERY_INDEXER_S3_REGION" + name = "MPC_INDEXER_S3_REGION" value = var.indexer_options.s3_region } // Conditional block in case s3_url is present. See https://stackoverflow.com/a/69891235 dynamic "env" { for_each = var.indexer_options.s3_url == null ? [] : [1] content { - name = "MPC_RECOVERY_INDEXER_S3_URL" + name = "MPC_INDEXER_S3_URL" value = var.indexer_options.s3_url } } env { - name = "MPC_RECOVERY_INDEXER_START_BLOCK_HEIGHT" + name = "MPC_INDEXER_START_BLOCK_HEIGHT" value = var.indexer_options.start_block_height } env { - name = "MPC_RECOVERY_ACCOUNT_SK" + name = "MPC_ACCOUNT_SK" value_source { secret_key_ref { secret = var.account_sk_secret_id @@ -71,7 +71,7 @@ resource "google_cloud_run_v2_service" "node" { } } env { - name = "MPC_RECOVERY_CIPHER_SK" + name = "MPC_CIPHER_SK" value_source { secret_key_ref { secret = var.cipher_sk_secret_id @@ -83,7 +83,7 @@ resource "google_cloud_run_v2_service" "node" { dynamic "env" { for_each = var.sign_sk_secret_id == null ? [] : [1] content { - name = "MPC_RECOVERY_SIGN_SK" + name = "MPC_SIGN_SK" value_source { secret_key_ref { secret = var.sign_sk_secret_id @@ -115,19 +115,19 @@ resource "google_cloud_run_v2_service" "node" { value = var.indexer_options.s3_region } env { - name = "MPC_RECOVERY_GCP_PROJECT_ID" + name = "MPC_GCP_PROJECT_ID" value = var.project } env { - name = "MPC_RECOVERY_SK_SHARE_SECRET_ID" + name = "MPC_SK_SHARE_SECRET_ID" value = var.sk_share_secret_id } env { - name = "MPC_RECOVERY_ENV" + name = "MPC_ENV" value = var.env } env { - name = "MPC_RECOVERY_WEB_PORT" + name = "MPC_WEB_PORT" value = "3000" } env { diff --git a/infra/multichain-dev/main.tf b/infra/multichain-dev/main.tf index 4a4c89176..25e5ac5e8 100644 --- a/infra/multichain-dev/main.tf +++ b/infra/multichain-dev/main.tf @@ -16,27 +16,27 @@ module "gce-container" { env = concat(var.static_env, [ { - name = "MPC_RECOVERY_NODE_ID" + name = "MPC_NODE_ID" value = "${count.index}" }, { - name = "MPC_RECOVERY_ACCOUNT_ID" + name = "MPC_ACCOUNT_ID" value = var.node_configs["${count.index}"].account }, { - name = "MPC_RECOVERY_CIPHER_PK" + name = "MPC_CIPHER_PK" value = var.node_configs["${count.index}"].cipher_pk }, { - name = "MPC_RECOVERY_ACCOUNT_SK" + name = "MPC_ACCOUNT_SK" value = data.google_secret_manager_secret_version.account_sk_secret_id[count.index].secret_data }, { - name = "MPC_RECOVERY_CIPHER_SK" + name = "MPC_CIPHER_SK" value = data.google_secret_manager_secret_version.cipher_sk_secret_id[count.index].secret_data }, { - name = "MPC_RECOVERY_SIGN_SK" + name = "MPC_SIGN_SK" value = data.google_secret_manager_secret_version.sign_sk_secret_id[count.index] != null ? data.google_secret_manager_secret_version.sign_sk_secret_id[count.index].secret_data : data.google_secret_manager_secret_version.account_sk_secret_id[count.index].secret_data }, { @@ -48,15 +48,15 @@ module "gce-container" { value = data.google_secret_manager_secret_version.aws_secret_key_secret_id.secret_data }, { - name = "MPC_RECOVERY_LOCAL_ADDRESS" + name = "MPC_LOCAL_ADDRESS" value = "http://${google_compute_address.internal_ips[count.index].address}" }, { - name = "MPC_RECOVERY_SK_SHARE_SECRET_ID" + name = "MPC_SK_SHARE_SECRET_ID" value = var.node_configs["${count.index}"].sk_share_secret_id }, { - name = "MPC_RECOVERY_ENV", + name = "MPC_ENV", value = var.env } ]) diff --git a/infra/multichain-dev/variables.tf b/infra/multichain-dev/variables.tf index 043e5b77e..a0b5912ce 100644 --- a/infra/multichain-dev/variables.tf +++ b/infra/multichain-dev/variables.tf @@ -75,7 +75,7 @@ variable "node_configs" { } variable "env" { - type = string + type = string default = "dev" } @@ -86,19 +86,19 @@ variable "static_env" { })) default = [ { - name = "MPC_RECOVERY_NEAR_RPC" + name = "MPC_NEAR_RPC" value = "https://rpc.testnet.near.org" }, { - name = "MPC_RECOVERY_CONTRACT_ID" + name = "MPC_CONTRACT_ID" value = "v5.multichain-mpc-dev.testnet" }, { - name = "MPC_RECOVERY_INDEXER_S3_BUCKET" + name = "MPC_INDEXER_S3_BUCKET" value = "near-lake-data-testnet" }, { - name = "MPC_RECOVERY_INDEXER_START_BLOCK_HEIGHT" + name = "MPC_INDEXER_START_BLOCK_HEIGHT" value = 159307004 }, { @@ -106,11 +106,11 @@ variable "static_env" { value = "eu-central-1" }, { - name = "MPC_RECOVERY_GCP_PROJECT_ID" + name = "MPC_GCP_PROJECT_ID" value = "pagoda-discovery-platform-dev" }, { - name = "MPC_RECOVERY_WEB_PORT" + name = "MPC_WEB_PORT" value = "3000" }, { @@ -118,35 +118,35 @@ variable "static_env" { value = "mpc_recovery_node=debug" }, { - name = "MPC_RECOVERY_INDEXER_S3_REGION" + name = "MPC_INDEXER_S3_REGION" value = "eu-central-1" }, { - name = "MPC_RECOVERY_MIN_TRIPLES" + name = "MPC_MIN_TRIPLES" value = 20 }, { - name = "MPC_RECOVERY_MAX_TRIPLES" + name = "MPC_MAX_TRIPLES" value = 640 }, { - name = "MPC_RECOVERY_MIN_PRESIGNATURES" + name = "MPC_MIN_PRESIGNATURES" value = 10 }, { - name = "MPC_RECOVERY_MAX_PRESIGNATURES" + name = "MPC_MAX_PRESIGNATURES" value = 320 }, { - name = "MPC_RECOVERY_MAX_CONCURRENT_INTRODUCTION" + name = "MPC_MAX_CONCURRENT_INTRODUCTION" value = 2 }, { - name = "MPC_RECOVERY_MAX_CONCURRENT_GENERATION" + name = "MPC_MAX_CONCURRENT_GENERATION" value = 16 }, { - name = "MPC_RECOVERY_TRIPLE_TIMEOUT_SEC" + name = "MPC_TRIPLE_TIMEOUT_SEC" value = 1200 } ] diff --git a/infra/multichain-mainnet-dev/main.tf b/infra/multichain-mainnet-dev/main.tf index ee09a4db6..8e3f0d66f 100644 --- a/infra/multichain-mainnet-dev/main.tf +++ b/infra/multichain-mainnet-dev/main.tf @@ -16,28 +16,28 @@ module "gce-container" { env = concat(var.static_env, [ { - name = "MPC_RECOVERY_NODE_ID" + name = "MPC_NODE_ID" value = "${count.index}" }, { - name = "MPC_RECOVERY_ACCOUNT_ID" + name = "MPC_ACCOUNT_ID" value = var.node_configs["${count.index}"].account }, { - name = "MPC_RECOVERY_CIPHER_PK" + name = "MPC_CIPHER_PK" value = var.node_configs["${count.index}"].cipher_pk }, { - name = "MPC_RECOVERY_ACCOUNT_SK" + name = "MPC_ACCOUNT_SK" value = data.google_secret_manager_secret_version.account_sk_secret_id[count.index].secret_data }, { - name = "MPC_RECOVERY_CIPHER_SK" + name = "MPC_CIPHER_SK" value = data.google_secret_manager_secret_version.cipher_sk_secret_id[count.index].secret_data }, { - name = "MPC_RECOVERY_SIGN_SK" - value = data.google_secret_manager_secret_version.sign_sk_secret_id[count.index].secret_data + name = "MPC_SIGN_SK" + value = data.google_secret_manager_secret_version.sign_sk_secret_id[count.index].secret_data }, { name = "AWS_ACCESS_KEY_ID" @@ -48,15 +48,15 @@ module "gce-container" { value = data.google_secret_manager_secret_version.aws_secret_key_secret_id.secret_data }, { - name = "MPC_RECOVERY_LOCAL_ADDRESS" + name = "MPC_LOCAL_ADDRESS" value = "https://${var.node_configs[count.index].domain}" }, { - name = "MPC_RECOVERY_SK_SHARE_SECRET_ID" + name = "MPC_SK_SHARE_SECRET_ID" value = var.node_configs["${count.index}"].sk_share_secret_id }, { - name = "MPC_RECOVERY_ENV", + name = "MPC_ENV", value = var.env } ]) @@ -72,7 +72,7 @@ resource "google_compute_global_address" "external_ips" { resource "google_compute_managed_ssl_certificate" "mainnet_dev_ssl" { count = length(var.node_configs) - name = "multichain-mainnet-dev-ssl-${count.index}" + name = "multichain-mainnet-dev-ssl-${count.index}" managed { domains = [var.node_configs["${count.index}"].domain] @@ -142,13 +142,13 @@ resource "google_compute_global_forwarding_rule" "default" { } resource "google_compute_global_forwarding_rule" "https_fw" { - count = length(var.node_configs) - name = "multichain-mainnet-dev-https-rule-${count.index}" - target = google_compute_target_https_proxy.default_https[count.index].id - port_range = "443" - ip_protocol = "TCP" + count = length(var.node_configs) + name = "multichain-mainnet-dev-https-rule-${count.index}" + target = google_compute_target_https_proxy.default_https[count.index].id + port_range = "443" + ip_protocol = "TCP" load_balancing_scheme = "EXTERNAL" - ip_address = google_compute_global_address.external_ips[count.index].address + ip_address = google_compute_global_address.external_ips[count.index].address } resource "google_compute_target_http_proxy" "default" { @@ -159,11 +159,11 @@ resource "google_compute_target_http_proxy" "default" { } resource "google_compute_target_https_proxy" "default_https" { - count = length(var.node_configs) - name = "multichain-mainnet-dev-target-https-proxy-${count.index}" - description = "a description" - ssl_certificates = [ google_compute_managed_ssl_certificate.mainnet_dev_ssl[count.index].self_link ] - url_map = google_compute_url_map.default[count.index].id + count = length(var.node_configs) + name = "multichain-mainnet-dev-target-https-proxy-${count.index}" + description = "a description" + ssl_certificates = [google_compute_managed_ssl_certificate.mainnet_dev_ssl[count.index].self_link] + url_map = google_compute_url_map.default[count.index].id } resource "google_compute_url_map" "default" { @@ -173,8 +173,8 @@ resource "google_compute_url_map" "default" { } resource "google_compute_url_map" "default_redirect" { - count = length(var.node_configs) - name = "multichain-mainnet-dev-redirect-url-map-${count.index}" + count = length(var.node_configs) + name = "multichain-mainnet-dev-redirect-url-map-${count.index}" default_url_redirect { strip_query = false diff --git a/infra/multichain-mainnet-dev/variables.tf b/infra/multichain-mainnet-dev/variables.tf index c8733611f..780991b8f 100644 --- a/infra/multichain-mainnet-dev/variables.tf +++ b/infra/multichain-mainnet-dev/variables.tf @@ -76,7 +76,7 @@ variable "node_configs" { } variable "env" { - type = string + type = string default = "dev" } @@ -87,19 +87,19 @@ variable "static_env" { })) default = [ { - name = "MPC_RECOVERY_NEAR_RPC" + name = "MPC_NEAR_RPC" value = "https://rpc.mainnet.near.org" }, { - name = "MPC_RECOVERY_CONTRACT_ID" + name = "MPC_CONTRACT_ID" value = "multichain-mpc-dev.near" }, { - name = "MPC_RECOVERY_INDEXER_S3_BUCKET" + name = "MPC_INDEXER_S3_BUCKET" value = "near-lake-data-mainnet" }, { - name = "MPC_RECOVERY_INDEXER_START_BLOCK_HEIGHT" + name = "MPC_INDEXER_START_BLOCK_HEIGHT" value = 122414750 }, { @@ -107,11 +107,11 @@ variable "static_env" { value = "eu-central-1" }, { - name = "MPC_RECOVERY_GCP_PROJECT_ID" + name = "MPC_GCP_PROJECT_ID" value = "pagoda-discovery-platform-dev" }, { - name = "MPC_RECOVERY_WEB_PORT" + name = "MPC_WEB_PORT" value = "3000" }, { @@ -119,35 +119,35 @@ variable "static_env" { value = "mpc_recovery_node=debug" }, { - name = "MPC_RECOVERY_INDEXER_S3_REGION" + name = "MPC_INDEXER_S3_REGION" value = "eu-central-1" }, { - name = "MPC_RECOVERY_MIN_TRIPLES" + name = "MPC_MIN_TRIPLES" value = 20 }, { - name = "MPC_RECOVERY_MAX_TRIPLES" + name = "MPC_MAX_TRIPLES" value = 640 }, { - name = "MPC_RECOVERY_MIN_PRESIGNATURES" + name = "MPC_MIN_PRESIGNATURES" value = 10 }, { - name = "MPC_RECOVERY_MAX_PRESIGNATURES" + name = "MPC_MAX_PRESIGNATURES" value = 320 }, { - name = "MPC_RECOVERY_MAX_CONCURRENT_INTRODUCTION" + name = "MPC_MAX_CONCURRENT_INTRODUCTION" value = 2 }, { - name = "MPC_RECOVERY_MAX_CONCURRENT_GENERATION" + name = "MPC_MAX_CONCURRENT_GENERATION" value = 16 }, { - name = "MPC_RECOVERY_TRIPLE_TIMEOUT_SEC" + name = "MPC_TRIPLE_TIMEOUT_SEC" value = 1200 } ] @@ -155,5 +155,5 @@ variable "static_env" { variable "domain" { description = "DNS name of the node" - default = "" -} \ No newline at end of file + default = "" +} diff --git a/infra/multichain-testnet/main.tf b/infra/multichain-testnet/main.tf index 56d00956c..1e4710094 100644 --- a/infra/multichain-testnet/main.tf +++ b/infra/multichain-testnet/main.tf @@ -16,27 +16,27 @@ module "gce-container" { env = concat(var.static_env, [ { - name = "MPC_RECOVERY_NODE_ID" + name = "MPC_NODE_ID" value = "${count.index}" }, { - name = "MPC_RECOVERY_ACCOUNT_ID" + name = "MPC_ACCOUNT_ID" value = var.node_configs["${count.index}"].account }, { - name = "MPC_RECOVERY_CIPHER_PK" + name = "MPC_CIPHER_PK" value = var.node_configs["${count.index}"].cipher_pk }, { - name = "MPC_RECOVERY_ACCOUNT_SK" + name = "MPC_ACCOUNT_SK" value = data.google_secret_manager_secret_version.account_sk_secret_id[count.index].secret_data }, { - name = "MPC_RECOVERY_CIPHER_SK" + name = "MPC_CIPHER_SK" value = data.google_secret_manager_secret_version.cipher_sk_secret_id[count.index].secret_data }, { - name = "MPC_RECOVERY_SIGN_SK" + name = "MPC_SIGN_SK" value = data.google_secret_manager_secret_version.sign_sk_secret_id[count.index] != null ? data.google_secret_manager_secret_version.sign_sk_secret_id[count.index].secret_data : data.google_secret_manager_secret_version.account_sk_secret_id[count.index].secret_data }, { @@ -48,19 +48,19 @@ module "gce-container" { value = data.google_secret_manager_secret_version.aws_secret_key_secret_id.secret_data }, { - name = "MPC_RECOVERY_LOCAL_ADDRESS" + name = "MPC_LOCAL_ADDRESS" value = "http://${google_compute_global_address.external_ips[count.index].address}" }, { - name = "MPC_RECOVERY_SK_SHARE_SECRET_ID" + name = "MPC_SK_SHARE_SECRET_ID" value = var.node_configs["${count.index}"].sk_share_secret_id }, { - name = "MPC_RECOVERY_ENV", + name = "MPC_ENV", value = var.env }, { - name = "MPC_RECOVERY_GCP_PROJECT_ID" + name = "MPC_GCP_PROJECT_ID" value = var.project_id }, ]) diff --git a/infra/multichain-testnet/variables.tf b/infra/multichain-testnet/variables.tf index a21579c1a..952833ad7 100644 --- a/infra/multichain-testnet/variables.tf +++ b/infra/multichain-testnet/variables.tf @@ -85,19 +85,19 @@ variable "static_env" { })) default = [ { - name = "MPC_RECOVERY_NEAR_RPC" + name = "MPC_NEAR_RPC" value = "https://rpc.testnet.near.org" }, { - name = "MPC_RECOVERY_CONTRACT_ID" + name = "MPC_CONTRACT_ID" value = "v2.multichain-mpc.testnet" }, { - name = "MPC_RECOVERY_INDEXER_S3_BUCKET" + name = "MPC_INDEXER_S3_BUCKET" value = "near-lake-data-testnet" }, { - name = "MPC_RECOVERY_INDEXER_START_BLOCK_HEIGHT" + name = "MPC_INDEXER_START_BLOCK_HEIGHT" value = 158767549 }, { @@ -105,7 +105,7 @@ variable "static_env" { value = "eu-central-1" }, { - name = "MPC_RECOVERY_WEB_PORT" + name = "MPC_WEB_PORT" value = "3000" }, { @@ -113,7 +113,7 @@ variable "static_env" { value = "mpc_recovery_node=debug" }, { - name = "MPC_RECOVERY_INDEXER_S3_REGION" + name = "MPC_INDEXER_S3_REGION" value = "eu-central-1" } ] diff --git a/infra/partner-mainnet/main.tf b/infra/partner-mainnet/main.tf index 40c4a232d..371e6fd8c 100644 --- a/infra/partner-mainnet/main.tf +++ b/infra/partner-mainnet/main.tf @@ -16,27 +16,27 @@ module "gce-container" { env = concat(var.static_env, [ { - name = "MPC_RECOVERY_NODE_ID" + name = "MPC_NODE_ID" value = "${count.index}" }, { - name = "MPC_RECOVERY_ACCOUNT_ID" + name = "MPC_ACCOUNT_ID" value = var.node_configs["${count.index}"].account }, { - name = "MPC_RECOVERY_CIPHER_PK" + name = "MPC_CIPHER_PK" value = var.node_configs["${count.index}"].cipher_pk }, { - name = "MPC_RECOVERY_ACCOUNT_SK" + name = "MPC_ACCOUNT_SK" value = data.google_secret_manager_secret_version.account_sk_secret_id[count.index].secret_data }, { - name = "MPC_RECOVERY_CIPHER_SK" + name = "MPC_CIPHER_SK" value = data.google_secret_manager_secret_version.cipher_sk_secret_id[count.index].secret_data }, { - name = "MPC_RECOVERY_SIGN_SK" + name = "MPC_SIGN_SK" value = data.google_secret_manager_secret_version.sign_sk_secret_id[count.index] != null ? data.google_secret_manager_secret_version.sign_sk_secret_id[count.index].secret_data : data.google_secret_manager_secret_version.account_sk_secret_id[count.index].secret_data }, { @@ -48,15 +48,15 @@ module "gce-container" { value = data.google_secret_manager_secret_version.aws_secret_key_secret_id.secret_data }, { - name = "MPC_RECOVERY_LOCAL_ADDRESS" + name = "MPC_LOCAL_ADDRESS" value = "https://${var.node_configs[count.index].domain}" }, { - name = "MPC_RECOVERY_SK_SHARE_SECRET_ID" + name = "MPC_SK_SHARE_SECRET_ID" value = var.node_configs["${count.index}"].sk_share_secret_id }, { - name = "MPC_RECOVERY_ENV", + name = "MPC_ENV", value = var.env } ]) @@ -70,17 +70,17 @@ resource "google_service_account" "service_account" { resource "google_project_iam_binding" "sa-roles" { for_each = toset([ - "roles/datastore.user", - "roles/secretmanager.admin", - "roles/storage.objectAdmin", - "roles/iam.serviceAccountAdmin", + "roles/datastore.user", + "roles/secretmanager.admin", + "roles/storage.objectAdmin", + "roles/iam.serviceAccountAdmin", ]) role = each.key members = [ "serviceAccount:${google_service_account.service_account.email}" - ] - project = var.project_id + ] + project = var.project_id } resource "google_compute_global_address" "external_ips" { @@ -95,7 +95,7 @@ resource "google_compute_global_address" "external_ips" { resource "google_compute_managed_ssl_certificate" "mainnet_ssl" { count = length(var.node_configs) - name = "multichain-partner-mainnet-ssl-${count.index}" + name = "multichain-partner-mainnet-ssl-${count.index}" managed { domains = [var.node_configs[count.index].domain] @@ -157,38 +157,38 @@ resource "google_compute_health_check" "multichain_healthcheck" { } resource "google_compute_global_forwarding_rule" "http_fw" { - count = length(var.node_configs) - name = "multichain-partner-mainnet-http-rule-${count.index}" - target = google_compute_target_http_proxy.default[count.index].id - port_range = "80" - ip_protocol = "TCP" + count = length(var.node_configs) + name = "multichain-partner-mainnet-http-rule-${count.index}" + target = google_compute_target_http_proxy.default[count.index].id + port_range = "80" + ip_protocol = "TCP" load_balancing_scheme = "EXTERNAL" - ip_address = google_compute_global_address.external_ips[count.index].address + ip_address = google_compute_global_address.external_ips[count.index].address } resource "google_compute_global_forwarding_rule" "https_fw" { - count = length(var.node_configs) - name = "multichain-partner-mainnet-https-rule-${count.index}" - target = google_compute_target_https_proxy.default_https[count.index].id - port_range = "443" - ip_protocol = "TCP" + count = length(var.node_configs) + name = "multichain-partner-mainnet-https-rule-${count.index}" + target = google_compute_target_https_proxy.default_https[count.index].id + port_range = "443" + ip_protocol = "TCP" load_balancing_scheme = "EXTERNAL" - ip_address = google_compute_global_address.external_ips[count.index].address + ip_address = google_compute_global_address.external_ips[count.index].address } resource "google_compute_target_http_proxy" "default" { - count = length(var.node_configs) + count = length(var.node_configs) name = "multichain-partner-mainnet-http-target-proxy-${count.index}" description = "a description" url_map = google_compute_url_map.redirect_default[count.index].id } resource "google_compute_target_https_proxy" "default_https" { - count = length(var.node_configs) - name = "multichain-partner-mainnet-https-target-proxy-${count.index}" - description = "a description" - ssl_certificates = [ google_compute_managed_ssl_certificate.mainnet_ssl[count.index].self_link ] - url_map = google_compute_url_map.default[count.index].id + count = length(var.node_configs) + name = "multichain-partner-mainnet-https-target-proxy-${count.index}" + description = "a description" + ssl_certificates = [google_compute_managed_ssl_certificate.mainnet_ssl[count.index].self_link] + url_map = google_compute_url_map.default[count.index].id } resource "google_compute_url_map" "default" { @@ -198,8 +198,8 @@ resource "google_compute_url_map" "default" { } resource "google_compute_url_map" "redirect_default" { - count = length(var.node_configs) - name = "multichain-partner-mainnet-redirect-url-map-${count.index}" + count = length(var.node_configs) + name = "multichain-partner-mainnet-redirect-url-map-${count.index}" default_url_redirect { strip_query = false https_redirect = true @@ -230,15 +230,15 @@ resource "google_compute_instance_group" "multichain_group" { } resource "google_compute_firewall" "app_port" { - name = "allow-multichain-healthcheck-access" + name = "allow-multichain-healthcheck-access" network = var.network - source_ranges = [ "130.211.0.0/22", "35.191.0.0/16" ] - source_tags = [ "multichain" ] + source_ranges = ["130.211.0.0/22", "35.191.0.0/16"] + source_tags = ["multichain"] allow { protocol = "tcp" - ports = [ "80", "3000" ] + ports = ["80", "3000"] } -} \ No newline at end of file +} diff --git a/infra/partner-mainnet/variables.tf b/infra/partner-mainnet/variables.tf index b3e980a66..e80b224ad 100644 --- a/infra/partner-mainnet/variables.tf +++ b/infra/partner-mainnet/variables.tf @@ -43,8 +43,8 @@ variable "network" { variable "additional_metadata" { type = map(any) description = "Additional metadata to attach to the instance" - default = { - cos-update-strategy: "update_enabled" + default = { + cos-update-strategy : "update_enabled" } } @@ -77,7 +77,7 @@ variable "node_configs" { } variable "env" { - type = string + type = string default = "mainnet" } @@ -88,19 +88,19 @@ variable "static_env" { })) default = [ { - name = "MPC_RECOVERY_NEAR_RPC" + name = "MPC_NEAR_RPC" value = "https://rpc.mainnet.near.org" }, { - name = "MPC_RECOVERY_CONTRACT_ID" + name = "MPC_CONTRACT_ID" value = "v2.multichain-mpc.testnet" }, { - name = "MPC_RECOVERY_INDEXER_S3_BUCKET" + name = "MPC_INDEXER_S3_BUCKET" value = "near-lake-data-mainnet" }, { - name = "MPC_RECOVERY_INDEXER_START_BLOCK_HEIGHT" + name = "MPC_INDEXER_START_BLOCK_HEIGHT" value = 124092099 }, { @@ -108,11 +108,11 @@ variable "static_env" { value = "eu-central-1" }, { - name = "MPC_RECOVERY_GCP_PROJECT_ID" + name = "MPC_GCP_PROJECT_ID" value = "" }, { - name = "MPC_RECOVERY_WEB_PORT" + name = "MPC_WEB_PORT" value = "3000" }, { @@ -120,17 +120,17 @@ variable "static_env" { value = "mpc_recovery_node=debug" }, { - name = "MPC_RECOVERY_INDEXER_S3_REGION" + name = "MPC_INDEXER_S3_REGION" value = "eu-central-1" } ] } variable "create_network" { - default = false + default = false description = "Do you want to create a new VPC network (true) or use default GCP network (false)?" } variable "domain" { description = "DNS name for your node" -} \ No newline at end of file +} diff --git a/infra/partner-testnet/main.tf b/infra/partner-testnet/main.tf index 41826cd30..46af03079 100644 --- a/infra/partner-testnet/main.tf +++ b/infra/partner-testnet/main.tf @@ -16,27 +16,27 @@ module "gce-container" { env = concat(var.static_env, [ { - name = "MPC_RECOVERY_NODE_ID" + name = "MPC_NODE_ID" value = "${count.index}" }, { - name = "MPC_RECOVERY_ACCOUNT_ID" + name = "MPC_ACCOUNT_ID" value = var.node_configs["${count.index}"].account }, { - name = "MPC_RECOVERY_CIPHER_PK" + name = "MPC_CIPHER_PK" value = var.node_configs["${count.index}"].cipher_pk }, { - name = "MPC_RECOVERY_ACCOUNT_SK" + name = "MPC_ACCOUNT_SK" value = data.google_secret_manager_secret_version.account_sk_secret_id[count.index].secret_data }, { - name = "MPC_RECOVERY_CIPHER_SK" + name = "MPC_CIPHER_SK" value = data.google_secret_manager_secret_version.cipher_sk_secret_id[count.index].secret_data }, { - name = "MPC_RECOVERY_SIGN_SK" + name = "MPC_SIGN_SK" value = data.google_secret_manager_secret_version.sign_sk_secret_id[count.index] != null ? data.google_secret_manager_secret_version.sign_sk_secret_id[count.index].secret_data : data.google_secret_manager_secret_version.account_sk_secret_id[count.index].secret_data }, { @@ -48,15 +48,15 @@ module "gce-container" { value = data.google_secret_manager_secret_version.aws_secret_key_secret_id.secret_data }, { - name = "MPC_RECOVERY_LOCAL_ADDRESS" + name = "MPC_LOCAL_ADDRESS" value = "http://${google_compute_global_address.external_ips[count.index].address}" }, { - name = "MPC_RECOVERY_SK_SHARE_SECRET_ID" + name = "MPC_SK_SHARE_SECRET_ID" value = var.node_configs["${count.index}"].sk_share_secret_id }, { - name = "MPC_RECOVERY_ENV", + name = "MPC_ENV", value = var.env } ]) @@ -70,17 +70,17 @@ resource "google_service_account" "service_account" { resource "google_project_iam_binding" "sa-roles" { for_each = toset([ - "roles/datastore.user", - "roles/secretmanager.admin", - "roles/storage.objectAdmin", - "roles/iam.serviceAccountAdmin", + "roles/datastore.user", + "roles/secretmanager.admin", + "roles/storage.objectAdmin", + "roles/iam.serviceAccountAdmin", ]) role = each.key members = [ "serviceAccount:${google_service_account.service_account.email}" - ] - project = var.project_id + ] + project = var.project_id } resource "google_compute_global_address" "external_ips" { @@ -144,16 +144,16 @@ resource "google_compute_health_check" "multichain_healthcheck" { } resource "google_compute_global_forwarding_rule" "default" { - count = length(var.node_configs) - name = "multichain-partner-rule-${count.index}" - target = google_compute_target_http_proxy.default[count.index].id - port_range = "80" + count = length(var.node_configs) + name = "multichain-partner-rule-${count.index}" + target = google_compute_target_http_proxy.default[count.index].id + port_range = "80" load_balancing_scheme = "EXTERNAL" - ip_address = google_compute_global_address.external_ips[count.index].address + ip_address = google_compute_global_address.external_ips[count.index].address } resource "google_compute_target_http_proxy" "default" { - count = length(var.node_configs) + count = length(var.node_configs) name = "multichain-partner-target-proxy-${count.index}" description = "a description" url_map = google_compute_url_map.default[count.index].id @@ -188,15 +188,15 @@ resource "google_compute_instance_group" "multichain_group" { } resource "google_compute_firewall" "app_port" { - name = "allow-multichain-healthcheck-access" + name = "allow-multichain-healthcheck-access" network = var.network - source_ranges = [ "130.211.0.0/22", "35.191.0.0/16" ] - source_tags = [ "multichain" ] + source_ranges = ["130.211.0.0/22", "35.191.0.0/16"] + source_tags = ["multichain"] allow { protocol = "tcp" - ports = [ "80", "3000" ] + ports = ["80", "3000"] } -} \ No newline at end of file +} diff --git a/infra/partner-testnet/variables.tf b/infra/partner-testnet/variables.tf index fdc8cb884..37b54ceeb 100644 --- a/infra/partner-testnet/variables.tf +++ b/infra/partner-testnet/variables.tf @@ -74,7 +74,7 @@ variable "node_configs" { } variable "env" { - type = string + type = string default = "dev" } @@ -85,19 +85,19 @@ variable "static_env" { })) default = [ { - name = "MPC_RECOVERY_NEAR_RPC" + name = "MPC_NEAR_RPC" value = "https://rpc.testnet.near.org" }, { - name = "MPC_RECOVERY_CONTRACT_ID" + name = "MPC_CONTRACT_ID" value = "v2.multichain-mpc.testnet" }, { - name = "MPC_RECOVERY_INDEXER_S3_BUCKET" + name = "MPC_INDEXER_S3_BUCKET" value = "near-lake-data-testnet" }, { - name = "MPC_RECOVERY_INDEXER_START_BLOCK_HEIGHT" + name = "MPC_INDEXER_START_BLOCK_HEIGHT" value = 158767549 }, { @@ -105,11 +105,11 @@ variable "static_env" { value = "eu-central-1" }, { - name = "MPC_RECOVERY_GCP_PROJECT_ID" + name = "MPC_GCP_PROJECT_ID" value = "" }, { - name = "MPC_RECOVERY_WEB_PORT" + name = "MPC_WEB_PORT" value = "3000" }, { @@ -117,13 +117,13 @@ variable "static_env" { value = "mpc_recovery_node=debug" }, { - name = "MPC_RECOVERY_INDEXER_S3_REGION" + name = "MPC_INDEXER_S3_REGION" value = "eu-central-1" } ] } variable "create_network" { - default = false + default = false description = "Do you want to create a new VPC network (true) or use default GCP network (false)?" -} \ No newline at end of file +} From c02b47e2105526169185973247c34dc0c64ba90f Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 21:21:21 -0700 Subject: [PATCH 02/24] Rename mpc-recovery-node binary to mpc-node --- chain-signatures/Cargo.lock | 2 +- chain-signatures/node/Cargo.toml | 4 ++-- chain-signatures/node/src/main.rs | 4 ++-- infra/modules/multichain/main.tf | 2 +- infra/multichain-dev/variables.tf | 2 +- infra/multichain-mainnet-dev/variables.tf | 2 +- infra/multichain-testnet/variables.tf | 2 +- infra/partner-mainnet/variables.tf | 2 +- infra/partner-testnet/variables.tf | 2 +- .../chain-signatures/src/containers.rs | 14 +++++++------- integration-tests/chain-signatures/src/execute.rs | 4 ++-- integration-tests/chain-signatures/src/lib.rs | 12 ++++++------ integration-tests/chain-signatures/src/local.rs | 8 ++++---- .../chain-signatures/tests/actions/mod.rs | 2 +- .../chain-signatures/tests/actions/wait_for.rs | 2 +- .../chain-signatures/tests/cases/mod.rs | 8 ++++---- .../chain-signatures/tests/cases/nightly.rs | 4 ++-- 17 files changed, 38 insertions(+), 38 deletions(-) diff --git a/chain-signatures/Cargo.lock b/chain-signatures/Cargo.lock index 536419193..9abbb68f4 100644 --- a/chain-signatures/Cargo.lock +++ b/chain-signatures/Cargo.lock @@ -3780,7 +3780,7 @@ dependencies = [ ] [[package]] -name = "mpc-recovery-node" +name = "mpc-node" version = "1.0.0-rc.1" dependencies = [ "anyhow", diff --git a/chain-signatures/node/Cargo.toml b/chain-signatures/node/Cargo.toml index f6a3c370c..f0346c0bc 100644 --- a/chain-signatures/node/Cargo.toml +++ b/chain-signatures/node/Cargo.toml @@ -1,10 +1,10 @@ [package] -name = "mpc-recovery-node" +name = "mpc-node" version = "1.0.0-rc.1" edition = "2021" [[bin]] -name = "mpc-recovery-node" +name = "mpc-node" path = "src/main.rs" [dependencies] diff --git a/chain-signatures/node/src/main.rs b/chain-signatures/node/src/main.rs index 8eaf8249f..e4eb8f24d 100644 --- a/chain-signatures/node/src/main.rs +++ b/chain-signatures/node/src/main.rs @@ -1,6 +1,6 @@ use clap::Parser; -use mpc_recovery_node::cli::Cli; +use mpc_node::cli::Cli; fn main() -> anyhow::Result<()> { - mpc_recovery_node::cli::run(Cli::parse()) + mpc_node::cli::run(Cli::parse()) } diff --git a/infra/modules/multichain/main.tf b/infra/modules/multichain/main.tf index c7dad4678..91b0dbc1f 100644 --- a/infra/modules/multichain/main.tf +++ b/infra/modules/multichain/main.tf @@ -132,7 +132,7 @@ resource "google_cloud_run_v2_service" "node" { } env { name = "RUST_LOG" - value = "mpc_recovery_node=debug" + value = "mpc_node=debug" } ports { diff --git a/infra/multichain-dev/variables.tf b/infra/multichain-dev/variables.tf index a0b5912ce..7c03d0926 100644 --- a/infra/multichain-dev/variables.tf +++ b/infra/multichain-dev/variables.tf @@ -115,7 +115,7 @@ variable "static_env" { }, { name = "RUST_LOG" - value = "mpc_recovery_node=debug" + value = "mpc_node=debug" }, { name = "MPC_INDEXER_S3_REGION" diff --git a/infra/multichain-mainnet-dev/variables.tf b/infra/multichain-mainnet-dev/variables.tf index 780991b8f..5cb9639cb 100644 --- a/infra/multichain-mainnet-dev/variables.tf +++ b/infra/multichain-mainnet-dev/variables.tf @@ -116,7 +116,7 @@ variable "static_env" { }, { name = "RUST_LOG" - value = "mpc_recovery_node=debug" + value = "mpc_node=debug" }, { name = "MPC_INDEXER_S3_REGION" diff --git a/infra/multichain-testnet/variables.tf b/infra/multichain-testnet/variables.tf index 952833ad7..e03a96cc0 100644 --- a/infra/multichain-testnet/variables.tf +++ b/infra/multichain-testnet/variables.tf @@ -110,7 +110,7 @@ variable "static_env" { }, { name = "RUST_LOG" - value = "mpc_recovery_node=debug" + value = "mpc_node=debug" }, { name = "MPC_INDEXER_S3_REGION" diff --git a/infra/partner-mainnet/variables.tf b/infra/partner-mainnet/variables.tf index e80b224ad..49e152049 100644 --- a/infra/partner-mainnet/variables.tf +++ b/infra/partner-mainnet/variables.tf @@ -117,7 +117,7 @@ variable "static_env" { }, { name = "RUST_LOG" - value = "mpc_recovery_node=debug" + value = "mpc_node=debug" }, { name = "MPC_INDEXER_S3_REGION" diff --git a/infra/partner-testnet/variables.tf b/infra/partner-testnet/variables.tf index 37b54ceeb..81bdd2bd7 100644 --- a/infra/partner-testnet/variables.tf +++ b/infra/partner-testnet/variables.tf @@ -114,7 +114,7 @@ variable "static_env" { }, { name = "RUST_LOG" - value = "mpc_recovery_node=debug" + value = "mpc_node=debug" }, { name = "MPC_INDEXER_S3_REGION" diff --git a/integration-tests/chain-signatures/src/containers.rs b/integration-tests/chain-signatures/src/containers.rs index c7b3bd73d..c48592c19 100644 --- a/integration-tests/chain-signatures/src/containers.rs +++ b/integration-tests/chain-signatures/src/containers.rs @@ -65,13 +65,13 @@ impl<'a> Node<'a> { ); LakeIndexer::populate_proxy(&proxy_name, true, &rpc_address_proxied, &near_rpc).await?; - let indexer_options = mpc_recovery_node::indexer::Options { + let indexer_options = mpc_node::indexer::Options { s3_bucket: ctx.localstack.s3_bucket.clone(), s3_region: ctx.localstack.s3_region.clone(), s3_url: Some(ctx.localstack.s3_host_address.clone()), start_block_height: 0, }; - let args = mpc_recovery_node::cli::Cli::Start { + let args = mpc_node::cli::Cli::Start { near_rpc: rpc_address_proxied.clone(), mpc_contract_id: ctx.mpc_contract.id().clone(), account_id: account_id.clone(), @@ -91,10 +91,10 @@ impl<'a> Node<'a> { max_presignatures: cfg.presig_cfg.max_presignatures, } .into_str_args(); - let image: GenericImage = GenericImage::new("near/mpc-recovery-node", "latest") + let image: GenericImage = GenericImage::new("near/mpc-node", "latest") .with_wait_for(WaitFor::Nothing) .with_exposed_port(Self::CONTAINER_PORT) - .with_env_var("RUST_LOG", "mpc_recovery_node=DEBUG") + .with_env_var("RUST_LOG", "mpc_node=DEBUG") .with_env_var("RUST_BACKTRACE", "1"); let image: RunnableImage = (image, args).into(); let image = image.with_network(&ctx.docker_network); @@ -152,7 +152,7 @@ impl<'a> Node<'a> { let storage_options = ctx.storage_options.clone(); let near_rpc = config.near_rpc; let mpc_contract_id = ctx.mpc_contract.id().clone(); - let indexer_options = mpc_recovery_node::indexer::Options { + let indexer_options = mpc_node::indexer::Options { s3_bucket: ctx.localstack.s3_bucket.clone(), s3_region: ctx.localstack.s3_region.clone(), s3_url: Some(ctx.localstack.s3_host_address.clone()), @@ -160,7 +160,7 @@ impl<'a> Node<'a> { }; let sign_sk = near_crypto::SecretKey::from_seed(near_crypto::KeyType::ED25519, "integration-test"); - let args = mpc_recovery_node::cli::Cli::Start { + let args = mpc_node::cli::Cli::Start { near_rpc: near_rpc.clone(), mpc_contract_id: mpc_contract_id.clone(), account_id: account_id.clone(), @@ -183,7 +183,7 @@ impl<'a> Node<'a> { let image: GenericImage = GenericImage::new("near/mpc-recovery-node", "latest") .with_wait_for(WaitFor::Nothing) .with_exposed_port(Self::CONTAINER_PORT) - .with_env_var("RUST_LOG", "mpc_recovery_node=DEBUG") + .with_env_var("RUST_LOG", "mpc_node=DEBUG") .with_env_var("RUST_BACKTRACE", "1"); let image: RunnableImage = (image, args).into(); let image = image.with_network(&ctx.docker_network); diff --git a/integration-tests/chain-signatures/src/execute.rs b/integration-tests/chain-signatures/src/execute.rs index cb0dd4dea..b7915090b 100644 --- a/integration-tests/chain-signatures/src/execute.rs +++ b/integration-tests/chain-signatures/src/execute.rs @@ -27,14 +27,14 @@ pub fn executable(release: bool, executable: &str) -> Option pub fn spawn_multichain( release: bool, node: &str, - cli: mpc_recovery_node::cli::Cli, + cli: mpc_node::cli::Cli, ) -> anyhow::Result { let executable = executable(release, PACKAGE_MULTICHAIN) .with_context(|| format!("could not find target dir while starting {node} node"))?; async_process::Command::new(&executable) .args(cli.into_str_args()) - .env("RUST_LOG", "mpc_recovery_node=INFO") + .env("RUST_LOG", "mpc_node=INFO") .envs(std::env::vars()) .stdout(async_process::Stdio::inherit()) .stderr(async_process::Stdio::inherit()) diff --git a/integration-tests/chain-signatures/src/lib.rs b/integration-tests/chain-signatures/src/lib.rs index c6b2ef7df..bf5fac159 100644 --- a/integration-tests/chain-signatures/src/lib.rs +++ b/integration-tests/chain-signatures/src/lib.rs @@ -13,11 +13,11 @@ use anyhow::Context as _; use bollard::exec::{CreateExecOptions, StartExecResults}; use futures::StreamExt; use mpc_contract::primitives::CandidateInfo; -use mpc_recovery_node::gcp::GcpService; -use mpc_recovery_node::protocol::presignature::PresignatureConfig; -use mpc_recovery_node::protocol::triple::TripleConfig; -use mpc_recovery_node::storage; -use mpc_recovery_node::storage::triple_storage::TripleNodeStorageBox; +use mpc_node::gcp::GcpService; +use mpc_node::protocol::presignature::PresignatureConfig; +use mpc_node::protocol::triple::TripleConfig; +use mpc_node::storage; +use mpc_node::storage::triple_storage::TripleNodeStorageBox; use near_crypto::KeyFile; use near_workspaces::network::{Sandbox, ValidatorKey}; use near_workspaces::types::SecretKey; @@ -278,7 +278,7 @@ pub async fn setup(docker_client: &DockerClient) -> anyhow::Result> crate::containers::Datastore::run(docker_client, docker_network, gcp_project_id).await?; let sk_share_local_path = "multichain-integration-secret-manager".to_string(); - let storage_options = mpc_recovery_node::storage::Options { + let storage_options = mpc_node::storage::Options { env: "local-test".to_string(), gcp_project_id: "multichain-integration".to_string(), sk_share_secret_id: None, diff --git a/integration-tests/chain-signatures/src/local.rs b/integration-tests/chain-signatures/src/local.rs index daac9ce44..c2967a53a 100644 --- a/integration-tests/chain-signatures/src/local.rs +++ b/integration-tests/chain-signatures/src/local.rs @@ -44,7 +44,7 @@ impl Node { let sign_sk = near_crypto::SecretKey::from_seed(near_crypto::KeyType::ED25519, "integration-test"); - let indexer_options = mpc_recovery_node::indexer::Options { + let indexer_options = mpc_node::indexer::Options { s3_bucket: ctx.localstack.s3_bucket.clone(), s3_region: ctx.localstack.s3_region.clone(), s3_url: Some(ctx.localstack.s3_host_address.clone()), @@ -65,7 +65,7 @@ impl Node { LakeIndexer::populate_proxy(&proxy_name, true, &rpc_address_proxied, &near_rpc).await?; let mpc_contract_id = ctx.mpc_contract.id().clone(); - let cli = mpc_recovery_node::cli::Cli::Start { + let cli = mpc_node::cli::Cli::Start { near_rpc: rpc_address_proxied.clone(), mpc_contract_id: mpc_contract_id.clone(), account_id: account_id.clone(), @@ -113,7 +113,7 @@ impl Node { let account_id = config.account_id; let account_sk = config.account_sk; let storage_options = ctx.storage_options.clone(); - let indexer_options = mpc_recovery_node::indexer::Options { + let indexer_options = mpc_node::indexer::Options { s3_bucket: ctx.localstack.s3_bucket.clone(), s3_region: ctx.localstack.s3_region.clone(), s3_url: Some(ctx.localstack.s3_host_address.clone()), @@ -123,7 +123,7 @@ impl Node { near_crypto::SecretKey::from_seed(near_crypto::KeyType::ED25519, "integration-test"); let near_rpc = config.near_rpc; let mpc_contract_id = ctx.mpc_contract.id().clone(); - let cli = mpc_recovery_node::cli::Cli::Start { + let cli = mpc_node::cli::Cli::Start { near_rpc: near_rpc.clone(), mpc_contract_id: mpc_contract_id.clone(), account_id: account_id.clone(), diff --git a/integration-tests/chain-signatures/tests/actions/mod.rs b/integration-tests/chain-signatures/tests/actions/mod.rs index 00f0db451..1ea890256 100644 --- a/integration-tests/chain-signatures/tests/actions/mod.rs +++ b/integration-tests/chain-signatures/tests/actions/mod.rs @@ -17,7 +17,7 @@ use mpc_contract::errors; use mpc_contract::primitives::SignRequest; use mpc_contract::primitives::SignatureRequest; use mpc_contract::RunningContractState; -use mpc_recovery_node::kdf::into_eth_sig; +use mpc_node::kdf::into_eth_sig; use near_crypto::InMemorySigner; use near_jsonrpc_client::methods::broadcast_tx_async::RpcBroadcastTxAsyncRequest; use near_lake_primitives::CryptoHash; diff --git a/integration-tests/chain-signatures/tests/actions/wait_for.rs b/integration-tests/chain-signatures/tests/actions/wait_for.rs index 87c62b234..3238ac50d 100644 --- a/integration-tests/chain-signatures/tests/actions/wait_for.rs +++ b/integration-tests/chain-signatures/tests/actions/wait_for.rs @@ -11,7 +11,7 @@ use crypto_shared::SignatureResponse; use k256::Secp256k1; use mpc_contract::ProtocolContractState; use mpc_contract::RunningContractState; -use mpc_recovery_node::web::StateView; +use mpc_node::web::StateView; use near_jsonrpc_client::methods::tx::RpcTransactionStatusRequest; use near_jsonrpc_client::methods::tx::TransactionInfo; use near_lake_primitives::CryptoHash; diff --git a/integration-tests/chain-signatures/tests/cases/mod.rs b/integration-tests/chain-signatures/tests/cases/mod.rs index 914547123..2613e3e4c 100644 --- a/integration-tests/chain-signatures/tests/cases/mod.rs +++ b/integration-tests/chain-signatures/tests/cases/mod.rs @@ -7,10 +7,10 @@ use crypto_shared::{self, derive_epsilon, derive_key, x_coordinate, ScalarExt}; use integration_tests_chain_signatures::containers::{self, DockerClient}; use integration_tests_chain_signatures::MultichainConfig; use k256::elliptic_curve::point::AffineCoordinates; -use mpc_recovery_node::kdf::into_eth_sig; -use mpc_recovery_node::test_utils; -use mpc_recovery_node::types::LatestBlockHeight; -use mpc_recovery_node::util::NearPublicKeyExt; +use mpc_node::kdf::into_eth_sig; +use mpc_node::test_utils; +use mpc_node::types::LatestBlockHeight; +use mpc_node::util::NearPublicKeyExt; use test_log::test; pub mod nightly; diff --git a/integration-tests/chain-signatures/tests/cases/nightly.rs b/integration-tests/chain-signatures/tests/cases/nightly.rs index 568f0239c..1f44ef3f5 100644 --- a/integration-tests/chain-signatures/tests/cases/nightly.rs +++ b/integration-tests/chain-signatures/tests/cases/nightly.rs @@ -1,6 +1,6 @@ use integration_tests_chain_signatures::MultichainConfig; -use mpc_recovery_node::protocol::presignature::PresignatureConfig; -use mpc_recovery_node::protocol::triple::TripleConfig; +use mpc_node::protocol::presignature::PresignatureConfig; +use mpc_node::protocol::triple::TripleConfig; use test_log::test; use crate::actions::{self, wait_for}; From cf59bf2d740efc5701bf07e6eb4a927bbc7671e6 Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 22:14:14 -0700 Subject: [PATCH 03/24] Rename some forgotten binary names --- .github/workflows/multichain-integration.yml | 2 +- .github/workflows/multichain-nightly.yml | 2 +- Dockerfile.multichain | 6 +++--- integration-tests/chain-signatures/Cargo.lock | 4 ++-- integration-tests/chain-signatures/Cargo.toml | 2 +- integration-tests/chain-signatures/build.rs | 2 +- integration-tests/chain-signatures/src/containers.rs | 2 +- integration-tests/chain-signatures/src/execute.rs | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/multichain-integration.yml b/.github/workflows/multichain-integration.yml index 0986708b4..d3f5b0cce 100644 --- a/.github/workflows/multichain-integration.yml +++ b/.github/workflows/multichain-integration.yml @@ -86,7 +86,7 @@ jobs: - name: Build Chain-Signatures Node working-directory: ./chain-signatures - run: cargo build -p mpc-recovery-node --release + run: cargo build -p mpc-node --release # Build the tests before actually running them to see how long the tests take to run by itself # instead of including the build time in the test time report on Github. diff --git a/.github/workflows/multichain-nightly.yml b/.github/workflows/multichain-nightly.yml index 5830206c3..e3ccc4ee1 100644 --- a/.github/workflows/multichain-nightly.yml +++ b/.github/workflows/multichain-nightly.yml @@ -97,7 +97,7 @@ jobs: - name: Build Chain-Signatures Node working-directory: ./chain-signatures - run: cargo build -p mpc-recovery-node --release + run: cargo build -p mpc-node --release - name: Build Chain-Signatures Integration Tests working-directory: ./integration-tests/chain-signatures diff --git a/Dockerfile.multichain b/Dockerfile.multichain index ba6546edb..3d02c9d7c 100644 --- a/Dockerfile.multichain +++ b/Dockerfile.multichain @@ -16,12 +16,12 @@ COPY chain-signatures/. . RUN sed -i 's#"keys",##' Cargo.toml RUN sed -i 's#"contract",##' Cargo.toml RUN sed -i 's#target-dir = "../target"#target-dir = "target"#' .cargo/config.toml -RUN cargo build --release --package mpc-recovery-node +RUN cargo build --release --package mpc-node FROM debian:stable-slim as runtime RUN apt-get update && apt-get install --assume-yes libssl-dev ca-certificates curl RUN update-ca-certificates -COPY --from=builder /usr/src/app/target/release/mpc-recovery-node /usr/local/bin/mpc-recovery-node +COPY --from=builder /usr/src/app/target/release/mpc-node /usr/local/bin/mpc-node WORKDIR /usr/local/bin -ENTRYPOINT [ "mpc-recovery-node" ] \ No newline at end of file +ENTRYPOINT [ "mpc-node" ] \ No newline at end of file diff --git a/integration-tests/chain-signatures/Cargo.lock b/integration-tests/chain-signatures/Cargo.lock index 07f73a2e5..a2a62e484 100644 --- a/integration-tests/chain-signatures/Cargo.lock +++ b/integration-tests/chain-signatures/Cargo.lock @@ -3748,7 +3748,7 @@ dependencies = [ "lazy_static", "mpc-contract", "mpc-keys", - "mpc-recovery-node", + "mpc-node", "near-account-id", "near-crypto 0.23.0", "near-fetch", @@ -4263,7 +4263,7 @@ dependencies = [ ] [[package]] -name = "mpc-recovery-node" +name = "mpc-node" version = "1.0.0-rc.1" dependencies = [ "anyhow", diff --git a/integration-tests/chain-signatures/Cargo.toml b/integration-tests/chain-signatures/Cargo.toml index 500592a75..c9cc780b6 100644 --- a/integration-tests/chain-signatures/Cargo.toml +++ b/integration-tests/chain-signatures/Cargo.toml @@ -46,7 +46,7 @@ near-workspaces = { git = "https://github.com/near/near-workspaces-rs", branch = crypto-shared = { path = "../../chain-signatures/crypto-shared" } mpc-contract = { path = "../../chain-signatures/contract" } mpc-keys = { path = "../../chain-signatures/keys" } -mpc-recovery-node = { path = "../../chain-signatures/node" } +mpc-node = { path = "../../chain-signatures/node" } clap = { version = "4.5.4", features = ["derive"] } lazy_static = "1.4.0" diff --git a/integration-tests/chain-signatures/build.rs b/integration-tests/chain-signatures/build.rs index d21995ecc..aca2ccf01 100644 --- a/integration-tests/chain-signatures/build.rs +++ b/integration-tests/chain-signatures/build.rs @@ -4,7 +4,7 @@ use std::{env, fs, io}; use anyhow::Context; use async_process::{Command, ExitStatus, Stdio}; -const PACKAGE_MULTICHAIN: &str = "mpc-recovery-node"; +const PACKAGE_MULTICHAIN: &str = "mpc-node"; const PACKAGE_CONTRACT: &str = "mpc-contract"; const TARGET_CONTRACT: &str = "wasm32-unknown-unknown"; const TARGET_FOLDER: &str = "target"; diff --git a/integration-tests/chain-signatures/src/containers.rs b/integration-tests/chain-signatures/src/containers.rs index c48592c19..acbe04dae 100644 --- a/integration-tests/chain-signatures/src/containers.rs +++ b/integration-tests/chain-signatures/src/containers.rs @@ -180,7 +180,7 @@ impl<'a> Node<'a> { sign_sk: Some(sign_sk), } .into_str_args(); - let image: GenericImage = GenericImage::new("near/mpc-recovery-node", "latest") + let image: GenericImage = GenericImage::new("near/mpc-node", "latest") .with_wait_for(WaitFor::Nothing) .with_exposed_port(Self::CONTAINER_PORT) .with_env_var("RUST_LOG", "mpc_node=DEBUG") diff --git a/integration-tests/chain-signatures/src/execute.rs b/integration-tests/chain-signatures/src/execute.rs index b7915090b..030f5ff3a 100644 --- a/integration-tests/chain-signatures/src/execute.rs +++ b/integration-tests/chain-signatures/src/execute.rs @@ -1,7 +1,7 @@ use anyhow::Context; use async_process::Child; -const PACKAGE_MULTICHAIN: &str = "mpc-recovery-node"; +const PACKAGE_MULTICHAIN: &str = "mpc-node"; pub fn target_dir() -> Option { let mut out_dir = std::path::Path::new(std::env!("OUT_DIR")); From c02663ae72535ffbec0425682b11596c03dd1211 Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 12:23:05 -0700 Subject: [PATCH 04/24] Made update methods us MpcContractError --- chain-signatures/contract/src/lib.rs | 52 ++++++++++++++---------- chain-signatures/contract/tests/tests.rs | 12 ++++-- 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/chain-signatures/contract/src/lib.rs b/chain-signatures/contract/src/lib.rs index f094153f6..0de35f7c4 100644 --- a/chain-signatures/contract/src/lib.rs +++ b/chain-signatures/contract/src/lib.rs @@ -501,12 +501,15 @@ impl VersionedMpcContract { Ok(true) } else { Err(MpcContractError::VoteError( - VoteError::UnexpectedProtocolState("Running".to_string()), + VoteError::UnexpectedProtocolState("Running: invalid epoch".to_string()), )) } } - _ => Err(MpcContractError::VoteError( - VoteError::UnexpectedProtocolState("Running".to_string()), + ProtocolContractState::NotInitialized => Err(MpcContractError::VoteError( + VoteError::UnexpectedProtocolState("NotInitialized".to_string()), + )), + ProtocolContractState::Initializing(_) => Err(MpcContractError::VoteError( + VoteError::UnexpectedProtocolState("Initializing".to_string()), )), } } @@ -519,40 +522,30 @@ impl VersionedMpcContract { &mut self, code: Option>, config: Option, - ) -> Result { + ) -> Result { // Only voters can propose updates: self.voter()?; let Some(id) = self.proposed_updates().propose(code, config) else { - return Err(VoteError::Unexpected( + return Err(MpcContractError::from(VoteError::Unexpected( "cannot propose update due to incorrect parameters".into(), - )); + ))); }; - env::log_str(&format!("id={id:?}")); Ok(id) } /// Vote for a proposed update given the [`UpdateId`] of the update. /// - /// Returns Ok(true) if the amount of participants surpassed the threshold and the update was executed. + /// Returns Ok(true) if the amount of voters surpassed the threshold and the update was executed. + /// Returns Ok(false) if the amount of voters did not surpass the threshold. Returns Err if the update + /// was not found or if the voter is not a participant in the protocol. #[handle_result] pub fn vote_update(&mut self, id: UpdateId) -> Result { - let threshold = match self { - Self::V0(contract) => match &contract.protocol_state { - ProtocolContractState::Running(state) => state.threshold, - ProtocolContractState::Resharing(state) => state.threshold, - _ => { - return Err(MpcContractError::VoteError( - VoteError::UnexpectedProtocolState("Initialized or NotInitialized".into()), - )) - } - }, - }; - + let threshold = self.threshold()?; let voter = self.voter()?; let Some(votes) = self.proposed_updates().vote(&id, voter) else { - return Err(MpcContractError::VoteError(VoteError::UpdateNotFound)); + return Err(MpcContractError::from(VoteError::UpdateNotFound)); }; // Not enough votes, wait for more. @@ -564,7 +557,7 @@ impl VersionedMpcContract { self.proposed_updates() .do_update(&id, "update_config", UPDATE_CONFIG_GAS) else { - return Err(MpcContractError::VoteError(VoteError::UpdateNotFound)); + return Err(MpcContractError::from(VoteError::UpdateNotFound)); }; Ok(true) @@ -772,12 +765,27 @@ impl VersionedMpcContract { } } + fn threshold(&self) -> Result { + match self { + Self::V0(contract) => match &contract.protocol_state { + ProtocolContractState::Initializing(state) => Ok(state.threshold), + ProtocolContractState::Running(state) => Ok(state.threshold), + ProtocolContractState::Resharing(state) => Ok(state.threshold), + ProtocolContractState::NotInitialized => { + Err(VoteError::UnexpectedProtocolState("NotInitialized".into())) + } + }, + } + } + fn proposed_updates(&mut self) -> &mut ProposedUpdates { match self { Self::V0(contract) => &mut contract.proposed_updates, } } + /// Get our own account id as a voter. Check to see if we are a participant in the protocol. + /// If we are not a participant, return an error. fn voter(&self) -> Result { let voter = env::signer_account_id(); match self { diff --git a/chain-signatures/contract/tests/tests.rs b/chain-signatures/contract/tests/tests.rs index 092ddd158..54b8f4227 100644 --- a/chain-signatures/contract/tests/tests.rs +++ b/chain-signatures/contract/tests/tests.rs @@ -9,7 +9,7 @@ use k256::elliptic_curve::point::DecompressPoint; use k256::elliptic_curve::sec1::ToEncodedPoint; use k256::{AffinePoint, FieldBytes, Scalar, Secp256k1}; use mpc_contract::config::{min_to_ms, Config}; -use mpc_contract::errors; +use mpc_contract::errors::{self, MpcContractError}; use mpc_contract::primitives::{ CandidateInfo, ParticipantInfo, Participants, SignRequest, SignatureRequest, }; @@ -407,17 +407,21 @@ async fn test_contract_propose_update() { } async fn test_propose_update_config(contract: &Contract, accounts: &[Account]) { - // contract should not be able to propose updates unless its apart of the participant/voter set. + // contract should not be able to propose updates unless it's a part of the participant/voter set. let execution = contract .call("propose_update") .args_json(serde_json::json!({ - "contract": vec![1, 2, 3], + "code": vec![1, 2, 3], })) .transact() .await .unwrap(); dbg!(&execution); - assert!(execution.is_failure()); + assert!(execution + .into_result() + .unwrap_err() + .to_string() + .contains(&MpcContractError::from(errors::VoteError::VoterNotParticipant).to_string())); // have each participant propose a new update: let new_config = Config { From 54044b8f4aeee8c24e22b22f68c7fb137bccbda7 Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 12:23:27 -0700 Subject: [PATCH 05/24] Made proposed updates more space efficient --- chain-signatures/contract/src/update.rs | 48 ++++++++++++++++--------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/chain-signatures/contract/src/update.rs b/chain-signatures/contract/src/update.rs index f7eb977e8..2a58c988d 100644 --- a/chain-signatures/contract/src/update.rs +++ b/chain-signatures/contract/src/update.rs @@ -10,6 +10,7 @@ use near_sdk::{env, AccountId, Gas, NearToken, Promise}; #[derive( Copy, Clone, + Default, Debug, BorshDeserialize, BorshSerialize, @@ -23,6 +24,14 @@ use near_sdk::{env, AccountId, Gas, NearToken, Promise}; )] pub struct UpdateId(pub(crate) u64); +impl UpdateId { + pub fn next(&mut self) -> Self { + let id = self.0; + self.0 += 1; + Self(id) + } +} + impl From for UpdateId { fn from(id: u64) -> Self { Self(id) @@ -35,11 +44,16 @@ pub enum Update { Contract(Vec), } +#[derive(Debug, BorshSerialize, BorshDeserialize)] +struct UpdateEntry { + updates: Vec, + votes: HashSet, +} + #[derive(Default, Debug, BorshSerialize, BorshDeserialize)] pub struct ProposedUpdates { - updates: HashMap>, - votes: HashMap>, - next_id: u64, + entries: HashMap, + next_id: UpdateId, } impl ProposedUpdates { @@ -56,11 +70,14 @@ impl ProposedUpdates { (None, None) => return None, }; - let id = UpdateId::from(self.next_id); - self.next_id += 1; - - self.updates.insert(id, updates); - self.votes.insert(id, HashSet::new()); + let id = self.next_id.next(); + self.entries.insert( + id, + UpdateEntry { + updates, + votes: HashSet::new(), + }, + ); Some(id) } @@ -69,21 +86,20 @@ impl ProposedUpdates { /// /// Returns Some(votes) if the given [`UpdateId`] exists, otherwise None. pub fn vote(&mut self, id: &UpdateId, voter: AccountId) -> Option<&HashSet> { - let votes = self.votes.get_mut(id)?; - votes.insert(voter); - Some(votes) + let entry = self.entries.get_mut(id)?; + entry.votes.insert(voter); + Some(&entry.votes) } - pub fn remove(&mut self, id: &UpdateId) -> Option> { - self.votes.remove(id); - self.updates.remove(id) + fn remove(&mut self, id: &UpdateId) -> Option { + self.entries.remove(id) } pub fn do_update(&mut self, id: &UpdateId, config_callback: &str, gas: Gas) -> Option { - let updates = self.remove(id)?; + let entry = self.remove(id)?; let mut promise = Promise::new(env::current_account_id()); - for update in updates { + for update in entry.updates { match update { Update::Config(config) => { promise = promise.function_call( From 6381121bd6194c60a42501cdefb02fcc4900284b Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 12:23:49 -0700 Subject: [PATCH 06/24] Added bytes_used for config and code updates --- chain-signatures/contract/src/update.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/chain-signatures/contract/src/update.rs b/chain-signatures/contract/src/update.rs index 2a58c988d..520300be6 100644 --- a/chain-signatures/contract/src/update.rs +++ b/chain-signatures/contract/src/update.rs @@ -48,6 +48,7 @@ pub enum Update { struct UpdateEntry { updates: Vec, votes: HashSet, + bytes_used: u64, } #[derive(Default, Debug, BorshSerialize, BorshDeserialize)] @@ -61,6 +62,7 @@ impl ProposedUpdates { /// /// Returns Some(UpdateId) if the update was successfully proposed, otherwise None. pub fn propose(&mut self, code: Option>, config: Option) -> Option { + let bytes_used = bytes_used(&code, &config); let updates = match (code, config) { (Some(contract), Some(config)) => { vec![Update::Contract(contract), Update::Config(config)] @@ -76,6 +78,7 @@ impl ProposedUpdates { UpdateEntry { updates, votes: HashSet::new(), + bytes_used, }, ); @@ -115,3 +118,15 @@ impl ProposedUpdates { Some(promise) } } + +fn bytes_used(code: &Option>, config: &Option) -> u64 { + let mut bytes_used = 0; + if let Some(config) = config { + let bytes = serde_json::to_vec(&config).unwrap(); + bytes_used += bytes.len() as u64; + } + if let Some(code) = code { + bytes_used += code.len() as u64; + } + bytes_used +} From a98dd91bb6a6a9540ebec4110c0c6f5c05171aba Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 12:24:13 -0700 Subject: [PATCH 07/24] Removed unnecessary near-rng crate --- chain-signatures/Cargo.lock | 7 ------- chain-signatures/contract/Cargo.toml | 1 - chain-signatures/contract/src/update.rs | 4 ++-- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/chain-signatures/Cargo.lock b/chain-signatures/Cargo.lock index 9abbb68f4..05a6557a0 100644 --- a/chain-signatures/Cargo.lock +++ b/chain-signatures/Cargo.lock @@ -3756,7 +3756,6 @@ dependencies = [ "k256", "near-crypto 0.23.0", "near-gas", - "near-rng", "near-sdk", "near-workspaces", "rand 0.8.5", @@ -4542,12 +4541,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "near-rng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efd376ff92ef9c5ef550f808406056854815f10e046703ae97f61946ef53a12" - [[package]] name = "near-rpc-error-core" version = "0.20.1" diff --git a/chain-signatures/contract/Cargo.toml b/chain-signatures/contract/Cargo.toml index 690a0f1f8..12b80f8d6 100644 --- a/chain-signatures/contract/Cargo.toml +++ b/chain-signatures/contract/Cargo.toml @@ -15,7 +15,6 @@ schemars = "0.8" k256 = { version = "0.13.1", features = ["sha256", "ecdsa", "serde", "arithmetic", "expose-field"] } crypto-shared = { path = "../crypto-shared" } near-gas = { version = "0.2.5", features = ["serde", "borsh", "schemars"] } -near-rng = "0.1.1" thiserror = "1" [dev-dependencies] diff --git a/chain-signatures/contract/src/update.rs b/chain-signatures/contract/src/update.rs index 520300be6..6f8e84846 100644 --- a/chain-signatures/contract/src/update.rs +++ b/chain-signatures/contract/src/update.rs @@ -54,7 +54,7 @@ struct UpdateEntry { #[derive(Default, Debug, BorshSerialize, BorshDeserialize)] pub struct ProposedUpdates { entries: HashMap, - next_id: UpdateId, + generator: UpdateId, } impl ProposedUpdates { @@ -72,7 +72,7 @@ impl ProposedUpdates { (None, None) => return None, }; - let id = self.next_id.next(); + let id = self.generator.next(); self.entries.insert( id, UpdateEntry { From 00847f6fd2dd549decff700f2369a98b45b1ad6b Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 12:49:53 -0700 Subject: [PATCH 08/24] Added deposit to propose_update --- chain-signatures/contract/src/errors.rs | 2 ++ chain-signatures/contract/src/lib.rs | 9 +++++++++ chain-signatures/contract/src/update.rs | 22 +++++++++++++++++----- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/chain-signatures/contract/src/errors.rs b/chain-signatures/contract/src/errors.rs index 3bafdf82a..b09c3802b 100644 --- a/chain-signatures/contract/src/errors.rs +++ b/chain-signatures/contract/src/errors.rs @@ -68,6 +68,8 @@ pub enum VoteError { ParticipantsBelowThreshold, #[error("Update not found.")] UpdateNotFound, + #[error("Attached deposit is lower than required. Attached: {0}, Required: {1}.")] + InsufficientDeposit(u128, u128), #[error("Unexpected protocol state: {0}")] UnexpectedProtocolState(String), #[error("Unexpected: {0}")] diff --git a/chain-signatures/contract/src/lib.rs b/chain-signatures/contract/src/lib.rs index 0de35f7c4..908e55e41 100644 --- a/chain-signatures/contract/src/lib.rs +++ b/chain-signatures/contract/src/lib.rs @@ -526,6 +526,15 @@ impl VersionedMpcContract { // Only voters can propose updates: self.voter()?; + let attached = env::attached_deposit(); + let required = ProposedUpdates::required_deposit(&code, &config); + if attached < required { + return Err(MpcContractError::from(VoteError::InsufficientDeposit( + attached.as_yoctonear(), + required.as_yoctonear(), + ))); + } + let Some(id) = self.proposed_updates().propose(code, config) else { return Err(MpcContractError::from(VoteError::Unexpected( "cannot propose update due to incorrect parameters".into(), diff --git a/chain-signatures/contract/src/update.rs b/chain-signatures/contract/src/update.rs index 6f8e84846..838a1b7ac 100644 --- a/chain-signatures/contract/src/update.rs +++ b/chain-signatures/contract/src/update.rs @@ -48,7 +48,7 @@ pub enum Update { struct UpdateEntry { updates: Vec, votes: HashSet, - bytes_used: u64, + bytes_used: u128, } #[derive(Default, Debug, BorshSerialize, BorshDeserialize)] @@ -58,6 +58,10 @@ pub struct ProposedUpdates { } impl ProposedUpdates { + pub fn required_deposit(code: &Option>, config: &Option) -> NearToken { + required_deposit(bytes_used(&code, &config)) + } + /// Propose an update given the new contract code and/or config. /// /// Returns Some(UpdateId) if the update was successfully proposed, otherwise None. @@ -119,14 +123,22 @@ impl ProposedUpdates { } } -fn bytes_used(code: &Option>, config: &Option) -> u64 { - let mut bytes_used = 0; +fn bytes_used(code: &Option>, config: &Option) -> u128 { + let mut bytes_used = std::mem::size_of::() as u128; + + // Assume a high max of 128 participant votes per update entry. + bytes_used += 128 * std::mem::size_of::() as u128; + if let Some(config) = config { let bytes = serde_json::to_vec(&config).unwrap(); - bytes_used += bytes.len() as u64; + bytes_used += bytes.len() as u128; } if let Some(code) = code { - bytes_used += code.len() as u64; + bytes_used += code.len() as u128; } bytes_used } + +fn required_deposit(bytes_used: u128) -> NearToken { + env::storage_byte_cost().saturating_mul(bytes_used) +} From a5d4cc469caf030769c86e49813cb3f8f865bd0a Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 13:39:08 -0700 Subject: [PATCH 09/24] Make config dynamic for easier changes --- chain-signatures/contract/src/config.rs | 85 +++++++++++++++++++------ chain-signatures/contract/src/state.rs | 2 +- 2 files changed, 67 insertions(+), 20 deletions(-) diff --git a/chain-signatures/contract/src/config.rs b/chain-signatures/contract/src/config.rs index bf910a65e..dab8b67c8 100644 --- a/chain-signatures/contract/src/config.rs +++ b/chain-signatures/contract/src/config.rs @@ -1,30 +1,77 @@ +use std::collections::HashMap; + use borsh::{self, BorshDeserialize, BorshSerialize}; -use serde::{Deserialize, Serialize}; +use near_sdk::serde::{Deserialize, Serialize}; -#[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +#[derive( + Clone, Default, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq, +)] pub struct Config { - /// Timeout for triple generation in milliseconds. - pub triple_timeout: u64, - /// Timeout for presignature generation in milliseconds. - pub presignature_timeout: u64, - /// Timeout for signature generation in milliseconds. - pub signature_timeout: u64, + #[serde(flatten)] + pub entries: HashMap, +} + +impl Config { + pub fn get(&self, key: &str) -> Option<&serde_json::Value> { + let value = self.entries.get(key)?; + Some(&value.0) + } } -impl Default for Config { - fn default() -> Self { - Self { - triple_timeout: min_to_ms(20), - presignature_timeout: secs_to_ms(30), - signature_timeout: secs_to_ms(30), - } +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct DynamicValue(serde_json::Value); + +impl From for DynamicValue { + fn from(value: serde_json::Value) -> Self { + Self(value) } } -pub const fn secs_to_ms(secs: u64) -> u64 { - secs * 1000 +impl BorshDeserialize for DynamicValue { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + let value = serde_json::from_reader(reader) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; + Ok(Self(value)) + } } -pub const fn min_to_ms(min: u64) -> u64 { - min * 60 * 1000 +impl BorshSerialize for DynamicValue { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + serde_json::to_writer(writer, &self.0) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e)) + } +} + +#[cfg(test)] +mod tests { + use crate::config::Config; + + #[test] + fn test_load_config() { + let config_str: serde_json::Value = serde_json::from_str( + r#"{ + "triple_timeout": 20000, + "presignature_timeout": 30000, + "signature_timeout": 30000, + "string": "value", + "integer": 1000 + }"#, + ) + .unwrap(); + + let config_macro = serde_json::json!({ + "triple_timeout": 20000, + "presignature_timeout": 30000, + "signature_timeout": 30000, + "string": "value", + "integer": 1000, + }); + + assert_eq!(config_str, config_macro); + + let config: Config = serde_json::from_value(config_macro).unwrap(); + + assert_eq!(config.get("string").unwrap(), &serde_json::json!("value"),); + assert_eq!(config.get("integer").unwrap(), &serde_json::json!(1000),); + } } diff --git a/chain-signatures/contract/src/state.rs b/chain-signatures/contract/src/state.rs index 5f30978d8..73a9d9573 100644 --- a/chain-signatures/contract/src/state.rs +++ b/chain-signatures/contract/src/state.rs @@ -1,8 +1,8 @@ use std::collections::HashSet; use borsh::{self, BorshDeserialize, BorshSerialize}; +use near_sdk::serde::{Deserialize, Serialize}; use near_sdk::{AccountId, PublicKey}; -use serde::{Deserialize, Serialize}; use crate::primitives::{Candidates, Participants, PkVotes, Votes}; From 31342cc4b79dc2e52338398c5759ea47bf18920e Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 14:18:12 -0700 Subject: [PATCH 10/24] Added proper borsh serialization and payable --- chain-signatures/contract/src/config.rs | 30 ++++++++++++----- chain-signatures/contract/src/lib.rs | 2 +- chain-signatures/contract/tests/tests.rs | 42 +++++++++++++++++------- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/chain-signatures/contract/src/config.rs b/chain-signatures/contract/src/config.rs index dab8b67c8..b4f3cea64 100644 --- a/chain-signatures/contract/src/config.rs +++ b/chain-signatures/contract/src/config.rs @@ -27,19 +27,30 @@ impl From for DynamicValue { } } +impl BorshSerialize for DynamicValue { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + let str = serde_json::to_string(&self.0) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; + + BorshSerialize::serialize(&str, writer) + } +} + impl BorshDeserialize for DynamicValue { fn deserialize_reader(reader: &mut R) -> std::io::Result { - let value = serde_json::from_reader(reader) + let str: String = BorshDeserialize::deserialize_reader(reader)?; + let value = serde_json::from_str(&str) .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; Ok(Self(value)) } } -impl BorshSerialize for DynamicValue { - fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - serde_json::to_writer(writer, &self.0) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e)) - } +pub const fn secs_to_ms(secs: u64) -> u64 { + secs * 1000 +} + +pub const fn min_to_ms(min: u64) -> u64 { + min * 60 * 1000 } #[cfg(test)] @@ -69,9 +80,10 @@ mod tests { assert_eq!(config_str, config_macro); - let config: Config = serde_json::from_value(config_macro).unwrap(); + let config: Option = serde_json::from_value(config_macro).unwrap(); + println!("{config:?}"); - assert_eq!(config.get("string").unwrap(), &serde_json::json!("value"),); - assert_eq!(config.get("integer").unwrap(), &serde_json::json!(1000),); + // assert_eq!(config.get("string").unwrap(), &serde_json::json!("value"),); + // assert_eq!(config.get("integer").unwrap(), &serde_json::json!(1000),); } } diff --git a/chain-signatures/contract/src/lib.rs b/chain-signatures/contract/src/lib.rs index 908e55e41..6b909114a 100644 --- a/chain-signatures/contract/src/lib.rs +++ b/chain-signatures/contract/src/lib.rs @@ -109,7 +109,6 @@ impl VersionedMpcContract { /// To avoid overloading the network with too many requests, /// we ask for a small deposit for each signature request. /// The fee changes based on how busy the network is. - #[allow(unused_variables)] #[handle_result] #[payable] pub fn sign(&mut self, request: SignRequest) -> Result { @@ -517,6 +516,7 @@ impl VersionedMpcContract { /// Propose an update to the contract. [`Update`] are all the possible updates that can be proposed. /// /// returns Some(id) if the proposal was successful, None otherwise + #[payable] #[handle_result] pub fn propose_update( &mut self, diff --git a/chain-signatures/contract/tests/tests.rs b/chain-signatures/contract/tests/tests.rs index 54b8f4227..2314adcab 100644 --- a/chain-signatures/contract/tests/tests.rs +++ b/chain-signatures/contract/tests/tests.rs @@ -21,6 +21,7 @@ use signature::digest::{Digest, FixedOutput}; use signature::DigestSigner; use std::collections::{BTreeMap, HashMap}; +use std::hash::Hash; use std::str::FromStr; const CONTRACT_FILE_PATH: &str = "../../target/wasm32-unknown-unknown/release/mpc_contract.wasm"; @@ -403,7 +404,7 @@ async fn test_contract_propose_update() { dbg!(contract.id()); test_propose_update_config(&contract, &accounts).await; - test_propose_update_contract(&contract, &accounts).await; + // test_propose_update_contract(&contract, &accounts).await; } async fn test_propose_update_config(contract: &Contract, accounts: &[Account]) { @@ -424,28 +425,32 @@ async fn test_propose_update_config(contract: &Contract, accounts: &[Account]) { .contains(&MpcContractError::from(errors::VoteError::VoterNotParticipant).to_string())); // have each participant propose a new update: - let new_config = Config { - triple_timeout: min_to_ms(10), - ..Default::default() - }; + let new_config = serde_json::json!({ + "triple_timeout": min_to_ms(20), + "presignature_timeout": min_to_ms(30), + "signature_timeout": min_to_ms(30), + "string": "value", + "integer": 1000, + }); let mut proposals = Vec::with_capacity(accounts.len()); for account in accounts { - let execution = account + let propose_execution = account .call(contract.id(), "propose_update") .args_json(serde_json::json!({ "config": &new_config, })) + .deposit(NearToken::from_near(1)) .transact() .await .unwrap(); - assert!(execution.is_success()); - dbg!(execution.logs()); - let proposal_id: UpdateId = execution.json().unwrap(); + dbg!(&propose_execution); + assert!(propose_execution.is_success()); + let proposal_id: UpdateId = propose_execution.json().unwrap(); dbg!(&proposal_id); proposals.push(proposal_id); } - let old_config: Config = contract.view("config").await.unwrap().json().unwrap(); + let old_config: serde_json::Value = contract.view("config").await.unwrap().json().unwrap(); let state: mpc_contract::ProtocolContractState = contract.view("state").await.unwrap().json().unwrap(); @@ -477,9 +482,23 @@ async fn test_propose_update_config(contract: &Contract, accounts: &[Account]) { } } // check that the proposal executed since the threshold got changed. - let config: Config = contract.view("config").await.unwrap().json().unwrap(); + let config: serde_json::Value = contract.view("config").await.unwrap().json().unwrap(); assert_ne!(config, old_config); assert_eq!(config, new_config); + + // Check that we can partially set hardcoded configs, while leaving other configs as dynamic values: + #[derive(Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq)] + pub struct LocalConfig { + pub triple_timeout: u64, + pub presignature_timeout: u64, + pub signature_timeout: u64, + + #[serde(flatten)] + other: HashMap, + } + let config: LocalConfig = serde_json::from_value(config).unwrap(); + let new_config: LocalConfig = serde_json::from_value(new_config).unwrap(); + assert_eq!(config, new_config); } async fn test_propose_update_contract(contract: &Contract, accounts: &[Account]) { @@ -494,6 +513,7 @@ async fn test_propose_update_contract(contract: &Contract, accounts: &[Account]) "code": &new_wasm, })) .max_gas() + .deposit(NearToken::from_near(1)) .transact() .await .unwrap(); From 72708105db1984e540a9fa4c084b4f7e663b0dbd Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 14:22:46 -0700 Subject: [PATCH 11/24] Use to_vec instead for config borsh ser --- chain-signatures/contract/src/config.rs | 17 +++++++---------- chain-signatures/contract/tests/tests.rs | 2 +- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/chain-signatures/contract/src/config.rs b/chain-signatures/contract/src/config.rs index b4f3cea64..f0d78b400 100644 --- a/chain-signatures/contract/src/config.rs +++ b/chain-signatures/contract/src/config.rs @@ -29,17 +29,16 @@ impl From for DynamicValue { impl BorshSerialize for DynamicValue { fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - let str = serde_json::to_string(&self.0) + let buf = serde_json::to_vec(&self.0) .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; - - BorshSerialize::serialize(&str, writer) + BorshSerialize::serialize(&buf, writer) } } impl BorshDeserialize for DynamicValue { fn deserialize_reader(reader: &mut R) -> std::io::Result { - let str: String = BorshDeserialize::deserialize_reader(reader)?; - let value = serde_json::from_str(&str) + let buf: Vec = BorshDeserialize::deserialize_reader(reader)?; + let value = serde_json::from_slice(&buf) .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; Ok(Self(value)) } @@ -80,10 +79,8 @@ mod tests { assert_eq!(config_str, config_macro); - let config: Option = serde_json::from_value(config_macro).unwrap(); - println!("{config:?}"); - - // assert_eq!(config.get("string").unwrap(), &serde_json::json!("value"),); - // assert_eq!(config.get("integer").unwrap(), &serde_json::json!(1000),); + let config: Config = serde_json::from_value(config_macro).unwrap(); + assert_eq!(config.get("string").unwrap(), &serde_json::json!("value"),); + assert_eq!(config.get("integer").unwrap(), &serde_json::json!(1000),); } } diff --git a/chain-signatures/contract/tests/tests.rs b/chain-signatures/contract/tests/tests.rs index 2314adcab..e841d3a7c 100644 --- a/chain-signatures/contract/tests/tests.rs +++ b/chain-signatures/contract/tests/tests.rs @@ -404,7 +404,7 @@ async fn test_contract_propose_update() { dbg!(contract.id()); test_propose_update_config(&contract, &accounts).await; - // test_propose_update_contract(&contract, &accounts).await; + test_propose_update_contract(&contract, &accounts).await; } async fn test_propose_update_config(contract: &Contract, accounts: &[Account]) { From 41340b61018207f5ba107095c3080b26c68f5431 Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 14:40:29 -0700 Subject: [PATCH 12/24] Update deposit cost --- chain-signatures/contract/tests/tests.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/chain-signatures/contract/tests/tests.rs b/chain-signatures/contract/tests/tests.rs index e841d3a7c..126865903 100644 --- a/chain-signatures/contract/tests/tests.rs +++ b/chain-signatures/contract/tests/tests.rs @@ -439,7 +439,7 @@ async fn test_propose_update_config(contract: &Contract, accounts: &[Account]) { .args_json(serde_json::json!({ "config": &new_config, })) - .deposit(NearToken::from_near(1)) + .deposit(NearToken::from_millinear(100)) .transact() .await .unwrap(); @@ -502,6 +502,7 @@ async fn test_propose_update_config(contract: &Contract, accounts: &[Account]) { } async fn test_propose_update_contract(contract: &Contract, accounts: &[Account]) { + const CONTRACT_DEPLOY: NearToken = NearToken::from_near(8); let state: mpc_contract::ProtocolContractState = contract.view("state").await.unwrap().json().unwrap(); @@ -513,7 +514,7 @@ async fn test_propose_update_contract(contract: &Contract, accounts: &[Account]) "code": &new_wasm, })) .max_gas() - .deposit(NearToken::from_near(1)) + .deposit(CONTRACT_DEPLOY) .transact() .await .unwrap(); From 3858a829f6ac95d1f24c0ef2934f1ef26343140d Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 14:43:01 -0700 Subject: [PATCH 13/24] Clippy --- chain-signatures/contract/src/update.rs | 8 ++++---- chain-signatures/contract/tests/tests.rs | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/chain-signatures/contract/src/update.rs b/chain-signatures/contract/src/update.rs index 838a1b7ac..7afc070a2 100644 --- a/chain-signatures/contract/src/update.rs +++ b/chain-signatures/contract/src/update.rs @@ -25,7 +25,7 @@ use near_sdk::{env, AccountId, Gas, NearToken, Promise}; pub struct UpdateId(pub(crate) u64); impl UpdateId { - pub fn next(&mut self) -> Self { + pub fn generate(&mut self) -> Self { let id = self.0; self.0 += 1; Self(id) @@ -54,12 +54,12 @@ struct UpdateEntry { #[derive(Default, Debug, BorshSerialize, BorshDeserialize)] pub struct ProposedUpdates { entries: HashMap, - generator: UpdateId, + id: UpdateId, } impl ProposedUpdates { pub fn required_deposit(code: &Option>, config: &Option) -> NearToken { - required_deposit(bytes_used(&code, &config)) + required_deposit(bytes_used(code, config)) } /// Propose an update given the new contract code and/or config. @@ -76,7 +76,7 @@ impl ProposedUpdates { (None, None) => return None, }; - let id = self.generator.next(); + let id = self.id.generate(); self.entries.insert( id, UpdateEntry { diff --git a/chain-signatures/contract/tests/tests.rs b/chain-signatures/contract/tests/tests.rs index 126865903..fa6dc36a0 100644 --- a/chain-signatures/contract/tests/tests.rs +++ b/chain-signatures/contract/tests/tests.rs @@ -8,7 +8,7 @@ use k256::elliptic_curve::ops::Reduce; use k256::elliptic_curve::point::DecompressPoint; use k256::elliptic_curve::sec1::ToEncodedPoint; use k256::{AffinePoint, FieldBytes, Scalar, Secp256k1}; -use mpc_contract::config::{min_to_ms, Config}; +use mpc_contract::config::min_to_ms; use mpc_contract::errors::{self, MpcContractError}; use mpc_contract::primitives::{ CandidateInfo, ParticipantInfo, Participants, SignRequest, SignatureRequest, @@ -21,7 +21,6 @@ use signature::digest::{Digest, FixedOutput}; use signature::DigestSigner; use std::collections::{BTreeMap, HashMap}; -use std::hash::Hash; use std::str::FromStr; const CONTRACT_FILE_PATH: &str = "../../target/wasm32-unknown-unknown/release/mpc_contract.wasm"; From b213d8e9df78a16f976acc6b0f00b54c4dfa7c77 Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 15:04:54 -0700 Subject: [PATCH 14/24] Added propose_update refund diff and migrate --- chain-signatures/contract/src/errors.rs | 2 ++ chain-signatures/contract/src/lib.rs | 34 ++++++++++++++++++++----- chain-signatures/contract/src/update.rs | 14 +++++++--- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/chain-signatures/contract/src/errors.rs b/chain-signatures/contract/src/errors.rs index b09c3802b..b7b5e118b 100644 --- a/chain-signatures/contract/src/errors.rs +++ b/chain-signatures/contract/src/errors.rs @@ -50,6 +50,8 @@ pub enum PublicKeyError { pub enum InitError { #[error("Threshold cannot be greater than the number of candidates")] ThresholdTooHigh, + #[error("Cannot load in contract due to missing state")] + ContractStateIsMissing, } #[derive(Debug, thiserror::Error)] diff --git a/chain-signatures/contract/src/lib.rs b/chain-signatures/contract/src/lib.rs index 6b909114a..133382417 100644 --- a/chain-signatures/contract/src/lib.rs +++ b/chain-signatures/contract/src/lib.rs @@ -13,8 +13,8 @@ use k256::Scalar; use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize}; use near_sdk::collections::LookupMap; use near_sdk::{ - env, log, near_bindgen, AccountId, CryptoHash, Gas, GasWeight, NearToken, PromiseError, - PublicKey, + env, log, near_bindgen, AccountId, CryptoHash, Gas, GasWeight, NearToken, Promise, + PromiseError, PublicKey, }; use primitives::{ CandidateInfo, Candidates, Participants, PkVotes, SignRequest, SignaturePromiseError, @@ -524,7 +524,7 @@ impl VersionedMpcContract { config: Option, ) -> Result { // Only voters can propose updates: - self.voter()?; + let proposer = self.voter()?; let attached = env::attached_deposit(); let required = ProposedUpdates::required_deposit(&code, &config); @@ -541,6 +541,13 @@ impl VersionedMpcContract { ))); }; + // Refund the difference if the propser attached more than required. + if let Some(diff) = attached.checked_sub(required) { + if diff > NearToken::from_yoctonear(0) { + Promise::new(proposer).transfer(diff); + } + } + Ok(id) } @@ -562,10 +569,7 @@ impl VersionedMpcContract { return Ok(false); } - let Some(_promise) = - self.proposed_updates() - .do_update(&id, "update_config", UPDATE_CONFIG_GAS) - else { + let Some(_promise) = self.proposed_updates().do_update(&id, UPDATE_CONFIG_GAS) else { return Err(MpcContractError::from(VoteError::UpdateNotFound)); }; @@ -636,6 +640,22 @@ impl VersionedMpcContract { })) } + /// This will be called internally by the contract to migrate the state when a new contract + /// is deployed. This function should be changed every time state is changed to do the proper + /// migrate flow. + /// + /// If nothing is changed, then this function will just return the current state. If it fails + /// to read the state, then it will return an error. + #[private] + #[init(ignore_state)] + #[handle_result] + pub fn migrate() -> Result { + let old: MpcContract = env::state_read().ok_or(MpcContractError::InitError( + InitError::ContractStateIsMissing, + ))?; + Ok(VersionedMpcContract::V0(old)) + } + pub fn state(&self) -> &ProtocolContractState { match self { Self::V0(mpc_contract) => &mpc_contract.protocol_state, diff --git a/chain-signatures/contract/src/update.rs b/chain-signatures/contract/src/update.rs index 7afc070a2..9ad8bbf3b 100644 --- a/chain-signatures/contract/src/update.rs +++ b/chain-signatures/contract/src/update.rs @@ -102,7 +102,7 @@ impl ProposedUpdates { self.entries.remove(id) } - pub fn do_update(&mut self, id: &UpdateId, config_callback: &str, gas: Gas) -> Option { + pub fn do_update(&mut self, id: &UpdateId, gas: Gas) -> Option { let entry = self.remove(id)?; let mut promise = Promise::new(env::current_account_id()); @@ -110,13 +110,21 @@ impl ProposedUpdates { match update { Update::Config(config) => { promise = promise.function_call( - config_callback.into(), + "update_config".into(), serde_json::to_vec(&(&config,)).unwrap(), NearToken::from_near(0), gas, ); } - Update::Contract(code) => promise = promise.deploy_contract(code), + Update::Contract(code) => { + // deploy contract then do a `migrate` call to migrate state. + promise = promise.deploy_contract(code).function_call( + "migrate".into(), + Vec::new(), + NearToken::from_near(0), + gas, + ); + } } } Some(promise) From cf17f8afb8e82433812d1f2e4a18066a4b5a9c68 Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 15:46:42 -0700 Subject: [PATCH 15/24] Added additional test case for a contract that fails to migrate --- chain-signatures/contract/tests/tests.rs | 62 ++++++++++++++++++ chain-signatures/res/mpc_test_contract.wasm | Bin 0 -> 23316 bytes .../test-contracts/.cargo/config.toml | 2 + chain-signatures/test-contracts/.gitignore | 2 + chain-signatures/test-contracts/Cargo.toml | 28 ++++++++ chain-signatures/test-contracts/build.sh | 5 ++ chain-signatures/test-contracts/src/lib.rs | 18 +++++ 7 files changed, 117 insertions(+) create mode 100755 chain-signatures/res/mpc_test_contract.wasm create mode 100644 chain-signatures/test-contracts/.cargo/config.toml create mode 100644 chain-signatures/test-contracts/.gitignore create mode 100644 chain-signatures/test-contracts/Cargo.toml create mode 100755 chain-signatures/test-contracts/build.sh create mode 100644 chain-signatures/test-contracts/src/lib.rs diff --git a/chain-signatures/contract/tests/tests.rs b/chain-signatures/contract/tests/tests.rs index fa6dc36a0..8d8e98336 100644 --- a/chain-signatures/contract/tests/tests.rs +++ b/chain-signatures/contract/tests/tests.rs @@ -24,6 +24,7 @@ use std::collections::{BTreeMap, HashMap}; use std::str::FromStr; const CONTRACT_FILE_PATH: &str = "../../target/wasm32-unknown-unknown/release/mpc_contract.wasm"; +const INVALID_CONTRACT: &str = "../../target/wasm32-unknown-unknown/release/mpc_test_contract.wasm"; const PARTICIPANT_LEN: usize = 3; fn candidates(names: Option>) -> HashMap { @@ -404,6 +405,7 @@ async fn test_contract_propose_update() { test_propose_update_config(&contract, &accounts).await; test_propose_update_contract(&contract, &accounts).await; + test_invalid_contract_deploy(&contract, &accounts).await; } async fn test_propose_update_config(contract: &Contract, accounts: &[Account]) { @@ -561,3 +563,63 @@ async fn test_propose_update_contract(contract: &Contract, accounts: &[Account]) let state: mpc_contract::ProtocolContractState = execution.json().unwrap(); dbg!(state); } + +async fn test_invalid_contract_deploy(contract: &Contract, accounts: &[Account]) { + const CONTRACT_DEPLOY: NearToken = NearToken::from_near(1); + let state: mpc_contract::ProtocolContractState = + contract.view("state").await.unwrap().json().unwrap(); + + // Let's propose a contract update instead now. + let new_wasm = std::fs::read(INVALID_CONTRACT).unwrap(); + let execution = accounts[0] + .call(contract.id(), "propose_update") + .args_json(serde_json::json!({ + "code": &new_wasm, + })) + .max_gas() + .deposit(CONTRACT_DEPLOY) + .transact() + .await + .unwrap(); + dbg!(&execution); + assert!(execution.is_success()); + let proposal_id: UpdateId = execution.json().unwrap(); + for (i, voter) in accounts.iter().enumerate() { + let execution = voter + .call(contract.id(), "vote_update") + .args_json(serde_json::json!({ + "id": proposal_id, + })) + .max_gas() + .transact() + .await + .unwrap(); + + if i < 2 { + assert!( + execution.is_success(), + "execution should have succeeded: {state:#?}\n{execution:#?}" + ); + } + + if i == 1 { + dbg!(&execution); + } + } + + // Try calling into state and see if it works after the contract updates with an invalid + // contract. It will fail in `migrate` so a state rollback on the contract code should have + // happened. + let execution = accounts[0] + .call(contract.id(), "state") + .args_json(serde_json::json!({ + "id": proposal_id, + })) + .transact() + .await + .unwrap(); + + dbg!(&execution); + let state: mpc_contract::ProtocolContractState = execution.json().unwrap(); + dbg!(state); +} diff --git a/chain-signatures/res/mpc_test_contract.wasm b/chain-signatures/res/mpc_test_contract.wasm new file mode 100755 index 0000000000000000000000000000000000000000..06f314d1436375cc2e01839a10f3db8b3554e86f GIT binary patch literal 23316 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 LPWO+X=KOyFopFQp literal 0 HcmV?d00001 diff --git a/chain-signatures/test-contracts/.cargo/config.toml b/chain-signatures/test-contracts/.cargo/config.toml new file mode 100644 index 000000000..9766b8111 --- /dev/null +++ b/chain-signatures/test-contracts/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target-dir = "../../target" diff --git a/chain-signatures/test-contracts/.gitignore b/chain-signatures/test-contracts/.gitignore new file mode 100644 index 000000000..76ca40736 --- /dev/null +++ b/chain-signatures/test-contracts/.gitignore @@ -0,0 +1,2 @@ + +Cargo.lock \ No newline at end of file diff --git a/chain-signatures/test-contracts/Cargo.toml b/chain-signatures/test-contracts/Cargo.toml new file mode 100644 index 000000000..5e8936797 --- /dev/null +++ b/chain-signatures/test-contracts/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "mpc-test-contract" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["cdylib", "lib"] + +[profile.release] +codegen-units = 1 +# Tell `rustc` to optimize for small code size. +opt-level = "z" +lto = true +debug = false +panic = "abort" + +[dependencies] +borsh = "1.5.0" +serde = { version = "1", features = ["derive"] } +serde_json = "1" +thiserror = "1" + +near-sdk = { version = "5.2.1", features = ["legacy", "unit-testing"] } +near-gas = { version = "0.2.5", features = ["serde", "borsh", "schemars"] } + +# Need to ignore root workspace +[workspace] diff --git a/chain-signatures/test-contracts/build.sh b/chain-signatures/test-contracts/build.sh new file mode 100755 index 000000000..4368def7b --- /dev/null +++ b/chain-signatures/test-contracts/build.sh @@ -0,0 +1,5 @@ +#!/bin/sh +TARGET="${CARGO_TARGET_DIR:-../../target}" + +cargo build --target wasm32-unknown-unknown --release +cp $TARGET/wasm32-unknown-unknown/release/mpc_test_contract.wasm ../res/ diff --git a/chain-signatures/test-contracts/src/lib.rs b/chain-signatures/test-contracts/src/lib.rs new file mode 100644 index 000000000..c98d0f515 --- /dev/null +++ b/chain-signatures/test-contracts/src/lib.rs @@ -0,0 +1,18 @@ +use near_sdk::{env, near, PanicOnDefault}; + +// use crate::FailureContractExt; + +#[derive(Debug, PanicOnDefault)] +#[near(serializers=[borsh, json], contract_state)] +pub struct FailureContract { + state: String, +} + +#[near] +impl FailureContract { + #[private] + #[init(ignore_state)] + pub fn migrate() -> Self { + env::panic_str("Migrate should rollback state"); + } +} From 81af3fb31072cd01f31b4ea6ad0b1af62133f8ab Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 20:51:53 -0700 Subject: [PATCH 16/24] Update INVALID contract path --- chain-signatures/contract/tests/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain-signatures/contract/tests/tests.rs b/chain-signatures/contract/tests/tests.rs index 8d8e98336..1ff5f8d00 100644 --- a/chain-signatures/contract/tests/tests.rs +++ b/chain-signatures/contract/tests/tests.rs @@ -24,7 +24,7 @@ use std::collections::{BTreeMap, HashMap}; use std::str::FromStr; const CONTRACT_FILE_PATH: &str = "../../target/wasm32-unknown-unknown/release/mpc_contract.wasm"; -const INVALID_CONTRACT: &str = "../../target/wasm32-unknown-unknown/release/mpc_test_contract.wasm"; +const INVALID_CONTRACT: &str = "../res/mpc_test_contract.wasm"; const PARTICIPANT_LEN: usize = 3; fn candidates(names: Option>) -> HashMap { From 8dab958a9130fb8dab775634db07d82310d919fc Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 22:16:41 -0700 Subject: [PATCH 17/24] Made config module --- chain-signatures/contract/src/config/impls.rs | 40 ++++++++++++++++++ .../contract/src/{config.rs => config/mod.rs} | 42 ++----------------- 2 files changed, 44 insertions(+), 38 deletions(-) create mode 100644 chain-signatures/contract/src/config/impls.rs rename chain-signatures/contract/src/{config.rs => config/mod.rs} (56%) diff --git a/chain-signatures/contract/src/config/impls.rs b/chain-signatures/contract/src/config/impls.rs new file mode 100644 index 000000000..d745a431a --- /dev/null +++ b/chain-signatures/contract/src/config/impls.rs @@ -0,0 +1,40 @@ +use borsh::{self, BorshDeserialize, BorshSerialize}; + +use super::{Config, DynamicValue}; + +impl Config { + pub fn get(&self, key: &str) -> Option<&serde_json::Value> { + let value = self.entries.get(key)?; + Some(&value.0) + } +} + +impl From for DynamicValue { + fn from(value: serde_json::Value) -> Self { + Self(value) + } +} +impl BorshSerialize for DynamicValue { + fn serialize(&self, writer: &mut W) -> std::io::Result<()> { + let buf = serde_json::to_vec(&self.0) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; + BorshSerialize::serialize(&buf, writer) + } +} + +impl BorshDeserialize for DynamicValue { + fn deserialize_reader(reader: &mut R) -> std::io::Result { + let buf: Vec = BorshDeserialize::deserialize_reader(reader)?; + let value = serde_json::from_slice(&buf) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; + Ok(Self(value)) + } +} + +pub const fn secs_to_ms(secs: u64) -> u64 { + secs * 1000 +} + +pub const fn min_to_ms(min: u64) -> u64 { + min * 60 * 1000 +} diff --git a/chain-signatures/contract/src/config.rs b/chain-signatures/contract/src/config/mod.rs similarity index 56% rename from chain-signatures/contract/src/config.rs rename to chain-signatures/contract/src/config/mod.rs index f0d78b400..152e9cbba 100644 --- a/chain-signatures/contract/src/config.rs +++ b/chain-signatures/contract/src/config/mod.rs @@ -1,3 +1,7 @@ +mod impls; + +pub use impls::{min_to_ms, secs_to_ms}; + use std::collections::HashMap; use borsh::{self, BorshDeserialize, BorshSerialize}; @@ -11,47 +15,9 @@ pub struct Config { pub entries: HashMap, } -impl Config { - pub fn get(&self, key: &str) -> Option<&serde_json::Value> { - let value = self.entries.get(key)?; - Some(&value.0) - } -} - #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct DynamicValue(serde_json::Value); -impl From for DynamicValue { - fn from(value: serde_json::Value) -> Self { - Self(value) - } -} - -impl BorshSerialize for DynamicValue { - fn serialize(&self, writer: &mut W) -> std::io::Result<()> { - let buf = serde_json::to_vec(&self.0) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; - BorshSerialize::serialize(&buf, writer) - } -} - -impl BorshDeserialize for DynamicValue { - fn deserialize_reader(reader: &mut R) -> std::io::Result { - let buf: Vec = BorshDeserialize::deserialize_reader(reader)?; - let value = serde_json::from_slice(&buf) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; - Ok(Self(value)) - } -} - -pub const fn secs_to_ms(secs: u64) -> u64 { - secs * 1000 -} - -pub const fn min_to_ms(min: u64) -> u64 { - min * 60 * 1000 -} - #[cfg(test)] mod tests { use crate::config::Config; From 2190faf44c6db535d3cfc10a43876bb723de29bb Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 23:44:41 -0700 Subject: [PATCH 18/24] Made config an option that can be initialized from contract --- chain-signatures/contract/src/lib.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/chain-signatures/contract/src/lib.rs b/chain-signatures/contract/src/lib.rs index 133382417..8431b4886 100644 --- a/chain-signatures/contract/src/lib.rs +++ b/chain-signatures/contract/src/lib.rs @@ -87,7 +87,11 @@ impl MpcContract { } } - pub fn init(threshold: usize, candidates: BTreeMap) -> Self { + pub fn init( + threshold: usize, + candidates: BTreeMap, + config: Option, + ) -> Self { MpcContract { protocol_state: ProtocolContractState::Initializing(InitializingContractState { candidates: Candidates { candidates }, @@ -97,7 +101,7 @@ impl MpcContract { pending_requests: LookupMap::new(StorageKey::PendingRequests), request_counter: 0, proposed_updates: ProposedUpdates::default(), - config: Config::default(), + config: config.unwrap_or_else(Config::default), } } } @@ -585,6 +589,7 @@ impl VersionedMpcContract { pub fn init( threshold: usize, candidates: BTreeMap, + config: Option, ) -> Result { log!( "init: signer={}, threshold={}, candidates={}", @@ -597,7 +602,7 @@ impl VersionedMpcContract { return Err(MpcContractError::InitError(InitError::ThresholdTooHigh)); } - Ok(Self::V0(MpcContract::init(threshold, candidates))) + Ok(Self::V0(MpcContract::init(threshold, candidates, config))) } // This function can be used to transfer the MPC network to a new contract. @@ -609,6 +614,7 @@ impl VersionedMpcContract { participants: Participants, threshold: usize, public_key: PublicKey, + config: Option, ) -> Result { log!( "init_running: signer={}, epoch={}, participants={}, threshold={}, public_key={:?}", @@ -636,7 +642,7 @@ impl VersionedMpcContract { pending_requests: LookupMap::new(StorageKey::PendingRequests), request_counter: 0, proposed_updates: ProposedUpdates::default(), - config: Config::default(), + config: config.unwrap_or_else(Config::default), })) } From 644be9b2b3b68e9f077b5b06d271a0c14c5bf1a9 Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Wed, 24 Jul 2024 23:57:29 -0700 Subject: [PATCH 19/24] Made node use contract config with LocalConfig --- chain-signatures/contract/src/config/impls.rs | 56 +++++++- chain-signatures/contract/src/config/mod.rs | 62 ++++++++- chain-signatures/node/src/cli.rs | 121 ++++++++---------- chain-signatures/node/src/config.rs | 51 ++++++++ chain-signatures/node/src/indexer.rs | 6 +- chain-signatures/node/src/lib.rs | 1 + chain-signatures/node/src/mesh/mod.rs | 8 -- .../node/src/protocol/consensus.rs | 8 +- .../node/src/protocol/cryptography.rs | 20 +-- chain-signatures/node/src/protocol/message.rs | 4 +- chain-signatures/node/src/protocol/mod.rs | 32 +++-- chain-signatures/node/src/protocol/monitor.rs | 5 +- .../node/src/protocol/presignature.rs | 36 +----- chain-signatures/node/src/protocol/triple.rs | 80 ++++++------ chain-signatures/node/src/rpc_client.rs | 12 ++ chain-signatures/node/src/test_utils.rs | 24 ++-- integration-tests/chain-signatures/Cargo.lock | 7 - .../chain-signatures/src/containers.rs | 24 ++-- integration-tests/chain-signatures/src/lib.rs | 27 ++-- .../chain-signatures/src/local.rs | 24 ++-- .../chain-signatures/tests/cases/nightly.rs | 44 ++++--- 21 files changed, 389 insertions(+), 263 deletions(-) create mode 100644 chain-signatures/node/src/config.rs diff --git a/chain-signatures/contract/src/config/impls.rs b/chain-signatures/contract/src/config/impls.rs index d745a431a..c9e1b42c6 100644 --- a/chain-signatures/contract/src/config/impls.rs +++ b/chain-signatures/contract/src/config/impls.rs @@ -1,11 +1,59 @@ use borsh::{self, BorshDeserialize, BorshSerialize}; -use super::{Config, DynamicValue}; +use super::{Config, DynamicValue, PresignatureConfig, ProtocolConfig, TripleConfig}; + +const MAX_EXPECTED_PARTICIPANTS: usize = 32; + +// The network multiplier is used to calculate the maximum amount of protocols in totality +// that should be in the network. +const NETWORK_MULTIPLIER: usize = 128; impl Config { - pub fn get(&self, key: &str) -> Option<&serde_json::Value> { - let value = self.entries.get(key)?; - Some(&value.0) + pub fn get(&self, key: &str) -> Option { + match key { + "protocol" => Some(serde_json::to_value(self.protocol.clone()).unwrap()), + _ => { + let value = self.other.get(key)?; + Some(value.0.clone()) + } + } + } +} + +impl Default for ProtocolConfig { + fn default() -> Self { + Self { + max_concurrent_introduction: 4, + max_concurrent_generation: 4 * MAX_EXPECTED_PARTICIPANTS, + triple: TripleConfig::default(), + presignature: PresignatureConfig::default(), + + other: Default::default(), + } + } +} + +impl Default for TripleConfig { + fn default() -> Self { + Self { + min_triples: 1024, + max_triples: 1024 * MAX_EXPECTED_PARTICIPANTS * NETWORK_MULTIPLIER, + generation_timeout: min_to_ms(20), + + other: Default::default(), + } + } +} + +impl Default for PresignatureConfig { + fn default() -> Self { + Self { + min_presignatures: 512, + max_presignatures: 512 * MAX_EXPECTED_PARTICIPANTS * NETWORK_MULTIPLIER, + generation_timeout: secs_to_ms(60), + + other: Default::default(), + } } } diff --git a/chain-signatures/contract/src/config/mod.rs b/chain-signatures/contract/src/config/mod.rs index 152e9cbba..06ccaf480 100644 --- a/chain-signatures/contract/src/config/mod.rs +++ b/chain-signatures/contract/src/config/mod.rs @@ -7,16 +7,68 @@ use std::collections::HashMap; use borsh::{self, BorshDeserialize, BorshSerialize}; use near_sdk::serde::{Deserialize, Serialize}; +/// Dynamic value is used to store any kind of value in the contract state. These values +/// can be deserialized on the fly to get the actual configurations, but the contract will +/// not be the ones directly utilizing these values unless they are concrete types. +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct DynamicValue(serde_json::Value); + #[derive( Clone, Default, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq, )] pub struct Config { + protocol: ProtocolConfig, + + /// The remaining entries that can be present in future forms of the configuration. #[serde(flatten)] - pub entries: HashMap, + pub other: HashMap, } -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -pub struct DynamicValue(serde_json::Value); +#[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +pub struct ProtocolConfig { + /// Maximum amount of concurrent protocol generation that can be introduced by this node. + /// This only includes protocols that generate triples and presignatures. + pub max_concurrent_introduction: usize, + /// Maximum amount of concurrent protocol generation that can be done per node. + /// This only includes protocols that generate triples and presignatures. + pub max_concurrent_generation: usize, + /// Configuration for triple generation. + pub triple: TripleConfig, + /// Configuration for presignature generation. + pub presignature: PresignatureConfig, + + /// The remaining entries that can be present in future forms of the configuration. + #[serde(flatten)] + pub other: HashMap, +} + +#[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +pub struct TripleConfig { + /// Minimum amount of triples that is owned by each node. + pub min_triples: usize, + /// Maximum amount of triples that is in the whole network. + pub max_triples: usize, + /// Timeout for triple generation in milliseconds. + pub generation_timeout: u64, + + /// The remaining entries that can be present in future forms of the configuration. + #[serde(flatten)] + pub other: HashMap, +} + +#[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +pub struct PresignatureConfig { + /// Minimum amount of presignatures that is owned by each node. + pub min_presignatures: usize, + /// Maximum amount of presignatures that is in the whole network. + pub max_presignatures: usize, + /// Timeout for presignature generation in milliseconds. + pub generation_timeout: u64, + + /// The remaining entries that can be present in future forms of the configuration. + #[serde(flatten)] + pub other: HashMap, +} #[cfg(test)] mod tests { @@ -46,7 +98,7 @@ mod tests { assert_eq!(config_str, config_macro); let config: Config = serde_json::from_value(config_macro).unwrap(); - assert_eq!(config.get("string").unwrap(), &serde_json::json!("value"),); - assert_eq!(config.get("integer").unwrap(), &serde_json::json!(1000),); + assert_eq!(config.get("string").unwrap(), serde_json::json!("value")); + assert_eq!(config.get("integer").unwrap(), serde_json::json!(1000)); } } diff --git a/chain-signatures/node/src/cli.rs b/chain-signatures/node/src/cli.rs index 2a7cbe294..cb32c3a5e 100644 --- a/chain-signatures/node/src/cli.rs +++ b/chain-signatures/node/src/cli.rs @@ -1,8 +1,6 @@ +use crate::config::{Config, LocalConfig, NetworkConfig}; use crate::gcp::GcpService; -use crate::mesh::NetworkConfig; -use crate::protocol::presignature::PresignatureConfig; -use crate::protocol::triple::TripleConfig; -use crate::protocol::{Config, MpcSignProtocol, SignQueue}; +use crate::protocol::{MpcSignProtocol, SignQueue}; use crate::storage::triple_storage::LockTripleNodeStorageBox; use crate::{indexer, storage, web}; use clap::Parser; @@ -61,38 +59,30 @@ pub enum Cli { /// Storage options #[clap(flatten)] storage_options: storage::Options, - /// At minimum, how many triples to stockpile on this node. - #[arg(long, env("MPC_MIN_TRIPLES"), default_value("20"))] - min_triples: usize, - /// At maximum, how many triples to stockpile on this node. - #[arg(long, env("MPC_MAX_TRIPLES"), default_value("640"))] - max_triples: usize, + // /// At minimum, how many triples to stockpile on this node. + // #[arg(long, env("MPC_MIN_TRIPLES"), default_value("20"))] + // min_triples: usize, + // /// At maximum, how many triples to stockpile on this node. + // #[arg(long, env("MPC_MAX_TRIPLES"), default_value("640"))] + // max_triples: usize, - /// At maximum, how many triple protocols can this current node introduce - /// at the same time. This should be something like `max_concurrent_gen / num_nodes` - #[arg( - long, - env("MPC_MAX_CONCURRENT_INTRODUCTION"), - default_value("2") - )] - max_concurrent_introduction: usize, + // /// At maximum, how many triple protocols can this current node introduce + // /// at the same time. This should be something like `max_concurrent_gen / num_nodes` + // #[arg(long, env("MPC_MAX_CONCURRENT_INTRODUCTION"), default_value("2"))] + // max_concurrent_introduction: usize, - /// At maximum, how many ongoing protocols for triples to be running - /// at the same time. The rest will be queued up. - #[arg( - long, - env("MPC_MAX_CONCURRENT_GENERATION"), - default_value("16") - )] - max_concurrent_generation: usize, + // /// At maximum, how many ongoing protocols for triples to be running + // /// at the same time. The rest will be queued up. + // #[arg(long, env("MPC_MAX_CONCURRENT_GENERATION"), default_value("16"))] + // max_concurrent_generation: usize, - /// At minimum, how many presignatures to stockpile on this node. - #[arg(long, env("MPC_MIN_PRESIGNATURES"), default_value("10"))] - min_presignatures: usize, + // /// At minimum, how many presignatures to stockpile on this node. + // #[arg(long, env("MPC_MIN_PRESIGNATURES"), default_value("10"))] + // min_presignatures: usize, - /// At maximum, how many presignatures to stockpile on the network. - #[arg(long, env("MPC_MAX_PRESIGNATURES"), default_value("320"))] - max_presignatures: usize, + // /// At maximum, how many presignatures to stockpile on the network. + // #[arg(long, env("MPC_MAX_PRESIGNATURES"), default_value("320"))] + // max_presignatures: usize, }, } @@ -111,12 +101,12 @@ impl Cli { indexer_options, my_address, storage_options, - min_triples, - max_triples, - max_concurrent_introduction, - max_concurrent_generation, - min_presignatures, - max_presignatures, + // min_triples, + // max_triples, + // max_concurrent_introduction, + // max_concurrent_generation, + // min_presignatures, + // max_presignatures, } => { let mut args = vec![ "start".to_string(), @@ -134,18 +124,18 @@ impl Cli { cipher_pk, "--cipher-sk".to_string(), cipher_sk, - "--min-triples".to_string(), - min_triples.to_string(), - "--max-triples".to_string(), - max_triples.to_string(), - "--max-concurrent-introduction".to_string(), - max_concurrent_introduction.to_string(), - "--max-concurrent-generation".to_string(), - max_concurrent_generation.to_string(), - "--min-presignatures".to_string(), - min_presignatures.to_string(), - "--max-presignatures".to_string(), - max_presignatures.to_string(), + // "--min-triples".to_string(), + // min_triples.to_string(), + // "--max-triples".to_string(), + // max_triples.to_string(), + // "--max-concurrent-introduction".to_string(), + // max_concurrent_introduction.to_string(), + // "--max-concurrent-generation".to_string(), + // max_concurrent_generation.to_string(), + // "--min-presignatures".to_string(), + // min_presignatures.to_string(), + // "--max-presignatures".to_string(), + // max_presignatures.to_string(), ]; if let Some(sign_sk) = sign_sk { args.extend(["--sign-sk".to_string(), sign_sk.to_string()]); @@ -204,12 +194,12 @@ pub fn run(cmd: Cli) -> anyhow::Result<()> { indexer_options, my_address, storage_options, - min_triples, - max_triples, - max_concurrent_introduction, - max_concurrent_generation, - min_presignatures, - max_presignatures, + // min_triples, + // max_triples, + // max_concurrent_introduction, + // max_concurrent_generation, + // min_presignatures, + // max_presignatures, } => { let sign_queue = Arc::new(RwLock::new(SignQueue::new())); let rt = tokio::runtime::Builder::new_multi_thread() @@ -260,19 +250,12 @@ pub fn run(cmd: Cli) -> anyhow::Result<()> { key_storage, triple_storage, Config { - triple_cfg: TripleConfig { - min_triples, - max_triples, - max_concurrent_introduction, - max_concurrent_generation, - }, - presig_cfg: PresignatureConfig { - min_presignatures, - max_presignatures, - }, - network_cfg: NetworkConfig { - cipher_pk: hpke::PublicKey::try_from_bytes(&hex::decode(cipher_pk)?)?, - sign_sk, + protocol: Default::default(), + local: LocalConfig { + network: NetworkConfig { + cipher_pk: hpke::PublicKey::try_from_bytes(&hex::decode(cipher_pk)?)?, + sign_sk, + }, }, }, ); diff --git a/chain-signatures/node/src/config.rs b/chain-signatures/node/src/config.rs new file mode 100644 index 000000000..0894c9e49 --- /dev/null +++ b/chain-signatures/node/src/config.rs @@ -0,0 +1,51 @@ +use std::collections::HashMap; + +use mpc_contract::config::ProtocolConfig; +use mpc_keys::hpke; + +/// The contract's config is a dynamic representation of all configurations possible. +pub type ContractConfig = HashMap; + +#[derive(Clone, Debug, Default)] +pub struct Config { + pub protocol: ProtocolConfig, + pub local: LocalConfig, +} + +impl Config { + pub fn try_from_contract(mut contract: ContractConfig, original: &Config) -> Option { + let Ok(protocol) = serde_json::from_value(contract.remove("protocol")?) else { + return None; + }; + + Some(Self { + protocol, + local: original.local.clone(), + }) + } +} + +/// All the local configurations on a node that are not accessible by anyone else +/// but the current node. +#[derive(Clone, Debug, Default)] +pub struct LocalConfig { + pub network: NetworkConfig, +} + +#[derive(Clone, Debug)] +pub struct NetworkConfig { + pub sign_sk: near_crypto::SecretKey, + pub cipher_pk: hpke::PublicKey, +} + +impl Default for NetworkConfig { + fn default() -> Self { + Self { + sign_sk: near_crypto::SecretKey::from_seed( + near_crypto::KeyType::ED25519, + "test-entropy", + ), + cipher_pk: hpke::PublicKey::from_bytes(&[0; 32]), + } + } +} diff --git a/chain-signatures/node/src/indexer.rs b/chain-signatures/node/src/indexer.rs index bea18337a..9f0b689d7 100644 --- a/chain-signatures/node/src/indexer.rs +++ b/chain-signatures/node/src/indexer.rs @@ -31,11 +31,7 @@ pub struct Options { pub s3_bucket: String, /// AWS S3 region name for NEAR Lake Indexer - #[clap( - long, - env("MPC_INDEXER_S3_REGION"), - default_value = "eu-central-1" - )] + #[clap(long, env("MPC_INDEXER_S3_REGION"), default_value = "eu-central-1")] pub s3_region: String, /// AWS S3 URL for NEAR Lake Indexer (can be used to point to LocalStack) diff --git a/chain-signatures/node/src/lib.rs b/chain-signatures/node/src/lib.rs index e4d8ee019..676e8a22a 100644 --- a/chain-signatures/node/src/lib.rs +++ b/chain-signatures/node/src/lib.rs @@ -1,4 +1,5 @@ pub mod cli; +pub mod config; pub mod gcp; pub mod http_client; pub mod indexer; diff --git a/chain-signatures/node/src/mesh/mod.rs b/chain-signatures/node/src/mesh/mod.rs index f6635b716..db71f6e49 100644 --- a/chain-signatures/node/src/mesh/mod.rs +++ b/chain-signatures/node/src/mesh/mod.rs @@ -1,16 +1,8 @@ -use mpc_keys::hpke; - use crate::protocol::contract::primitives::Participants; use crate::protocol::ProtocolState; pub mod connection; -#[derive(Clone, Debug)] -pub struct NetworkConfig { - pub sign_sk: near_crypto::SecretKey, - pub cipher_pk: hpke::PublicKey, -} - #[derive(Default)] pub struct Mesh { /// Pool of connections to participants. Used to check who is alive in the network. diff --git a/chain-signatures/node/src/protocol/consensus.rs b/chain-signatures/node/src/protocol/consensus.rs index d03a580b7..95653b433 100644 --- a/chain-signatures/node/src/protocol/consensus.rs +++ b/chain-signatures/node/src/protocol/consensus.rs @@ -137,13 +137,11 @@ impl ConsensusProtocol for StartedState { contract_state.threshold, epoch, ctx.my_account_id(), - &ctx.cfg().presig_cfg, ); let triple_manager = Arc::new(RwLock::new(TripleManager::new( me, contract_state.threshold, epoch, - &ctx.cfg().triple_cfg, self.triple_data, ctx.triple_storage(), ctx.my_account_id(), @@ -374,7 +372,6 @@ impl ConsensusProtocol for WaitingForConsensusState { me, self.threshold, self.epoch, - &ctx.cfg().triple_cfg, vec![], ctx.triple_storage(), ctx.my_account_id(), @@ -396,7 +393,6 @@ impl ConsensusProtocol for WaitingForConsensusState { self.threshold, self.epoch, ctx.my_account_id(), - &ctx.cfg().presig_cfg, ))), signature_manager: Arc::new(RwLock::new(SignatureManager::new( me, @@ -676,8 +672,8 @@ impl ConsensusProtocol for JoiningState { .call(ctx.signer(), ctx.mpc_contract_id(), "join") .args_json(json!({ "url": ctx.my_address(), - "cipher_pk": ctx.cfg().network_cfg.cipher_pk.to_bytes(), - "sign_pk": ctx.cfg().network_cfg.sign_sk.public_key(), + "cipher_pk": ctx.cfg().local.network.cipher_pk.to_bytes(), + "sign_pk": ctx.cfg().local.network.sign_sk.public_key(), })) .max_gas() .retry_exponential(10, 3) diff --git a/chain-signatures/node/src/protocol/cryptography.rs b/chain-signatures/node/src/protocol/cryptography.rs index ab4c66adf..3d6f91bcd 100644 --- a/chain-signatures/node/src/protocol/cryptography.rs +++ b/chain-signatures/node/src/protocol/cryptography.rs @@ -97,7 +97,7 @@ impl CryptographicProtocol for GeneratingState { .await .send_encrypted( ctx.me().await, - &ctx.cfg().network_cfg.sign_sk, + &ctx.cfg().local.network.sign_sk, ctx.http_client(), ctx.mesh().active_participants(), ) @@ -158,7 +158,7 @@ impl CryptographicProtocol for GeneratingState { .await .send_encrypted( ctx.me().await, - &ctx.cfg().network_cfg.sign_sk, + &ctx.cfg().local.network.sign_sk, ctx.http_client(), ctx.mesh().active_participants(), ) @@ -195,7 +195,7 @@ impl CryptographicProtocol for WaitingForConsensusState { .await .send_encrypted( ctx.me().await, - &ctx.cfg().network_cfg.sign_sk, + &ctx.cfg().local.network.sign_sk, ctx.http_client(), ctx.mesh().active_participants(), ) @@ -250,7 +250,7 @@ impl CryptographicProtocol for ResharingState { .await .send_encrypted( ctx.me().await, - &ctx.cfg().network_cfg.sign_sk, + &ctx.cfg().local.network.sign_sk, ctx.http_client(), &active, ) @@ -317,7 +317,7 @@ impl CryptographicProtocol for ResharingState { .await .send_encrypted( ctx.me().await, - &ctx.cfg().network_cfg.sign_sk, + &ctx.cfg().local.network.sign_sk, ctx.http_client(), &active, ) @@ -351,6 +351,7 @@ impl CryptographicProtocol for RunningState { mut self, ctx: C, ) -> Result { + let protocol_cfg = &ctx.cfg().protocol; let active = ctx.mesh().active_participants(); if active.len() < self.threshold { tracing::info!( @@ -366,10 +367,10 @@ impl CryptographicProtocol for RunningState { crate::metrics::MESSAGE_QUEUE_SIZE .with_label_values(&[my_account_id.as_str()]) .set(messages.len() as i64); - if let Err(err) = triple_manager.stockpile(active) { + if let Err(err) = triple_manager.stockpile(active, protocol_cfg) { tracing::warn!(?err, "running: failed to stockpile triples"); } - for (p, msg) in triple_manager.poke().await { + for (p, msg) in triple_manager.poke(protocol_cfg).await { let info = self.fetch_participant(&p)?; messages.push(info.clone(), MpcMessage::Triple(msg)); } @@ -394,6 +395,7 @@ impl CryptographicProtocol for RunningState { &self.public_key, &self.private_share, &mut triple_manager, + protocol_cfg, ) .await { @@ -456,7 +458,7 @@ impl CryptographicProtocol for RunningState { let failures = messages .send_encrypted( ctx.me().await, - &ctx.cfg().network_cfg.sign_sk, + &ctx.cfg().local.network.sign_sk, ctx.http_client(), active, ) @@ -469,7 +471,7 @@ impl CryptographicProtocol for RunningState { } drop(messages); - self.stuck_monitor.write().await.check().await; + self.stuck_monitor.write().await.check(protocol_cfg).await; Ok(NodeState::Running(self)) } } diff --git a/chain-signatures/node/src/protocol/message.rs b/chain-signatures/node/src/protocol/message.rs index 28751823b..af0f4df8e 100644 --- a/chain-signatures/node/src/protocol/message.rs +++ b/chain-signatures/node/src/protocol/message.rs @@ -23,6 +23,7 @@ use tokio::sync::RwLock; pub trait MessageCtx { async fn me(&self) -> Participant; fn mesh(&self) -> &Mesh; + fn cfg(&self) -> &crate::config::Config; } #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] @@ -230,6 +231,7 @@ impl MessageHandler for RunningState { ctx: C, queue: &mut MpcMessageQueue, ) -> Result<(), MessageHandleError> { + let protocol_cfg = &ctx.cfg().protocol; let participants = ctx.mesh().active_participants(); let mut triple_manager = self.triple_manager.write().await; @@ -253,7 +255,7 @@ impl MessageHandler for RunningState { !triple_manager.refresh_gc(id) }); for (id, queue) in triple_messages { - let protocol = match triple_manager.get_or_generate(*id, participants) { + let protocol = match triple_manager.get_or_generate(*id, participants, protocol_cfg) { Ok(protocol) => protocol, Err(err) => { // ignore the message since the generation had bad parameters. Also have the other node who diff --git a/chain-signatures/node/src/protocol/mod.rs b/chain-signatures/node/src/protocol/mod.rs index 35bf8c83d..0fd41c6e0 100644 --- a/chain-signatures/node/src/protocol/mod.rs +++ b/chain-signatures/node/src/protocol/mod.rs @@ -21,9 +21,8 @@ pub use state::NodeState; use self::consensus::ConsensusCtx; use self::cryptography::CryptographicCtx; use self::message::MessageCtx; -use self::presignature::PresignatureConfig; -use self::triple::TripleConfig; -use crate::mesh::{Mesh, NetworkConfig}; +use crate::config::Config; +use crate::mesh::Mesh; use crate::protocol::consensus::ConsensusProtocol; use crate::protocol::cryptography::CryptographicProtocol; use crate::protocol::message::{MessageHandler, MpcMessageQueue}; @@ -41,13 +40,6 @@ use tokio::sync::mpsc::{self, error::TryRecvError}; use tokio::sync::RwLock; use url::Url; -#[derive(Clone, Debug)] -pub struct Config { - pub triple_cfg: TripleConfig, - pub presig_cfg: PresignatureConfig, - pub network_cfg: NetworkConfig, -} - struct Ctx { my_address: Url, account_id: AccountId, @@ -148,6 +140,10 @@ impl MessageCtx for &MpcSignProtocol { fn mesh(&self) -> &Mesh { &self.ctx.mesh } + + fn cfg(&self) -> &Config { + &self.ctx.cfg + } } pub struct MpcSignProtocol { @@ -241,6 +237,22 @@ impl MpcSignProtocol { }; tracing::debug!(?contract_state); + // Sets the latest configurations from the contract: + self.ctx.cfg = match rpc_client::fetch_mpc_config( + &self.ctx.rpc_client, + &self.ctx.mpc_contract_id, + &self.ctx.cfg, + ) + .await + { + Ok(config) => config, + Err(e) => { + tracing::error!("could not fetch contract's config: {e}"); + tokio::time::sleep(Duration::from_secs(1)).await; + continue; + } + }; + // Establish the participants for this current iteration of the protocol loop. This will // set which participants are currently active in the protocol and determines who will be // receiving messages. diff --git a/chain-signatures/node/src/protocol/monitor.rs b/chain-signatures/node/src/protocol/monitor.rs index c75239f9e..a6096d47f 100644 --- a/chain-signatures/node/src/protocol/monitor.rs +++ b/chain-signatures/node/src/protocol/monitor.rs @@ -1,3 +1,4 @@ +use mpc_contract::config::ProtocolConfig; use std::collections::HashSet; use std::sync::Arc; use std::time::{Duration, Instant}; @@ -39,10 +40,10 @@ impl StuckMonitor { /// will report that the protocol is stuck. /// /// Returns `true` if the protocol is stuck. - pub async fn check(&mut self) -> bool { + pub async fn check(&mut self, cfg: &ProtocolConfig) -> bool { let triple_manager = self.triple_manager.read().await; let latest_triples: HashSet<_> = triple_manager.triples.keys().cloned().collect(); - if triple_manager.has_min_triples() { + if triple_manager.has_min_triples(cfg) { drop(triple_manager); self.reset(latest_triples); return false; diff --git a/chain-signatures/node/src/protocol/presignature.rs b/chain-signatures/node/src/protocol/presignature.rs index d231e7507..b1e4ed29b 100644 --- a/chain-signatures/node/src/protocol/presignature.rs +++ b/chain-signatures/node/src/protocol/presignature.rs @@ -1,5 +1,5 @@ use super::message::PresignatureMessage; -use super::triple::{Triple, TripleConfig, TripleId, TripleManager}; +use super::triple::{Triple, TripleId, TripleManager}; use crate::protocol::contract::primitives::Participants; use crate::types::{PresignatureProtocol, SecretKeyShare, TAKEN_TIMEOUT}; use crate::util::AffinePointExt; @@ -9,6 +9,7 @@ use cait_sith::{KeygenOutput, PresignArguments, PresignOutput}; use chrono::Utc; use crypto_shared::PublicKey; use k256::Secp256k1; +use mpc_contract::config::ProtocolConfig; use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet, VecDeque}; use std::time::Instant; @@ -27,12 +28,6 @@ pub struct Presignature { pub participants: Vec, } -#[derive(Copy, Clone, Debug)] -pub struct PresignatureConfig { - pub min_presignatures: usize, - pub max_presignatures: usize, -} - /// An ongoing presignature generator. pub struct PresignatureGenerator { pub participants: Vec, @@ -117,17 +112,10 @@ pub struct PresignatureManager { threshold: usize, epoch: u64, my_account_id: AccountId, - presig_cfg: PresignatureConfig, } impl PresignatureManager { - pub fn new( - me: Participant, - threshold: usize, - epoch: u64, - my_account_id: &AccountId, - presig_cfg: &PresignatureConfig, - ) -> Self { + pub fn new(me: Participant, threshold: usize, epoch: u64, my_account_id: &AccountId) -> Self { Self { presignatures: HashMap::new(), generators: HashMap::new(), @@ -138,7 +126,6 @@ impl PresignatureManager { threshold, epoch, my_account_id: my_account_id.clone(), - presig_cfg: *presig_cfg, } } @@ -260,27 +247,18 @@ impl PresignatureManager { pk: &PublicKey, sk_share: &SecretKeyShare, triple_manager: &mut TripleManager, + cfg: &ProtocolConfig, ) -> Result<(), InitializationError> { - let PresignatureConfig { - min_presignatures, - max_presignatures, - } = self.presig_cfg; - - let TripleConfig { - max_concurrent_introduction, - .. - } = triple_manager.triple_cfg; - let not_enough_presignatures = { // Stopgap to prevent too many presignatures in the system. This should be around min_presig*nodes*2 // for good measure so that we have enough presignatures to do sig generation while also maintain // the minimum number of presignature where a single node can't flood the system. - if self.potential_len() >= max_presignatures { + if self.potential_len() >= cfg.presignature.max_presignatures { false } else { // We will always try to generate a new triple if we have less than the minimum - self.my_len() < min_presignatures - && self.introduced.len() < max_concurrent_introduction + self.my_len() < cfg.presignature.min_presignatures + && self.introduced.len() < cfg.max_concurrent_introduction } }; diff --git a/chain-signatures/node/src/protocol/triple.rs b/chain-signatures/node/src/protocol/triple.rs index 00dd65e67..578441396 100644 --- a/chain-signatures/node/src/protocol/triple.rs +++ b/chain-signatures/node/src/protocol/triple.rs @@ -14,6 +14,7 @@ use chrono::Utc; use highway::{HighwayHash, HighwayHasher}; use k256::elliptic_curve::group::GroupEncoding; use k256::Secp256k1; +use mpc_contract::config::ProtocolConfig; use serde::{Deserialize, Serialize}; use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet, VecDeque}; @@ -40,15 +41,22 @@ pub struct TripleGenerator { pub participants: Vec, pub protocol: TripleProtocol, pub timestamp: Option, + pub timeout: Duration, } impl TripleGenerator { - pub fn new(id: TripleId, participants: Vec, protocol: TripleProtocol) -> Self { + pub fn new( + id: TripleId, + participants: Vec, + protocol: TripleProtocol, + timeout: u64, + ) -> Self { Self { id, participants, protocol, timestamp: None, + timeout: Duration::from_millis(timeout), } } @@ -69,19 +77,6 @@ impl TripleGenerator { } } -// TODO: easy way to deserialize human readable string for CLI passable args -#[derive(Copy, Clone, Debug)] -pub struct TripleConfig { - /// Minimum amount of triples that is owned by each node. - pub min_triples: usize, - /// Maximum amount of triples that is owned by each node. - pub max_triples: usize, - /// Maximum amount of concurrent triple generation that can be introduce by this node. - pub max_concurrent_introduction: usize, - /// Maximum amount of concurrent triple generation that can be done per node. - pub max_concurrent_generation: usize, -} - /// Abstracts how triples are generated by providing a way to request a new triple that will be /// complete some time in the future and a way to take an already generated triple. pub struct TripleManager { @@ -112,7 +107,6 @@ pub struct TripleManager { pub me: Participant, pub threshold: usize, pub epoch: u64, - pub triple_cfg: TripleConfig, pub triple_storage: LockTripleNodeStorageBox, pub my_account_id: AccountId, } @@ -131,7 +125,6 @@ impl fmt::Debug for TripleManager { .field("threshold", &self.threshold) .field("epoch", &self.epoch) .field("my_account_id", &self.my_account_id) - .field("triple_cfg", &self.triple_cfg) .finish() } } @@ -141,7 +134,6 @@ impl TripleManager { me: Participant, threshold: usize, epoch: u64, - triple_cfg: &TripleConfig, triple_data: Vec, triple_storage: LockTripleNodeStorageBox, my_account_id: &AccountId, @@ -167,7 +159,6 @@ impl TripleManager { me, threshold, epoch, - triple_cfg: *triple_cfg, triple_storage, my_account_id: my_account_id.clone(), } @@ -194,8 +185,8 @@ impl TripleManager { self.len() + self.generators.len() } - pub fn has_min_triples(&self) -> bool { - self.my_len() >= self.triple_cfg.min_triples + pub fn has_min_triples(&self, cfg: &ProtocolConfig) -> bool { + self.my_len() >= cfg.triple.min_triples } /// Clears an entry from failed triples if that triple protocol was created more than 2 hrs ago @@ -212,7 +203,11 @@ impl TripleManager { } /// Starts a new Beaver triple generation protocol. - pub fn generate(&mut self, participants: &Participants) -> Result<(), InitializationError> { + pub fn generate( + &mut self, + participants: &Participants, + timeout: u64, + ) -> Result<(), InitializationError> { let id = rand::random(); // Check if the `id` is already in the system. Error out and have the next cycle try again. @@ -232,8 +227,10 @@ impl TripleManager { self.me, self.threshold, )?); - self.generators - .insert(id, TripleGenerator::new(id, participants, protocol)); + self.generators.insert( + id, + TripleGenerator::new(id, participants, protocol, timeout), + ); self.queued.push_back(id); self.introduced.insert(id); crate::metrics::NUM_TOTAL_HISTORICAL_TRIPLE_GENERATORS @@ -244,30 +241,27 @@ impl TripleManager { /// Stockpile triples if the amount of unspent triples is below the minimum /// and the maximum number of all ongoing generation protocols is below the maximum. - pub fn stockpile(&mut self, participants: &Participants) -> Result<(), InitializationError> { - let TripleConfig { - min_triples, - max_triples, - max_concurrent_introduction, - max_concurrent_generation, - } = self.triple_cfg; - + pub fn stockpile( + &mut self, + participants: &Participants, + cfg: &ProtocolConfig, + ) -> Result<(), InitializationError> { let not_enough_triples = { // Stopgap to prevent too many triples in the system. This should be around min_triple*nodes*2 // for good measure so that we have enough triples to do presig generation while also maintain // the minimum number of triples where a single node can't flood the system. - if self.potential_len() >= max_triples { + if self.potential_len() >= cfg.triple.max_triples { false } else { // We will always try to generate a new triple if we have less than the minimum - self.my_len() < min_triples - && self.introduced.len() < max_concurrent_introduction - && self.generators.len() < max_concurrent_generation + self.my_len() < cfg.triple.min_triples + && self.introduced.len() < cfg.max_concurrent_introduction + && self.generators.len() < cfg.max_concurrent_generation } }; if not_enough_triples { - self.generate(participants)?; + self.generate(participants, cfg.triple.generation_timeout)?; } Ok(()) } @@ -392,6 +386,7 @@ impl TripleManager { &mut self, id: TripleId, participants: &Participants, + cfg: &ProtocolConfig, ) -> Result, CryptographicError> { if self.triples.contains_key(&id) || self.gc.contains_key(&id) { Ok(None) @@ -399,7 +394,7 @@ impl TripleManager { let potential_len = self.potential_len(); match self.generators.entry(id) { Entry::Vacant(e) => { - if potential_len >= self.triple_cfg.max_triples { + if potential_len >= cfg.triple.max_triples { // We are at the maximum amount of triples, we cannot generate more. So just in case a node // sends more triple generation requests, reject them and have them tiemout. return Ok(None); @@ -412,7 +407,12 @@ impl TripleManager { self.me, self.threshold, )?); - let generator = e.insert(TripleGenerator::new(id, participants, protocol)); + let generator = e.insert(TripleGenerator::new( + id, + participants, + protocol, + cfg.triple.generation_timeout, + )); self.queued.push_back(id); crate::metrics::NUM_TOTAL_HISTORICAL_TRIPLE_GENERATORS .with_label_values(&[self.my_account_id.as_str()]) @@ -428,9 +428,9 @@ impl TripleManager { /// messages to be sent to the respective participant. /// /// An empty vector means we cannot progress until we receive a new message. - pub async fn poke(&mut self) -> Vec<(Participant, TripleMessage)> { + pub async fn poke(&mut self, cfg: &ProtocolConfig) -> Vec<(Participant, TripleMessage)> { // Add more protocols to the ongoing pool if there is space. - let to_generate_len = self.triple_cfg.max_concurrent_generation - self.ongoing.len(); + let to_generate_len = cfg.max_concurrent_generation - self.ongoing.len(); if !self.queued.is_empty() && to_generate_len > 0 { for _ in 0..to_generate_len { self.queued.pop_front().map(|id| self.ongoing.insert(id)); diff --git a/chain-signatures/node/src/rpc_client.rs b/chain-signatures/node/src/rpc_client.rs index 4dd28164f..7804f3731 100644 --- a/chain-signatures/node/src/rpc_client.rs +++ b/chain-signatures/node/src/rpc_client.rs @@ -1,3 +1,4 @@ +use crate::config::{Config, ContractConfig}; use crate::protocol::ProtocolState; use near_account_id::AccountId; @@ -16,6 +17,17 @@ pub async fn fetch_mpc_contract_state( .map_err(|_| anyhow::anyhow!("protocol state has not been initialized yet")) } +pub async fn fetch_mpc_config( + rpc_client: &near_fetch::Client, + mpc_contract_id: &AccountId, + original: &Config, +) -> anyhow::Result { + let contract_config: ContractConfig = + rpc_client.view(mpc_contract_id, "config").await?.json()?; + Config::try_from_contract(contract_config, original) + .ok_or_else(|| anyhow::anyhow!("failed to parse contract config")) +} + pub async fn vote_for_public_key( rpc_client: &near_fetch::Client, signer: &InMemorySigner, diff --git a/chain-signatures/node/src/test_utils.rs b/chain-signatures/node/src/test_utils.rs index 74b373af0..4771441e9 100644 --- a/chain-signatures/node/src/test_utils.rs +++ b/chain-signatures/node/src/test_utils.rs @@ -1,6 +1,7 @@ +use crate::config::Config; use crate::protocol::contract::primitives::Participants; use crate::protocol::presignature::GenerationError; -use crate::protocol::triple::{Triple, TripleConfig, TripleId, TripleManager}; +use crate::protocol::triple::{Triple, TripleId, TripleManager}; use crate::protocol::ParticipantInfo; use crate::storage::triple_storage::LockTripleNodeStorageBox; use crate::{gcp::GcpService, protocol::message::TripleMessage, storage}; @@ -16,16 +17,11 @@ use tokio::sync::RwLock; // Constants to be used for testing. const STARTING_EPOCH: u64 = 0; -const TRIPLE_CFG: TripleConfig = TripleConfig { - min_triples: 2, - max_triples: 10, - max_concurrent_introduction: 4, - max_concurrent_generation: 16, -}; struct TestTripleManagers { managers: Vec, participants: Participants, + config: Config, } impl TestTripleManagers { @@ -67,7 +63,6 @@ impl TestTripleManagers { Participant::from(num), num_managers as usize, STARTING_EPOCH, - &TRIPLE_CFG, vec![], triple_storage, &account_id, @@ -77,16 +72,20 @@ impl TestTripleManagers { TestTripleManagers { managers, participants, + config: Config::default(), } } fn generate(&mut self, index: usize) -> Result<(), InitializationError> { - self.managers[index].generate(&self.participants) + self.managers[index].generate( + &self.participants, + self.config.protocol.triple.generation_timeout, + ) } async fn poke(&mut self, index: usize) -> Result { let mut quiet = true; - let messages = self.managers[index].poke().await; + let messages = self.managers[index].poke(&self.config.protocol).await; for ( participant, ref tm @ TripleMessage { @@ -98,7 +97,10 @@ impl TestTripleManagers { quiet = false; let participant_i: u32 = participant.into(); let manager = &mut self.managers[participant_i as usize]; - if let Some(protocol) = manager.get_or_generate(id, &self.participants).unwrap() { + if let Some(protocol) = manager + .get_or_generate(id, &self.participants, &self.config.protocol) + .unwrap() + { protocol.message(from, data.to_vec()); } else { println!("Tried to write to completed mailbox {:?}", tm); diff --git a/integration-tests/chain-signatures/Cargo.lock b/integration-tests/chain-signatures/Cargo.lock index a2a62e484..b237811ce 100644 --- a/integration-tests/chain-signatures/Cargo.lock +++ b/integration-tests/chain-signatures/Cargo.lock @@ -4244,7 +4244,6 @@ dependencies = [ "crypto-shared", "k256", "near-gas", - "near-rng", "near-sdk", "schemars", "serde", @@ -5043,12 +5042,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "near-rng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efd376ff92ef9c5ef550f808406056854815f10e046703ae97f61946ef53a12" - [[package]] name = "near-rpc-error-core" version = "0.20.1" diff --git a/integration-tests/chain-signatures/src/containers.rs b/integration-tests/chain-signatures/src/containers.rs index acbe04dae..c4f2c0900 100644 --- a/integration-tests/chain-signatures/src/containers.rs +++ b/integration-tests/chain-signatures/src/containers.rs @@ -83,12 +83,12 @@ impl<'a> Node<'a> { indexer_options: indexer_options.clone(), my_address: None, storage_options: ctx.storage_options.clone(), - min_triples: cfg.triple_cfg.min_triples, - max_triples: cfg.triple_cfg.max_triples, - max_concurrent_introduction: cfg.triple_cfg.max_concurrent_introduction, - max_concurrent_generation: cfg.triple_cfg.max_concurrent_generation, - min_presignatures: cfg.presig_cfg.min_presignatures, - max_presignatures: cfg.presig_cfg.max_presignatures, + // min_triples: cfg.triple_cfg.min_triples, + // max_triples: cfg.triple_cfg.max_triples, + // max_concurrent_introduction: cfg.triple_cfg.max_concurrent_introduction, + // max_concurrent_generation: cfg.triple_cfg.max_concurrent_generation, + // min_presignatures: cfg.presig_cfg.min_presignatures, + // max_presignatures: cfg.presig_cfg.max_presignatures, } .into_str_args(); let image: GenericImage = GenericImage::new("near/mpc-node", "latest") @@ -171,12 +171,12 @@ impl<'a> Node<'a> { indexer_options: indexer_options.clone(), my_address: None, storage_options: storage_options.clone(), - min_triples: cfg.triple_cfg.min_triples, - max_triples: cfg.triple_cfg.max_triples, - max_concurrent_introduction: cfg.triple_cfg.max_concurrent_introduction, - max_concurrent_generation: cfg.triple_cfg.max_concurrent_generation, - min_presignatures: cfg.presig_cfg.min_presignatures, - max_presignatures: cfg.presig_cfg.max_presignatures, + // min_triples: cfg.protocol.triple.min_triples, + // max_triples: cfg.protocol.triple.max_triples, + // max_concurrent_introduction: cfg.triple_cfg.max_concurrent_introduction, + // max_concurrent_generation: cfg.triple_cfg.max_concurrent_generation, + // min_presignatures: cfg.presig_cfg.min_presignatures, + // max_presignatures: cfg.presig_cfg.max_presignatures, sign_sk: Some(sign_sk), } .into_str_args(); diff --git a/integration-tests/chain-signatures/src/lib.rs b/integration-tests/chain-signatures/src/lib.rs index bf5fac159..0084ec00b 100644 --- a/integration-tests/chain-signatures/src/lib.rs +++ b/integration-tests/chain-signatures/src/lib.rs @@ -12,10 +12,9 @@ use crate::containers::LocalStack; use anyhow::Context as _; use bollard::exec::{CreateExecOptions, StartExecResults}; use futures::StreamExt; +use mpc_contract::config::{PresignatureConfig, ProtocolConfig, TripleConfig}; use mpc_contract::primitives::CandidateInfo; use mpc_node::gcp::GcpService; -use mpc_node::protocol::presignature::PresignatureConfig; -use mpc_node::protocol::triple::TripleConfig; use mpc_node::storage; use mpc_node::storage::triple_storage::TripleNodeStorageBox; use near_crypto::KeyFile; @@ -31,8 +30,7 @@ const NETWORK: &str = "mpc_it_network"; pub struct MultichainConfig { pub nodes: usize, pub threshold: usize, - pub triple_cfg: TripleConfig, - pub presig_cfg: PresignatureConfig, + pub protocol: ProtocolConfig, } impl Default for MultichainConfig { @@ -40,15 +38,18 @@ impl Default for MultichainConfig { Self { nodes: 3, threshold: 2, - triple_cfg: TripleConfig { - min_triples: 8, - max_triples: 80, - max_concurrent_introduction: 8, - max_concurrent_generation: 24, - }, - presig_cfg: PresignatureConfig { - min_presignatures: 2, - max_presignatures: 20, + protocol: ProtocolConfig { + triple: TripleConfig { + min_triples: 8, + max_triples: 80, + ..Default::default() + }, + presignature: PresignatureConfig { + min_presignatures: 2, + max_presignatures: 20, + ..Default::default() + }, + ..Default::default() }, } } diff --git a/integration-tests/chain-signatures/src/local.rs b/integration-tests/chain-signatures/src/local.rs index c2967a53a..f100d74e4 100644 --- a/integration-tests/chain-signatures/src/local.rs +++ b/integration-tests/chain-signatures/src/local.rs @@ -77,12 +77,12 @@ impl Node { indexer_options, my_address: None, storage_options: ctx.storage_options.clone(), - min_triples: cfg.triple_cfg.min_triples, - max_triples: cfg.triple_cfg.max_triples, - max_concurrent_introduction: cfg.triple_cfg.max_concurrent_introduction, - max_concurrent_generation: cfg.triple_cfg.max_concurrent_generation, - min_presignatures: cfg.presig_cfg.min_presignatures, - max_presignatures: cfg.presig_cfg.max_presignatures, + // min_triples: cfg.triple_cfg.min_triples, + // max_triples: cfg.triple_cfg.max_triples, + // max_concurrent_introduction: cfg.triple_cfg.max_concurrent_introduction, + // max_concurrent_generation: cfg.triple_cfg.max_concurrent_generation, + // min_presignatures: cfg.presig_cfg.min_presignatures, + // max_presignatures: cfg.presig_cfg.max_presignatures, }; let mpc_node_id = format!("multichain/{account_id}", account_id = account_id); @@ -135,12 +135,12 @@ impl Node { indexer_options: indexer_options.clone(), my_address: None, storage_options: storage_options.clone(), - min_triples: cfg.triple_cfg.min_triples, - max_triples: cfg.triple_cfg.max_triples, - max_concurrent_introduction: cfg.triple_cfg.max_concurrent_introduction, - max_concurrent_generation: cfg.triple_cfg.max_concurrent_generation, - min_presignatures: cfg.presig_cfg.min_presignatures, - max_presignatures: cfg.presig_cfg.max_presignatures, + // min_triples: cfg.triple_cfg.min_triples, + // max_triples: cfg.triple_cfg.max_triples, + // max_concurrent_introduction: cfg.triple_cfg.max_concurrent_introduction, + // max_concurrent_generation: cfg.triple_cfg.max_concurrent_generation, + // min_presignatures: cfg.presig_cfg.min_presignatures, + // max_presignatures: cfg.presig_cfg.max_presignatures, }; let mpc_node_id = format!("multichain/{account_id}", account_id = account_id); diff --git a/integration-tests/chain-signatures/tests/cases/nightly.rs b/integration-tests/chain-signatures/tests/cases/nightly.rs index 1f44ef3f5..ccadde63a 100644 --- a/integration-tests/chain-signatures/tests/cases/nightly.rs +++ b/integration-tests/chain-signatures/tests/cases/nightly.rs @@ -1,6 +1,4 @@ use integration_tests_chain_signatures::MultichainConfig; -use mpc_node::protocol::presignature::PresignatureConfig; -use mpc_node::protocol::triple::TripleConfig; use test_log::test; use crate::actions::{self, wait_for}; @@ -15,28 +13,34 @@ async fn test_nightly_signature_production() -> anyhow::Result<()> { const MIN_TRIPLES: usize = 10; const MAX_TRIPLES: usize = 2 * NODES * MIN_TRIPLES; - let triple_cfg = TripleConfig { - // This is the min triples required by each node. - min_triples: MIN_TRIPLES, - // This is the total amount of triples that will be generated by all nodes. - max_triples: MAX_TRIPLES, - // This is the amount each node can introduce a triple generation protocol into the system. - max_concurrent_introduction: 4, - // This is the maximum amount of triples that can be generated concurrently by the whole system. - max_concurrent_generation: 24, - }; - let presig_cfg = PresignatureConfig { - // this is the min presignatures required by each node - min_presignatures: 10, - // This is the total amount of presignatures that will be generated by all nodes. - max_presignatures: 1000, - }; + // let triple_cfg = TripleConfig { + // // This is the min triples required by each node. + // min_triples: MIN_TRIPLES, + // // This is the total amount of triples that will be generated by all nodes. + // max_triples: MAX_TRIPLES, + // // This is the amount each node can introduce a triple generation protocol into the system. + // max_concurrent_introduction: 4, + // // This is the maximum amount of triples that can be generated concurrently by the whole system. + // max_concurrent_generation: 24, + // }; + // let presig_cfg = PresignatureConfig { + // // this is the min presignatures required by each node + // min_presignatures: 10, + // // This is the total amount of presignatures that will be generated by all nodes. + // max_presignatures: 1000, + // }; let config = MultichainConfig { - triple_cfg, - presig_cfg, nodes: NODES, threshold: THRESHOLD, + protocol: ProtocolConfig { + triple: TripleConfig { + min_triples: MIN_TRIPLES, + max_triples: MAX_TRIPLES, + ..Default::default() + }, + ..Default::default() + }, }; with_multichain_nodes(config, |ctx| { From cf320f7fe12b65ee44e30ce4f85c275fe27f28d1 Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Thu, 25 Jul 2024 01:06:11 -0700 Subject: [PATCH 20/24] Added --override-config for partial overrides --- chain-signatures/contract/src/lib.rs | 4 +- chain-signatures/node/src/cli.rs | 76 ++++--------- chain-signatures/node/src/config.rs | 107 +++++++++++++++++- .../chain-signatures/src/containers.rs | 19 ++-- .../chain-signatures/src/local.rs | 19 ++-- .../chain-signatures/tests/cases/nightly.rs | 18 +-- 6 files changed, 141 insertions(+), 102 deletions(-) diff --git a/chain-signatures/contract/src/lib.rs b/chain-signatures/contract/src/lib.rs index 8431b4886..b51afb458 100644 --- a/chain-signatures/contract/src/lib.rs +++ b/chain-signatures/contract/src/lib.rs @@ -101,7 +101,7 @@ impl MpcContract { pending_requests: LookupMap::new(StorageKey::PendingRequests), request_counter: 0, proposed_updates: ProposedUpdates::default(), - config: config.unwrap_or_else(Config::default), + config: config.unwrap_or_default(), } } } @@ -642,7 +642,7 @@ impl VersionedMpcContract { pending_requests: LookupMap::new(StorageKey::PendingRequests), request_counter: 0, proposed_updates: ProposedUpdates::default(), - config: config.unwrap_or_else(Config::default), + config: config.unwrap_or_default(), })) } diff --git a/chain-signatures/node/src/cli.rs b/chain-signatures/node/src/cli.rs index cb32c3a5e..9fe16a8ee 100644 --- a/chain-signatures/node/src/cli.rs +++ b/chain-signatures/node/src/cli.rs @@ -1,4 +1,4 @@ -use crate::config::{Config, LocalConfig, NetworkConfig}; +use crate::config::{Config, LocalConfig, NetworkConfig, OverrideConfig}; use crate::gcp::GcpService; use crate::protocol::{MpcSignProtocol, SignQueue}; use crate::storage::triple_storage::LockTripleNodeStorageBox; @@ -59,30 +59,9 @@ pub enum Cli { /// Storage options #[clap(flatten)] storage_options: storage::Options, - // /// At minimum, how many triples to stockpile on this node. - // #[arg(long, env("MPC_MIN_TRIPLES"), default_value("20"))] - // min_triples: usize, - // /// At maximum, how many triples to stockpile on this node. - // #[arg(long, env("MPC_MAX_TRIPLES"), default_value("640"))] - // max_triples: usize, - - // /// At maximum, how many triple protocols can this current node introduce - // /// at the same time. This should be something like `max_concurrent_gen / num_nodes` - // #[arg(long, env("MPC_MAX_CONCURRENT_INTRODUCTION"), default_value("2"))] - // max_concurrent_introduction: usize, - - // /// At maximum, how many ongoing protocols for triples to be running - // /// at the same time. The rest will be queued up. - // #[arg(long, env("MPC_MAX_CONCURRENT_GENERATION"), default_value("16"))] - // max_concurrent_generation: usize, - - // /// At minimum, how many presignatures to stockpile on this node. - // #[arg(long, env("MPC_MIN_PRESIGNATURES"), default_value("10"))] - // min_presignatures: usize, - - // /// At maximum, how many presignatures to stockpile on the network. - // #[arg(long, env("MPC_MAX_PRESIGNATURES"), default_value("320"))] - // max_presignatures: usize, + /// The set of configurations that we will use to override contract configurations. + #[arg(long, env("MPC_OVERRIDE_CONFIG"), value_parser = clap::value_parser!(OverrideConfig))] + override_config: Option, }, } @@ -101,12 +80,7 @@ impl Cli { indexer_options, my_address, storage_options, - // min_triples, - // max_triples, - // max_concurrent_introduction, - // max_concurrent_generation, - // min_presignatures, - // max_presignatures, + override_config, } => { let mut args = vec![ "start".to_string(), @@ -124,18 +98,6 @@ impl Cli { cipher_pk, "--cipher-sk".to_string(), cipher_sk, - // "--min-triples".to_string(), - // min_triples.to_string(), - // "--max-triples".to_string(), - // max_triples.to_string(), - // "--max-concurrent-introduction".to_string(), - // max_concurrent_introduction.to_string(), - // "--max-concurrent-generation".to_string(), - // max_concurrent_generation.to_string(), - // "--min-presignatures".to_string(), - // min_presignatures.to_string(), - // "--max-presignatures".to_string(), - // max_presignatures.to_string(), ]; if let Some(sign_sk) = sign_sk { args.extend(["--sign-sk".to_string(), sign_sk.to_string()]); @@ -143,6 +105,13 @@ impl Cli { if let Some(my_address) = my_address { args.extend(["--my-address".to_string(), my_address.to_string()]); } + if let Some(override_config) = override_config { + args.extend([ + "--override-config".to_string(), + serde_json::to_string(&override_config).unwrap(), + ]); + } + args.extend(indexer_options.into_str_args()); args.extend(storage_options.into_str_args()); args @@ -194,12 +163,7 @@ pub fn run(cmd: Cli) -> anyhow::Result<()> { indexer_options, my_address, storage_options, - // min_triples, - // max_triples, - // max_concurrent_introduction, - // max_concurrent_generation, - // min_presignatures, - // max_presignatures, + override_config, } => { let sign_queue = Arc::new(RwLock::new(SignQueue::new())); let rt = tokio::runtime::Builder::new_multi_thread() @@ -249,15 +213,13 @@ pub fn run(cmd: Cli) -> anyhow::Result<()> { sign_queue, key_storage, triple_storage, - Config { - protocol: Default::default(), - local: LocalConfig { - network: NetworkConfig { - cipher_pk: hpke::PublicKey::try_from_bytes(&hex::decode(cipher_pk)?)?, - sign_sk, - }, + Config::new(LocalConfig { + over: override_config.unwrap_or_else(Default::default), + network: NetworkConfig { + cipher_pk: hpke::PublicKey::try_from_bytes(&hex::decode(cipher_pk)?)?, + sign_sk, }, - }, + }), ); rt.block_on(async { diff --git a/chain-signatures/node/src/config.rs b/chain-signatures/node/src/config.rs index 0894c9e49..8b32f11d4 100644 --- a/chain-signatures/node/src/config.rs +++ b/chain-signatures/node/src/config.rs @@ -1,10 +1,13 @@ use std::collections::HashMap; +use std::str::FromStr; use mpc_contract::config::ProtocolConfig; use mpc_keys::hpke; +use serde::{Deserialize, Serialize}; +use serde_json::Value; /// The contract's config is a dynamic representation of all configurations possible. -pub type ContractConfig = HashMap; +pub type ContractConfig = HashMap; #[derive(Clone, Debug, Default)] pub struct Config { @@ -13,8 +16,25 @@ pub struct Config { } impl Config { + pub fn new(local: LocalConfig) -> Self { + let mut protocol = ProtocolConfig::default(); + + // We should also override are default initalized config if our overrides are present: + if let Some(map) = local.over.entries.as_object() { + if map.len() > 0 { + let mut base = serde_json::to_value(protocol).unwrap(); + merge(&mut base, &local.over.entries); + protocol = serde_json::from_value(base).unwrap(); + } + } + + Self { protocol, local } + } + pub fn try_from_contract(mut contract: ContractConfig, original: &Config) -> Option { - let Ok(protocol) = serde_json::from_value(contract.remove("protocol")?) else { + let mut protocol = contract.remove("protocol")?; + merge(&mut protocol, &original.local.over.entries); + let Ok(protocol) = serde_json::from_value(protocol) else { return None; }; @@ -30,6 +50,7 @@ impl Config { #[derive(Clone, Debug, Default)] pub struct LocalConfig { pub network: NetworkConfig, + pub over: OverrideConfig, } #[derive(Clone, Debug)] @@ -49,3 +70,85 @@ impl Default for NetworkConfig { } } } + +/// The override config is the set of configurations we want to override from the +/// default configuration. This is a partial set of configurations, purely only +/// the values that the node wants to override. +/// +/// The set of configs that can be overridden are only the non-[`LocalConfig`] +/// ones since we already control those. +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +pub struct OverrideConfig { + entries: Value, +} + +impl OverrideConfig { + pub fn new(entries: Value) -> Self { + Self { entries } + } +} + +impl FromStr for OverrideConfig { + type Err = serde_json::Error; + + fn from_str(s: &str) -> Result { + serde_json::from_str(s) + } +} + +pub fn merge(base: &mut Value, new: &Value) { + match (base, new) { + (base @ &mut Value::Object(_), Value::Object(new)) => { + let base = base.as_object_mut().unwrap(); + for (key, new_value) in new { + let base = base.entry(key).or_insert(Value::Null); + merge(base, new_value); + } + } + (base, new) => *base = new.clone(), + } +} + +#[cfg(test)] +mod tests { + use serde::Deserialize; + + use super::merge; + + #[test] + fn test_merge() { + #[allow(dead_code)] + #[derive(Debug, Deserialize)] + struct B { + c: i32, + d: i32, + } + + #[allow(dead_code)] + #[derive(Debug, Deserialize)] + struct Base { + a: i32, + b: B, + } + + let mut base = serde_json::json!( { + "a": 1, + "b": { + "c": 2, + "d": 3, + }, + }); + + let new = serde_json::json!({ + "b": { + "c": 4, + "e": 5, + }, + "f": 6, + }); + + merge(&mut base, &new); + let base: Base = serde_json::from_value(base).unwrap(); + dbg!(base); + } +} diff --git a/integration-tests/chain-signatures/src/containers.rs b/integration-tests/chain-signatures/src/containers.rs index c4f2c0900..5d31c62eb 100644 --- a/integration-tests/chain-signatures/src/containers.rs +++ b/integration-tests/chain-signatures/src/containers.rs @@ -7,6 +7,7 @@ use bollard::exec::CreateExecOptions; use bollard::{container::LogsOptions, network::CreateNetworkOptions, service::Ipam, Docker}; use futures::{lock::Mutex, StreamExt}; use mpc_keys::hpke; +use mpc_node::config::OverrideConfig; use near_workspaces::AccountId; use once_cell::sync::Lazy; use serde_json::json; @@ -83,12 +84,9 @@ impl<'a> Node<'a> { indexer_options: indexer_options.clone(), my_address: None, storage_options: ctx.storage_options.clone(), - // min_triples: cfg.triple_cfg.min_triples, - // max_triples: cfg.triple_cfg.max_triples, - // max_concurrent_introduction: cfg.triple_cfg.max_concurrent_introduction, - // max_concurrent_generation: cfg.triple_cfg.max_concurrent_generation, - // min_presignatures: cfg.presig_cfg.min_presignatures, - // max_presignatures: cfg.presig_cfg.max_presignatures, + override_config: Some(OverrideConfig::new(serde_json::to_value( + cfg.protocol.clone(), + )?)), } .into_str_args(); let image: GenericImage = GenericImage::new("near/mpc-node", "latest") @@ -171,13 +169,10 @@ impl<'a> Node<'a> { indexer_options: indexer_options.clone(), my_address: None, storage_options: storage_options.clone(), - // min_triples: cfg.protocol.triple.min_triples, - // max_triples: cfg.protocol.triple.max_triples, - // max_concurrent_introduction: cfg.triple_cfg.max_concurrent_introduction, - // max_concurrent_generation: cfg.triple_cfg.max_concurrent_generation, - // min_presignatures: cfg.presig_cfg.min_presignatures, - // max_presignatures: cfg.presig_cfg.max_presignatures, sign_sk: Some(sign_sk), + override_config: Some(OverrideConfig::new(serde_json::to_value( + cfg.protocol.clone(), + )?)), } .into_str_args(); let image: GenericImage = GenericImage::new("near/mpc-node", "latest") diff --git a/integration-tests/chain-signatures/src/local.rs b/integration-tests/chain-signatures/src/local.rs index f100d74e4..bf4839e16 100644 --- a/integration-tests/chain-signatures/src/local.rs +++ b/integration-tests/chain-signatures/src/local.rs @@ -3,6 +3,7 @@ use crate::{execute, utils, MultichainConfig}; use crate::containers::LakeIndexer; use async_process::Child; use mpc_keys::hpke; +use mpc_node::config::OverrideConfig; use near_workspaces::AccountId; pub struct Node { @@ -77,12 +78,9 @@ impl Node { indexer_options, my_address: None, storage_options: ctx.storage_options.clone(), - // min_triples: cfg.triple_cfg.min_triples, - // max_triples: cfg.triple_cfg.max_triples, - // max_concurrent_introduction: cfg.triple_cfg.max_concurrent_introduction, - // max_concurrent_generation: cfg.triple_cfg.max_concurrent_generation, - // min_presignatures: cfg.presig_cfg.min_presignatures, - // max_presignatures: cfg.presig_cfg.max_presignatures, + override_config: Some(OverrideConfig::new(serde_json::to_value( + cfg.protocol.clone(), + )?)), }; let mpc_node_id = format!("multichain/{account_id}", account_id = account_id); @@ -135,12 +133,9 @@ impl Node { indexer_options: indexer_options.clone(), my_address: None, storage_options: storage_options.clone(), - // min_triples: cfg.triple_cfg.min_triples, - // max_triples: cfg.triple_cfg.max_triples, - // max_concurrent_introduction: cfg.triple_cfg.max_concurrent_introduction, - // max_concurrent_generation: cfg.triple_cfg.max_concurrent_generation, - // min_presignatures: cfg.presig_cfg.min_presignatures, - // max_presignatures: cfg.presig_cfg.max_presignatures, + override_config: Some(OverrideConfig::new(serde_json::to_value( + cfg.protocol.clone(), + )?)), }; let mpc_node_id = format!("multichain/{account_id}", account_id = account_id); diff --git a/integration-tests/chain-signatures/tests/cases/nightly.rs b/integration-tests/chain-signatures/tests/cases/nightly.rs index ccadde63a..94e466fa3 100644 --- a/integration-tests/chain-signatures/tests/cases/nightly.rs +++ b/integration-tests/chain-signatures/tests/cases/nightly.rs @@ -1,4 +1,5 @@ use integration_tests_chain_signatures::MultichainConfig; +use mpc_contract::config::{ProtocolConfig, TripleConfig}; use test_log::test; use crate::actions::{self, wait_for}; @@ -13,23 +14,6 @@ async fn test_nightly_signature_production() -> anyhow::Result<()> { const MIN_TRIPLES: usize = 10; const MAX_TRIPLES: usize = 2 * NODES * MIN_TRIPLES; - // let triple_cfg = TripleConfig { - // // This is the min triples required by each node. - // min_triples: MIN_TRIPLES, - // // This is the total amount of triples that will be generated by all nodes. - // max_triples: MAX_TRIPLES, - // // This is the amount each node can introduce a triple generation protocol into the system. - // max_concurrent_introduction: 4, - // // This is the maximum amount of triples that can be generated concurrently by the whole system. - // max_concurrent_generation: 24, - // }; - // let presig_cfg = PresignatureConfig { - // // this is the min presignatures required by each node - // min_presignatures: 10, - // // This is the total amount of presignatures that will be generated by all nodes. - // max_presignatures: 1000, - // }; - let config = MultichainConfig { nodes: NODES, threshold: THRESHOLD, From eb84b36885d1dd6bee810be22ffaeff16394523f Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Thu, 25 Jul 2024 01:20:21 -0700 Subject: [PATCH 21/24] Added SignatureConfig --- chain-signatures/contract/src/config/impls.rs | 15 ++++++++++++++- chain-signatures/contract/src/config/mod.rs | 12 ++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/chain-signatures/contract/src/config/impls.rs b/chain-signatures/contract/src/config/impls.rs index c9e1b42c6..a42dbe6dc 100644 --- a/chain-signatures/contract/src/config/impls.rs +++ b/chain-signatures/contract/src/config/impls.rs @@ -1,6 +1,8 @@ use borsh::{self, BorshDeserialize, BorshSerialize}; -use super::{Config, DynamicValue, PresignatureConfig, ProtocolConfig, TripleConfig}; +use super::{ + Config, DynamicValue, PresignatureConfig, ProtocolConfig, SignatureConfig, TripleConfig, +}; const MAX_EXPECTED_PARTICIPANTS: usize = 32; @@ -27,6 +29,7 @@ impl Default for ProtocolConfig { max_concurrent_generation: 4 * MAX_EXPECTED_PARTICIPANTS, triple: TripleConfig::default(), presignature: PresignatureConfig::default(), + signature: Default::default(), other: Default::default(), } @@ -57,6 +60,16 @@ impl Default for PresignatureConfig { } } +impl Default for SignatureConfig { + fn default() -> Self { + Self { + generation_timeout: secs_to_ms(60), + + other: Default::default(), + } + } +} + impl From for DynamicValue { fn from(value: serde_json::Value) -> Self { Self(value) diff --git a/chain-signatures/contract/src/config/mod.rs b/chain-signatures/contract/src/config/mod.rs index 06ccaf480..0e6f2a43d 100644 --- a/chain-signatures/contract/src/config/mod.rs +++ b/chain-signatures/contract/src/config/mod.rs @@ -36,6 +36,8 @@ pub struct ProtocolConfig { pub triple: TripleConfig, /// Configuration for presignature generation. pub presignature: PresignatureConfig, + /// Configuration for signature generation. + pub signature: SignatureConfig, /// The remaining entries that can be present in future forms of the configuration. #[serde(flatten)] @@ -70,6 +72,16 @@ pub struct PresignatureConfig { pub other: HashMap, } +#[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] +pub struct SignatureConfig { + /// Timeout for signature generation in milliseconds. + pub generation_timeout: u64, + + /// The remaining entries that can be present in future forms of the configuration. + #[serde(flatten)] + pub other: HashMap, +} + #[cfg(test)] mod tests { use crate::config::Config; From a08817e5f2271fe164342f2ff9f539e5825c5aef Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Thu, 25 Jul 2024 01:39:16 -0700 Subject: [PATCH 22/24] Use timeouts from contract configs --- chain-signatures/contract/src/config/impls.rs | 1 + chain-signatures/contract/src/config/mod.rs | 2 ++ chain-signatures/node/src/http_client.rs | 19 +++++++------- .../node/src/protocol/cryptography.rs | 7 +++++ chain-signatures/node/src/protocol/message.rs | 8 +++--- .../node/src/protocol/presignature.rs | 22 +++++++++++++--- .../node/src/protocol/signature.rs | 26 ++++++++++++++++--- chain-signatures/node/src/protocol/triple.rs | 2 +- chain-signatures/node/src/types.rs | 9 ------- chain-signatures/node/src/util.rs | 11 ++------ infra/multichain-dev/variables.tf | 4 --- infra/multichain-mainnet-dev/variables.tf | 4 --- 12 files changed, 69 insertions(+), 46 deletions(-) diff --git a/chain-signatures/contract/src/config/impls.rs b/chain-signatures/contract/src/config/impls.rs index a42dbe6dc..f232f35bb 100644 --- a/chain-signatures/contract/src/config/impls.rs +++ b/chain-signatures/contract/src/config/impls.rs @@ -25,6 +25,7 @@ impl Config { impl Default for ProtocolConfig { fn default() -> Self { Self { + message_timeout: min_to_ms(5), max_concurrent_introduction: 4, max_concurrent_generation: 4 * MAX_EXPECTED_PARTICIPANTS, triple: TripleConfig::default(), diff --git a/chain-signatures/contract/src/config/mod.rs b/chain-signatures/contract/src/config/mod.rs index 0e6f2a43d..25c5e3735 100644 --- a/chain-signatures/contract/src/config/mod.rs +++ b/chain-signatures/contract/src/config/mod.rs @@ -26,6 +26,8 @@ pub struct Config { #[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] pub struct ProtocolConfig { + /// Message timeout in milliseconds for any protocol message that gets sent over the wire. + pub message_timeout: u64, /// Maximum amount of concurrent protocol generation that can be introduced by this node. /// This only includes protocols that generate triples and presignatures. pub max_concurrent_introduction: usize, diff --git a/chain-signatures/node/src/http_client.rs b/chain-signatures/node/src/http_client.rs index 7ab55a480..970640f2a 100644 --- a/chain-signatures/node/src/http_client.rs +++ b/chain-signatures/node/src/http_client.rs @@ -2,6 +2,7 @@ use crate::protocol::contract::primitives::{ParticipantInfo, Participants}; use crate::protocol::message::SignedMessage; use crate::protocol::MpcMessage; use cait_sith::protocol::Participant; +use mpc_contract::config::ProtocolConfig; use mpc_keys::hpke::Ciphered; use reqwest::{Client, IntoUrl}; use std::collections::{HashMap, HashSet, VecDeque}; @@ -10,9 +11,6 @@ use std::time::{Duration, Instant}; use tokio_retry::strategy::{jitter, ExponentialBackoff}; use tokio_retry::Retry; -// 5 minutes max to wait for this message to be sent by defaults -const MESSAGE_TIMEOUT: Duration = Duration::from_secs(5 * 60); - #[derive(Debug, thiserror::Error)] pub enum SendError { #[error("http request was unsuccessful: {0}")] @@ -102,6 +100,7 @@ impl MessageQueue { sign_sk: &near_crypto::SecretKey, client: &Client, participants: &Participants, + cfg: &ProtocolConfig, ) -> Vec { let mut failed = VecDeque::new(); let mut errors = Vec::new(); @@ -111,7 +110,7 @@ impl MessageQueue { let uncompacted = self.deque.len(); let mut encrypted = HashMap::new(); while let Some((info, msg, instant)) = self.deque.pop_front() { - if instant.elapsed() > message_type_to_timeout(&msg) { + if instant.elapsed() > timeout(&msg, cfg) { errors.push(SendError::Timeout(format!( "{} message has timed out: {info:?}", msg.typename(), @@ -221,13 +220,13 @@ fn partition_ciphered_256kb(encrypted: Vec) -> Vec Duration { +fn timeout(msg: &MpcMessage, cfg: &ProtocolConfig) -> Duration { match msg { - MpcMessage::Generating(_) => MESSAGE_TIMEOUT, - MpcMessage::Resharing(_) => MESSAGE_TIMEOUT, - MpcMessage::Triple(_) => crate::util::get_triple_timeout(), - MpcMessage::Presignature(_) => crate::types::PROTOCOL_PRESIG_TIMEOUT, - MpcMessage::Signature(_) => crate::types::PROTOCOL_SIGNATURE_TIMEOUT, + MpcMessage::Generating(_) => Duration::from_millis(cfg.message_timeout), + MpcMessage::Resharing(_) => Duration::from_millis(cfg.message_timeout), + MpcMessage::Triple(_) => Duration::from_millis(cfg.triple.generation_timeout), + MpcMessage::Presignature(_) => Duration::from_millis(cfg.presignature.generation_timeout), + MpcMessage::Signature(_) => Duration::from_millis(cfg.signature.generation_timeout), } } diff --git a/chain-signatures/node/src/protocol/cryptography.rs b/chain-signatures/node/src/protocol/cryptography.rs index 3d6f91bcd..5713f27d2 100644 --- a/chain-signatures/node/src/protocol/cryptography.rs +++ b/chain-signatures/node/src/protocol/cryptography.rs @@ -100,6 +100,7 @@ impl CryptographicProtocol for GeneratingState { &ctx.cfg().local.network.sign_sk, ctx.http_client(), ctx.mesh().active_participants(), + &ctx.cfg().protocol, ) .await; if !failures.is_empty() { @@ -161,6 +162,7 @@ impl CryptographicProtocol for GeneratingState { &ctx.cfg().local.network.sign_sk, ctx.http_client(), ctx.mesh().active_participants(), + &ctx.cfg().protocol, ) .await; if !failures.is_empty() { @@ -198,6 +200,7 @@ impl CryptographicProtocol for WaitingForConsensusState { &ctx.cfg().local.network.sign_sk, ctx.http_client(), ctx.mesh().active_participants(), + &ctx.cfg().protocol, ) .await; if !failures.is_empty() { @@ -253,6 +256,7 @@ impl CryptographicProtocol for ResharingState { &ctx.cfg().local.network.sign_sk, ctx.http_client(), &active, + &ctx.cfg().protocol, ) .await; if !failures.is_empty() { @@ -320,6 +324,7 @@ impl CryptographicProtocol for ResharingState { &ctx.cfg().local.network.sign_sk, ctx.http_client(), &active, + &ctx.cfg().protocol, ) .await; if !failures.is_empty() { @@ -438,6 +443,7 @@ impl CryptographicProtocol for RunningState { &stable, my_requests, &mut presignature_manager, + protocol_cfg, ); drop(sign_queue); drop(presignature_manager); @@ -461,6 +467,7 @@ impl CryptographicProtocol for RunningState { &ctx.cfg().local.network.sign_sk, ctx.http_client(), active, + protocol_cfg, ) .await; if !failures.is_empty() { diff --git a/chain-signatures/node/src/protocol/message.rs b/chain-signatures/node/src/protocol/message.rs index af0f4df8e..4bfc00e46 100644 --- a/chain-signatures/node/src/protocol/message.rs +++ b/chain-signatures/node/src/protocol/message.rs @@ -243,7 +243,7 @@ impl MessageHandler for RunningState { || queue.iter().any(|msg| { util::is_elapsed_longer_than_timeout( msg.timestamp, - crate::types::PROTOCOL_TRIPLE_TIMEOUT, + protocol_cfg.triple.generation_timeout, ) }) { @@ -280,7 +280,7 @@ impl MessageHandler for RunningState { || queue.iter().any(|msg| { util::is_elapsed_longer_than_timeout( msg.timestamp, - crate::types::PROTOCOL_PRESIG_TIMEOUT, + protocol_cfg.presignature.generation_timeout, ) }) { @@ -316,6 +316,7 @@ impl MessageHandler for RunningState { &mut triple_manager, &self.public_key, &self.private_share, + protocol_cfg, ) .await { @@ -370,7 +371,7 @@ impl MessageHandler for RunningState { || queue.iter().any(|msg| { util::is_elapsed_longer_than_timeout( msg.timestamp, - crate::types::PROTOCOL_SIGNATURE_TIMEOUT, + protocol_cfg.signature.generation_timeout, ) }) { @@ -418,6 +419,7 @@ impl MessageHandler for RunningState { *epsilon, *delta, &mut presignature_manager, + protocol_cfg, ) { Ok(protocol) => protocol, Err(GenerationError::PresignatureIsGenerating(_)) => { diff --git a/chain-signatures/node/src/protocol/presignature.rs b/chain-signatures/node/src/protocol/presignature.rs index b1e4ed29b..5dfba6d9f 100644 --- a/chain-signatures/node/src/protocol/presignature.rs +++ b/chain-signatures/node/src/protocol/presignature.rs @@ -12,7 +12,7 @@ use k256::Secp256k1; use mpc_contract::config::ProtocolConfig; use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet, VecDeque}; -use std::time::Instant; +use std::time::{Duration, Instant}; use near_account_id::AccountId; @@ -36,6 +36,7 @@ pub struct PresignatureGenerator { pub triple1: TripleId, pub mine: bool, pub timestamp: Instant, + pub timeout: Duration, } impl PresignatureGenerator { @@ -45,6 +46,7 @@ impl PresignatureGenerator { triple0: TripleId, triple1: TripleId, mine: bool, + timeout: u64, ) -> Self { Self { protocol, @@ -53,11 +55,12 @@ impl PresignatureGenerator { triple1, mine, timestamp: Instant::now(), + timeout: Duration::from_millis(timeout), } } pub fn poke(&mut self) -> Result>, ProtocolError> { - if self.timestamp.elapsed() > crate::types::PROTOCOL_PRESIG_TIMEOUT { + if self.timestamp.elapsed() > self.timeout { tracing::info!( self.triple0, self.triple1, @@ -170,6 +173,7 @@ impl PresignatureManager { public_key: &PublicKey, private_share: &SecretKeyShare, mine: bool, + timeout: u64, ) -> Result { let participants: Vec<_> = participants.keys().cloned().collect(); let protocol = Box::new(cait_sith::presign( @@ -195,6 +199,7 @@ impl PresignatureManager { triple0.id, triple1.id, mine, + timeout, )) } @@ -206,6 +211,7 @@ impl PresignatureManager { triple1: Triple, public_key: &PublicKey, private_share: &SecretKeyShare, + timeout: u64, ) -> Result<(), InitializationError> { let id = rand::random(); @@ -229,6 +235,7 @@ impl PresignatureManager { public_key, private_share, true, + timeout, )?; self.generators.insert(id, generator); self.introduced.insert(id); @@ -280,7 +287,14 @@ impl PresignatureManager { triple_manager.insert_mine(triple0).await; triple_manager.insert_mine(triple1).await; } else { - self.generate(&presig_participants, triple0, triple1, pk, sk_share)?; + self.generate( + &presig_participants, + triple0, + triple1, + pk, + sk_share, + cfg.presignature.generation_timeout, + )?; } } else { tracing::debug!("running: we don't have enough triples to generate a presignature"); @@ -306,6 +320,7 @@ impl PresignatureManager { triple_manager: &mut TripleManager, public_key: &PublicKey, private_share: &SecretKeyShare, + cfg: &ProtocolConfig, ) -> Result<&mut PresignatureProtocol, GenerationError> { if self.presignatures.contains_key(&id) { Err(GenerationError::AlreadyGenerated) @@ -362,6 +377,7 @@ impl PresignatureManager { public_key, private_share, false, + cfg.presignature.generation_timeout, )?; let generator = entry.insert(generator); crate::metrics::NUM_TOTAL_HISTORICAL_PRESIGNATURE_GENERATORS diff --git a/chain-signatures/node/src/protocol/signature.rs b/chain-signatures/node/src/protocol/signature.rs index 1dd5e4687..7ea715f01 100644 --- a/chain-signatures/node/src/protocol/signature.rs +++ b/chain-signatures/node/src/protocol/signature.rs @@ -12,6 +12,7 @@ use chrono::Utc; use crypto_shared::SerializableScalar; use crypto_shared::{derive_key, PublicKey}; use k256::{Scalar, Secp256k1}; +use mpc_contract::config::ProtocolConfig; use mpc_contract::primitives::SignatureRequest; use rand::rngs::StdRng; use rand::seq::{IteratorRandom, SliceRandom}; @@ -124,6 +125,7 @@ pub struct SignatureGenerator { pub delta: Scalar, pub sign_request_timestamp: Instant, pub generator_timestamp: Instant, + pub timeout: Duration, } impl SignatureGenerator { @@ -137,6 +139,7 @@ impl SignatureGenerator { epsilon: Scalar, delta: Scalar, sign_request_timestamp: Instant, + timeout: u64, ) -> Self { Self { protocol, @@ -148,11 +151,12 @@ impl SignatureGenerator { delta, sign_request_timestamp, generator_timestamp: Instant::now(), + timeout: Duration::from_millis(timeout), } } pub fn poke(&mut self) -> Result>, ProtocolError> { - if self.generator_timestamp.elapsed() > crate::types::PROTOCOL_SIGNATURE_TIMEOUT { + if self.generator_timestamp.elapsed() > self.timeout { tracing::info!(self.presignature_id, "signature protocol timed out"); return Err(ProtocolError::Other( anyhow::anyhow!("signature protocol timed out").into(), @@ -242,6 +246,7 @@ impl SignatureManager { public_key: PublicKey, presignature: Presignature, req: GenerationRequest, + timeout: u64, ) -> Result { let participants = participants.keys_vec(); let GenerationRequest { @@ -274,6 +279,7 @@ impl SignatureManager { epsilon, delta, sign_request_timestamp, + timeout, )) } @@ -283,10 +289,17 @@ impl SignatureManager { req: GenerationRequest, presignature: Presignature, participants: &Participants, + timeout: u64, ) -> Result<(), InitializationError> { tracing::info!(receipt_id = %receipt_id, participants = ?participants.keys_vec(), "restarting failed protocol to generate signature"); - let generator = - Self::generate_internal(participants, self.me, self.public_key, presignature, req)?; + let generator = Self::generate_internal( + participants, + self.me, + self.public_key, + presignature, + req, + timeout, + )?; self.generators.insert(receipt_id, generator); Ok(()) } @@ -302,6 +315,7 @@ impl SignatureManager { epsilon: Scalar, delta: Scalar, sign_request_timestamp: Instant, + timeout: u64, ) -> Result<(), InitializationError> { tracing::info!( %receipt_id, @@ -322,6 +336,7 @@ impl SignatureManager { delta, sign_request_timestamp, }, + timeout, )?; self.generators.insert(receipt_id, generator); Ok(()) @@ -344,6 +359,7 @@ impl SignatureManager { epsilon: Scalar, delta: Scalar, presignature_manager: &mut PresignatureManager, + cfg: &ProtocolConfig, ) -> Result<&mut SignatureProtocol, GenerationError> { if self.completed.contains_key(&presignature_id) { tracing::warn!(%receipt_id, presignature_id, "presignature has already been used to generate a signature"); @@ -381,6 +397,7 @@ impl SignatureManager { delta, sign_request_timestamp: Instant::now(), }, + cfg.signature.generation_timeout, )?; let generator = entry.insert(generator); Ok(&mut generator.protocol) @@ -491,6 +508,7 @@ impl SignatureManager { stable: &Participants, my_requests: &mut HashMap, presignature_manager: &mut PresignatureManager, + cfg: &ProtocolConfig, ) { let mut failed_presigs = Vec::new(); while let Some(mut presignature) = { @@ -521,6 +539,7 @@ impl SignatureManager { failed_req, presignature, &sig_participants, + cfg.signature.generation_timeout, ) { tracing::warn!(%receipt_id, presig_id, ?err, "failed to retry signature generation: trashing presignature"); continue; @@ -549,6 +568,7 @@ impl SignatureManager { my_request.epsilon, my_request.delta, my_request.time_added, + cfg.signature.generation_timeout, ) { tracing::warn!(%receipt_id, presig_id, ?err, "failed to start signature generation: trashing presignature"); continue; diff --git a/chain-signatures/node/src/protocol/triple.rs b/chain-signatures/node/src/protocol/triple.rs index 578441396..2e5249da1 100644 --- a/chain-signatures/node/src/protocol/triple.rs +++ b/chain-signatures/node/src/protocol/triple.rs @@ -62,7 +62,7 @@ impl TripleGenerator { pub fn poke(&mut self) -> Result>, ProtocolError> { let timestamp = self.timestamp.get_or_insert_with(Instant::now); - if timestamp.elapsed() > crate::util::get_triple_timeout() { + if timestamp.elapsed() > self.timeout { tracing::info!( id = self.id, elapsed = ?timestamp.elapsed(), diff --git a/chain-signatures/node/src/types.rs b/chain-signatures/node/src/types.rs index 6be92800e..416fb3ea5 100644 --- a/chain-signatures/node/src/types.rs +++ b/chain-signatures/node/src/types.rs @@ -16,15 +16,6 @@ use crate::protocol::contract::ResharingContractState; use near_account_id::AccountId; -/// Default timeout for triple generation protocols. Times out after 20 minutes of being alive. -pub const PROTOCOL_TRIPLE_TIMEOUT: Duration = Duration::from_secs(20 * 60); - -/// Default timeout for presig generation protocols. Times out after 1 minute of being alive since this should be shorted lived. -pub const PROTOCOL_PRESIG_TIMEOUT: Duration = Duration::from_secs(60); - -/// Default timeout for signature generation protocol. Times out after 1 minute of being alive since this should be shorted lived. -pub const PROTOCOL_SIGNATURE_TIMEOUT: Duration = Duration::from_secs(60); - /// Default invalidation time for failed triples: 2 hrs pub const FAILED_TRIPLES_TIMEOUT: Duration = Duration::from_secs(120 * 60); diff --git a/chain-signatures/node/src/util.rs b/chain-signatures/node/src/util.rs index 1f7b9874f..85ebb147e 100644 --- a/chain-signatures/node/src/util.rs +++ b/chain-signatures/node/src/util.rs @@ -2,7 +2,6 @@ use chrono::{DateTime, LocalResult, TimeZone, Utc}; use crypto_shared::{near_public_key_to_affine_point, PublicKey}; use k256::elliptic_curve::sec1::{FromEncodedPoint, ToEncodedPoint}; use k256::{AffinePoint, EncodedPoint}; -use std::env; use std::time::Duration; pub trait NearPublicKeyExt { @@ -64,15 +63,9 @@ impl AffinePointExt for AffinePoint { } } -pub fn get_triple_timeout() -> Duration { - env::var("MPC_TRIPLE_TIMEOUT_SEC") - .map(|val| val.parse::().ok().map(Duration::from_secs)) - .unwrap_or_default() - .unwrap_or(crate::types::PROTOCOL_TRIPLE_TIMEOUT) -} - -pub fn is_elapsed_longer_than_timeout(timestamp_sec: u64, timeout: Duration) -> bool { +pub fn is_elapsed_longer_than_timeout(timestamp_sec: u64, timeout: u64) -> bool { if let LocalResult::Single(msg_timestamp) = Utc.timestamp_opt(timestamp_sec as i64, 0) { + let timeout = Duration::from_millis(timeout); let now_datetime: DateTime = Utc::now(); // Calculate the difference in seconds let elapsed_duration = now_datetime.signed_duration_since(msg_timestamp); diff --git a/infra/multichain-dev/variables.tf b/infra/multichain-dev/variables.tf index 7c03d0926..a7aa28122 100644 --- a/infra/multichain-dev/variables.tf +++ b/infra/multichain-dev/variables.tf @@ -144,10 +144,6 @@ variable "static_env" { { name = "MPC_MAX_CONCURRENT_GENERATION" value = 16 - }, - { - name = "MPC_TRIPLE_TIMEOUT_SEC" - value = 1200 } ] } diff --git a/infra/multichain-mainnet-dev/variables.tf b/infra/multichain-mainnet-dev/variables.tf index 5cb9639cb..11c6c3fe1 100644 --- a/infra/multichain-mainnet-dev/variables.tf +++ b/infra/multichain-mainnet-dev/variables.tf @@ -145,10 +145,6 @@ variable "static_env" { { name = "MPC_MAX_CONCURRENT_GENERATION" value = 16 - }, - { - name = "MPC_TRIPLE_TIMEOUT_SEC" - value = 1200 } ] } From 4d7931f59b07534be61a9aed8efe718bc4f1c666 Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Thu, 25 Jul 2024 01:46:40 -0700 Subject: [PATCH 23/24] Removed no longer needed env variables from tf --- infra/multichain-dev/variables.tf | 20 ------------------- infra/multichain-mainnet-dev/variables.tf | 24 ----------------------- 2 files changed, 44 deletions(-) diff --git a/infra/multichain-dev/variables.tf b/infra/multichain-dev/variables.tf index a7aa28122..34285d630 100644 --- a/infra/multichain-dev/variables.tf +++ b/infra/multichain-dev/variables.tf @@ -124,26 +124,6 @@ variable "static_env" { { name = "MPC_MIN_TRIPLES" value = 20 - }, - { - name = "MPC_MAX_TRIPLES" - value = 640 - }, - { - name = "MPC_MIN_PRESIGNATURES" - value = 10 - }, - { - name = "MPC_MAX_PRESIGNATURES" - value = 320 - }, - { - name = "MPC_MAX_CONCURRENT_INTRODUCTION" - value = 2 - }, - { - name = "MPC_MAX_CONCURRENT_GENERATION" - value = 16 } ] } diff --git a/infra/multichain-mainnet-dev/variables.tf b/infra/multichain-mainnet-dev/variables.tf index 11c6c3fe1..d211993ac 100644 --- a/infra/multichain-mainnet-dev/variables.tf +++ b/infra/multichain-mainnet-dev/variables.tf @@ -122,30 +122,6 @@ variable "static_env" { name = "MPC_INDEXER_S3_REGION" value = "eu-central-1" }, - { - name = "MPC_MIN_TRIPLES" - value = 20 - }, - { - name = "MPC_MAX_TRIPLES" - value = 640 - }, - { - name = "MPC_MIN_PRESIGNATURES" - value = 10 - }, - { - name = "MPC_MAX_PRESIGNATURES" - value = 320 - }, - { - name = "MPC_MAX_CONCURRENT_INTRODUCTION" - value = 2 - }, - { - name = "MPC_MAX_CONCURRENT_GENERATION" - value = 16 - } ] } From d9b358b76c7205d3c76da01172e4c6c09749f7eb Mon Sep 17 00:00:00 2001 From: Phuong Nguyen Date: Thu, 25 Jul 2024 01:58:39 -0700 Subject: [PATCH 24/24] Moved GC timeout to contract config --- chain-signatures/contract/src/config/impls.rs | 5 +++++ chain-signatures/contract/src/config/mod.rs | 5 +++++ chain-signatures/contract/src/update.rs | 1 + chain-signatures/node/src/config.rs | 2 +- chain-signatures/node/src/protocol/message.rs | 6 +++--- chain-signatures/node/src/protocol/presignature.rs | 6 +++--- chain-signatures/node/src/protocol/signature.rs | 10 ++++------ chain-signatures/node/src/protocol/triple.rs | 8 ++++---- chain-signatures/node/src/types.rs | 7 ------- 9 files changed, 26 insertions(+), 24 deletions(-) diff --git a/chain-signatures/contract/src/config/impls.rs b/chain-signatures/contract/src/config/impls.rs index f232f35bb..433f883bd 100644 --- a/chain-signatures/contract/src/config/impls.rs +++ b/chain-signatures/contract/src/config/impls.rs @@ -26,6 +26,7 @@ impl Default for ProtocolConfig { fn default() -> Self { Self { message_timeout: min_to_ms(5), + garbage_timeout: hours_to_ms(2), max_concurrent_introduction: 4, max_concurrent_generation: 4 * MAX_EXPECTED_PARTICIPANTS, triple: TripleConfig::default(), @@ -100,3 +101,7 @@ pub const fn secs_to_ms(secs: u64) -> u64 { pub const fn min_to_ms(min: u64) -> u64 { min * 60 * 1000 } + +pub const fn hours_to_ms(hours: u64) -> u64 { + hours * 60 * 60 * 1000 +} diff --git a/chain-signatures/contract/src/config/mod.rs b/chain-signatures/contract/src/config/mod.rs index 25c5e3735..2f9932732 100644 --- a/chain-signatures/contract/src/config/mod.rs +++ b/chain-signatures/contract/src/config/mod.rs @@ -27,7 +27,12 @@ pub struct Config { #[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize, PartialEq, Eq)] pub struct ProtocolConfig { /// Message timeout in milliseconds for any protocol message that gets sent over the wire. + /// This can be overriden by more specific timeouts in each protocol. pub message_timeout: u64, + /// Garbage collection timeout in milliseconds for any protocol message. This is the timeout + /// used for when any protocols have either been spent or failed, their IDs are kept to keep + /// track of the state of the protocol until this timeout reaches. + pub garbage_timeout: u64, /// Maximum amount of concurrent protocol generation that can be introduced by this node. /// This only includes protocols that generate triples and presignatures. pub max_concurrent_introduction: usize, diff --git a/chain-signatures/contract/src/update.rs b/chain-signatures/contract/src/update.rs index 9ad8bbf3b..d932a1a14 100644 --- a/chain-signatures/contract/src/update.rs +++ b/chain-signatures/contract/src/update.rs @@ -38,6 +38,7 @@ impl From for UpdateId { } } +#[allow(clippy::large_enum_variant)] // TODO: Config is big #[derive(Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize)] pub enum Update { Config(Config), diff --git a/chain-signatures/node/src/config.rs b/chain-signatures/node/src/config.rs index 8b32f11d4..7309e7053 100644 --- a/chain-signatures/node/src/config.rs +++ b/chain-signatures/node/src/config.rs @@ -21,7 +21,7 @@ impl Config { // We should also override are default initalized config if our overrides are present: if let Some(map) = local.over.entries.as_object() { - if map.len() > 0 { + if !map.is_empty() { let mut base = serde_json::to_value(protocol).unwrap(); merge(&mut base, &local.over.entries); protocol = serde_json::from_value(base).unwrap(); diff --git a/chain-signatures/node/src/protocol/message.rs b/chain-signatures/node/src/protocol/message.rs index 4bfc00e46..8e9f76f3e 100644 --- a/chain-signatures/node/src/protocol/message.rs +++ b/chain-signatures/node/src/protocol/message.rs @@ -466,9 +466,9 @@ impl MessageHandler for RunningState { protocol.message(message.from, message.data); } } - triple_manager.garbage_collect(); - presignature_manager.garbage_collect(); - signature_manager.garbage_collect(); + triple_manager.garbage_collect(protocol_cfg); + presignature_manager.garbage_collect(protocol_cfg); + signature_manager.garbage_collect(protocol_cfg); Ok(()) } } diff --git a/chain-signatures/node/src/protocol/presignature.rs b/chain-signatures/node/src/protocol/presignature.rs index 5dfba6d9f..d57cf9b36 100644 --- a/chain-signatures/node/src/protocol/presignature.rs +++ b/chain-signatures/node/src/protocol/presignature.rs @@ -1,7 +1,7 @@ use super::message::PresignatureMessage; use super::triple::{Triple, TripleId, TripleManager}; use crate::protocol::contract::primitives::Participants; -use crate::types::{PresignatureProtocol, SecretKeyShare, TAKEN_TIMEOUT}; +use crate::types::{PresignatureProtocol, SecretKeyShare}; use crate::util::AffinePointExt; use cait_sith::protocol::{Action, InitializationError, Participant, ProtocolError}; @@ -153,9 +153,9 @@ impl PresignatureManager { self.len() == 0 } - pub fn garbage_collect(&mut self) { + pub fn garbage_collect(&mut self, cfg: &ProtocolConfig) { self.gc - .retain(|_, instant| instant.elapsed() < TAKEN_TIMEOUT); + .retain(|_, instant| instant.elapsed() < Duration::from_millis(cfg.garbage_timeout)); } pub fn refresh_gc(&mut self, id: &PresignatureId) -> bool { diff --git a/chain-signatures/node/src/protocol/signature.rs b/chain-signatures/node/src/protocol/signature.rs index 7ea715f01..158df7f01 100644 --- a/chain-signatures/node/src/protocol/signature.rs +++ b/chain-signatures/node/src/protocol/signature.rs @@ -25,9 +25,6 @@ use near_account_id::AccountId; use near_fetch::signer::SignerExt; use near_primitives::hash::CryptoHash; -/// Duration for which completed signatures are retained. -pub const COMPLETION_EXISTENCE_TIMEOUT: Duration = Duration::from_secs(120 * 60); - pub struct SignRequest { pub receipt_id: CryptoHash, pub request: ContractSignRequest, @@ -660,8 +657,9 @@ impl SignatureManager { } /// Garbage collect all the completed signatures. - pub fn garbage_collect(&mut self) { - self.completed - .retain(|_, timestamp| timestamp.elapsed() < COMPLETION_EXISTENCE_TIMEOUT); + pub fn garbage_collect(&mut self, cfg: &ProtocolConfig) { + self.completed.retain(|_, timestamp| { + timestamp.elapsed() < Duration::from_millis(cfg.garbage_timeout) + }); } } diff --git a/chain-signatures/node/src/protocol/triple.rs b/chain-signatures/node/src/protocol/triple.rs index 2e5249da1..206014e62 100644 --- a/chain-signatures/node/src/protocol/triple.rs +++ b/chain-signatures/node/src/protocol/triple.rs @@ -5,7 +5,6 @@ use super::presignature::GenerationError; use crate::gcp::error; use crate::storage::triple_storage::{LockTripleNodeStorageBox, TripleData}; use crate::types::TripleProtocol; -use crate::types::TAKEN_TIMEOUT; use crate::util::AffinePointExt; use cait_sith::protocol::{Action, InitializationError, Participant, ProtocolError}; @@ -190,9 +189,10 @@ impl TripleManager { } /// Clears an entry from failed triples if that triple protocol was created more than 2 hrs ago - pub fn garbage_collect(&mut self) { - self.gc - .retain(|_, timestamp| timestamp.elapsed() < TAKEN_TIMEOUT) + pub fn garbage_collect(&mut self, cfg: &ProtocolConfig) { + self.gc.retain(|_, timestamp| { + timestamp.elapsed() < Duration::from_millis(cfg.garbage_timeout) + }); } /// Refresh item in the garbage collection. If it is present, return true and update internally diff --git a/chain-signatures/node/src/types.rs b/chain-signatures/node/src/types.rs index 416fb3ea5..704bba090 100644 --- a/chain-signatures/node/src/types.rs +++ b/chain-signatures/node/src/types.rs @@ -1,5 +1,4 @@ use std::sync::Arc; -use std::time::Duration; use cait_sith::protocol::{InitializationError, Participant}; use cait_sith::triples::TripleGenerationOutput; @@ -16,12 +15,6 @@ use crate::protocol::contract::ResharingContractState; use near_account_id::AccountId; -/// Default invalidation time for failed triples: 2 hrs -pub const FAILED_TRIPLES_TIMEOUT: Duration = Duration::from_secs(120 * 60); - -/// Default invalidation time for taken triples and presignatures: 2 hrs -pub const TAKEN_TIMEOUT: Duration = Duration::from_secs(120 * 60); - pub type SecretKeyShare = ::Scalar; pub type TripleProtocol = Box> + Send + Sync>;