[beta] Backports (#6497)

* Fix slow balances (#6471)

* Update token updates

* Update token info fetching

* Update logger

* Minor fixes to updates and notifications for balances

* Use Pubsub

* Fix timeout.

* Use pubsub for status.

* Fix signer subscription.

* Process tokens in chunks.

* Fix tokens loaded by chunks

* Linting

* Dispatch tokens asap

* Fix chunks processing.

* Better filter options

* Parallel log fetching.

* Fix signer polling.

* Fix initial block query.

* Token balances updates : the right(er) way

* Better tokens info fetching

* Fixes in token data fetching

* Only fetch what's needed (tokens)

* Fix linting issues

* Revert "Transaction permissioning (#6441)"

This reverts commit eed0e8b03a.

* Revert "Revert "Transaction permissioning (#6441)""

This reverts commit 8f96415e58dde652e5828706eb2639d43416f448.

* Update wasm-tests.

* Fixing balances fetching

* Fix requests tracking in UI

* Fix request watching

* Update the Logger

* PR Grumbles Fixes

* PR Grumbles fixes

* Linting...

* eth_call returns output of contract creations (#6420)

* eth_call returns output of contract creations

* Fix parameters order.

* Save outputs for light client as well.

* Don't accept transactions above block gas limit.

* Expose health status over RPC (#6274)

* Node-health to a separate crate.

* Initialize node_health outside of dapps.

* Expose health over RPC.

* Bring back 412 and fix JS.

* Add health to workspace and tests.

* Fix compilation without default features.

* Fix borked merge.

* Revert to generics to avoid virtual calls.

* Fix node-health tests.

* Add missing trailing comma.

* Fixing/removing failing JS tests.

* do not activate genesis epoch in immediate transition validator contract (#6349)

* Fix memory tracing.

* Add test to cover that.

* ensure balances of constructor accounts are kept

* test balance of spec-constructed account is kept
This commit is contained in:
Tomasz Drwięga
2017-09-11 18:01:02 +02:00
committed by Gav Wood
parent 6ef9780b81
commit 980418898a
95 changed files with 2537 additions and 1245 deletions

View File

@@ -36,6 +36,7 @@ use db::{self, Writable, Readable, CacheUpdatePolicy};
use cache_manager::CacheManager;
use encoded;
use engines::epoch::{Transition as EpochTransition, PendingTransition as PendingEpochTransition};
use rayon::prelude::*;
const LOG_BLOOMS_LEVELS: usize = 3;
const LOG_BLOOMS_ELEMENTS_PER_INDEX: usize = 16;
@@ -143,7 +144,7 @@ pub trait BlockProvider {
/// Returns logs matching given filter.
fn logs<F>(&self, blocks: Vec<BlockNumber>, matches: F, limit: Option<usize>) -> Vec<LocalizedLogEntry>
where F: Fn(&LogEntry) -> bool, Self: Sized;
where F: Fn(&LogEntry) -> bool + Send + Sync, Self: Sized;
}
macro_rules! otry {
@@ -354,50 +355,56 @@ impl BlockProvider for BlockChain {
}
fn logs<F>(&self, mut blocks: Vec<BlockNumber>, matches: F, limit: Option<usize>) -> Vec<LocalizedLogEntry>
where F: Fn(&LogEntry) -> bool, Self: Sized {
where F: Fn(&LogEntry) -> bool + Send + Sync, Self: Sized {
// sort in reverse order
blocks.sort_by(|a, b| b.cmp(a));
let mut log_index = 0;
let mut logs = blocks.into_iter()
.filter_map(|number| self.block_hash(number).map(|hash| (number, hash)))
.filter_map(|(number, hash)| self.block_receipts(&hash).map(|r| (number, hash, r.receipts)))
.filter_map(|(number, hash, receipts)| self.block_body(&hash).map(|ref b| (number, hash, receipts, b.transaction_hashes())))
.flat_map(|(number, hash, mut receipts, mut hashes)| {
if receipts.len() != hashes.len() {
warn!("Block {} ({}) has different number of receipts ({}) to transactions ({}). Database corrupt?", number, hash, receipts.len(), hashes.len());
assert!(false);
}
log_index = receipts.iter().fold(0, |sum, receipt| sum + receipt.logs.len());
let mut logs = blocks
.chunks(128)
.flat_map(move |blocks_chunk| {
blocks_chunk.into_par_iter()
.filter_map(|number| self.block_hash(*number).map(|hash| (*number, hash)))
.filter_map(|(number, hash)| self.block_receipts(&hash).map(|r| (number, hash, r.receipts)))
.filter_map(|(number, hash, receipts)| self.block_body(&hash).map(|ref b| (number, hash, receipts, b.transaction_hashes())))
.flat_map(|(number, hash, mut receipts, mut hashes)| {
if receipts.len() != hashes.len() {
warn!("Block {} ({}) has different number of receipts ({}) to transactions ({}). Database corrupt?", number, hash, receipts.len(), hashes.len());
assert!(false);
}
let mut log_index = receipts.iter().fold(0, |sum, receipt| sum + receipt.logs.len());
let receipts_len = receipts.len();
hashes.reverse();
receipts.reverse();
receipts.into_iter()
.map(|receipt| receipt.logs)
.zip(hashes)
.enumerate()
.flat_map(move |(index, (mut logs, tx_hash))| {
let current_log_index = log_index;
let no_of_logs = logs.len();
log_index -= no_of_logs;
logs.reverse();
logs.into_iter()
let receipts_len = receipts.len();
hashes.reverse();
receipts.reverse();
receipts.into_iter()
.map(|receipt| receipt.logs)
.zip(hashes)
.enumerate()
.map(move |(i, log)| LocalizedLogEntry {
entry: log,
block_hash: hash,
block_number: number,
transaction_hash: tx_hash,
// iterating in reverse order
transaction_index: receipts_len - index - 1,
transaction_log_index: no_of_logs - i - 1,
log_index: current_log_index - i - 1,
.flat_map(move |(index, (mut logs, tx_hash))| {
let current_log_index = log_index;
let no_of_logs = logs.len();
log_index -= no_of_logs;
logs.reverse();
logs.into_iter()
.enumerate()
.map(move |(i, log)| LocalizedLogEntry {
entry: log,
block_hash: hash,
block_number: number,
transaction_hash: tx_hash,
// iterating in reverse order
transaction_index: receipts_len - index - 1,
transaction_log_index: no_of_logs - i - 1,
log_index: current_log_index - i - 1,
})
})
.filter(|log_entry| matches(&log_entry.entry))
.take(limit.unwrap_or(::std::usize::MAX))
.collect::<Vec<_>>()
})
.collect::<Vec<_>>()
})
.filter(|log_entry| matches(&log_entry.entry))
.take(limit.unwrap_or(::std::usize::MAX))
.collect::<Vec<LocalizedLogEntry>>();
logs.reverse();

View File

@@ -24,7 +24,7 @@ use time::precise_time_ns;
// util
use util::{Bytes, PerfTimer, Itertools, Mutex, RwLock, MutexGuard, Hashable};
use util::{journaldb, DBValue, TrieFactory, Trie};
use util::{U256, H256, Address, H2048};
use util::{U256, H256, Address};
use util::trie::TrieSpec;
use util::kvdb::*;
@@ -748,7 +748,7 @@ impl Client {
self.factories.clone(),
).expect("state known to be available for just-imported block; qed");
let options = TransactOptions { tracing: false, vm_tracing: false, check_nonce: false };
let options = TransactOptions::with_no_tracing().dont_check_nonce().save_output_from_contract();
let res = Executive::new(&mut state, &env_info, &*self.engine)
.transact(&transaction, options);
@@ -912,7 +912,7 @@ impl Client {
_ => {},
}
let block_number = match self.block_number(id.clone()) {
let block_number = match self.block_number(id) {
Some(num) => num,
None => return None,
};
@@ -1111,6 +1111,15 @@ impl Client {
data: data,
}.fake_sign(from)
}
fn block_number_ref(&self, id: &BlockId) -> Option<BlockNumber> {
match *id {
BlockId::Number(number) => Some(number),
BlockId::Hash(ref hash) => self.chain.read().block_number(hash),
BlockId::Earliest => Some(0),
BlockId::Latest | BlockId::Pending => Some(self.chain.read().best_block_number()),
}
}
}
impl snapshot::DatabaseRestore for Client {
@@ -1143,7 +1152,9 @@ impl BlockChainClient for Client {
let mut state = self.state_at(block).ok_or(CallError::StatePruned)?;
let original_state = if analytics.state_diffing { Some(state.clone()) } else { None };
let options = TransactOptions { tracing: analytics.transaction_tracing, vm_tracing: analytics.vm_tracing, check_nonce: false };
let options = TransactOptions::new(analytics.transaction_tracing, analytics.vm_tracing)
.dont_check_nonce()
.save_output_from_contract();
let mut ret = Executive::new(&mut state, &env_info, &*self.engine).transact_virtual(t, options)?;
// TODO gav move this into Executive.
@@ -1166,7 +1177,7 @@ impl BlockChainClient for Client {
// that's just a copy of the state.
let original_state = self.state_at(block).ok_or(CallError::StatePruned)?;
let sender = t.sender();
let options = TransactOptions { tracing: true, vm_tracing: false, check_nonce: false };
let options = TransactOptions::with_tracing().dont_check_nonce();
let cond = |gas| {
let mut tx = t.as_unsigned().clone();
@@ -1231,7 +1242,9 @@ impl BlockChainClient for Client {
return Err(CallError::TransactionNotFound);
}
let options = TransactOptions { tracing: analytics.transaction_tracing, vm_tracing: analytics.vm_tracing, check_nonce: false };
let options = TransactOptions::new(analytics.transaction_tracing, analytics.vm_tracing)
.dont_check_nonce()
.save_output_from_contract();
const PROOF: &'static str = "Transactions fetched from blockchain; blockchain transactions are valid; qed";
let rest = txs.split_off(address.index);
for t in txs {
@@ -1308,12 +1321,7 @@ impl BlockChainClient for Client {
}
fn block_number(&self, id: BlockId) -> Option<BlockNumber> {
match id {
BlockId::Number(number) => Some(number),
BlockId::Hash(ref hash) => self.chain.read().block_number(hash),
BlockId::Earliest => Some(0),
BlockId::Latest | BlockId::Pending => Some(self.chain.read().best_block_number()),
}
self.block_number_ref(&id)
}
fn block_body(&self, id: BlockId) -> Option<encoded::Body> {
@@ -1566,16 +1574,17 @@ impl BlockChainClient for Client {
self.engine.additional_params().into_iter().collect()
}
fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockId, to_block: BlockId) -> Option<Vec<BlockNumber>> {
match (self.block_number(from_block), self.block_number(to_block)) {
(Some(from), Some(to)) => Some(self.chain.read().blocks_with_bloom(bloom, from, to)),
_ => None
}
}
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry> {
let (from, to) = match (self.block_number_ref(&filter.from_block), self.block_number_ref(&filter.to_block)) {
(Some(from), Some(to)) => (from, to),
_ => return Vec::new(),
};
let chain = self.chain.read();
let blocks = filter.bloom_possibilities().iter()
.filter_map(|bloom| self.blocks_with_bloom(bloom, filter.from_block.clone(), filter.to_block.clone()))
.map(move |bloom| {
chain.blocks_with_bloom(bloom, from, to)
})
.flat_map(|m| m)
// remove duplicate elements
.collect::<HashSet<u64>>()
@@ -1894,7 +1903,7 @@ impl ProvingBlockChainClient for Client {
let backend = state::backend::Proving::new(jdb.as_hashdb_mut());
let mut state = state.replace_backend(backend);
let options = TransactOptions { tracing: false, vm_tracing: false, check_nonce: false };
let options = TransactOptions::with_no_tracing().dont_check_nonce().save_output_from_contract();
let res = Executive::new(&mut state, &env_info, &*self.engine).transact(&transaction, options);
match res {

View File

@@ -486,10 +486,6 @@ impl BlockChainClient for TestBlockChainClient {
self.receipts.read().get(&id).cloned()
}
fn blocks_with_bloom(&self, _bloom: &H2048, _from_block: BlockId, _to_block: BlockId) -> Option<Vec<BlockNumber>> {
unimplemented!();
}
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry> {
let mut logs = self.logs.read().clone();
let len = logs.len();

View File

@@ -33,7 +33,7 @@ use trace::LocalizedTrace;
use transaction::{LocalizedTransaction, PendingTransaction, SignedTransaction};
use verification::queue::QueueInfo as BlockQueueInfo;
use util::{U256, Address, H256, H2048, Bytes, Itertools};
use util::{U256, Address, H256, Bytes, Itertools};
use util::hashdb::DBValue;
use types::ids::*;
@@ -175,9 +175,6 @@ pub trait BlockChainClient : Sync + Send {
/// Get the best block header.
fn best_block_header(&self) -> encoded::Header;
/// Returns numbers of blocks containing given bloom.
fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockId, to_block: BlockId) -> Option<Vec<BlockNumber>>;
/// Returns logs matching given filter.
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry>;

View File

@@ -538,7 +538,9 @@ impl Engine for AuthorityRound {
let parent_hash = block.fields().header.parent_hash().clone();
::engines::common::push_last_hash(block, last_hashes.clone(), self, &parent_hash)?;
if !epoch_begin { return Ok(()) }
// with immediate transitions, we don't use the epoch mechanism anyway.
// the genesis is always considered an epoch, but we ignore it intentionally.
if self.immediate_transitions || !epoch_begin { return Ok(()) }
// genesis is never a new block, but might as well check.
let header = block.fields().header.clone();

View File

@@ -72,9 +72,75 @@ pub struct TransactOptions {
pub vm_tracing: bool,
/// Check transaction nonce before execution.
pub check_nonce: bool,
/// Records the output from init contract calls.
pub output_from_init_contract: bool,
}
pub fn executor<E>(engine: &E, vm_factory: &Factory, params: &ActionParams)
impl TransactOptions {
/// Create new `TransactOptions` with given tracer and VM tracer.
pub fn new(tracing: bool, vm_tracing: bool) -> Self {
TransactOptions {
tracing,
vm_tracing,
check_nonce: true,
output_from_init_contract: false,
}
}
/// Disables the nonce check
pub fn dont_check_nonce(mut self) -> Self {
self.check_nonce = false;
self
}
/// Saves the output from contract creation.
pub fn save_output_from_contract(mut self) -> Self {
self.output_from_init_contract = true;
self
}
/// Creates new `TransactOptions` with default tracing and VM tracing.
pub fn with_tracing_and_vm_tracing() -> Self {
TransactOptions {
tracing: true,
vm_tracing: true,
check_nonce: true,
output_from_init_contract: false,
}
}
/// Creates new `TransactOptions` with default tracing and no VM tracing.
pub fn with_tracing() -> Self {
TransactOptions {
tracing: true,
vm_tracing: false,
check_nonce: true,
output_from_init_contract: false,
}
}
/// Creates new `TransactOptions` with no tracing and default VM tracing.
pub fn with_vm_tracing() -> Self {
TransactOptions {
tracing: false,
vm_tracing: true,
check_nonce: true,
output_from_init_contract: false,
}
}
/// Creates new `TransactOptions` without any tracing.
pub fn with_no_tracing() -> Self {
TransactOptions {
tracing: false,
vm_tracing: false,
check_nonce: true,
output_from_init_contract: false,
}
}
}
pub fn executor<E>(engine: &E, vm_factory: &Factory, params: &ActionParams)
-> Box<evm::Evm> where E: Engine + ?Sized
{
if engine.supports_wasm() && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) {
@@ -137,14 +203,15 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
/// This function should be used to execute transaction.
pub fn transact(&'a mut self, t: &SignedTransaction, options: TransactOptions) -> Result<Executed, ExecutionError> {
let check = options.check_nonce;
let output = options.output_from_init_contract;
match options.tracing {
true => match options.vm_tracing {
true => self.transact_with_tracer(t, check, ExecutiveTracer::default(), ExecutiveVMTracer::toplevel()),
false => self.transact_with_tracer(t, check, ExecutiveTracer::default(), NoopVMTracer),
true => self.transact_with_tracer(t, check, output, ExecutiveTracer::default(), ExecutiveVMTracer::toplevel()),
false => self.transact_with_tracer(t, check, output, ExecutiveTracer::default(), NoopVMTracer),
},
false => match options.vm_tracing {
true => self.transact_with_tracer(t, check, NoopTracer, ExecutiveVMTracer::toplevel()),
false => self.transact_with_tracer(t, check, NoopTracer, NoopVMTracer),
true => self.transact_with_tracer(t, check, output, NoopTracer, ExecutiveVMTracer::toplevel()),
false => self.transact_with_tracer(t, check, output, NoopTracer, NoopVMTracer),
},
}
}
@@ -169,6 +236,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
&'a mut self,
t: &SignedTransaction,
check_nonce: bool,
output_from_create: bool,
mut tracer: T,
mut vm_tracer: V
) -> Result<Executed, ExecutionError> where T: Tracer, V: VMTracer {
@@ -237,7 +305,8 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
data: None,
call_type: CallType::None,
};
(self.create(params, &mut substate, &mut tracer, &mut vm_tracer), vec![])
let mut out = if output_from_create { Some(vec![]) } else { None };
(self.create(params, &mut substate, &mut out, &mut tracer, &mut vm_tracer), out.unwrap_or_else(Vec::new))
},
Action::Call(ref address) => {
let params = ActionParams {
@@ -430,6 +499,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
&mut self,
params: ActionParams,
substate: &mut Substate,
output: &mut Option<Bytes>,
tracer: &mut T,
vm_tracer: &mut V,
) -> evm::Result<(U256, ReturnData)> where T: Tracer, V: VMTracer {
@@ -471,7 +541,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
let mut subvmtracer = vm_tracer.prepare_subtrace(params.code.as_ref().expect("two ways into create (Externalities::create and Executive::transact_with_tracer); both place `Some(...)` `code` in `params`; qed"));
let res = {
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::InitContract(trace_output.as_mut()), &mut subtracer, &mut subvmtracer)
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::InitContract(output.as_mut().or(trace_output.as_mut())), &mut subtracer, &mut subvmtracer)
};
vm_tracer.done_subtrace(subvmtracer);
@@ -480,7 +550,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
Ok(ref res) => tracer.trace_create(
trace_info,
gas - res.gas_left,
trace_output,
trace_output.map(|data| output.as_ref().map(|out| out.to_vec()).unwrap_or(data)),
created,
subtracer.traces()
),
@@ -641,7 +711,7 @@ mod tests {
let (gas_left, _) = {
let mut ex = Executive::new(&mut state, &info, &engine);
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
assert_eq!(gas_left, U256::from(79_975));
@@ -699,7 +769,7 @@ mod tests {
let (gas_left, _) = {
let mut ex = Executive::new(&mut state, &info, &engine);
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
assert_eq!(gas_left, U256::from(62_976));
@@ -866,7 +936,7 @@ mod tests {
let (gas_left, _) = {
let mut ex = Executive::new(&mut state, &info, &engine);
ex.create(params.clone(), &mut substate, &mut tracer, &mut vm_tracer).unwrap()
ex.create(params.clone(), &mut substate, &mut None, &mut tracer, &mut vm_tracer).unwrap()
};
assert_eq!(gas_left, U256::from(96_776));
@@ -951,7 +1021,7 @@ mod tests {
let (gas_left, _) = {
let mut ex = Executive::new(&mut state, &info, &engine);
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
assert_eq!(gas_left, U256::from(62_976));
@@ -1002,7 +1072,7 @@ mod tests {
{
let mut ex = Executive::new(&mut state, &info, &engine);
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap();
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap();
}
assert_eq!(substate.contracts_created.len(), 1);
@@ -1138,7 +1208,7 @@ mod tests {
let executed = {
let mut ex = Executive::new(&mut state, &info, &engine);
let opts = TransactOptions { check_nonce: true, tracing: false, vm_tracing: false };
let opts = TransactOptions { check_nonce: true, tracing: false, vm_tracing: false, output_from_init_contract: false };
ex.transact(&t, opts).unwrap()
};
@@ -1175,7 +1245,7 @@ mod tests {
let res = {
let mut ex = Executive::new(&mut state, &info, &engine);
let opts = TransactOptions { check_nonce: true, tracing: false, vm_tracing: false };
let opts = TransactOptions { check_nonce: true, tracing: false, vm_tracing: false, output_from_init_contract: false };
ex.transact(&t, opts)
};
@@ -1208,7 +1278,7 @@ mod tests {
let res = {
let mut ex = Executive::new(&mut state, &info, &engine);
let opts = TransactOptions { check_nonce: true, tracing: false, vm_tracing: false };
let opts = TransactOptions { check_nonce: true, tracing: false, vm_tracing: false, output_from_init_contract: false };
ex.transact(&t, opts)
};
@@ -1241,7 +1311,7 @@ mod tests {
let res = {
let mut ex = Executive::new(&mut state, &info, &engine);
let opts = TransactOptions { check_nonce: true, tracing: false, vm_tracing: false };
let opts = TransactOptions { check_nonce: true, tracing: false, vm_tracing: false, output_from_init_contract: false };
ex.transact(&t, opts)
};
@@ -1275,7 +1345,7 @@ mod tests {
let result = {
let mut ex = Executive::new(&mut state, &info, &engine);
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer)
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer)
};
match result {

View File

@@ -219,7 +219,7 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth, self.static_flag);
// TODO: handle internal error separately
match ex.create(params, self.substate, self.tracer, self.vm_tracer) {
match ex.create(params, self.substate, &mut None, self.tracer, self.vm_tracer) {
Ok((gas_left, _)) => {
self.substate.contracts_created.push(address.clone());
ContractCreateResult::Created(address, gas_left)

View File

@@ -99,6 +99,7 @@ extern crate native_contracts;
extern crate num_cpus;
extern crate num;
extern crate rand;
extern crate rayon;
extern crate rlp;
extern crate rustc_hex;
extern crate rustc_serialize;

View File

@@ -742,7 +742,7 @@ impl MinerService for Miner {
state.add_balance(&sender, &(needed_balance - balance), CleanupMode::NoEmpty)
.map_err(ExecutionError::from)?;
}
let options = TransactOptions { tracing: analytics.transaction_tracing, vm_tracing: analytics.vm_tracing, check_nonce: false };
let options = TransactOptions { tracing: analytics.transaction_tracing, vm_tracing: analytics.vm_tracing, check_nonce: false, output_from_init_contract: true };
let mut ret = Executive::new(&mut state, &env_info, &*self.engine).transact(t, options)?;
// TODO gav move this into Executive.

View File

@@ -506,8 +506,6 @@ pub struct AccountDetails {
pub balance: U256,
}
/// Transactions with `gas > (gas_limit + gas_limit * Factor(in percents))` are not imported to the queue.
const GAS_LIMIT_HYSTERESIS: usize = 200; // (100/GAS_LIMIT_HYSTERESIS) %
/// Transaction with the same (sender, nonce) can be replaced only if
/// `new_gas_price > old_gas_price + old_gas_price >> SHIFT`
const GAS_PRICE_BUMP_SHIFT: usize = 3; // 2 = 25%, 3 = 12.5%, 4 = 6.25%
@@ -570,8 +568,8 @@ pub struct TransactionQueue {
minimal_gas_price: U256,
/// The maximum amount of gas any individual transaction may use.
tx_gas_limit: U256,
/// Current gas limit (block gas limit * factor). Transactions above the limit will not be accepted (default to !0)
total_gas_limit: U256,
/// Current gas limit (block gas limit). Transactions above the limit will not be accepted (default to !0)
block_gas_limit: U256,
/// Maximal time transaction may occupy the queue.
/// When we reach `max_time_in_queue / 2^3` we re-validate
/// account balance.
@@ -631,7 +629,7 @@ impl TransactionQueue {
TransactionQueue {
strategy,
minimal_gas_price: U256::zero(),
total_gas_limit: !U256::zero(),
block_gas_limit: !U256::zero(),
tx_gas_limit,
max_time_in_queue: DEFAULT_QUEUING_PERIOD,
current,
@@ -674,16 +672,10 @@ impl TransactionQueue {
self.current.gas_price_entry_limit()
}
/// Sets new gas limit. Transactions with gas slightly (`GAS_LIMIT_HYSTERESIS`) above the limit won't be imported.
/// Sets new gas limit. Transactions with gas over the limit will not be accepted.
/// Any transaction already imported to the queue is not affected.
pub fn set_gas_limit(&mut self, gas_limit: U256) {
let extra = gas_limit / U256::from(GAS_LIMIT_HYSTERESIS);
let total_gas_limit = match gas_limit.overflowing_add(extra) {
(_, true) => !U256::zero(),
(val, false) => val,
};
self.total_gas_limit = total_gas_limit;
self.block_gas_limit = gas_limit;
}
/// Sets new total gas limit.
@@ -819,13 +811,13 @@ impl TransactionQueue {
}));
}
let gas_limit = cmp::min(self.tx_gas_limit, self.total_gas_limit);
let gas_limit = cmp::min(self.tx_gas_limit, self.block_gas_limit);
if tx.gas > gas_limit {
trace!(target: "txqueue",
"Dropping transaction above gas limit: {:?} ({} > min({}, {}))",
tx.hash(),
tx.gas,
self.total_gas_limit,
self.block_gas_limit,
self.tx_gas_limit
);
return Err(Error::Transaction(TransactionError::GasLimitExceeded {
@@ -1922,13 +1914,13 @@ pub mod test {
// given
let mut txq = TransactionQueue::default();
txq.set_gas_limit(U256::zero());
assert_eq!(txq.total_gas_limit, U256::zero());
assert_eq!(txq.block_gas_limit, U256::zero());
// when
txq.set_gas_limit(!U256::zero());
// then
assert_eq!(txq.total_gas_limit, !U256::zero());
assert_eq!(txq.block_gas_limit, !U256::zero());
}
#[test]
@@ -1945,7 +1937,7 @@ pub mod test {
// then
assert_eq!(unwrap_tx_err(res), TransactionError::GasLimitExceeded {
limit: U256::from(50_250), // Should be 100.5% of set_gas_limit
limit: U256::from(50_000),
got: gas,
});
let stats = txq.status();

View File

@@ -311,11 +311,10 @@ impl Spec {
};
let mut substate = Substate::new();
state.kill_account(&address);
{
let mut exec = Executive::new(&mut state, &env_info, self.engine.as_ref());
if let Err(e) = exec.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer) {
if let Err(e) = exec.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer) {
warn!(target: "spec", "Genesis constructor execution at {} failed: {}.", address, e);
}
}
@@ -525,6 +524,9 @@ mod tests {
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let state = State::from_existing(db.boxed_clone(), spec.state_root(), spec.engine.account_start_nonce(0), Default::default()).unwrap();
let expected = H256::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap();
assert_eq!(state.storage_at(&Address::from_str("0000000000000000000000000000000000000005").unwrap(), &H256::zero()).unwrap(), expected);
let address = Address::from_str("0000000000000000000000000000000000000005").unwrap();
assert_eq!(state.storage_at(&address, &H256::zero()).unwrap(), expected);
assert_eq!(state.balance(&address).unwrap(), 1.into());
}
}

View File

@@ -642,7 +642,7 @@ impl<B: Backend> State<B> {
fn execute(&mut self, env_info: &EnvInfo, engine: &Engine, t: &SignedTransaction, tracing: bool, virt: bool)
-> Result<Executed, ExecutionError>
{
let options = TransactOptions { tracing: tracing, vm_tracing: false, check_nonce: true };
let options = TransactOptions { tracing: tracing, vm_tracing: false, check_nonce: true, output_from_init_contract: true };
let mut e = Executive::new(self, env_info, engine);
match virt {

View File

@@ -380,14 +380,13 @@ mod tests {
self.numbers.get(&index).cloned()
}
fn blocks_with_bloom(&self, _bloom: &H2048, _from_block: BlockNumber, _to_block: BlockNumber) -> Vec<BlockNumber> {
unimplemented!()
}
fn block_receipts(&self, _hash: &H256) -> Option<BlockReceipts> {
unimplemented!()
}
fn blocks_with_bloom(&self, _bloom: &H2048, _from_block: BlockNumber, _to_block: BlockNumber) -> Vec<BlockNumber> {
unimplemented!()
}
fn logs<F>(&self, _blocks: Vec<BlockNumber>, _matches: F, _limit: Option<usize>) -> Vec<LocalizedLogEntry>
where F: Fn(&LogEntry) -> bool, Self: Sized {