diff --git a/crates/ethcore/src/engines/mod.rs b/crates/ethcore/src/engines/mod.rs index 7eff7c6981..472d242029 100644 --- a/crates/ethcore/src/engines/mod.rs +++ b/crates/ethcore/src/engines/mod.rs @@ -660,10 +660,11 @@ pub trait EthEngine: Engine<::machine::EthereumMachine> { &self, t: UnverifiedTransaction, header: &Header, - gas_price: Option, - current_block_reward_address: Option
, + gas_price: Option, + current_block_reward_address: Option
, + current_fees_address: Option
, ) -> Result { - self.machine().verify_transaction_unordered(t, header, gas_price, current_block_reward_address) + self.machine().verify_transaction_unordered(t, header, gas_price, current_block_reward_address, current_fees_address) } /// Perform basic/cheap transaction verification. diff --git a/crates/ethcore/src/machine/impls.rs b/crates/ethcore/src/machine/impls.rs index 2aadfa3750..c5a443a822 100644 --- a/crates/ethcore/src/machine/impls.rs +++ b/crates/ethcore/src/machine/impls.rs @@ -376,52 +376,76 @@ impl EthereumMachine { &self, t: UnverifiedTransaction, header: &Header, - gas_price: Option, - current_block_reward_addr: Option
, + gas_price: Option, + current_block_reward_addr: Option
, + current_fees_addr: Option
, ) -> Result { - // Cheching block reward transaction. It should be verified with zero gas price - // all other should pay at least minimal gas price - // Check transaction sended by the block author - let public = t.recover_public()?; - let sender = public_to_address(&public); - let sended_by_block_author = sender == *header.author(); - - //Check if transaction has block reward specific data - let has_reward_data = match t.as_unsigned() { - TypedTransaction::Legacy(tx) => { - tx.data == vec![0xc3, 0x3f, 0xb8, 0x77] - } - _ => false, - }; - - //Check if transaction calling the correct contract - let calling_block_reward = match t.as_unsigned() { - TypedTransaction::Legacy(tx) => { - match tx.action { - Action::Call(addr) => { - if let Some(reward_address) = current_block_reward_addr { - addr == reward_address - } else { - false - } - } - _ => false, - } - } - _ => false, - }; - - let is_block_reward_tx = sended_by_block_author && has_reward_data && calling_block_reward; - - if !is_block_reward_tx { - if let Some(price) = gas_price { - if t.tx().gas_price < price { - return Err(transaction::Error::InsufficientGas { minimal: price, got: t.tx().gas_price }); - } - } - } + // Cheching block reward transaction. It should be verified with zero gas price + // all other should pay at least minimal gas price + // Check transaction sended by the block author + let public = t.recover_public()?; + let sender = public_to_address(&public); + let sended_by_block_author = sender == *header.author(); + + //Check if transaction has block reward specific data + let has_reward_data = match t.as_unsigned() { + TypedTransaction::Legacy(tx) => { + tx.data == vec![0xc3, 0x3f, 0xb8, 0x77] + } + _ => false, + }; + + //Check if transaction has fees specific data + let has_fees_data = match t.as_unsigned() { + TypedTransaction::Legacy(tx) => { + tx.data == vec![0x57, 0xc3, 0xc9, 0xfb] + } + _ => false, + }; + + //Check if transaction calling the block reward contract + let calling_block_reward = match t.as_unsigned() { + TypedTransaction::Legacy(tx) => { + match tx.action { + Action::Call(addr) => { + if let Some(reward_address) = current_block_reward_addr { + addr == reward_address + } else { + false + } + } + _ => false, + } + } + _ => false, + }; + + //Check if transaction calling the fees contract + let calling_fees = match t.as_unsigned() { + TypedTransaction::Legacy(tx) => { + match tx.action { + Action::Call(addr) => { + if let Some(fees_address) = current_fees_addr { + addr == fees_address + } else { + false + } + } + _ => false, + } + } + _ => false, + }; + let is_airdao_tx = sended_by_block_author && ((has_reward_data && calling_block_reward) || (has_fees_data && calling_fees)); + if !is_airdao_tx { + if let Some(price) = gas_price { + if t.tx().gas_price < price { + return Err(transaction::Error::InsufficientGas { minimal: price, got: t.tx().gas_price }); + } + } + } // ensure that the user was willing to at least pay the base fee if t.tx().gas_price < header.base_fee().unwrap_or_default() && !t.has_zero_gas_price() { diff --git a/crates/ethcore/src/verification/verification.rs b/crates/ethcore/src/verification/verification.rs index 810cf38081..8d9f9b7c3a 100644 --- a/crates/ethcore/src/verification/verification.rs +++ b/crates/ethcore/src/verification/verification.rs @@ -128,6 +128,7 @@ pub fn verify_block_unordered( let latest_gas_price = engine.get_gas_price(&header); let current_block_reward_address = engine.current_block_reward_address(&header); + let current_fees_address = engine.current_fees_address(&header); // t_nb 5.3 iterate over all transactions let transactions = block @@ -135,7 +136,7 @@ pub fn verify_block_unordered( .into_iter() .map(|t| { // t_nb 5.3.1 call verify_unordered. Check signatures and calculate address - let t = engine.verify_transaction_unordered(t, &header, latest_gas_price, current_block_reward_address)?; + let t = engine.verify_transaction_unordered(t, &header, latest_gas_price, current_block_reward_address, current_fees_address)?; // t_nb 5.3.2 check if nonce is more then max nonce (EIP-168 and EIP169) if let Some(max_nonce) = nonce_cap { if t.tx().nonce >= max_nonce {