From 210c265bf52b56a921d6d8603316fced3c3fffaa Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 30 Oct 2024 09:20:54 +0100 Subject: [PATCH 1/8] logging: do_validator_engine_actions: skipping because we are syncing. --- crates/ethcore/src/engines/hbbft/hbbft_engine.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/ethcore/src/engines/hbbft/hbbft_engine.rs b/crates/ethcore/src/engines/hbbft/hbbft_engine.rs index 64ee9d24e..a235d92ba 100644 --- a/crates/ethcore/src/engines/hbbft/hbbft_engine.rs +++ b/crates/ethcore/src/engines/hbbft/hbbft_engine.rs @@ -1009,6 +1009,7 @@ impl HoneyBadgerBFT { Some(client_arc) => { if self.is_syncing(&client_arc) { // we are syncing - do not do anything. + trace!(target: "engine", "do_validator_engine_actions: skipping because we are syncing."); return Ok(()); } From 293f6aa7e1f03426d4fc6013609c1a747075f496 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 30 Oct 2024 11:22:18 +0100 Subject: [PATCH 2/8] logging public keys of pending validators --- .../ethcore/src/engines/hbbft/keygen_transactions.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/crates/ethcore/src/engines/hbbft/keygen_transactions.rs b/crates/ethcore/src/engines/hbbft/keygen_transactions.rs index e0d6ee567..067e21584 100644 --- a/crates/ethcore/src/engines/hbbft/keygen_transactions.rs +++ b/crates/ethcore/src/engines/hbbft/keygen_transactions.rs @@ -128,11 +128,19 @@ impl KeygenTransactionSender { .map(|p| (*p, PublicWrapper { inner: p.clone() })) .collect(); + let pub_leys_arc = Arc::new(pub_keys); + + //let pub_key_len = pub_keys.len(); // if synckeygen creation fails then either signer or validator pub keys are problematic. // Todo: We should expect up to f clients to write invalid pub keys. Report and re-start pending validator set selection. - let (mut synckeygen, part) = engine_signer_to_synckeygen(signer, Arc::new(pub_keys)) + let (mut synckeygen, part) = engine_signer_to_synckeygen(signer, pub_leys_arc.clone()) .map_err(|e| { - warn!(target:"engine", "engine_signer_to_synckeygen error {:?}", e); + warn!(target:"engine", "engine_signer_to_synckeygen pub keys count {:?} error {:?}", pub_leys_arc.len(), e); + + pub_leys_arc.iter().for_each(|(k, v)| { + warn!(target:"engine", "pub key {}", k); + }); + CallError::ReturnValueInvalid })?; From 6cdddabb7e758cbab01a364434ed2ca3ba5a4a57 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 30 Oct 2024 11:23:25 +0100 Subject: [PATCH 3/8] cargo fmt --all -- --config imports_granularity=Crate --- crates/ethcore/src/engines/hbbft/keygen_transactions.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/ethcore/src/engines/hbbft/keygen_transactions.rs b/crates/ethcore/src/engines/hbbft/keygen_transactions.rs index 067e21584..b7dd738d5 100644 --- a/crates/ethcore/src/engines/hbbft/keygen_transactions.rs +++ b/crates/ethcore/src/engines/hbbft/keygen_transactions.rs @@ -136,11 +136,9 @@ impl KeygenTransactionSender { let (mut synckeygen, part) = engine_signer_to_synckeygen(signer, pub_leys_arc.clone()) .map_err(|e| { warn!(target:"engine", "engine_signer_to_synckeygen pub keys count {:?} error {:?}", pub_leys_arc.len(), e); - pub_leys_arc.iter().for_each(|(k, v)| { warn!(target:"engine", "pub key {}", k); }); - CallError::ReturnValueInvalid })?; From 67cd17649a66a93c41fb42a1e6d8ea21fc904dcb Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 30 Oct 2024 12:20:48 +0100 Subject: [PATCH 4/8] PublicKey: check if public key is valid for the use of BLS 381 12 --- .../ethcore/src/engines/hbbft/contracts/keygen_history.rs | 7 +++++++ crates/ethcore/src/engines/hbbft/keygen_transactions.rs | 6 +++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/ethcore/src/engines/hbbft/contracts/keygen_history.rs b/crates/ethcore/src/engines/hbbft/contracts/keygen_history.rs index e008790c2..4ebcd1a87 100644 --- a/crates/ethcore/src/engines/hbbft/contracts/keygen_history.rs +++ b/crates/ethcore/src/engines/hbbft/contracts/keygen_history.rs @@ -179,6 +179,13 @@ pub struct KeyPairWrapper { pub inner: Arc>>>, } +impl PublicWrapper { + /// Check if the public key is valid. + pub fn is_valid(&self) -> bool { + self.encrypt(b"a", &mut rand::thread_rng()).is_ok() + } +} + impl<'a> PublicKey for PublicWrapper { type Error = crypto::publickey::Error; type SecretKey = KeyPairWrapper; diff --git a/crates/ethcore/src/engines/hbbft/keygen_transactions.rs b/crates/ethcore/src/engines/hbbft/keygen_transactions.rs index b7dd738d5..5c1cd90ba 100644 --- a/crates/ethcore/src/engines/hbbft/keygen_transactions.rs +++ b/crates/ethcore/src/engines/hbbft/keygen_transactions.rs @@ -137,7 +137,11 @@ impl KeygenTransactionSender { .map_err(|e| { warn!(target:"engine", "engine_signer_to_synckeygen pub keys count {:?} error {:?}", pub_leys_arc.len(), e); pub_leys_arc.iter().for_each(|(k, v)| { - warn!(target:"engine", "pub key {}", k); + warn!(target:"engine", "pub key {}", k.as_bytes().iter().join("")); + + if !v.is_valid() { + warn!(target:"engine", "INVALID pub key {}", k); + } }); CallError::ReturnValueInvalid })?; From b93d9e61de7580f2c66ad4f0d085fb04176d286e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 30 Oct 2024 22:25:37 +0100 Subject: [PATCH 5/8] i132 on detecting invalid public keys, write parts to progress into the next key gen phase for this node https://github.com/DMDcoin/diamond-node/issues/132 --- .../src/engines/hbbft/keygen_transactions.rs | 102 ++++++++++++++---- 1 file changed, 80 insertions(+), 22 deletions(-) diff --git a/crates/ethcore/src/engines/hbbft/keygen_transactions.rs b/crates/ethcore/src/engines/hbbft/keygen_transactions.rs index 5c1cd90ba..5bdaf668b 100644 --- a/crates/ethcore/src/engines/hbbft/keygen_transactions.rs +++ b/crates/ethcore/src/engines/hbbft/keygen_transactions.rs @@ -16,7 +16,7 @@ use engines::{ }, signer::EngineSigner, }; -use ethereum_types::{Address, U256}; +use ethereum_types::{Address, Public, U256}; use itertools::Itertools; use parking_lot::RwLock; use std::{collections::BTreeMap, sync::Arc}; @@ -36,6 +36,23 @@ enum ShouldSendKeyAnswer { Yes, } +#[derive(Debug)] +pub enum KeyGenError { + NoSigner, + NoFullClient, + NoPartToWrite, + InvalidPublicKey(Vec), + CallError(CallError), + Unexpected +} + + +impl From for KeyGenError { + fn from(e: CallError) -> Self { + KeyGenError::CallError(e) + } +} + static KEYGEN_TRANSACTION_SEND_DELAY: u64 = 3; static KEYGEN_TRANSACTION_RESEND_DELAY: u64 = 10; @@ -102,17 +119,17 @@ impl KeygenTransactionSender { &mut self, client: &dyn EngineClient, signer: &Arc>>>, - ) -> Result<(), CallError> { + ) -> Result<(), KeyGenError> { // If we have no signer there is nothing for us to send. let address = match signer.read().as_ref() { Some(signer) => signer.address(), None => { warn!(target: "engine", "Could not send keygen transactions, because signer module could not be retrieved"); - return Err(CallError::ReturnValueInvalid); + return Err(KeyGenError::NoSigner); } }; - let full_client = client.as_full_client().ok_or(CallError::NotFullClient)?; + let full_client = client.as_full_client().ok_or(KeyGenError::NoFullClient)?; // If the chain is still syncing, do not send Parts or Acks. if full_client.is_major_syncing() { @@ -122,40 +139,81 @@ impl KeygenTransactionSender { trace!(target:"engine", " get_validator_pubkeys..."); - let vmap = get_validator_pubkeys(&*client, BlockId::Latest, ValidatorType::Pending)?; + let vmap = get_validator_pubkeys(&*client, BlockId::Latest, ValidatorType::Pending).map_err(|e| KeyGenError::CallError(e))?; let pub_keys: BTreeMap<_, _> = vmap .values() .map(|p| (*p, PublicWrapper { inner: p.clone() })) .collect(); - let pub_leys_arc = Arc::new(pub_keys); + let pub_keys_arc = Arc::new(pub_keys); + let upcoming_epoch = get_posdao_epoch(client, BlockId::Latest).map_err(|e| KeyGenError::CallError(e))? + 1; //let pub_key_len = pub_keys.len(); // if synckeygen creation fails then either signer or validator pub keys are problematic. // Todo: We should expect up to f clients to write invalid pub keys. Report and re-start pending validator set selection. - let (mut synckeygen, part) = engine_signer_to_synckeygen(signer, pub_leys_arc.clone()) - .map_err(|e| { - warn!(target:"engine", "engine_signer_to_synckeygen pub keys count {:?} error {:?}", pub_leys_arc.len(), e); - pub_leys_arc.iter().for_each(|(k, v)| { - warn!(target:"engine", "pub key {}", k.as_bytes().iter().join("")); - - if !v.is_valid() { - warn!(target:"engine", "INVALID pub key {}", k); + let (mut synckeygen, part) = + match engine_signer_to_synckeygen(signer, pub_keys_arc.clone()) { + Ok((mut synckeygen_, part_)) => (synckeygen_, part_), + Err(e) => { + warn!(target:"engine", "engine_signer_to_synckeygen pub keys count {:?} error {:?}", pub_keys_arc.len(), e); + //let mut failure_pub_keys: Vec = Vec::new(); + let mut failure_pub_keys: Vec = Vec::new(); + pub_keys_arc.iter().for_each(|(k, v)| { + warn!(target:"engine", "pub key {}", k.as_bytes().iter().join("")); + + if !v.is_valid() { + warn!(target:"engine", "INVALID pub key {}", k); + + // append the bytes of the public key to the failure_pub_keys. + k.as_bytes().iter().for_each(|b| { + failure_pub_keys.push(*b); + }); + } + }); + + // if we should send our parts, we will send the public keys of the troublemakers instead. + + match self.should_send_part(client, &address).map_err(|e| KeyGenError::CallError(e))? { + ShouldSendKeyAnswer::NoNotThisKeyGenMode => return Err(KeyGenError::Unexpected), + ShouldSendKeyAnswer::NoWaiting => return Err(KeyGenError::Unexpected), + ShouldSendKeyAnswer::Yes => { + + // the required gas values have been approximated by + // experimenting and it's a very rough estimation. + // it can be further fine tuned to be just above the real consumption. + // ACKs require much more gas, + // and usually run into the gas limit problems. + let gas: usize = failure_pub_keys.len() * 800 + 100_000; + + let part_transaction = + TransactionRequest::call(*KEYGEN_HISTORY_ADDRESS, failure_pub_keys) + .gas(U256::from(gas)) + .nonce(full_client.nonce(&address, BlockId::Latest).unwrap()) + .gas_price(U256::from(10000000000u64)); + full_client + .transact_silently(part_transaction) + .map_err(|e| { + warn!(target:"engine", "could not transact_silently: {:?}", e); + CallError::ReturnValueInvalid + })?; + + trace!(target:"engine", "PART Transaction send."); + return Ok(()); + }, } - }); - CallError::ReturnValueInvalid - })?; + }, + }; // If there is no part then we are not part of the pending validator set and there is nothing for us to do. let part_data = match part { Some(part) => part, None => { warn!(target:"engine", "no part to write."); - return Err(CallError::ReturnValueInvalid); + return Err(KeyGenError::NoPartToWrite); } }; - let upcoming_epoch = get_posdao_epoch(client, BlockId::Latest)? + 1; + trace!(target:"engine", "preparing to send PARTS for upcoming epoch: {}", upcoming_epoch); // Check if we already sent our part. @@ -165,7 +223,7 @@ impl KeygenTransactionSender { Ok(part) => part, Err(e) => { warn!(target:"engine", "could not serialize part: {:?}", e); - return Err(CallError::ReturnValueInvalid); + return Err(KeyGenError::Unexpected); } }; let serialized_part_len = serialized_part.len(); @@ -223,7 +281,7 @@ impl KeygenTransactionSender { } Err(err) => { error!(target:"engine", "could not retrieve part for {} call failed. Error: {:?}", *v, err); - return Err(err); + return Err(KeyGenError::CallError(err)); } } ); @@ -240,7 +298,7 @@ impl KeygenTransactionSender { for ack in acks { let ack_to_push = match bincode::serialize(&ack) { Ok(serialized_ack) => serialized_ack, - Err(_) => return Err(CallError::ReturnValueInvalid), + Err(e) => return Err(KeyGenError::Unexpected), }; total_bytes_for_acks += ack_to_push.len(); serialized_acks.push(ack_to_push); From 3e6e9c611a2d32ff99674da0f54047c148417b9a Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 30 Oct 2024 23:28:57 +0100 Subject: [PATCH 6/8] compressing part as bincode , logging Nonce for Part Transaction that holds the public key. --- .../src/engines/hbbft/keygen_transactions.rs | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/crates/ethcore/src/engines/hbbft/keygen_transactions.rs b/crates/ethcore/src/engines/hbbft/keygen_transactions.rs index 5bdaf668b..a9cb45c72 100644 --- a/crates/ethcore/src/engines/hbbft/keygen_transactions.rs +++ b/crates/ethcore/src/engines/hbbft/keygen_transactions.rs @@ -41,9 +41,9 @@ pub enum KeyGenError { NoSigner, NoFullClient, NoPartToWrite, - InvalidPublicKey(Vec), CallError(CallError), - Unexpected + Unexpected, + } @@ -185,10 +185,20 @@ impl KeygenTransactionSender { // and usually run into the gas limit problems. let gas: usize = failure_pub_keys.len() * 800 + 100_000; + let serialized_part = match bincode::serialize(&failure_pub_keys) { + Ok(part) => part, + Err(e) => { + warn!(target:"engine", "could not serialize part: {:?}", e); + return Err(KeyGenError::Unexpected); + } + }; + + let nonce = full_client.nonce(&address, BlockId::Latest).unwrap(); + let part_transaction = - TransactionRequest::call(*KEYGEN_HISTORY_ADDRESS, failure_pub_keys) + TransactionRequest::call(*KEYGEN_HISTORY_ADDRESS, serialized_part) .gas(U256::from(gas)) - .nonce(full_client.nonce(&address, BlockId::Latest).unwrap()) + .nonce(nonce) .gas_price(U256::from(10000000000u64)); full_client .transact_silently(part_transaction) @@ -197,7 +207,7 @@ impl KeygenTransactionSender { CallError::ReturnValueInvalid })?; - trace!(target:"engine", "PART Transaction send."); + trace!(target:"engine", "PART Transaction send for moving forward key gen phase with nonce: {}", nonce); return Ok(()); }, } From 65d32e8b8ddbe05ef960475e34ea2339cd952cc6 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 31 Oct 2024 00:12:19 +0100 Subject: [PATCH 7/8] refactored part transactions to a function. --- .../src/engines/hbbft/keygen_transactions.rs | 90 +++++++++---------- 1 file changed, 41 insertions(+), 49 deletions(-) diff --git a/crates/ethcore/src/engines/hbbft/keygen_transactions.rs b/crates/ethcore/src/engines/hbbft/keygen_transactions.rs index a9cb45c72..c1669d599 100644 --- a/crates/ethcore/src/engines/hbbft/keygen_transactions.rs +++ b/crates/ethcore/src/engines/hbbft/keygen_transactions.rs @@ -22,6 +22,8 @@ use parking_lot::RwLock; use std::{collections::BTreeMap, sync::Arc}; use types::ids::BlockId; +use crate::client::BlockChainClient; + pub struct KeygenTransactionSender { last_keygen_mode: KeyGenMode, keygen_mode_counter: u64, @@ -177,13 +179,6 @@ impl KeygenTransactionSender { ShouldSendKeyAnswer::NoNotThisKeyGenMode => return Err(KeyGenError::Unexpected), ShouldSendKeyAnswer::NoWaiting => return Err(KeyGenError::Unexpected), ShouldSendKeyAnswer::Yes => { - - // the required gas values have been approximated by - // experimenting and it's a very rough estimation. - // it can be further fine tuned to be just above the real consumption. - // ACKs require much more gas, - // and usually run into the gas limit problems. - let gas: usize = failure_pub_keys.len() * 800 + 100_000; let serialized_part = match bincode::serialize(&failure_pub_keys) { Ok(part) => part, @@ -192,22 +187,9 @@ impl KeygenTransactionSender { return Err(KeyGenError::Unexpected); } }; - - let nonce = full_client.nonce(&address, BlockId::Latest).unwrap(); - - let part_transaction = - TransactionRequest::call(*KEYGEN_HISTORY_ADDRESS, serialized_part) - .gas(U256::from(gas)) - .nonce(nonce) - .gas_price(U256::from(10000000000u64)); - full_client - .transact_silently(part_transaction) - .map_err(|e| { - warn!(target:"engine", "could not transact_silently: {:?}", e); - CallError::ReturnValueInvalid - })?; - - trace!(target:"engine", "PART Transaction send for moving forward key gen phase with nonce: {}", nonce); + + send_part_transaction(full_client, client, &address, upcoming_epoch, serialized_part)?; + trace!(target:"engine", "PART Transaction send for moving forward key gen phase"); return Ok(()); }, } @@ -229,6 +211,7 @@ impl KeygenTransactionSender { // Check if we already sent our part. match self.should_send_part(client, &address)? { ShouldSendKeyAnswer::Yes => { + let serialized_part = match bincode::serialize(&part_data) { Ok(part) => part, Err(e) => { @@ -236,33 +219,8 @@ impl KeygenTransactionSender { return Err(KeyGenError::Unexpected); } }; - let serialized_part_len = serialized_part.len(); - let current_round = get_current_key_gen_round(client)?; - let write_part_data = key_history_contract::functions::write_part::call( - upcoming_epoch, - current_round, - serialized_part, - ); - - // the required gas values have been approximated by - // experimenting and it's a very rough estimation. - // it can be further fine tuned to be just above the real consumption. - // ACKs require much more gas, - // and usually run into the gas limit problems. - let gas: usize = serialized_part_len * 800 + 100_000; - - let part_transaction = - TransactionRequest::call(*KEYGEN_HISTORY_ADDRESS, write_part_data.0) - .gas(U256::from(gas)) - .nonce(full_client.nonce(&address, BlockId::Latest).unwrap()) - .gas_price(U256::from(10000000000u64)); - full_client - .transact_silently(part_transaction) - .map_err(|e| { - warn!(target:"engine", "could not transact_silently: {:?}", e); - CallError::ReturnValueInvalid - })?; + send_part_transaction(full_client, client, &address, upcoming_epoch, serialized_part)?; trace!(target:"engine", "PART Transaction send."); return Ok(()); } @@ -341,3 +299,37 @@ impl KeygenTransactionSender { Ok(()) } } + + +fn send_part_transaction(full_client: &dyn BlockChainClient, client: &dyn EngineClient, mining_address: &Address, upcoming_epoch: U256 , data: Vec) -> Result<(), KeyGenError> { + + // the required gas values have been approximated by + // experimenting and it's a very rough estimation. + // it can be further fine tuned to be just above the real consumption. + // ACKs require much more gas, + // and usually run into the gas limit problems. + let gas: usize = data.len() * 800 + 100_000; + + let nonce = full_client.nonce(&mining_address, BlockId::Latest).unwrap(); + let current_round = get_current_key_gen_round(client)?; + let write_part_data = key_history_contract::functions::write_part::call( + upcoming_epoch, + current_round, + data, + ); + + let part_transaction = + TransactionRequest::call(*KEYGEN_HISTORY_ADDRESS, write_part_data.0) + .gas(U256::from(gas)) + .nonce(nonce) + .gas_price(U256::from(10000000000u64)); + full_client + .transact_silently(part_transaction) + .map_err(|e| { + warn!(target:"engine", "could not transact_silently: {:?}", e); + CallError::ReturnValueInvalid + })?; + + return Ok(()); + +} From e74af66a52b862599ead45194d6aad1141f3815e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 31 Oct 2024 00:46:11 +0100 Subject: [PATCH 8/8] cargo fmt --all -- --config imports_granularity=Crate --- .../src/engines/hbbft/keygen_transactions.rs | 139 ++++++++++-------- 1 file changed, 76 insertions(+), 63 deletions(-) diff --git a/crates/ethcore/src/engines/hbbft/keygen_transactions.rs b/crates/ethcore/src/engines/hbbft/keygen_transactions.rs index c1669d599..440b7c479 100644 --- a/crates/ethcore/src/engines/hbbft/keygen_transactions.rs +++ b/crates/ethcore/src/engines/hbbft/keygen_transactions.rs @@ -45,10 +45,8 @@ pub enum KeyGenError { NoPartToWrite, CallError(CallError), Unexpected, - } - impl From for KeyGenError { fn from(e: CallError) -> Self { KeyGenError::CallError(e) @@ -141,60 +139,72 @@ impl KeygenTransactionSender { trace!(target:"engine", " get_validator_pubkeys..."); - let vmap = get_validator_pubkeys(&*client, BlockId::Latest, ValidatorType::Pending).map_err(|e| KeyGenError::CallError(e))?; + let vmap = get_validator_pubkeys(&*client, BlockId::Latest, ValidatorType::Pending) + .map_err(|e| KeyGenError::CallError(e))?; let pub_keys: BTreeMap<_, _> = vmap .values() .map(|p| (*p, PublicWrapper { inner: p.clone() })) .collect(); let pub_keys_arc = Arc::new(pub_keys); - let upcoming_epoch = get_posdao_epoch(client, BlockId::Latest).map_err(|e| KeyGenError::CallError(e))? + 1; + let upcoming_epoch = + get_posdao_epoch(client, BlockId::Latest).map_err(|e| KeyGenError::CallError(e))? + 1; //let pub_key_len = pub_keys.len(); // if synckeygen creation fails then either signer or validator pub keys are problematic. // Todo: We should expect up to f clients to write invalid pub keys. Report and re-start pending validator set selection. - let (mut synckeygen, part) = - match engine_signer_to_synckeygen(signer, pub_keys_arc.clone()) { - Ok((mut synckeygen_, part_)) => (synckeygen_, part_), - Err(e) => { - warn!(target:"engine", "engine_signer_to_synckeygen pub keys count {:?} error {:?}", pub_keys_arc.len(), e); - //let mut failure_pub_keys: Vec = Vec::new(); - let mut failure_pub_keys: Vec = Vec::new(); - pub_keys_arc.iter().for_each(|(k, v)| { - warn!(target:"engine", "pub key {}", k.as_bytes().iter().join("")); - - if !v.is_valid() { - warn!(target:"engine", "INVALID pub key {}", k); - - // append the bytes of the public key to the failure_pub_keys. - k.as_bytes().iter().for_each(|b| { - failure_pub_keys.push(*b); - }); - } - }); - - // if we should send our parts, we will send the public keys of the troublemakers instead. - - match self.should_send_part(client, &address).map_err(|e| KeyGenError::CallError(e))? { - ShouldSendKeyAnswer::NoNotThisKeyGenMode => return Err(KeyGenError::Unexpected), - ShouldSendKeyAnswer::NoWaiting => return Err(KeyGenError::Unexpected), - ShouldSendKeyAnswer::Yes => { - - let serialized_part = match bincode::serialize(&failure_pub_keys) { - Ok(part) => part, - Err(e) => { - warn!(target:"engine", "could not serialize part: {:?}", e); - return Err(KeyGenError::Unexpected); - } - }; - - send_part_transaction(full_client, client, &address, upcoming_epoch, serialized_part)?; - trace!(target:"engine", "PART Transaction send for moving forward key gen phase"); - return Ok(()); - }, + let (mut synckeygen, part) = match engine_signer_to_synckeygen(signer, pub_keys_arc.clone()) + { + Ok((mut synckeygen_, part_)) => (synckeygen_, part_), + Err(e) => { + warn!(target:"engine", "engine_signer_to_synckeygen pub keys count {:?} error {:?}", pub_keys_arc.len(), e); + //let mut failure_pub_keys: Vec = Vec::new(); + let mut failure_pub_keys: Vec = Vec::new(); + pub_keys_arc.iter().for_each(|(k, v)| { + warn!(target:"engine", "pub key {}", k.as_bytes().iter().join("")); + + if !v.is_valid() { + warn!(target:"engine", "INVALID pub key {}", k); + + // append the bytes of the public key to the failure_pub_keys. + k.as_bytes().iter().for_each(|b| { + failure_pub_keys.push(*b); + }); } - }, - }; + }); + + // if we should send our parts, we will send the public keys of the troublemakers instead. + + match self + .should_send_part(client, &address) + .map_err(|e| KeyGenError::CallError(e))? + { + ShouldSendKeyAnswer::NoNotThisKeyGenMode => { + return Err(KeyGenError::Unexpected) + } + ShouldSendKeyAnswer::NoWaiting => return Err(KeyGenError::Unexpected), + ShouldSendKeyAnswer::Yes => { + let serialized_part = match bincode::serialize(&failure_pub_keys) { + Ok(part) => part, + Err(e) => { + warn!(target:"engine", "could not serialize part: {:?}", e); + return Err(KeyGenError::Unexpected); + } + }; + + send_part_transaction( + full_client, + client, + &address, + upcoming_epoch, + serialized_part, + )?; + trace!(target:"engine", "PART Transaction send for moving forward key gen phase"); + return Ok(()); + } + } + } + }; // If there is no part then we are not part of the pending validator set and there is nothing for us to do. let part_data = match part { @@ -205,13 +215,11 @@ impl KeygenTransactionSender { } }; - trace!(target:"engine", "preparing to send PARTS for upcoming epoch: {}", upcoming_epoch); // Check if we already sent our part. match self.should_send_part(client, &address)? { ShouldSendKeyAnswer::Yes => { - let serialized_part = match bincode::serialize(&part_data) { Ok(part) => part, Err(e) => { @@ -220,7 +228,13 @@ impl KeygenTransactionSender { } }; - send_part_transaction(full_client, client, &address, upcoming_epoch, serialized_part)?; + send_part_transaction( + full_client, + client, + &address, + upcoming_epoch, + serialized_part, + )?; trace!(target:"engine", "PART Transaction send."); return Ok(()); } @@ -300,9 +314,13 @@ impl KeygenTransactionSender { } } - -fn send_part_transaction(full_client: &dyn BlockChainClient, client: &dyn EngineClient, mining_address: &Address, upcoming_epoch: U256 , data: Vec) -> Result<(), KeyGenError> { - +fn send_part_transaction( + full_client: &dyn BlockChainClient, + client: &dyn EngineClient, + mining_address: &Address, + upcoming_epoch: U256, + data: Vec, +) -> Result<(), KeyGenError> { // the required gas values have been approximated by // experimenting and it's a very rough estimation. // it can be further fine tuned to be just above the real consumption. @@ -312,17 +330,13 @@ fn send_part_transaction(full_client: &dyn BlockChainClient, client: &dyn Engine let nonce = full_client.nonce(&mining_address, BlockId::Latest).unwrap(); let current_round = get_current_key_gen_round(client)?; - let write_part_data = key_history_contract::functions::write_part::call( - upcoming_epoch, - current_round, - data, - ); - - let part_transaction = - TransactionRequest::call(*KEYGEN_HISTORY_ADDRESS, write_part_data.0) - .gas(U256::from(gas)) - .nonce(nonce) - .gas_price(U256::from(10000000000u64)); + let write_part_data = + key_history_contract::functions::write_part::call(upcoming_epoch, current_round, data); + + let part_transaction = TransactionRequest::call(*KEYGEN_HISTORY_ADDRESS, write_part_data.0) + .gas(U256::from(gas)) + .nonce(nonce) + .gas_price(U256::from(10000000000u64)); full_client .transact_silently(part_transaction) .map_err(|e| { @@ -331,5 +345,4 @@ fn send_part_transaction(full_client: &dyn BlockChainClient, client: &dyn Engine })?; return Ok(()); - }