core/types, core/vm: mark tx execution as failed if error return

Motivation:
    Current problem with gas estimation is not all cases is correct
    using gas metrics, e.g. in the frontier contract deploys can fail without
    consuming all gas due to have not enough gas to store contract code.
    So a `failed` flag is useful which can detect the vm execution
    status.

In Addition:
    the `Reverted` flag has been removed, since it is too sensitive to
    insert addtional field to it.
This commit is contained in:
rjl493456442 2017-06-28 10:32:31 +08:00
parent 66d8ff8983
commit 65a6cc2f1e
12 changed files with 123 additions and 136 deletions

View file

@ -167,7 +167,7 @@ func (b *SimulatedBackend) CallContract(ctx context.Context, call ethereum.CallM
if err != nil {
return nil, err
}
rval, _, err := b.callContract(ctx, call, b.blockchain.CurrentBlock(), state)
rval, _, _, err := b.callContract(ctx, call, b.blockchain.CurrentBlock(), state)
return rval, err
}
@ -177,7 +177,7 @@ func (b *SimulatedBackend) PendingCallContract(ctx context.Context, call ethereu
defer b.mu.Unlock()
defer b.pendingState.RevertToSnapshot(b.pendingState.Snapshot())
rval, _, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
rval, _, _, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
return rval, err
}
@ -215,11 +215,11 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
call.Gas = new(big.Int).SetUint64(mid)
snapshot := b.pendingState.Snapshot()
_, gas, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
_, _, failed, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
b.pendingState.RevertToSnapshot(snapshot)
// If the transaction became invalid or used all the gas (failed), raise the gas limit
if err != nil || gas.Cmp(call.Gas) == 0 {
// If the transaction became invalid or failed, raise the gas limit
if err != nil || failed {
lo = mid
continue
}
@ -231,7 +231,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
// callContract implemens common code between normal and pending contract calls.
// state is modified during execution, make sure to copy it if necessary.
func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, statedb *state.StateDB) ([]byte, *big.Int, error) {
func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, statedb *state.StateDB) ([]byte, *big.Int, bool, error) {
// Ensure message is initialized properly.
if call.GasPrice == nil {
call.GasPrice = big.NewInt(1)
@ -253,8 +253,8 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
// about the transaction and calling mechanisms.
vmenv := vm.NewEVM(evmContext, statedb, b.config, vm.Config{})
gaspool := new(core.GasPool).AddGas(math.MaxBig256)
ret, gasUsed, _, _, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb()
return ret, gasUsed, err
ret, gasUsed, _, failed, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb()
return ret, gasUsed, failed, err
}
// SendTransaction updates the pending block to include the given transaction.

View file

@ -98,7 +98,7 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common
// about the transaction and calling mechanisms.
vmenv := vm.NewEVM(context, statedb, config, cfg)
// Apply the transaction to the current state (included in the env)
_, gas, reverted, err := ApplyMessage(vmenv, msg, gp)
_, gas, _, err := ApplyMessage(vmenv, msg, gp)
if err != nil {
return nil, nil, err
}
@ -111,7 +111,6 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common
receipt := types.NewReceipt(root.Bytes(), usedGas)
receipt.TxHash = tx.Hash()
receipt.GasUsed = new(big.Int).Set(gas)
receipt.Reverted = reverted
// if the transaction created a contract, store the creation address in the receipt.
if msg.To() == nil {
receipt.ContractAddress = crypto.CreateAddress(vmenv.Context.Origin, tx.Nonce())

View file

@ -130,8 +130,8 @@ func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition
func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) ([]byte, *big.Int, bool, error) {
st := NewStateTransition(evm, msg, gp)
ret, _, gasUsed, reverted, err := st.TransitionDb()
return ret, gasUsed, reverted, err
ret, _, gasUsed, failed, err := st.TransitionDb()
return ret, gasUsed, failed, err
}
func (st *StateTransition) from() vm.AccountRef {
@ -208,7 +208,7 @@ func (st *StateTransition) preCheck() error {
// TransitionDb will transition the state by applying the current message and returning the result
// including the required gas for the operation as well as the used gas. It returns an error if it
// failed. An error indicates a consensus issue.
func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big.Int, reverted bool, err error) {
func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big.Int, failed bool, err error) {
if err = st.preCheck(); err != nil {
return
}
@ -236,11 +236,11 @@ func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big
vmerr error
)
if contractCreation {
ret, _, st.gas, reverted, vmerr = evm.Create(sender, st.data, st.gas, st.value)
ret, _, st.gas, failed, vmerr = evm.Create(sender, st.data, st.gas, st.value)
} else {
// Increment the nonce for the next transaction
st.state.SetNonce(sender.Address(), st.state.GetNonce(sender.Address())+1)
ret, st.gas, reverted, vmerr = evm.Call(sender, st.to().Address(), st.data, st.gas, st.value)
ret, st.gas, failed, vmerr = evm.Call(sender, st.to().Address(), st.data, st.gas, st.value)
}
if vmerr != nil {
log.Debug("VM returned with error", "err", vmerr)
@ -256,7 +256,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big
st.refundGas()
st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(st.gasUsed(), st.gasPrice))
return ret, requiredGas, st.gasUsed(), reverted, err
return ret, requiredGas, st.gasUsed(), failed, err
}
func (st *StateTransition) refundGas() {

View file

@ -20,7 +20,6 @@ func (r Receipt) MarshalJSON() ([]byte, error) {
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
ContractAddress common.Address `json:"contractAddress"`
GasUsed *hexutil.Big `json:"gasUsed" gencodec:"required"`
Reverted bool `json:"reverted" gencode:"required"`
}
var enc Receipt
enc.PostState = r.PostState
@ -30,7 +29,6 @@ func (r Receipt) MarshalJSON() ([]byte, error) {
enc.TxHash = r.TxHash
enc.ContractAddress = r.ContractAddress
enc.GasUsed = (*hexutil.Big)(r.GasUsed)
enc.Reverted = r.Reverted
return json.Marshal(&enc)
}
@ -43,7 +41,6 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
TxHash *common.Hash `json:"transactionHash" gencodec:"required"`
ContractAddress *common.Address `json:"contractAddress"`
GasUsed *hexutil.Big `json:"gasUsed" gencodec:"required"`
Reverted *bool `json:"reverted" gencode:"required"`
}
var dec Receipt
if err := json.Unmarshal(input, &dec); err != nil {
@ -76,8 +73,5 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
return errors.New("missing required field 'gasUsed' for Receipt")
}
r.GasUsed = (*big.Int)(dec.GasUsed)
if dec.Reverted != nil {
r.Reverted = *dec.Reverted
}
return nil
}

