Merge remote-tracking branch 'remotes/upstream/master' into transactions-permission-contract-fix
This commit is contained in:
@@ -11,7 +11,6 @@ ansi_term = "0.9"
|
||||
bloomchain = "0.1"
|
||||
bn = { git = "https://github.com/paritytech/bn" }
|
||||
byteorder = "1.0"
|
||||
clippy = { version = "0.0.103", optional = true}
|
||||
common-types = { path = "types" }
|
||||
crossbeam = "0.2.9"
|
||||
ethash = { path = "../ethash" }
|
||||
@@ -83,6 +82,5 @@ evm-debug-tests = ["evm-debug"]
|
||||
slow-blocks = [] # Use SLOW_TX_DURATION="50" (compile time!) to track transactions over 50ms
|
||||
json-tests = []
|
||||
test-heavy = []
|
||||
dev = ["clippy"]
|
||||
default = []
|
||||
benches = []
|
||||
|
||||
@@ -32,7 +32,6 @@ macro_rules! overflowing {
|
||||
}}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(enum_variant_names))]
|
||||
enum Request<Cost: ::evm::CostType> {
|
||||
Gas(Cost),
|
||||
GasMem(Cost, Cost),
|
||||
@@ -101,7 +100,6 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
|
||||
/// Determine how much gas is used by the given instruction, given the machine's state.
|
||||
///
|
||||
/// We guarantee that the final element of the returned tuple (`provided`) will be `Some`
|
||||
|
||||
@@ -66,7 +66,6 @@ struct CodeReader<'a> {
|
||||
code: &'a [u8]
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(len_without_is_empty))]
|
||||
impl<'a> CodeReader<'a> {
|
||||
|
||||
/// Create new code reader - starting at position 0.
|
||||
@@ -287,7 +286,6 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
||||
fn exec_instruction(
|
||||
&mut self,
|
||||
gas: Cost,
|
||||
|
||||
Submodule ethcore/res/wasm-tests updated: d6185ea16e...d9d6133c1b
@@ -22,7 +22,6 @@ pub type LogBloom = ::log_entry::LogBloom;
|
||||
/// Constant 2048-bit datum for 0. Often used as a default.
|
||||
pub static ZERO_LOGBLOOM: LogBloom = ::bigint::hash::H2048([0x00; 256]);
|
||||
|
||||
#[cfg_attr(feature="dev", allow(enum_variant_names))]
|
||||
/// Semantic boolean for when a seal/signature is included.
|
||||
pub enum Seal {
|
||||
/// The seal/signature is included.
|
||||
|
||||
@@ -301,7 +301,6 @@ pub struct SealedBlock {
|
||||
}
|
||||
|
||||
impl<'x> OpenBlock<'x> {
|
||||
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
||||
/// Create a new `OpenBlock` ready for transaction pushing.
|
||||
pub fn new(
|
||||
engine: &'x EthEngine,
|
||||
@@ -614,7 +613,6 @@ impl IsBlock for SealedBlock {
|
||||
}
|
||||
|
||||
/// Enact the block given by block header, transactions and uncles
|
||||
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
||||
pub fn enact(
|
||||
header: &Header,
|
||||
transactions: &[SignedTransaction],
|
||||
@@ -688,7 +686,6 @@ fn push_transactions(block: &mut OpenBlock, transactions: &[SignedTransaction])
|
||||
|
||||
// TODO [ToDr] Pass `PreverifiedBlock` by move, this will avoid unecessary allocation
|
||||
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
|
||||
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
||||
pub fn enact_verified(
|
||||
block: &PreverifiedBlock,
|
||||
engine: &EthEngine,
|
||||
@@ -731,7 +728,6 @@ mod tests {
|
||||
use transaction::SignedTransaction;
|
||||
|
||||
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
|
||||
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
||||
fn enact_bytes(
|
||||
block_bytes: &[u8],
|
||||
engine: &EthEngine,
|
||||
@@ -778,7 +774,6 @@ mod tests {
|
||||
}
|
||||
|
||||
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards
|
||||
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
||||
fn enact_and_seal(
|
||||
block_bytes: &[u8],
|
||||
engine: &EthEngine,
|
||||
|
||||
@@ -970,7 +970,6 @@ impl BlockChain {
|
||||
self.cache_man.lock().note_used(CacheId::BlockDetails(block_hash));
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(similar_names))]
|
||||
/// Inserts the block into backing cache database.
|
||||
/// Expects the block to be valid and already verified.
|
||||
/// If the block is already known, does nothing.
|
||||
@@ -1475,7 +1474,6 @@ impl BlockChain {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#![cfg_attr(feature="dev", allow(similar_names))]
|
||||
use std::sync::Arc;
|
||||
use rustc_hex::FromHex;
|
||||
use hash::keccak;
|
||||
@@ -1583,7 +1581,6 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
|
||||
fn test_find_uncles() {
|
||||
let mut canon_chain = ChainGenerator::default();
|
||||
let mut finalizer = BlockFinalizer::default();
|
||||
@@ -1793,7 +1790,6 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
|
||||
fn test_small_fork() {
|
||||
let mut canon_chain = ChainGenerator::default();
|
||||
let mut finalizer = BlockFinalizer::default();
|
||||
|
||||
@@ -1857,7 +1857,7 @@ impl MiningBlockChainClient for Client {
|
||||
let mut open_block = OpenBlock::new(
|
||||
engine,
|
||||
self.factories.clone(),
|
||||
false, // TODO: this will need to be parameterised once we want to do immediate mining insertion.
|
||||
self.tracedb.read().tracing_enabled(),
|
||||
self.state_db.lock().boxed_clone_canon(&h),
|
||||
best_header,
|
||||
self.build_last_hashes(h.clone()),
|
||||
|
||||
@@ -51,8 +51,12 @@ mod finality;
|
||||
|
||||
/// `AuthorityRound` params.
|
||||
pub struct AuthorityRoundParams {
|
||||
/// Time to wait before next block or authority switching.
|
||||
pub step_duration: Duration,
|
||||
/// Time to wait before next block or authority switching,
|
||||
/// in seconds.
|
||||
///
|
||||
/// Deliberately typed as u16 as too high of a value leads
|
||||
/// to slow block issuance.
|
||||
pub step_duration: u16,
|
||||
/// Starting step,
|
||||
pub start_step: Option<u64>,
|
||||
/// Valid validators.
|
||||
@@ -71,10 +75,17 @@ pub struct AuthorityRoundParams {
|
||||
pub maximum_uncle_count: usize,
|
||||
}
|
||||
|
||||
const U16_MAX: usize = ::std::u16::MAX as usize;
|
||||
|
||||
impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
|
||||
fn from(p: ethjson::spec::AuthorityRoundParams) -> Self {
|
||||
let mut step_duration_usize: usize = p.step_duration.into();
|
||||
if step_duration_usize > U16_MAX {
|
||||
step_duration_usize = U16_MAX;
|
||||
warn!(target: "engine", "step_duration is too high ({}), setting it to {}", step_duration_usize, U16_MAX);
|
||||
}
|
||||
AuthorityRoundParams {
|
||||
step_duration: Duration::from_secs(p.step_duration.into()),
|
||||
step_duration: step_duration_usize as u16,
|
||||
validators: new_validator_set(p.validators),
|
||||
start_step: p.start_step.map(Into::into),
|
||||
validate_score_transition: p.validate_score_transition.map_or(0, Into::into),
|
||||
@@ -92,26 +103,47 @@ impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
|
||||
struct Step {
|
||||
calibrate: bool, // whether calibration is enabled.
|
||||
inner: AtomicUsize,
|
||||
duration: Duration,
|
||||
duration: u16,
|
||||
}
|
||||
|
||||
impl Step {
|
||||
fn load(&self) -> usize { self.inner.load(AtomicOrdering::SeqCst) }
|
||||
fn duration_remaining(&self) -> Duration {
|
||||
let now = unix_now();
|
||||
let step_end = self.duration * (self.load() as u32 + 1);
|
||||
if step_end > now {
|
||||
step_end - now
|
||||
} else {
|
||||
Duration::from_secs(0)
|
||||
let expected_seconds = (self.load() as u64)
|
||||
.checked_add(1)
|
||||
.and_then(|ctr| ctr.checked_mul(self.duration as u64));
|
||||
match expected_seconds {
|
||||
Some(secs) => {
|
||||
let step_end = Duration::from_secs(secs);
|
||||
if step_end > now {
|
||||
step_end - now
|
||||
} else {
|
||||
Duration::from_secs(0)
|
||||
}
|
||||
},
|
||||
None => {
|
||||
let ctr = self.load();
|
||||
error!(target: "engine", "Step counter is too high: {}, aborting", ctr);
|
||||
panic!("step counter is too high: {}", ctr)
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
fn increment(&self) {
|
||||
self.inner.fetch_add(1, AtomicOrdering::SeqCst);
|
||||
use std::usize;
|
||||
// fetch_add won't panic on overflow but will rather wrap
|
||||
// around, leading to zero as the step counter, which might
|
||||
// lead to unexpected situations, so it's better to shut down.
|
||||
if self.inner.fetch_add(1, AtomicOrdering::SeqCst) == usize::MAX {
|
||||
error!(target: "engine", "Step counter is too high: {}, aborting", usize::MAX);
|
||||
panic!("step counter is too high: {}", usize::MAX);
|
||||
}
|
||||
|
||||
}
|
||||
fn calibrate(&self) {
|
||||
if self.calibrate {
|
||||
let new_step = unix_now().as_secs() / self.duration.as_secs();
|
||||
let new_step = unix_now().as_secs() / (self.duration as u64);
|
||||
self.inner.store(new_step as usize, AtomicOrdering::SeqCst);
|
||||
}
|
||||
}
|
||||
@@ -359,8 +391,12 @@ impl AsMillis for Duration {
|
||||
impl AuthorityRound {
|
||||
/// Create a new instance of AuthorityRound engine.
|
||||
pub fn new(our_params: AuthorityRoundParams, machine: EthereumMachine) -> Result<Arc<Self>, Error> {
|
||||
if our_params.step_duration == 0 {
|
||||
error!(target: "engine", "Authority Round step duration can't be zero, aborting");
|
||||
panic!("authority_round: step duration can't be zero")
|
||||
}
|
||||
let should_timeout = our_params.start_step.is_none();
|
||||
let initial_step = our_params.start_step.unwrap_or_else(|| (unix_now().as_secs() / our_params.step_duration.as_secs())) as usize;
|
||||
let initial_step = our_params.start_step.unwrap_or_else(|| (unix_now().as_secs() / (our_params.step_duration as u64))) as usize;
|
||||
let engine = Arc::new(
|
||||
AuthorityRound {
|
||||
transition_service: IoService::<()>::start()?,
|
||||
@@ -1019,7 +1055,7 @@ mod tests {
|
||||
fn reports_skipped() {
|
||||
let last_benign = Arc::new(AtomicUsize::new(0));
|
||||
let params = AuthorityRoundParams {
|
||||
step_duration: Default::default(),
|
||||
step_duration: 1,
|
||||
start_step: Some(1),
|
||||
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
|
||||
validate_score_transition: 0,
|
||||
@@ -1059,7 +1095,7 @@ mod tests {
|
||||
fn test_uncles_transition() {
|
||||
let last_benign = Arc::new(AtomicUsize::new(0));
|
||||
let params = AuthorityRoundParams {
|
||||
step_duration: Default::default(),
|
||||
step_duration: 1,
|
||||
start_step: Some(1),
|
||||
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
|
||||
validate_score_transition: 0,
|
||||
@@ -1081,4 +1117,50 @@ mod tests {
|
||||
assert_eq!(aura.maximum_uncle_count(1), 0);
|
||||
assert_eq!(aura.maximum_uncle_count(100), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected="counter is too high")]
|
||||
fn test_counter_increment_too_high() {
|
||||
use super::Step;
|
||||
let step = Step {
|
||||
calibrate: false,
|
||||
inner: AtomicUsize::new(::std::usize::MAX),
|
||||
duration: 1,
|
||||
};
|
||||
step.increment();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected="counter is too high")]
|
||||
fn test_counter_duration_remaining_too_high() {
|
||||
use super::Step;
|
||||
let step = Step {
|
||||
calibrate: false,
|
||||
inner: AtomicUsize::new(::std::usize::MAX),
|
||||
duration: 1,
|
||||
};
|
||||
step.duration_remaining();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected="authority_round: step duration can't be zero")]
|
||||
fn test_step_duration_zero() {
|
||||
let last_benign = Arc::new(AtomicUsize::new(0));
|
||||
let params = AuthorityRoundParams {
|
||||
step_duration: 0,
|
||||
start_step: Some(1),
|
||||
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
|
||||
validate_score_transition: 0,
|
||||
validate_step_transition: 0,
|
||||
immediate_transitions: true,
|
||||
maximum_uncle_count_transition: 0,
|
||||
maximum_uncle_count: 0,
|
||||
block_reward: Default::default(),
|
||||
};
|
||||
|
||||
let mut c_params = ::spec::CommonParams::default();
|
||||
c_params.gas_limit_bound_divisor = 5.into();
|
||||
let machine = ::machine::EthereumMachine::regular(c_params, Default::default());
|
||||
AuthorityRound::new(params, machine).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ impl ValidatorContract {
|
||||
let client = self.client.read().clone();
|
||||
Box::new(move |a, d| client.as_ref()
|
||||
.and_then(Weak::upgrade)
|
||||
.ok_or("No client!".into())
|
||||
.ok_or_else(|| "No client!".into())
|
||||
.and_then(|c| {
|
||||
match c.as_full_client() {
|
||||
Some(c) => c.transact_contract(a, d)
|
||||
|
||||
@@ -138,7 +138,7 @@ impl ValidatorSet for Multi {
|
||||
}
|
||||
*self.block_number.write() = Box::new(move |id| client
|
||||
.upgrade()
|
||||
.ok_or("No client!".into())
|
||||
.ok_or_else(|| "No client!".into())
|
||||
.and_then(|c| c.block_number(id).ok_or("Unknown block".into())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ impl ValidatorSet for ValidatorSafeContract {
|
||||
let client = self.client.read().clone();
|
||||
Box::new(move |addr, data| client.as_ref()
|
||||
.and_then(Weak::upgrade)
|
||||
.ok_or("No client!".into())
|
||||
.ok_or_else(|| "No client!".into())
|
||||
.and_then(|c| {
|
||||
match c.as_full_client() {
|
||||
Some(c) => c.call_contract(id, addr, data),
|
||||
|
||||
@@ -336,7 +336,6 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
|
||||
impl Ethash {
|
||||
fn calculate_difficulty(&self, header: &Header, parent: &Header) -> U256 {
|
||||
const EXP_DIFF_PERIOD: u64 = 100_000;
|
||||
|
||||
@@ -85,7 +85,6 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B>
|
||||
where T: Tracer, V: VMTracer, B: StateBackend
|
||||
{
|
||||
/// Basic `Externalities` constructor.
|
||||
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
||||
pub fn new(state: &'a mut State<B>,
|
||||
env_info: &'a EnvInfo,
|
||||
machine: &'a Machine,
|
||||
@@ -302,7 +301,6 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
Ok(self.state.code_size(address)?.unwrap_or(0))
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(match_ref_pats))]
|
||||
fn ret(mut self, gas: &U256, data: &ReturnData, apply_state: bool) -> vm::Result<U256>
|
||||
where Self: Sized {
|
||||
let handle_copy = |to: &mut Option<&mut Bytes>| {
|
||||
|
||||
@@ -16,23 +16,6 @@
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(feature="benches", feature(test))]
|
||||
#![cfg_attr(feature="dev", feature(plugin))]
|
||||
#![cfg_attr(feature="dev", plugin(clippy))]
|
||||
|
||||
// Clippy settings
|
||||
// Most of the time much more readable
|
||||
#![cfg_attr(feature="dev", allow(needless_range_loop))]
|
||||
// Shorter than if-else
|
||||
#![cfg_attr(feature="dev", allow(match_bool))]
|
||||
// Keeps consistency (all lines with `.clone()`).
|
||||
#![cfg_attr(feature="dev", allow(clone_on_copy))]
|
||||
// Complains on Box<E> when implementing From<Box<E>>
|
||||
#![cfg_attr(feature="dev", allow(boxed_local))]
|
||||
// Complains about nested modules with same name as parent
|
||||
#![cfg_attr(feature="dev", allow(module_inception))]
|
||||
// TODO [todr] a lot of warnings to be fixed
|
||||
#![cfg_attr(feature="dev", allow(assign_op_pattern))]
|
||||
|
||||
|
||||
//! Ethcore library
|
||||
//!
|
||||
|
||||
@@ -366,7 +366,6 @@ impl Miner {
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(match_same_arms))]
|
||||
/// Prepares new block for sealing including top transactions from queue.
|
||||
fn prepare_block(&self, chain: &MiningBlockChainClient) -> (ClosedBlock, Option<H256>) {
|
||||
let _timer = PerfTimer::new("prepare_block");
|
||||
@@ -729,8 +728,6 @@ impl Miner {
|
||||
/// Are we allowed to do a non-mandatory reseal?
|
||||
fn tx_reseal_allowed(&self) -> bool { Instant::now() > *self.next_allowed_reseal.lock() }
|
||||
|
||||
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
|
||||
#[cfg_attr(feature="dev", allow(redundant_closure))]
|
||||
fn from_pending_block<H, F, G>(&self, latest_block_number: BlockNumber, from_chain: F, map_block: G) -> H
|
||||
where F: Fn() -> H, G: FnOnce(&ClosedBlock) -> H {
|
||||
let sealing_work = self.sealing_work.lock();
|
||||
@@ -890,7 +887,6 @@ impl MinerService for Miner {
|
||||
results
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(collapsible_if))]
|
||||
fn import_own_transaction(
|
||||
&self,
|
||||
chain: &MiningBlockChainClient,
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(all(nightly, feature="dev"), feature(plugin))]
|
||||
#![cfg_attr(all(nightly, feature="dev"), plugin(clippy))]
|
||||
|
||||
//! Miner module
|
||||
//! Keeps track of transactions and mined block.
|
||||
|
||||
@@ -136,7 +136,6 @@ impl PartialOrd for TransactionOrigin {
|
||||
}
|
||||
|
||||
impl Ord for TransactionOrigin {
|
||||
#[cfg_attr(feature="dev", allow(match_same_arms))]
|
||||
fn cmp(&self, other: &TransactionOrigin) -> Ordering {
|
||||
if *other == *self {
|
||||
return Ordering::Equal;
|
||||
@@ -516,7 +515,6 @@ pub struct AccountDetails {
|
||||
const GAS_PRICE_BUMP_SHIFT: usize = 3; // 2 = 25%, 3 = 12.5%, 4 = 6.25%
|
||||
|
||||
/// Describes the strategy used to prioritize transactions in the queue.
|
||||
#[cfg_attr(feature="dev", allow(enum_variant_names))]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum PrioritizationStrategy {
|
||||
/// Use only gas price. Disregards the actual computation cost of the transaction.
|
||||
|
||||
@@ -186,7 +186,6 @@ impl IoHandler<ClientIoMessage> for ClientIoHandler {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(single_match))]
|
||||
fn message(&self, _io: &IoContext<ClientIoMessage>, net_message: &ClientIoMessage) {
|
||||
use std::thread;
|
||||
|
||||
|
||||
@@ -57,7 +57,6 @@ impl StateProducer {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(let_and_return))]
|
||||
/// Tick the state producer. This alters the state, writing new data into
|
||||
/// the database.
|
||||
pub fn tick<R: Rng>(&mut self, rng: &mut R, db: &mut HashDB) {
|
||||
|
||||
@@ -35,6 +35,15 @@ use std::cell::{RefCell, Cell};
|
||||
|
||||
const STORAGE_CACHE_ITEMS: usize = 8192;
|
||||
|
||||
/// Boolean type for clean/dirty status.
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub enum Filth {
|
||||
/// Data has not been changed.
|
||||
Clean,
|
||||
/// Data has been changed.
|
||||
Dirty,
|
||||
}
|
||||
|
||||
/// Single account in the system.
|
||||
/// Keeps track of changes to the code and storage.
|
||||
/// The changes are applied in `commit_storage` and `commit_code`
|
||||
|
||||
@@ -604,7 +604,6 @@ impl<B: Backend> State<B> {
|
||||
}
|
||||
|
||||
/// Add `incr` to the balance of account `a`.
|
||||
#[cfg_attr(feature="dev", allow(single_match))]
|
||||
pub fn add_balance(&mut self, a: &Address, incr: &U256, cleanup_mode: CleanupMode) -> trie::Result<()> {
|
||||
trace!(target: "state", "add_balance({}, {}): {}", a, incr, self.balance(a)?);
|
||||
let is_value_transfer = !incr.is_zero();
|
||||
@@ -744,8 +743,6 @@ impl<B: Backend> State<B> {
|
||||
}
|
||||
|
||||
/// Commits our cached account changes into the trie.
|
||||
#[cfg_attr(feature="dev", allow(match_ref_pats))]
|
||||
#[cfg_attr(feature="dev", allow(needless_borrow))]
|
||||
pub fn commit(&mut self) -> Result<(), Error> {
|
||||
// first, commit the sub trees.
|
||||
let mut accounts = self.cache.borrow_mut();
|
||||
|
||||
@@ -58,7 +58,6 @@ impl Substate {
|
||||
}
|
||||
|
||||
/// Get the cleanup mode object from this.
|
||||
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
|
||||
pub fn to_cleanup_mode(&mut self, schedule: &Schedule) -> CleanupMode {
|
||||
match (schedule.kill_dust != CleanDustMode::Off, schedule.no_empty, schedule.kill_empty) {
|
||||
(false, false, _) => CleanupMode::ForceCreate,
|
||||
|
||||
@@ -427,7 +427,6 @@ impl state::Backend for StateDB {
|
||||
cache.accounts.get_mut(addr).map(|a| a.as_ref().map(|a| a.clone_basic()))
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(map_clone))]
|
||||
fn get_cached_code(&self, hash: &H256) -> Option<Arc<Vec<u8>>> {
|
||||
let mut cache = self.code_cache.lock();
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ use cache_manager::CacheManager;
|
||||
const TRACE_DB_VER: &'static [u8] = b"1.0";
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[cfg_attr(feature="dev", allow(enum_variant_names))]
|
||||
enum TraceDBIndex {
|
||||
/// Block traces index.
|
||||
BlockTraces = 0,
|
||||
|
||||
@@ -164,7 +164,6 @@ struct QueueSignal {
|
||||
}
|
||||
|
||||
impl QueueSignal {
|
||||
#[cfg_attr(feature="dev", allow(bool_comparison))]
|
||||
fn set_sync(&self) {
|
||||
// Do not signal when we are about to close
|
||||
if self.deleting.load(AtomicOrdering::Relaxed) {
|
||||
@@ -179,7 +178,6 @@ impl QueueSignal {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(bool_comparison))]
|
||||
fn set_async(&self) {
|
||||
// Do not signal when we are about to close
|
||||
if self.deleting.load(AtomicOrdering::Relaxed) {
|
||||
|
||||
@@ -498,7 +498,6 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(feature="dev", allow(similar_names))]
|
||||
fn test_verify_block() {
|
||||
use rlp::RlpStream;
|
||||
|
||||
|
||||
@@ -96,7 +96,6 @@ pub trait Ext {
|
||||
/// Returns Err, if we run out of gas.
|
||||
/// Otherwise returns call_result which contains gas left
|
||||
/// and true if subcall was successfull.
|
||||
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
||||
fn call(&mut self,
|
||||
gas: &U256,
|
||||
sender_address: &Address,
|
||||
|
||||
@@ -69,17 +69,17 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
|
||||
),
|
||||
Static(
|
||||
"_ccall",
|
||||
&[I32; 6],
|
||||
&[I64, I32, I32, I32, I32, I32, I32],
|
||||
Some(I32),
|
||||
),
|
||||
Static(
|
||||
"_dcall",
|
||||
&[I32; 5],
|
||||
&[I64, I32, I32, I32, I32, I32],
|
||||
Some(I32),
|
||||
),
|
||||
Static(
|
||||
"_scall",
|
||||
&[I32; 5],
|
||||
&[I64, I32, I32, I32, I32, I32],
|
||||
Some(I32),
|
||||
),
|
||||
Static(
|
||||
|
||||
@@ -111,6 +111,7 @@ impl vm::Vm for WasmInterpreter {
|
||||
address: params.address,
|
||||
sender: params.sender,
|
||||
origin: params.origin,
|
||||
code_address: params.code_address,
|
||||
value: params.value.value(),
|
||||
},
|
||||
&self.program,
|
||||
|
||||
@@ -104,6 +104,7 @@ pub struct RuntimeContext {
|
||||
pub address: Address,
|
||||
pub sender: Address,
|
||||
pub origin: Address,
|
||||
pub code_address: Address,
|
||||
pub value: U256,
|
||||
}
|
||||
|
||||
@@ -305,6 +306,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
//
|
||||
// method signature:
|
||||
// fn (
|
||||
// gas: i64,
|
||||
// address: *const u8,
|
||||
// val_ptr: *const u8,
|
||||
// input_ptr: *const u8,
|
||||
@@ -323,6 +325,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
//
|
||||
// signature (same as static call):
|
||||
// fn (
|
||||
// gas: i64,
|
||||
// address: *const u8,
|
||||
// input_ptr: *const u8,
|
||||
// input_len: u32,
|
||||
@@ -330,7 +333,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
// result_len: u32,
|
||||
// ) -> i32
|
||||
|
||||
self.do_call(false, CallType::CallCode, context)
|
||||
self.do_call(false, CallType::DelegateCall, context)
|
||||
}
|
||||
|
||||
fn do_call(
|
||||
@@ -363,6 +366,9 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
let address = self.pop_address(&mut context)?;
|
||||
trace!(target: "wasm", " address: {:?}", address);
|
||||
|
||||
let gas = context.value_stack.pop_as::<i64>()? as u64;
|
||||
trace!(target: "wasm", " gas: {:?}", gas);
|
||||
|
||||
if let Some(ref val) = val {
|
||||
let address_balance = self.ext.balance(&self.context.address)
|
||||
.map_err(|_| UserTrap::BalanceQueryError)?;
|
||||
@@ -377,16 +383,16 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
|
||||
let mut result = Vec::with_capacity(result_alloc_len as usize);
|
||||
result.resize(result_alloc_len as usize, 0);
|
||||
let gas = self.gas_left()
|
||||
.map_err(|_| UserTrap::InvalidGasState)?
|
||||
.into();
|
||||
|
||||
// todo: optimize to use memory views once it's in
|
||||
let payload = self.memory.get(input_ptr, input_len as usize)?;
|
||||
|
||||
self.charge(|_| gas.into())?;
|
||||
|
||||
let call_result = self.ext.call(
|
||||
&gas,
|
||||
&self.context.sender,
|
||||
&self.context.address,
|
||||
&gas.into(),
|
||||
match call_type { CallType::DelegateCall => &self.context.sender, _ => &self.context.address },
|
||||
match call_type { CallType::Call | CallType::StaticCall => &address, _ => &self.context.address },
|
||||
val,
|
||||
&payload,
|
||||
&address,
|
||||
@@ -396,12 +402,16 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
|
||||
match call_result {
|
||||
vm::MessageCallResult::Success(gas_left, _) => {
|
||||
self.gas_counter = self.gas_limit - gas_left.low_u64();
|
||||
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
|
||||
self.gas_counter = self.gas_counter - gas_left.low_u64();
|
||||
|
||||
self.memory.set(result_ptr, &result)?;
|
||||
Ok(Some(0i32.into()))
|
||||
},
|
||||
vm::MessageCallResult::Reverted(gas_left, _) => {
|
||||
self.gas_counter = self.gas_limit - gas_left.low_u64();
|
||||
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
|
||||
self.gas_counter = self.gas_counter - gas_left.low_u64();
|
||||
|
||||
self.memory.set(result_ptr, &result)?;
|
||||
Ok(Some((-1i32).into()))
|
||||
},
|
||||
@@ -416,6 +426,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
{
|
||||
// signature (same as code call):
|
||||
// fn (
|
||||
// gas: i64,
|
||||
// address: *const u8,
|
||||
// input_ptr: *const u8,
|
||||
// input_len: u32,
|
||||
|
||||
@@ -60,7 +60,7 @@ fn empty() {
|
||||
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(99_982));
|
||||
assert_eq!(gas_left, U256::from(96_678));
|
||||
}
|
||||
|
||||
// This test checks if the contract deserializes payload header properly.
|
||||
@@ -112,7 +112,7 @@ fn logger() {
|
||||
U256::from(1_000_000_000),
|
||||
"Logger sets 0x04 key to the trasferred value"
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(19_147));
|
||||
assert_eq!(gas_left, U256::from(15_860));
|
||||
}
|
||||
|
||||
// This test checks if the contract can allocate memory and pass pointer to the result stream properly.
|
||||
@@ -147,7 +147,7 @@ fn identity() {
|
||||
sender,
|
||||
"Idenity test contract does not return the sender passed"
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(99_844));
|
||||
assert_eq!(gas_left, U256::from(96_540));
|
||||
}
|
||||
|
||||
// Dispersion test sends byte array and expect the contract to 'disperse' the original elements with
|
||||
@@ -180,7 +180,7 @@ fn dispersion() {
|
||||
result,
|
||||
vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0]
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(96_393));
|
||||
assert_eq!(gas_left, U256::from(96_116));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -208,7 +208,7 @@ fn suicide_not() {
|
||||
result,
|
||||
vec![0u8]
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(96_725));
|
||||
assert_eq!(gas_left, U256::from(96_461));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -240,7 +240,7 @@ fn suicide() {
|
||||
};
|
||||
|
||||
assert!(ext.suicides.contains(&refund));
|
||||
assert_eq!(gas_left, U256::from(96_687));
|
||||
assert_eq!(gas_left, U256::from(96_429));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -270,7 +270,7 @@ fn create() {
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Create,
|
||||
gas: U256::from(65_899),
|
||||
gas: U256::from(62_545),
|
||||
sender_address: None,
|
||||
receive_address: None,
|
||||
value: Some(1_000_000_000.into()),
|
||||
@@ -278,9 +278,52 @@ fn create() {
|
||||
code_address: None,
|
||||
}
|
||||
));
|
||||
assert_eq!(gas_left, U256::from(65_892));
|
||||
assert_eq!(gas_left, U256::from(62_538));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn call_msg() {
|
||||
::ethcore_logger::init_log();
|
||||
|
||||
let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap();
|
||||
let receiver: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap();
|
||||
let contract_address: Address = "0d461d4174b4ae35775c4a342f1e5e1e4e6c4db5".parse().unwrap();
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.sender = sender.clone();
|
||||
params.address = receiver.clone();
|
||||
params.code_address = contract_address.clone();
|
||||
params.gas = U256::from(100_000);
|
||||
params.code = Some(Arc::new(load_sample!("call.wasm")));
|
||||
params.data = Some(Vec::new());
|
||||
|
||||
let mut ext = FakeExt::new();
|
||||
ext.balances.insert(receiver.clone(), U256::from(10000000000u64));
|
||||
|
||||
let gas_left = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(gas_left) => gas_left,
|
||||
GasLeft::NeedsReturn { .. } => { panic!("Call test should not return payload"); },
|
||||
}
|
||||
};
|
||||
|
||||
trace!(target: "wasm", "fake_calls: {:?}", &ext.calls);
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
gas: U256::from(33_000),
|
||||
sender_address: Some(receiver),
|
||||
receive_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])),
|
||||
value: Some(1000000000.into()),
|
||||
data: vec![129u8, 123, 113, 107, 101, 97],
|
||||
code_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])),
|
||||
}
|
||||
));
|
||||
|
||||
assert_eq!(gas_left, U256::from(95_699));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn call_code() {
|
||||
@@ -312,7 +355,7 @@ fn call_code() {
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
gas: U256::from(98_713),
|
||||
gas: U256::from(20_000),
|
||||
sender_address: Some(sender),
|
||||
receive_address: Some(receiver),
|
||||
value: None,
|
||||
@@ -324,7 +367,7 @@ fn call_code() {
|
||||
// siphash result
|
||||
let res = LittleEndian::read_u32(&result[..]);
|
||||
assert_eq!(res, 4198595614);
|
||||
assert_eq!(gas_left, U256::from(93_855));
|
||||
assert_eq!(gas_left, U256::from(90_550));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -333,6 +376,7 @@ fn call_static() {
|
||||
|
||||
let sender: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap();
|
||||
let receiver: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap();
|
||||
let contract_address: Address = "0d461d4174b4ae35775c4a342f1e5e1e4e6c4db5".parse().unwrap();
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.sender = sender.clone();
|
||||
@@ -341,6 +385,7 @@ fn call_static() {
|
||||
params.code = Some(Arc::new(load_sample!("call_static.wasm")));
|
||||
params.data = Some(Vec::new());
|
||||
params.value = ActionValue::transfer(1_000_000_000);
|
||||
params.code_address = contract_address.clone();
|
||||
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
@@ -357,9 +402,9 @@ fn call_static() {
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
gas: U256::from(98_713),
|
||||
sender_address: Some(sender),
|
||||
receive_address: Some(receiver),
|
||||
gas: U256::from(20_000),
|
||||
sender_address: Some(receiver),
|
||||
receive_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
|
||||
value: None,
|
||||
data: vec![1u8, 2, 3, 5, 7, 11],
|
||||
code_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
|
||||
@@ -370,7 +415,7 @@ fn call_static() {
|
||||
let res = LittleEndian::read_u32(&result[..]);
|
||||
assert_eq!(res, 317632590);
|
||||
|
||||
assert_eq!(gas_left, U256::from(93_855));
|
||||
assert_eq!(gas_left, U256::from(90_550));
|
||||
}
|
||||
|
||||
// Realloc test
|
||||
@@ -393,7 +438,7 @@ fn realloc() {
|
||||
}
|
||||
};
|
||||
assert_eq!(result, vec![0u8; 2]);
|
||||
assert_eq!(gas_left, U256::from(96_723));
|
||||
assert_eq!(gas_left, U256::from(96_445));
|
||||
}
|
||||
|
||||
// Tests that contract's ability to read from a storage
|
||||
@@ -419,7 +464,7 @@ fn storage_read() {
|
||||
};
|
||||
|
||||
assert_eq!(Address::from(&result[12..32]), address);
|
||||
assert_eq!(gas_left, U256::from(99_767));
|
||||
assert_eq!(gas_left, U256::from(96_463));
|
||||
}
|
||||
|
||||
// Tests keccak calculation
|
||||
@@ -445,7 +490,7 @@ fn keccak() {
|
||||
};
|
||||
|
||||
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
|
||||
assert_eq!(gas_left, U256::from(81_446));
|
||||
assert_eq!(gas_left, U256::from(81_067));
|
||||
}
|
||||
|
||||
// memcpy test.
|
||||
@@ -477,7 +522,7 @@ fn memcpy() {
|
||||
};
|
||||
|
||||
assert_eq!(result, test_payload);
|
||||
assert_eq!(gas_left, U256::from(72_216));
|
||||
assert_eq!(gas_left, U256::from(71_940));
|
||||
}
|
||||
|
||||
// memmove test.
|
||||
@@ -509,7 +554,7 @@ fn memmove() {
|
||||
};
|
||||
|
||||
assert_eq!(result, test_payload);
|
||||
assert_eq!(gas_left, U256::from(72_216));
|
||||
assert_eq!(gas_left, U256::from(71_940));
|
||||
}
|
||||
|
||||
// memset test
|
||||
@@ -534,7 +579,7 @@ fn memset() {
|
||||
};
|
||||
|
||||
assert_eq!(result, vec![228u8; 8192]);
|
||||
assert_eq!(gas_left, U256::from(72_196));
|
||||
assert_eq!(gas_left, U256::from(71_921));
|
||||
}
|
||||
|
||||
macro_rules! reqrep_test {
|
||||
@@ -591,7 +636,7 @@ fn math_add() {
|
||||
U256::from_dec_str("1888888888888888888888888888887").unwrap(),
|
||||
(&result[..]).into()
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(95_524));
|
||||
assert_eq!(gas_left, U256::from(95_384));
|
||||
}
|
||||
|
||||
// multiplication
|
||||
@@ -613,7 +658,7 @@ fn math_mul() {
|
||||
U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(),
|
||||
(&result[..]).into()
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(94_674));
|
||||
assert_eq!(gas_left, U256::from(94_374));
|
||||
}
|
||||
|
||||
// subtraction
|
||||
@@ -635,7 +680,7 @@ fn math_sub() {
|
||||
U256::from_dec_str("111111111111111111111111111111").unwrap(),
|
||||
(&result[..]).into()
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(95_516));
|
||||
assert_eq!(gas_left, U256::from(95_372));
|
||||
}
|
||||
|
||||
// subtraction with overflow
|
||||
@@ -677,7 +722,7 @@ fn math_div() {
|
||||
U256::from_dec_str("1125000").unwrap(),
|
||||
(&result[..]).into()
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(88_514));
|
||||
assert_eq!(gas_left, U256::from(88_356));
|
||||
}
|
||||
|
||||
// This test checks the ability of wasm contract to invoke
|
||||
@@ -765,7 +810,7 @@ fn externs() {
|
||||
"Gas limit requested and returned does not match"
|
||||
);
|
||||
|
||||
assert_eq!(gas_left, U256::from(94_858));
|
||||
assert_eq!(gas_left, U256::from(95_321));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -791,7 +836,7 @@ fn embedded_keccak() {
|
||||
};
|
||||
|
||||
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
|
||||
assert_eq!(gas_left, U256::from(81_446));
|
||||
assert_eq!(gas_left, U256::from(81_067));
|
||||
}
|
||||
|
||||
/// This test checks the correctness of log extern
|
||||
@@ -826,5 +871,5 @@ fn events() {
|
||||
assert_eq!(&log_entry.data, b"gnihtemos");
|
||||
|
||||
assert_eq!(&result, b"gnihtemos");
|
||||
assert_eq!(gas_left, U256::from(79_637));
|
||||
assert_eq!(gas_left, U256::from(79_206));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user