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

Dvm update from 304 #559

Merged
merged 4 commits into from
Mar 23, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
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 @@ -163,85 +163,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 @@ -256,7 +178,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 @@ -425,6 +347,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