View file

@ -40,10 +40,6 @@ type Receipt struct {
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
ContractAddress common.Address `json:"contractAddress"`
GasUsed *big.Int `json:"gasUsed" gencodec:"required"`
// The Reverted field is true if transaction is reverted during state transition,
// As the transaction revert will cause all the remaining gas to be consumed,
// This field could help to gas estimation.
Reverted bool `json:"reverted" gencode:"required"`
}
type receiptMarshaling struct {
@ -95,7 +91,7 @@ func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
for i, log := range r.Logs {
logs[i] = (*LogForStorage)(log)
}
return rlp.Encode(w, []interface{}{r.PostState, r.CumulativeGasUsed, r.Bloom, r.TxHash, r.ContractAddress, logs, r.GasUsed, r.Reverted})
return rlp.Encode(w, []interface{}{r.PostState, r.CumulativeGasUsed, r.Bloom, r.TxHash, r.ContractAddress, logs, r.GasUsed})
}
// DecodeRLP implements rlp.Decoder, and loads both consensus and implementation
@ -109,7 +105,6 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
ContractAddress common.Address
Logs []*LogForStorage
GasUsed *big.Int
Reverted bool
}
if err := s.Decode(&receipt); err != nil {
return err
@ -121,7 +116,7 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
r.Logs[i] = (*Log)(log)
}
// Assign the implementation fields
r.TxHash, r.ContractAddress, r.GasUsed, r.Reverted = receipt.TxHash, receipt.ContractAddress, receipt.GasUsed, receipt.Reverted
r.TxHash, r.ContractAddress, r.GasUsed = receipt.TxHash, receipt.ContractAddress, receipt.GasUsed
return nil
}

