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

Sync with subnet-evm (up to b4b595e) #508

Merged
merged 3 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions accounts/abi/abi.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ func (abi ABI) PackOutput(name string, args ...interface{}) ([]byte, error) {
}

// getInputs gets input arguments of the given [name] method.
// useStrictMode indicates whether to check the input data length strictly.
func (abi ABI) getInputs(name string, data []byte, useStrictMode bool) (Arguments, error) {
// since there can't be naming collisions with contracts and events,
// we need to decide whether we're calling a method or an event
Expand Down Expand Up @@ -196,6 +197,9 @@ func (abi ABI) getArguments(name string, data []byte) (Arguments, error) {
}

// UnpackInput unpacks the input according to the ABI specification.
// useStrictMode indicates whether to check the input data length strictly.
// By default it was set to true. In order to support the general EVM tool compatibility this
// should be set to false. This transition (true -> false) should be done with a network upgrade.
func (abi ABI) UnpackInput(name string, data []byte, useStrictMode bool) ([]interface{}, error) {
args, err := abi.getInputs(name, data, useStrictMode)
if err != nil {
Expand All @@ -216,6 +220,9 @@ func (abi ABI) Unpack(name string, data []byte) ([]interface{}, error) {
// UnpackInputIntoInterface unpacks the input in v according to the ABI specification.
// It performs an additional copy. Please only use, if you want to unpack into a
// structure that does not strictly conform to the ABI structure (e.g. has additional arguments)
// useStrictMode indicates whether to check the input data length strictly.
// By default it was set to true. In order to support the general EVM tool compatibility this
// should be set to false. This transition (true -> false) should be done with a network upgrade.
func (abi ABI) UnpackInputIntoInterface(v interface{}, name string, data []byte, useStrictMode bool) error {
args, err := abi.getInputs(name, data, useStrictMode)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ func (b *SimulatedBackend) FilterLogs(ctx context.Context, query interfaces.Filt
to = query.ToBlock.Int64()
}
// Construct the range filter
filter, _ = b.filterSystem.NewRangeFilter(from, to, query.Addresses, query.Topics)
filter = b.filterSystem.NewRangeFilter(from, to, query.Addresses, query.Topics)
}
// Run the filter and return all the logs
logs, err := filter.Logs(ctx)
Expand Down Expand Up @@ -911,7 +911,7 @@ func (fb *filterBackend) EventMux() *event.TypeMux { panic("not supported") }

func (fb *filterBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
switch number {
case rpc.PendingBlockNumber, rpc.AcceptedBlockNumber:
case rpc.PendingBlockNumber, rpc.FinalizedBlockNumber:
if block := fb.backend.acceptedBlock; block != nil {
return block.Header(), nil
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/abigen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ import (
"strings"

"github.com/ava-labs/coreth/accounts/abi/bind"
"github.com/ava-labs/coreth/cmd/utils"
"github.com/ava-labs/coreth/internal/flags"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common/compiler"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
Expand Down
89 changes: 89 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.

// Package utils contains internal helper functions for go-ethereum commands.
package utils

import (
"fmt"
"io"
"os"
"runtime"
"strings"

"github.com/urfave/cli/v2"
)

// Fatalf formats a message to standard error and exits the program.
// The message is also printed to standard output if standard error
// is redirected to a different file.
func Fatalf(format string, args ...interface{}) {
w := io.MultiWriter(os.Stdout, os.Stderr)
if runtime.GOOS == "windows" {
// The SameFile check below doesn't work on Windows.
// stdout is unlikely to get redirected though, so just print there.
w = os.Stdout
} else {
outf, _ := os.Stdout.Stat()
errf, _ := os.Stderr.Stat()
if outf != nil && errf != nil && os.SameFile(outf, errf) {
w = os.Stderr
}
}
fmt.Fprintf(w, "Fatal: "+format+"\n", args...)
os.Exit(1)
}

// CheckExclusive verifies that only a single instance of the provided flags was
// set by the user. Each flag might optionally be followed by a string type to
// specialize it further.
func CheckExclusive(ctx *cli.Context, args ...interface{}) {
set := make([]string, 0, 1)
for i := 0; i < len(args); i++ {
// Make sure the next argument is a flag and skip if not set
flag, ok := args[i].(cli.Flag)
if !ok {
panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i]))
}
// Check if next arg extends current and expand its name if so
name := flag.Names()[0]

if i+1 < len(args) {
switch option := args[i+1].(type) {
case string:
// Extended flag check, make sure value set doesn't conflict with passed in option
if ctx.String(flag.Names()[0]) == option {
name += "=" + option
set = append(set, "--"+name)
}
// shift arguments and continue
i++
continue

case cli.Flag:
default:
panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1]))
}
}
// Mark the flag if it's set
if ctx.IsSet(flag.Names()[0]) {
set = append(set, "--"+name)
}
}
if len(set) > 1 {
Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", "))
}
}
12 changes: 10 additions & 2 deletions eth/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,11 @@ func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) {
}
var header *types.Header
if blockNr.IsAccepted() {
header = api.eth.LastAcceptedBlock().Header()
if api.eth.APIBackend.isLatestAndAllowed(blockNr) {
header = api.eth.blockchain.CurrentHeader()
} else {
header = api.eth.LastAcceptedBlock().Header()
}
} else {
block := api.eth.blockchain.GetBlockByNumber(uint64(blockNr))
if block == nil {
Expand Down Expand Up @@ -241,7 +245,11 @@ func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hex
if number, ok := blockNrOrHash.Number(); ok {
var header *types.Header
if number.IsAccepted() {
header = api.eth.LastAcceptedBlock().Header()
if api.eth.APIBackend.isLatestAndAllowed(number) {
header = api.eth.blockchain.CurrentHeader()
} else {
header = api.eth.LastAcceptedBlock().Header()
}
} else {
block := api.eth.blockchain.GetBlockByNumber(uint64(number))
if block == nil {
Expand Down
11 changes: 11 additions & 0 deletions eth/api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumb
// identically.
acceptedBlock := b.eth.LastAcceptedBlock()
if number.IsAccepted() {
if b.isLatestAndAllowed(number) {
return b.eth.blockchain.CurrentHeader(), nil
}
return acceptedBlock.Header(), nil
}

Expand Down Expand Up @@ -151,6 +154,10 @@ func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumbe
// identically.
acceptedBlock := b.eth.LastAcceptedBlock()
if number.IsAccepted() {
if b.isLatestAndAllowed(number) {
header := b.eth.blockchain.CurrentBlock()
return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil
}
return acceptedBlock, nil
}

Expand Down Expand Up @@ -488,3 +495,7 @@ func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Blo
func (b *EthAPIBackend) MinRequiredTip(ctx context.Context, header *types.Header) (*big.Int, error) {
return dummy.MinRequiredTip(b.ChainConfig(), header)
}

func (b *EthAPIBackend) isLatestAndAllowed(number rpc.BlockNumber) bool {
return number.IsLatest() && b.IsAllowUnfinalizedQueries()
}
12 changes: 2 additions & 10 deletions eth/filters/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -439,11 +439,7 @@ func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*type
end = crit.ToBlock.Int64()
}
// Construct the range filter
var err error
filter, err = api.sys.NewRangeFilter(begin, end, crit.Addresses, crit.Topics)
if err != nil {
return nil, err
}
filter = api.sys.NewRangeFilter(begin, end, crit.Addresses, crit.Topics)
}
// Run the filter and return all the logs
logs, err := filter.Logs(ctx)
Expand Down Expand Up @@ -497,11 +493,7 @@ func (api *FilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]*types.Lo
end = f.crit.ToBlock.Int64()
}
// Construct the range filter
var err error
filter, err = api.sys.NewRangeFilter(begin, end, f.crit.Addresses, f.crit.Topics)
if err != nil {
return nil, err
}
filter = api.sys.NewRangeFilter(begin, end, f.crit.Addresses, f.crit.Topics)
}
// Run the filter and return all the logs
logs, err := filter.Logs(ctx)
Expand Down
7 changes: 2 additions & 5 deletions eth/filters/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/bitutil"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/stretchr/testify/require"
)

