Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

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

30 changes: 15 additions & 15 deletions core/sr-eth-primitives/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,21 @@ enum Seal {

#[derive(Default, PartialEq, Eq, Clone, Encode, Decode, RlpEncodable, RlpDecodable, RuntimeDebug)]
pub struct EthHeader {
parent_hash: H256,
timestamp: u64,
number: BlockNumber,
author: Address,
transactions_root: H256,
uncles_hash: H256,
extra_data: Bytes,
state_root: H256,
receipts_root: H256,
log_bloom: Bloom,
gas_used: U256,
gas_limit: U256,
difficulty: U256,
seal: Vec<Bytes>,
hash: Option<H256>,
pub parent_hash: H256,
pub timestamp: u64,
pub number: BlockNumber,
pub author: Address,
pub transactions_root: H256,
pub uncles_hash: H256,
pub extra_data: Bytes,
pub state_root: H256,
pub receipts_root: H256,
pub log_bloom: Bloom,
pub gas_used: U256,
pub gas_limit: U256,
pub difficulty: U256,
pub seal: Vec<Bytes>,
pub hash: Option<H256>,
}

/// Alter value of given field, reset memoised hash if changed.
Expand Down
9 changes: 9 additions & 0 deletions srml/eth-relay/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ rlp = { package = "rlp", git = "https://github.com/darwinia-network/parity-commo
ethash = { git = "https://github.com/hammeWang/ethash-rs.git", rev = "70a4f078", default-features = false}
merkle-patricia-trie = { path = "../../core/merkle-patricia-trie", default-features = false}

[dev-dependencies]
runtime-io = { package = "sr-io", git = "https://github.com/darwinia-network/substrate.git", branch = "darwinia-develop"}
primitives = { package = "substrate-primitives", git = "https://github.com/darwinia-network/substrate.git", branch = "darwinia-develop" }
transaction-payment = { package = "srml-transaction-payment", git = "https://github.com/darwinia-network/substrate.git", branch = "darwinia-develop" }
rustc-hex = "2.0"
keccak-hasher = "0.15.2"
triehash = { package = "triehash", git = "https://github.com/darwinia-network/parity-common.git" }
hex-literal = "0.2.1"

[features]
default = ["std"]
std = [
Expand Down
73 changes: 38 additions & 35 deletions srml/eth-relay/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ use merkle_patricia_trie::{trie::Trie, MerklePatriciaTrie, Proof};

type DAG = LightDAG<EthereumPatch>;

mod mock;
mod tests;

pub trait Trait: system::Trait {
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}
Expand Down Expand Up @@ -99,6 +102,9 @@ decl_module! {
pub fn test_relay_header(origin, header: EthHeader) {
let _relayer = ensure_signed(origin)?;

// TODO: Just for easy testing.
Self::genesis_header(&header);

<Module<T>>::deposit_event(RawEvent::NewHeader(header));
}

Expand Down Expand Up @@ -136,37 +142,14 @@ decl_module! {
<Module<T>>::deposit_event(RawEvent::NewHeader(header));
}

pub fn test_check_receipt(origin, receipt: Receipt, proof_record: ActionRecord) {
let _relayer = ensure_signed(origin)?;

<Module<T>>::deposit_event(RawEvent::RelayProof(proof_record));
}

pub fn check_receipt(origin, receipt: Receipt, proof_record: ActionRecord) {
pub fn check_receipt(origin, proof_record: ActionRecord) {
let _relayer = ensure_signed(origin)?;

let header_hash = proof_record.header_hash;
if !HeaderOf::exists(header_hash) {
return Err("This block header does not exist.")
}

let header = HeaderOf::get(header_hash).unwrap();

let proof: Proof = rlp::decode(&proof_record.proof).unwrap();
let key = rlp::encode(&proof_record.index);
let verified_receipt = Self::verify_receipt(&proof_record);

let value = MerklePatriciaTrie::verify_proof(header.receipts_root().0.to_vec(), &key, proof)
.unwrap();
assert!(value.is_some());
ensure!(verified_receipt.is_some(), "Receipt proof verification failed.");

let receipt_encoded = rlp::encode(&receipt);

assert_eq!(value.unwrap(), receipt_encoded);
// confirm that the block hash is right
// get the receipt MPT trie root from the block header
// Using receipt MPT trie root to verify the proof and index etc.

<Module<T>>::deposit_event(RawEvent::RelayProof(proof_record));
<Module<T>>::deposit_event(RawEvent::RelayProof(verified_receipt.unwrap(), proof_record));
}

// Assuming that there are at least one honest worker submiting headers
Expand All @@ -184,7 +167,7 @@ decl_event! {
<T as system::Trait>::AccountId
{
NewHeader(EthHeader),
RelayProof(ActionRecord),
RelayProof(Receipt, ActionRecord),
TODO(AccountId),
}
}
Expand All @@ -208,6 +191,30 @@ impl<T: Trait> Module<T> {
BeginHeader::put(header.clone());
}

fn verify_receipt(proof_record: &ActionRecord) -> Option<Receipt> {
let header_hash = proof_record.header_hash;
if !HeaderOf::exists(header_hash) {
return None; //Err("This block header does not exist.");
}

let header = HeaderOf::get(header_hash).unwrap();

let proof: Proof = rlp::decode(&proof_record.proof).unwrap();
let key = rlp::encode(&proof_record.index);

let value = MerklePatriciaTrie::verify_proof(header.receipts_root().0.to_vec(), &key, proof).unwrap();
if !value.is_some() {
return None;
}

let proof_receipt: Receipt = rlp::decode(&value.unwrap()).expect("can't deserialize the receipt");

Some(proof_receipt)
// confirm that the block hash is right
// get the receipt MPT trie root from the block header
// Using receipt MPT trie root to verify the proof and index etc.
}

/// 1. proof of difficulty
/// 2. proof of pow (mixhash)
/// 3. challenge
Expand All @@ -228,13 +235,9 @@ impl<T: Trait> Module<T> {
// check difficulty
let ethash_params = EthashPartial::production();
// ethash_params.set_difficulty_bomb_delays(0xc3500, 5000000);
let result = ethash_params.verify_block_basic(header);
match result {
Ok(_) => (),
Err(e) => {
return Err("Block difficulty verification failed.");
}
};
let result = ethash_params
.verify_block_basic(header)
.expect("Block difficulty verification failed.");

// verify difficulty
let difficulty = ethash_params.calculate_difficulty(header, &prev_header);
Expand Down
155 changes: 155 additions & 0 deletions srml/eth-relay/src/mock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
//! Test utilities

#![cfg(test)]

use crate::{GenesisConfig, Module, Trait};
use primitives::H256;
use runtime_io;
use sr_primitives::{
testing::Header,
traits::{ConvertInto, IdentityLookup},
weights::{DispatchInfo, Weight},
Perbill,
};
use std::cell::RefCell;
use support::traits::Get;
use support::{impl_outer_origin, parameter_types};

impl_outer_origin! {
pub enum Origin for Runtime {}
}

thread_local! {
static EXISTENTIAL_DEPOSIT: RefCell<u64> = RefCell::new(0);
static TRANSFER_FEE: RefCell<u64> = RefCell::new(0);
static CREATION_FEE: RefCell<u64> = RefCell::new(0);
}

pub struct ExistentialDeposit;
impl Get<u64> for ExistentialDeposit {
fn get() -> u64 {
EXISTENTIAL_DEPOSIT.with(|v| *v.borrow())
}
}

pub struct TransferFee;
impl Get<u64> for TransferFee {
fn get() -> u64 {
TRANSFER_FEE.with(|v| *v.borrow())
}
}

pub struct CreationFee;
impl Get<u64> for CreationFee {
fn get() -> u64 {
CREATION_FEE.with(|v| *v.borrow())
}
}

// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Runtime;
parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const MaximumBlockWeight: u32 = 1024;
pub const MaximumBlockLength: u32 = 2 * 1024;
pub const AvailableBlockRatio: Perbill = Perbill::one();
}
impl system::Trait for Runtime {
type Origin = Origin;
type Index = u64;
type BlockNumber = u64;
type Call = ();
type Hash = H256;
type Hashing = ::sr_primitives::traits::BlakeTwo256;
type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = ();
type BlockHashCount = BlockHashCount;
type MaximumBlockWeight = MaximumBlockWeight;
type MaximumBlockLength = MaximumBlockLength;
type AvailableBlockRatio = AvailableBlockRatio;
type Version = ();
}
parameter_types! {
pub const TransactionBaseFee: u64 = 0;
pub const TransactionByteFee: u64 = 1;
}

impl Trait for Runtime {
type Event = ();
}

parameter_types! {
pub const MinimumPeriod: u64 = 5;
}

pub struct ExtBuilder {
existential_deposit: u64,
transfer_fee: u64,
creation_fee: u64,
monied: bool,
vesting: bool,
}
impl Default for ExtBuilder {
fn default() -> Self {
Self {
existential_deposit: 0,
transfer_fee: 0,
creation_fee: 0,
monied: false,
vesting: false,
}
}
}
impl ExtBuilder {
pub fn existential_deposit(mut self, existential_deposit: u64) -> Self {
self.existential_deposit = existential_deposit;
self
}
#[allow(dead_code)]
pub fn transfer_fee(mut self, transfer_fee: u64) -> Self {
self.transfer_fee = transfer_fee;
self
}
pub fn creation_fee(mut self, creation_fee: u64) -> Self {
self.creation_fee = creation_fee;
self
}
pub fn monied(mut self, monied: bool) -> Self {
self.monied = monied;
if self.existential_deposit == 0 {
self.existential_deposit = 1;
}
self
}
pub fn vesting(mut self, vesting: bool) -> Self {
self.vesting = vesting;
self
}
pub fn set_associated_consts(&self) {
EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit);
TRANSFER_FEE.with(|v| *v.borrow_mut() = self.transfer_fee);
CREATION_FEE.with(|v| *v.borrow_mut() = self.creation_fee);
}
pub fn build(self) -> runtime_io::TestExternalities {
self.set_associated_consts();
let mut t = system::GenesisConfig::default().build_storage::<Runtime>().unwrap();

t.into()
}
}

pub type System = system::Module<Runtime>;
pub type EthRelay = Module<Runtime>;

pub const CALL: &<Runtime as system::Trait>::Call = &();

/// create a transaction info struct from weight. Handy to avoid building the whole struct.
pub fn info_from_weight(w: Weight) -> DispatchInfo {
DispatchInfo {
weight: w,
..Default::default()
}
}
Loading