simplify BlockReward::reward implementation (#10906)

* simplify BlockReward::reward implementation

* fixed failing tests
This commit is contained in:
Marek Kotewicz 2019-07-30 12:05:06 +02:00 committed by GitHub
parent ec90fc47bc
commit 12256a1e97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 11 additions and 29 deletions

View File

@ -1273,7 +1273,7 @@ impl Engine for AuthorityRound {
Some(ref c) if block.header.number() >= self.block_reward_contract_transition => { Some(ref c) if block.header.number() >= self.block_reward_contract_transition => {
let mut call = super::default_system_or_code_call(&self.machine, block); let mut call = super::default_system_or_code_call(&self.machine, block);
let rewards = c.reward(&beneficiaries, &mut call)?; let rewards = c.reward(beneficiaries, &mut call)?;
rewards.into_iter().map(|(author, amount)| (author, RewardKind::External, amount)).collect() rewards.into_iter().map(|(author, amount)| (author, RewardKind::External, amount)).collect()
}, },
_ => { _ => {

View File

@ -17,9 +17,8 @@
//! A module with types for declaring block rewards and a client interface for interacting with a //! A module with types for declaring block rewards and a client interface for interacting with a
//! block reward contract. //! block reward contract.
use ethabi; use ethabi::FunctionOutputDecoder;
use ethabi::ParamType; use ethereum_types::{Address, U256};
use ethereum_types::{H160, Address, U256};
use std::sync::Arc; use std::sync::Arc;
use hash::keccak; use hash::keccak;
@ -112,44 +111,27 @@ impl BlockRewardContract {
/// `machine.execute_as_system`). /// `machine.execute_as_system`).
pub fn reward( pub fn reward(
&self, &self,
beneficiaries: &[(Address, RewardKind)], beneficiaries: Vec<(Address, RewardKind)>,
caller: &mut SystemOrCodeCall, caller: &mut SystemOrCodeCall,
) -> Result<Vec<(Address, U256)>, Error> { ) -> Result<Vec<(Address, U256)>, Error> {
let input = block_reward_contract::functions::reward::encode_input( let (addresses, rewards): (Vec<_>, Vec<_>) = beneficiaries.into_iter().unzip();
beneficiaries.iter().map(|&(address, _)| H160::from(address)), let (input, decoder) = block_reward_contract::functions::reward::call(addresses, rewards.into_iter().map(u16::from));
beneficiaries.iter().map(|&(_, ref reward_kind)| u16::from(*reward_kind)),
);
let output = caller(self.kind.clone(), input) let output = caller(self.kind.clone(), input)
.map_err(Into::into) .map_err(Into::into)
.map_err(EngineError::FailedSystemCall)?; .map_err(EngineError::FailedSystemCall)?;
// since this is a non-constant call we can't use ethabi's function output let (addresses, rewards) = decoder.decode(&output)
// deserialization, sadness ensues.
let types = &[
ParamType::Array(Box::new(ParamType::Address)),
ParamType::Array(Box::new(ParamType::Uint(256))),
];
let tokens = ethabi::decode(types, &output)
.map_err(|err| err.to_string()) .map_err(|err| err.to_string())
.map_err(EngineError::FailedSystemCall)?; .map_err(EngineError::FailedSystemCall)?;
assert!(tokens.len() == 2);
let addresses = tokens[0].clone().to_array().expect("type checked by ethabi::decode; qed");
let rewards = tokens[1].clone().to_array().expect("type checked by ethabi::decode; qed");
if addresses.len() != rewards.len() { if addresses.len() != rewards.len() {
return Err(EngineError::FailedSystemCall( return Err(EngineError::FailedSystemCall(
"invalid data returned by reward contract: both arrays must have the same size".into() "invalid data returned by reward contract: both arrays must have the same size".into()
).into()); ).into());
} }
let addresses = addresses.into_iter().map(|t| t.to_address().expect("type checked by ethabi::decode; qed")); Ok(addresses.into_iter().zip(rewards.into_iter()).collect())
let rewards = rewards.into_iter().map(|t| t.to_uint().expect("type checked by ethabi::decode; qed"));
Ok(addresses.zip(rewards).collect())
} }
} }
@ -222,7 +204,7 @@ mod test {
}; };
// if no beneficiaries are given no rewards are attributed // if no beneficiaries are given no rewards are attributed
assert!(block_reward_contract.reward(&vec![], &mut call).unwrap().is_empty()); assert!(block_reward_contract.reward(vec![], &mut call).unwrap().is_empty());
// the contract rewards (1000 + kind) for each benefactor // the contract rewards (1000 + kind) for each benefactor
let beneficiaries = vec![ let beneficiaries = vec![
@ -231,7 +213,7 @@ mod test {
(Address::from_str("0000000000000000000000000000000000000035").unwrap(), RewardKind::EmptyStep), (Address::from_str("0000000000000000000000000000000000000035").unwrap(), RewardKind::EmptyStep),
]; ];
let rewards = block_reward_contract.reward(&beneficiaries, &mut call).unwrap(); let rewards = block_reward_contract.reward(beneficiaries, &mut call).unwrap();
let expected = vec![ let expected = vec![
(Address::from_str("0000000000000000000000000000000000000033").unwrap(), U256::from(1000)), (Address::from_str("0000000000000000000000000000000000000033").unwrap(), U256::from(1000)),
(Address::from_str("0000000000000000000000000000000000000034").unwrap(), U256::from(1000 + 101)), (Address::from_str("0000000000000000000000000000000000000034").unwrap(), U256::from(1000 + 101)),

View File

@ -264,7 +264,7 @@ impl Engine for Arc<Ethash> {
let mut call = engines::default_system_or_code_call(&self.machine, block); let mut call = engines::default_system_or_code_call(&self.machine, block);
let rewards = c.reward(&beneficiaries, &mut call)?; let rewards = c.reward(beneficiaries, &mut call)?;
rewards.into_iter().map(|(author, amount)| (author, RewardKind::External, amount)).collect() rewards.into_iter().map(|(author, amount)| (author, RewardKind::External, amount)).collect()
}, },
_ => { _ => {