Skip to content

Commit

Permalink
Genesis block in pallet-ethereum (#79)
Browse files Browse the repository at this point in the history
* Store genesis block in pallet-ethereum

* Return genesis block on BlockNumber::Earliest

* Styling fixes
  • Loading branch information
tgmichel authored Jul 22, 2020
1 parent e92bef4 commit 5f1ad2b
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 60 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

122 changes: 66 additions & 56 deletions frame/ethereum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ decl_storage! {
TransactionStatuses: map hasher(blake2_128_concat) H256 => Option<TransactionStatus>;
Transactions: map hasher(blake2_128_concat) H256 => Option<(H256, u32)>;
}
add_extra_genesis {
build(|_config: &GenesisConfig| {
<Module<T>>::store_block(T::BlockNumber::from(0));
});
}
}

decl_event!(
Expand Down Expand Up @@ -174,62 +179,7 @@ decl_module! {

// The signature could also look like: `fn on_finalize()`
fn on_finalize(n: T::BlockNumber) {
let transactions_and_receipts = PendingTransactionsAndReceipts::take();
let (transactions, receipts): (Vec<_>, Vec<_>) =
transactions_and_receipts.into_iter().unzip();
let ommers = Vec::<ethereum::Header>::new();

let header = ethereum::Header {
parent_hash: frame_system::Module::<T>::parent_hash(),
ommers_hash: H256::from_slice(
Keccak256::digest(&rlp::encode_list(&ommers)[..]).as_slice(),
), // TODO: check ommers hash.
beneficiary: <Module<T>>::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(),
), // TODO: check transactions hash.
receipts_root: H256::from_slice(
Keccak256::digest(&rlp::encode_list(&receipts)[..]).as_slice(),
), // TODO: check receipts hash.
logs_bloom: Bloom::default(), // TODO: gather the logs bloom from receipts.
difficulty: U256::zero(),
number: U256::from(
UniqueSaturatedInto::<u128>::unique_saturated_into(
frame_system::Module::<T>::block_number()
)
),
gas_limit: U256::zero(), // TODO: set this using Ethereum's gas limit change algorithm.
gas_used: U256::zero(), // TODO: get this from receipts.
timestamp: UniqueSaturatedInto::<u64>::unique_saturated_into(
pallet_timestamp::Module::<T>::get()
),
extra_data: H256::default(),
mix_hash: H256::default(),
nonce: H64::default(),
};
let hash = H256::from_slice(Keccak256::digest(&rlp::encode(&header)).as_slice());

let block = ethereum::Block {
header,
transactions: transactions.clone(),
ommers,
};

for t in &transactions {
let transaction_hash = H256::from_slice(
Keccak256::digest(&rlp::encode(t)).as_slice()
);
if let Some(status) = TransactionStatuses::get(transaction_hash) {
Transactions::insert(
transaction_hash,
(hash, status.transaction_index)
);
}
}

BlocksAndReceipts::insert(hash, (block, receipts));
BlockNumbers::<T>::insert(n, hash);
<Module<T>>::store_block(n);
}

// A runtime code run after every block and have access to extended set of APIs.
Expand Down Expand Up @@ -259,6 +209,66 @@ impl<T: Trait> frame_support::unsigned::ValidateUnsigned for Module<T> {
// 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<T: Trait> Module<T> {

fn store_block(n: T::BlockNumber) {
let transactions_and_receipts = PendingTransactionsAndReceipts::take();
let (transactions, receipts): (Vec<_>, Vec<_>) =
transactions_and_receipts.into_iter().unzip();
let ommers = Vec::<ethereum::Header>::new();

let header = ethereum::Header {
parent_hash: frame_system::Module::<T>::parent_hash(),
ommers_hash: H256::from_slice(
Keccak256::digest(&rlp::encode_list(&ommers)[..]).as_slice(),
), // TODO: check ommers hash.
beneficiary: <Module<T>>::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(),
), // TODO: check transactions hash.
receipts_root: H256::from_slice(
Keccak256::digest(&rlp::encode_list(&receipts)[..]).as_slice(),
), // TODO: check receipts hash.
logs_bloom: Bloom::default(), // TODO: gather the logs bloom from receipts.
difficulty: U256::zero(),
number: U256::from(
UniqueSaturatedInto::<u128>::unique_saturated_into(
frame_system::Module::<T>::block_number()
)
),
gas_limit: U256::zero(), // TODO: set this using Ethereum's gas limit change algorithm.
gas_used: U256::zero(), // TODO: get this from receipts.
timestamp: UniqueSaturatedInto::<u64>::unique_saturated_into(
pallet_timestamp::Module::<T>::get()
),
extra_data: H256::default(),
mix_hash: H256::default(),
nonce: H64::default(),
};
let hash = H256::from_slice(Keccak256::digest(&rlp::encode(&header)).as_slice());

let block = ethereum::Block {
header,
transactions: transactions.clone(),
ommers,
};

for t in &transactions {
let transaction_hash = H256::from_slice(
Keccak256::digest(&rlp::encode(t)).as_slice()
);
if let Some(status) = TransactionStatuses::get(transaction_hash) {
Transactions::insert(
transaction_hash,
(hash, status.transaction_index)
);
}
}

BlocksAndReceipts::insert(hash, (block, receipts));
BlockNumbers::<T>::insert(n, hash);
}

pub fn find_author() -> H160 {
let digest = <frame_system::Module<T>>::digest();
let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime());
Expand Down
2 changes: 1 addition & 1 deletion rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ impl<B, C, SC, P, CT, BE> EthApi<B, C, SC, P, CT, BE> where
);
},
BlockNumber::Earliest => {
native_number = Some(1);
native_number = Some(0);
},
BlockNumber::Pending => {
native_number = None;
Expand Down
1 change: 1 addition & 0 deletions template/node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ sp-consensus-aura = { version = "0.8.0-dev", path = "../../vendor/substrate/prim
sp-consensus = { version = "0.8.0-dev", path = "../../vendor/substrate/primitives/consensus/common" }
sc-consensus = { version = "0.8.0-dev", path = "../../vendor/substrate/client/consensus/common" }
evm = { version = "2.0.0-dev", package = "pallet-evm", path = "../../vendor/substrate/frame/evm" }
ethereum = { version = "0.1.0", package = "pallet-ethereum", path = "../../frame/ethereum" }
sc-finality-grandpa = { version = "0.8.0-dev", path = "../../vendor/substrate/client/finality-grandpa" }
sp-finality-grandpa = { version = "2.0.0-dev", path = "../../vendor/substrate/primitives/finality-grandpa" }
sc-client-api = { version = "2.0.0-dev", path = "../../vendor/substrate/client/api" }
Expand Down
5 changes: 3 additions & 2 deletions template/node/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
use sp_core::{U256, Pair, Public, sr25519};
use evm::{ConvertAccountId, HashTruncateConvertAccountId};
use frontier_template_runtime::{
AccountId, AuraConfig, BalancesConfig, EVMConfig, GenesisConfig, GrandpaConfig, Signature,
SudoConfig, SystemConfig, WASM_BINARY,
AccountId, AuraConfig, BalancesConfig, EVMConfig, EthereumConfig, GenesisConfig, GrandpaConfig,
Signature, SudoConfig, SystemConfig, WASM_BINARY,
};
use sc_service::ChainType;
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
Expand Down Expand Up @@ -162,5 +162,6 @@ fn testnet_genesis(
evm: Some(EVMConfig {
accounts: evm_accounts,
}),
ethereum: Some(EthereumConfig {}),
}
}
2 changes: 1 addition & 1 deletion template/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ construct_runtime!(
Balances: balances::{Module, Call, Storage, Config<T>, Event<T>},
TransactionPayment: transaction_payment::{Module, Storage},
Sudo: sudo::{Module, Call, Config<T>, Storage, Event<T>},
Ethereum: ethereum::{Module, Call, Storage, Event<T>, ValidateUnsigned},
Ethereum: ethereum::{Module, Call, Storage, Event<T>, Config, ValidateUnsigned},
EVM: evm::{Module, Config, Call, Storage, Event<T>},
}
);
Expand Down

0 comments on commit 5f1ad2b

Please sign in to comment.