merge with master

This commit is contained in:
Robert Habermeier
2016-07-12 13:09:42 +02:00
35 changed files with 367 additions and 113 deletions

View File

@@ -16,8 +16,6 @@
//! Blockchain block.
#![cfg_attr(feature="dev", allow(ptr_arg))] // Because of &LastHashes -> &Vec<_>
use common::*;
use engine::*;
use state::*;
@@ -76,11 +74,11 @@ pub struct BlockRefMut<'a> {
/// Block header.
pub header: &'a mut Header,
/// Block transactions.
pub transactions: &'a Vec<SignedTransaction>,
pub transactions: &'a [SignedTransaction],
/// Block uncles.
pub uncles: &'a Vec<Header>,
pub uncles: &'a [Header],
/// Transaction receipts.
pub receipts: &'a Vec<Receipt>,
pub receipts: &'a [Receipt],
/// State.
pub state: &'a mut State,
/// Traces.
@@ -92,11 +90,11 @@ pub struct BlockRef<'a> {
/// Block header.
pub header: &'a Header,
/// Block transactions.
pub transactions: &'a Vec<SignedTransaction>,
pub transactions: &'a [SignedTransaction],
/// Block uncles.
pub uncles: &'a Vec<Header>,
pub uncles: &'a [Header],
/// Transaction receipts.
pub receipts: &'a Vec<Receipt>,
pub receipts: &'a [Receipt],
/// State.
pub state: &'a State,
/// Traces.
@@ -152,16 +150,16 @@ pub trait IsBlock {
fn state(&self) -> &State { &self.block().state }
/// Get all information on transactions in this block.
fn transactions(&self) -> &Vec<SignedTransaction> { &self.block().base.transactions }
fn transactions(&self) -> &[SignedTransaction] { &self.block().base.transactions }
/// Get all information on receipts in this block.
fn receipts(&self) -> &Vec<Receipt> { &self.block().receipts }
fn receipts(&self) -> &[Receipt] { &self.block().receipts }
/// Get all information concerning transaction tracing in this block.
fn traces(&self) -> &Option<Vec<Trace>> { &self.block().traces }
/// Get all uncles in this block.
fn uncles(&self) -> &Vec<Header> { &self.block().base.uncles }
fn uncles(&self) -> &[Header] { &self.block().base.uncles }
}
/// Trait for a object that has a state database.

View File

@@ -426,7 +426,7 @@ impl Client {
};
// Commit results
let receipts = block.receipts().clone();
let receipts = block.receipts().to_owned();
let traces = From::from(block.traces().clone().unwrap_or_else(Vec::new));
// CHECK! I *think* this is fine, even if the state_root is equal to another

View File

