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
|
/// Cost calculation type. For low-gas usage we calculate costs using usize instead of U256
|
||||||
pub trait CostType: Sized + From<usize> + Copy + Send
|
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>
|
+ ops::Shr<usize, Output=Self> + ops::Shl<usize, Output=Self>
|
||||||
+ cmp::Ord + fmt::Debug {
|
+ cmp::Ord + fmt::Debug {
|
||||||
/// Converts this cost into `U256`
|
/// 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))?)
|
Request::GasMem(default_gas, mem_needed(stack.peek(0), stack.peek(1))?)
|
||||||
},
|
},
|
||||||
instructions::SHA3 => {
|
instructions::SHA3 => {
|
||||||
let w = overflowing!(add_gas_usize(Gas::from_u256(*stack.peek(1))?, 31));
|
let words = overflowing!(to_word_size(Gas::from_u256(*stack.peek(1))?));
|
||||||
let words = w >> 5;
|
let gas = overflowing!(Gas::from(schedule.sha3_gas).overflow_add(overflowing!(Gas::from(schedule.sha3_word_gas).overflow_mul(words))));
|
||||||
let gas = Gas::from(schedule.sha3_gas) + (Gas::from(schedule.sha3_word_gas) * words);
|
|
||||||
Request::GasMem(gas, mem_needed(stack.peek(0), stack.peek(1))?)
|
Request::GasMem(gas, mem_needed(stack.peek(0), stack.peek(1))?)
|
||||||
},
|
},
|
||||||
instructions::CALLDATACOPY | instructions::CODECOPY | instructions::RETURNDATACOPY => {
|
instructions::CALLDATACOPY | instructions::CODECOPY | instructions::RETURNDATACOPY => {
|
||||||
@ -231,9 +230,24 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
|||||||
|
|
||||||
Request::GasMemProvide(gas, mem, Some(requested))
|
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 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)
|
Request::GasMemProvide(gas, mem, None)
|
||||||
},
|
},
|
||||||
@ -283,8 +297,8 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
|||||||
},
|
},
|
||||||
Request::GasMemCopy(gas, mem_size, copy) => {
|
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 (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 = overflowing!(to_word_size(copy));
|
||||||
let copy_gas = Gas::from(schedule.copy_gas) * 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(copy_gas));
|
||||||
let gas = overflowing!(gas.overflow_add(mem_gas_cost));
|
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 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 (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)?;
|
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))
|
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]
|
#[inline]
|
||||||
fn calculate_eip1283_sstore_gas<Gas: evm::CostType>(schedule: &Schedule, original: &U256, current: &U256, new: &U256) -> Gas {
|
fn calculate_eip1283_sstore_gas<Gas: evm::CostType>(schedule: &Schedule, original: &U256, current: &U256, new: &U256) -> Gas {
|
||||||
Gas::from(
|
Gas::from(
|
||||||
|
@ -365,6 +365,104 @@
|
|||||||
"chain": "Constantinople (test)"
|
"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