Get rid of duplicated code (#2915)
This commit is contained in:
parent
152a551e8b
commit
dedc4d5cfc
@ -173,7 +173,7 @@ lazy_static! {
|
|||||||
arr[SIGNEXTEND as usize] = InstructionInfo::new("SIGNEXTEND", 0, 2, 1, false, GasPriceTier::Low);
|
arr[SIGNEXTEND as usize] = InstructionInfo::new("SIGNEXTEND", 0, 2, 1, false, GasPriceTier::Low);
|
||||||
arr[SHA3 as usize] = InstructionInfo::new("SHA3", 0, 2, 1, false, GasPriceTier::Special);
|
arr[SHA3 as usize] = InstructionInfo::new("SHA3", 0, 2, 1, false, GasPriceTier::Special);
|
||||||
arr[ADDRESS as usize] = InstructionInfo::new("ADDRESS", 0, 0, 1, false, GasPriceTier::Base);
|
arr[ADDRESS as usize] = InstructionInfo::new("ADDRESS", 0, 0, 1, false, GasPriceTier::Base);
|
||||||
arr[BALANCE as usize] = InstructionInfo::new("BALANCE", 0, 1, 1, false, GasPriceTier::Ext);
|
arr[BALANCE as usize] = InstructionInfo::new("BALANCE", 0, 1, 1, false, GasPriceTier::Special);
|
||||||
arr[ORIGIN as usize] = InstructionInfo::new("ORIGIN", 0, 0, 1, false, GasPriceTier::Base);
|
arr[ORIGIN as usize] = InstructionInfo::new("ORIGIN", 0, 0, 1, false, GasPriceTier::Base);
|
||||||
arr[CALLER as usize] = InstructionInfo::new("CALLER", 0, 0, 1, false, GasPriceTier::Base);
|
arr[CALLER as usize] = InstructionInfo::new("CALLER", 0, 0, 1, false, GasPriceTier::Base);
|
||||||
arr[CALLVALUE as usize] = InstructionInfo::new("CALLVALUE", 0, 0, 1, false, GasPriceTier::Base);
|
arr[CALLVALUE as usize] = InstructionInfo::new("CALLVALUE", 0, 0, 1, false, GasPriceTier::Base);
|
||||||
@ -183,8 +183,8 @@ lazy_static! {
|
|||||||
arr[CODESIZE as usize] = InstructionInfo::new("CODESIZE", 0, 0, 1, false, GasPriceTier::Base);
|
arr[CODESIZE as usize] = InstructionInfo::new("CODESIZE", 0, 0, 1, false, GasPriceTier::Base);
|
||||||
arr[CODECOPY as usize] = InstructionInfo::new("CODECOPY", 0, 3, 0, true, GasPriceTier::VeryLow);
|
arr[CODECOPY as usize] = InstructionInfo::new("CODECOPY", 0, 3, 0, true, GasPriceTier::VeryLow);
|
||||||
arr[GASPRICE as usize] = InstructionInfo::new("GASPRICE", 0, 0, 1, false, GasPriceTier::Base);
|
arr[GASPRICE as usize] = InstructionInfo::new("GASPRICE", 0, 0, 1, false, GasPriceTier::Base);
|
||||||
arr[EXTCODESIZE as usize] = InstructionInfo::new("EXTCODESIZE", 0, 1, 1, false, GasPriceTier::Ext);
|
arr[EXTCODESIZE as usize] = InstructionInfo::new("EXTCODESIZE", 0, 1, 1, false, GasPriceTier::Special);
|
||||||
arr[EXTCODECOPY as usize] = InstructionInfo::new("EXTCODECOPY", 0, 4, 0, true, GasPriceTier::Ext);
|
arr[EXTCODECOPY as usize] = InstructionInfo::new("EXTCODECOPY", 0, 4, 0, true, GasPriceTier::Special);
|
||||||
arr[BLOCKHASH as usize] = InstructionInfo::new("BLOCKHASH", 0, 1, 1, false, GasPriceTier::Ext);
|
arr[BLOCKHASH as usize] = InstructionInfo::new("BLOCKHASH", 0, 1, 1, false, GasPriceTier::Ext);
|
||||||
arr[COINBASE as usize] = InstructionInfo::new("COINBASE", 0, 0, 1, false, GasPriceTier::Base);
|
arr[COINBASE as usize] = InstructionInfo::new("COINBASE", 0, 0, 1, false, GasPriceTier::Base);
|
||||||
arr[TIMESTAMP as usize] = InstructionInfo::new("TIMESTAMP", 0, 0, 1, false, GasPriceTier::Base);
|
arr[TIMESTAMP as usize] = InstructionInfo::new("TIMESTAMP", 0, 0, 1, false, GasPriceTier::Base);
|
||||||
@ -277,7 +277,7 @@ lazy_static! {
|
|||||||
arr[CALLCODE as usize] = InstructionInfo::new("CALLCODE", 0, 7, 1, true, GasPriceTier::Special);
|
arr[CALLCODE as usize] = InstructionInfo::new("CALLCODE", 0, 7, 1, true, GasPriceTier::Special);
|
||||||
arr[RETURN as usize] = InstructionInfo::new("RETURN", 0, 2, 0, true, GasPriceTier::Zero);
|
arr[RETURN as usize] = InstructionInfo::new("RETURN", 0, 2, 0, true, GasPriceTier::Zero);
|
||||||
arr[DELEGATECALL as usize] = InstructionInfo::new("DELEGATECALL", 0, 6, 1, true, GasPriceTier::Special);
|
arr[DELEGATECALL as usize] = InstructionInfo::new("DELEGATECALL", 0, 6, 1, true, GasPriceTier::Special);
|
||||||
arr[SUICIDE as usize] = InstructionInfo::new("SUICIDE", 0, 1, 0, true, GasPriceTier::Zero);
|
arr[SUICIDE as usize] = InstructionInfo::new("SUICIDE", 0, 1, 0, true, GasPriceTier::Special);
|
||||||
arr
|
arr
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -30,12 +30,20 @@ macro_rules! overflowing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature="dev", allow(enum_variant_names))]
|
#[cfg_attr(feature="dev", allow(enum_variant_names))]
|
||||||
enum InstructionCost<Cost: CostType> {
|
enum Request<Cost: CostType> {
|
||||||
Gas(Cost),
|
Gas(Cost),
|
||||||
GasMem(Cost, Cost, Option<Cost>),
|
GasMem(Cost, Cost),
|
||||||
|
GasMemProvide(Cost, Cost, Option<U256>),
|
||||||
GasMemCopy(Cost, Cost, Cost)
|
GasMemCopy(Cost, Cost, Cost)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct InstructionRequirements<Cost: CostType> {
|
||||||
|
pub gas_cost: Cost,
|
||||||
|
pub provide_gas: Option<Cost>,
|
||||||
|
pub memory_total_gas: Cost,
|
||||||
|
pub memory_required_size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Gasometer<Gas: CostType> {
|
pub struct Gasometer<Gas: CostType> {
|
||||||
pub current_gas: Gas,
|
pub current_gas: Gas,
|
||||||
pub current_mem_gas: Gas,
|
pub current_mem_gas: Gas,
|
||||||
@ -59,11 +67,19 @@ impl<Gas: CostType> Gasometer<Gas> {
|
|||||||
|
|
||||||
/// How much gas is provided to a CALL/CREATE, given that we need to deduct `needed` for this operation
|
/// How much gas is provided to a CALL/CREATE, given that we need to deduct `needed` for this operation
|
||||||
/// and that we `requested` some.
|
/// and that we `requested` some.
|
||||||
pub fn gas_provided(&self, schedule: &Schedule, needed: Gas, requested: Option<evm::Result<Gas>>) -> evm::Result<Gas> {
|
pub fn gas_provided(&self, schedule: &Schedule, needed: Gas, requested: Option<U256>) -> evm::Result<Gas> {
|
||||||
|
// Try converting requested gas to `Gas` (`U256/u64`)
|
||||||
|
// but in EIP150 even if we request more we should never fail from OOG
|
||||||
|
let requested = requested.map(Gas::from_u256);
|
||||||
|
|
||||||
match schedule.sub_gas_cap_divisor {
|
match schedule.sub_gas_cap_divisor {
|
||||||
Some(cap_divisor) if self.current_gas >= needed => {
|
Some(cap_divisor) if self.current_gas >= needed => {
|
||||||
let gas_remaining = self.current_gas - needed;
|
let gas_remaining = self.current_gas - needed;
|
||||||
let max_gas_provided = gas_remaining - gas_remaining / Gas::from(cap_divisor);
|
let max_gas_provided = match cap_divisor {
|
||||||
|
64 => gas_remaining - (gas_remaining >> 6),
|
||||||
|
cap_divisor => gas_remaining - gas_remaining / Gas::from(cap_divisor),
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(Ok(r)) = requested {
|
if let Some(Ok(r)) = requested {
|
||||||
Ok(min(r, max_gas_provided))
|
Ok(min(r, max_gas_provided))
|
||||||
} else {
|
} else {
|
||||||
@ -78,7 +94,7 @@ impl<Gas: CostType> Gasometer<Gas> {
|
|||||||
} else {
|
} else {
|
||||||
Ok(0.into())
|
Ok(0.into())
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,21 +104,21 @@ impl<Gas: CostType> Gasometer<Gas> {
|
|||||||
/// We guarantee that the final element of the returned tuple (`provided`) will be `Some`
|
/// We guarantee that the final element of the returned tuple (`provided`) will be `Some`
|
||||||
/// iff the `instruction` is one of `CREATE`, or any of the `CALL` variants. In this case,
|
/// iff the `instruction` is one of `CREATE`, or any of the `CALL` variants. In this case,
|
||||||
/// it will be the amount of gas that the current context provides to the child context.
|
/// it will be the amount of gas that the current context provides to the child context.
|
||||||
pub fn get_gas_cost_mem(
|
pub fn requirements(
|
||||||
&mut self,
|
&mut self,
|
||||||
ext: &evm::Ext,
|
ext: &evm::Ext,
|
||||||
instruction: Instruction,
|
instruction: Instruction,
|
||||||
info: &InstructionInfo,
|
info: &InstructionInfo,
|
||||||
stack: &Stack<U256>,
|
stack: &Stack<U256>,
|
||||||
current_mem_size: usize,
|
current_mem_size: usize,
|
||||||
) -> evm::Result<(Gas, Gas, usize, Option<Gas>)> {
|
) -> evm::Result<InstructionRequirements<Gas>> {
|
||||||
let schedule = ext.schedule();
|
let schedule = ext.schedule();
|
||||||
let tier = instructions::get_tier_idx(info.tier);
|
let tier = instructions::get_tier_idx(info.tier);
|
||||||
let default_gas = Gas::from(schedule.tier_step_gas[tier]);
|
let default_gas = Gas::from(schedule.tier_step_gas[tier]);
|
||||||
|
|
||||||
let cost = match instruction {
|
let cost = match instruction {
|
||||||
instructions::JUMPDEST => {
|
instructions::JUMPDEST => {
|
||||||
InstructionCost::Gas(Gas::from(1))
|
Request::Gas(Gas::from(1))
|
||||||
},
|
},
|
||||||
instructions::SSTORE => {
|
instructions::SSTORE => {
|
||||||
let address = H256::from(stack.peek(0));
|
let address = H256::from(stack.peek(0));
|
||||||
@ -116,16 +132,16 @@ impl<Gas: CostType> Gasometer<Gas> {
|
|||||||
// !is_zero(&val) && is_zero(newval)
|
// !is_zero(&val) && is_zero(newval)
|
||||||
schedule.sstore_reset_gas
|
schedule.sstore_reset_gas
|
||||||
};
|
};
|
||||||
InstructionCost::Gas(Gas::from(gas))
|
Request::Gas(Gas::from(gas))
|
||||||
},
|
},
|
||||||
instructions::SLOAD => {
|
instructions::SLOAD => {
|
||||||
InstructionCost::Gas(Gas::from(schedule.sload_gas))
|
Request::Gas(Gas::from(schedule.sload_gas))
|
||||||
},
|
},
|
||||||
instructions::BALANCE => {
|
instructions::BALANCE => {
|
||||||
InstructionCost::Gas(Gas::from(schedule.balance_gas))
|
Request::Gas(Gas::from(schedule.balance_gas))
|
||||||
},
|
},
|
||||||
instructions::EXTCODESIZE => {
|
instructions::EXTCODESIZE => {
|
||||||
InstructionCost::Gas(Gas::from(schedule.extcodesize_gas))
|
Request::Gas(Gas::from(schedule.extcodesize_gas))
|
||||||
},
|
},
|
||||||
instructions::SUICIDE => {
|
instructions::SUICIDE => {
|
||||||
let mut gas = Gas::from(schedule.suicide_gas);
|
let mut gas = Gas::from(schedule.suicide_gas);
|
||||||
@ -135,28 +151,28 @@ impl<Gas: CostType> Gasometer<Gas> {
|
|||||||
gas = overflowing!(gas.overflow_add(schedule.suicide_to_new_account_cost.into()));
|
gas = overflowing!(gas.overflow_add(schedule.suicide_to_new_account_cost.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionCost::Gas(gas)
|
Request::Gas(gas)
|
||||||
},
|
},
|
||||||
instructions::MSTORE | instructions::MLOAD => {
|
instructions::MSTORE | instructions::MLOAD => {
|
||||||
InstructionCost::GasMem(default_gas, try!(mem_needed_const(stack.peek(0), 32)), None)
|
Request::GasMem(default_gas, try!(mem_needed_const(stack.peek(0), 32)))
|
||||||
},
|
},
|
||||||
instructions::MSTORE8 => {
|
instructions::MSTORE8 => {
|
||||||
InstructionCost::GasMem(default_gas, try!(mem_needed_const(stack.peek(0), 1)), None)
|
Request::GasMem(default_gas, try!(mem_needed_const(stack.peek(0), 1)))
|
||||||
},
|
},
|
||||||
instructions::RETURN => {
|
instructions::RETURN => {
|
||||||
InstructionCost::GasMem(default_gas, try!(mem_needed(stack.peek(0), stack.peek(1))), None)
|
Request::GasMem(default_gas, try!(mem_needed(stack.peek(0), stack.peek(1))))
|
||||||
},
|
},
|
||||||
instructions::SHA3 => {
|
instructions::SHA3 => {
|
||||||
let w = overflowing!(add_gas_usize(try!(Gas::from_u256(*stack.peek(1))), 31));
|
let w = overflowing!(add_gas_usize(try!(Gas::from_u256(*stack.peek(1))), 31));
|
||||||
let words = w >> 5;
|
let words = w >> 5;
|
||||||
let gas = Gas::from(schedule.sha3_gas) + (Gas::from(schedule.sha3_word_gas) * words);
|
let gas = Gas::from(schedule.sha3_gas) + (Gas::from(schedule.sha3_word_gas) * words);
|
||||||
InstructionCost::GasMem(gas, try!(mem_needed(stack.peek(0), stack.peek(1))), None)
|
Request::GasMem(gas, try!(mem_needed(stack.peek(0), stack.peek(1))))
|
||||||
},
|
},
|
||||||
instructions::CALLDATACOPY | instructions::CODECOPY => {
|
instructions::CALLDATACOPY | instructions::CODECOPY => {
|
||||||
InstructionCost::GasMemCopy(default_gas, try!(mem_needed(stack.peek(0), stack.peek(2))), try!(Gas::from_u256(*stack.peek(2))))
|
Request::GasMemCopy(default_gas, try!(mem_needed(stack.peek(0), stack.peek(2))), try!(Gas::from_u256(*stack.peek(2))))
|
||||||
},
|
},
|
||||||
instructions::EXTCODECOPY => {
|
instructions::EXTCODECOPY => {
|
||||||
InstructionCost::GasMemCopy(schedule.extcodecopy_base_gas.into(), try!(mem_needed(stack.peek(1), stack.peek(3))), try!(Gas::from_u256(*stack.peek(3))))
|
Request::GasMemCopy(schedule.extcodecopy_base_gas.into(), try!(mem_needed(stack.peek(1), stack.peek(3))), try!(Gas::from_u256(*stack.peek(3))))
|
||||||
},
|
},
|
||||||
instructions::LOG0...instructions::LOG4 => {
|
instructions::LOG0...instructions::LOG4 => {
|
||||||
let no_of_topics = instructions::get_log_topics(instruction);
|
let no_of_topics = instructions::get_log_topics(instruction);
|
||||||
@ -164,7 +180,7 @@ impl<Gas: CostType> Gasometer<Gas> {
|
|||||||
|
|
||||||
let data_gas = overflowing!(try!(Gas::from_u256(*stack.peek(1))).overflow_mul(Gas::from(schedule.log_data_gas)));
|
let data_gas = overflowing!(try!(Gas::from_u256(*stack.peek(1))).overflow_mul(Gas::from(schedule.log_data_gas)));
|
||||||
let gas = overflowing!(data_gas.overflow_add(Gas::from(log_gas)));
|
let gas = overflowing!(data_gas.overflow_add(Gas::from(log_gas)));
|
||||||
InstructionCost::GasMem(gas, try!(mem_needed(stack.peek(0), stack.peek(1))), None)
|
Request::GasMem(gas, try!(mem_needed(stack.peek(0), stack.peek(1))))
|
||||||
},
|
},
|
||||||
instructions::CALL | instructions::CALLCODE => {
|
instructions::CALL | instructions::CALLCODE => {
|
||||||
let mut gas = Gas::from(schedule.call_gas);
|
let mut gas = Gas::from(schedule.call_gas);
|
||||||
@ -183,70 +199,82 @@ impl<Gas: CostType> Gasometer<Gas> {
|
|||||||
gas = overflowing!(gas.overflow_add(schedule.call_value_transfer_gas.into()));
|
gas = overflowing!(gas.overflow_add(schedule.call_value_transfer_gas.into()));
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: refactor to avoid duplicate calculation here and later on.
|
let requested = *stack.peek(0);
|
||||||
let (mem_gas_cost, _, _) = try!(self.mem_gas_cost(schedule, current_mem_size, &mem));
|
|
||||||
let cost_so_far = overflowing!(gas.overflow_add(mem_gas_cost.into()));
|
|
||||||
let requested = Gas::from_u256(*stack.peek(0));
|
|
||||||
let provided = try!(self.gas_provided(schedule, cost_so_far, Some(requested)));
|
|
||||||
gas = overflowing!(gas.overflow_add(provided));
|
|
||||||
|
|
||||||
InstructionCost::GasMem(gas, mem, Some(provided))
|
Request::GasMemProvide(gas, mem, Some(requested))
|
||||||
},
|
},
|
||||||
instructions::DELEGATECALL => {
|
instructions::DELEGATECALL => {
|
||||||
let mut gas = Gas::from(schedule.call_gas);
|
let gas = Gas::from(schedule.call_gas);
|
||||||
let mem = cmp::max(
|
let mem = cmp::max(
|
||||||
try!(mem_needed(stack.peek(4), stack.peek(5))),
|
try!(mem_needed(stack.peek(4), stack.peek(5))),
|
||||||
try!(mem_needed(stack.peek(2), stack.peek(3)))
|
try!(mem_needed(stack.peek(2), stack.peek(3)))
|
||||||
);
|
);
|
||||||
|
let requested = *stack.peek(0);
|
||||||
|
|
||||||
// TODO: refactor to avoid duplicate calculation here and later on.
|
Request::GasMemProvide(gas, mem, Some(requested))
|
||||||
let (mem_gas_cost, _, _) = try!(self.mem_gas_cost(schedule, current_mem_size, &mem));
|
|
||||||
let cost_so_far = overflowing!(gas.overflow_add(mem_gas_cost.into()));
|
|
||||||
let requested = Gas::from_u256(*stack.peek(0));
|
|
||||||
let provided = try!(self.gas_provided(schedule, cost_so_far, Some(requested)));
|
|
||||||
gas = overflowing!(gas.overflow_add(provided));
|
|
||||||
|
|
||||||
InstructionCost::GasMem(gas, mem, Some(provided))
|
|
||||||
},
|
},
|
||||||
instructions::CREATE => {
|
instructions::CREATE => {
|
||||||
let mut gas = Gas::from(schedule.create_gas);
|
let gas = Gas::from(schedule.create_gas);
|
||||||
let mem = try!(mem_needed(stack.peek(1), stack.peek(2)));
|
let mem = try!(mem_needed(stack.peek(1), stack.peek(2)));
|
||||||
|
|
||||||
// TODO: refactor to avoid duplicate calculation here and later on.
|
Request::GasMemProvide(gas, mem, None)
|
||||||
let (mem_gas_cost, _, _) = try!(self.mem_gas_cost(schedule, current_mem_size, &mem));
|
|
||||||
let cost_so_far = overflowing!(gas.overflow_add(mem_gas_cost.into()));
|
|
||||||
let provided = try!(self.gas_provided(schedule, cost_so_far, None));
|
|
||||||
gas = overflowing!(gas.overflow_add(provided));
|
|
||||||
|
|
||||||
InstructionCost::GasMem(gas, mem, Some(provided))
|
|
||||||
},
|
},
|
||||||
instructions::EXP => {
|
instructions::EXP => {
|
||||||
let expon = stack.peek(1);
|
let expon = stack.peek(1);
|
||||||
let bytes = ((expon.bits() + 7) / 8) as usize;
|
let bytes = ((expon.bits() + 7) / 8) as usize;
|
||||||
let gas = Gas::from(schedule.exp_gas + schedule.exp_byte_gas * bytes);
|
let gas = Gas::from(schedule.exp_gas + schedule.exp_byte_gas * bytes);
|
||||||
InstructionCost::Gas(gas)
|
Request::Gas(gas)
|
||||||
},
|
},
|
||||||
_ => InstructionCost::Gas(default_gas),
|
_ => Request::Gas(default_gas),
|
||||||
};
|
};
|
||||||
|
|
||||||
match cost {
|
Ok(match cost {
|
||||||
InstructionCost::Gas(gas) => {
|
Request::Gas(gas) => {
|
||||||
Ok((gas, self.current_mem_gas, 0, None))
|
InstructionRequirements {
|
||||||
|
gas_cost: gas,
|
||||||
|
provide_gas: None,
|
||||||
|
memory_required_size: 0,
|
||||||
|
memory_total_gas: self.current_mem_gas,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
InstructionCost::GasMem(gas, mem_size, provided) => {
|
Request::GasMem(gas, mem_size) => {
|
||||||
let (mem_gas_cost, new_mem_gas, new_mem_size) = try!(self.mem_gas_cost(schedule, current_mem_size, &mem_size));
|
let (mem_gas_cost, new_mem_gas, new_mem_size) = try!(self.mem_gas_cost(schedule, current_mem_size, &mem_size));
|
||||||
let gas = overflowing!(gas.overflow_add(mem_gas_cost));
|
let gas = overflowing!(gas.overflow_add(mem_gas_cost));
|
||||||
Ok((gas, new_mem_gas, new_mem_size, provided))
|
InstructionRequirements {
|
||||||
|
gas_cost: gas,
|
||||||
|
provide_gas: None,
|
||||||
|
memory_required_size: new_mem_size,
|
||||||
|
memory_total_gas: new_mem_gas,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
InstructionCost::GasMemCopy(gas, mem_size, copy) => {
|
Request::GasMemProvide(gas, mem_size, requested) => {
|
||||||
|
let (mem_gas_cost, new_mem_gas, new_mem_size) = try!(self.mem_gas_cost(schedule, current_mem_size, &mem_size));
|
||||||
|
let gas = overflowing!(gas.overflow_add(mem_gas_cost));
|
||||||
|
let provided = try!(self.gas_provided(schedule, gas, requested));
|
||||||
|
let total_gas = overflowing!(gas.overflow_add(provided));
|
||||||
|
|
||||||
|
InstructionRequirements {
|
||||||
|
gas_cost: total_gas,
|
||||||
|
provide_gas: Some(provided),
|
||||||
|
memory_required_size: new_mem_size,
|
||||||
|
memory_total_gas: new_mem_gas,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Request::GasMemCopy(gas, mem_size, copy) => {
|
||||||
let (mem_gas_cost, new_mem_gas, new_mem_size) = try!(self.mem_gas_cost(schedule, current_mem_size, &mem_size));
|
let (mem_gas_cost, new_mem_gas, new_mem_size) = try!(self.mem_gas_cost(schedule, current_mem_size, &mem_size));
|
||||||
let copy = overflowing!(add_gas_usize(copy, 31)) >> 5;
|
let copy = overflowing!(add_gas_usize(copy, 31)) >> 5;
|
||||||
let copy_gas = Gas::from(schedule.copy_gas) * copy;
|
let copy_gas = Gas::from(schedule.copy_gas) * copy;
|
||||||
let gas = overflowing!(gas.overflow_add(copy_gas));
|
let gas = overflowing!(gas.overflow_add(copy_gas));
|
||||||
let gas = overflowing!(gas.overflow_add(mem_gas_cost));
|
let gas = overflowing!(gas.overflow_add(mem_gas_cost));
|
||||||
Ok((gas, new_mem_gas, new_mem_size, None))
|
|
||||||
}
|
InstructionRequirements {
|
||||||
}
|
gas_cost: gas,
|
||||||
|
provide_gas: None,
|
||||||
|
memory_required_size: new_mem_size,
|
||||||
|
memory_total_gas: new_mem_gas,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mem_gas_cost(&self, schedule: &evm::Schedule, current_mem_size: usize, mem_size: &Gas) -> evm::Result<(Gas, Gas, usize)> {
|
fn mem_gas_cost(&self, schedule: &evm::Schedule, current_mem_size: usize, mem_size: &Gas) -> evm::Result<(Gas, Gas, usize)> {
|
||||||
@ -256,7 +284,7 @@ impl<Gas: CostType> Gasometer<Gas> {
|
|||||||
let a = overflowing!(s.overflow_mul(Gas::from(schedule.memory_gas)));
|
let a = overflowing!(s.overflow_mul(Gas::from(schedule.memory_gas)));
|
||||||
|
|
||||||
// Calculate s*s/quad_coeff_div
|
// Calculate s*s/quad_coeff_div
|
||||||
debug_assert_eq!(schedule.quad_coeff_div, 512);
|
assert_eq!(schedule.quad_coeff_div, 512);
|
||||||
let b = overflowing!(s.overflow_mul_shr(s, 9));
|
let b = overflowing!(s.overflow_mul_shr(s, 9));
|
||||||
Ok(overflowing!(a.overflow_add(b)))
|
Ok(overflowing!(a.overflow_add(b)))
|
||||||
};
|
};
|
||||||
@ -328,3 +356,4 @@ fn test_calculate_mem_cost() {
|
|||||||
assert_eq!(new_mem_gas, 3);
|
assert_eq!(new_mem_gas, 3);
|
||||||
assert_eq!(mem_size, 32);
|
assert_eq!(mem_size, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,14 +120,14 @@ impl<Cost: CostType> evm::Evm for Interpreter<Cost> {
|
|||||||
try!(self.verify_instruction(ext, instruction, info, &stack));
|
try!(self.verify_instruction(ext, instruction, info, &stack));
|
||||||
|
|
||||||
// Calculate gas cost
|
// Calculate gas cost
|
||||||
let (gas_cost, mem_gas, mem_size, provided) = try!(gasometer.get_gas_cost_mem(ext, instruction, info, &stack, self.mem.size()));
|
let requirements = try!(gasometer.requirements(ext, instruction, info, &stack, self.mem.size()));
|
||||||
// TODO: make compile-time removable if too much of a performance hit.
|
// TODO: make compile-time removable if too much of a performance hit.
|
||||||
let trace_executed = ext.trace_prepare_execute(reader.position - 1, instruction, &gas_cost.as_u256());
|
let trace_executed = ext.trace_prepare_execute(reader.position - 1, instruction, &requirements.gas_cost.as_u256());
|
||||||
|
|
||||||
try!(gasometer.verify_gas(&gas_cost));
|
try!(gasometer.verify_gas(&requirements.gas_cost));
|
||||||
self.mem.expand(mem_size);
|
self.mem.expand(requirements.memory_required_size);
|
||||||
gasometer.current_mem_gas = mem_gas;
|
gasometer.current_mem_gas = requirements.memory_total_gas;
|
||||||
gasometer.current_gas = gasometer.current_gas - gas_cost;
|
gasometer.current_gas = gasometer.current_gas - requirements.gas_cost;
|
||||||
|
|
||||||
evm_debug!({ informant.before_instruction(reader.position, instruction, info, &gasometer.current_gas, &stack) });
|
evm_debug!({ informant.before_instruction(reader.position, instruction, info, &gasometer.current_gas, &stack) });
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ impl<Cost: CostType> evm::Evm for Interpreter<Cost> {
|
|||||||
|
|
||||||
// Execute instruction
|
// Execute instruction
|
||||||
let result = try!(self.exec_instruction(
|
let result = try!(self.exec_instruction(
|
||||||
gasometer.current_gas, ¶ms, ext, instruction, &mut reader, &mut stack, provided
|
gasometer.current_gas, ¶ms, ext, instruction, &mut reader, &mut stack, requirements.provide_gas
|
||||||
));
|
));
|
||||||
|
|
||||||
evm_debug!({ informant.after_instruction(instruction) });
|
evm_debug!({ informant.after_instruction(instruction) });
|
||||||
|
38
evmbin/Cargo.lock
generated
38
evmbin/Cargo.lock
generated
@ -155,7 +155,7 @@ name = "ethash"
|
|||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"sha3 0.1.0",
|
"sha3 0.1.0",
|
||||||
]
|
]
|
||||||
@ -208,6 +208,9 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ethcore-bloom-journal"
|
name = "ethcore-bloom-journal"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"siphasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ethcore-devtools"
|
name = "ethcore-devtools"
|
||||||
@ -223,7 +226,7 @@ dependencies = [
|
|||||||
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)",
|
"mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)",
|
||||||
"parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -275,8 +278,9 @@ dependencies = [
|
|||||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rlp 0.1.0",
|
"rlp 0.1.0",
|
||||||
"rocksdb 0.4.5 (git+https://github.com/ethcore/rust-rocksdb)",
|
"rocksdb 0.4.5 (git+https://github.com/ethcore/rust-rocksdb)",
|
||||||
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -334,6 +338,7 @@ dependencies = [
|
|||||||
"itertools 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"itertools 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -632,13 +637,28 @@ name = "odds"
|
|||||||
version = "0.2.23"
|
version = "0.2.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "owning_ref"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.2.8"
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"parking_lot_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -867,6 +887,11 @@ dependencies = [
|
|||||||
"gcc 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gcc 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "siphasher"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
@ -1179,7 +1204,9 @@ dependencies = [
|
|||||||
"checksum num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a16a42856a256b39c6d3484f097f6713e14feacd9bfb02290917904fae46c81c"
|
"checksum num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a16a42856a256b39c6d3484f097f6713e14feacd9bfb02290917904fae46c81c"
|
||||||
"checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3"
|
"checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3"
|
||||||
"checksum odds 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e04630a62b3f1cc8c58b4d8f2555a40136f02b420e158242936ef286a72d33a0"
|
"checksum odds 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e04630a62b3f1cc8c58b4d8f2555a40136f02b420e158242936ef286a72d33a0"
|
||||||
"checksum parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "968f685642555d2f7e202c48b8b11de80569e9bfea817f7f12d7c61aac62d4e6"
|
"checksum owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d91377085359426407a287ab16884a0111ba473aa6844ff01d4ec20ce3d75e7"
|
||||||
|
"checksum parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e1435e7a2a00dfebededd6c6bdbd54008001e94b4a2aadd6aef0dc4c56317621"
|
||||||
|
"checksum parking_lot_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb1b97670a2ffadce7c397fb80a3d687c4f3060140b885621ef1653d0e5d5068"
|
||||||
"checksum primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0e31b86efadeaeb1235452171a66689682783149a6249ff334a2c5d8218d00a4"
|
"checksum primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0e31b86efadeaeb1235452171a66689682783149a6249ff334a2c5d8218d00a4"
|
||||||
"checksum primal-bit 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "464a91febc06166783d4f5ba3577b5ed8dda8e421012df80bfe48a971ed7be8f"
|
"checksum primal-bit 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "464a91febc06166783d4f5ba3577b5ed8dda8e421012df80bfe48a971ed7be8f"
|
||||||
"checksum primal-check 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "647c81b67bb9551a7b88d0bcd785ac35b7d0bf4b2f358683d7c2375d04daec51"
|
"checksum primal-check 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "647c81b67bb9551a7b88d0bcd785ac35b7d0bf4b2f358683d7c2375d04daec51"
|
||||||
@ -1205,6 +1232,7 @@ dependencies = [
|
|||||||
"checksum serde_codegen 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e575e583f7d162e163af117fb9791fbd2bd203c31023b3219617e12c5997a738"
|
"checksum serde_codegen 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e575e583f7d162e163af117fb9791fbd2bd203c31023b3219617e12c5997a738"
|
||||||
"checksum serde_codegen_internals 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "318f7e77aa5187391d74aaf4553d2189f56b0ce25e963414c951b97877ffdcec"
|
"checksum serde_codegen_internals 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "318f7e77aa5187391d74aaf4553d2189f56b0ce25e963414c951b97877ffdcec"
|
||||||
"checksum serde_json 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1cb6b19e74d9f65b9d03343730b643d729a446b29376785cd65efdff4675e2fc"
|
"checksum serde_json 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1cb6b19e74d9f65b9d03343730b643d729a446b29376785cd65efdff4675e2fc"
|
||||||
|
"checksum siphasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c44e42fa187b5a8782489cf7740cc27c3125806be2bf33563cf5e02e9533fcd"
|
||||||
"checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e"
|
"checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e"
|
||||||
"checksum slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dbdd334bd28d328dad1c41b0ea662517883d8880d8533895ef96c8003dec9c4"
|
"checksum slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dbdd334bd28d328dad1c41b0ea662517883d8880d8533895ef96c8003dec9c4"
|
||||||
"checksum smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcc8d19212aacecf95e4a7a2179b26f7aeb9732a915cf01f05b0d3e044865410"
|
"checksum smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcc8d19212aacecf95e4a7a2179b26f7aeb9732a915cf01f05b0d3e044865410"
|
||||||
|
@ -31,7 +31,7 @@ pub struct FakeExt {
|
|||||||
impl Default for FakeExt {
|
impl Default for FakeExt {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
FakeExt {
|
FakeExt {
|
||||||
schedule: Schedule::new_homestead(),
|
schedule: Schedule::new_homestead_gas_fix(),
|
||||||
store: HashMap::new(),
|
store: HashMap::new(),
|
||||||
depth: 1,
|
depth: 1,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user