Skip to content

Commit

Permalink
Merge 75ce4f0 into d0e94e7
Browse files Browse the repository at this point in the history
  • Loading branch information
sorpaas committed Jun 13, 2017
2 parents d0e94e7 + 75ce4f0 commit 1ed74b8
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 31 deletions.
1 change: 1 addition & 0 deletions gethrpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ pub struct RPCBlock {
pub gasLimit: String,
pub gasUsed: String,
pub timestamp: String,
#[serde(default)]
pub transactions: Vec<String>,
pub uncles: Vec<String>
}
Expand Down
11 changes: 0 additions & 11 deletions jsontests/tests/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,19 @@ lazy_static! {
serde_json::from_str(include_str!("files/vmSystemOperationsTest.json")).unwrap();
}

#[test] fn aBAcalls0() { assert_eq!(test_transaction("ABAcalls0", &TESTS["ABAcalls0"], true), true); }
#[test] fn aBAcalls1() { assert_eq!(test_transaction("ABAcalls1", &TESTS["ABAcalls1"], true), true); }
#[test] fn aBAcalls2() { assert_eq!(test_transaction("ABAcalls2", &TESTS["ABAcalls2"], true), true); }
#[test] fn aBAcalls3() { assert_eq!(test_transaction("ABAcalls3", &TESTS["ABAcalls3"], true), true); }
#[test] fn aBAcallsSuicide0() { assert_eq!(test_transaction("ABAcallsSuicide0", &TESTS["ABAcallsSuicide0"], true), true); }
#[test] fn aBAcallsSuicide1() { assert_eq!(test_transaction("ABAcallsSuicide1", &TESTS["ABAcallsSuicide1"], true), true); }
#[test] fn callRecursiveBomb0() { assert_eq!(test_transaction("CallRecursiveBomb0", &TESTS["CallRecursiveBomb0"], true), true); }
#[test] fn callRecursiveBomb1() { assert_eq!(test_transaction("CallRecursiveBomb1", &TESTS["CallRecursiveBomb1"], true), true); }
#[test] fn callRecursiveBomb2() { assert_eq!(test_transaction("CallRecursiveBomb2", &TESTS["CallRecursiveBomb2"], true), true); }
#[test] fn callRecursiveBomb3() { assert_eq!(test_transaction("CallRecursiveBomb3", &TESTS["CallRecursiveBomb3"], true), true); }
#[test] fn callToNameRegistrator0() { assert_eq!(test_transaction("CallToNameRegistrator0", &TESTS["CallToNameRegistrator0"], true), true); }
#[test] fn callToNameRegistratorNotMuchMemory0() { assert_eq!(test_transaction("CallToNameRegistratorNotMuchMemory0", &TESTS["CallToNameRegistratorNotMuchMemory0"], true), true); }
#[test] fn callToNameRegistratorNotMuchMemory1() { assert_eq!(test_transaction("CallToNameRegistratorNotMuchMemory1", &TESTS["CallToNameRegistratorNotMuchMemory1"], true), true); }
#[test] fn callToNameRegistratorOutOfGas() { assert_eq!(test_transaction("CallToNameRegistratorOutOfGas", &TESTS["CallToNameRegistratorOutOfGas"], true), true); }
#[test] fn callToNameRegistratorTooMuchMemory0() { assert_eq!(test_transaction("CallToNameRegistratorTooMuchMemory0", &TESTS["CallToNameRegistratorTooMuchMemory0"], true), true); }
#[test] fn callToNameRegistratorTooMuchMemory1() { assert_eq!(test_transaction("CallToNameRegistratorTooMuchMemory1", &TESTS["CallToNameRegistratorTooMuchMemory1"], true), true); }
#[test] fn callToNameRegistratorTooMuchMemory2() { assert_eq!(test_transaction("CallToNameRegistratorTooMuchMemory2", &TESTS["CallToNameRegistratorTooMuchMemory2"], true), true); }
#[test] fn callToPrecompiledContract() { assert_eq!(test_transaction("CallToPrecompiledContract", &TESTS["CallToPrecompiledContract"], true), true); }
#[test] fn callToReturn1() { assert_eq!(test_transaction("CallToReturn1", &TESTS["CallToReturn1"], true), true); }
#[test] fn postToNameRegistrator0() { assert_eq!(test_transaction("PostToNameRegistrator0", &TESTS["PostToNameRegistrator0"], true), true); }
#[test] fn postToReturn1() { assert_eq!(test_transaction("PostToReturn1", &TESTS["PostToReturn1"], true), true); }
#[test] fn testNameRegistrator() { assert_eq!(test_transaction("TestNameRegistrator", &TESTS["TestNameRegistrator"], true), true); }
#[test] fn callcodeToNameRegistrator0() { assert_eq!(test_transaction("callcodeToNameRegistrator0", &TESTS["callcodeToNameRegistrator0"], true), true); }
#[test] fn callcodeToReturn1() { assert_eq!(test_transaction("callcodeToReturn1", &TESTS["callcodeToReturn1"], true), true); }
#[test] fn callstatelessToNameRegistrator0() { assert_eq!(test_transaction("callstatelessToNameRegistrator0", &TESTS["callstatelessToNameRegistrator0"], true), true); }
#[test] fn callstatelessToReturn1() { assert_eq!(test_transaction("callstatelessToReturn1", &TESTS["callstatelessToReturn1"], true), true); }
#[test] fn createNameRegistrator() { assert_eq!(test_transaction("createNameRegistrator", &TESTS["createNameRegistrator"], true), true); }
Expand Down
18 changes: 10 additions & 8 deletions sputnikvm/src/vm/eval/cost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use utils::bigint::{M256, U256};
use std::cmp::max;
use vm::{Memory, Instruction};
use super::State;
use super::precompiled::is_precompiled;