View file

@ -62,8 +62,7 @@ type Contract struct {
Args []byte
DelegateCall bool
Reverted bool // use to represent whether transaction is reverted during state transition
// child's reverted field changed will also affect parent.
Failed bool // Used to identify the execution status of the current transaction
}
// NewContract returns a new contract environment for the execution of EVM.
@ -154,11 +153,11 @@ func (self *Contract) SetCallCode(addr *common.Address, hash common.Hash, code [
self.CodeAddr = addr
}
// MarkReverted mark current transaction's execution has meet revert.
func (self *Contract) MarkReverted() {
self.Reverted = true
// MarkFailed mark current transaction's execution failed.
func (self *Contract) MarkFailed() {
self.Failed = true
// affect parent recursively
if parent, ok := self.caller.(*Contract); ok {
parent.MarkReverted()
parent.MarkFailed()
}
}

View file

@ -124,7 +124,7 @@ func (evm *EVM) Cancel() {
// Call executes the contract associated with the addr with the given input as parameters. It also handles any
// necessary value transfer required and takes the necessary steps to create accounts and reverses the state in
// case of an execution error or failed value transfer.
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, reverted bool, err error) {
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, failed bool, err error) {
if evm.vmConfig.NoRecursion && evm.depth > 0 {
return nil, gas, false, nil
}
@ -163,9 +163,10 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
// when we're in homestead this also counts for code storage gas errors.
if err != nil {
contract.UseGas(contract.Gas)
evm.Revert(snapshot, contract)
evm.StateDB.RevertToSnapshot(snapshot)
contract.MarkFailed()
}
return ret, contract.Gas, contract.Reverted, err
return ret, contract.Gas, contract.Failed, err
}
// CallCode executes the contract associated with the addr with the given input as parameters. It also handles any
@ -200,7 +201,8 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
ret, err = run(evm, snapshot, contract, input)
if err != nil {
contract.UseGas(contract.Gas)
evm.Revert(snapshot, contract)
evm.StateDB.RevertToSnapshot(snapshot)
contract.MarkFailed()
}
return ret, contract.Gas, err
@ -234,14 +236,15 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
ret, err = run(evm, snapshot, contract, input)
if err != nil {
contract.UseGas(contract.Gas)
evm.Revert(snapshot, contract)
evm.StateDB.RevertToSnapshot(snapshot)
contract.MarkFailed()
}
return ret, contract.Gas, err
}
// Create creates a new contract using code as deployment code.
func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, reverted bool, err error) {
func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, failed bool, err error) {
if evm.vmConfig.NoRecursion && evm.depth > 0 {
return nil, common.Address{}, gas, false, nil
}
@ -295,7 +298,12 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I
if maxCodeSizeExceeded ||
(err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) {
contract.UseGas(contract.Gas)
evm.Revert(snapshot, contract)
evm.StateDB.RevertToSnapshot(snapshot)
}
// When the virtual machine returns an error or stores an excessive contract code,
// the execution of the transaction is marked as failed.
if maxCodeSizeExceeded || err != nil {
contract.MarkFailed()
}
// If the vm returned with an error the return value should be set to nil.
// This isn't consensus critical but merely to for behaviour reasons such as
@ -304,7 +312,7 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I
ret = nil
}
return ret, contractAddr, contract.Gas, contract.Reverted, err
return ret, contractAddr, contract.Gas, contract.Failed, err
}
// ChainConfig returns the evmironment's chain configuration
@ -312,10 +320,3 @@ func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }
// Interpreter returns the EVM interpreter
func (evm *EVM) Interpreter() *Interpreter { return evm.interpreter }
// Revert revert all state changes made since the given revision.
// set `reverted` flag recursively.
func (evm *EVM) Revert(snapshot int, contract *Contract) {
evm.StateDB.RevertToSnapshot(snapshot)
contract.MarkReverted()
}

View file

