diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 30df44eb4..951e66a2d 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -1273,7 +1273,7 @@ impl Engine for AuthorityRound { 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 rewards = c.reward(&beneficiaries, &mut call)?; + let rewards = c.reward(beneficiaries, &mut call)?; rewards.into_iter().map(|(author, amount)| (author, RewardKind::External, amount)).collect() }, _ => { diff --git a/ethcore/src/engines/block_reward.rs b/ethcore/src/engines/block_reward.rs index 908fc9ceb..8df88d9f2 100644 --- a/ethcore/src/engines/block_reward.rs +++ b/ethcore/src/engines/block_reward.rs @@ -17,9 +17,8 @@ //! A module with types for declaring block rewards and a client interface for interacting with a //! block reward contract. -use ethabi; -use ethabi::ParamType; -use ethereum_types::{H160, Address, U256}; +use ethabi::FunctionOutputDecoder; +use ethereum_types::{Address, U256}; use std::sync::Arc; use hash::keccak; @@ -112,44 +111,27 @@ impl BlockRewardContract { /// `machine.execute_as_system`). pub fn reward( &self, - beneficiaries: &[(Address, RewardKind)], + beneficiaries: Vec<(Address, RewardKind)>, caller: &mut SystemOrCodeCall, ) -> Result, Error> { - let input = block_reward_contract::functions::reward::encode_input( - beneficiaries.iter().map(|&(address, _)| H160::from(address)), - beneficiaries.iter().map(|&(_, ref reward_kind)| u16::from(*reward_kind)), - ); + let (addresses, rewards): (Vec<_>, Vec<_>) = beneficiaries.into_iter().unzip(); + let (input, decoder) = block_reward_contract::functions::reward::call(addresses, rewards.into_iter().map(u16::from)); let output = caller(self.kind.clone(), input) .map_err(Into::into) .map_err(EngineError::FailedSystemCall)?; - // since this is a non-constant call we can't use ethabi's function 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) + let (addresses, rewards) = decoder.decode(&output) .map_err(|err| err.to_string()) .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() { return Err(EngineError::FailedSystemCall( "invalid data returned by reward contract: both arrays must have the same size".into() ).into()); } - let addresses = addresses.into_iter().map(|t| t.to_address().expect("type checked by ethabi::decode; qed")); - let rewards = rewards.into_iter().map(|t| t.to_uint().expect("type checked by ethabi::decode; qed")); - - Ok(addresses.zip(rewards).collect()) + Ok(addresses.into_iter().zip(rewards.into_iter()).collect()) } } @@ -222,7 +204,7 @@ mod test { }; // 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 let beneficiaries = vec![ @@ -231,7 +213,7 @@ mod test { (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![ (Address::from_str("0000000000000000000000000000000000000033").unwrap(), U256::from(1000)), (Address::from_str("0000000000000000000000000000000000000034").unwrap(), U256::from(1000 + 101)), diff --git a/ethcore/src/engines/ethash.rs b/ethcore/src/engines/ethash.rs index d25bed59b..21aeca87c 100644 --- a/ethcore/src/engines/ethash.rs +++ b/ethcore/src/engines/ethash.rs @@ -264,7 +264,7 @@ impl Engine for Arc { 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() }, _ => {