func BenchmarkBloomBits512(b *testing.B) {
Expand Down Expand Up @@ -147,8 +146,7 @@ func benchmarkBloomBits(b *testing.B, sectionSize uint64) {
var addr common.Address
addr[0] = byte(i)
addr[1] = byte(i / 256)
filter, err := sys.NewRangeFilter(0, int64(cnt*sectionSize-1), []common.Address{addr}, nil)
require.NoError(b, err)
filter := sys.NewRangeFilter(0, int64(cnt*sectionSize-1), []common.Address{addr}, nil)
if _, err := filter.Logs(context.Background()); err != nil {
b.Error("filter.Logs error:", err)
}
Expand Down Expand Up @@ -191,8 +189,7 @@ func BenchmarkNoBloomBits(b *testing.B) {

b.Log("Running filter benchmarks...")
start := time.Now()
filter, err := sys.NewRangeFilter(0, int64(*headNum), []common.Address{{}}, nil)
require.NoError(b, err)
filter := sys.NewRangeFilter(0, int64(*headNum), []common.Address{{}}, nil)
filter.Logs(context.Background())
d := time.Since(start)
b.Log("Finished running filter benchmarks")
Expand Down
77 changes: 52 additions & 25 deletions eth/filters/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,7 @@ type Filter struct {

// NewRangeFilter creates a new filter which uses a bloom filter on blocks to
// figure out whether a particular block is interesting or not.
func (sys *FilterSystem) NewRangeFilter(begin, end int64, addresses []common.Address, topics [][]common.Hash) (*Filter, error) {
allowUnfinalizedQueries := sys.backend.IsAllowUnfinalizedQueries()
acceptedBlock := sys.backend.LastAcceptedBlock()

func (sys *FilterSystem) NewRangeFilter(begin, end int64, addresses []common.Address, topics [][]common.Hash) *Filter {
// Flatten the address and topic filter clauses into a single bloombits filter
// system. Since the bloombits are not positional, nil topics are permitted,
// which get flattened into a nil byte slice.
Expand All @@ -77,24 +74,14 @@ func (sys *FilterSystem) NewRangeFilter(begin, end int64, addresses []common.Add
}
size, _ := sys.backend.BloomStatus()

if !allowUnfinalizedQueries && acceptedBlock != nil {
lastAccepted := acceptedBlock.Number().Int64()
if begin >= 0 && begin > lastAccepted {
return nil, fmt.Errorf("requested from block %d after last accepted block %d", begin, lastAccepted)
}
if end >= 0 && end > lastAccepted {
return nil, fmt.Errorf("requested to block %d after last accepted block %d", end, lastAccepted)
}
}

// Create a generic filter and convert it into a range filter
filter := newFilter(sys, addresses, topics)

filter.matcher = bloombits.NewMatcher(size, filters)
filter.begin = begin
filter.end = end

return filter, nil
return filter
}

// NewBlockFilter creates a new filter which directly inspects the contents of
Expand Down Expand Up @@ -130,6 +117,21 @@ func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) {
}
return f.blockLogs(ctx, header)
}

// Disallow blocks past the last accepted block if the backend does not
// allow unfinalized queries.
allowUnfinalizedQueries := f.sys.backend.IsAllowUnfinalizedQueries()
acceptedBlock := f.sys.backend.LastAcceptedBlock()
if !allowUnfinalizedQueries && acceptedBlock != nil {
lastAccepted := acceptedBlock.Number().Int64()
if f.begin >= 0 && f.begin > lastAccepted {
return nil, fmt.Errorf("requested from block %d after last accepted block %d", f.begin, lastAccepted)
}
if f.end >= 0 && f.end > lastAccepted {
return nil, fmt.Errorf("requested to block %d after last accepted block %d", f.end, lastAccepted)
}
}

// Short-cut if all we care about is pending logs
if f.begin == rpc.PendingBlockNumber.Int64() {
if f.end != rpc.PendingBlockNumber.Int64() {
Expand All @@ -149,14 +151,38 @@ func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) {
return nil, nil
}
var (
head = header.Number.Uint64()
end = uint64(f.end)
head = header.Number.Int64()
)
if f.begin < 0 {
f.begin = int64(head)

resolveSpecial := func(number int64) (int64, error) {
var hdr *types.Header
switch number {
case rpc.LatestBlockNumber.Int64():
return head, nil
case rpc.PendingBlockNumber.Int64():
// we should return head here since we've already captured
// that we need to get the pending logs in the pending boolean above
return head, nil
case rpc.FinalizedBlockNumber.Int64():
hdr, _ = f.sys.backend.HeaderByNumber(ctx, rpc.FinalizedBlockNumber)
if hdr == nil {
return 0, errors.New("finalized header not found")
}
case rpc.SafeBlockNumber.Int64():
hdr, _ = f.sys.backend.HeaderByNumber(ctx, rpc.SafeBlockNumber)
if hdr == nil {
return 0, errors.New("safe header not found")
}
default:
return number, nil
}
return hdr.Number.Int64(), nil
}
if f.end < 0 {
end = head
if f.begin, err = resolveSpecial(f.begin); err != nil {
return nil, err
}
if f.end, err = resolveSpecial(f.end); err != nil {
return nil, err
}

// When querying unfinalized data without a populated end block, it is
Expand All @@ -165,18 +191,19 @@ func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) {
// We error in this case to prevent a bad UX where the caller thinks there
// are no logs from the specified beginning to end (when in reality there may
// be some).
if end < uint64(f.begin) {
return nil, fmt.Errorf("begin block %d is greater than end block %d", f.begin, end)
if f.end < f.begin {
return nil, fmt.Errorf("begin block %d is greater than end block %d", f.begin, f.end)
}

// If the requested range of blocks exceeds the maximum number of blocks allowed by the backend
// return an error instead of searching for the logs.
if maxBlocks := f.sys.backend.GetMaxBlocksPerRequest(); int64(end)-f.begin >= maxBlocks && maxBlocks > 0 {
return nil, fmt.Errorf("requested too many blocks from %d to %d, maximum is set to %d", f.begin, int64(end), maxBlocks)
if maxBlocks := f.sys.backend.GetMaxBlocksPerRequest(); f.end-f.begin >= maxBlocks && maxBlocks > 0 {
return nil, fmt.Errorf("requested too many blocks from %d to %d, maximum is set to %d", f.begin, f.end, maxBlocks)
}
// Gather all indexed logs, and finish with non indexed ones
var (
logs []*types.Log
end = uint64(f.end)
size, sections = f.sys.backend.BloomStatus()
)
if indexed := sections * size; indexed > uint64(f.begin) {
Expand Down
Loading
Loading