@ -551,7 +551,7 @@ func opCreate(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S
}
contract.UseGas(gas)
// ignore reverted here since it is only useful in vm entry.
// ignore failed flag here since it is only useful in vm entrance.
_, addr, returnGas, _, suberr := evm.Create(contract, input, gas, value)
// Push item on the stack based on the returned error. If the ruleset is
// homestead we must check for CodeStoreOutOfGasError (homestead only
@ -589,7 +589,7 @@ func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta
if value.Sign() != 0 {
gas += params.CallStipend
}
// ignore revert here, same with opCreate.
// ignore failed flag here, same with opCreate.
ret, returnGas, _, err := evm.Call(contract, address, args, gas, value)
if err != nil {
stack.push(new(big.Int))

View file

@ -113,7 +113,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, bool, err
// set the receiver's (the executing contract) code for execution.
cfg.State.SetCode(address, code)
// Call the code with the given configuration.
ret, _, reverted, err := vmenv.Call(
ret, _, failed, err := vmenv.Call(
sender,
common.StringToAddress("contract"),
input,
@ -121,7 +121,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, bool, err
cfg.Value,
)
return ret, cfg.State, reverted, err
return ret, cfg.State, failed, err
}
// Create executes the code using the EVM create method
@ -141,13 +141,13 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, bool, er
)
// Call the code with the given configuration.
code, address, leftOverGas, reverted, err := vmenv.Create(
code, address, leftOverGas, failed, err := vmenv.Create(
sender,
input,
cfg.GasLimit,
cfg.Value,
)
return code, address, leftOverGas, reverted, err
return code, address, leftOverGas, failed, err
}
// Call executes the code given by the contract's address. It will return the
@ -162,7 +162,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, bo
sender := cfg.State.GetOrNewStateObject(cfg.Origin)
// Call the code with the given configuration.
ret, leftOverGas, reverted, err := vmenv.Call(
ret, leftOverGas, failed, err := vmenv.Call(
sender,
address,
input,
@ -170,5 +170,5 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, bo
cfg.Value,
)
return ret, leftOverGas, reverted, err
return ret, leftOverGas, failed, err
}

View file

