github.com/cryptogateway/go-paymex@v0.0.0-20210204174735-96277fb1e602/les/state_accessor.go (about) 1 // Copyright 2021 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package les 18 19 import ( 20 "context" 21 "errors" 22 "fmt" 23 24 "github.com/cryptogateway/go-paymex/core" 25 "github.com/cryptogateway/go-paymex/core/state" 26 "github.com/cryptogateway/go-paymex/core/types" 27 "github.com/cryptogateway/go-paymex/core/vm" 28 "github.com/cryptogateway/go-paymex/light" 29 ) 30 31 // stateAtBlock retrieves the state database associated with a certain block. 32 func (leth *LightEthereum) stateAtBlock(ctx context.Context, block *types.Block, reexec uint64) (*state.StateDB, func(), error) { 33 return light.NewState(ctx, block.Header(), leth.odr), func() {}, nil 34 } 35 36 // statesInRange retrieves a batch of state databases associated with the specific 37 // block ranges. 38 func (leth *LightEthereum) statesInRange(ctx context.Context, fromBlock *types.Block, toBlock *types.Block, reexec uint64) ([]*state.StateDB, func(), error) { 39 var states []*state.StateDB 40 for number := fromBlock.NumberU64(); number <= toBlock.NumberU64(); number++ { 41 header, err := leth.blockchain.GetHeaderByNumberOdr(ctx, number) 42 if err != nil { 43 return nil, nil, err 44 } 45 states = append(states, light.NewState(ctx, header, leth.odr)) 46 } 47 return states, nil, nil 48 } 49 50 // stateAtTransaction returns the execution environment of a certain transaction. 51 func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, func(), error) { 52 // Short circuit if it's genesis block. 53 if block.NumberU64() == 0 { 54 return nil, vm.BlockContext{}, nil, nil, errors.New("no transaction in genesis") 55 } 56 // Create the parent state database 57 parent, err := leth.blockchain.GetBlock(ctx, block.ParentHash(), block.NumberU64()-1) 58 if err != nil { 59 return nil, vm.BlockContext{}, nil, nil, err 60 } 61 statedb, _, err := leth.stateAtBlock(ctx, parent, reexec) 62 if err != nil { 63 return nil, vm.BlockContext{}, nil, nil, err 64 } 65 if txIndex == 0 && len(block.Transactions()) == 0 { 66 return nil, vm.BlockContext{}, statedb, func() {}, nil 67 } 68 // Recompute transactions up to the target index. 69 signer := types.MakeSigner(leth.blockchain.Config(), block.Number()) 70 for idx, tx := range block.Transactions() { 71 // Assemble the transaction call message and return if the requested offset 72 msg, _ := tx.AsMessage(signer) 73 txContext := core.NewEVMTxContext(msg) 74 context := core.NewEVMBlockContext(block.Header(), leth.blockchain, nil) 75 if idx == txIndex { 76 return msg, context, statedb, func() {}, nil 77 } 78 // Not yet the searched for transaction, execute on top of the current state 79 vmenv := vm.NewEVM(context, txContext, statedb, leth.blockchain.Config(), vm.Config{}) 80 if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { 81 return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) 82 } 83 // Ensure any modifications are committed to the state 84 // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect 85 statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number())) 86 } 87 return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash()) 88 }