Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

graphql: return correct logs for tx (ethereum#25612) #3

Closed
wants to merge 38 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
d0dc349
graphql: return correct logs for tx (#25612)
s1na Aug 31, 2022
3b41be6
graphql: fixes missing tx logs (#25745)
s1na Sep 13, 2022
972007a
Release Geth v1.10.24
karalabe Sep 14, 2022
8f61fc8
params: set TerminalTotalDifficultyPassed to true (#25769)
MariusVanDerWijden Sep 15, 2022
69568c5
params: release Geth v1.10.25
karalabe Sep 15, 2022
85e469f
eth/protocols/snap: fix problems due to idle-but-busy peers (#25651)
holiman Aug 31, 2022
937ea49
eth/protocols/snap: throttle trie heal requests when peers DoS us (#2…
karalabe Sep 9, 2022
a32e69a
trie: check childrens' existence concurrently for snap heal (#25694)
karalabe Sep 6, 2022
99bbb33
eth: fix a rare datarace on CHT challenge reply / shutdown (#25831)
karalabe Sep 20, 2022
27600a5
eth/filters: change filter block to be by-ref (#26054)
holiman Oct 27, 2022
211dbb7
rpc: handle wrong HTTP batch response length (#26064)
jmank88 Nov 2, 2022
e5eb32a
params: release geth v1.10.26 stable
fjl Nov 3, 2022
37748e5
stateful
itsdevbear Jan 16, 2023
cdf5821
use PrecompileExecutor
calbera Jan 18, 2023
2def4f0
use host terminology
calbera Jan 18, 2023
b7ecb9e
return precompiledContract and bool
calbera Jan 18, 2023
d1c5ff3
use ctx in Run instead of statedb
calbera Jan 18, 2023
981b007
Merge pull request #4 from berachain/new-precompile
itsdevbear Jan 19, 2023
12579d8
change to ph
itsdevbear Jan 19, 2023
f1ef333
bing bong
itsdevbear Jan 19, 2023
e604f74
rename to runner
calbera Jan 23, 2023
6dfd7b1
rename constructor
calbera Jan 23, 2023
6b58c1d
new precompile function types
calbera Jan 24, 2023
8f77e9a
precompile controller
calbera Jan 24, 2023
eca0bbb
make PrecompileController public
calbera Jan 25, 2023
cdf3a39
ctx setter
calbera Jan 25, 2023
dc459cd
add statedb in contract.Run
calbera Jan 25, 2023
60266f5
use Prepare on controller
calbera Jan 25, 2023
952aea2
prepare for state transition
calbera Jan 25, 2023
ca260e9
contract has registry key
calbera Feb 2, 2023
2ad2464
has and get
calbera Feb 2, 2023
d6fbbb7
controller > manager
calbera Feb 2, 2023
e4d555f
with statedb
calbera Feb 3, 2023
fe0db77
with ctx
calbera Feb 3, 2023
0d5324b
simple precompile manager
calbera Feb 6, 2023
561d4bc
allow setting block context to evm
calbera Feb 10, 2023
62f7754
remove unneded evm funcs
calbera Feb 10, 2023
6096143
simplify precompile manager
calbera Feb 16, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion accounts/abi/bind/bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
}
eventIdentifiers[normalizedName] = true
normalized.Name = normalizedName

used := make(map[string]bool)
normalized.Inputs = make([]abi.Argument, len(original.Inputs))
copy(normalized.Inputs, original.Inputs)
Expand Down
159 changes: 117 additions & 42 deletions core/vm/contracts.go

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions core/vm/contracts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ package vm

import (
"bytes"
"context"
"encoding/json"
"fmt"
"math/big"
"os"
"testing"
"time"
Expand Down Expand Up @@ -91,6 +93,16 @@ var blake2FMalformedInputTests = []precompiledFailureTest{
},
}

func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uint64) (ret []byte, remainingGas uint64, err error) {
gasCost := p.RequiredGas(input)
if suppliedGas < gasCost {
return nil, 0, ErrOutOfGas
}
suppliedGas -= gasCost
output, err := p.Run(context.Background(), input, common.Address{}, new(big.Int), true)
return output, suppliedGas, err
}

func testPrecompiled(addr string, test precompiledTest, t *testing.T) {
p := allPrecompiles[common.HexToAddress(addr)]
in := common.Hex2Bytes(test.Input)
Expand Down
68 changes: 45 additions & 23 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package vm

import (
"context"
"math/big"
"sync/atomic"
"time"
Expand All @@ -41,20 +42,21 @@ type (
GetHashFunc func(uint64) common.Hash
)

func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
var precompiles map[common.Address]PrecompiledContract
switch {
case evm.chainRules.IsBerlin:
precompiles = PrecompiledContractsBerlin
case evm.chainRules.IsIstanbul:
precompiles = PrecompiledContractsIstanbul
case evm.chainRules.IsByzantium:
precompiles = PrecompiledContractsByzantium
default:
precompiles = PrecompiledContractsHomestead
}
p, ok := precompiles[addr]
return p, ok
// `PrecompileManager` allows the EVM to execute a precompiled contract.
type PrecompileManager interface {
Reset(ctx context.Context)

// `Has` returns if a precompiled contract was found at `addr`.
Has(addr common.Address) bool

// `Get` returns the precompiled contract at `addr`. Returns nil if no
// contract is found at `addr`.
Get(addr common.Address) PrecompiledContract

// `Run` runs a precompiled contract and returns the remaining gas.
Run(sdb StateDB, p PrecompiledContract, input []byte, caller common.Address,
value *big.Int, suppliedGas uint64, readonly bool,
) (ret []byte, remainingGas uint64, err error)
}

// BlockContext provides the EVM with auxiliary information. Once provided
Expand All @@ -75,7 +77,7 @@ type BlockContext struct {
Time *big.Int // Provides information for TIME
Difficulty *big.Int // Provides information for DIFFICULTY
BaseFee *big.Int // Provides information for BASEFEE
Random *common.Hash // Provides information for RANDOM
Random *common.Hash // Provides information for PREVRANDAO
}

// TxContext provides the EVM with information about a transaction.
Expand All @@ -101,6 +103,8 @@ type EVM struct {
TxContext
// StateDB gives access to the underlying state
StateDB StateDB
// PrecompileManager finds and runs precompiled contracts
PrecompileManager PrecompileManager
// Depth is the current call stack
depth int

Expand Down Expand Up @@ -138,6 +142,15 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig
return evm
}

func NewEVMWithPrecompiles(
blockCtx BlockContext, txCtx TxContext, statedb StateDB,
chainConfig *params.ChainConfig, config Config, precompileController PrecompileManager,
) *EVM {
evm := NewEVM(blockCtx, txCtx, statedb, chainConfig, config)
evm.PrecompileManager = precompileController
return evm
}

// Reset resets the EVM with a new transaction context.Reset
// This is not threadsafe and should only be done very cautiously.
func (evm *EVM) Reset(txCtx TxContext, statedb StateDB) {
Expand Down Expand Up @@ -175,7 +188,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
return nil, gas, ErrInsufficientBalance
}
snapshot := evm.StateDB.Snapshot()
p, isPrecompile := evm.precompile(addr)
isPrecompile := evm.PrecompileManager.Has(addr)

if !evm.StateDB.Exist(addr) {
if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 {
Expand Down Expand Up @@ -212,7 +225,9 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
}

if isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas)
ret, gas, err = evm.PrecompileManager.Run(
evm.StateDB, evm.PrecompileManager.Get(addr), input, caller.Address(), value, gas, false,
)
} else {
// Initialise a new contract and set the code that is to be used by the EVM.
// The contract is a scoped environment for this execution context only.
Expand Down Expand Up @@ -274,8 +289,10 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
}

// It is allowed to call precompiles, even via delegatecall
if p, isPrecompile := evm.precompile(addr); isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas)
if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile {
ret, gas, err = evm.PrecompileManager.Run(
evm.StateDB, evm.PrecompileManager.Get(addr), input, caller.Address(), value, gas, true,
)
} else {
addrCopy := addr
// Initialise a new contract and set the code that is to be used by the EVM.
Expand Down Expand Up @@ -315,8 +332,11 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
}

// It is allowed to call precompiles, even via delegatecall
if p, isPrecompile := evm.precompile(addr); isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas)
if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile {
parent := caller.(*Contract)
ret, gas, err = evm.PrecompileManager.Run(
evm.StateDB, evm.PrecompileManager.Get(addr), input, parent.CallerAddress, parent.value, gas, false,
)
} else {
addrCopy := addr
// Initialise a new contract and make initialise the delegate values
Expand Down Expand Up @@ -364,8 +384,10 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
}(gas)
}

if p, isPrecompile := evm.precompile(addr); isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas)
if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile {
ret, gas, err = evm.PrecompileManager.Run(
evm.StateDB, evm.PrecompileManager.Get(addr), input, caller.Address(), new(big.Int), gas, true,
)
} else {
// At this point, we use a copy of address. If we don't, the go compiler will
// leak the 'contract' to the outer scope, and make allocation for 'contract'
Expand Down
19 changes: 13 additions & 6 deletions core/vm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,16 +392,21 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
// opExtCodeHash returns the code hash of a specified account.
// There are several cases when the function is called, while we can relay everything
// to `state.GetCodeHash` function to ensure the correctness.
// (1) Caller tries to get the code hash of a normal contract account, state
//
// (1) Caller tries to get the code hash of a normal contract account, state
//
// should return the relative code hash and set it as the result.
//
// (2) Caller tries to get the code hash of a non-existent account, state should
// (2) Caller tries to get the code hash of a non-existent account, state should
//
// return common.Hash{} and zero will be set as the result.
//
// (3) Caller tries to get the code hash for an account without contract code,
// (3) Caller tries to get the code hash for an account without contract code,
//
// state should return emptyCodeHash(0xc5d246...) as the result.
//
// (4) Caller tries to get the code hash of a precompiled account, the result
// (4) Caller tries to get the code hash of a precompiled account, the result
//
// should be zero or emptyCodeHash.
//
// It is worth noting that in order to avoid unnecessary create and clean,
Expand All @@ -410,10 +415,12 @@ func opExtCodeCopy(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
// If the precompile account is not transferred any amount on a private or
// customized chain, the return value will be zero.
//
// (5) Caller tries to get the code hash for an account which is marked as suicided
// (5) Caller tries to get the code hash for an account which is marked as suicided
//
// in the current transaction, the code hash of this account should be returned.
//
// (6) Caller tries to get the code hash for an account which is marked as deleted,
// (6) Caller tries to get the code hash for an account which is marked as deleted,
//
// this account should be regarded as a non-existent account and zero should be returned.
func opExtCodeHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
slot := scope.Stack.peek()
Expand Down
10 changes: 5 additions & 5 deletions eth/filters/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ type Filter struct {
addresses []common.Address
topics [][]common.Hash

block common.Hash // Block hash if filtering a single block
begin, end int64 // Range interval if filtering multiple blocks
block *common.Hash // Block hash if filtering a single block
begin, end int64 // Range interval if filtering multiple blocks

matcher *bloombits.Matcher
}
Expand Down Expand Up @@ -78,7 +78,7 @@ func (sys *FilterSystem) NewRangeFilter(begin, end int64, addresses []common.Add
func (sys *FilterSystem) NewBlockFilter(block common.Hash, addresses []common.Address, topics [][]common.Hash) *Filter {
// Create a generic filter and convert it into a block filter
filter := newFilter(sys, addresses, topics)
filter.block = block
filter.block = &block
return filter
}

Expand All @@ -96,8 +96,8 @@ func newFilter(sys *FilterSystem, addresses []common.Address, topics [][]common.
// first block that contains matches, updating the start of the filter accordingly.
func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) {
// If we're doing singleton block filtering, execute and return
if f.block != (common.Hash{}) {
header, err := f.sys.backend.HeaderByHash(ctx, f.block)
if f.block != nil {
header, err := f.sys.backend.HeaderByHash(ctx, *f.block)
if err != nil {
return nil, err
}
Expand Down
18 changes: 14 additions & 4 deletions eth/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,11 +391,16 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error {
if h.checkpointHash != (common.Hash{}) {
// Request the peer's checkpoint header for chain height/weight validation
resCh := make(chan *eth.Response)
if _, err := peer.RequestHeadersByNumber(h.checkpointNumber, 1, 0, false, resCh); err != nil {

req, err := peer.RequestHeadersByNumber(h.checkpointNumber, 1, 0, false, resCh)
if err != nil {
return err
}
// Start a timer to disconnect if the peer doesn't reply in time
go func() {
// Ensure the request gets cancelled in case of error/drop
defer req.Close()

timeout := time.NewTimer(syncChallengeTimeout)
defer timeout.Stop()

Expand Down Expand Up @@ -437,10 +442,15 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error {
// If we have any explicit peer required block hashes, request them
for number, hash := range h.requiredBlocks {
resCh := make(chan *eth.Response)
if _, err := peer.RequestHeadersByNumber(number, 1, 0, false, resCh); err != nil {

req, err := peer.RequestHeadersByNumber(number, 1, 0, false, resCh)
if err != nil {
return err
}
go func(number uint64, hash common.Hash) {
go func(number uint64, hash common.Hash, req *eth.Request) {
// Ensure the request gets cancelled in case of error/drop
defer req.Close()

timeout := time.NewTimer(syncChallengeTimeout)
defer timeout.Stop()

Expand Down Expand Up @@ -469,7 +479,7 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error {
peer.Log().Warn("Required block challenge timed out, dropping", "addr", peer.RemoteAddr(), "type", peer.Name())
h.removePeer(peer.ID())
}
}(number, hash)
}(number, hash, req)
}
// Handle incoming messages until the connection is torn down
return handler(peer)
Expand Down
Loading