@ -119,21 +119,21 @@ func TestCall(t *testing.T) {
func TestTransactionReverted(t *testing.T) {
/*
Contract Source Code
```
contract Demo {
function Demo() {}
function IllegalDivision() returns(int) {
var dividend = 0;
return 1 / dividend;
}
function LegalDivision() returns(int) {
var dividend = 1;
return 1 / dividend;
}
}
```
*/
Contract Source Code
```
contract Demo {
function Demo() {}
function IllegalDivision() returns(int) {
var dividend = 0;
return 1 / dividend;
}
function LegalDivision() returns(int) {
var dividend = 1;
return 1 / dividend;
}
}
```
*/
var definition = `[{"constant":false,"inputs":[],"name":"LegalDivision","outputs":[{"name":"","type":"int256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"IllegalDivision","outputs":[{"name":"","type":"int256"}],"payable":false,"type":"function"},{"inputs":[],"payable":false,"type":"constructor"}]`
var rawcode = common.Hex2Bytes("6060604052341561000c57fe5b5b5b5b60f88061001d6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632d256662146044578063522de105146067575bfe5b3415604b57fe5b6051608a565b6040518082815260200191505060405180910390f35b3415606e57fe5b607460ab565b6040518082815260200191505060405180910390f35b60006000600190508060ff16600181151560a057fe5b0460ff1691505b5090565b60006000600090508060ff16600181151560c157fe5b0460ff1691505b50905600a165627a7a7230582091585859014c4644d0427bf34abc65433b5874993ddea00cac57bcb87ee4cb6b0029")
@ -151,7 +151,7 @@ func TestTransactionReverted(t *testing.T) {
if err != nil {
t.Fatal(err)
}
var reverted bool
var failed bool
// deploy
cfg := &Config{
Origin: common.HexToAddress("sender"),
@ -160,58 +160,58 @@ func TestTransactionReverted(t *testing.T) {
if err != nil {
t.Fatal(err)
}
_, _, reverted, _ = Execute(code, legalDivision, cfg)
if reverted != false {
_, _, failed, _ = Execute(code, legalDivision, cfg)
if failed != false {
t.Fatal("Expect false, got true")
}
_, _, reverted, _ = Execute(code, illegalDivision, cfg)
if reverted != true {
_, _, failed, _ = Execute(code, illegalDivision, cfg)
if failed != true {
t.Fatal("Expect true, got false")
}
}
func TestDelegateReverted(t *testing.T) {
/*
Contract Source Code
```
contract Relay {
address public currentVersion;
address public owner;
Contract Source Code
```
contract Relay {
address public currentVersion;
address public owner;
modifier onlyOwner() {
if (msg.sender != owner) {
throw;
}
_;
}
function Relay(address _address) {
currentVersion = _address;
owner = msg.sender;
}
function changeContract(address newVersion) public
onlyOwner()
{
currentVersion = newVersion;
}
function() {
if(!currentVersion.delegatecall(msg.data)) throw;
}
}
modifier onlyOwner() {
if (msg.sender != owner) {
throw;
}
_;
}
function Relay(address _address) {
currentVersion = _address;
owner = msg.sender;
}
function changeContract(address newVersion) public
onlyOwner()
{
currentVersion = newVersion;
}
function() {
if(!currentVersion.delegatecall(msg.data)) throw;
}
}
contract Demo {
function Demo() {
}
function IllegalDivision() returns(int) {
var dividend = 0;
return 1 / dividend;
}
function LegalDivision() returns(int) {
var dividend = 1;
return 1 / dividend;
}
}
```
*/
contract Demo {
function Demo() {
}
function IllegalDivision() returns(int) {
var dividend = 0;
return 1 / dividend;
}
function LegalDivision() returns(int) {
var dividend = 1;
return 1 / dividend;
}
}
```
*/
var definition = `[{"constant":false,"inputs":[],"name":"LegalDivision","outputs":[{"name":"","type":"int256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"IllegalDivision","outputs":[{"name":"","type":"int256"}],"payable":false,"type":"function"},{"inputs":[],"payable":false,"type":"constructor"}]`
var rawcode1 = common.Hex2Bytes("6060604052341561000c57fe5b5b5b5b60f88061001d6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632d256662146044578063522de105146067575bfe5b3415604b57fe5b6051608a565b6040518082815260200191505060405180910390f35b3415606e57fe5b607460ab565b6040518082815260200191505060405180910390f35b60006000600190508060ff16600181151560a057fe5b0460ff1691505b5090565b60006000600090508060ff16600181151560c157fe5b0460ff1691505b50905600a165627a7a7230582091585859014c4644d0427bf34abc65433b5874993ddea00cac57bcb87ee4cb6b0029")
var rawcode2 = common.Hex2Bytes("6060604052341561000c57fe5b60405160208061039c833981016040528080519060200190919050505b80600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b505b6102df806100bd6000396000f30060606040523615610055576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680633d71c3af146100ea5780638da5cb5b146101205780639d888e8614610172575b341561005d57fe5b6100e85b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600036600060405160200152604051808383808284378201915050925050506020604051808303818560325a03f415156100d057fe5b50506040518051905015156100e55760006000fd5b5b565b005b34156100f257fe5b61011e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506101c4565b005b341561012857fe5b610130610267565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561017a57fe5b61018261028d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156102215760006000fd5b80600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b5b50565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16815600a165627a7a723058208496aa0ef6d67e2e0423b76e8fd61b92e0047fe2e20ad20f887caf2b378dfa300029")
@ -230,7 +230,7 @@ func TestDelegateReverted(t *testing.T) {
if err != nil {
t.Fatal(err)
}
var reverted bool
var failed bool
// deploy
cfg := &Config{
Origin: common.HexToAddress("sender"),
@ -244,12 +244,12 @@ func TestDelegateReverted(t *testing.T) {
if err != nil {
t.Fatal(err)
}
_, _, reverted, _ = Call(addr2, legalDivision, cfg)
if reverted != false {
_, _, failed, _ = Call(addr2, legalDivision, cfg)
if failed != false {
t.Fatal("Expect false, got true")
}
_, _, reverted, _ = Call(addr2, illegalDivision, cfg)
if reverted != true {
_, _, failed, _ = Call(addr2, illegalDivision, cfg)
if failed != true {
t.Fatal("Expect true, got false")
}
}

View file

@ -543,7 +543,7 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, txHash common.
// Run the transaction with tracing enabled.
vmenv := vm.NewEVM(context, statedb, api.config, vm.Config{Debug: true, Tracer: tracer})
ret, gas, reverted, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas()))
ret, gas, failed, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas()))
if err != nil {
return nil, fmt.Errorf("tracing failed: %v", err)
}
@ -553,7 +553,7 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, txHash common.
Gas: gas,
ReturnValue: fmt.Sprintf("%x", ret),
StructLogs: ethapi.FormatLogs(tracer.StructLogs()),
Reverted: reverted,
Failed: failed,
}, nil
case *ethapi.JavascriptTracer:
return tracer.GetResult()
@ -591,7 +591,7 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int) (co
vmenv := vm.NewEVM(context, statedb, api.config, vm.Config{})
gp := new(core.GasPool).AddGas(tx.Gas())
_, _, _,err := core.ApplyMessage(vmenv, msg, gp)
_, _, _, err := core.ApplyMessage(vmenv, msg, gp)
if err != nil {
return nil, vm.Context{}, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err)
}

View file

@ -580,12 +580,12 @@ type CallArgs struct {
Data hexutil.Bytes `json:"data"`
}
func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config) ([]byte, *big.Int, error) {
func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config) ([]byte, *big.Int, bool, error) {
defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now())
state, header, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
if state == nil || err != nil {
return nil, common.Big0, err
return nil, common.Big0, false, err
}
// Set sender address or use a default if none specified
addr := args.From
@ -623,7 +623,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
// Get a new instance of the EVM.
evm, vmError, err := s.b.GetEVM(ctx, msg, state, header, vmCfg)
if err != nil {
return nil, common.Big0, err
return nil, common.Big0, false, err
}
// Wait for the context to be done and cancel the evm. Even if the
// EVM has finished, cancelling may be done (repeatedly)
@ -637,17 +637,17 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
// Setup the gas pool (also for unmetered requests)
// and apply the message.
gp := new(core.GasPool).AddGas(math.MaxBig256)
res, gas, _, err := core.ApplyMessage(evm, msg, gp)
res, gas, failed, err := core.ApplyMessage(evm, msg, gp)
if err := vmError(); err != nil {
return nil, common.Big0, err
return nil, common.Big0, false, err
}
return res, gas, err
return res, gas, failed, err
}
// Call executes the given transaction on the state for the given block number.
// It doesn't make and changes in the state/blockchain and is useful to execute and retrieve values.
func (s *PublicBlockChainAPI) Call(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber) (hexutil.Bytes, error) {
result, _, err := s.doCall(ctx, args, blockNr, vm.Config{DisableGasMetering: true})
result, _, _, err := s.doCall(ctx, args, blockNr, vm.Config{DisableGasMetering: true})
return (hexutil.Bytes)(result), err
}
@ -670,10 +670,10 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (*
mid := (hi + lo) / 2
(*big.Int)(&args.Gas).SetUint64(mid)
_, gas, err := s.doCall(ctx, args, rpc.PendingBlockNumber, vm.Config{})
_, _, failed, err := s.doCall(ctx, args, rpc.PendingBlockNumber, vm.Config{})
// If the transaction became invalid or used all the gas (failed), raise the gas limit
if err != nil || gas.Cmp((*big.Int)(&args.Gas)) == 0 {
// If the transaction became invalid or failed, raise the gas limit
if err != nil || failed {
lo = mid
continue
}
@ -690,7 +690,7 @@ type ExecutionResult struct {
Gas *big.Int `json:"gas"`
ReturnValue string `json:"returnValue"`
StructLogs []StructLogRes `json:"structLogs"`
Reverted bool `json:"reverted"`
Failed bool `json:"failed"`
}
// StructLogRes stores a structured log emitted by the EVM while replaying a
@ -1081,7 +1081,6 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(hash common.Hash) (map[
"contractAddress": nil,
"logs": receipt.Logs,
"logsBloom": receipt.Bloom,
"reverted": receipt.Reverted,
}
if receipt.Logs == nil {
fields["logs"] = [][]*types.Log{}