core/vm: track 63/64 call gas off stack (#15563)

* core/vm: track 63/64 call gas off stack

Gas calculations in gasCall* relayed the available gas for calls by
replacing it on the stack. This lead to inconsistent traces, which we
papered over by copying the pre-execution stack in trace mode.

This change relays available gas using a temporary variable, off the
stack, and allows removing the weird copy.

* core/vm: remove stackCopy

* core/vm: pop call gas into pool

* core/vm: to -> addr
This commit is contained in:
Felix Lange
2017-11-28 20:05:49 +01:00
committed by Péter Szilágyi
parent 8f35e3086c
commit be12392fba
4 changed files with 55 additions and 99 deletions

View File

@ -342,19 +342,11 @@ func gasCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem
return 0, errGasUintOverflow
}
cg, err := callGas(gt, contract.Gas, gas, stack.Back(0))
evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0))
if err != nil {
return 0, err
}
// Replace the stack item with the new gas calculation. This means that
// either the original item is left on the stack or the item is replaced by:
// (availableGas - gas) * 63 / 64
// We replace the stack item so that it's available when the opCall instruction is
// called. This information is otherwise lost due to the dependency on *current*
// available gas.
stack.data[stack.len()-1] = new(big.Int).SetUint64(cg)
if gas, overflow = math.SafeAdd(gas, cg); overflow {
if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
return 0, errGasUintOverflow
}
return gas, nil
@ -374,19 +366,11 @@ func gasCallCode(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack,
return 0, errGasUintOverflow
}
cg, err := callGas(gt, contract.Gas, gas, stack.Back(0))
evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0))
if err != nil {
return 0, err
}
// Replace the stack item with the new gas calculation. This means that
// either the original item is left on the stack or the item is replaced by:
// (availableGas - gas) * 63 / 64
// We replace the stack item so that it's available when the opCall instruction is
// called. This information is otherwise lost due to the dependency on *current*
// available gas.
stack.data[stack.len()-1] = new(big.Int).SetUint64(cg)
if gas, overflow = math.SafeAdd(gas, cg); overflow {
if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
return 0, errGasUintOverflow
}
return gas, nil
@ -436,18 +420,11 @@ func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *St
return 0, errGasUintOverflow
}
cg, err := callGas(gt, contract.Gas, gas, stack.Back(0))
evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0))
if err != nil {
return 0, err
}
// Replace the stack item with the new gas calculation. This means that
// either the original item is left on the stack or the item is replaced by:
// (availableGas - gas) * 63 / 64
// We replace the stack item so that it's available when the opCall instruction is
// called.
stack.data[stack.len()-1] = new(big.Int).SetUint64(cg)
if gas, overflow = math.SafeAdd(gas, cg); overflow {
if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
return 0, errGasUintOverflow
}
return gas, nil
@ -463,18 +440,11 @@ func gasStaticCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stac
return 0, errGasUintOverflow
}
cg, err := callGas(gt, contract.Gas, gas, stack.Back(0))
evm.callGasTemp, err = callGas(gt, contract.Gas, gas, stack.Back(0))
if err != nil {
return 0, err
}
// Replace the stack item with the new gas calculation. This means that
// either the original item is left on the stack or the item is replaced by:
// (availableGas - gas) * 63 / 64
// We replace the stack item so that it's available when the opCall instruction is
// called.
stack.data[stack.len()-1] = new(big.Int).SetUint64(cg)
if gas, overflow = math.SafeAdd(gas, cg); overflow {
if gas, overflow = math.SafeAdd(gas, evm.callGasTemp); overflow {
return 0, errGasUintOverflow
}
return gas, nil