const G_ZERO: usize = 0;
const G_BASE: usize = 2;
Expand Down Expand Up @@ -46,12 +47,12 @@ fn sstore_cost<M: Memory + Default>(machine: &State<M>) -> Gas {
}
}

fn call_cost<M: Memory + Default>(machine: &State<M>) -> Gas {
extra_cost(machine)
fn call_cost<M: Memory + Default>(machine: &State<M>, is_callcode: bool) -> Gas {
extra_cost(machine, is_callcode)
}

fn extra_cost<M: Memory + Default>(machine: &State<M>) -> Gas {
Gas::from(machine.patch.gas_call) + xfer_cost(machine) + new_cost(machine)
fn extra_cost<M: Memory + Default>(machine: &State<M>, is_callcode: bool) -> Gas {
Gas::from(machine.patch.gas_call) + xfer_cost(machine) + new_cost(machine, is_callcode)
}

fn xfer_cost<M: Memory + Default>(machine: &State<M>) -> Gas {
Expand All @@ -63,9 +64,9 @@ fn xfer_cost<M: Memory + Default>(machine: &State<M>) -> Gas {
}
}

fn new_cost<M: Memory + Default>(machine: &State<M>) -> Gas {
fn new_cost<M: Memory + Default>(machine: &State<M>, is_callcode: bool) -> Gas {
let address: Address = machine.stack.peek(1).unwrap().into();
if machine.account_state.balance(address).unwrap() == U256::zero() && machine.account_state.nonce(address).unwrap() == M256::zero() && machine.account_state.code(address).unwrap().len() == 0 {
if machine.account_state.balance(address).unwrap() == U256::zero() && machine.account_state.nonce(address).unwrap() == M256::zero() && machine.account_state.code(address).unwrap().len() == 0 && !is_precompiled(address) && !is_callcode {
G_NEWACCOUNT.into()
} else {
Gas::zero()
Expand Down Expand Up @@ -158,8 +159,9 @@ pub fn memory_cost<M: Memory + Default>(instruction: Instruction, state: &State<
/// Calculate the gas cost.
pub fn gas_cost<M: Memory + Default>(instruction: Instruction, state: &State<M>) -> Gas {
match instruction {
Instruction::CALL | Instruction::CALLCODE |
Instruction::DELEGATECALL => call_cost(state),
Instruction::CALL => call_cost(state, false),
Instruction::CALLCODE => call_cost(state, true),
Instruction::DELEGATECALL => unimplemented!(),
Instruction::SUICIDE => suicide_cost(state),
Instruction::SSTORE => sstore_cost(state),

Expand Down
14 changes: 11 additions & 3 deletions sputnikvm/src/vm/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ impl<M> State<M> {
pub fn available_gas(&self) -> Gas {
self.context.gas_limit - self.memory_gas() - self.used_gas
}

pub fn total_used_gas(&self) -> Gas {
self.memory_gas() + self.used_gas
}
}

/// A VM state with PC.
Expand Down Expand Up @@ -248,10 +252,12 @@ impl<M: Memory + Default> Machine<M> {

match sub.status() {
MachineStatus::ExitedOk => {
let sub_total_used_gas = sub.state.total_used_gas();

self.state.account_state = sub.state.account_state;
self.state.blockhash_state = sub.state.blockhash_state;
self.state.logs = sub.state.logs;
self.state.used_gas = self.state.used_gas + sub.state.used_gas;
self.state.used_gas = self.state.used_gas + sub_total_used_gas;
self.state.refunded_gas = self.state.refunded_gas + sub.state.refunded_gas;
if self.state.available_gas() >= code_deposit_gas(sub.state.out.len()) {
self.state.account_state.decrease_balance(sub.state.context.caller,
Expand Down Expand Up @@ -279,18 +285,20 @@ impl<M: Memory + Default> Machine<M> {

match sub.status() {
MachineStatus::ExitedOk => {
let sub_total_used_gas = sub.state.total_used_gas();

self.state.account_state = sub.state.account_state;
self.state.blockhash_state = sub.state.blockhash_state;
self.state.logs = sub.state.logs;
self.state.used_gas = self.state.used_gas + sub.state.used_gas;
self.state.used_gas = self.state.used_gas + sub_total_used_gas;
self.state.refunded_gas = self.state.refunded_gas + sub.state.refunded_gas;
copy_into_memory(&mut self.state.memory, sub.state.out.as_slice(),
out_start, M256::zero(), out_len);
},
MachineStatus::ExitedErr(_) => {
// self.state.used_gas = self.state.used_gas + sub.state.used_gas;
self.state.stack.pop().unwrap();
self.state.stack.push(M256::from(1u64)).unwrap();
self.state.stack.push(M256::zero()).unwrap();
},
_ => panic!(),
}
Expand Down
29 changes: 26 additions & 3 deletions sputnikvm/src/vm/eval/precompiled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,26 @@ use ripemd160::Ripemd160;
use secp256k1::{Secp256k1, RecoverableSignature, Message, RecoveryId, Error};
use digest::{Input, FixedOutput};

fn gas_div_ceil(a: Gas, b: Gas) -> Gas {
if a % b == Gas::zero() {
a / b
} else {
a / b + Gas::from(1u64)
}
}

pub fn is_precompiled(address: Address) -> bool {
let ecrec_address = Address::from_str("0x0000000000000000000000000000000000000001").unwrap();
let sha256_address = Address::from_str("0x0000000000000000000000000000000000000002").unwrap();
let rip160_address = Address::from_str("0x0000000000000000000000000000000000000003").unwrap();
let id_address = Address::from_str("0x0000000000000000000000000000000000000004").unwrap();

address == ecrec_address ||
address == sha256_address ||
address == rip160_address ||
address == id_address
}

impl<M: Memory + Default> Machine<M> {
#[allow(unused_variables)]
pub fn step_precompiled(&mut self) -> bool {
Expand Down Expand Up @@ -39,7 +59,8 @@ impl<M: Memory + Default> Machine<M> {

fn step_precompiled_id(&mut self) {
let gas = Gas::from(15u64) +
Gas::from(3u64) * (Gas::from(self.state.context.data.len()) / Gas::from(32u64));
Gas::from(3u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
Gas::from(32u64));
if gas > self.state.context.gas_limit {
self.state.used_gas = self.state.context.gas_limit;
self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
Expand All @@ -52,7 +73,8 @@ impl<M: Memory + Default> Machine<M> {

fn step_precompiled_rip160(&mut self) {
let gas = Gas::from(600u64) +
Gas::from(120u64) * (Gas::from(self.state.context.data.len()) / Gas::from(32u64));
Gas::from(120u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
Gas::from(32u64));
if gas > self.state.context.gas_limit {
self.state.used_gas = self.state.context.gas_limit;
self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
Expand All @@ -72,7 +94,8 @@ impl<M: Memory + Default> Machine<M> {

fn step_precompiled_sha256(&mut self) {
let gas = Gas::from(60u64) +
Gas::from(12u64) * (Gas::from(self.state.context.data.len()) / Gas::from(32u64));
Gas::from(12u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
Gas::from(32u64));
if gas > self.state.context.gas_limit {
self.state.used_gas = self.state.context.gas_limit;
self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
Expand Down
9 changes: 6 additions & 3 deletions sputnikvm/src/vm/eval/run/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,19 @@ pub fn call<M: Memory + Default>(state: &mut State<M>, stipend_gas: Gas, after_g
let gas_limit = min(gas + stipend_gas, after_gas);

let transaction = Transaction::MessageCall {
address: if as_self { state.context.address } else { to },
address: to,
caller: state.context.address,
gas_price: state.context.gas_price,
gas_limit: gas_limit,
value: value,
data: input,
};
let context = transaction.into_context(
let mut context = transaction.into_context(
Gas::zero(), Some(state.context.origin), &mut state.account_state, true
).unwrap();
push!(state, M256::zero());
if as_self {
context.address = state.context.address;
}
push!(state, M256::from(1u64));
Some((context, (out_start, out_len)))
}
11 changes: 8 additions & 3 deletions sputnikvm/src/vm/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,22 +77,27 @@ impl Transaction {
Transaction::MessageCall {
address, caller, gas_price, gas_limit, value, data
} => {
account_state.require(caller)?;
account_state.require_code(address)?;

if !is_code {
let nonce = account_state.nonce(caller)?;
let nonce = account_state.nonce(caller).unwrap();
account_state.set_nonce(caller, nonce + M256::from(1u64)).unwrap();
}

Ok(Context {
address, caller, data, gas_price, value,
gas_limit: gas_limit - upfront,
code: account_state.code(address)?.into(),
code: account_state.code(address).unwrap().into(),
origin: origin.unwrap_or(caller),
})
},
Transaction::ContractCreation {
caller, gas_price, gas_limit, value, init,
} => {
let nonce = account_state.nonce(caller)?;
account_state.require(caller)?;

let nonce = account_state.nonce(caller).unwrap();
account_state.set_nonce(caller, nonce + M256::from(1u64)).unwrap();

let mut rlp = RlpStream::new_list(2);
Expand Down

0 comments on commit 1ed74b8

Please sign in to comment.