v2.6.3-beta (#11040)
* add more tx tests (#11038) * Fix parallel transactions race-condition (#10995) * Add blake2_f precompile (#11017) * [trace] introduce trace failed to Ext (#11019) * Edit publish-onchain.sh to use https (#11016) * Fix deadlock in network-devp2p (#11013) * EIP 1108: Reduce alt_bn128 precompile gas costs (#11008) * xDai chain support and nodes list update (#10989) * EIP 2028: transaction gas lowered from 68 to 16 (#10987) * EIP-1344 Add CHAINID op-code (#10983) * manual publish jobs for releases, no changes for nightlies (#10977) * [blooms-db] Fix benchmarks (#10974) * Verify transaction against its block during import (#10954) * Better error message for rpc gas price errors (#10931) * Fix fork choice (#10837) * Fix compilation on recent nightlies (#10991)
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -54,7 +54,7 @@ pub use vm::{LastHashes, EnvInfo};
|
||||
pub use error::TransactionImportError;
|
||||
pub use verification::VerifierType;
|
||||
|
||||
mod traits;
|
||||
pub mod traits;
|
||||
|
||||
mod chain_notify;
|
||||
mod private_notify;
|
||||
|
||||
@@ -19,6 +19,8 @@ use machine::Machine;
|
||||
use types::header::{Header, ExtendedHeader};
|
||||
use block::ExecutedBlock;
|
||||
use error::Error;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
|
||||
/// `InstantSeal` params.
|
||||
#[derive(Default, Debug, PartialEq)]
|
||||
@@ -40,6 +42,7 @@ impl From<::ethjson::spec::InstantSealParams> for InstantSealParams {
|
||||
pub struct InstantSeal {
|
||||
params: InstantSealParams,
|
||||
machine: Machine,
|
||||
last_sealed_block: AtomicU64,
|
||||
}
|
||||
|
||||
impl InstantSeal {
|
||||
@@ -48,6 +51,7 @@ impl InstantSeal {
|
||||
InstantSeal {
|
||||
params,
|
||||
machine,
|
||||
last_sealed_block: AtomicU64::new(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,11 +66,19 @@ impl Engine for InstantSeal {
|
||||
fn sealing_state(&self) -> SealingState { SealingState::Ready }
|
||||
|
||||
fn generate_seal(&self, block: &ExecutedBlock, _parent: &Header) -> Seal {
|
||||
if block.transactions.is_empty() {
|
||||
Seal::None
|
||||
} else {
|
||||
Seal::Regular(Vec::new())
|
||||
if !block.transactions.is_empty() {
|
||||
let block_number = block.header.number();
|
||||
let last_sealed_block = self.last_sealed_block.load(Ordering::SeqCst);
|
||||
// Return a regular seal if the given block is _higher_ than
|
||||
// the last sealed one
|
||||
if block_number > last_sealed_block {
|
||||
let prev_last_sealed_block = self.last_sealed_block.compare_and_swap(last_sealed_block, block_number, Ordering::SeqCst);
|
||||
if prev_last_sealed_block == last_sealed_block {
|
||||
return Seal::Regular(Vec::new())
|
||||
}
|
||||
}
|
||||
}
|
||||
Seal::None
|
||||
}
|
||||
|
||||
fn verify_local_seal(&self, _header: &Header) -> Result<(), Error> {
|
||||
|
||||
@@ -57,6 +57,11 @@ pub fn new_poanet<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/poacore.json"))
|
||||
}
|
||||
|
||||
/// Create a new xDai mainnet chain spec.
|
||||
pub fn new_xdai<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/xdai.json"))
|
||||
}
|
||||
|
||||
/// Create a new Volta mainnet chain spec.
|
||||
pub fn new_volta<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/volta.json"))
|
||||
|
||||
@@ -396,7 +396,8 @@ impl<'a> CallCreateExecutive<'a> {
|
||||
let default = [];
|
||||
let data = if let Some(ref d) = params.data { d as &[u8] } else { &default as &[u8] };
|
||||
|
||||
let cost = builtin.cost(data);
|
||||
// NOTE(niklasad1): block number is used by `builtin alt_bn128 ops` to enable eip1108
|
||||
let cost = builtin.cost(data, self.info.number);
|
||||
if cost <= params.gas {
|
||||
let mut builtin_out_buffer = Vec::new();
|
||||
let result = {
|
||||
@@ -406,7 +407,7 @@ impl<'a> CallCreateExecutive<'a> {
|
||||
if let Err(e) = result {
|
||||
state.revert_to_checkpoint();
|
||||
|
||||
Err(e.into())
|
||||
Err(vm::Error::BuiltIn(e))
|
||||
} else {
|
||||
state.discard_checkpoint();
|
||||
|
||||
|
||||
@@ -400,6 +400,10 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
self.env_info
|
||||
}
|
||||
|
||||
fn chain_id(&self) -> u64 {
|
||||
self.machine.params().chain_id
|
||||
}
|
||||
|
||||
fn depth(&self) -> usize {
|
||||
self.depth
|
||||
}
|
||||
@@ -420,6 +424,10 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
self.vm_tracer.trace_prepare_execute(pc, instruction, gas_cost, mem_written, store_written)
|
||||
}
|
||||
|
||||
fn trace_failed(&mut self) {
|
||||
self.vm_tracer.trace_failed();
|
||||
}
|
||||
|
||||
fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem: &[u8]) {
|
||||
self.vm_tracer.trace_executed(gas_used, stack_push, mem)
|
||||
}
|
||||
|
||||
@@ -211,6 +211,8 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B>
|
||||
self.ext.env_info()
|
||||
}
|
||||
|
||||
fn chain_id(&self) -> u64 { 0 }
|
||||
|
||||
fn depth(&self) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
@@ -55,13 +55,13 @@
|
||||
|
||||
extern crate account_db;
|
||||
extern crate ansi_term;
|
||||
extern crate bn;
|
||||
extern crate common_types as types;
|
||||
extern crate crossbeam_utils;
|
||||
extern crate ethabi;
|
||||
extern crate ethash;
|
||||
extern crate ethcore_blockchain as blockchain;
|
||||
extern crate ethcore_bloom_journal as bloom_journal;
|
||||
extern crate ethcore_builtin as builtin;
|
||||
extern crate ethcore_call_contract as call_contract;
|
||||
extern crate ethcore_db as db;
|
||||
extern crate ethcore_io as io;
|
||||
@@ -83,10 +83,8 @@ extern crate len_caching_lock;
|
||||
extern crate lru_cache;
|
||||
extern crate memory_cache;
|
||||
extern crate memory_db;
|
||||
extern crate num;
|
||||
extern crate num_cpus;
|
||||
extern crate parity_bytes as bytes;
|
||||
extern crate parity_crypto;
|
||||
extern crate parity_snappy as snappy;
|
||||
extern crate parking_lot;
|
||||
extern crate pod_account;
|
||||
@@ -153,7 +151,6 @@ extern crate fetch;
|
||||
extern crate parity_runtime;
|
||||
|
||||
pub mod block;
|
||||
pub mod builtin;
|
||||
pub mod client;
|
||||
pub mod engines;
|
||||
pub mod error;
|
||||
|
||||
@@ -467,7 +467,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn should_disallow_unsigned_transactions() {
|
||||
let rlp = "ea80843b9aca0083015f90948921ebb5f79e9e3920abe571004d0b1d5119c154865af3107a400080038080".into();
|
||||
let rlp = "ea80843b9aca0083015f90948921ebb5f79e9e3920abe571004d0b1d5119c154865af3107a400080038080";
|
||||
let transaction: UnverifiedTransaction = ::rlp::decode(&::rustc_hex::FromHex::from_hex(rlp).unwrap()).unwrap();
|
||||
let spec = ::ethereum::new_ropsten_test();
|
||||
let ethparams = get_default_ethash_extensions();
|
||||
|
||||
@@ -33,7 +33,7 @@ use futures::sync::mpsc;
|
||||
use io::IoChannel;
|
||||
use miner::filter_options::{FilterOptions, FilterOperator};
|
||||
use miner::pool_client::{PoolClient, CachedNonceClient, NonceCache};
|
||||
use miner;
|
||||
use miner::{self, MinerService};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use rayon::prelude::*;
|
||||
use types::transaction::{
|
||||
@@ -54,6 +54,7 @@ use client::{
|
||||
BlockChain, ChainInfo, BlockProducer, SealedBlockImporter, Nonce, TransactionInfo, TransactionId
|
||||
};
|
||||
use client::{BlockId, ClientIoMessage};
|
||||
use client::traits::EngineClient;
|
||||
use engines::{Engine, Seal, SealingState, EngineSigner};
|
||||
use error::Error;
|
||||
use executed::ExecutionError;
|
||||
@@ -509,7 +510,7 @@ impl Miner {
|
||||
let sender = transaction.sender();
|
||||
|
||||
// Re-verify transaction again vs current state.
|
||||
let result = client.verify_signed(&transaction)
|
||||
let result = client.verify_for_pending_block(&transaction, &open_block.header)
|
||||
.map_err(|e| e.into())
|
||||
.and_then(|_| {
|
||||
open_block.push_transaction(transaction, None)
|
||||
@@ -855,9 +856,9 @@ impl Miner {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Prepare pending block, check whether sealing is needed, and then update sealing.
|
||||
fn prepare_and_update_sealing<C: miner::BlockChainClient>(&self, chain: &C) {
|
||||
use miner::MinerService;
|
||||
match self.engine.sealing_state() {
|
||||
SealingState::Ready => {
|
||||
self.maybe_enable_sealing();
|
||||
@@ -1414,6 +1415,9 @@ impl miner::MinerService for Miner {
|
||||
service_transaction_checker.as_ref(),
|
||||
);
|
||||
queue.cull(client);
|
||||
if is_internal_import {
|
||||
chain.update_sealing();
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(e) = channel.send(ClientIoMessage::execute(cull)) {
|
||||
@@ -1421,8 +1425,12 @@ impl miner::MinerService for Miner {
|
||||
}
|
||||
} else {
|
||||
self.transaction_queue.cull(client);
|
||||
if is_internal_import {
|
||||
self.update_sealing(chain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref service_transaction_checker) = self.service_transaction_checker {
|
||||
match service_transaction_checker.refresh_cache(chain) {
|
||||
Ok(true) => {
|
||||
|
||||
@@ -113,11 +113,13 @@ impl<'a, C: 'a> PoolClient<'a, C> where
|
||||
}
|
||||
}
|
||||
|
||||
/// Verifies if signed transaction is executable.
|
||||
/// Verifies transaction against its block (before its import into this block)
|
||||
/// Also Verifies if signed transaction is executable.
|
||||
///
|
||||
/// This should perform any verifications that rely on chain status.
|
||||
pub fn verify_signed(&self, tx: &SignedTransaction) -> Result<(), transaction::Error> {
|
||||
self.engine.machine().verify_transaction(&tx, &self.best_block_header, self.chain)
|
||||
pub fn verify_for_pending_block(&self, tx: &SignedTransaction, header: &Header) -> Result<(), transaction::Error> {
|
||||
self.engine.machine().verify_transaction_basic(tx, header)?;
|
||||
self.engine.machine().verify_transaction(tx, &self.best_block_header, self.chain)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,8 +140,7 @@ impl<'a, C: 'a> pool::client::Client for PoolClient<'a, C> where
|
||||
self.engine.verify_transaction_basic(&tx, &self.best_block_header)?;
|
||||
let tx = self.engine.verify_transaction_unordered(tx, &self.best_block_header)?;
|
||||
|
||||
self.verify_signed(&tx)?;
|
||||
|
||||
self.engine.machine().verify_transaction(&tx, &self.best_block_header, self.chain)?;
|
||||
Ok(tx)
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ fn fmt_err<F: ::std::fmt::Display>(f: F) -> String {
|
||||
/// we define a "bugfix" hard fork as any hard fork which
|
||||
/// you would put on-by-default in a new chain.
|
||||
#[derive(Debug, PartialEq, Default)]
|
||||
#[cfg_attr(test, derive(Clone))]
|
||||
#[cfg_attr(any(test, feature = "test-helpers"), derive(Clone))]
|
||||
pub struct CommonParams {
|
||||
/// Account start nonce.
|
||||
pub account_start_nonce: U256,
|
||||
@@ -123,6 +123,10 @@ pub struct CommonParams {
|
||||
pub eip1283_disable_transition: BlockNumber,
|
||||
/// Number of first block where EIP-1014 rules begin.
|
||||
pub eip1014_transition: BlockNumber,
|
||||
/// Number of first block where EIP-1344 rules begin: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1344.md
|
||||
pub eip1344_transition: BlockNumber,
|
||||
/// Number of first block where EIP-2028 rules begin.
|
||||
pub eip2028_transition: BlockNumber,
|
||||
/// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin.
|
||||
pub dust_protection_transition: BlockNumber,
|
||||
/// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled.
|
||||
@@ -189,7 +193,11 @@ impl CommonParams {
|
||||
schedule.have_return_data = block_number >= self.eip211_transition;
|
||||
schedule.have_bitwise_shifting = block_number >= self.eip145_transition;
|
||||
schedule.have_extcodehash = block_number >= self.eip1052_transition;
|
||||
schedule.have_chain_id = block_number >= self.eip1344_transition;
|
||||
schedule.eip1283 = block_number >= self.eip1283_transition && !(block_number >= self.eip1283_disable_transition);
|
||||
if block_number >= self.eip2028_transition {
|
||||
schedule.tx_data_non_zero_gas = 16;
|
||||
}
|
||||
if block_number >= self.eip210_transition {
|
||||
schedule.blockhash_gas = 800;
|
||||
}
|
||||
@@ -308,6 +316,14 @@ impl From<ethjson::spec::Params> for CommonParams {
|
||||
BlockNumber::max_value,
|
||||
Into::into,
|
||||
),
|
||||
eip1344_transition: p.eip1344_transition.map_or_else(
|
||||
BlockNumber::max_value,
|
||||
Into::into,
|
||||
),
|
||||
eip2028_transition: p.eip2028_transition.map_or_else(
|
||||
BlockNumber::max_value,
|
||||
Into::into,
|
||||
),
|
||||
dust_protection_transition: p.dust_protection_transition.map_or_else(
|
||||
BlockNumber::max_value,
|
||||
Into::into,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
//! Simple executive tracer.
|
||||
|
||||
use std::cmp::min;
|
||||
use ethereum_types::{U256, Address};
|
||||
use vm::{Error as VmError, ActionParams};
|
||||
use log::{debug, warn};
|
||||
@@ -194,12 +195,16 @@ impl Tracer for ExecutiveTracer {
|
||||
}
|
||||
}
|
||||
|
||||
struct TraceData {
|
||||
mem_written: Option<(usize, usize)>,
|
||||
store_written: Option<(U256, U256)>,
|
||||
}
|
||||
|
||||
/// Simple VM tracer. Traces all operations.
|
||||
pub struct ExecutiveVMTracer {
|
||||
data: VMTrace,
|
||||
depth: usize,
|
||||
last_mem_written: Option<(usize, usize)>,
|
||||
last_store_written: Option<(U256, U256)>,
|
||||
trace_stack: Vec<TraceData>,
|
||||
}
|
||||
|
||||
impl ExecutiveVMTracer {
|
||||
@@ -213,8 +218,7 @@ impl ExecutiveVMTracer {
|
||||
subs: vec![],
|
||||
},
|
||||
depth: 0,
|
||||
last_mem_written: None,
|
||||
last_store_written: None,
|
||||
trace_stack: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,30 +245,27 @@ impl VMTracer for ExecutiveVMTracer {
|
||||
executed: None,
|
||||
});
|
||||
});
|
||||
self.last_mem_written = mem_written;
|
||||
self.last_store_written = store_written;
|
||||
self.trace_stack.push(TraceData { mem_written, store_written });
|
||||
}
|
||||
|
||||
fn trace_failed(&mut self) {
|
||||
let _ = self.trace_stack.pop().expect("pushed in trace_prepare_execute; qed");
|
||||
}
|
||||
|
||||
fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem: &[u8]) {
|
||||
let mem_diff = self.last_mem_written.take().map(|(o, s)| {
|
||||
let TraceData { mem_written, store_written } = self.trace_stack.pop().expect("pushed in trace_prepare_execute; qed");
|
||||
let mem_diff = mem_written.map(|(o, s)| {
|
||||
if o + s > mem.len() {
|
||||
warn!(
|
||||
target: "trace",
|
||||
"Last mem written is out of bounds {} (mem is {})",
|
||||
o + s,
|
||||
mem.len(),
|
||||
);
|
||||
(o, &[][..])
|
||||
} else {
|
||||
(o, &(mem[o..o+s]))
|
||||
warn!(target: "trace", "mem_written is out of bounds");
|
||||
}
|
||||
(o, &mem[min(mem.len(), o)..min(o + s, mem.len())])
|
||||
});
|
||||
let store_diff = self.last_store_written.take();
|
||||
let store_diff = store_written;
|
||||
Self::with_trace_in_depth(&mut self.data, self.depth, move |trace| {
|
||||
let ex = VMExecutedOperation {
|
||||
gas_used: gas_used,
|
||||
stack_push: stack_push.iter().cloned().collect(),
|
||||
mem_diff: mem_diff.map(|(s, r)| MemoryDiff { offset: s, data: r.iter().cloned().collect() }),
|
||||
stack_push: stack_push.to_vec(),
|
||||
mem_diff: mem_diff.map(|(s, r)| MemoryDiff { offset: s, data: r.to_vec() }),
|
||||
store_diff: store_diff.map(|(l, v)| StorageDiff { location: l, value: v }),
|
||||
};
|
||||
trace.operations.last_mut().expect("trace_executed is always called after a trace_prepare_execute; trace.operations cannot be empty; qed").executed = Some(ex);
|
||||
|
||||
@@ -85,6 +85,9 @@ pub trait VMTracer: Send {
|
||||
/// Trace the preparation to execute a single valid instruction.
|
||||
fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _gas_cost: U256, _mem_written: Option<(usize, usize)>, _store_written: Option<(U256, U256)>) {}
|
||||
|
||||
/// Trace the execution failure of a single instruction.
|
||||
fn trace_failed(&mut self) {}
|
||||
|
||||
/// Trace the finalised execution of a single valid instruction.
|
||||
fn trace_executed(&mut self, _gas_used: U256, _stack_push: &[U256], _mem: &[u8]) {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user