Implement CREATE2 gas changes and fix some potential overflowing (#9694)
* Implement CREATE2 gas changes and fix some potential overflowing * Ignore create2 state tests * Split CREATE and CREATE2 in gasometer * Generalize rounding (x + 31) / 32 to to_word_size
This commit is contained in:
parent
4186467129
commit
c8ae675b95
@ -63,7 +63,7 @@ impl Finalize for Error {
|
||||
|
||||
/// Cost calculation type. For low-gas usage we calculate costs using usize instead of U256
|
||||
pub trait CostType: Sized + From<usize> + Copy + Send
|
||||
+ ops::Mul<Output=Self> + ops::Div<Output=Self> + ops::Add<Output=Self> +ops::Sub<Output=Self>
|
||||
+ ops::Mul<Output=Self> + ops::Div<Output=Self> + ops::Add<Output=Self> + ops::Sub<Output=Self>
|
||||
+ ops::Shr<usize, Output=Self> + ops::Shl<usize, Output=Self>
|
||||
+ cmp::Ord + fmt::Debug {
|
||||
/// Converts this cost into `U256`
|
||||
|
@ -176,9 +176,8 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
||||
Request::GasMem(default_gas, mem_needed(stack.peek(0), stack.peek(1))?)
|
||||
},
|
||||
instructions::SHA3 => {
|
||||
let w = overflowing!(add_gas_usize(Gas::from_u256(*stack.peek(1))?, 31));
|
||||
let words = w >> 5;
|
||||
let gas = Gas::from(schedule.sha3_gas) + (Gas::from(schedule.sha3_word_gas) * words);
|
||||
let words = overflowing!(to_word_size(Gas::from_u256(*stack.peek(1))?));
|
||||
let gas = overflowing!(Gas::from(schedule.sha3_gas).overflow_add(overflowing!(Gas::from(schedule.sha3_word_gas).overflow_mul(words))));
|
||||
Request::GasMem(gas, mem_needed(stack.peek(0), stack.peek(1))?)
|
||||
},
|
||||
instructions::CALLDATACOPY | instructions::CODECOPY | instructions::RETURNDATACOPY => {
|
||||
@ -231,9 +230,24 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
||||
|
||||
Request::GasMemProvide(gas, mem, Some(requested))
|
||||
},
|
||||
instructions::CREATE | instructions::CREATE2 => {
|
||||
instructions::CREATE => {
|
||||
let start = stack.peek(1);
|
||||
let len = stack.peek(2);
|
||||
|
||||
let gas = Gas::from(schedule.create_gas);
|
||||
let mem = mem_needed(stack.peek(1), stack.peek(2))?;
|
||||
let mem = mem_needed(start, len)?;
|
||||
|
||||
Request::GasMemProvide(gas, mem, None)
|
||||
},
|
||||
instructions::CREATE2 => {
|
||||
let start = stack.peek(1);
|
||||
let len = stack.peek(2);
|
||||
|
||||
let base = Gas::from(schedule.create_gas);
|
||||
let word = overflowing!(to_word_size(Gas::from_u256(*len)?));
|
||||
let word_gas = overflowing!(Gas::from(schedule.sha3_word_gas).overflow_mul(word));
|
||||
let gas = overflowing!(base.overflow_add(word_gas));
|
||||
let mem = mem_needed(start, len)?;
|
||||
|
||||
Request::GasMemProvide(gas, mem, None)
|
||||
},
|
||||
@ -283,8 +297,8 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
||||
},
|
||||
Request::GasMemCopy(gas, mem_size, copy) => {
|
||||
let (mem_gas_cost, new_mem_gas, new_mem_size) = self.mem_gas_cost(schedule, current_mem_size, &mem_size)?;
|
||||
let copy = overflowing!(add_gas_usize(copy, 31)) >> 5;
|
||||
let copy_gas = Gas::from(schedule.copy_gas) * copy;
|
||||
let copy = overflowing!(to_word_size(copy));
|
||||
let copy_gas = overflowing!(Gas::from(schedule.copy_gas).overflow_mul(copy));
|
||||
let gas = overflowing!(gas.overflow_add(copy_gas));
|
||||
let gas = overflowing!(gas.overflow_add(mem_gas_cost));
|
||||
|
||||
@ -311,7 +325,7 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
||||
};
|
||||
|
||||
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;
|
||||
let req_mem_size_rounded = overflowing!(to_word_size(*mem_size)) << 5;
|
||||
|
||||
let (mem_gas_cost, new_mem_gas) = if req_mem_size_rounded > current_mem_size {
|
||||
let new_mem_gas = gas_for_mem(req_mem_size_rounded)?;
|
||||
@ -343,6 +357,16 @@ fn add_gas_usize<Gas: evm::CostType>(value: Gas, num: usize) -> (Gas, bool) {
|
||||
value.overflow_add(Gas::from(num))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_word_size<Gas: evm::CostType>(value: Gas) -> (Gas, bool) {
|
||||
let (gas, overflow) = add_gas_usize(value, 31);
|
||||
if overflow {
|
||||
return (gas, overflow);
|
||||
}
|
||||
|
||||
(gas >> 5, false)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn calculate_eip1283_sstore_gas<Gas: evm::CostType>(schedule: &Schedule, original: &U256, current: &U256, new: &U256) -> Gas {
|
||||
Gas::from(
|
||||
|
@ -365,6 +365,104 @@
|
||||
"chain": "Constantinople (test)"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"reference": "9590",
|
||||
"failing": "stCreate2Test",
|
||||
"subtests": {
|
||||
"call_then_create2_successful_then_returndatasize": {
|
||||
"subnumbers": ["1"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"returndatacopy_afterFailing_create": {
|
||||
"subnumbers": ["1"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"create2checkFieldsInInitcode": {
|
||||
"subnumbers": ["1","2","3","5","6","7"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"Create2Recursive": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"create2collisionBalance": {
|
||||
"subnumbers": ["2","3"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"create2InitCodes": {
|
||||
"subnumbers": ["1","5","6","7","8","9"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"Create2OOGafterInitCode": {
|
||||
"subnumbers": ["2"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"CreateMessageRevertedOOGInInit": {
|
||||
"subnumbers": ["2"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"returndatacopy_following_revert_in_create": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"create2collisionSelfdestructed": {
|
||||
"subnumbers": ["2"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"returndatacopy_0_0_following_successful_create": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"Create2OnDepth1023": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"Create2OOGafterInitCodeReturndata2": {
|
||||
"subnumbers": ["2"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"RevertOpcodeInCreateReturns": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"CREATE2_ContractSuicideDuringInit_ThenStoreThenReturn": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"returndatasize_following_successful_create": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"call_outsize_then_create2_successful_then_returndatasize": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"CreateMessageReverted": {
|
||||
"subnumbers": ["2"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"CREATE2_Suicide": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"Create2OOGafterInitCodeRevert": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"Create2OnDepth1024": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"create2collisionStorage": {
|
||||
"subnumbers": ["2","3"],
|
||||
"chain": "Constantinople (test)"
|
||||
},
|
||||
"create2callPrecompiles": {
|
||||
"subnumbers": ["*"],
|
||||
"chain": "Constantinople (test)"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user