@@ -107,6 +107,9 @@ pub trait CostType: ops::Mul<Output=Self> + ops::Div<Output=Self> + ops::Add<Out
fn overflow_add(self, other: Self) -> (Self, bool);
/// Multiple with overflow
fn overflow_mul(self, other: Self) -> (Self, bool);
/// Single-step full multiplication and division: `self*other/div`
/// Should not overflow on intermediate steps
fn overflow_mul_div(self, other: Self, div: Self) -> (Self, bool);
}
impl CostType for U256 {
@@ -129,6 +132,17 @@ impl CostType for U256 {
fn overflow_mul(self, other: Self) -> (Self, bool) {
Uint::overflowing_mul(self, other)
}
fn overflow_mul_div(self, other: Self, div: Self) -> (Self, bool) {
let x = self.full_mul(other);
let (U512(parts), o) = Uint::overflowing_div(x, U512::from(div));
let overflow = (parts[4] | parts[5] | parts[6] | parts[7]) > 0;
(
U256([parts[0], parts[1], parts[2], parts[3]]),
o | overflow
)
}
}
impl CostType for usize {
@@ -154,6 +168,14 @@ impl CostType for usize {
fn overflow_mul(self, other: Self) -> (Self, bool) {
self.overflowing_mul(other)
}
fn overflow_mul_div(self, other: Self, div: Self) -> (Self, bool) {
let (c, o) = U128::from(self).overflowing_mul(U128::from(other));
let (U128(parts), o1) = c.overflowing_div(U128::from(div));
let result = parts[0] as usize;
let overflow = o | o1 | (parts[1] > 0) | (parts[0] > result as u64);
(result, overflow)
}
}
/// Evm interface
@@ -164,3 +186,41 @@ pub trait Evm {
/// to compute the final gas left.
fn exec(&mut self, params: ActionParams, ext: &mut Ext) -> Result<GasLeft>;
}
#[test]
fn should_calculate_overflow_mul_div_without_overflow() {
// given
let num = 10_000_000;
// when
let (res1, o1) = U256::from(num).overflow_mul_div(U256::from(num), U256::from(num));
let (res2, o2) = num.overflow_mul_div(num, num);
// then
assert_eq!(res1, U256::from(num));
assert!(!o1);
assert_eq!(res2, num);
assert!(!o2);
}
#[test]
fn should_calculate_overflow_mul_div_with_overflow() {
// given
let max = ::std::u64::MAX;
let num1 = U256([max, max, max, max]);
let num2 = ::std::usize::MAX;
// when
let (res1, o1) = num1.overflow_mul_div(num1, num1 - U256::from(2));
let (res2, o2) = num2.overflow_mul_div(num2, num2 - 2);
// then
// (x+2)^2/x = (x^2 + 4x + 4)/x = x + 4 + 4/x ~ (MAX-2) + 4 + 0 = 1
assert_eq!(res2, 1);
assert!(o2);
assert_eq!(res1, U256::from(1));
assert!(o1);
}

View File

@@ -68,6 +68,9 @@ impl<Gas: CostType> Gasometer<Gas> {
let default_gas = Gas::from(schedule.tier_step_gas[tier]);
let cost = match instruction {
instructions::JUMPDEST => {
InstructionCost::Gas(Gas::from(1))
},
instructions::SSTORE => {
let address = H256::from(stack.peek(0));
let newval = stack.peek(1);
@@ -106,9 +109,6 @@ impl<Gas: CostType> Gasometer<Gas> {
instructions::EXTCODECOPY => {
InstructionCost::GasMemCopy(default_gas, try!(self.mem_needed(stack.peek(1), stack.peek(3))), try!(Gas::from_u256(*stack.peek(3))))
},
instructions::JUMPDEST => {
InstructionCost::Gas(Gas::from(1))
},
instructions::LOG0...instructions::LOG4 => {
let no_of_topics = instructions::get_log_topics(instruction);
let log_gas = schedule.log_gas + schedule.log_topic_gas * no_of_topics;
@@ -199,14 +199,12 @@ impl<Gas: CostType> Gasometer<Gas> {
let s = mem_size >> 5;
// s * memory_gas + s * s / quad_coeff_div
let a = overflowing!(s.overflow_mul(Gas::from(schedule.memory_gas)));
// We need to go to U512 to calculate s*s/quad_coeff_div
let b = U512::from(s.as_u256()) * U512::from(s.as_u256()) / U512::from(schedule.quad_coeff_div);
if b > U512::from(!U256::zero()) {
Err(evm::Error::OutOfGas)
} else {
Ok(overflowing!(a.overflow_add(try!(Gas::from_u256(U256::from(b))))))
}
// Calculate s*s/quad_coeff_div
let b = overflowing!(s.overflow_mul_div(s, Gas::from(schedule.quad_coeff_div)));
Ok(overflowing!(a.overflow_add(b)))
};
let current_mem_size = Gas::from(current_mem_size);
let req_mem_size_rounded = (overflowing!(mem_size.overflow_add(Gas::from(31 as usize))) >> 5) << 5;

View File

@@ -143,7 +143,7 @@ impl Header {
/// Get the difficulty field of the header.
pub fn difficulty(&self) -> &U256 { &self.difficulty }
/// Get the seal field of the header.
pub fn seal(&self) -> &Vec<Bytes> { &self.seal }
pub fn seal(&self) -> &[Bytes] { &self.seal }
// TODO: seal_at, set_seal_at &c.

View File

@@ -98,7 +98,7 @@ const V7_VERSION_KEY: &'static [u8] = &[ b'j', b'v', b'e', b'r', 0, 0, 0, 0, 0,
const DB_VERSION: u32 = 0x203;
const PADDING : [u8; 10] = [0u8; 10];
/// Version for OverlayRecent database.
/// Version for `OverlayRecent` database.
/// more involved than the archive version because of journaling.
#[derive(Default)]
pub struct OverlayRecentV7 {
@@ -258,4 +258,4 @@ impl Migration for OverlayRecentV7 {
try!(self.walk_journal(source));
self.migrate_journal(source, batch, dest)
}
}
}

View File

@@ -665,7 +665,7 @@ impl MinerService for Miner {
};
match (&self.options.pending_set, sealing_set) {
(&PendingSet::AlwaysQueue, _) | (&PendingSet::SealingOrElseQueue, None) => queue.top_transactions(),
(_, sealing) => sealing.map_or_else(Vec::new, |s| s.transactions().clone()),
(_, sealing) => sealing.map_or_else(Vec::new, |s| s.transactions().to_owned()),
}
}
@@ -702,7 +702,7 @@ impl MinerService for Miner {
.iter()
.map(|t| t.hash());
let receipts = pending.receipts().clone().into_iter();
let receipts = pending.receipts().iter().cloned();
hashes.zip(receipts).collect()
},

View File

@@ -143,7 +143,7 @@ impl Spec {
}
/// Get the known knodes of the network in enode format.
pub fn nodes(&self) -> &Vec<String> { &self.nodes }
pub fn nodes(&self) -> &[String] { &self.nodes }
/// Get the configured Network ID.
pub fn network_id(&self) -> U256 { self.params.network_id }