Skip to content

Commit

Permalink
feat: use contract configs (#731)
Browse files Browse the repository at this point in the history
* Renamed chain-signature MPC_RECOVERY_* env vars to MPC_*

* Rename mpc-recovery-node binary to mpc-node

* Rename some forgotten binary names

* Made update methods us MpcContractError

* Made proposed updates more space efficient

* Added bytes_used for config and code updates

* Removed unnecessary near-rng crate

* Added deposit to propose_update

* Make config dynamic for easier changes

* Added proper borsh serialization and payable

* Use to_vec instead for config borsh ser

* Update deposit cost

* Clippy

* Added propose_update refund diff and migrate

* Added additional test case for a contract that fails to migrate

* Update INVALID contract path

* Made config module

* Made config an option that can be initialized from contract

* Made node use contract config with LocalConfig

* Added --override-config for partial overrides

* Added SignatureConfig

* Use timeouts from contract configs

* Removed no longer needed env variables from tf

* Moved GC timeout to contract config

---------

Co-authored-by: Serhii Volovyk <[email protected]>
  • Loading branch information
ChaoticTempest and volovyks authored Jul 26, 2024
1 parent 5d817b4 commit 5762932
Show file tree
Hide file tree
Showing 29 changed files with 691 additions and 459 deletions.
86 changes: 0 additions & 86 deletions chain-signatures/contract/src/config.rs

This file was deleted.

107 changes: 107 additions & 0 deletions chain-signatures/contract/src/config/impls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use borsh::{self, BorshDeserialize, BorshSerialize};

use super::{
Config, DynamicValue, PresignatureConfig, ProtocolConfig, SignatureConfig, 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> {
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 {
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(),
presignature: PresignatureConfig::default(),
signature: Default::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(),
}
}
}

impl Default for SignatureConfig {
fn default() -> Self {
Self {
generation_timeout: secs_to_ms(60),

other: Default::default(),
}
}
}

impl From<serde_json::Value> for DynamicValue {
fn from(value: serde_json::Value) -> Self {
Self(value)
}
}
impl BorshSerialize for DynamicValue {
fn serialize<W: std::io::Write>(&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<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
let buf: Vec<u8> = 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
}

pub const fn hours_to_ms(hours: u64) -> u64 {
hours * 60 * 60 * 1000
}
160 changes: 160 additions & 0 deletions chain-signatures/contract/src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
mod impls;

pub use impls::{min_to_ms, secs_to_ms};

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 {
pub protocol: ProtocolConfig,

/// The remaining entries that can be present in future forms of the configuration.
#[serde(flatten)]
pub other: HashMap<String, DynamicValue>,
}

#[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,
/// 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,
/// Configuration for signature generation.
pub signature: SignatureConfig,

/// The remaining entries that can be present in future forms of the configuration.
#[serde(flatten)]
pub other: HashMap<String, DynamicValue>,
}

#[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<String, DynamicValue>,
}

#[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<String, DynamicValue>,
}

#[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<String, DynamicValue>,
}

#[cfg(test)]
mod tests {
use crate::config::Config;

#[test]
fn test_load_config() {
let config_str: serde_json::Value = serde_json::from_str(
r#"{
"protocol": {
"message_timeout": 10000,
"garbage_timeout": 20000,
"max_concurrent_introduction": 10,
"max_concurrent_generation": 10,
"triple": {
"min_triples": 10,
"max_triples": 100,
"generation_timeout": 10000
},
"presignature": {
"min_presignatures": 10,
"max_presignatures": 100,
"generation_timeout": 10000
},
"signature": {
"generation_timeout": 10000
},
"string": "value",
"integer": 1000
},
"string": "value2",
"integer": 20
}"#,
)
.unwrap();

let config_macro = serde_json::json!({
"protocol": {
"message_timeout": 10000,
"garbage_timeout": 20000,
"max_concurrent_introduction": 10,
"max_concurrent_generation": 10,
"triple": {
"min_triples": 10,
"max_triples": 100,
"generation_timeout": 10000
},
"presignature": {
"min_presignatures": 10,
"max_presignatures": 100,
"generation_timeout": 10000
},
"signature": {
"generation_timeout": 10000
},
"string": "value",
"integer": 1000
},
"string": "value2",
"integer": 20
});

assert_eq!(config_str, config_macro);

let config: Config = serde_json::from_value(config_macro).unwrap();
assert_eq!(config.protocol.message_timeout, 10000);
assert_eq!(config.get("integer").unwrap(), serde_json::json!(20));
assert_eq!(config.get("string").unwrap(), serde_json::json!("value2"));
}
}
Loading

0 comments on commit 5762932

Please sign in to comment.