Skip to content
This repository has been archived by the owner on Mar 13, 2023. It is now read-only.

Commit

Permalink
Dvm update from 304 (#559)
Browse files Browse the repository at this point in the history
* Companion for 304

* Companion for 302

* Companion for 324

* Companion for 326
  • Loading branch information
boundless-forest authored Mar 23, 2021
1 parent ea6bc73 commit 48f7efd
Show file tree
Hide file tree
Showing 9 changed files with 377 additions and 127 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ members = [
"frame/evm/precompile/contracts/modexp",
"frame/evm/precompile/contracts/simple",
"frame/evm/precompile/contracts/withdraw",
"frame/evm/precompile/contracts/sha3fips",
"frame/header-mmr",
"frame/header-mmr/rpc",
"frame/header-mmr/rpc/runtime-api",
Expand Down
19 changes: 18 additions & 1 deletion client/dvm/db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,12 @@ impl DatabaseSettingsSrc {
}

pub(crate) mod columns {
pub const NUM_COLUMNS: u32 = 3;
pub const NUM_COLUMNS: u32 = 4;

pub const META: u32 = 0;
pub const BLOCK_MAPPING: u32 = 1;
pub const TRANSACTION_MAPPING: u32 = 2;
pub const SYNCED_MAPPING: u32 = 3;
}

pub(crate) mod static_keys {
Expand Down Expand Up @@ -161,6 +162,16 @@ pub struct MappingDb<Block: BlockT> {
}

impl<Block: BlockT> MappingDb<Block> {
pub fn is_synced(&self, block_hash: &Block::Hash) -> Result<bool, String> {
match self
.db
.get(crate::columns::SYNCED_MAPPING, &block_hash.encode())
{
Some(raw) => Ok(bool::decode(&mut &raw[..]).map_err(|e| format!("{:?}", e))?),
None => Ok(false),
}
}

pub fn block_hashes(&self, ethereum_block_hash: &H256) -> Result<Vec<Block::Hash>, String> {
match self
.db
Expand Down Expand Up @@ -218,6 +229,12 @@ impl<Block: BlockT> MappingDb<Block> {
);
}

transaction.set(
crate::columns::SYNCED_MAPPING,
&commitment.block_hash.encode(),
&true.encode(),
);

self.db
.commit(transaction)
.map_err(|e| format!("{:?}", e))?;
Expand Down
87 changes: 45 additions & 42 deletions client/dvm/mapping-sync/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ where
Ok(())
}

pub fn sync_one_level<Block: BlockT, C, B>(
pub fn sync_one_block<Block: BlockT, C, B>(
client: &C,
substrate_backend: &B,
frontier_backend: &dc_db::Backend<Block>,
Expand All @@ -89,55 +89,58 @@ where
{
let mut current_syncing_tips = frontier_backend.meta().current_syncing_tips()?;

if current_syncing_tips.len() == 0 {
// Sync genesis block.

let header = substrate_backend
.header(BlockId::Number(Zero::zero()))
.map_err(|e| format!("{:?}", e))?
.ok_or("Genesis header not found".to_string())?;
sync_genesis_block(client, frontier_backend, &header)?;

current_syncing_tips.push(header.hash());
frontier_backend
.meta()
.write_current_syncing_tips(current_syncing_tips)?;
if current_syncing_tips.is_empty() {
let mut leaves = substrate_backend.leaves().map_err(|e| format!("{:?}", e))?;
if leaves.is_empty() {
return Ok(false);
}

Ok(true)
} else {
let mut syncing_tip_and_children = None;
current_syncing_tips.append(&mut leaves);
}

for tip in &current_syncing_tips {
let children = substrate_backend
.children(*tip)
.map_err(|e| format!("{:?}", e))?;
let mut operating_tip = None;

if children.len() > 0 {
syncing_tip_and_children = Some((*tip, children));
break;
}
while let Some(checking_tip) = current_syncing_tips.pop() {
if !frontier_backend
.mapping()
.is_synced(&checking_tip)
.map_err(|e| format!("{:?}", e))?
{
operating_tip = Some(checking_tip);
break;
}
}

if let Some((syncing_tip, children)) = syncing_tip_and_children {
current_syncing_tips.retain(|tip| tip != &syncing_tip);

for child in children {
let header = substrate_backend
.header(BlockId::Hash(child))
.map_err(|e| format!("{:?}", e))?
.ok_or("Header not found".to_string())?;

sync_block(frontier_backend, &header)?;
current_syncing_tips.push(child);
}
let operating_tip = match operating_tip {
Some(operating_tip) => operating_tip,
None => {
frontier_backend
.meta()
.write_current_syncing_tips(current_syncing_tips)?;

Ok(true)
} else {
Ok(false)
return Ok(false);
}
};

let operating_header = substrate_backend
.header(BlockId::Hash(operating_tip))
.map_err(|e| format!("{:?}", e))?
.ok_or("Header not found".to_string())?;

if operating_header.number() == &Zero::zero() {
sync_genesis_block(client, frontier_backend, &operating_header)?;

frontier_backend
.meta()
.write_current_syncing_tips(current_syncing_tips)?;
Ok(true)
} else {
sync_block(frontier_backend, &operating_header)?;

current_syncing_tips.push(*operating_header.parent_hash());
frontier_backend
.meta()
.write_current_syncing_tips(current_syncing_tips)?;
Ok(true)
}
}

Expand All @@ -155,7 +158,7 @@ where
let mut synced_any = false;

for _ in 0..limit {
synced_any = synced_any || sync_one_level(client, substrate_backend, frontier_backend)?;
synced_any = synced_any || sync_one_block(client, substrate_backend, frontier_backend)?;
}

Ok(synced_any)
Expand Down
172 changes: 90 additions & 82 deletions frame/dvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ use dp_evm::CallOrCreateInfo;
use dp_storage::PALLET_ETHEREUM_SCHEMA;
pub use dvm_rpc_runtime_api::TransactionStatus;
// --- substrate ---
use frame_support::ensure;
use frame_support::traits::Currency;
use frame_support::{
decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResultWithPostInfo,
traits::FindAuthor, traits::Get, weights::Weight,
};
use frame_support::{ensure, traits::UnfilteredDispatchable};
use frame_system::{ensure_none, RawOrigin};
use frame_system::ensure_none;
use sp_runtime::{
generic::DigestItem,
traits::{Saturating, UniqueSaturatedInto},
Expand Down Expand Up @@ -162,85 +162,7 @@ decl_module! {
fn transact(origin, transaction: ethereum::Transaction) -> DispatchResultWithPostInfo {
ensure_none(origin)?;

ensure!(
dp_consensus::find_pre_log(&frame_system::Module::<T>::digest()).is_err(),
Error::<T>::PreLogExists,
);

let source = Self::recover_signer(&transaction)
.ok_or_else(|| Error::<T>::InvalidSignature)?;

let transaction_hash = H256::from_slice(
Keccak256::digest(&rlp::encode(&transaction)).as_slice()
);
let transaction_index = Pending::get().len() as u32;

let (to, contract_address, info) = Self::execute(
source,
transaction.input.clone(),
transaction.value,
transaction.gas_limit,
Some(transaction.gas_price),
Some(transaction.nonce),
transaction.action,
None,
)?;

let (reason, status, used_gas) = match info {
CallOrCreateInfo::Call(info) => {
(info.exit_reason, TransactionStatus {
transaction_hash,
transaction_index,
from: source,
to,
contract_address: None,
logs: info.logs.clone(),
logs_bloom: {
let mut bloom: Bloom = Bloom::default();
Self::logs_bloom(
info.logs,
&mut bloom
);
bloom
},
}, info.used_gas)
},
CallOrCreateInfo::Create(info) => {
(info.exit_reason, TransactionStatus {
transaction_hash,
transaction_index,
from: source,
to,
contract_address: Some(info.value),
logs: info.logs.clone(),
logs_bloom: {
let mut bloom: Bloom = Bloom::default();
Self::logs_bloom(
info.logs,
&mut bloom
);
bloom
},
}, info.used_gas)
},
};

let receipt = ethereum::Receipt {
state_root: match reason {
ExitReason::Succeed(_) => H256::from_low_u64_be(1),
ExitReason::Error(_) => H256::from_low_u64_le(0),
ExitReason::Revert(_) => H256::from_low_u64_le(0),
ExitReason::Fatal(_) => H256::from_low_u64_le(0),
},
used_gas,
logs_bloom: status.clone().logs_bloom,
logs: status.clone().logs,
};

Pending::append((transaction, status, receipt));

Self::deposit_event(Event::Executed(source, contract_address.unwrap_or_default(), transaction_hash, reason));
Ok(Some(T::GasWeightMapping::gas_to_weight(used_gas.unique_saturated_into())).into())
Self::do_transact(transaction)
}

fn on_finalize(_block_number: T::BlockNumber) {
Expand All @@ -255,7 +177,7 @@ decl_module! {
let PreLog::Block(block) = log;

for transaction in block.transactions {
let _ = Call::<T>::transact(transaction).dispatch_bypass_filter(RawOrigin::None.into());
Self::do_transact(transaction).expect("pre-block transaction verification failed; the block cannot be built");
}
}
0
Expand Down Expand Up @@ -429,6 +351,92 @@ impl<T: Config> Module<T> {
}
}

fn do_transact(transaction: ethereum::Transaction) -> DispatchResultWithPostInfo {
ensure!(
dp_consensus::find_pre_log(&frame_system::Module::<T>::digest()).is_err(),
Error::<T>::PreLogExists,
);
let source =
Self::recover_signer(&transaction).ok_or_else(|| Error::<T>::InvalidSignature)?;

let transaction_hash =
H256::from_slice(Keccak256::digest(&rlp::encode(&transaction)).as_slice());
let transaction_index = Pending::get().len() as u32;

let (to, contract_address, info) = Self::execute(
source,
transaction.input.clone(),
transaction.value,
transaction.gas_limit,
Some(transaction.gas_price),
Some(transaction.nonce),
transaction.action,
None,
)?;

let (reason, status, used_gas) = match info {
CallOrCreateInfo::Call(info) => (
info.exit_reason,
TransactionStatus {
transaction_hash,
transaction_index,
from: source,
to,
contract_address: None,
logs: info.logs.clone(),
logs_bloom: {
let mut bloom: Bloom = Bloom::default();
Self::logs_bloom(info.logs, &mut bloom);
bloom
},
},
info.used_gas,
),
CallOrCreateInfo::Create(info) => (
info.exit_reason,
TransactionStatus {
transaction_hash,
transaction_index,
from: source,
to,
contract_address: Some(info.value),
logs: info.logs.clone(),
logs_bloom: {
let mut bloom: Bloom = Bloom::default();
Self::logs_bloom(info.logs, &mut bloom);
bloom
},
},
info.used_gas,
),
};

let receipt = ethereum::Receipt {
state_root: match reason {
ExitReason::Succeed(_) => H256::from_low_u64_be(1),
ExitReason::Error(_) => H256::from_low_u64_le(0),
ExitReason::Revert(_) => H256::from_low_u64_le(0),
ExitReason::Fatal(_) => H256::from_low_u64_le(0),
},
used_gas,
logs_bloom: status.clone().logs_bloom,
logs: status.clone().logs,
};

Pending::append((transaction, status, receipt));

Self::deposit_event(Event::Executed(
source,
contract_address.unwrap_or_default(),
transaction_hash,
reason,
));
Ok(Some(T::GasWeightMapping::gas_to_weight(
used_gas.unique_saturated_into(),
))
.into())
}

/// Get the author using the FindAuthor trait.
pub fn find_author() -> H160 {
let digest = <frame_system::Module<T>>::digest();
Expand Down
Loading

0 comments on commit 48f7efd

Please sign in to comment.