diff --git a/frame/ethereum/src/lib.rs b/frame/ethereum/src/lib.rs index 5ef0878372..9f948fc515 100644 --- a/frame/ethereum/src/lib.rs +++ b/frame/ethereum/src/lib.rs @@ -22,7 +22,10 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] -use frame_support::{decl_module, decl_storage, decl_error, decl_event, ensure, weights::Weight, traits::Get}; +use frame_support::{ + decl_module, decl_storage, decl_error, decl_event, ensure, + weights::Weight, traits::Get, traits::FindAuthor +}; use sp_std::prelude::*; use frame_system::{self as system, ensure_none}; use ethereum_types::{H160, H64, H256, U256, Bloom}; @@ -54,6 +57,7 @@ pub trait Trait: frame_system::Trait + pallet_balances::Trait + palle /// The overarching event type. type Event: From> + Into<::Event>; type ChainId: Get; + type FindAuthor: FindAuthor; } decl_storage! { @@ -181,7 +185,7 @@ decl_module! { ommers_hash: H256::from_slice( Keccak256::digest(&rlp::encode_list(&ommers)[..]).as_slice(), ), // TODO: check ommers hash. - beneficiary: H160::default(), + beneficiary: >::find_author(), state_root: H256::default(), // TODO: figure out if there's better way to get a sort-of-valid state root. transactions_root: H256::from_slice( Keccak256::digest(&rlp::encode_list(&transactions)[..]).as_slice(), @@ -256,6 +260,16 @@ impl frame_support::unsigned::ValidateUnsigned for Module { // functions that do not write to storage and operation functions that do. // - Private functions. These are your usual private utilities unavailable to other pallets. impl Module { + pub fn find_author() -> H160 { + let digest = >::digest(); + let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime()); + if let Some(authority_id) = T::FindAuthor::find_author(pre_runtime_digests) { + authority_id + } else { + H160::default() + } + } + pub fn transaction_status(hash: H256) -> Option { TransactionStatuses::get(hash) } diff --git a/frame/ethereum/src/mock.rs b/frame/ethereum/src/mock.rs index 0af020a9b8..41e7b124f2 100644 --- a/frame/ethereum/src/mock.rs +++ b/frame/ethereum/src/mock.rs @@ -19,7 +19,9 @@ use super::*; use crate::{Module, Trait}; use ethereum::{TransactionAction, TransactionSignature}; -use frame_support::{impl_outer_origin, parameter_types, weights::Weight}; +use frame_support::{ + impl_outer_origin, parameter_types, weights::Weight, ConsensusEngineId +}; use pallet_evm::{FeeCalculator, HashTruncateConvertAccountId}; use rlp::*; use sp_core::{H160, H256, U256}; @@ -100,6 +102,15 @@ impl FeeCalculator for FixedGasPrice { } } +pub struct EthereumFindAuthor; +impl FindAuthor for EthereumFindAuthor { + fn find_author<'a, I>(_digests: I) -> Option where + I: 'a + IntoIterator + { + Some(address_build(0).1) + } +} + parameter_types! { pub const TransactionByteFee: u64 = 1; pub const ChainId: u64 = 42; @@ -118,6 +129,7 @@ impl pallet_evm::Trait for Test { impl Trait for Test { type Event = (); type ChainId = ChainId; + type FindAuthor = EthereumFindAuthor; } pub type System = frame_system::Module; @@ -130,6 +142,16 @@ pub struct AccountInfo { pub private_key: H256, } +fn address_build(seed: u8) -> (H256, H160) { + let private_key = H256::from_slice(&[(seed + 1) as u8; 32]); //H256::from_low_u64_be((i + 1) as u64); + let secret_key = secp256k1::SecretKey::parse_slice(&private_key[..]).unwrap(); + let public_key = secp256k1::PublicKey::from_secret_key(&secret_key); + let address = H160::from(H256::from_slice( + &Keccak256::digest(&public_key.serialize()[1..])[..], + )); + (private_key, address) +} + // This function basically just builds a genesis storage key/value store according to // our desired mockup. pub fn new_test_ext(accounts_len: usize) -> (Vec, sp_io::TestExternalities) { @@ -140,12 +162,7 @@ pub fn new_test_ext(accounts_len: usize) -> (Vec, sp_io::TestExtern let pairs = (0..accounts_len) .map(|i| { - let private_key = H256::from_slice(&[(i + 1) as u8; 32]); //H256::from_low_u64_be((i + 1) as u64); - let secret_key = secp256k1::SecretKey::parse_slice(&private_key[..]).unwrap(); - let public_key = secp256k1::PublicKey::from_secret_key(&secret_key); - let address = H160::from(H256::from_slice( - &Keccak256::digest(&public_key.serialize()[1..])[..], - )); + let (private_key, address) = address_build(i as u8); AccountInfo { private_key: private_key, address: address, diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index b03c0887f3..fc7766ae03 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -79,9 +79,9 @@ fn rich_block_build( ) })), parent_hash: block.header.parent_hash, - uncles_hash: H256::zero(), // TODO - author: H160::default(), // TODO - miner: H160::default(), // TODO + uncles_hash: H256::zero(), + author: block.header.beneficiary, + miner: block.header.beneficiary, state_root: block.header.state_root, transactions_root: block.header.transactions_root, receipts_root: block.header.receipts_root, @@ -92,23 +92,22 @@ fn rich_block_build( logs_bloom: Some(block.header.logs_bloom), timestamp: U256::from(block.header.timestamp), difficulty: block.header.difficulty, - total_difficulty: None, // TODO + total_difficulty: None, seal_fields: vec![ Bytes(block.header.mix_hash.as_bytes().to_vec()), Bytes(block.header.nonce.as_bytes().to_vec()) ], - uncles: vec![], // TODO + uncles: vec![], transactions: BlockTransactions::Full( block.transactions.iter().enumerate().map(|(index, transaction)|{ - let mut status = statuses[index].clone(); - // A fallback to default check - if status.is_none() { - status = Some(TransactionStatus::default()); - } - transaction_build(transaction.clone(), block.clone(), status.unwrap()) + transaction_build( + transaction.clone(), + block.clone(), + statuses[index].clone().unwrap_or_default() + ) }).collect() ), - size: None // TODO + size: Some(U256::from(rlp::encode(&block).len() as u32)) }, extra_info: BTreeMap::new() } diff --git a/template/runtime/src/lib.rs b/template/runtime/src/lib.rs index 5cff3fd7ad..dfbee30079 100644 --- a/template/runtime/src/lib.rs +++ b/template/runtime/src/lib.rs @@ -39,7 +39,7 @@ use sp_runtime::{ transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, ModuleId, MultiSignature, }; -use sp_std::prelude::*; +use sp_std::{prelude::*, marker::PhantomData}; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; @@ -55,7 +55,7 @@ pub use frame_support::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, IdentityFee, Weight, }, - StorageValue, + StorageValue, ConsensusEngineId }; use ethereum::{Block as EthereumBlock, Transaction as EthereumTransaction, Receipt as EthereumReceipt}; use frontier_rpc_primitives::{TransactionStatus}; @@ -303,8 +303,23 @@ impl evm::Trait for Runtime { type Precompiles = (); } +pub struct EthereumFindAuthor(PhantomData); +impl> FindAuthor for EthereumFindAuthor +{ + fn find_author<'a, I>(digests: I) -> Option where + I: 'a + IntoIterator + { + if let Some(author_index) = F::find_author(digests) { + let authority_id = Aura::authorities()[author_index as usize].clone(); + return Some(HashTruncateConvertAccountId::::convert_account_id(&authority_id)); + } + None + } +} + impl ethereum::Trait for Runtime { type Event = Event; + type FindAuthor = EthereumFindAuthor; type ChainId = ChainId; } @@ -466,14 +481,7 @@ impl_runtime_apis! { } fn author() -> H160 { - let digest = >::digest(); - let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime()); - if let Some(index) = >::find_author(pre_runtime_digests) { - let authority_id = &>::authorities()[index as usize]; - >::convert_account_id(&authority_id) - } else { - H160::zero() - } + >::find_author() } fn storage_at(address: H160, index: U256) -> H256 {