diff --git a/Cargo.toml b/Cargo.toml index ffd9c17d1..0659ede04 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] http = "0.1.17" -tapyrus = { git = "https://github.com/chaintope/rust-tapyrus", tag = "v0.4.5", features = ["use-serde", "rand"] } +tapyrus = { version = "0.4.8", features = ["use-serde", "rand"] } secp256k1 = "0.15.3" log = "0.4.6" env_logger = "0.9.0" diff --git a/src/bin/tapyrus-signerd.rs b/src/bin/tapyrus-signerd.rs index cf4131a38..710b6e068 100644 --- a/src/bin/tapyrus-signerd.rs +++ b/src/bin/tapyrus-signerd.rs @@ -205,7 +205,7 @@ mod tests { #[test] fn test_load_federations() { let pubkey = PublicKey::from_str( - "02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b72506", + "0315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c9", ) .unwrap(); @@ -215,6 +215,19 @@ mod tests { assert_eq!(federations.len(), 2); } + #[test] + fn test_load_federations_threshold_change() { + let pubkey = PublicKey::from_str( + "0315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c9", + ) + .unwrap(); + + let path = Path::new("tests/resources/federations_threshold_change.toml"); + let federations = load_federations(&pubkey, path); + + assert_eq!(federations.len(), 2); + } + #[test] #[should_panic(expected = "Can't open federations_file. path: \"/foo/bar/no_exist_file.toml\"")] fn test_load_federations_invalid_file_path() { @@ -229,11 +242,11 @@ mod tests { #[test] #[should_panic( - expected = "federations_file: Invalid Federation at 0 height. message: The nodevss has wrong vss which has wrong number of commitments." + expected = "federations_file: Invalid Federation at 20 height. message: The nodevss has wrong vss which has wrong number of commitments." )] fn test_load_federations_has_invalid_federation() { let pubkey = PublicKey::from_str( - "02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b72506", + "0315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c9", ) .unwrap(); @@ -243,7 +256,7 @@ mod tests { #[test] #[should_panic( - expected = "federations_file: Invalid TOML format. missing field `aggregated-public-key` for key `federation` at line 12 column 1" + expected = "federations_file: Invalid Federation at 100 height. message: No xfield in federation. Aggregated pubkey or max block size is expected" )] fn test_load_federations_invalid_toml_format() { let pubkey = PublicKey::from_str( @@ -254,4 +267,15 @@ mod tests { let path = Path::new("tests/resources/federations_invalid_toml_format.toml"); load_federations(&pubkey, path); } + + #[test] + fn test_load_federations_has_max_block_size() { + let pubkey = PublicKey::from_str( + "0302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25", + ) + .unwrap(); + + let path = Path::new("tests/resources/federations_has_max_block_size.toml"); + load_federations(&pubkey, path); + } } diff --git a/src/cli/setup/compute_sig.rs b/src/cli/setup/compute_sig.rs index 0b5c60e41..f24af630e 100644 --- a/src/cli/setup/compute_sig.rs +++ b/src/cli/setup/compute_sig.rs @@ -18,7 +18,7 @@ use curv::{BigInt, FE, GE}; use std::collections::BTreeMap; use std::fmt; use std::str::FromStr; -use tapyrus::blockdata::block::Block; +use tapyrus::blockdata::block::{Block, XField}; use tapyrus::consensus::encode::{deserialize, serialize}; use tapyrus::{PrivateKey, PublicKey}; @@ -42,6 +42,26 @@ impl fmt::Display for ComputeSigResponse { } } +pub struct ComputeXFieldSigResponse { + xfield_signature: tapyrus::util::signature::Signature, +} + +impl ComputeXFieldSigResponse { + fn new(xfield_signature: tapyrus::util::signature::Signature) -> Self { + ComputeXFieldSigResponse { + xfield_signature: xfield_signature, + } + } +} + +impl Response for ComputeXFieldSigResponse {} + +impl fmt::Display for ComputeXFieldSigResponse { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", hex::encode(serialize(&self.xfield_signature))) + } +} + pub struct ComputeSigCommand {} impl<'a> ComputeSigCommand { @@ -67,12 +87,6 @@ impl<'a> ComputeSigCommand { .map(|i| ECScalar::from(&i)) .ok_or(Error::InvalidArgs("node-secret-share".to_string()))?; - let mut block: Block = matches - .value_of("block") - .and_then(|s| hex::decode(s).ok()) - .and_then(|hex| deserialize::(&hex).ok()) - .ok_or(Error::InvalidArgs("block".to_string()))?; - let node_vss_vec: Vec = matches .values_of("node-vss") .ok_or(Error::InvalidArgs("node-vss".to_string()))? @@ -123,6 +137,34 @@ impl<'a> ComputeSigCommand { "the length of sig should equal to the length of node vss" ); + let signing_block = matches.is_present("block"); + let block: Option = if signing_block { + matches + .value_of("block") + .and_then(|s| hex::decode(s).ok()) + .and_then(|hex| deserialize::(&hex).ok()) + .ok_or(Error::InvalidArgs("block".to_string()))? + .into() + } else { + None + }; + + let mut xfield = XField::None; + if block.is_none() { + xfield = matches + .value_of("xfield") + .and_then(|s| hex::decode(s).ok()) + .and_then(|hex| deserialize::(&hex).ok()) + .ok_or(Error::InvalidArgs("xfield".to_string()))?; + + match xfield { + XField::None | XField::Unknown(_, _) => { + return Err(Error::InvalidArgs("xfield".to_string())); + } + _ => (), + } + } + let mut public_keys: Vec = block_vss_vec .iter() .map(|vss| vss.sender_public_key) @@ -144,12 +186,25 @@ impl<'a> ComputeSigCommand { x_i: node_secret_share, }; - let (is_positive, block_shared_keys, _local_sig) = Vss::create_local_sig_from_shares( - &priv_shared_keys, - index, - &shared_block_secrets, - &block, - )?; + let (is_positive, block_shared_keys, _local_sig) = if let Some(ref block) = block { + Vss::create_local_sig_from_shares_for_block( + &priv_shared_keys, + index, + &shared_block_secrets, + &block, + )? + } else if xfield != XField::None { + Vss::create_local_sig_from_shares_for_xfield( + &priv_shared_keys, + index, + &shared_block_secrets, + &xfield, + )? + } else { + return Err(Error::InvalidArgs( + "Either xfield or block is expected".to_string(), + )); + }; let shared_secrets = vss_to_shared_secret_map(&node_vss_vec, ¶ms); @@ -157,8 +212,15 @@ impl<'a> ComputeSigCommand { for (sig, public_key) in keyed_local_sigs { signatures.insert(SignerID { pubkey: public_key }, (sig.gamma_i, sig.e)); } + + let hash = if let Some(ref block) = block { + block.header.signature_hash().to_vec() + } else { + xfield.signature_hash().unwrap().to_vec() + }; + let signature = Vss::aggregate_and_verify_signature( - &block, + &hash, signatures, &public_keys, &shared_secrets, @@ -166,13 +228,18 @@ impl<'a> ComputeSigCommand { &shared_block_secrets, &priv_shared_keys, )?; - let hash = block.header.signature_hash(); + signature.verify(&hash, &priv_shared_keys.y)?; let sig_hex = Sign::format_signature(&signature); let sig: tapyrus::util::signature::Signature = deserialize(&hex::decode(sig_hex).map_err(|_| Error::InvalidSig)?)?; - block.header.proof = Some(sig); - Ok(Box::new(ComputeSigResponse::new(block))) + + if let Some(mut block) = block { + block.header.proof = Some(sig); + Ok(Box::new(ComputeSigResponse::new(block))) + } else { + Ok(Box::new(ComputeXFieldSigResponse::new(sig))) + } } pub fn args<'b>() -> App<'a, 'b> { @@ -189,9 +256,16 @@ impl<'a> ComputeSigCommand { .help("the minimum number of signers required to sign block"), Arg::with_name("block") .long("block") - .required(true) .takes_value(true) + .conflicts_with("xfied") + .required_unless("xfield") .help("block to be signed as a hex string format"), + Arg::with_name("xfield") + .long("xfield") + .takes_value(true) + .conflicts_with("block") + .required_unless("block") + .help("xfield change to be signed as a hex string format"), Arg::with_name("node-secret-share") .long("node-secret-share") .required(true) @@ -654,4 +728,80 @@ mod tests { ]); let _ = ComputeSigCommand::execute(&matches); } + + #[test] + fn test_execute_invalid_xfield() { + let matches = ComputeSigCommand::args().get_matches_from(vec![ + "computesig", + "--threshold", + "2", + "--xfield", + "x", + "--block-vss", + "03b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d03b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d0002a19e63fadf5c9c2e43ca7898148626af65b7bf0ece9db41186b98050e04f5b0bd4d89b2950241a856e6da564288743fbcc4b324f5631bb696553f365e6d957e8b0ec2d0e288215d1b561cf3c4517743e630bef13ea88c639465d5bbc22a1a9f547c16dbdacca5791321622bb12f1fd60007a77154ca36b8de432d91f6e3eeb1d658f81dad15e1bca0fa4203d0d88de7620ba79d8b24f79d0fe350d93e507f36ba19e63fadf5c9c2e43ca7898148626af65b7bf0ece9db41186b98050e04f5b0b2b2764d6afdbe57a91925a9bd778bc0433b4cdb0a9ce44969aac0c991926a447cd8c025a4f7bf5a690c2dec246628adecdee12d176db38dcbabc23bfb62132e77ee55761cf189133318d8ca95fd853557b7ddbc7114ef7c191c3a75466844d16fa8c8ec0921c23c0e897a33aa976aa77490b87f3ea7d50f6eeb7e72a8d69b6e1", + "--block-vss", + "0313f2a73541e6d55a75a80a6da819885c6ed6e56ecff19f5e928c4ea202ca7c9003b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d000260a540d7a18ce6795fe15d661d19f5e869855cbf4f26f03b976af5348941077c63250f2db3eb32875f2ab4a29cc25edd82cac3f589765b5ab1fb0048cef49ea4ddf06f11a001e1271b212e3e3c2387c1509c511c1623368eb5540ef113219c3884eb8edbb50c6116bcde0d51973c8669cb317251b23e5e0605f11bd6b36bb8e3a33cabf430e5efda94cb837ecddf19b33e54de2f05c17807d4b129b33aaabd9260a540d7a18ce6795fe15d661d19f5e869855cbf4f26f03b976af5348941077c9cdaf0d24c14cd78a0d54b5d633da1227d353c0a7689a4a54e04ffb6310b5d8b852329c91eea9673c32002248f96bd8899e7e0b6e7edafeb86e08637f3a2c08b11eed4135071e495857bbd9ef2d5f62c3b3ede4e29e24c8cdb80285c3534cb146ad404719bcd32778a08ffc8296efc67463241f4babb8982b36cd8bfe8713e26", + "--block-vss", + "023cb7d6326e33332d04d026be1a04cdaf084703d8dc75322182d8fb314a03a87703b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d00021ebb71ead55be76658b0e94847f7298ccaebf86bd95a2eb4f598a362000faee6eed381a222dfa8172fb1afa93b0d48da11ae313ec5933330980527e476ca959d575681f8b9c3d618701533f148f9f1cc60ee54f4bd19bc1f653f59fc8572b0536d461c8454af57e4ab98b2a89561764183604661d24d33f1fe21d8f81a66899f16cddb4bc18af3cb1fe2b7b0700fa0873f9365e64b11a90ee8a2003e2ccde29b1ebb71ead55be76658b0e94847f7298ccaebf86bd95a2eb4f598a362000faee6112c7e5ddd2057e8d04e5056c4f2b725ee51cec13a6ccccf67fad81a8935669291ebd5724f71bf36e716b637a9db2f1400e9ee7693230746d98e06ad517876952d0d209734d8d10e1a9c3507a4fc4784d11c7b7bf6a8f1010af582498dfb3e8629c2ea58d8865bd32c0aeaa6e3eececf6b5fb1044ebd01eed49e2365242eb174", + "--node-vss", + "03b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d03b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d0002b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d1bb2811fe36fa9e15b7afc0ecdb4c51cad86c2c9135607f38e4ae581983112734aab9f763d82eaa3cfe0792e4b8da3022f0f42b32ceb01757265fa99f29c76fd1675a7e28bf8f325b32f87e7c0c01503216f46f169ae7eebbcd7a2c0ac3f54e6660325ccf75e6b278364d1e71c48c5fcf1de97237e5cdbb2635980c0c77b1af9b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d1bb2811fe36fa9e15b7afc0ecdb4c51cad86c2c9135607f38e4ae581983112734aab9f763d82eaa3cfe0792e4b8da3022f0f42b32ceb01757265fa99f29c76fd1675a7e28bf8f325b32f87e7c0c01503216f46f169ae7eebbcd7a2c0ac3f54e6660325ccf75e6b278364d1e71c48c5fcf1de97237e5cdbb2635980c0c77b1af9", + "--node-vss", + "0313f2a73541e6d55a75a80a6da819885c6ed6e56ecff19f5e928c4ea202ca7c9003b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d000213f2a73541e6d55a75a80a6da819885c6ed6e56ecff19f5e928c4ea202ca7c90adbd69de8655fcc6ead8e771f9f31ead7a431e543bf8ac8d921c80ab301bc8d1ce3573e2158dd7d16a2783265a0d1f44612fb44b24f6cabfa71e9fad736137f59e1a7bfc38def0de39f3faf29421e15c1424aa0bbe275dd0ec832fd7c34fb2f89f1cf17ad25ab75c2c124179386e18105a3d907a6f80cca43851485ce4fbdce913f2a73541e6d55a75a80a6da819885c6ed6e56ecff19f5e928c4ea202ca7c90adbd69de8655fcc6ead8e771f9f31ead7a431e543bf8ac8d921c80ab301bc8d1ce3573e2158dd7d16a2783265a0d1f44612fb44b24f6cabfa71e9fad736137f59e1a7bfc38def0de39f3faf29421e15c1424aa0bbe275dd0ec832fd7c34fb2f89f1cf17ad25ab75c2c124179386e18105a3d907a6f80cca43851485ce4fbdce9", + "--node-vss", + "023cb7d6326e33332d04d026be1a04cdaf084703d8dc75322182d8fb314a03a87703b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d00023cb7d6326e33332d04d026be1a04cdaf084703d8dc75322182d8fb314a03a877be6e3e5cdfc8877c9f9b1a0bbee781019c55098025b03fcede5e4947d16f6140dc0f59ac7b7a5e00aa48b8cd214011edfd9706c97032a7e91207ed8ea7127c9955918c6a7dd61da49783c4013b49f7120ffa04586f9c91e5c938bcd3667442ca801b6775343b6f71791392d4ccbd84edec9cfc8c8d5f8bce817c8c39e6386ce63cb7d6326e33332d04d026be1a04cdaf084703d8dc75322182d8fb314a03a877be6e3e5cdfc8877c9f9b1a0bbee781019c55098025b03fcede5e4947d16f6140dc0f59ac7b7a5e00aa48b8cd214011edfd9706c97032a7e91207ed8ea7127c9955918c6a7dd61da49783c4013b49f7120ffa04586f9c91e5c938bcd3667442ca801b6775343b6f71791392d4ccbd84edec9cfc8c8d5f8bce817c8c39e6386ce6", + "--node-secret-share", + "853b7ebcfdf491f5288aa635217462fc7e0a4743cbf493e95d54f6cac2792387", + "--aggregated-public-key", + "03addb2555f37abf8f28f11f498bec7bd1460e7243c1813847c49a7ae326a97d1c", + "--sig", + "2bebd2c65553c400ff9ed3e13ec59a0fddeefb34ccebd932db44fe63de139538c26be91145a7b67096e44bb318eb1780f4fc1630e6cde6d5705690236fbe089003b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d", + "--sig", + "a4af87b6a5f9563e3a7815241cfe0099d5bad2e949b36933313b2ad44ad6d098c26be91145a7b67096e44bb318eb1780f4fc1630e6cde6d5705690236fbe08900313f2a73541e6d55a75a80a6da819885c6ed6e56ecff19f5e928c4ea202ca7c90", + "--sig", + "1d733ca6f69ee87b75515666fb36672512d7cdb7173258f7c75ef8b7e763cab7c26be91145a7b67096e44bb318eb1780f4fc1630e6cde6d5705690236fbe0890023cb7d6326e33332d04d026be1a04cdaf084703d8dc75322182d8fb314a03a877", + "--private-key", + "L2hmApEYQBQo81RLJc5MMwo6ZZywnfVzuQj6uCfxFLaV2Yo2pVyq", + ]); + let response = ComputeSigCommand::execute(&matches); + assert_eq!( + format!("{}", response.err().unwrap()), + "InvalidArgs(\"xfield\")" + ); + } + + #[test] + fn test_execute_success_xfield() { + let matches = ComputeSigCommand::args().get_matches_from(vec![ + "computesig", + "--threshold", + "2", + "--xfield", + "0121025700236c2890233592fcef262f4520d22af9160e3d9705855140eb2aa06c35d3", + "--block-vss", + "0256b1bf5532d6627e763cd694d432dd061132ddfb528d692e23fecf6cca4c20f30256b1bf5532d6627e763cd694d432dd061132ddfb528d692e23fecf6cca4c20f300020690cb2a3d02b81fc4fd3aebcbf8d06c95489a1afacd85ede4a90ed1e03a63b94d9b24190fce33b12eb517a7567c583a90ce2d51988b28dc0f6cd614f9320604b9c1c7ffeda2cb3a025bb887627cbfdb6b7067c4fd38a9f83cc301845b80a5c325222cc677c75453d719a8ac9a6244da6d45693d3f929ccd6c2c2ff1716ca74132b1f2b2bf09d498dbc66743dc1e0ae1c2600698fc22f108aa9de0532d7981110690cb2a3d02b81fc4fd3aebcbf8d06c95489a1afacd85ede4a90ed1e03a63b9b264dbe6f031cc4ed14ae858a983a7c56f31d2ae6774d723f09329ea06cdf62b2f14042ab1b3d483429ab1544dd9fd91397755656433718c6a05070558510c99c7d254c8cb323b2a5e340521cd7707d026ef8a5077d8f4d7c47f7c0d7a6e1411a49c47eae9a8089937cc42f06b1ad08763234cfe81ddf1da16a7ba8a0bd60405", + "--block-vss", + "02c4635894070e1d1b6fc669782d7efc5e62116e811970a431833975761fee89890256b1bf5532d6627e763cd694d432dd061132ddfb528d692e23fecf6cca4c20f3000274af185b0f4ae72af4f6bf75a4858c4dc3a7f28752870cf80faac1d826542a5e7733c73498893e25c74d9a9b0b635c8c341b751bfe41e320fa344ab25f2595acd9f3928757c5969f3f7614ed9c0b393785d5d7690e9453e9995a3dc233285568bdb08095ab59806afd00eb315f5fe9a58a08b55351f431c6e8938c0818a12c7f59867f3c769be24296958dbe25c47084166e965996f9fe5e3117d1692205f01074af185b0f4ae72af4f6bf75a4858c4dc3a7f28752870cf80faac1d826542a5e88cc38cb6776c1da38b26564f49ca373cbe48ae401be1cdf05cbb54ca0da66831835d442a4334cd2643a0dba643e3179a00eca0d291e4e3344d71f76adff833c3194a466903b228392f5539c525e6a262748b4eb5d626d004f91f028f7667e3dd1703df47a15147a95fbe475de37dfe5d139e4ee9f2dc7d631952b35eacba56d", + "--block-vss", + "0377b47c58ff3e309c283296d975808918b96656d4816ea244fbfceee836f7d11b0256b1bf5532d6627e763cd694d432dd061132ddfb528d692e23fecf6cca4c20f300026b9a0b482fd2f58bc5ba78762751d24c4c1622f3c392868bc005a07162a969a5a0930bdb6ae2f72d650985e8e765de785ef7bca2117039841a3dce61a1a502573b94c844e4b68c4211b2fe5052957dab66b4536e23495e3377e9be7ffe0c3ed48918270ed5f1a08df6002c6d94d8668943888a7e4e4df0b28e6b8516e7e31e4513922442e3008c9677541c96b3f95d535c7398d77c987d6de0e3b41a875cb25f6b9a0b482fd2f58bc5ba78762751d24c4c1622f3c392868bc005a07162a969a55f6cf424951d08d29af67a17189a2187a108435dee8fc67be5c2319d5e5af9d8ffaf64a2b639282ac7b2e7550d164bb86912c410b8fec9c0b2aed33382e8cdd04e4c754bc0d59173198eea0f1b883a6baf9ecc3ca1b903a61219d1e2eb7d3440aff3e8df0a8b66d5a39c01b3689dc2bc2e70d4f21e773b0e5539c87cabc47444", + "--node-vss", + "0256b1bf5532d6627e763cd694d432dd061132ddfb528d692e23fecf6cca4c20f30256b1bf5532d6627e763cd694d432dd061132ddfb528d692e23fecf6cca4c20f3000256b1bf5532d6627e763cd694d432dd061132ddfb528d692e23fecf6cca4c20f3a9a238f2f935deca950a2a2133a9a6773012bec36c9f37de8955781b5839575ce540d2c7af035bc9643ffaccf9e4f82e2f86e79d762a0a2645b346db0cd201c05482b0a18cf0f9d5c630023d808dc54a9e24ac884f4849b4a2e7cd76c53313f3261e1777e2bad13b1799f3ee3dcf89d485e7a3fade4203bd05088789582cb47956b1bf5532d6627e763cd694d432dd061132ddfb528d692e23fecf6cca4c20f3a9a238f2f935deca950a2a2133a9a6773012bec36c9f37de8955781b5839575ce540d2c7af035bc9643ffaccf9e4f82e2f86e79d762a0a2645b346db0cd201c05482b0a18cf0f9d5c630023d808dc54a9e24ac884f4849b4a2e7cd76c53313f3261e1777e2bad13b1799f3ee3dcf89d485e7a3fade4203bd05088789582cb479", + "--node-vss", + "02c4635894070e1d1b6fc669782d7efc5e62116e811970a431833975761fee89890256b1bf5532d6627e763cd694d432dd061132ddfb528d692e23fecf6cca4c20f30002c4635894070e1d1b6fc669782d7efc5e62116e811970a431833975761fee89895eefc5bae0eeeebdf8614d74a51a23b9d3bce95294a1de04901726b54a73e3b4db2951648e5d0ed3b8ac1690427a4b8157c3626db147f5e10af6636dada7759e56fc455d5804ac5e41980ab346b0ac35cea254a41e94d21d45fd64d62f7f391956897da644dde3f4888797c41e74dce07fb661ce671a3adf402af463bcb31e41c4635894070e1d1b6fc669782d7efc5e62116e811970a431833975761fee89895eefc5bae0eeeebdf8614d74a51a23b9d3bce95294a1de04901726b54a73e3b4db2951648e5d0ed3b8ac1690427a4b8157c3626db147f5e10af6636dada7759e56fc455d5804ac5e41980ab346b0ac35cea254a41e94d21d45fd64d62f7f391956897da644dde3f4888797c41e74dce07fb661ce671a3adf402af463bcb31e41", + "--node-vss", + "0377b47c58ff3e309c283296d975808918b96656d4816ea244fbfceee836f7d11b0256b1bf5532d6627e763cd694d432dd061132ddfb528d692e23fecf6cca4c20f3000277b47c58ff3e309c283296d975808918b96656d4816ea244fbfceee836f7d11b110adf8789d05e65dd341359cd2714b08208e7ce017d3e0bf71d6eaa0ca9c76f1063e7d72914f0e98e1b378f52d0d4619f0ba0a4ca6d27cedec328b0483483c28ea4984f9d157515144c750b743172bd7c9d7b278a82a1625086b241f22071a6f7c3a69d6e8119fa2af1d79aad5967f72977e7649e3227789b6f5f4dbaede03777b47c58ff3e309c283296d975808918b96656d4816ea244fbfceee836f7d11b110adf8789d05e65dd341359cd2714b08208e7ce017d3e0bf71d6eaa0ca9c76f1063e7d72914f0e98e1b378f52d0d4619f0ba0a4ca6d27cedec328b0483483c28ea4984f9d157515144c750b743172bd7c9d7b278a82a1625086b241f22071a6f7c3a69d6e8119fa2af1d79aad5967f72977e7649e3227789b6f5f4dbaede037", + "--sig", + "5eb574266ead78a0616089c5e01a2c650c32422680d48e4428b83543834714437e5d309fe0d0745e18bd8984eefca234da8af200b1f7a7e9dd168bbdea56d8680256b1bf5532d6627e763cd694d432dd061132ddfb528d692e23fecf6cca4c20f3", + "--sig", + "df8a7ab4be43ece5b0f8381078afebdc2e91020b499b78b56fe9e860fb1c099f7e5d309fe0d0745e18bd8984eefca234da8af200b1f7a7e9dd168bbdea56d86802c4635894070e1d1b6fc669782d7efc5e62116e811970a431833975761fee8989", + "--sig","605f81430dda612b008fe65b1145ab549640e5096319c2eaf7493cf1a2babdba7e5d309fe0d0745e18bd8984eefca234da8af200b1f7a7e9dd168bbdea56d8680377b47c58ff3e309c283296d975808918b96656d4816ea244fbfceee836f7d11b", + "--node-secret-share", + "746b3bbb9619cf29cb13634d099dcead746710473445c5d920d07cadff9771b0", + "--aggregated-public-key", + "0303a8d919266c95407e8aa247b058d510e6286ddb9ba73c7a283edc67bb11ed1e", + "--private-key", + "KzJbxJCY4FZX7Ki8tsg5V9dAsxhgGBWAbQEcakByuHH2Y7KyrvZZ" + ]); + let response = ComputeSigCommand::execute(&matches); + assert!(response.is_ok()); + } } diff --git a/src/cli/setup/create_block_vss.rs b/src/cli/setup/create_block_vss.rs index 1ce307bc8..fd40ca94c 100644 --- a/src/cli/setup/create_block_vss.rs +++ b/src/cli/setup/create_block_vss.rs @@ -109,7 +109,7 @@ impl<'a> CreateBlockVssCommand { .long("threshold") .required(true) .takes_value(true) - .help("the minimum number of signers required to sign block"), + .help("the minimum number of signers required to sign block/xfield change"), ]) } } diff --git a/src/cli/setup/sign.rs b/src/cli/setup/sign.rs index 832f046be..e80a19353 100644 --- a/src/cli/setup/sign.rs +++ b/src/cli/setup/sign.rs @@ -15,7 +15,7 @@ use curv::elliptic::curves::traits::{ECPoint, ECScalar}; use curv::{BigInt, FE, GE}; use std::fmt; use std::str::FromStr; -use tapyrus::blockdata::block::Block; +use tapyrus::blockdata::block::{Block, XField}; use tapyrus::consensus::encode::deserialize; use tapyrus::{PrivateKey, PublicKey}; @@ -61,12 +61,6 @@ impl<'a> SignCommand { .and_then(|s| s.parse::().ok()) .ok_or(Error::InvalidArgs("threshold".to_string()))?; - let block: Block = matches - .value_of("block") - .and_then(|s| hex::decode(s).ok()) - .and_then(|hex| deserialize::(&hex).ok()) - .ok_or(Error::InvalidArgs("block".to_string()))?; - let node_secret_share: FE = matches .value_of("node-secret-share") .and_then(|s| BigInt::from_str_radix(s, 16).ok()) @@ -104,12 +98,55 @@ impl<'a> SignCommand { x_i: node_secret_share, }; - let (_, _, local_sig) = Vss::create_local_sig_from_shares( - &priv_shared_keys, - index, - &shared_block_secrets, - &block, - )?; + let signing_block = matches.is_present("block"); + let block: Option = if signing_block { + matches + .value_of("block") + .and_then(|s| hex::decode(s).ok()) + .and_then(|hex| deserialize::(&hex).ok()) + .ok_or(Error::InvalidArgs("block".to_string()))? + .into() + } else { + None + }; + + let mut xfield = XField::None; + if block.is_none() { + xfield = matches + .value_of("xfield") + .and_then(|s| hex::decode(s).ok()) + .and_then(|hex| deserialize::(&hex).ok()) + .ok_or(Error::InvalidArgs("xfield".to_string()))?; + + match xfield { + XField::None | XField::Unknown(_, _) => { + return Err(Error::InvalidArgs( + "Either xfield or block is expected".to_string(), + )); + } + _ => (), + } + } + + let (_, _, local_sig) = if let Some(ref block) = block { + Vss::create_local_sig_from_shares_for_block( + &priv_shared_keys, + index, + &shared_block_secrets, + &block, + ) + } else if xfield != XField::None { + Vss::create_local_sig_from_shares_for_xfield( + &priv_shared_keys, + index, + &shared_block_secrets, + &xfield, + ) + } else { + return Err(Error::InvalidArgs( + "Either xfield or block is expected".to_string(), + )); + }?; let secp = tapyrus::secp256k1::Secp256k1::new(); let public_key = PublicKey::from_private_key(&secp, &private_key); @@ -130,9 +167,16 @@ impl<'a> SignCommand { .help("the minimum number of signers required to sign block"), Arg::with_name("block") .long("block") - .required(true) + .required(false) .takes_value(true) + .conflicts_with("xfield") .help("block to be signed as a hex string format"), + Arg::with_name("xfield") + .long("xfield") + .required(false) + .takes_value(true) + .conflicts_with("block") + .help("xfield change to be signed as a hex string format"), Arg::with_name("node-secret-share") .long("node-secret-share") .required(true) @@ -349,4 +393,111 @@ mod tests { "InvalidArgs(\"private-key\")" ); } + + #[test] + fn test_execute_xfield() { + let matches = SignCommand::args().get_matches_from(vec![ + "sign", + "--threshold", + "2", + "--xfield", + "0121025700236c2890233592fcef262f4520d22af9160e3d9705855140eb2aa06c35d3", + "--block-vss", + "03b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d03b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d0002a716af61616f37a27feb739d454b4695e8e4bc2b2ba3286c7c9bc96ccf2a1430c00d2070dd82cf532e7ef1042c00fc73e71ec8e2f9a245515c994f6c4bbf04fd6aafd46ec55a077a5577e7c7f5b18d13d251bf11d74f7e77b0be6e5cfe40baa3c5be600ba7cd38c3231973923a8aab0d95c1c64ef647d71f84c5923ab0e7330a76a499b08a457f92a5a58f358829ceb665a83798a09639361954d2f00b31a718a716af61616f37a27feb739d454b4695e8e4bc2b2ba3286c7c9bc96ccf2a14303ff2df8f227d30acd1810efbd3ff038c18e1371d065dbaaea366b092b440f732abec3f793c98b4c6791e95b9cbc7c8561d5b04c20ce127d77546b2795664816198e00cf4a0136b1861e3e8029d5164924117d8b60223b135a18b54580f8773a7d233d9dd447f252c2e915fb414ffddc72483ce9badc0166b6dbb853e5c8b7b6b", + "--block-vss", + "0313f2a73541e6d55a75a80a6da819885c6ed6e56ecff19f5e928c4ea202ca7c9003b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d000274d1162809397bff8421607bdc49162b3cc60324ddf1240974cec8d94a8e89c69fea398b0ae42d73015b53fa1e423cfbe814092c35866d6a5d663f50cce431ebc5c1609192fff04939e1e3d846e73b818e01eb997897a78b7a34b4779b94807d5d033e6358429e728731edcf18b0e24766e665b2ee2f63b77d7103191a02dba3fcfb2173c35583c1bc20dfc07b38bb5ba977e86b5cf03a545831711508b7561974d1162809397bff8421607bdc49162b3cc60324ddf1240974cec8d94a8e89c66015c674f51bd28cfea4ac05e1bdc30417ebf6d3ca799295a299c0ae331bca44b2f57788129b817f3723b6579c328bad1149428a83d3d9cac1c4eb3edb512aa1e81bbf2ffd3be0c4e3dcac483858f44ad695f9f8c23cdc2d8061895e51c9c9083108f0e17b0445f39f773ca82585dea76f2a7351ea0c841fd60e73466cb60457", + "--block-vss", + "023cb7d6326e33332d04d026be1a04cdaf084703d8dc75322182d8fb314a03a87703b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d00028fbd54f9b704c6c951c1b1f45bbc9c4559935d5bfe209d75507b70d4087829cf55e451b9e2ff5b91f491d2cd3fdc149d409fa2c4f07f009216cbb26afd496986a1dcb869f5418b1d3a1f9e75c655eade41930318e355844c2fc42018a7b345a466c0d55ce2fbc3584a0d155c4f7aef8ffe4ce60cc29682aa307fc3e5cbfcacfc92523e57c607ba85506a22d95c3789c9e3af172f3bafb01e6c9ef4ba19f9da1a8fbd54f9b704c6c951c1b1f45bbc9c4559935d5bfe209d75507b70d4087829cfaa1bae461d00a46e0b6e2d32c023eb62bf605d3b0f80ff6de9344d9402b692a97451c274ded2a2776a75158c7069b40a2fa61ad3c15921e12ee40c4a724689e67ff0299ad0e4ce45035dbc8fa1bdf287a7f1a9c06c7366b4c3073046ba0c2e5fedae0e8a92a4e97c25813d7ba6217de74ca8bd9c5bbd6a0c5e95722674748f3a", + "--node-secret-share", + "70f344fe8d0e53cd0341beae344ca68b8f09427a32aa33603c5fde61b66a09dc", + "--aggregated-public-key", + "03addb2555f37abf8f28f11f498bec7bd1460e7243c1813847c49a7ae326a97d1c", + "--private-key", + "L2hmApEYQBQo81RLJc5MMwo6ZZywnfVzuQj6uCfxFLaV2Yo2pVyq", + ]); + let response = SignCommand::execute(&matches); + assert!(response.is_ok()); + } + + #[test] + fn test_invalid_xfield() { + let matches = SignCommand::args().get_matches_from(vec![ + "sign", + "--threshold", + "2", + "--xfield", + "x", + "--block-vss", + "03b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d03b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d0002a716af61616f37a27feb739d454b4695e8e4bc2b2ba3286c7c9bc96ccf2a1430c00d2070dd82cf532e7ef1042c00fc73e71ec8e2f9a245515c994f6c4bbf04fd6aafd46ec55a077a5577e7c7f5b18d13d251bf11d74f7e77b0be6e5cfe40baa3c5be600ba7cd38c3231973923a8aab0d95c1c64ef647d71f84c5923ab0e7330a76a499b08a457f92a5a58f358829ceb665a83798a09639361954d2f00b31a718a716af61616f37a27feb739d454b4695e8e4bc2b2ba3286c7c9bc96ccf2a14303ff2df8f227d30acd1810efbd3ff038c18e1371d065dbaaea366b092b440f732abec3f793c98b4c6791e95b9cbc7c8561d5b04c20ce127d77546b2795664816198e00cf4a0136b1861e3e8029d5164924117d8b60223b135a18b54580f8773a7d233d9dd447f252c2e915fb414ffddc72483ce9badc0166b6dbb853e5c8b7b6b", + "--block-vss", + "0313f2a73541e6d55a75a80a6da819885c6ed6e56ecff19f5e928c4ea202ca7c9003b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d000274d1162809397bff8421607bdc49162b3cc60324ddf1240974cec8d94a8e89c69fea398b0ae42d73015b53fa1e423cfbe814092c35866d6a5d663f50cce431ebc5c1609192fff04939e1e3d846e73b818e01eb997897a78b7a34b4779b94807d5d033e6358429e728731edcf18b0e24766e665b2ee2f63b77d7103191a02dba3fcfb2173c35583c1bc20dfc07b38bb5ba977e86b5cf03a545831711508b7561974d1162809397bff8421607bdc49162b3cc60324ddf1240974cec8d94a8e89c66015c674f51bd28cfea4ac05e1bdc30417ebf6d3ca799295a299c0ae331bca44b2f57788129b817f3723b6579c328bad1149428a83d3d9cac1c4eb3edb512aa1e81bbf2ffd3be0c4e3dcac483858f44ad695f9f8c23cdc2d8061895e51c9c9083108f0e17b0445f39f773ca82585dea76f2a7351ea0c841fd60e73466cb60457", + "--block-vss", + "023cb7d6326e33332d04d026be1a04cdaf084703d8dc75322182d8fb314a03a87703b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d00028fbd54f9b704c6c951c1b1f45bbc9c4559935d5bfe209d75507b70d4087829cf55e451b9e2ff5b91f491d2cd3fdc149d409fa2c4f07f009216cbb26afd496986a1dcb869f5418b1d3a1f9e75c655eade41930318e355844c2fc42018a7b345a466c0d55ce2fbc3584a0d155c4f7aef8ffe4ce60cc29682aa307fc3e5cbfcacfc92523e57c607ba85506a22d95c3789c9e3af172f3bafb01e6c9ef4ba19f9da1a8fbd54f9b704c6c951c1b1f45bbc9c4559935d5bfe209d75507b70d4087829cfaa1bae461d00a46e0b6e2d32c023eb62bf605d3b0f80ff6de9344d9402b692a97451c274ded2a2776a75158c7069b40a2fa61ad3c15921e12ee40c4a724689e67ff0299ad0e4ce45035dbc8fa1bdf287a7f1a9c06c7366b4c3073046ba0c2e5fedae0e8a92a4e97c25813d7ba6217de74ca8bd9c5bbd6a0c5e95722674748f3a", + "--node-secret-share", + "70f344fe8d0e53cd0341beae344ca68b8f09427a32aa33603c5fde61b66a09dc", + "--aggregated-public-key", + "03addb2555f37abf8f28f11f498bec7bd1460e7243c1813847c49a7ae326a97d1c", + "--private-key", + "L2hmApEYQBQo81RLJc5MMwo6ZZywnfVzuQj6uCfxFLaV2Yo2pVyq", + ]); + let response = SignCommand::execute(&matches); + assert_eq!( + format!("{}", response.err().unwrap()), + "InvalidArgs(\"xfield\")" + ); + } + + #[test] + fn test_invalid_xfield_none() { + let matches = SignCommand::args().get_matches_from(vec![ + "sign", + "--threshold", + "2", + "--xfield", + "00", + "--block-vss", + "03b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d03b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d0002a716af61616f37a27feb739d454b4695e8e4bc2b2ba3286c7c9bc96ccf2a1430c00d2070dd82cf532e7ef1042c00fc73e71ec8e2f9a245515c994f6c4bbf04fd6aafd46ec55a077a5577e7c7f5b18d13d251bf11d74f7e77b0be6e5cfe40baa3c5be600ba7cd38c3231973923a8aab0d95c1c64ef647d71f84c5923ab0e7330a76a499b08a457f92a5a58f358829ceb665a83798a09639361954d2f00b31a718a716af61616f37a27feb739d454b4695e8e4bc2b2ba3286c7c9bc96ccf2a14303ff2df8f227d30acd1810efbd3ff038c18e1371d065dbaaea366b092b440f732abec3f793c98b4c6791e95b9cbc7c8561d5b04c20ce127d77546b2795664816198e00cf4a0136b1861e3e8029d5164924117d8b60223b135a18b54580f8773a7d233d9dd447f252c2e915fb414ffddc72483ce9badc0166b6dbb853e5c8b7b6b", + "--block-vss", + "0313f2a73541e6d55a75a80a6da819885c6ed6e56ecff19f5e928c4ea202ca7c9003b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d000274d1162809397bff8421607bdc49162b3cc60324ddf1240974cec8d94a8e89c69fea398b0ae42d73015b53fa1e423cfbe814092c35866d6a5d663f50cce431ebc5c1609192fff04939e1e3d846e73b818e01eb997897a78b7a34b4779b94807d5d033e6358429e728731edcf18b0e24766e665b2ee2f63b77d7103191a02dba3fcfb2173c35583c1bc20dfc07b38bb5ba977e86b5cf03a545831711508b7561974d1162809397bff8421607bdc49162b3cc60324ddf1240974cec8d94a8e89c66015c674f51bd28cfea4ac05e1bdc30417ebf6d3ca799295a299c0ae331bca44b2f57788129b817f3723b6579c328bad1149428a83d3d9cac1c4eb3edb512aa1e81bbf2ffd3be0c4e3dcac483858f44ad695f9f8c23cdc2d8061895e51c9c9083108f0e17b0445f39f773ca82585dea76f2a7351ea0c841fd60e73466cb60457", + "--block-vss", + "023cb7d6326e33332d04d026be1a04cdaf084703d8dc75322182d8fb314a03a87703b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d00028fbd54f9b704c6c951c1b1f45bbc9c4559935d5bfe209d75507b70d4087829cf55e451b9e2ff5b91f491d2cd3fdc149d409fa2c4f07f009216cbb26afd496986a1dcb869f5418b1d3a1f9e75c655eade41930318e355844c2fc42018a7b345a466c0d55ce2fbc3584a0d155c4f7aef8ffe4ce60cc29682aa307fc3e5cbfcacfc92523e57c607ba85506a22d95c3789c9e3af172f3bafb01e6c9ef4ba19f9da1a8fbd54f9b704c6c951c1b1f45bbc9c4559935d5bfe209d75507b70d4087829cfaa1bae461d00a46e0b6e2d32c023eb62bf605d3b0f80ff6de9344d9402b692a97451c274ded2a2776a75158c7069b40a2fa61ad3c15921e12ee40c4a724689e67ff0299ad0e4ce45035dbc8fa1bdf287a7f1a9c06c7366b4c3073046ba0c2e5fedae0e8a92a4e97c25813d7ba6217de74ca8bd9c5bbd6a0c5e95722674748f3a", + "--node-secret-share", + "70f344fe8d0e53cd0341beae344ca68b8f09427a32aa33603c5fde61b66a09dc", + "--aggregated-public-key", + "03addb2555f37abf8f28f11f498bec7bd1460e7243c1813847c49a7ae326a97d1c", + "--private-key", + "L2hmApEYQBQo81RLJc5MMwo6ZZywnfVzuQj6uCfxFLaV2Yo2pVyq", + ]); + let response = SignCommand::execute(&matches); + assert_eq!( + format!("{}", response.err().unwrap()), + "InvalidArgs(\"Either xfield or block is expected\")" + ); + } + + #[test] + fn test_no_block_no_xfield() { + let matches = SignCommand::args().get_matches_from(vec![ + "sign", + "--threshold", + "2", + "--block-vss", + "03b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d03b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d0002a716af61616f37a27feb739d454b4695e8e4bc2b2ba3286c7c9bc96ccf2a1430c00d2070dd82cf532e7ef1042c00fc73e71ec8e2f9a245515c994f6c4bbf04fd6aafd46ec55a077a5577e7c7f5b18d13d251bf11d74f7e77b0be6e5cfe40baa3c5be600ba7cd38c3231973923a8aab0d95c1c64ef647d71f84c5923ab0e7330a76a499b08a457f92a5a58f358829ceb665a83798a09639361954d2f00b31a718a716af61616f37a27feb739d454b4695e8e4bc2b2ba3286c7c9bc96ccf2a14303ff2df8f227d30acd1810efbd3ff038c18e1371d065dbaaea366b092b440f732abec3f793c98b4c6791e95b9cbc7c8561d5b04c20ce127d77546b2795664816198e00cf4a0136b1861e3e8029d5164924117d8b60223b135a18b54580f8773a7d233d9dd447f252c2e915fb414ffddc72483ce9badc0166b6dbb853e5c8b7b6b", + "--block-vss", + "0313f2a73541e6d55a75a80a6da819885c6ed6e56ecff19f5e928c4ea202ca7c9003b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d000274d1162809397bff8421607bdc49162b3cc60324ddf1240974cec8d94a8e89c69fea398b0ae42d73015b53fa1e423cfbe814092c35866d6a5d663f50cce431ebc5c1609192fff04939e1e3d846e73b818e01eb997897a78b7a34b4779b94807d5d033e6358429e728731edcf18b0e24766e665b2ee2f63b77d7103191a02dba3fcfb2173c35583c1bc20dfc07b38bb5ba977e86b5cf03a545831711508b7561974d1162809397bff8421607bdc49162b3cc60324ddf1240974cec8d94a8e89c66015c674f51bd28cfea4ac05e1bdc30417ebf6d3ca799295a299c0ae331bca44b2f57788129b817f3723b6579c328bad1149428a83d3d9cac1c4eb3edb512aa1e81bbf2ffd3be0c4e3dcac483858f44ad695f9f8c23cdc2d8061895e51c9c9083108f0e17b0445f39f773ca82585dea76f2a7351ea0c841fd60e73466cb60457", + "--block-vss", + "023cb7d6326e33332d04d026be1a04cdaf084703d8dc75322182d8fb314a03a87703b8ad9e3271a20d5eb2b622e455fcffa5c9c90e38b192772b2e1b58f6b442e78d00028fbd54f9b704c6c951c1b1f45bbc9c4559935d5bfe209d75507b70d4087829cf55e451b9e2ff5b91f491d2cd3fdc149d409fa2c4f07f009216cbb26afd496986a1dcb869f5418b1d3a1f9e75c655eade41930318e355844c2fc42018a7b345a466c0d55ce2fbc3584a0d155c4f7aef8ffe4ce60cc29682aa307fc3e5cbfcacfc92523e57c607ba85506a22d95c3789c9e3af172f3bafb01e6c9ef4ba19f9da1a8fbd54f9b704c6c951c1b1f45bbc9c4559935d5bfe209d75507b70d4087829cfaa1bae461d00a46e0b6e2d32c023eb62bf605d3b0f80ff6de9344d9402b692a97451c274ded2a2776a75158c7069b40a2fa61ad3c15921e12ee40c4a724689e67ff0299ad0e4ce45035dbc8fa1bdf287a7f1a9c06c7366b4c3073046ba0c2e5fedae0e8a92a4e97c25813d7ba6217de74ca8bd9c5bbd6a0c5e95722674748f3a", + "--node-secret-share", + "70f344fe8d0e53cd0341beae344ca68b8f09427a32aa33603c5fde61b66a09dc", + "--aggregated-public-key", + "03addb2555f37abf8f28f11f498bec7bd1460e7243c1813847c49a7ae326a97d1c", + "--private-key", + "L2hmApEYQBQo81RLJc5MMwo6ZZywnfVzuQj6uCfxFLaV2Yo2pVyq", + ]); + let response = SignCommand::execute(&matches); + assert_eq!( + format!("{}", response.err().unwrap()), + "InvalidArgs(\"xfield\")" + ); + } } diff --git a/src/crypto/multi_party_schnorr.rs b/src/crypto/multi_party_schnorr.rs index f3a33741c..bc81e509f 100644 --- a/src/crypto/multi_party_schnorr.rs +++ b/src/crypto/multi_party_schnorr.rs @@ -256,7 +256,7 @@ impl LocalSig { } } -#[derive(Clone, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct Signature { pub sigma: FE, pub v: GE, diff --git a/src/crypto/vss.rs b/src/crypto/vss.rs index 372dca2bc..a6603dff1 100644 --- a/src/crypto/vss.rs +++ b/src/crypto/vss.rs @@ -22,7 +22,7 @@ use std::collections::BTreeMap; use std::fmt; use std::io; use std::str::FromStr; -use tapyrus::blockdata::block::Block; +use tapyrus::blockdata::block::{Block, XField}; use tapyrus::consensus::encode::{self, *}; use tapyrus::util::prime::jacobi; use tapyrus::{PrivateKey, PublicKey}; @@ -119,6 +119,32 @@ impl Vss { } pub fn create_local_sig_from_shares( + _priv_shared_keys: &SharedKeys, + index: usize, + shared_block_secrets: &BidirectionalSharedSecretMap, + local_sig_for_positive: &LocalSig, + local_sig_for_negative: &LocalSig, + ) -> Result<(bool, SharedKeys, LocalSig), Error> { + let shared_keys_for_positive = + Sign::verify_vss_and_construct_key(&shared_block_secrets.for_positive(), &index)?; + + let shared_keys_for_negative = + Sign::verify_vss_and_construct_key(&shared_block_secrets.for_negative(), &index)?; + + let y = shared_keys_for_positive + .y + .y_coor() + .expect("can not get y_coor"); + let is_positive = jacobi(&Converter::to_vec(&y)) == 1; + let (shared_keys, local_sig) = if is_positive { + (shared_keys_for_positive, local_sig_for_positive) + } else { + (shared_keys_for_negative, local_sig_for_negative) + }; + Ok((is_positive, shared_keys, local_sig.clone())) + } + + pub fn create_local_sig_from_shares_for_block( priv_shared_keys: &SharedKeys, index: usize, shared_block_secrets: &BidirectionalSharedSecretMap, @@ -139,22 +165,47 @@ impl Vss { &priv_shared_keys, block.header.signature_hash(), ); + Self::create_local_sig_from_shares( + priv_shared_keys, + index, + shared_block_secrets, + &local_sig_for_positive, + &local_sig_for_negative, + ) + } - let y = shared_keys_for_positive - .y - .y_coor() - .expect("can not get y_coor"); - let is_positive = jacobi(&Converter::to_vec(&y)) == 1; - let (shared_keys, local_sig) = if is_positive { - (shared_keys_for_positive, local_sig_for_positive) - } else { - (shared_keys_for_negative, local_sig_for_negative) - }; - Ok((is_positive, shared_keys, local_sig)) + pub fn create_local_sig_from_shares_for_xfield( + priv_shared_keys: &SharedKeys, + index: usize, + shared_block_secrets: &BidirectionalSharedSecretMap, + xfield: &XField, + ) -> Result<(bool, SharedKeys, LocalSig), Error> { + let shared_keys_for_positive = + Sign::verify_vss_and_construct_key(&shared_block_secrets.for_positive(), &index)?; + let local_sig_for_positive = Sign::sign_xfield( + &shared_keys_for_positive, + &priv_shared_keys, + xfield.signature_hash()?, + ); + + let shared_keys_for_negative = + Sign::verify_vss_and_construct_key(&shared_block_secrets.for_negative(), &index)?; + let local_sig_for_negative = Sign::sign_xfield( + &shared_keys_for_negative, + &priv_shared_keys, + xfield.signature_hash()?, + ); + Self::create_local_sig_from_shares( + priv_shared_keys, + index, + shared_block_secrets, + &local_sig_for_positive, + &local_sig_for_negative, + ) } pub fn aggregate_and_verify_signature( - block: &Block, + hash: &[u8], signatures: BTreeMap, pubkey_list: &Vec, shared_secrets: &SharedSecretMap, @@ -189,7 +240,6 @@ impl Vss { block_shared_keys.unwrap().2, ); let public_key = priv_shared_keys.y; - let hash = block.header.signature_hash(); signature.verify(&hash[..], &public_key)?; Ok(signature) } @@ -544,9 +594,13 @@ mod tests { }) .collect(); - let (is_positive, key, local_sig) = - Vss::create_local_sig_from_shares(&priv_shared_keys, 1, &shared_block_secrets, &block) - .expect("error occurred in Vss::create_local_sig_from_shares"); + let (is_positive, key, local_sig) = Vss::create_local_sig_from_shares_for_block( + &priv_shared_keys, + 1, + &shared_block_secrets, + &block, + ) + .expect("error occurred in Vss::create_local_sig_from_shares"); let expected_localsig = to_local_sig(&v["expected_localsig"]).unwrap(); let expected_block_shared_keys = @@ -557,4 +611,87 @@ mod tests { assert_eq!(key.x_i, expected_block_shared_keys.1); assert_eq!(key.y, expected_block_shared_keys.2); } + + #[test] + fn test_create_local_sig_from_shares_xfield1() { + let contents = load_test_vector("./tests/resources/vss.json").unwrap(); + let v: Value = + serde_json::from_value(contents["create_local_sig_from_shares_successfully"].clone()) + .unwrap(); + let priv_shared_keys: SharedKeys = + serde_json::from_value(v["priv_shared_key"].clone()).unwrap(); + let xfield: XField = XField::AggregatePublicKey( + PublicKey::from_str( + "025700236c2890233592fcef262f4520d22af9160e3d9705855140eb2aa06c35d3", + ) + .unwrap(), + ); + let shared_block_secrets = v["shared_block_secrets"] + .as_object() + .unwrap() + .iter() + .map(|(k, value)| { + ( + to_signer_id(k), + (to_shared_secret(&value[0]), to_shared_secret(&value[1])), + ) + }) + .collect(); + + let (is_positive, key, local_sig) = Vss::create_local_sig_from_shares_for_xfield( + &priv_shared_keys, + 1, + &shared_block_secrets, + &xfield, + ) + .expect("error occurred in Vss::create_local_sig_from_shares"); + + let expected_localsig = to_local_sig(&v["expected_localsig"]).unwrap(); + let expected_block_shared_keys = + to_block_shared_keys(&v["expected_block_shared_keys"]).unwrap(); + + assert_eq!(false, is_positive); + assert_eq!(key.x_i, expected_block_shared_keys.1); + assert_eq!(key.y, expected_block_shared_keys.2); + //TODO : check signature + } + + #[test] + fn test_create_local_sig_from_shares_xfield2() { + let contents = load_test_vector("./tests/resources/vss.json").unwrap(); + let v: Value = + serde_json::from_value(contents["create_local_sig_from_shares_successfully"].clone()) + .unwrap(); + let priv_shared_keys: SharedKeys = + serde_json::from_value(v["priv_shared_key"].clone()).unwrap(); + let xfield: XField = XField::MaxBlockSize(100); + let shared_block_secrets = v["shared_block_secrets"] + .as_object() + .unwrap() + .iter() + .map(|(k, value)| { + ( + to_signer_id(k), + (to_shared_secret(&value[0]), to_shared_secret(&value[1])), + ) + }) + .collect(); + + let (is_positive, key, local_sig) = Vss::create_local_sig_from_shares_for_xfield( + &priv_shared_keys, + 1, + &shared_block_secrets, + &xfield, + ) + .expect("error occurred in Vss::create_local_sig_from_shares"); + + let expected_localsig = to_local_sig(&v["expected_localsig"]).unwrap(); + let expected_block_shared_keys = + to_block_shared_keys(&v["expected_block_shared_keys"]).unwrap(); + + assert_eq!(false, is_positive); + assert_eq!(key.x_i, expected_block_shared_keys.1); + assert_eq!(key.y, expected_block_shared_keys.2); + //TODO : check signature + } } diff --git a/src/federation.rs b/src/federation.rs index 004149782..e7c5ab560 100644 --- a/src/federation.rs +++ b/src/federation.rs @@ -1,12 +1,16 @@ -use crate::crypto::multi_party_schnorr::SharedKeys; +use crate::crypto::multi_party_schnorr::{SharedKeys, Signature}; use crate::crypto::vss::Vss; use crate::errors::Error; use crate::net::SignerID; use crate::sign::Sign; use crate::signer_node::{SharedSecret, SharedSecretMap}; +use crate::tapyrus::blockdata::block::XField; + use curv::cryptographic_primitives::secret_sharing::feldman_vss::{ ShamirSecretSharing, VerifiableSS, }; +use curv::elliptic::curves::traits::*; +use curv::{BigInt, FE, GE}; use std::collections::HashSet; use tapyrus::PublicKey; @@ -78,7 +82,7 @@ impl Federations { .federation .into_iter() .map(|i| Federation::from(*pubkey, i)) - .collect(); + .collect::, _>>()?; let r = Federations::new(vec); r.validate()?; @@ -102,8 +106,13 @@ pub struct Federation { /// Verifiable Secret Share and commitments from all signers in the federation. /// This field must be None when the signer is not a member of the federation. nodevss: Option>, - /// The aggregated public key - aggregated_public_key: PublicKey, + /// The federation parameter + /// aggregated public key / max block size + xfield: XField, + /// pubkey for signature verification + pub verification_key: Option, + /// federation signature + pub signature: Option, } impl Federation { @@ -112,17 +121,56 @@ impl Federation { block_height: u32, threshold: Option, nodevss: Option>, - aggregated_public_key: PublicKey, + xfield: XField, + verification_key: Option, + signature: Option, ) -> Self { Self { signer_id: SignerID::new(public_key), block_height, threshold, nodevss, - aggregated_public_key, + xfield, + verification_key, + signature, } } + pub fn from(pubkey: PublicKey, ser: SerFederation) -> Result { + let xfield: XField = match (ser.aggregated_public_key, ser.max_block_size) { + (Some(pubkey), None) => XField::AggregatePublicKey(pubkey), + (None, Some(x)) => XField::MaxBlockSize(x), + _ => { + return Err(Error::InvalidFederation( + Some(ser.block_height), + "No xfield in federation. Aggregated pubkey or max block size is expected", + )) + } + }; + let sig: Option = match ser.block_height { + 0 => None, + _ => { + let signature_hex = ser.signature.clone().unwrap_or_else(|| { + format!("No signature in federation at height {}", ser.block_height) + }); + + match multi_party_signature_from_hex(signature_hex.as_str()) { + Ok(sig) => Some(sig), + Err(e) => return Err(e), + } + } + }; + Ok(Self::new( + pubkey, + ser.block_height, + ser.threshold, + ser.nodevss, + xfield, + None, + sig, + )) + } + pub fn node_index(&self) -> usize { self.signers() .iter() @@ -154,8 +202,21 @@ impl Federation { .as_ref() .expect("The nodevss must not None, when it's used.") } - pub fn aggregated_public_key(&self) -> PublicKey { - self.aggregated_public_key + pub fn xfield(&self) -> &XField { + &self.xfield + } + + pub fn aggregated_public_key(&self) -> Option { + match self.xfield { + XField::AggregatePublicKey(x) => Some(x), + _ => None, + } + } + pub fn max_block_size(&self) -> Option { + match self.xfield { + XField::MaxBlockSize(x) => Some(x), + _ => None, + } } /// Returns Map collection of received shares from all each signers in Key Generation Protocol @@ -263,26 +324,96 @@ impl Federation { self.threshold.is_some() && self.nodevss.is_some() } - pub fn from(pubkey: PublicKey, ser: SerFederation) -> Self { + pub fn from_pubkey( + pubkey: PublicKey, + block_height: u32, + threshold: u8, + nodevss: Vec, + signature: Option, + ) -> Self { Self::new( pubkey, - ser.block_height, - ser.threshold, - ser.nodevss, - ser.aggregated_public_key, + block_height, + Some(threshold), + Some(nodevss), + XField::AggregatePublicKey(pubkey), + None, + signature, ) } - pub fn to_ser(self) -> SerFederation { - SerFederation { - block_height: self.block_height, - threshold: self.threshold, - nodevss: self.nodevss, - aggregated_public_key: self.aggregated_public_key, - } + pub fn from_maxblocksize( + pubkey: PublicKey, + block_height: u32, + maxblocksize: u32, + signature: Option, + ) -> Self { + Self::new( + pubkey, + block_height, + None, + None, + XField::MaxBlockSize(maxblocksize), + None, + signature, + ) + } + + pub fn to_ser(self) -> Result { + let nodevss = self.nodevss.clone(); + let signature: String = Sign::format_signature(&self.signature.clone().unwrap()); + + let federation = match self.xfield { + XField::AggregatePublicKey(_) => SerFederation { + block_height: self.block_height, + threshold: self.threshold, + nodevss: nodevss, + signature: Some(signature), + aggregated_public_key: self.aggregated_public_key(), + max_block_size: None, + }, + XField::MaxBlockSize(_) => SerFederation { + block_height: self.block_height, + threshold: self.threshold, + nodevss: nodevss, + signature: Some(signature), + max_block_size: self.max_block_size(), + aggregated_public_key: None, + }, + _ => SerFederation { + block_height: self.block_height, + threshold: self.threshold, + nodevss: nodevss, + signature: Some(signature), + max_block_size: None, + aggregated_public_key: None, + }, + }; + Ok(federation) } } +pub fn multi_party_signature_from_hex(s: &str) -> Result { + if s.len() != 128 { + return Err(Error::InvalidSig); + } + + let v_hex = &s[0..64]; + let sigma_hex = &s[64..128]; + + let v_bytes = hex::decode(v_hex).map_err(|_| Error::InvalidSig)?; + + let v_ge = GE::from_bytes(&v_bytes).map_err(|_| Error::InvalidSig)?; + + let sigma = BigInt::from_str_radix(sigma_hex, 16).unwrap(); + let sigma_fe: FE = ECScalar::from(&sigma); + + Ok(Signature { + sigma: sigma_fe, + v: v_ge, + }) +} + #[derive(Clone, Debug, Serialize, Deserialize)] pub struct SerFederations { federation: Vec, @@ -296,22 +427,31 @@ pub struct SerFederation { #[serde(rename = "node-vss")] nodevss: Option>, #[serde(rename = "aggregated-public-key")] - aggregated_public_key: PublicKey, + aggregated_public_key: Option, + #[serde(rename = "max-block-size")] + max_block_size: Option, + #[serde(rename = "signature")] + signature: Option, } #[cfg(test)] mod tests { + use crate::crypto::multi_party_schnorr::Signature; use crate::errors::Error; use crate::federation::{Federation, Federations}; + use crate::hex::FromHex; use crate::net::SignerID; + use crate::tapyrus::blockdata::block::XField; use crate::tests::helper::keys::TEST_KEYS; use crate::tests::helper::node_vss::node_vss; use curv::arithmetic::traits::Converter; - use curv::elliptic::curves::traits::ECScalar; - use curv::BigInt; + use curv::elliptic::curves::traits::{ECPoint, ECScalar}; + use curv::{BigInt, GE}; use std::str::FromStr; use tapyrus::PublicKey; + use super::SerFederation; + #[test] fn test_get_by_block_height() { let federation0 = Federation::new( @@ -319,21 +459,27 @@ mod tests { 0, Some(3), Some(node_vss(0)), - TEST_KEYS.aggregated(), + XField::AggregatePublicKey(TEST_KEYS.aggregated()), + None, + None, ); let federation100 = Federation::new( TEST_KEYS.pubkeys()[4], 100, Some(3), Some(node_vss(1)), - TEST_KEYS.aggregated(), + XField::AggregatePublicKey(TEST_KEYS.aggregated()), + None, + None, ); let federation200 = Federation::new( TEST_KEYS.pubkeys()[4], 200, Some(4), Some(node_vss(2)), - TEST_KEYS.aggregated(), + XField::AggregatePublicKey(TEST_KEYS.aggregated()), + None, + None, ); let federations = Federations::new(vec![ federation0.clone(), @@ -352,7 +498,9 @@ mod tests { 0, Some(3), Some(node_vss(0)), - TEST_KEYS.aggregated(), + XField::AggregatePublicKey(TEST_KEYS.aggregated()), + None, + None, ); let expected: Vec = TEST_KEYS @@ -364,15 +512,39 @@ mod tests { } fn valid_federation() -> Federation { + let sigma = ECScalar::from( + &BigInt::from_str_radix( + "16b63d6f3b5a88762d4477b843b857a3bf86677c7044db22a9aada2eb17d0641", + 16, + ) + .expect("Failed to parse BigInt"), + ); + + let v_bytes = + Vec::from_hex("dde06d981f17045b11c8db7b47846ceca4825f286756440ea158e0b2dba86028") + .expect("Failed to decode hex string"); + let v = GE::from_bytes(&v_bytes).expect("Failed to create GE from bytes"); + + let sig = Signature { sigma, v }; + Federation::new( TEST_KEYS.pubkeys()[0], - 0, + 10, Some(3), Some(node_vss(0)), - TEST_KEYS.aggregated(), + XField::AggregatePublicKey(TEST_KEYS.aggregated()), + None, + Some(sig), ) } + fn valid_federation_maxblocksize() -> Federation { + let mut federation = valid_federation(); + + federation.xfield = XField::MaxBlockSize(400000); + federation + } + #[test] fn test_federations_validate() { let federations = Federations::new(vec![valid_federation()]); @@ -394,59 +566,73 @@ mod tests { } _ => assert!(false, "it should error"), } + + let federations = + Federations::new(vec![valid_federation(), valid_federation_maxblocksize()]); + match federations.validate() { + Err(Error::InvalidFederation(None, m)) => { + assert_eq!(m, "The federations include block height duplication. The block height in all federations should be unique.") + } + _ => assert!(false, "it should error"), + } } #[test] fn test_federation_validate() { - let federation = valid_federation(); - assert!(federation.validate().is_ok()); + let valid_federation_generators = [valid_federation, valid_federation_maxblocksize]; + + for valid_federation_generator in valid_federation_generators { + let federation = valid_federation_generator(); + assert!(federation.validate().is_ok()); + + // federation has overlapped nodevss + let mut federation = valid_federation_generator(); + let vss = federation.nodevss.as_ref().unwrap()[0].clone(); + federation.nodevss.as_mut().unwrap().push(vss); + match federation.validate() { + Err(Error::InvalidFederation(_, m)) => { + assert_eq!(m, "nodevss has overlapping sender vss.") + } + _ => assert!(false, "it should error"), + } - // federation has overlapped nodevss - let mut federation = valid_federation(); - let vss = federation.nodevss.as_ref().unwrap()[0].clone(); - federation.nodevss.as_mut().unwrap().push(vss); - match federation.validate() { - Err(Error::InvalidFederation(_, m)) => { - assert_eq!(m, "nodevss has overlapping sender vss.") + // federation has invalid vss whose receiver is not equal with the node itself. + let mut federation = valid_federation_generator(); + federation.nodevss.as_mut().unwrap()[0].receiver_public_key = TEST_KEYS.pubkeys()[4]; + match federation.validate() { + Err(Error::InvalidFederation(_, m)) => { + assert_eq!(m, "The nodevss has wrong receiver value. All VSS's receiver_public_key should be equal with publish key of the signer who runs the node.") + } + _ => assert!(false, "it should error"), } - _ => assert!(false, "it should error"), - } - // federation has invalid vss whose receiver is not equal with the node itself. - let mut federation = valid_federation(); - federation.nodevss.as_mut().unwrap()[0].receiver_public_key = TEST_KEYS.pubkeys()[4]; - match federation.validate() { - Err(Error::InvalidFederation(_, m)) => { - assert_eq!(m, "The nodevss has wrong receiver value. All VSS's receiver_public_key should be equal with publish key of the signer who runs the node.") + // the federation has invalid number of commitment + let mut federation = valid_federation_generator(); + for i in federation.nodevss.as_mut().unwrap().iter_mut() { + let commitments = &mut i.positive_commitments; + commitments.drain(0..1); + } + match federation.validate() { + Err(Error::InvalidFederation(_, m)) => assert_eq!( + m, + "The nodevss has wrong vss which has wrong number of commitments." + ), + _ => assert!(false, "it should error"), } - _ => assert!(false, "it should error"), - } - // the federation has invalid number of commitment - let mut federation = valid_federation(); - for i in federation.nodevss.as_mut().unwrap().iter_mut() { - let commitments = &mut i.positive_commitments; - commitments.drain(0..1); - } - match federation.validate() { - Err(Error::InvalidFederation(_, m)) => assert_eq!( - m, - "The nodevss has wrong vss which has wrong number of commitments." - ), - _ => assert!(false, "it should error"), - } + // the federation has invalid secret share + let mut federation = valid_federation_generator(); - // the federation has invalid secret share - let mut federation = valid_federation(); - - federation.nodevss.as_mut().unwrap()[0].positive_secret = ECScalar::from( - &BigInt::from_hex("9b77b12bf0ec14c6094be7657a3a3d473077bc3c8b694ead6c1b6d8c5b4e816c"), - ); - match federation.validate() { - Err(Error::InvalidFederation(_, m)) => { - assert_eq!(m, "The nodevss includes invalid share.") + federation.nodevss.as_mut().unwrap()[0].positive_secret = + ECScalar::from(&BigInt::from_hex( + "9b77b12bf0ec14c6094be7657a3a3d473077bc3c8b694ead6c1b6d8c5b4e816c", + )); + match federation.validate() { + Err(Error::InvalidFederation(_, m)) => { + assert_eq!(m, "The nodevss includes invalid share.") + } + _ => assert!(false, "it should error"), } - _ => assert!(false, "it should error"), } // Skip vss validation when the federation doesn't include the signer. @@ -470,18 +656,25 @@ mod tests { fn test_serialize_deserialize() { let federation = valid_federation(); - let ser = federation.clone().to_ser(); + let ser = federation.clone().to_ser().unwrap(); + let str = toml::to_string(&ser).unwrap(); + let deserialized = + Federation::from(federation.signer_id.pubkey, toml::from_str(&str).unwrap()).unwrap(); + assert_eq!(federation, deserialized); + + let federation = valid_federation_maxblocksize(); + + let ser = federation.clone().to_ser().unwrap(); let str = toml::to_string(&ser).unwrap(); - println!("{}", str); let deserialized = - Federation::from(federation.signer_id.pubkey, toml::from_str(&str).unwrap()); + Federation::from(federation.signer_id.pubkey, toml::from_str(&str).unwrap()).unwrap(); assert_eq!(federation, deserialized); } #[test] fn test_from_pubkey_and_toml() { let pubkey = PublicKey::from_str( - "02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b72506", + "0302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25", ) .unwrap(); @@ -489,44 +682,48 @@ mod tests { let toml = r#" [[federation]] block-height = 0 - threshold = 3 - aggregated-public-key = "030d856ac9f5871c3785a2d76e3a5d9eca6fcce70f4de63339671dfb9d1f33edb0" + threshold = 2 + aggregated-public-key = "02459adb8a8f052be94874aef7d4c3d3ddb71fcdaa869b1d515a92d63cb29c2806" node-vss = [ - "02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b7250602472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060003472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b72506bb360eeb9d77cc606471ca455eb68331fbbdab6d009da456bef3920a61222f5835f7638e641b55dba9c5711ba47d50b8e1eefcf06d42c71708ae28dd1a038b02651456363420d02dc28ef180b66e781413133effde76d7eb7a57cffe41de3e6537325720efa3c4a847f84e72830280f2ff37758c69ade23f45d9e8c2f28f7b92a984669067dd13ecd9789da097d76f3b9c9b179f9948025db5e2ae00522f55515126b42d8c99f0b72c28ad5bf95ee38f4154f37df7d4a621b68db4f9f5c8070b472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b7250644c9f1146288339f9b8e35baa1497cce04425492ff625ba9410c6df49eddccd739e10be2c059db79d50c629fe78a929d8458d064261aaa873a478ccb3b0c18f7df28e9bf75c9e4f8101b4bfb007c538499945ed651aea6122164ee9dcff02405b41ced6471dc0099a740921e10ba7d539e69153b25b2bb97257fa8dd5f0109aa52e94a550998d573aebced1eb10aaafbae5cbfb6413eed0c17f88204f2e4b13c7746199720b3bee5c3d50b9ca9e3c32e905d7058a3cb9ec899bf428ba2e0d9c7", - "02785a891f323acd6cef0fc509bb14304410595914267c50467e51c87142acbb5e02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060003785a891f323acd6cef0fc509bb14304410595914267c50467e51c87142acbb5e12ab6cc10390ee6e31985e52e7d5701bed4c265dfc899cac07bc9c608ab02a74bf633344275792c413aac61fb108ba49aacb935cc637833a3d5f8bbc412a4578eec59fd45330922725e96c6c8e65980e3f571a9e99c7ea80abaabbfcc7a8541ca3bb9fb3393e593db51bf5bee44181cdf4cb1d617c0ce63682d8559f1424897b90c6c5c2684dda9a0f592fdc159c6dc744465f6de103c2ffe012c9a839034ae04a12fc2cc261586bf6b5814b1742449544aec456524b30fd530db6a76459162d785a891f323acd6cef0fc509bb14304410595914267c50467e51c87142acbb5eed54933efc6f1191ce67a1ad182a8fe412b3d9a203766353f843639e754fd1bbe5e5c0c4374a92bff9f7b7328d3baeb061b738dce75093a7a941cce96c5daf18284364f8ebabd43d3439169e92b27699e20be185ce3fb0fe44abc08fac1e25f4d256e87497f82f367abc2225cfe7d171f528160e681ae6a14df51ffdded1e96da93cc0bc30c7af4d608c6e026ca9b51f6ec61ad548117d0b98f010f847b2907e21ed09bf936cb602babaa8b37fcda1d159b6dd756c483ce982d1541e1a9bac03", - "02ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90002472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060003ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90015ea9fee96aed6d9c0fc2fbe0bd1883dee223b3200246ff1e21976bdbc9a0fc82ef0de1465a7dc27596e2e97087c70743c9a3686ed25882f342ab43c01d243053231904aa20a48130ce3da8a6c9c1cb96e3abf13c7fc2bc6467ff859ea85c78e0bba3cb4d94e2ed91b73b7734bc77f5a9e59e4f5dfa0358fabc24f72b3766f926e8cfbe7135e85b9463e796725b6d35f66d28929d1eda1e447260aa716b09f4acedc39c6e379af7740e5daf14fb9664872a8c3eecab1d3cd68f7d1d460344c32ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b900ea156011695129263f03d041f42e77c211ddc4cdffdb900e1de689414365ec672f24627e0a688cd54fb215fef833a804ad996f9f375f049e607bb739054b6d2cf43fcba949dd1cfa0f09b21873b445536717763e09e17383c8045e95917764c5bffccad34e90d7b469cdcc73bf2897af89b2f9171561143d12fd8996bf39d1bb20b4881975fef44f40ba71f14d827f3d2f26bc6182d5341189fefe308174a542ccb96b7a0ac351921d4efea5b01362c3d6bf8e815898e699ff4b2c6ac84d18d7", - "02d111519ba1f3013a7a613ecdcc17f4d53fbcb558b70404b5fb0c84ebb90a8d3c02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060003d111519ba1f3013a7a613ecdcc17f4d53fbcb558b70404b5fb0c84ebb90a8d3cb1e1ab71073241af34aabcee036dbb020b36121aebc19731ca3abeb3bbd19d9e1a7baec1441d10b7f1fbd182a4e53f9acc6f4de22485ceffe1254a77b10e9bf0a7d42cccac1043afccfd198b3cd1a0e498ece3a8f3b181f7ae3c3eb2c918e022f1502cf7a4cc817babde2cbd7f080c887ee2a4900355dcb716400a00620afc19776f6a43ba14206db88b85b80f5a3781bdfde64627b8c1ff7228b73626a648c66f3707fc6985b9b775144308ea347c7fc38099240ce9165bdbc9c5ffb5b71050d111519ba1f3013a7a613ecdcc17f4d53fbcb558b70404b5fb0c84ebb90a8d3c4e1e548ef8cdbe50cb554311fc9244fdf4c9ede5143e68ce35c5414b442e5e9128297089d43e94c182266476a1831e5eaa6668f1e00f9071df751e832475372f7c5e5ce7ecc7afd96d5feecfb8a0a28e602aea7040966c03a270aba823ea4277db9cd2bbb6f6017d04cecbcd41e758ebfd84d114b19279f867bd66ff5cd6615184dda648750e0152256f04cd7cc28d792daf3178267c6f443615b9a03d489ab3864c0d8af03257c52bd8199a308f51c114ee51d37f7033760a14253fdf76c29d", - "03831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060003831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc36efd8a52e2a27a50650b7e1f7db835c1f7fe5f7e587fb43e0009068b96d6ed306ae393ff8268523f6f4051a407c2e0164e14245b9499e714dd1691a5df832f1bcdd4c55bc2b958eea7b5f0de006bf6340d7ebc3de27fde6c0d639ce41f8af83f8a2f6b9f8d5dac2f971bf0f2ace4acc9ed2c70c617302755abd213421e7a1ccde12d18e5426de47339824faa5b40c307294d6835a92fa8e89ed6c1be85e9f9fd0ccd8f2fc4e0a1e5db88c74fd8a25b73076af74333671b84240b2d91d78303c831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafcc910275ad1d5d85af9af481e08247ca3e0801a081a7804bc1fff6f9646928d5c531a03ee21b178dd7fef9cb537d477705f48051f94363ceae0aec0a49b1e5460a47b2bf5fbacff69679a6ba3a839a36ef9e9ab7e4efdfad4dc6903e0af9df74c67a8d43ebc28d5acce6c2531d08b144fa2a06718eede8fd855aa7970c353d7ad833fa7f087bf2d00617549ef3da4f9986955f35e98b0c9db18021c853a2ddde4c52dfd720dd715403bdb22751217d54a58d0377f4ccc0723cab9a25b9587662e" + "021c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da0302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a2500021c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da7650c845ad480abe1a31a7d40815b7003b2cab562d22645980fd62b5fcaca5f6ce5946d3a138e4aef068730a987a2eb57bbfe02a83933a9f1865eed6b92814c08dc180ae7c0f0075c7645cb8cecf472069aa6cc10b8a1edc2623d4152fa3743b69fc0903900dc5727544c4c9cf1f40d12e8eda6d29f111216de58c5482354c161c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da7650c845ad480abe1a31a7d40815b7003b2cab562d22645980fd62b5fcaca5f6ce5946d3a138e4aef068730a987a2eb57bbfe02a83933a9f1865eed6b92814c08dc180ae7c0f0075c7645cb8cecf472069aa6cc10b8a1edc2623d4152fa3743b69fc0903900dc5727544c4c9cf1f40d12e8eda6d29f111216de58c5482354c16", + "0302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a250302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25000202f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec39a991401abf2e71cb8a0455c9b82542724eb2493f43558cd35a8a80eeeebf30b7531d698c1de7f199f8be4bdd265ef8f8950e2c8ba255718e2e847472d6411a5a8f697000faa20097baa0848d4945b5543dd0530108d2b1552940aa7785e427a02f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec39a991401abf2e71cb8a0455c9b82542724eb2493f43558cd35a8a80eeeebf30b7531d698c1de7f199f8be4bdd265ef8f8950e2c8ba255718e2e847472d6411a5a8f697000faa20097baa0848d4945b5543dd0530108d2b1552940aa7785e427a", + "0315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25000215d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f105ce821aefb02ed9bbada8355d3179ca4a8a392260db9c5d34e44006395256317b9b4bb48a435b9aa5d36fddab8d7bd764e27e0dfeeec273d3a635d2d53707a5600917878572511804651724a877d126452c33b7ea12df1318b1934c72d816b515d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f105ce821aefb02ed9bbada8355d3179ca4a8a392260db9c5d34e44006395256317b9b4bb48a435b9aa5d36fddab8d7bd764e27e0dfeeec273d3a635d2d53707a5600917878572511804651724a877d126452c33b7ea12df1318b1934c72d816b5" ] [[federation]] - block-height = 100 + block-height = 20 threshold = 2 - aggregated-public-key = "030acd6af981c498ebf2ffd9a341d2a96bde5832c150e7d300fa3583eee0f964fe" + aggregated-public-key = "0376c3265e7d81839c1b2312b95697d47cc5b3ab3369a92a5af52ef1c945792f50" node-vss = [ - "02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b7250602472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b72506bb360eeb9d77cc606471ca455eb68331fbbdab6d009da456bef3920a61222f58df14e215a3883ff8c8def6bdce4d9d80282749b8056ec72373a246b3de5aa120b336d88a9b977a2f2ff5f26a1633f70f2d776363c495a02617bb7a88a2fea285a0a0e33e16dd90acb06b22fc70086f7eb12cdfeb7eb622d8a455de1f448fd30a472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b7250644c9f1146288339f9b8e35baa1497cce04425492ff625ba9410c6df49eddccd761c1af39b4fcbe4e3a240848bc90f41681ec105286684d4832efdc5b96a0e027286d9f7d22ad52194da7d522e5586ce268c7fde21220aca78e21d1d1a5d69f2468fff1b0f8a3a142cf0e1c7d29cbe3e509c437cd680ab21715cb5c1844d2eff8", - "02ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90002472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90015ea9fee96aed6d9c0fc2fbe0bd1883dee223b3200246ff1e21976bdbc9a0fc81f4be7002fae5b70835ee7e51893f76dd840ea64010504b8c66197d9cad767236a786cc7b91146df5e8d1ff73ad220b3578359eda61c341a8b5c41de6b068f73696b619f9213a550d0bc159ba1ff43c4e90c85930904a6f7f582b52074e3d965ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b900ea156011695129263f03d041f42e77c211ddc4cdffdb900e1de689414365ec672ad0d285c094287a3e2cc42d88e0736a1e238f33cde1ef9bd1cd9a0e8fe4a37dec94b7927535da68f388e4d5f07e838b71c742302476336b68f47b2e802b8c88a0fd87b9acc67ab564501a9777cf6081f50798b2ae8f2dff8a5190a27cfaf0e3", - "03831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc36efd8a52e2a27a50650b7e1f7db835c1f7fe5f7e587fb43e0009068b96d6ed35b71e1d42c2b7755bc33a7408032915da2a640b1b4227e13cd28efafc9e4af50fa777e082bd1afc64a4c2a67379df5a49233b6f003b96625f25f8dbe14fc7478fb75efb0cbcf147375065344b5c5f802bcd9057740983297749375b21d876d26831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafcc910275ad1d5d85af9af481e08247ca3e0801a081a7804bc1fff6f9646928d5c8f2a6c11c0fa9382aff7496614860f05779d3a0c5e6813db99d4b53417ac77c624171c6f14d272660f2556c9db9e3cca3e05a814a09fd5952dac72e18c7851c518063e5896e261aef163636449d673aba880160e57b5beee92362d74b5eb71dd" + "0302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a250302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25000202f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec33ecf34027b4922b3145e69a6006ca3414a7d6cb3ba888c4eadc546cd640f60b930f5d90d1bffafd82e57409e72d5170bd65317e5b87e17d61818546c95d5f35e951ff864871be49c79cfdd99ce8c3457324f446c272622ffafd57e7654f45ecc02f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec33ecf34027b4922b3145e69a6006ca3414a7d6cb3ba888c4eadc546cd640f60b930f5d90d1bffafd82e57409e72d5170bd65317e5b87e17d61818546c95d5f35e951ff864871be49c79cfdd99ce8c3457324f446c272622ffafd57e7654f45ecc", + "0315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25000215d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f1f960f10435a23ea5c590bb1e2271e130fe67d582926c534aa1331d1b84ce127df4ae07160b3ef4bfdcb0035aea945ceb4b2323975fd90789d20637fdac29479d8fd125986ab6b55c756dcd270268cc0f49b303ed438732b94773f7b64ed7df9715d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f1f960f10435a23ea5c590bb1e2271e130fe67d582926c534aa1331d1b84ce127df4ae07160b3ef4bfdcb0035aea945ceb4b2323975fd90789d20637fdac29479d8fd125986ab6b55c756dcd270268cc0f49b303ed438732b94773f7b64ed7df97", + "039af53a49a365576de41a2e70cc148353d7d1f4cad45f888fd8bc6d2c94a976570302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a2500029af53a49a365576de41a2e70cc148353d7d1f4cad45f888fd8bc6d2c94a976579fc4ac8cde7d898910cb47345069cfc6c086e767b8e90276551762478dfe20fb0af6b91228e3e520a02c8e96904cc6ea13e7e5752d2c25fc260586561934b8024613acba6b7f33498353f3ff136bad71648278b5ef245f9f04cf10657728e0283dd5f93cd4f175390d7396499e506a5afb47121eb0316e018426f74348b9a8ac9af53a49a365576de41a2e70cc148353d7d1f4cad45f888fd8bc6d2c94a976579fc4ac8cde7d898910cb47345069cfc6c086e767b8e90276551762478dfe20fb0af6b91228e3e520a02c8e96904cc6ea13e7e5752d2c25fc260586561934b8024613acba6b7f33498353f3ff136bad71648278b5ef245f9f04cf10657728e0283dd5f93cd4f175390d7396499e506a5afb47121eb0316e018426f74348b9a8ac" ] + signature = "90c90936d44e75bf25f8a6d1c21020a8dc7ee7f4d62a3d7ae278d9ff6a74901f687eee4236a64805414a43c344d12882061518be61014e76027cf6b8fd845aa0" "#; let federations = Federations::from_pubkey_and_toml(&pubkey, toml).unwrap(); assert_eq!(federations.len(), 2); // valid toml. It has a federation doesn't includes the node. + let pubkey = PublicKey::from_str( + "021c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da", + ) + .unwrap(); + let toml = r#" [[federation]] block-height = 0 - aggregated-public-key = "030d856ac9f5871c3785a2d76e3a5d9eca6fcce70f4de63339671dfb9d1f33edb0" - - [[federation]] - block-height = 100 threshold = 2 - aggregated-public-key = "030acd6af981c498ebf2ffd9a341d2a96bde5832c150e7d300fa3583eee0f964fe" + aggregated-public-key = "02459adb8a8f052be94874aef7d4c3d3ddb71fcdaa869b1d515a92d63cb29c2806" node-vss = [ - "02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b7250602472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b72506bb360eeb9d77cc606471ca455eb68331fbbdab6d009da456bef3920a61222f58df14e215a3883ff8c8def6bdce4d9d80282749b8056ec72373a246b3de5aa120b336d88a9b977a2f2ff5f26a1633f70f2d776363c495a02617bb7a88a2fea285a0a0e33e16dd90acb06b22fc70086f7eb12cdfeb7eb622d8a455de1f448fd30a472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b7250644c9f1146288339f9b8e35baa1497cce04425492ff625ba9410c6df49eddccd761c1af39b4fcbe4e3a240848bc90f41681ec105286684d4832efdc5b96a0e027286d9f7d22ad52194da7d522e5586ce268c7fde21220aca78e21d1d1a5d69f2468fff1b0f8a3a142cf0e1c7d29cbe3e509c437cd680ab21715cb5c1844d2eff8", - "02ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90002472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90015ea9fee96aed6d9c0fc2fbe0bd1883dee223b3200246ff1e21976bdbc9a0fc81f4be7002fae5b70835ee7e51893f76dd840ea64010504b8c66197d9cad767236a786cc7b91146df5e8d1ff73ad220b3578359eda61c341a8b5c41de6b068f73696b619f9213a550d0bc159ba1ff43c4e90c85930904a6f7f582b52074e3d965ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b900ea156011695129263f03d041f42e77c211ddc4cdffdb900e1de689414365ec672ad0d285c094287a3e2cc42d88e0736a1e238f33cde1ef9bd1cd9a0e8fe4a37dec94b7927535da68f388e4d5f07e838b71c742302476336b68f47b2e802b8c88a0fd87b9acc67ab564501a9777cf6081f50798b2ae8f2dff8a5190a27cfaf0e3", - "03831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc36efd8a52e2a27a50650b7e1f7db835c1f7fe5f7e587fb43e0009068b96d6ed35b71e1d42c2b7755bc33a7408032915da2a640b1b4227e13cd28efafc9e4af50fa777e082bd1afc64a4c2a67379df5a49233b6f003b96625f25f8dbe14fc7478fb75efb0cbcf147375065344b5c5f802bcd9057740983297749375b21d876d26831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafcc910275ad1d5d85af9af481e08247ca3e0801a081a7804bc1fff6f9646928d5c8f2a6c11c0fa9382aff7496614860f05779d3a0c5e6813db99d4b53417ac77c624171c6f14d272660f2556c9db9e3cca3e05a814a09fd5952dac72e18c7851c518063e5896e261aef163636449d673aba880160e57b5beee92362d74b5eb71dd" + "021c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da021c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da00021c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da7650c845ad480abe1a31a7d40815b7003b2cab562d22645980fd62b5fcaca5f6ce5946d3a138e4aef068730a987a2eb57bbfe02a83933a9f1865eed6b92814c08dc180ae7c0f0075c7645cb8cecf472069aa6cc10b8a1edc2623d4152fa3743be73faa937a3ee41f556ac4b37b79282af663e3bc4a361221f2911d947a06a8361c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da7650c845ad480abe1a31a7d40815b7003b2cab562d22645980fd62b5fcaca5f6ce5946d3a138e4aef068730a987a2eb57bbfe02a83933a9f1865eed6b92814c08dc180ae7c0f0075c7645cb8cecf472069aa6cc10b8a1edc2623d4152fa3743be73faa937a3ee41f556ac4b37b79282af663e3bc4a361221f2911d947a06a836", + "0302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25021c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da000202f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec39a991401abf2e71cb8a0455c9b82542724eb2493f43558cd35a8a80eeeebf30b7531d698c1de7f199f8be4bdd265ef8f8950e2c8ba255718e2e847472d6411a5fa80b0328e8d55b146e52bd32bf6e5b7148d3bd1436cf8a86ff3d5c25d457c5c02f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec39a991401abf2e71cb8a0455c9b82542724eb2493f43558cd35a8a80eeeebf30b7531d698c1de7f199f8be4bdd265ef8f8950e2c8ba255718e2e847472d6411a5fa80b0328e8d55b146e52bd32bf6e5b7148d3bd1436cf8a86ff3d5c25d457c5c", + "0315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c9021c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da000215d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f105ce821aefb02ed9bbada8355d3179ca4a8a392260db9c5d34e44006395256317b9b4bb48a435b9aa5d36fddab8d7bd764e27e0dfeeec273d3a635d2d53707a55c14102eb04e3d6928149560ed26c8cd0923317dee7aa1941b5a822fabfcd41115d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f105ce821aefb02ed9bbada8355d3179ca4a8a392260db9c5d34e44006395256317b9b4bb48a435b9aa5d36fddab8d7bd764e27e0dfeeec273d3a635d2d53707a55c14102eb04e3d6928149560ed26c8cd0923317dee7aa1941b5a822fabfcd411" ] + [[federation]] + block-height = 30 + aggregated-public-key = "0376c3265e7d81839c1b2312b95697d47cc5b3ab3369a92a5af52ef1c945792f50" + signature ="90c90936d44e75bf25f8a6d1c21020a8dc7ee7f4d62a3d7ae278d9ff6a74901f687eee4236a64805414a43c344d12882061518be61014e76027cf6b8fd845aa0" "#; let federations = Federations::from_pubkey_and_toml(&pubkey, toml).unwrap(); @@ -553,10 +750,17 @@ mod tests { "02ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90002472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90015ea9fee96aed6d9c0fc2fbe0bd1883dee223b3200246ff1e21976bdbc9a0fc81f4be7002fae5b70835ee7e51893f76dd840ea64010504b8c66197d9cad767236a786cc7b91146df5e8d1ff73ad220b3578359eda61c341a8b5c41de6b068f73696b619f9213a550d0bc159ba1ff43c4e90c85930904a6f7f582b52074e3d965ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b900ea156011695129263f03d041f42e77c211ddc4cdffdb900e1de689414365ec672ad0d285c094287a3e2cc42d88e0736a1e238f33cde1ef9bd1cd9a0e8fe4a37dec94b7927535da68f388e4d5f07e838b71c742302476336b68f47b2e802b8c88a0fd87b9acc67ab564501a9777cf6081f50798b2ae8f2dff8a5190a27cfaf0e3", "03831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc36efd8a52e2a27a50650b7e1f7db835c1f7fe5f7e587fb43e0009068b96d6ed35b71e1d42c2b7755bc33a7408032915da2a640b1b4227e13cd28efafc9e4af50fa777e082bd1afc64a4c2a67379df5a49233b6f003b96625f25f8dbe14fc7478fb75efb0cbcf147375065344b5c5f802bcd9057740983297749375b21d876d26831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafcc910275ad1d5d85af9af481e08247ca3e0801a081a7804bc1fff6f9646928d5c8f2a6c11c0fa9382aff7496614860f05779d3a0c5e6813db99d4b53417ac77c624171c6f14d272660f2556c9db9e3cca3e05a814a09fd5952dac72e18c7851c518063e5896e261aef163636449d673aba880160e57b5beee92362d74b5eb71dd" ] + signature="90c90936d44e75bf25f8a6d1c21020a8dc7ee7f4d62a3d7ae278d9ff6a74901f687eee4236a64805414a43c344d12882061518be61014e76027cf6b8fd845aa0" "#; match Federations::from_pubkey_and_toml(&pubkey, toml) { - Err(Error::InvalidTomlFormat(_)) => assert!(true), + Err(Error::InvalidFederation(height, err)) => { + assert_eq!(height.unwrap(), 100); + assert_eq!( + err, + "No xfield in federation. Aggregated pubkey or max block size is expected" + ) + } _ => assert!(false, "it should error"), } @@ -574,18 +778,18 @@ mod tests { "03831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060003831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc36efd8a52e2a27a50650b7e1f7db835c1f7fe5f7e587fb43e0009068b96d6ed306ae393ff8268523f6f4051a407c2e0164e14245b9499e714dd1691a5df832f1bcdd4c55bc2b958eea7b5f0de006bf6340d7ebc3de27fde6c0d639ce41f8af83f8a2f6b9f8d5dac2f971bf0f2ace4acc9ed2c70c617302755abd213421e7a1ccde12d18e5426de47339824faa5b40c307294d6835a92fa8e89ed6c1be85e9f9fd0ccd8f2fc4e0a1e5db88c74fd8a25b73076af74333671b84240b2d91d78303c831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafcc910275ad1d5d85af9af481e08247ca3e0801a081a7804bc1fff6f9646928d5c531a03ee21b178dd7fef9cb537d477705f48051f94363ceae0aec0a49b1e5460a47b2bf5fbacff69679a6ba3a839a36ef9e9ab7e4efdfad4dc6903e0af9df74c67a8d43ebc28d5acce6c2531d08b144fa2a06718eede8fd855aa7970c353d7ad833fa7f087bf2d00617549ef3da4f9986955f35e98b0c9db18021c853a2ddde4c52dfd720dd715403bdb22751217d54a58d0377f4ccc0723cab9a25b9587662e" ] [[federation]] - block-height = 100 - threshold = 2 - aggregated-public-key = "030acd6af981c498ebf2ffd9a341d2a96bde5832c150e7d300fa3583eee0f964fe" - node-vss = [ - "02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b7250602472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b72506bb360eeb9d77cc606471ca455eb68331fbbdab6d009da456bef3920a61222f58df14e215a3883ff8c8def6bdce4d9d80282749b8056ec72373a246b3de5aa120b336d88a9b977a2f2ff5f26a1633f70f2d776363c495a02617bb7a88a2fea285a0a0e33e16dd90acb06b22fc70086f7eb12cdfeb7eb622d8a455de1f448fd30a472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b7250644c9f1146288339f9b8e35baa1497cce04425492ff625ba9410c6df49eddccd761c1af39b4fcbe4e3a240848bc90f41681ec105286684d4832efdc5b96a0e027286d9f7d22ad52194da7d522e5586ce268c7fde21220aca78e21d1d1a5d69f2468fff1b0f8a3a142cf0e1c7d29cbe3e509c437cd680ab21715cb5c1844d2eff8", - "02ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90002472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90015ea9fee96aed6d9c0fc2fbe0bd1883dee223b3200246ff1e21976bdbc9a0fc81f4be7002fae5b70835ee7e51893f76dd840ea64010504b8c66197d9cad767236a786cc7b91146df5e8d1ff73ad220b3578359eda61c341a8b5c41de6b068f73696b619f9213a550d0bc159ba1ff43c4e90c85930904a6f7f582b52074e3d965ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b900ea156011695129263f03d041f42e77c211ddc4cdffdb900e1de689414365ec672ad0d285c094287a3e2cc42d88e0736a1e238f33cde1ef9bd1cd9a0e8fe4a37dec94b7927535da68f388e4d5f07e838b71c742302476336b68f47b2e802b8c88a0fd87b9acc67ab564501a9777cf6081f50798b2ae8f2dff8a5190a27cfaf0e3", - "03831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc36efd8a52e2a27a50650b7e1f7db835c1f7fe5f7e587fb43e0009068b96d6ed35b71e1d42c2b7755bc33a7408032915da2a640b1b4227e13cd28efafc9e4af50fa777e082bd1afc64a4c2a67379df5a49233b6f003b96625f25f8dbe14fc7478fb75efb0cbcf147375065344b5c5f802bcd9057740983297749375b21d876d26831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafcc910275ad1d5d85af9af481e08247ca3e0801a081a7804bc1fff6f9646928d5c8f2a6c11c0fa9382aff7496614860f05779d3a0c5e6813db99d4b53417ac77c624171c6f14d272660f2556c9db9e3cca3e05a814a09fd5952dac72e18c7851c518063e5896e261aef163636449d673aba880160e57b5beee92362d74b5eb71dd" - ] + block-height = 200 + signature="90c90936d44e75bf25f8a6d1c21020a8dc7ee7f4d62a3d7ae278d9ff6a74901f687eee4236a64805414a43c344d12882061518be61014e76027cf6b8fd845aa0" "#; match Federations::from_pubkey_and_toml(&pubkey, toml) { - Err(Error::InvalidFederation(_, _)) => assert!(true), + Err(Error::InvalidFederation(height, err)) => { + assert_eq!(height.unwrap(), 200); + assert_eq!( + err, + "No xfield in federation. Aggregated pubkey or max block size is expected" + ) + } _ => assert!(false, "it should error"), } } diff --git a/src/sign.rs b/src/sign.rs index 301f50880..631ab6b75 100644 --- a/src/sign.rs +++ b/src/sign.rs @@ -5,6 +5,7 @@ use curv::arithmetic::traits::*; use curv::cryptographic_primitives::secret_sharing::feldman_vss::VerifiableSS; use curv::elliptic::curves::traits::*; use curv::{BigInt, FE, GE}; +use tapyrus::XFieldHash; use crate::errors::Error; use crate::signer_node::SharedSecretMap; @@ -78,6 +79,15 @@ impl Sign { local_sig } + pub fn sign_xfield( + eph_shared_keys: &SharedKeys, + priv_shared_keys: &SharedKeys, + message: XFieldHash, + ) -> LocalSig { + let local_sig = LocalSig::compute(&message[..], &eph_shared_keys, &priv_shared_keys); + local_sig + } + pub fn aggregate( vss_sum: &VerifiableSS, local_sigs: &Vec, diff --git a/src/signer_node/message_processor/mod.rs b/src/signer_node/message_processor/mod.rs index 9b1f620c0..c5e01266f 100644 --- a/src/signer_node/message_processor/mod.rs +++ b/src/signer_node/message_processor/mod.rs @@ -131,7 +131,7 @@ where let block_height = prev_state.block_height(); let federation = params.get_federation_by_block_height(block_height); - Vss::create_local_sig_from_shares( + Vss::create_local_sig_from_shares_for_block( &federation.node_secret_share(), params.self_node_index(block_height) + 1, shared_block_secrets, diff --git a/src/signer_node/message_processor/process_blocksig.rs b/src/signer_node/message_processor/process_blocksig.rs index f3e4034f8..820afd4a5 100644 --- a/src/signer_node/message_processor/process_blocksig.rs +++ b/src/signer_node/message_processor/process_blocksig.rs @@ -37,7 +37,7 @@ where let mut builder = DumpBuilder::default(); let federation = params.get_federation_by_block_height(block_height); let node_vss = federation.nodevss(); - let aggregated_public_key = federation.aggregated_public_key(); + let aggregated_public_key = federation.aggregated_public_key().unwrap(); builder .received(Received { sender: sender_id.clone(), @@ -132,7 +132,7 @@ where let federation = params.get_federation_by_block_height(block_height); let signature = match Vss::aggregate_and_verify_signature( - candidate_block, + &candidate_block.header.signature_hash(), new_signatures, ¶ms.pubkey_list(block_height), &federation.node_shared_secrets(), @@ -415,7 +415,9 @@ mod tests { 0, Some(dump.threshold as u8), Some(dump.node_vss.clone()), - dump.aggregated_public_key, + XField::AggregatePublicKey(dump.aggregated_public_key), + None, + None, )]; let federations = Federations::new(federations); let params = NodeParametersBuilder::new() @@ -459,7 +461,9 @@ mod tests { 0, Some(dump.threshold as u8), Some(dump.node_vss.clone()), - dump.aggregated_public_key, + XField::AggregatePublicKey(dump.aggregated_public_key), + None, + None, )]; let federations = Federations::new(federations); let params = NodeParametersBuilder::new() @@ -505,7 +509,9 @@ mod tests { 0, Some(dump.threshold as u8), Some(dump.node_vss.clone()), - dump.aggregated_public_key, + XField::AggregatePublicKey(dump.aggregated_public_key), + None, + None, )]; let federations = Federations::new(federations); let params = NodeParametersBuilder::new() diff --git a/src/signer_node/message_processor/process_candidateblock.rs b/src/signer_node/message_processor/process_candidateblock.rs index f0c93b7f5..c8cb88c6f 100644 --- a/src/signer_node/message_processor/process_candidateblock.rs +++ b/src/signer_node/message_processor/process_candidateblock.rs @@ -92,7 +92,7 @@ where let next_block_height = block_height + 1; let federation = params.get_federation_by_block_height(next_block_height); if let Some(public_key) = block.header.aggregated_public_key() { - if public_key == federation.aggregated_public_key() + if public_key == federation.aggregated_public_key().unwrap() && next_block_height == federation.block_height() { Ok(()) @@ -310,14 +310,18 @@ mod tests { 0, Some(3), Some(node_vss(0)), - TEST_KEYS.aggregated(), + XField::AggregatePublicKey(TEST_KEYS.aggregated()), + None, + None, ); let federation100 = Federation::new( TEST_KEYS.pubkeys()[4], 100, Some(3), Some(node_vss(1)), - TEST_KEYS.aggregated(), + XField::AggregatePublicKey(TEST_KEYS.aggregated()), + None, + None, ); let another_key = PublicKey::from_str( "030acd6af981c498ebf2ffd9a341d2a96bde5832c150e7d300fa3583eee0f964fe", @@ -328,7 +332,9 @@ mod tests { 200, Some(4), Some(node_vss(2)), - another_key, + XField::AggregatePublicKey(another_key), + None, + None, ); let federations = Federations::new(vec![ federation0.clone(), diff --git a/src/signer_node/mod.rs b/src/signer_node/mod.rs index 839553a57..911e78bf6 100644 --- a/src/signer_node/mod.rs +++ b/src/signer_node/mod.rs @@ -617,7 +617,7 @@ mod tests { use std::thread; use std::thread::JoinHandle; use std::time::Duration; - use tapyrus::blockdata::block::Block; + use tapyrus::blockdata::block::{Block, XField}; use tapyrus::consensus::encode::deserialize; use tapyrus::PublicKey; @@ -722,7 +722,9 @@ mod tests { 0, threshold, Some(node_vss(0)), - aggregated_public_key, + XField::AggregatePublicKey(aggregated_public_key), + None, + None, )])); let mut params = NodeParameters::new(to_address, public_key, rpc, 0, 10, true, federations); diff --git a/src/signer_node/node_parameters.rs b/src/signer_node/node_parameters.rs index 4982b860b..0ffa8a6fc 100644 --- a/src/signer_node/node_parameters.rs +++ b/src/signer_node/node_parameters.rs @@ -88,7 +88,7 @@ impl NodeParameters { pub fn aggregated_public_key(&self, block_height: u32) -> PublicKey { let federation = self.get_federation_by_block_height(block_height); - federation.aggregated_public_key() + federation.aggregated_public_key().unwrap() } } diff --git a/src/tests/helper/mod.rs b/src/tests/helper/mod.rs index 2208fd330..ea68c2dfe 100644 --- a/src/tests/helper/mod.rs +++ b/src/tests/helper/mod.rs @@ -47,7 +47,7 @@ pub mod test_vectors { use crate::tests::helper::node_parameters_builder::NodeParametersBuilder; use crate::tests::helper::rpc::MockRpc; - use tapyrus::blockdata::block::Block; + use tapyrus::blockdata::block::{Block, XField}; use tapyrus::consensus::encode::deserialize; use tapyrus::{PrivateKey, PublicKey}; @@ -156,13 +156,31 @@ pub mod test_vectors { let threshold = value["threshold"].as_u64().unwrap(); let aggregated_public_key = to_public_key(&value["aggregated_public_key"]); let public_key = to_public_key(&value["public_key"]); - let federations = vec![Federation::new( - public_key, - 0, - Some(threshold as u8), - Some(node_vss.clone()), - aggregated_public_key, - )]; + let mut federations = vec![]; + if value["aggregated_public_key"] != "" { + let aggregated_public_key = to_public_key(&value["aggregated_public_key"]); + federations = vec![Federation::new( + public_key, + 0, + Some(threshold as u8), + Some(node_vss.clone()), + XField::AggregatePublicKey(aggregated_public_key), + None, + None, + )]; + } else if value["max_block_size"] != "" { + let max_block_size = value["max_block_size"].as_u64().unwrap() as u32; + federations = vec![Federation::new( + public_key, + 0, + Some(threshold as u8), + Some(node_vss.clone()), + XField::MaxBlockSize(max_block_size), + None, + None, + )]; + } + let federations = Federations::new(federations); NodeParametersBuilder::new() .rpc(rpc) diff --git a/src/tests/helper/node_parameters_builder.rs b/src/tests/helper/node_parameters_builder.rs index 8dbc816c1..7b265b92e 100644 --- a/src/tests/helper/node_parameters_builder.rs +++ b/src/tests/helper/node_parameters_builder.rs @@ -4,6 +4,7 @@ use crate::tests::helper::address; use crate::tests::helper::keys::TEST_KEYS; use crate::tests::helper::node_vss::node_vss; use crate::tests::helper::rpc::MockRpc; +use tapyrus::blockdata::block::XField; use tapyrus::{Address, PublicKey}; pub struct NodeParametersBuilder { @@ -31,7 +32,9 @@ impl NodeParametersBuilder { 0, Some(2), Some(node_vss(0)), - TEST_KEYS.aggregated(), + XField::AggregatePublicKey(TEST_KEYS.aggregated()), + None, + None, )]), } } diff --git a/tests/resources/federations.toml b/tests/resources/federations.toml index 9bade3b6f..a97dd7e40 100644 --- a/tests/resources/federations.toml +++ b/tests/resources/federations.toml @@ -1,21 +1,19 @@ [[federation]] block-height = 0 -threshold = 3 -aggregated-public-key = "030d856ac9f5871c3785a2d76e3a5d9eca6fcce70f4de63339671dfb9d1f33edb0" +threshold = 2 +aggregated-public-key = "02459adb8a8f052be94874aef7d4c3d3ddb71fcdaa869b1d515a92d63cb29c2806" node-vss = [ - "02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b7250602472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060003472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b72506bb360eeb9d77cc606471ca455eb68331fbbdab6d009da456bef3920a61222f5835f7638e641b55dba9c5711ba47d50b8e1eefcf06d42c71708ae28dd1a038b02651456363420d02dc28ef180b66e781413133effde76d7eb7a57cffe41de3e6537325720efa3c4a847f84e72830280f2ff37758c69ade23f45d9e8c2f28f7b92a984669067dd13ecd9789da097d76f3b9c9b179f9948025db5e2ae00522f55515126b42d8c99f0b72c28ad5bf95ee38f4154f37df7d4a621b68db4f9f5c8070b472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b7250644c9f1146288339f9b8e35baa1497cce04425492ff625ba9410c6df49eddccd739e10be2c059db79d50c629fe78a929d8458d064261aaa873a478ccb3b0c18f7df28e9bf75c9e4f8101b4bfb007c538499945ed651aea6122164ee9dcff02405b41ced6471dc0099a740921e10ba7d539e69153b25b2bb97257fa8dd5f0109aa52e94a550998d573aebced1eb10aaafbae5cbfb6413eed0c17f88204f2e4b13c7746199720b3bee5c3d50b9ca9e3c32e905d7058a3cb9ec899bf428ba2e0d9c7", - "02785a891f323acd6cef0fc509bb14304410595914267c50467e51c87142acbb5e02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060003785a891f323acd6cef0fc509bb14304410595914267c50467e51c87142acbb5e12ab6cc10390ee6e31985e52e7d5701bed4c265dfc899cac07bc9c608ab02a74bf633344275792c413aac61fb108ba49aacb935cc637833a3d5f8bbc412a4578eec59fd45330922725e96c6c8e65980e3f571a9e99c7ea80abaabbfcc7a8541ca3bb9fb3393e593db51bf5bee44181cdf4cb1d617c0ce63682d8559f1424897b90c6c5c2684dda9a0f592fdc159c6dc744465f6de103c2ffe012c9a839034ae04a12fc2cc261586bf6b5814b1742449544aec456524b30fd530db6a76459162d785a891f323acd6cef0fc509bb14304410595914267c50467e51c87142acbb5eed54933efc6f1191ce67a1ad182a8fe412b3d9a203766353f843639e754fd1bbe5e5c0c4374a92bff9f7b7328d3baeb061b738dce75093a7a941cce96c5daf18284364f8ebabd43d3439169e92b27699e20be185ce3fb0fe44abc08fac1e25f4d256e87497f82f367abc2225cfe7d171f528160e681ae6a14df51ffdded1e96da93cc0bc30c7af4d608c6e026ca9b51f6ec61ad548117d0b98f010f847b2907e21ed09bf936cb602babaa8b37fcda1d159b6dd756c483ce982d1541e1a9bac03", - "02ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90002472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060003ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90015ea9fee96aed6d9c0fc2fbe0bd1883dee223b3200246ff1e21976bdbc9a0fc82ef0de1465a7dc27596e2e97087c70743c9a3686ed25882f342ab43c01d243053231904aa20a48130ce3da8a6c9c1cb96e3abf13c7fc2bc6467ff859ea85c78e0bba3cb4d94e2ed91b73b7734bc77f5a9e59e4f5dfa0358fabc24f72b3766f926e8cfbe7135e85b9463e796725b6d35f66d28929d1eda1e447260aa716b09f4acedc39c6e379af7740e5daf14fb9664872a8c3eecab1d3cd68f7d1d460344c32ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b900ea156011695129263f03d041f42e77c211ddc4cdffdb900e1de689414365ec672f24627e0a688cd54fb215fef833a804ad996f9f375f049e607bb739054b6d2cf43fcba949dd1cfa0f09b21873b445536717763e09e17383c8045e95917764c5bffccad34e90d7b469cdcc73bf2897af89b2f9171561143d12fd8996bf39d1bb20b4881975fef44f40ba71f14d827f3d2f26bc6182d5341189fefe308174a542ccb96b7a0ac351921d4efea5b01362c3d6bf8e815898e699ff4b2c6ac84d18d7", - "02d111519ba1f3013a7a613ecdcc17f4d53fbcb558b70404b5fb0c84ebb90a8d3c02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060003d111519ba1f3013a7a613ecdcc17f4d53fbcb558b70404b5fb0c84ebb90a8d3cb1e1ab71073241af34aabcee036dbb020b36121aebc19731ca3abeb3bbd19d9e1a7baec1441d10b7f1fbd182a4e53f9acc6f4de22485ceffe1254a77b10e9bf0a7d42cccac1043afccfd198b3cd1a0e498ece3a8f3b181f7ae3c3eb2c918e022f1502cf7a4cc817babde2cbd7f080c887ee2a4900355dcb716400a00620afc19776f6a43ba14206db88b85b80f5a3781bdfde64627b8c1ff7228b73626a648c66f3707fc6985b9b775144308ea347c7fc38099240ce9165bdbc9c5ffb5b71050d111519ba1f3013a7a613ecdcc17f4d53fbcb558b70404b5fb0c84ebb90a8d3c4e1e548ef8cdbe50cb554311fc9244fdf4c9ede5143e68ce35c5414b442e5e9128297089d43e94c182266476a1831e5eaa6668f1e00f9071df751e832475372f7c5e5ce7ecc7afd96d5feecfb8a0a28e602aea7040966c03a270aba823ea4277db9cd2bbb6f6017d04cecbcd41e758ebfd84d114b19279f867bd66ff5cd6615184dda648750e0152256f04cd7cc28d792daf3178267c6f443615b9a03d489ab3864c0d8af03257c52bd8199a308f51c114ee51d37f7033760a14253fdf76c29d", - "03831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060003831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc36efd8a52e2a27a50650b7e1f7db835c1f7fe5f7e587fb43e0009068b96d6ed306ae393ff8268523f6f4051a407c2e0164e14245b9499e714dd1691a5df832f1bcdd4c55bc2b958eea7b5f0de006bf6340d7ebc3de27fde6c0d639ce41f8af83f8a2f6b9f8d5dac2f971bf0f2ace4acc9ed2c70c617302755abd213421e7a1ccde12d18e5426de47339824faa5b40c307294d6835a92fa8e89ed6c1be85e9f9fd0ccd8f2fc4e0a1e5db88c74fd8a25b73076af74333671b84240b2d91d78303c831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafcc910275ad1d5d85af9af481e08247ca3e0801a081a7804bc1fff6f9646928d5c531a03ee21b178dd7fef9cb537d477705f48051f94363ceae0aec0a49b1e5460a47b2bf5fbacff69679a6ba3a839a36ef9e9ab7e4efdfad4dc6903e0af9df74c67a8d43ebc28d5acce6c2531d08b144fa2a06718eede8fd855aa7970c353d7ad833fa7f087bf2d00617549ef3da4f9986955f35e98b0c9db18021c853a2ddde4c52dfd720dd715403bdb22751217d54a58d0377f4ccc0723cab9a25b9587662e" + "021c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da0315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c900021c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da7650c845ad480abe1a31a7d40815b7003b2cab562d22645980fd62b5fcaca5f6ce5946d3a138e4aef068730a987a2eb57bbfe02a83933a9f1865eed6b92814c08dc180ae7c0f0075c7645cb8cecf472069aa6cc10b8a1edc2623d4152fa3743becb86773a5dca6c5951ec4e022c559762168ae04b8f4b05ca90c59a15a9a31371c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da7650c845ad480abe1a31a7d40815b7003b2cab562d22645980fd62b5fcaca5f6ce5946d3a138e4aef068730a987a2eb57bbfe02a83933a9f1865eed6b92814c08dc180ae7c0f0075c7645cb8cecf472069aa6cc10b8a1edc2623d4152fa3743becb86773a5dca6c5951ec4e022c559762168ae04b8f4b05ca90c59a15a9a3137", + "0302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a250315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c9000202f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec39a991401abf2e71cb8a0455c9b82542724eb2493f43558cd35a8a80eeeebf30b7531d698c1de7f199f8be4bdd265ef8f8950e2c8ba255718e2e847472d6411a5576c7dcd90c6ea61b06ee4be7d31d0f3732cce8eddad5d8235343f8c9377089802f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec39a991401abf2e71cb8a0455c9b82542724eb2493f43558cd35a8a80eeeebf30b7531d698c1de7f199f8be4bdd265ef8f8950e2c8ba255718e2e847472d6411a5576c7dcd90c6ea61b06ee4be7d31d0f3732cce8eddad5d8235343f8c93770898", + "0315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c9000215d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f105ce821aefb02ed9bbada8355d3179ca4a8a392260db9c5d34e44006395256317b9b4bb48a435b9aa5d36fddab8d7bd764e27e0dfeeec273d3a635d2d53707a563fe1ee05a9664c6e0b598e863c8d97f813535f1e5ab1c921608a46939b3595915d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f105ce821aefb02ed9bbada8355d3179ca4a8a392260db9c5d34e44006395256317b9b4bb48a435b9aa5d36fddab8d7bd764e27e0dfeeec273d3a635d2d53707a563fe1ee05a9664c6e0b598e863c8d97f813535f1e5ab1c921608a46939b35959" ] - [[federation]] -block-height = 100 +block-height = 20 threshold = 2 -aggregated-public-key = "030acd6af981c498ebf2ffd9a341d2a96bde5832c150e7d300fa3583eee0f964fe" +aggregated-public-key = "0376c3265e7d81839c1b2312b95697d47cc5b3ab3369a92a5af52ef1c945792f50" node-vss = [ - "02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b7250602472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b72506bb360eeb9d77cc606471ca455eb68331fbbdab6d009da456bef3920a61222f58df14e215a3883ff8c8def6bdce4d9d80282749b8056ec72373a246b3de5aa120b336d88a9b977a2f2ff5f26a1633f70f2d776363c495a02617bb7a88a2fea285a0a0e33e16dd90acb06b22fc70086f7eb12cdfeb7eb622d8a455de1f448fd30a472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b7250644c9f1146288339f9b8e35baa1497cce04425492ff625ba9410c6df49eddccd761c1af39b4fcbe4e3a240848bc90f41681ec105286684d4832efdc5b96a0e027286d9f7d22ad52194da7d522e5586ce268c7fde21220aca78e21d1d1a5d69f2468fff1b0f8a3a142cf0e1c7d29cbe3e509c437cd680ab21715cb5c1844d2eff8", - "02ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90002472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90015ea9fee96aed6d9c0fc2fbe0bd1883dee223b3200246ff1e21976bdbc9a0fc81f4be7002fae5b70835ee7e51893f76dd840ea64010504b8c66197d9cad767236a786cc7b91146df5e8d1ff73ad220b3578359eda61c341a8b5c41de6b068f73696b619f9213a550d0bc159ba1ff43c4e90c85930904a6f7f582b52074e3d965ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b900ea156011695129263f03d041f42e77c211ddc4cdffdb900e1de689414365ec672ad0d285c094287a3e2cc42d88e0736a1e238f33cde1ef9bd1cd9a0e8fe4a37dec94b7927535da68f388e4d5f07e838b71c742302476336b68f47b2e802b8c88a0fd87b9acc67ab564501a9777cf6081f50798b2ae8f2dff8a5190a27cfaf0e3", - "03831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc36efd8a52e2a27a50650b7e1f7db835c1f7fe5f7e587fb43e0009068b96d6ed35b71e1d42c2b7755bc33a7408032915da2a640b1b4227e13cd28efafc9e4af50fa777e082bd1afc64a4c2a67379df5a49233b6f003b96625f25f8dbe14fc7478fb75efb0cbcf147375065344b5c5f802bcd9057740983297749375b21d876d26831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafcc910275ad1d5d85af9af481e08247ca3e0801a081a7804bc1fff6f9646928d5c8f2a6c11c0fa9382aff7496614860f05779d3a0c5e6813db99d4b53417ac77c624171c6f14d272660f2556c9db9e3cca3e05a814a09fd5952dac72e18c7851c518063e5896e261aef163636449d673aba880160e57b5beee92362d74b5eb71dd" -] \ No newline at end of file + "0302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a250315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c9000202f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec33ecf34027b4922b3145e69a6006ca3414a7d6cb3ba888c4eadc546cd640f60b930f5d90d1bffafd82e57409e72d5170bd65317e5b87e17d61818546c95d5f35ede35276400c73ddfe17f6bd619bef8943a0ff34c87481fff9229ba9c37f2489b02f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec33ecf34027b4922b3145e69a6006ca3414a7d6cb3ba888c4eadc546cd640f60b930f5d90d1bffafd82e57409e72d5170bd65317e5b87e17d61818546c95d5f35ede35276400c73ddfe17f6bd619bef8943a0ff34c87481fff9229ba9c37f2489b", + "0315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c9000215d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f1f960f10435a23ea5c590bb1e2271e130fe67d582926c534aa1331d1b84ce127df4ae07160b3ef4bfdcb0035aea945ceb4b2323975fd90789d20637fdac29479dc783425afa4340fe9f1786b0d2fbd7aac64bd896942c015d70e47e59b88e2dc115d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f1f960f10435a23ea5c590bb1e2271e130fe67d582926c534aa1331d1b84ce127df4ae07160b3ef4bfdcb0035aea945ceb4b2323975fd90789d20637fdac29479dc783425afa4340fe9f1786b0d2fbd7aac64bd896942c015d70e47e59b88e2dc1", + "039af53a49a365576de41a2e70cc148353d7d1f4cad45f888fd8bc6d2c94a976570315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c900029af53a49a365576de41a2e70cc148353d7d1f4cad45f888fd8bc6d2c94a976579fc4ac8cde7d898910cb47345069cfc6c086e767b8e90276551762478dfe20fb0af6b91228e3e520a02c8e96904cc6ea13e7e5752d2c25fc260586561934b8024613acba6b7f33498353f3ff136bad71648278b5ef245f9f04cf10657728e028a9b19a1c578f25af03d49f9f8f96a8b6fd0a931a666e92531670bd34dbb362139af53a49a365576de41a2e70cc148353d7d1f4cad45f888fd8bc6d2c94a976579fc4ac8cde7d898910cb47345069cfc6c086e767b8e90276551762478dfe20fb0af6b91228e3e520a02c8e96904cc6ea13e7e5752d2c25fc260586561934b8024613acba6b7f33498353f3ff136bad71648278b5ef245f9f04cf10657728e028a9b19a1c578f25af03d49f9f8f96a8b6fd0a931a666e92531670bd34dbb36213" +] +signature = "90c90936d44e75bf25f8a6d1c21020a8dc7ee7f4d62a3d7ae278d9ff6a74901f687eee4236a64805414a43c344d12882061518be61014e76027cf6b8fd845aa0" diff --git a/tests/resources/federations_has_invalid_federation.toml b/tests/resources/federations_has_invalid_federation.toml index e34b852f8..79bd37ec4 100644 --- a/tests/resources/federations_has_invalid_federation.toml +++ b/tests/resources/federations_has_invalid_federation.toml @@ -1,21 +1,19 @@ [[federation]] block-height = 0 -threshold = 3 -aggregated-public-key = "030d856ac9f5871c3785a2d76e3a5d9eca6fcce70f4de63339671dfb9d1f33edb0" +threshold = 2 +aggregated-public-key = "02459adb8a8f052be94874aef7d4c3d3ddb71fcdaa869b1d515a92d63cb29c2806" node-vss = [ - "02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b7250602472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b72506bb360eeb9d77cc606471ca455eb68331fbbdab6d009da456bef3920a61222f58df14e215a3883ff8c8def6bdce4d9d80282749b8056ec72373a246b3de5aa120b336d88a9b977a2f2ff5f26a1633f70f2d776363c495a02617bb7a88a2fea285a0a0e33e16dd90acb06b22fc70086f7eb12cdfeb7eb622d8a455de1f448fd30a472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b7250644c9f1146288339f9b8e35baa1497cce04425492ff625ba9410c6df49eddccd761c1af39b4fcbe4e3a240848bc90f41681ec105286684d4832efdc5b96a0e027286d9f7d22ad52194da7d522e5586ce268c7fde21220aca78e21d1d1a5d69f2468fff1b0f8a3a142cf0e1c7d29cbe3e509c437cd680ab21715cb5c1844d2eff8", - "02785a891f323acd6cef0fc509bb14304410595914267c50467e51c87142acbb5e02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060003785a891f323acd6cef0fc509bb14304410595914267c50467e51c87142acbb5e12ab6cc10390ee6e31985e52e7d5701bed4c265dfc899cac07bc9c608ab02a74bf633344275792c413aac61fb108ba49aacb935cc637833a3d5f8bbc412a4578eec59fd45330922725e96c6c8e65980e3f571a9e99c7ea80abaabbfcc7a8541ca3bb9fb3393e593db51bf5bee44181cdf4cb1d617c0ce63682d8559f1424897b90c6c5c2684dda9a0f592fdc159c6dc744465f6de103c2ffe012c9a839034ae04a12fc2cc261586bf6b5814b1742449544aec456524b30fd530db6a76459162d785a891f323acd6cef0fc509bb14304410595914267c50467e51c87142acbb5eed54933efc6f1191ce67a1ad182a8fe412b3d9a203766353f843639e754fd1bbe5e5c0c4374a92bff9f7b7328d3baeb061b738dce75093a7a941cce96c5daf18284364f8ebabd43d3439169e92b27699e20be185ce3fb0fe44abc08fac1e25f4d256e87497f82f367abc2225cfe7d171f528160e681ae6a14df51ffdded1e96da93cc0bc30c7af4d608c6e026ca9b51f6ec61ad548117d0b98f010f847b2907e21ed09bf936cb602babaa8b37fcda1d159b6dd756c483ce982d1541e1a9bac03", - "02ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90002472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060003ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90015ea9fee96aed6d9c0fc2fbe0bd1883dee223b3200246ff1e21976bdbc9a0fc82ef0de1465a7dc27596e2e97087c70743c9a3686ed25882f342ab43c01d243053231904aa20a48130ce3da8a6c9c1cb96e3abf13c7fc2bc6467ff859ea85c78e0bba3cb4d94e2ed91b73b7734bc77f5a9e59e4f5dfa0358fabc24f72b3766f926e8cfbe7135e85b9463e796725b6d35f66d28929d1eda1e447260aa716b09f4acedc39c6e379af7740e5daf14fb9664872a8c3eecab1d3cd68f7d1d460344c32ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b900ea156011695129263f03d041f42e77c211ddc4cdffdb900e1de689414365ec672f24627e0a688cd54fb215fef833a804ad996f9f375f049e607bb739054b6d2cf43fcba949dd1cfa0f09b21873b445536717763e09e17383c8045e95917764c5bffccad34e90d7b469cdcc73bf2897af89b2f9171561143d12fd8996bf39d1bb20b4881975fef44f40ba71f14d827f3d2f26bc6182d5341189fefe308174a542ccb96b7a0ac351921d4efea5b01362c3d6bf8e815898e699ff4b2c6ac84d18d7", - "02d111519ba1f3013a7a613ecdcc17f4d53fbcb558b70404b5fb0c84ebb90a8d3c02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060003d111519ba1f3013a7a613ecdcc17f4d53fbcb558b70404b5fb0c84ebb90a8d3cb1e1ab71073241af34aabcee036dbb020b36121aebc19731ca3abeb3bbd19d9e1a7baec1441d10b7f1fbd182a4e53f9acc6f4de22485ceffe1254a77b10e9bf0a7d42cccac1043afccfd198b3cd1a0e498ece3a8f3b181f7ae3c3eb2c918e022f1502cf7a4cc817babde2cbd7f080c887ee2a4900355dcb716400a00620afc19776f6a43ba14206db88b85b80f5a3781bdfde64627b8c1ff7228b73626a648c66f3707fc6985b9b775144308ea347c7fc38099240ce9165bdbc9c5ffb5b71050d111519ba1f3013a7a613ecdcc17f4d53fbcb558b70404b5fb0c84ebb90a8d3c4e1e548ef8cdbe50cb554311fc9244fdf4c9ede5143e68ce35c5414b442e5e9128297089d43e94c182266476a1831e5eaa6668f1e00f9071df751e832475372f7c5e5ce7ecc7afd96d5feecfb8a0a28e602aea7040966c03a270aba823ea4277db9cd2bbb6f6017d04cecbcd41e758ebfd84d114b19279f867bd66ff5cd6615184dda648750e0152256f04cd7cc28d792daf3178267c6f443615b9a03d489ab3864c0d8af03257c52bd8199a308f51c114ee51d37f7033760a14253fdf76c29d", - "03831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060003831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc36efd8a52e2a27a50650b7e1f7db835c1f7fe5f7e587fb43e0009068b96d6ed306ae393ff8268523f6f4051a407c2e0164e14245b9499e714dd1691a5df832f1bcdd4c55bc2b958eea7b5f0de006bf6340d7ebc3de27fde6c0d639ce41f8af83f8a2f6b9f8d5dac2f971bf0f2ace4acc9ed2c70c617302755abd213421e7a1ccde12d18e5426de47339824faa5b40c307294d6835a92fa8e89ed6c1be85e9f9fd0ccd8f2fc4e0a1e5db88c74fd8a25b73076af74333671b84240b2d91d78303c831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafcc910275ad1d5d85af9af481e08247ca3e0801a081a7804bc1fff6f9646928d5c531a03ee21b178dd7fef9cb537d477705f48051f94363ceae0aec0a49b1e5460a47b2bf5fbacff69679a6ba3a839a36ef9e9ab7e4efdfad4dc6903e0af9df74c67a8d43ebc28d5acce6c2531d08b144fa2a06718eede8fd855aa7970c353d7ad833fa7f087bf2d00617549ef3da4f9986955f35e98b0c9db18021c853a2ddde4c52dfd720dd715403bdb22751217d54a58d0377f4ccc0723cab9a25b9587662e" + "021c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da0315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c900021c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da7650c845ad480abe1a31a7d40815b7003b2cab562d22645980fd62b5fcaca5f6ce5946d3a138e4aef068730a987a2eb57bbfe02a83933a9f1865eed6b92814c08dc180ae7c0f0075c7645cb8cecf472069aa6cc10b8a1edc2623d4152fa3743becb86773a5dca6c5951ec4e022c559762168ae04b8f4b05ca90c59a15a9a31371c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da7650c845ad480abe1a31a7d40815b7003b2cab562d22645980fd62b5fcaca5f6ce5946d3a138e4aef068730a987a2eb57bbfe02a83933a9f1865eed6b92814c08dc180ae7c0f0075c7645cb8cecf472069aa6cc10b8a1edc2623d4152fa3743becb86773a5dca6c5951ec4e022c559762168ae04b8f4b05ca90c59a15a9a3137", + "0302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a250315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c9000202f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec39a991401abf2e71cb8a0455c9b82542724eb2493f43558cd35a8a80eeeebf30b7531d698c1de7f199f8be4bdd265ef8f8950e2c8ba255718e2e847472d6411a5576c7dcd90c6ea61b06ee4be7d31d0f3732cce8eddad5d8235343f8c9377089802f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec39a991401abf2e71cb8a0455c9b82542724eb2493f43558cd35a8a80eeeebf30b7531d698c1de7f199f8be4bdd265ef8f8950e2c8ba255718e2e847472d6411a5576c7dcd90c6ea61b06ee4be7d31d0f3732cce8eddad5d8235343f8c93770898", + "0315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c9000215d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f105ce821aefb02ed9bbada8355d3179ca4a8a392260db9c5d34e44006395256317b9b4bb48a435b9aa5d36fddab8d7bd764e27e0dfeeec273d3a635d2d53707a563fe1ee05a9664c6e0b598e863c8d97f813535f1e5ab1c921608a46939b3595915d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f105ce821aefb02ed9bbada8355d3179ca4a8a392260db9c5d34e44006395256317b9b4bb48a435b9aa5d36fddab8d7bd764e27e0dfeeec273d3a635d2d53707a563fe1ee05a9664c6e0b598e863c8d97f813535f1e5ab1c921608a46939b35959" ] - [[federation]] -block-height = 100 -threshold = 2 -aggregated-public-key = "030acd6af981c498ebf2ffd9a341d2a96bde5832c150e7d300fa3583eee0f964fe" +block-height = 20 +threshold = 4 +aggregated-public-key = "0376c3265e7d81839c1b2312b95697d47cc5b3ab3369a92a5af52ef1c945792f50" node-vss = [ - "02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b7250602472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b72506bb360eeb9d77cc606471ca455eb68331fbbdab6d009da456bef3920a61222f58df14e215a3883ff8c8def6bdce4d9d80282749b8056ec72373a246b3de5aa120b336d88a9b977a2f2ff5f26a1633f70f2d776363c495a02617bb7a88a2fea285a0a0e33e16dd90acb06b22fc70086f7eb12cdfeb7eb622d8a455de1f448fd30a472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b7250644c9f1146288339f9b8e35baa1497cce04425492ff625ba9410c6df49eddccd761c1af39b4fcbe4e3a240848bc90f41681ec105286684d4832efdc5b96a0e027286d9f7d22ad52194da7d522e5586ce268c7fde21220aca78e21d1d1a5d69f2468fff1b0f8a3a142cf0e1c7d29cbe3e509c437cd680ab21715cb5c1844d2eff8", - "02ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90002472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b90015ea9fee96aed6d9c0fc2fbe0bd1883dee223b3200246ff1e21976bdbc9a0fc81f4be7002fae5b70835ee7e51893f76dd840ea64010504b8c66197d9cad767236a786cc7b91146df5e8d1ff73ad220b3578359eda61c341a8b5c41de6b068f73696b619f9213a550d0bc159ba1ff43c4e90c85930904a6f7f582b52074e3d965ce7edc292d7b747fab2f23584bbafaffde5c8ff17cf689969614441e0527b900ea156011695129263f03d041f42e77c211ddc4cdffdb900e1de689414365ec672ad0d285c094287a3e2cc42d88e0736a1e238f33cde1ef9bd1cd9a0e8fe4a37dec94b7927535da68f388e4d5f07e838b71c742302476336b68f47b2e802b8c88a0fd87b9acc67ab564501a9777cf6081f50798b2ae8f2dff8a5190a27cfaf0e3", - "03831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc02472012cf49fca573ca1f63deafe59df842f0bbe77e9ac7e67b211bb074b725060002831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc36efd8a52e2a27a50650b7e1f7db835c1f7fe5f7e587fb43e0009068b96d6ed35b71e1d42c2b7755bc33a7408032915da2a640b1b4227e13cd28efafc9e4af50fa777e082bd1afc64a4c2a67379df5a49233b6f003b96625f25f8dbe14fc7478fb75efb0cbcf147375065344b5c5f802bcd9057740983297749375b21d876d26831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafcc910275ad1d5d85af9af481e08247ca3e0801a081a7804bc1fff6f9646928d5c8f2a6c11c0fa9382aff7496614860f05779d3a0c5e6813db99d4b53417ac77c624171c6f14d272660f2556c9db9e3cca3e05a814a09fd5952dac72e18c7851c518063e5896e261aef163636449d673aba880160e57b5beee92362d74b5eb71dd" -] \ No newline at end of file + "0302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a250315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c9000202f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec33ecf34027b4922b3145e69a6006ca3414a7d6cb3ba888c4eadc546cd640f60b930f5d90d1bffafd82e57409e72d5170bd65317e5b87e17d61818546c95d5f35ede35276400c73ddfe17f6bd619bef8943a0ff34c87481fff9229ba9c37f2489b02f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec33ecf34027b4922b3145e69a6006ca3414a7d6cb3ba888c4eadc546cd640f60b930f5d90d1bffafd82e57409e72d5170bd65317e5b87e17d61818546c95d5f35ede35276400c73ddfe17f6bd619bef8943a0ff34c87481fff9229ba9c37f2489b", + "0315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c9000215d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f1f960f10435a23ea5c590bb1e2271e130fe67d582926c534aa1331d1b84ce127df4ae07160b3ef4bfdcb0035aea945ceb4b2323975fd90789d20637fdac29479dc783425afa4340fe9f1786b0d2fbd7aac64bd896942c015d70e47e59b88e2dc115d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f1f960f10435a23ea5c590bb1e2271e130fe67d582926c534aa1331d1b84ce127df4ae07160b3ef4bfdcb0035aea945ceb4b2323975fd90789d20637fdac29479dc783425afa4340fe9f1786b0d2fbd7aac64bd896942c015d70e47e59b88e2dc1", + "039af53a49a365576de41a2e70cc148353d7d1f4cad45f888fd8bc6d2c94a976570315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c900029af53a49a365576de41a2e70cc148353d7d1f4cad45f888fd8bc6d2c94a976579fc4ac8cde7d898910cb47345069cfc6c086e767b8e90276551762478dfe20fb0af6b91228e3e520a02c8e96904cc6ea13e7e5752d2c25fc260586561934b8024613acba6b7f33498353f3ff136bad71648278b5ef245f9f04cf10657728e028a9b19a1c578f25af03d49f9f8f96a8b6fd0a931a666e92531670bd34dbb362139af53a49a365576de41a2e70cc148353d7d1f4cad45f888fd8bc6d2c94a976579fc4ac8cde7d898910cb47345069cfc6c086e767b8e90276551762478dfe20fb0af6b91228e3e520a02c8e96904cc6ea13e7e5752d2c25fc260586561934b8024613acba6b7f33498353f3ff136bad71648278b5ef245f9f04cf10657728e028a9b19a1c578f25af03d49f9f8f96a8b6fd0a931a666e92531670bd34dbb36213" +] +signature = "90c90936d44e75bf25f8a6d1c21020a8dc7ee7f4d62a3d7ae278d9ff6a74901f687eee4236a64805414a43c344d12882061518be61014e76027cf6b8fd845aa0" diff --git a/tests/resources/federations_has_max_block_size.toml b/tests/resources/federations_has_max_block_size.toml new file mode 100644 index 000000000..a3a45814e --- /dev/null +++ b/tests/resources/federations_has_max_block_size.toml @@ -0,0 +1,27 @@ +[[federation]] +block-height = 0 +threshold = 2 +aggregated-public-key = "02459adb8a8f052be94874aef7d4c3d3ddb71fcdaa869b1d515a92d63cb29c2806" +node-vss = [ + "021c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da0302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a2500021c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da7650c845ad480abe1a31a7d40815b7003b2cab562d22645980fd62b5fcaca5f6ce5946d3a138e4aef068730a987a2eb57bbfe02a83933a9f1865eed6b92814c08dc180ae7c0f0075c7645cb8cecf472069aa6cc10b8a1edc2623d4152fa3743b69fc0903900dc5727544c4c9cf1f40d12e8eda6d29f111216de58c5482354c161c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da7650c845ad480abe1a31a7d40815b7003b2cab562d22645980fd62b5fcaca5f6ce5946d3a138e4aef068730a987a2eb57bbfe02a83933a9f1865eed6b92814c08dc180ae7c0f0075c7645cb8cecf472069aa6cc10b8a1edc2623d4152fa3743b69fc0903900dc5727544c4c9cf1f40d12e8eda6d29f111216de58c5482354c16", + "0302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a250302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25000202f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec39a991401abf2e71cb8a0455c9b82542724eb2493f43558cd35a8a80eeeebf30b7531d698c1de7f199f8be4bdd265ef8f8950e2c8ba255718e2e847472d6411a5a8f697000faa20097baa0848d4945b5543dd0530108d2b1552940aa7785e427a02f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec39a991401abf2e71cb8a0455c9b82542724eb2493f43558cd35a8a80eeeebf30b7531d698c1de7f199f8be4bdd265ef8f8950e2c8ba255718e2e847472d6411a5a8f697000faa20097baa0848d4945b5543dd0530108d2b1552940aa7785e427a", + "0315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25000215d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f105ce821aefb02ed9bbada8355d3179ca4a8a392260db9c5d34e44006395256317b9b4bb48a435b9aa5d36fddab8d7bd764e27e0dfeeec273d3a635d2d53707a5600917878572511804651724a877d126452c33b7ea12df1318b1934c72d816b515d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f105ce821aefb02ed9bbada8355d3179ca4a8a392260db9c5d34e44006395256317b9b4bb48a435b9aa5d36fddab8d7bd764e27e0dfeeec273d3a635d2d53707a5600917878572511804651724a877d126452c33b7ea12df1318b1934c72d816b5" +] +[[federation]] +block-height = 20 +threshold = 2 +aggregated-public-key = "0376c3265e7d81839c1b2312b95697d47cc5b3ab3369a92a5af52ef1c945792f50" +node-vss = [ + "0302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a250302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25000202f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec33ecf34027b4922b3145e69a6006ca3414a7d6cb3ba888c4eadc546cd640f60b930f5d90d1bffafd82e57409e72d5170bd65317e5b87e17d61818546c95d5f35e951ff864871be49c79cfdd99ce8c3457324f446c272622ffafd57e7654f45ecc02f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec33ecf34027b4922b3145e69a6006ca3414a7d6cb3ba888c4eadc546cd640f60b930f5d90d1bffafd82e57409e72d5170bd65317e5b87e17d61818546c95d5f35e951ff864871be49c79cfdd99ce8c3457324f446c272622ffafd57e7654f45ecc", + "0315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25000215d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f1f960f10435a23ea5c590bb1e2271e130fe67d582926c534aa1331d1b84ce127df4ae07160b3ef4bfdcb0035aea945ceb4b2323975fd90789d20637fdac29479d8fd125986ab6b55c756dcd270268cc0f49b303ed438732b94773f7b64ed7df9715d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f1f960f10435a23ea5c590bb1e2271e130fe67d582926c534aa1331d1b84ce127df4ae07160b3ef4bfdcb0035aea945ceb4b2323975fd90789d20637fdac29479d8fd125986ab6b55c756dcd270268cc0f49b303ed438732b94773f7b64ed7df97", + "039af53a49a365576de41a2e70cc148353d7d1f4cad45f888fd8bc6d2c94a976570302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a2500029af53a49a365576de41a2e70cc148353d7d1f4cad45f888fd8bc6d2c94a976579fc4ac8cde7d898910cb47345069cfc6c086e767b8e90276551762478dfe20fb0af6b91228e3e520a02c8e96904cc6ea13e7e5752d2c25fc260586561934b8024613acba6b7f33498353f3ff136bad71648278b5ef245f9f04cf10657728e0283dd5f93cd4f175390d7396499e506a5afb47121eb0316e018426f74348b9a8ac9af53a49a365576de41a2e70cc148353d7d1f4cad45f888fd8bc6d2c94a976579fc4ac8cde7d898910cb47345069cfc6c086e767b8e90276551762478dfe20fb0af6b91228e3e520a02c8e96904cc6ea13e7e5752d2c25fc260586561934b8024613acba6b7f33498353f3ff136bad71648278b5ef245f9f04cf10657728e0283dd5f93cd4f175390d7396499e506a5afb47121eb0316e018426f74348b9a8ac" +] +signature = "90c90936d44e75bf25f8a6d1c21020a8dc7ee7f4d62a3d7ae278d9ff6a74901f687eee4236a64805414a43c344d12882061518be61014e76027cf6b8fd845aa0" +[[federation]] +block-height = 10 +max-block-size = 200000 +signature = "90c90936d44e75bf25f8a6d1c21020a8dc7ee7f4d62a3d7ae278d9ff6a74901fb78f3393ed06260646df7121947d4ff826eacb7966c1e60f2237724b104e998a" +[[federation]] +block-height = 30 +max-block-size = 400000 +signature = "82cf50e3c68f972790780dceddfb573e3f36953bbab5497ac8acdcf02a6d496dcff5a14692d9f2f8e7d3d55d93de4fb471a1ed9ec726389c8ca5378ada5e5adc" diff --git a/tests/resources/federations_threshold_change.toml b/tests/resources/federations_threshold_change.toml new file mode 100644 index 000000000..ac3b1fe4e --- /dev/null +++ b/tests/resources/federations_threshold_change.toml @@ -0,0 +1,19 @@ +[[federation]] +block-height = 0 +threshold = 3 +aggregated-public-key = "02459adb8a8f052be94874aef7d4c3d3ddb71fcdaa869b1d515a92d63cb29c2806" +node-vss = [ + "021c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da0315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c900031c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da7650c845ad480abe1a31a7d40815b7003b2cab562d22645980fd62b5fcaca5f66689e699d0072832389b602f3e16fda6b534252253f011bddb8adf4e836d38c46454e63601ddc2459d9ae41d48cf2774589ae3fc5e1e6bb3e770e0029384582061357ad5d9bad55e7196d1c19fb567e6d808a8ab7c7e8cb842145c7860d92b31ce94a1cffdb033189553f6c10c6a65f4615787ac0558bfa0627a73ba14e44a8224624dbc30768f7cf67bd9913be0dca3e25063a70046ee3677fd7dea022bb0521c36ce51f73f01395af9f7955db0c99f8e34009ea1565679b851f19cba37a5da7650c845ad480abe1a31a7d40815b7003b2cab562d22645980fd62b5fcaca5f66689e699d0072832389b602f3e16fda6b534252253f011bddb8adf4e836d38c46454e63601ddc2459d9ae41d48cf2774589ae3fc5e1e6bb3e770e0029384582061357ad5d9bad55e7196d1c19fb567e6d808a8ab7c7e8cb842145c7860d92b31ce94a1cffdb033189553f6c10c6a65f4615787ac0558bfa0627a73ba14e44a8224624dbc30768f7cf67bd9913be0dca3e25063a70046ee3677fd7dea022bb052", + "0302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a250315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c9000302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec3bcd3f6244633e0ac0c12e1ffd0d8c6adb4f7ea57c38dcb677095bcf1e0fe1f3134c9f34e15534b43427f66873b5af00f641265ec611bf9c5b96728b8eb2ced5abd13057b552db1505b1515dca3925465f9242326598a4a8ccae72b266aa538ff0abc10f562e61b174fc6ca8cdef762da399e1cd3ba61bd0ed564f5a59320dc6cf6f7311dcd58736da1243c397e944ec2bdf71b56939466f752f58b3e8cc7ae9502f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec3bcd3f6244633e0ac0c12e1ffd0d8c6adb4f7ea57c38dcb677095bcf1e0fe1f3134c9f34e15534b43427f66873b5af00f641265ec611bf9c5b96728b8eb2ced5abd13057b552db1505b1515dca3925465f9242326598a4a8ccae72b266aa538ff0abc10f562e61b174fc6ca8cdef762da399e1cd3ba61bd0ed564f5a59320dc6cf6f7311dcd58736da1243c397e944ec2bdf71b56939466f752f58b3e8cc7ae95", + "0315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c9000315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f16df4da1e73f0fd19614149ef5e0043aefe6787a3af424c37266872f4373ac51a2d0c99b60ec203b6a66d5c236c8f9907f92de7a41c3cbb8aa0ec9917af63379c51cd4190b8e21782a7d54faa481b4be674d8cb7a35e95e81a73cbbec22e887248204e26b5d2426ba87718d6d26f2dfac941c94395dace2b2548876a53786aeb072fa82a6b364350361a4b19cc45ec65d40856cbd134c2dbe2e780ef080d306d815d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f16df4da1e73f0fd19614149ef5e0043aefe6787a3af424c37266872f4373ac51a2d0c99b60ec203b6a66d5c236c8f9907f92de7a41c3cbb8aa0ec9917af63379c51cd4190b8e21782a7d54faa481b4be674d8cb7a35e95e81a73cbbec22e887248204e26b5d2426ba87718d6d26f2dfac941c94395dace2b2548876a53786aeb072fa82a6b364350361a4b19cc45ec65d40856cbd134c2dbe2e780ef080d306d8" +] +[[federation]] +block-height = 40 +threshold = 2 +aggregated-public-key = "0376c3265e7d81839c1b2312b95697d47cc5b3ab3369a92a5af52ef1c945792f50" +node-vss = [ + "0302f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a250315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c9000202f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec33ecf34027b4922b3145e69a6006ca3414a7d6cb3ba888c4eadc546cd640f60b930f5d90d1bffafd82e57409e72d5170bd65317e5b87e17d61818546c95d5f35ede35276400c73ddfe17f6bd619bef8943a0ff34c87481fff9229ba9c37f2489b02f5584e30d2ee32e772d04ff8ee1efc90a7a91ac5b7c4025da7a42a67d06a25ca08028df6f430f739d1c387a7b837ccad852e61a90c961c0a44f942ad127ec33ecf34027b4922b3145e69a6006ca3414a7d6cb3ba888c4eadc546cd640f60b930f5d90d1bffafd82e57409e72d5170bd65317e5b87e17d61818546c95d5f35ede35276400c73ddfe17f6bd619bef8943a0ff34c87481fff9229ba9c37f2489b", + "0315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c9000215d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f1f960f10435a23ea5c590bb1e2271e130fe67d582926c534aa1331d1b84ce127df4ae07160b3ef4bfdcb0035aea945ceb4b2323975fd90789d20637fdac29479dc783425afa4340fe9f1786b0d2fbd7aac64bd896942c015d70e47e59b88e2dc115d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c90081da2716d12495f6e83bbfde76a914fc6cfe72d1b229130295a83d7b8352f1f960f10435a23ea5c590bb1e2271e130fe67d582926c534aa1331d1b84ce127df4ae07160b3ef4bfdcb0035aea945ceb4b2323975fd90789d20637fdac29479dc783425afa4340fe9f1786b0d2fbd7aac64bd896942c015d70e47e59b88e2dc1", + "039af53a49a365576de41a2e70cc148353d7d1f4cad45f888fd8bc6d2c94a976570315d137054b688717f7fe4bd22a1c886de7a07bf3beb041092fb79688306df3c900029af53a49a365576de41a2e70cc148353d7d1f4cad45f888fd8bc6d2c94a976579fc4ac8cde7d898910cb47345069cfc6c086e767b8e90276551762478dfe20fb0af6b91228e3e520a02c8e96904cc6ea13e7e5752d2c25fc260586561934b8024613acba6b7f33498353f3ff136bad71648278b5ef245f9f04cf10657728e028a9b19a1c578f25af03d49f9f8f96a8b6fd0a931a666e92531670bd34dbb362139af53a49a365576de41a2e70cc148353d7d1f4cad45f888fd8bc6d2c94a976579fc4ac8cde7d898910cb47345069cfc6c086e767b8e90276551762478dfe20fb0af6b91228e3e520a02c8e96904cc6ea13e7e5752d2c25fc260586561934b8024613acba6b7f33498353f3ff136bad71648278b5ef245f9f04cf10657728e028a9b19a1c578f25af03d49f9f8f96a8b6fd0a931a666e92531670bd34dbb36213" +] +signature = "f57c17352f242b96dff740252946570b813f034ad5f78f1061a20e22cc5b02a9b28c82c43d6b05bb927312d8d5bcd6aa8db79785f41e1249da9dcdf42025f8c8" \ No newline at end of file