Merge tag 'v1.10.7' into develop
This commit is contained in:
commit
416ff11059
@ -41,7 +41,7 @@ jobs:
|
|||||||
before_install:
|
before_install:
|
||||||
- export DOCKER_CLI_EXPERIMENTAL=enabled
|
- export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||||
script:
|
script:
|
||||||
- go run build/ci.go docker -image -manifest amd64,arm64 -upload karalabe/geth-docker-test
|
- go run build/ci.go docker -image -manifest amd64,arm64 -upload ethereum/client-go
|
||||||
|
|
||||||
- stage: build
|
- stage: build
|
||||||
if: type = push
|
if: type = push
|
||||||
@ -58,7 +58,7 @@ jobs:
|
|||||||
before_install:
|
before_install:
|
||||||
- export DOCKER_CLI_EXPERIMENTAL=enabled
|
- export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||||
script:
|
script:
|
||||||
- go run build/ci.go docker -image -manifest amd64,arm64 -upload karalabe/geth-docker-test
|
- go run build/ci.go docker -image -manifest amd64,arm64 -upload ethereum/client-go
|
||||||
|
|
||||||
# This builder does the Ubuntu PPA upload
|
# This builder does the Ubuntu PPA upload
|
||||||
- stage: build
|
- stage: build
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package bind
|
package bind
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
@ -74,6 +75,7 @@ func NewKeyStoreTransactor(keystore *keystore.KeyStore, account accounts.Account
|
|||||||
}
|
}
|
||||||
return tx.WithSignature(signer, signature)
|
return tx.WithSignature(signer, signature)
|
||||||
},
|
},
|
||||||
|
Context: context.Background(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,6 +99,7 @@ func NewKeyedTransactor(key *ecdsa.PrivateKey) *TransactOpts {
|
|||||||
}
|
}
|
||||||
return tx.WithSignature(signer, signature)
|
return tx.WithSignature(signer, signature)
|
||||||
},
|
},
|
||||||
|
Context: context.Background(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,6 +136,7 @@ func NewKeyStoreTransactorWithChainID(keystore *keystore.KeyStore, account accou
|
|||||||
}
|
}
|
||||||
return tx.WithSignature(signer, signature)
|
return tx.WithSignature(signer, signature)
|
||||||
},
|
},
|
||||||
|
Context: context.Background(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,6 +160,7 @@ func NewKeyedTransactorWithChainID(key *ecdsa.PrivateKey, chainID *big.Int) (*Tr
|
|||||||
}
|
}
|
||||||
return tx.WithSignature(signer, signature)
|
return tx.WithSignature(signer, signature)
|
||||||
},
|
},
|
||||||
|
Context: context.Background(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,5 +175,6 @@ func NewClefTransactor(clef *external.ExternalSigner, account accounts.Account)
|
|||||||
}
|
}
|
||||||
return clef.SignTx(account, transaction, nil) // Clef enforces its own chain id
|
return clef.SignTx(account, transaction, nil) // Clef enforces its own chain id
|
||||||
},
|
},
|
||||||
|
Context: context.Background(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -488,8 +488,19 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
|
|||||||
} else {
|
} else {
|
||||||
hi = b.pendingBlock.GasLimit()
|
hi = b.pendingBlock.GasLimit()
|
||||||
}
|
}
|
||||||
|
// Normalize the max fee per gas the call is willing to spend.
|
||||||
|
var feeCap *big.Int
|
||||||
|
if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) {
|
||||||
|
return 0, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
|
||||||
|
} else if call.GasPrice != nil {
|
||||||
|
feeCap = call.GasPrice
|
||||||
|
} else if call.GasFeeCap != nil {
|
||||||
|
feeCap = call.GasFeeCap
|
||||||
|
} else {
|
||||||
|
feeCap = common.Big0
|
||||||
|
}
|
||||||
// Recap the highest gas allowance with account's balance.
|
// Recap the highest gas allowance with account's balance.
|
||||||
if call.GasPrice != nil && call.GasPrice.BitLen() != 0 {
|
if feeCap.BitLen() != 0 {
|
||||||
balance := b.pendingState.GetBalance(call.From) // from can't be nil
|
balance := b.pendingState.GetBalance(call.From) // from can't be nil
|
||||||
available := new(big.Int).Set(balance)
|
available := new(big.Int).Set(balance)
|
||||||
if call.Value != nil {
|
if call.Value != nil {
|
||||||
@ -498,14 +509,14 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
|
|||||||
}
|
}
|
||||||
available.Sub(available, call.Value)
|
available.Sub(available, call.Value)
|
||||||
}
|
}
|
||||||
allowance := new(big.Int).Div(available, call.GasPrice)
|
allowance := new(big.Int).Div(available, feeCap)
|
||||||
if allowance.IsUint64() && hi > allowance.Uint64() {
|
if allowance.IsUint64() && hi > allowance.Uint64() {
|
||||||
transfer := call.Value
|
transfer := call.Value
|
||||||
if transfer == nil {
|
if transfer == nil {
|
||||||
transfer = new(big.Int)
|
transfer = new(big.Int)
|
||||||
}
|
}
|
||||||
log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance,
|
log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance,
|
||||||
"sent", transfer, "gasprice", call.GasPrice, "fundable", allowance)
|
"sent", transfer, "feecap", feeCap, "fundable", allowance)
|
||||||
hi = allowance.Uint64()
|
hi = allowance.Uint64()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -580,6 +580,26 @@ func TestEstimateGasWithPrice(t *testing.T) {
|
|||||||
Value: big.NewInt(100000000000),
|
Value: big.NewInt(100000000000),
|
||||||
Data: nil,
|
Data: nil,
|
||||||
}, 21000, errors.New("gas required exceeds allowance (10999)")}, // 10999=(2.2ether-1000wei)/(2e14)
|
}, 21000, errors.New("gas required exceeds allowance (10999)")}, // 10999=(2.2ether-1000wei)/(2e14)
|
||||||
|
|
||||||
|
{"EstimateEIP1559WithHighFees", ethereum.CallMsg{
|
||||||
|
From: addr,
|
||||||
|
To: &addr,
|
||||||
|
Gas: 0,
|
||||||
|
GasFeeCap: big.NewInt(1e14), // maxgascost = 2.1ether
|
||||||
|
GasTipCap: big.NewInt(1),
|
||||||
|
Value: big.NewInt(1e17), // the remaining balance for fee is 2.1ether
|
||||||
|
Data: nil,
|
||||||
|
}, params.TxGas, nil},
|
||||||
|
|
||||||
|
{"EstimateEIP1559WithSuperHighFees", ethereum.CallMsg{
|
||||||
|
From: addr,
|
||||||
|
To: &addr,
|
||||||
|
Gas: 0,
|
||||||
|
GasFeeCap: big.NewInt(1e14), // maxgascost = 2.1ether
|
||||||
|
GasTipCap: big.NewInt(1),
|
||||||
|
Value: big.NewInt(1e17 + 1), // the remaining balance for fee is 2.1ether
|
||||||
|
Data: nil,
|
||||||
|
}, params.TxGas, errors.New("gas required exceeds allowance (20999)")}, // 20999=(2.2ether-0.1ether-1wei)/(1e14)
|
||||||
}
|
}
|
||||||
for i, c := range cases {
|
for i, c := range cases {
|
||||||
got, err := sim.EstimateGas(context.Background(), c.message)
|
got, err := sim.EstimateGas(context.Background(), c.message)
|
||||||
@ -592,6 +612,9 @@ func TestEstimateGasWithPrice(t *testing.T) {
|
|||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if c.expectError == nil && err != nil {
|
||||||
|
t.Fatalf("test %d: didn't expect error, got %v", i, err)
|
||||||
|
}
|
||||||
if got != c.expect {
|
if got != c.expect {
|
||||||
t.Fatalf("test %d: gas estimation mismatch, want %d, got %d", i, c.expect, got)
|
t.Fatalf("test %d: gas estimation mismatch, want %d, got %d", i, c.expect, got)
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum"
|
"github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
@ -76,6 +78,29 @@ type WatchOpts struct {
|
|||||||
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
|
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MetaData collects all metadata for a bound contract.
|
||||||
|
type MetaData struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
Sigs map[string]string
|
||||||
|
Bin string
|
||||||
|
ABI string
|
||||||
|
ab *abi.ABI
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MetaData) GetAbi() (*abi.ABI, error) {
|
||||||
|
m.mu.Lock()
|
||||||
|
defer m.mu.Unlock()
|
||||||
|
if m.ab != nil {
|
||||||
|
return m.ab, nil
|
||||||
|
}
|
||||||
|
if parsed, err := abi.JSON(strings.NewReader(m.ABI)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
m.ab = &parsed
|
||||||
|
}
|
||||||
|
return m.ab, nil
|
||||||
|
}
|
||||||
|
|
||||||
// BoundContract is the base wrapper object that reflects a contract on the
|
// BoundContract is the base wrapper object that reflects a contract on the
|
||||||
// Ethereum network. It contains a collection of methods that are used by the
|
// Ethereum network. It contains a collection of methods that are used by the
|
||||||
// higher level contract bindings to operate.
|
// higher level contract bindings to operate.
|
||||||
|
@ -90,6 +90,7 @@ package {{.Package}}
|
|||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"strings"
|
"strings"
|
||||||
|
"errors"
|
||||||
|
|
||||||
ethereum "github.com/ethereum/go-ethereum"
|
ethereum "github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||||
@ -101,6 +102,7 @@ import (
|
|||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
var (
|
var (
|
||||||
|
_ = errors.New
|
||||||
_ = big.NewInt
|
_ = big.NewInt
|
||||||
_ = strings.NewReader
|
_ = strings.NewReader
|
||||||
_ = ethereum.NotFound
|
_ = ethereum.NotFound
|
||||||
@ -120,32 +122,48 @@ var (
|
|||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{range $contract := .Contracts}}
|
{{range $contract := .Contracts}}
|
||||||
// {{.Type}}ABI is the input ABI used to generate the binding from.
|
// {{.Type}}MetaData contains all meta data concerning the {{.Type}} contract.
|
||||||
const {{.Type}}ABI = "{{.InputABI}}"
|
var {{.Type}}MetaData = &bind.MetaData{
|
||||||
|
ABI: "{{.InputABI}}",
|
||||||
{{if $contract.FuncSigs}}
|
{{if $contract.FuncSigs -}}
|
||||||
// {{.Type}}FuncSigs maps the 4-byte function signature to its string representation.
|
Sigs: map[string]string{
|
||||||
var {{.Type}}FuncSigs = map[string]string{
|
|
||||||
{{range $strsig, $binsig := .FuncSigs}}"{{$binsig}}": "{{$strsig}}",
|
{{range $strsig, $binsig := .FuncSigs}}"{{$binsig}}": "{{$strsig}}",
|
||||||
{{end}}
|
{{end}}
|
||||||
|
},
|
||||||
|
{{end -}}
|
||||||
|
{{if .InputBin -}}
|
||||||
|
Bin: "0x{{.InputBin}}",
|
||||||
|
{{end}}
|
||||||
}
|
}
|
||||||
|
// {{.Type}}ABI is the input ABI used to generate the binding from.
|
||||||
|
// Deprecated: Use {{.Type}}MetaData.ABI instead.
|
||||||
|
var {{.Type}}ABI = {{.Type}}MetaData.ABI
|
||||||
|
|
||||||
|
{{if $contract.FuncSigs}}
|
||||||
|
// Deprecated: Use {{.Type}}MetaData.Sigs instead.
|
||||||
|
// {{.Type}}FuncSigs maps the 4-byte function signature to its string representation.
|
||||||
|
var {{.Type}}FuncSigs = {{.Type}}MetaData.Sigs
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{if .InputBin}}
|
{{if .InputBin}}
|
||||||
// {{.Type}}Bin is the compiled bytecode used for deploying new contracts.
|
// {{.Type}}Bin is the compiled bytecode used for deploying new contracts.
|
||||||
var {{.Type}}Bin = "0x{{.InputBin}}"
|
// Deprecated: Use {{.Type}}MetaData.Bin instead.
|
||||||
|
var {{.Type}}Bin = {{.Type}}MetaData.Bin
|
||||||
|
|
||||||
// Deploy{{.Type}} deploys a new Ethereum contract, binding an instance of {{.Type}} to it.
|
// Deploy{{.Type}} deploys a new Ethereum contract, binding an instance of {{.Type}} to it.
|
||||||
func Deploy{{.Type}}(auth *bind.TransactOpts, backend bind.ContractBackend {{range .Constructor.Inputs}}, {{.Name}} {{bindtype .Type $structs}}{{end}}) (common.Address, *types.Transaction, *{{.Type}}, error) {
|
func Deploy{{.Type}}(auth *bind.TransactOpts, backend bind.ContractBackend {{range .Constructor.Inputs}}, {{.Name}} {{bindtype .Type $structs}}{{end}}) (common.Address, *types.Transaction, *{{.Type}}, error) {
|
||||||
parsed, err := abi.JSON(strings.NewReader({{.Type}}ABI))
|
parsed, err := {{.Type}}MetaData.GetAbi()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Address{}, nil, nil, err
|
return common.Address{}, nil, nil, err
|
||||||
}
|
}
|
||||||
|
if parsed == nil {
|
||||||
|
return common.Address{}, nil, nil, errors.New("GetABI returned nil")
|
||||||
|
}
|
||||||
{{range $pattern, $name := .Libraries}}
|
{{range $pattern, $name := .Libraries}}
|
||||||
{{decapitalise $name}}Addr, _, _, _ := Deploy{{capitalise $name}}(auth, backend)
|
{{decapitalise $name}}Addr, _, _, _ := Deploy{{capitalise $name}}(auth, backend)
|
||||||
{{$contract.Type}}Bin = strings.Replace({{$contract.Type}}Bin, "__${{$pattern}}$__", {{decapitalise $name}}Addr.String()[2:], -1)
|
{{$contract.Type}}Bin = strings.Replace({{$contract.Type}}Bin, "__${{$pattern}}$__", {{decapitalise $name}}Addr.String()[2:], -1)
|
||||||
{{end}}
|
{{end}}
|
||||||
address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex({{.Type}}Bin), backend {{range .Constructor.Inputs}}, {{.Name}}{{end}})
|
address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex({{.Type}}Bin), backend {{range .Constructor.Inputs}}, {{.Name}}{{end}})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Address{}, nil, nil, err
|
return common.Address{}, nil, nil, err
|
||||||
}
|
}
|
||||||
|
13
accounts/external/backend.go
vendored
13
accounts/external/backend.go
vendored
@ -29,7 +29,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/event"
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/signer/core"
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ExternalBackend struct {
|
type ExternalBackend struct {
|
||||||
@ -203,7 +203,7 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
|
|||||||
t := common.NewMixedcaseAddress(*tx.To())
|
t := common.NewMixedcaseAddress(*tx.To())
|
||||||
to = &t
|
to = &t
|
||||||
}
|
}
|
||||||
args := &core.SendTxArgs{
|
args := &apitypes.SendTxArgs{
|
||||||
Data: &data,
|
Data: &data,
|
||||||
Nonce: hexutil.Uint64(tx.Nonce()),
|
Nonce: hexutil.Uint64(tx.Nonce()),
|
||||||
Value: hexutil.Big(*tx.Value()),
|
Value: hexutil.Big(*tx.Value()),
|
||||||
@ -211,11 +211,14 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
|
|||||||
To: to,
|
To: to,
|
||||||
From: common.NewMixedcaseAddress(account.Address),
|
From: common.NewMixedcaseAddress(account.Address),
|
||||||
}
|
}
|
||||||
if tx.GasFeeCap() != nil {
|
switch tx.Type() {
|
||||||
|
case types.LegacyTxType, types.AccessListTxType:
|
||||||
|
args.GasPrice = (*hexutil.Big)(tx.GasPrice())
|
||||||
|
case types.DynamicFeeTxType:
|
||||||
args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap())
|
args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap())
|
||||||
args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap())
|
args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap())
|
||||||
} else {
|
default:
|
||||||
args.GasPrice = (*hexutil.Big)(tx.GasPrice())
|
return nil, fmt.Errorf("Unsupported tx type %d", tx.Type())
|
||||||
}
|
}
|
||||||
// We should request the default chain id that we're operating with
|
// We should request the default chain id that we're operating with
|
||||||
// (the chain we're executing on)
|
// (the chain we're executing on)
|
||||||
|
@ -450,7 +450,7 @@ func maybeSkipArchive(env build.Environment) {
|
|||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
if env.Branch != "master" && !strings.HasPrefix(env.Tag, "v1.") {
|
if env.Branch != "master" && !strings.HasPrefix(env.Tag, "v1.") {
|
||||||
log.Printf("skipping archive creation because branch %q, tag %q is not on the whitelist", env.Branch, env.Tag)
|
log.Printf("skipping archive creation because branch %q, tag %q is not on the inclusion list", env.Branch, env.Tag)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -492,7 +492,7 @@ func doDocker(cmdline []string) {
|
|||||||
case env.Branch == "master":
|
case env.Branch == "master":
|
||||||
tags = []string{"latest"}
|
tags = []string{"latest"}
|
||||||
case strings.HasPrefix(env.Tag, "v1."):
|
case strings.HasPrefix(env.Tag, "v1."):
|
||||||
tags = []string{"stable", fmt.Sprintf("release-1.%d", params.VersionMinor), params.Version}
|
tags = []string{"stable", fmt.Sprintf("release-1.%d", params.VersionMinor), "v" + params.Version}
|
||||||
}
|
}
|
||||||
// If architecture specific image builds are requested, build and push them
|
// If architecture specific image builds are requested, build and push them
|
||||||
if *image {
|
if *image {
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/signer/core"
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
"github.com/ethereum/go-ethereum/signer/fourbyte"
|
"github.com/ethereum/go-ethereum/signer/fourbyte"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ func parse(data []byte) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
die(err)
|
die(err)
|
||||||
}
|
}
|
||||||
messages := core.ValidationMessages{}
|
messages := apitypes.ValidationMessages{}
|
||||||
db.ValidateCallData(nil, data, &messages)
|
db.ValidateCallData(nil, data, &messages)
|
||||||
for _, m := range messages.Messages {
|
for _, m := range messages.Messages {
|
||||||
fmt.Printf("%v: %v\n", m.Typ, m.Message)
|
fmt.Printf("%v: %v\n", m.Typ, m.Message)
|
||||||
|
@ -50,10 +50,10 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/ethereum/go-ethereum/signer/core"
|
"github.com/ethereum/go-ethereum/signer/core"
|
||||||
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
"github.com/ethereum/go-ethereum/signer/fourbyte"
|
"github.com/ethereum/go-ethereum/signer/fourbyte"
|
||||||
"github.com/ethereum/go-ethereum/signer/rules"
|
"github.com/ethereum/go-ethereum/signer/rules"
|
||||||
"github.com/ethereum/go-ethereum/signer/storage"
|
"github.com/ethereum/go-ethereum/signer/storage"
|
||||||
|
|
||||||
"github.com/mattn/go-colorable"
|
"github.com/mattn/go-colorable"
|
||||||
"github.com/mattn/go-isatty"
|
"github.com/mattn/go-isatty"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"gopkg.in/urfave/cli.v1"
|
||||||
@ -657,7 +657,7 @@ func signer(c *cli.Context) error {
|
|||||||
cors := utils.SplitAndTrim(c.GlobalString(utils.HTTPCORSDomainFlag.Name))
|
cors := utils.SplitAndTrim(c.GlobalString(utils.HTTPCORSDomainFlag.Name))
|
||||||
|
|
||||||
srv := rpc.NewServer()
|
srv := rpc.NewServer()
|
||||||
err := node.RegisterApisFromWhitelist(rpcAPI, []string{"account"}, srv, false)
|
err := node.RegisterApis(rpcAPI, []string{"account"}, srv, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Could not register API: %w", err)
|
utils.Fatalf("Could not register API: %w", err)
|
||||||
}
|
}
|
||||||
@ -923,7 +923,7 @@ func testExternalUI(api *core.SignerAPI) {
|
|||||||
time.Sleep(delay)
|
time.Sleep(delay)
|
||||||
data := hexutil.Bytes([]byte{})
|
data := hexutil.Bytes([]byte{})
|
||||||
to := common.NewMixedcaseAddress(a)
|
to := common.NewMixedcaseAddress(a)
|
||||||
tx := core.SendTxArgs{
|
tx := apitypes.SendTxArgs{
|
||||||
Data: &data,
|
Data: &data,
|
||||||
Nonce: 0x1,
|
Nonce: 0x1,
|
||||||
Value: hexutil.Big(*big.NewInt(6)),
|
Value: hexutil.Big(*big.NewInt(6)),
|
||||||
@ -1055,11 +1055,11 @@ func GenDoc(ctx *cli.Context) {
|
|||||||
data := hexutil.Bytes([]byte{0x01, 0x02, 0x03, 0x04})
|
data := hexutil.Bytes([]byte{0x01, 0x02, 0x03, 0x04})
|
||||||
add("SignTxRequest", desc, &core.SignTxRequest{
|
add("SignTxRequest", desc, &core.SignTxRequest{
|
||||||
Meta: meta,
|
Meta: meta,
|
||||||
Callinfo: []core.ValidationInfo{
|
Callinfo: []apitypes.ValidationInfo{
|
||||||
{Typ: "Warning", Message: "Something looks odd, show this message as a warning"},
|
{Typ: "Warning", Message: "Something looks odd, show this message as a warning"},
|
||||||
{Typ: "Info", Message: "User should see this as well"},
|
{Typ: "Info", Message: "User should see this as well"},
|
||||||
},
|
},
|
||||||
Transaction: core.SendTxArgs{
|
Transaction: apitypes.SendTxArgs{
|
||||||
Data: &data,
|
Data: &data,
|
||||||
Nonce: 0x1,
|
Nonce: 0x1,
|
||||||
Value: hexutil.Big(*big.NewInt(6)),
|
Value: hexutil.Big(*big.NewInt(6)),
|
||||||
@ -1075,7 +1075,7 @@ func GenDoc(ctx *cli.Context) {
|
|||||||
add("SignTxResponse - approve", "Response to request to sign a transaction. This response needs to contain the `transaction`"+
|
add("SignTxResponse - approve", "Response to request to sign a transaction. This response needs to contain the `transaction`"+
|
||||||
", because the UI is free to make modifications to the transaction.",
|
", because the UI is free to make modifications to the transaction.",
|
||||||
&core.SignTxResponse{Approved: true,
|
&core.SignTxResponse{Approved: true,
|
||||||
Transaction: core.SendTxArgs{
|
Transaction: apitypes.SendTxArgs{
|
||||||
Data: &data,
|
Data: &data,
|
||||||
Nonce: 0x4,
|
Nonce: 0x4,
|
||||||
Value: hexutil.Big(*big.NewInt(6)),
|
Value: hexutil.Big(*big.NewInt(6)),
|
||||||
|
@ -79,14 +79,44 @@ func BasicPing(t *utesting.T) {
|
|||||||
To: te.remoteEndpoint(),
|
To: te.remoteEndpoint(),
|
||||||
Expiration: futureExpiration(),
|
Expiration: futureExpiration(),
|
||||||
})
|
})
|
||||||
|
if err := te.checkPingPong(pingHash); err != nil {
|
||||||
reply, _, _ := te.read(te.l1)
|
|
||||||
if err := te.checkPong(reply, pingHash); err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkPong verifies that reply is a valid PONG matching the given ping hash.
|
// checkPingPong verifies that the remote side sends both a PONG with the
|
||||||
|
// correct hash, and a PING.
|
||||||
|
// The two packets do not have to be in any particular order.
|
||||||
|
func (te *testenv) checkPingPong(pingHash []byte) error {
|
||||||
|
var (
|
||||||
|
pings int
|
||||||
|
pongs int
|
||||||
|
)
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
reply, _, err := te.read(te.l1)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch reply.Kind() {
|
||||||
|
case v4wire.PongPacket:
|
||||||
|
if err := te.checkPong(reply, pingHash); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
pongs++
|
||||||
|
case v4wire.PingPacket:
|
||||||
|
pings++
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("expected PING or PONG, got %v %v", reply.Name(), reply)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if pongs == 1 && pings == 1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("expected 1 PING (got %d) and 1 PONG (got %d)", pings, pongs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkPong verifies that reply is a valid PONG matching the given ping hash,
|
||||||
|
// and a PING. The two packets do not have to be in any particular order.
|
||||||
func (te *testenv) checkPong(reply v4wire.Packet, pingHash []byte) error {
|
func (te *testenv) checkPong(reply v4wire.Packet, pingHash []byte) error {
|
||||||
if reply == nil {
|
if reply == nil {
|
||||||
return fmt.Errorf("expected PONG reply, got nil")
|
return fmt.Errorf("expected PONG reply, got nil")
|
||||||
@ -119,9 +149,7 @@ func PingWrongTo(t *utesting.T) {
|
|||||||
To: wrongEndpoint,
|
To: wrongEndpoint,
|
||||||
Expiration: futureExpiration(),
|
Expiration: futureExpiration(),
|
||||||
})
|
})
|
||||||
|
if err := te.checkPingPong(pingHash); err != nil {
|
||||||
reply, _, _ := te.read(te.l1)
|
|
||||||
if err := te.checkPong(reply, pingHash); err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,8 +167,7 @@ func PingWrongFrom(t *utesting.T) {
|
|||||||
Expiration: futureExpiration(),
|
Expiration: futureExpiration(),
|
||||||
})
|
})
|
||||||
|
|
||||||
reply, _, _ := te.read(te.l1)
|
if err := te.checkPingPong(pingHash); err != nil {
|
||||||
if err := te.checkPong(reply, pingHash); err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,8 +188,7 @@ func PingExtraData(t *utesting.T) {
|
|||||||
JunkData2: []byte{9, 8, 7, 6, 5, 4, 3, 2, 1},
|
JunkData2: []byte{9, 8, 7, 6, 5, 4, 3, 2, 1},
|
||||||
})
|
})
|
||||||
|
|
||||||
reply, _, _ := te.read(te.l1)
|
if err := te.checkPingPong(pingHash); err != nil {
|
||||||
if err := te.checkPong(reply, pingHash); err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,8 +209,7 @@ func PingExtraDataWrongFrom(t *utesting.T) {
|
|||||||
JunkData2: []byte{9, 8, 7, 6, 5, 4, 3, 2, 1},
|
JunkData2: []byte{9, 8, 7, 6, 5, 4, 3, 2, 1},
|
||||||
}
|
}
|
||||||
pingHash := te.send(te.l1, &req)
|
pingHash := te.send(te.l1, &req)
|
||||||
reply, _, _ := te.read(te.l1)
|
if err := te.checkPingPong(pingHash); err != nil {
|
||||||
if err := te.checkPong(reply, pingHash); err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -240,9 +265,9 @@ func BondThenPingWithWrongFrom(t *utesting.T) {
|
|||||||
To: te.remoteEndpoint(),
|
To: te.remoteEndpoint(),
|
||||||
Expiration: futureExpiration(),
|
Expiration: futureExpiration(),
|
||||||
})
|
})
|
||||||
|
if reply, _, err := te.read(te.l1); err != nil {
|
||||||
reply, _, _ := te.read(te.l1)
|
t.Fatal(err)
|
||||||
if err := te.checkPong(reply, pingHash); err != nil {
|
} else if err := te.checkPong(reply, pingHash); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,15 @@ The `evm t8n` tool is a stateless state transition utility. It is a utility
|
|||||||
which can
|
which can
|
||||||
|
|
||||||
1. Take a prestate, including
|
1. Take a prestate, including
|
||||||
- Accounts,
|
- Accounts,
|
||||||
- Block context information,
|
- Block context information,
|
||||||
- Previous blockshashes (*optional)
|
- Previous blockshashes (*optional)
|
||||||
2. Apply a set of transactions,
|
2. Apply a set of transactions,
|
||||||
3. Apply a mining-reward (*optional),
|
3. Apply a mining-reward (*optional),
|
||||||
4. And generate a post-state, including
|
4. And generate a post-state, including
|
||||||
- State root, transaction root, receipt root,
|
- State root, transaction root, receipt root,
|
||||||
- Information about rejected transactions,
|
- Information about rejected transactions,
|
||||||
- Optionally: a full or partial post-state dump
|
- Optionally: a full or partial post-state dump
|
||||||
|
|
||||||
## Specification
|
## Specification
|
||||||
|
|
||||||
@ -37,6 +37,8 @@ Command line params that has to be supported are
|
|||||||
--output.result result Determines where to put the result (stateroot, txroot etc) of the post-state.
|
--output.result result Determines where to put the result (stateroot, txroot etc) of the post-state.
|
||||||
`stdout` - into the stdout output
|
`stdout` - into the stdout output
|
||||||
`stderr` - into the stderr output
|
`stderr` - into the stderr output
|
||||||
|
--output.body value If set, the RLP of the transactions (block body) will be written to this file.
|
||||||
|
--input.txs stdin stdin or file name of where to find the transactions to apply. If the file prefix is '.rlp', then the data is interpreted as an RLP list of signed transactions.The '.rlp' format is identical to the output.body format. (default: "txs.json")
|
||||||
--state.fork value Name of ruleset to use.
|
--state.fork value Name of ruleset to use.
|
||||||
--state.chainid value ChainID to use (default: 1)
|
--state.chainid value ChainID to use (default: 1)
|
||||||
--state.reward value Mining reward. Set to -1 to disable (default: 0)
|
--state.reward value Mining reward. Set to -1 to disable (default: 0)
|
||||||
@ -110,7 +112,10 @@ Two resulting files:
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"rejected": [
|
"rejected": [
|
||||||
1
|
{
|
||||||
|
"index": 1,
|
||||||
|
"error": "nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -156,7 +161,10 @@ Output:
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"rejected": [
|
"rejected": [
|
||||||
1
|
{
|
||||||
|
"index": 1,
|
||||||
|
"error": "nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,34 +239,46 @@ The `BLOCKHASH` opcode requires blockhashes to be provided by the caller, inside
|
|||||||
If a required blockhash is not provided, the exit code should be `4`:
|
If a required blockhash is not provided, the exit code should be `4`:
|
||||||
Example where blockhashes are provided:
|
Example where blockhashes are provided:
|
||||||
```
|
```
|
||||||
./evm t8n --input.alloc=./testdata/3/alloc.json --input.txs=./testdata/3/txs.json --input.env=./testdata/3/env.json --trace
|
./evm --verbosity=1 t8n --input.alloc=./testdata/3/alloc.json --input.txs=./testdata/3/txs.json --input.env=./testdata/3/env.json --trace
|
||||||
|
INFO [07-27|11:53:40.960] Trie dumping started root=b7341d..857ea1
|
||||||
|
INFO [07-27|11:53:40.960] Trie dumping complete accounts=3 elapsed="103.298µs"
|
||||||
|
INFO [07-27|11:53:40.960] Wrote file file=alloc.json
|
||||||
|
INFO [07-27|11:53:40.960] Wrote file file=result.json
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2
|
cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2
|
||||||
```
|
```
|
||||||
```
|
```
|
||||||
{"pc":0,"op":96,"gas":"0x5f58ef8","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"PUSH1","error":""}
|
{"pc":0,"op":96,"gas":"0x5f58ef8","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"returnData":"0x","depth":1,"refund":0,"opName":"PUSH1","error":""}
|
||||||
{"pc":2,"op":64,"gas":"0x5f58ef5","gasCost":"0x14","memory":"0x","memSize":0,"stack":["0x1"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"BLOCKHASH","error":""}
|
{"pc":2,"op":64,"gas":"0x5f58ef5","gasCost":"0x14","memory":"0x","memSize":0,"stack":["0x1"],"returnData":"0x","depth":1,"refund":0,"opName":"BLOCKHASH","error":""}
|
||||||
{"pc":3,"op":0,"gas":"0x5f58ee1","gasCost":"0x0","memory":"0x","memSize":0,"stack":["0xdac58aa524e50956d0c0bae7f3f8bb9d35381365d07804dd5b48a5a297c06af4"],"returnStack":[],"returnData":"0x","depth":1,"refund":0,"opName":"STOP","error":""}
|
{"pc":3,"op":0,"gas":"0x5f58ee1","gasCost":"0x0","memory":"0x","memSize":0,"stack":["0xdac58aa524e50956d0c0bae7f3f8bb9d35381365d07804dd5b48a5a297c06af4"],"returnData":"0x","depth":1,"refund":0,"opName":"STOP","error":""}
|
||||||
{"output":"","gasUsed":"0x17","time":142709}
|
{"output":"","gasUsed":"0x17","time":156276}
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example, the caller has not provided the required blockhash:
|
In this example, the caller has not provided the required blockhash:
|
||||||
```
|
```
|
||||||
./evm t8n --input.alloc=./testdata/4/alloc.json --input.txs=./testdata/4/txs.json --input.env=./testdata/4/env.json --trace
|
./evm t8n --input.alloc=./testdata/4/alloc.json --input.txs=./testdata/4/txs.json --input.env=./testdata/4/env.json --trace
|
||||||
```
|
|
||||||
```
|
|
||||||
ERROR(4): getHash(3) invoked, blockhash for that block not provided
|
ERROR(4): getHash(3) invoked, blockhash for that block not provided
|
||||||
```
|
```
|
||||||
Error code: 4
|
Error code: 4
|
||||||
|
|
||||||
### Chaining
|
### Chaining
|
||||||
|
|
||||||
Another thing that can be done, is to chain invocations:
|
Another thing that can be done, is to chain invocations:
|
||||||
```
|
```
|
||||||
./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --output.alloc=stdout | ./evm t8n --input.alloc=stdin --input.env=./testdata/1/env.json --input.txs=./testdata/1/txs.json
|
./evm t8n --input.alloc=./testdata/1/alloc.json --input.txs=./testdata/1/txs.json --input.env=./testdata/1/env.json --output.alloc=stdout | ./evm t8n --input.alloc=stdin --input.env=./testdata/1/env.json --input.txs=./testdata/1/txs.json
|
||||||
INFO [01-21|22:41:22.963] rejected tx index=1 hash=0557ba..18d673 from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1"
|
INFO [07-27|11:53:41.049] rejected tx index=1 hash=0557ba..18d673 from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1"
|
||||||
INFO [01-21|22:41:22.966] rejected tx index=0 hash=0557ba..18d673 from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1"
|
INFO [07-27|11:53:41.050] Trie dumping started root=84208a..ae4e13
|
||||||
INFO [01-21|22:41:22.967] rejected tx index=1 hash=0557ba..18d673 from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1"
|
INFO [07-27|11:53:41.050] Trie dumping complete accounts=3 elapsed="59.412µs"
|
||||||
|
INFO [07-27|11:53:41.050] Wrote file file=result.json
|
||||||
|
INFO [07-27|11:53:41.051] rejected tx index=0 hash=0557ba..18d673 from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1"
|
||||||
|
INFO [07-27|11:53:41.051] rejected tx index=1 hash=0557ba..18d673 from=0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192 error="nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1"
|
||||||
|
INFO [07-27|11:53:41.052] Trie dumping started root=84208a..ae4e13
|
||||||
|
INFO [07-27|11:53:41.052] Trie dumping complete accounts=3 elapsed="45.734µs"
|
||||||
|
INFO [07-27|11:53:41.052] Wrote file file=alloc.json
|
||||||
|
INFO [07-27|11:53:41.052] Wrote file file=result.json
|
||||||
|
|
||||||
```
|
```
|
||||||
What happened here, is that we first applied two identical transactions, so the second one was rejected.
|
What happened here, is that we first applied two identical transactions, so the second one was rejected.
|
||||||
@ -267,3 +287,52 @@ the same two transactions: this time, both failed due to too low nonce.
|
|||||||
|
|
||||||
In order to meaningfully chain invocations, one would need to provide meaningful new `env`, otherwise the
|
In order to meaningfully chain invocations, one would need to provide meaningful new `env`, otherwise the
|
||||||
actual blocknumber (exposed to the EVM) would not increase.
|
actual blocknumber (exposed to the EVM) would not increase.
|
||||||
|
|
||||||
|
### Transactions in RLP form
|
||||||
|
|
||||||
|
It is possible to provide already-signed transactions as input to, using an `input.txs` which ends with the `rlp` suffix.
|
||||||
|
The input format for RLP-form transactions is _identical_ to the _output_ format for block bodies. Therefore, it's fully possible
|
||||||
|
to use the evm to go from `json` input to `rlp` input.
|
||||||
|
|
||||||
|
The following command takes **json** the transactions in `./testdata/13/txs.json` and signs them. After execution, they are output to `signed_txs.rlp`.:
|
||||||
|
```
|
||||||
|
./evm t8n --state.fork=London --input.alloc=./testdata/13/alloc.json --input.txs=./testdata/13/txs.json --input.env=./testdata/13/env.json --output.result=alloc_jsontx.json --output.body=signed_txs.rlp
|
||||||
|
INFO [07-27|11:53:41.124] Trie dumping started root=e4b924..6aef61
|
||||||
|
INFO [07-27|11:53:41.124] Trie dumping complete accounts=3 elapsed="94.284µs"
|
||||||
|
INFO [07-27|11:53:41.125] Wrote file file=alloc.json
|
||||||
|
INFO [07-27|11:53:41.125] Wrote file file=alloc_jsontx.json
|
||||||
|
INFO [07-27|11:53:41.125] Wrote file file=signed_txs.rlp
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
The `output.body` is the rlp-list of transactions, encoded in hex and placed in a string a'la `json` encoding rules:
|
||||||
|
```
|
||||||
|
cat signed_txs.rlp
|
||||||
|
"0xf8d2b86702f864010180820fa08284d09411111111111111111111111111111111111111118080c001a0b7dfab36232379bb3d1497a4f91c1966b1f932eae3ade107bf5d723b9cb474e0a06261c359a10f2132f126d250485b90cf20f30340801244a08ef6142ab33d1904b86702f864010280820fa08284d09411111111111111111111111111111111111111118080c080a0d4ec563b6568cd42d998fc4134b36933c6568d01533b5adf08769270243c6c7fa072bf7c21eac6bbeae5143371eef26d5e279637f3bd73482b55979d76d935b1e9"
|
||||||
|
```
|
||||||
|
|
||||||
|
We can use `rlpdump` to check what the contents are:
|
||||||
|
```
|
||||||
|
rlpdump -hex $(cat signed_txs.rlp | jq -r )
|
||||||
|
[
|
||||||
|
02f864010180820fa08284d09411111111111111111111111111111111111111118080c001a0b7dfab36232379bb3d1497a4f91c1966b1f932eae3ade107bf5d723b9cb474e0a06261c359a10f2132f126d250485b90cf20f30340801244a08ef6142ab33d1904,
|
||||||
|
02f864010280820fa08284d09411111111111111111111111111111111111111118080c080a0d4ec563b6568cd42d998fc4134b36933c6568d01533b5adf08769270243c6c7fa072bf7c21eac6bbeae5143371eef26d5e279637f3bd73482b55979d76d935b1e9,
|
||||||
|
]
|
||||||
|
```
|
||||||
|
Now, we can now use those (or any other already signed transactions), as input, like so:
|
||||||
|
```
|
||||||
|
./evm t8n --state.fork=London --input.alloc=./testdata/13/alloc.json --input.txs=./signed_txs.rlp --input.env=./testdata/13/env.json --output.result=alloc_rlptx.json
|
||||||
|
INFO [07-27|11:53:41.253] Trie dumping started root=e4b924..6aef61
|
||||||
|
INFO [07-27|11:53:41.253] Trie dumping complete accounts=3 elapsed="128.445µs"
|
||||||
|
INFO [07-27|11:53:41.253] Wrote file file=alloc.json
|
||||||
|
INFO [07-27|11:53:41.255] Wrote file file=alloc_rlptx.json
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
You might have noticed that the results from these two invocations were stored in two separate files.
|
||||||
|
And we can now finally check that they match.
|
||||||
|
```
|
||||||
|
cat alloc_jsontx.json | jq .stateRoot && cat alloc_rlptx.json | jq .stateRoot
|
||||||
|
"0xe4b924a6adb5959fccf769d5b7bb2f6359e26d1e76a2443c5a91a36d826aef61"
|
||||||
|
"0xe4b924a6adb5959fccf769d5b7bb2f6359e26d1e76a2443c5a91a36d826aef61"
|
||||||
|
```
|
||||||
|
@ -80,7 +80,9 @@ var (
|
|||||||
}
|
}
|
||||||
InputTxsFlag = cli.StringFlag{
|
InputTxsFlag = cli.StringFlag{
|
||||||
Name: "input.txs",
|
Name: "input.txs",
|
||||||
Usage: "`stdin` or file name of where to find the transactions to apply.",
|
Usage: "`stdin` or file name of where to find the transactions to apply. " +
|
||||||
|
"If the file prefix is '.rlp', then the data is interpreted as an RLP list of signed transactions." +
|
||||||
|
"The '.rlp' format is identical to the output.body format.",
|
||||||
Value: "txs.json",
|
Value: "txs.json",
|
||||||
}
|
}
|
||||||
RewardFlag = cli.Int64Flag{
|
RewardFlag = cli.Int64Flag{
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
@ -72,6 +73,7 @@ type input struct {
|
|||||||
Alloc core.GenesisAlloc `json:"alloc,omitempty"`
|
Alloc core.GenesisAlloc `json:"alloc,omitempty"`
|
||||||
Env *stEnv `json:"env,omitempty"`
|
Env *stEnv `json:"env,omitempty"`
|
||||||
Txs []*txWithKey `json:"txs,omitempty"`
|
Txs []*txWithKey `json:"txs,omitempty"`
|
||||||
|
TxRlp string `json:"txsRlp,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func Main(ctx *cli.Context) error {
|
func Main(ctx *cli.Context) error {
|
||||||
@ -199,12 +201,45 @@ func Main(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
defer inFile.Close()
|
defer inFile.Close()
|
||||||
decoder := json.NewDecoder(inFile)
|
decoder := json.NewDecoder(inFile)
|
||||||
|
if strings.HasSuffix(txStr, ".rlp") {
|
||||||
|
var body hexutil.Bytes
|
||||||
|
if err := decoder.Decode(&body); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var txs types.Transactions
|
||||||
|
if err := rlp.DecodeBytes(body, &txs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, tx := range txs {
|
||||||
|
txsWithKeys = append(txsWithKeys, &txWithKey{
|
||||||
|
key: nil,
|
||||||
|
tx: tx,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if err := decoder.Decode(&txsWithKeys); err != nil {
|
if err := decoder.Decode(&txsWithKeys); err != nil {
|
||||||
return NewError(ErrorJson, fmt.Errorf("failed unmarshaling txs-file: %v", err))
|
return NewError(ErrorJson, fmt.Errorf("failed unmarshaling txs-file: %v", err))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if len(inputData.TxRlp) > 0 {
|
||||||
|
// Decode the body of already signed transactions
|
||||||
|
body := common.FromHex(inputData.TxRlp)
|
||||||
|
var txs types.Transactions
|
||||||
|
if err := rlp.DecodeBytes(body, &txs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, tx := range txs {
|
||||||
|
txsWithKeys = append(txsWithKeys, &txWithKey{
|
||||||
|
key: nil,
|
||||||
|
tx: tx,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// JSON encoded transactions
|
||||||
txsWithKeys = inputData.Txs
|
txsWithKeys = inputData.Txs
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// We may have to sign the transactions.
|
// We may have to sign the transactions.
|
||||||
signer := types.MakeSigner(chainConfig, big.NewInt(int64(prestate.Env.Number)))
|
signer := types.MakeSigner(chainConfig, big.NewInt(int64(prestate.Env.Number)))
|
||||||
|
|
||||||
@ -365,6 +400,7 @@ func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, a
|
|||||||
return NewError(ErrorJson, fmt.Errorf("failed marshalling output: %v", err))
|
return NewError(ErrorJson, fmt.Errorf("failed marshalling output: %v", err))
|
||||||
}
|
}
|
||||||
os.Stdout.Write(b)
|
os.Stdout.Write(b)
|
||||||
|
os.Stdout.Write([]byte("\n"))
|
||||||
}
|
}
|
||||||
if len(stdErrObject) > 0 {
|
if len(stdErrObject) > 0 {
|
||||||
b, err := json.MarshalIndent(stdErrObject, "", " ")
|
b, err := json.MarshalIndent(stdErrObject, "", " ")
|
||||||
@ -372,6 +408,7 @@ func dispatchOutput(ctx *cli.Context, baseDir string, result *ExecutionResult, a
|
|||||||
return NewError(ErrorJson, fmt.Errorf("failed marshalling output: %v", err))
|
return NewError(ErrorJson, fmt.Errorf("failed marshalling output: %v", err))
|
||||||
}
|
}
|
||||||
os.Stderr.Write(b)
|
os.Stderr.Write(b)
|
||||||
|
os.Stderr.Write([]byte("\n"))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
23
cmd/evm/testdata/13/alloc.json
vendored
Normal file
23
cmd/evm/testdata/13/alloc.json
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"0x1111111111111111111111111111111111111111" : {
|
||||||
|
"balance" : "0x010000000000",
|
||||||
|
"code" : "0xfe",
|
||||||
|
"nonce" : "0x01",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||||
|
"balance" : "0x010000000000",
|
||||||
|
"code" : "0x",
|
||||||
|
"nonce" : "0x01",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"0xd02d72e067e77158444ef2020ff2d325f929b363" : {
|
||||||
|
"balance" : "0x01000000000000",
|
||||||
|
"code" : "0x",
|
||||||
|
"nonce" : "0x01",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
cmd/evm/testdata/13/env.json
vendored
Normal file
12
cmd/evm/testdata/13/env.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||||
|
"currentDifficulty" : "0x020000",
|
||||||
|
"currentNumber" : "0x01",
|
||||||
|
"currentTimestamp" : "0x079e",
|
||||||
|
"previousHash" : "0xcb23ee65a163121f640673b41788ee94633941405f95009999b502eedfbbfd4f",
|
||||||
|
"currentGasLimit" : "0x40000000",
|
||||||
|
"currentBaseFee" : "0x036b",
|
||||||
|
"blockHashes" : {
|
||||||
|
"0" : "0xcb23ee65a163121f640673b41788ee94633941405f95009999b502eedfbbfd4f"
|
||||||
|
}
|
||||||
|
}
|
4
cmd/evm/testdata/13/readme.md
vendored
Normal file
4
cmd/evm/testdata/13/readme.md
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
## Input transactions in RLP form
|
||||||
|
|
||||||
|
This testdata folder is used to examplify how transaction input can be provided in rlp form.
|
||||||
|
Please see the README in `evm` folder for how this is performed.
|
34
cmd/evm/testdata/13/txs.json
vendored
Normal file
34
cmd/evm/testdata/13/txs.json
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"input" : "0x",
|
||||||
|
"gas" : "0x84d0",
|
||||||
|
"nonce" : "0x1",
|
||||||
|
"to" : "0x1111111111111111111111111111111111111111",
|
||||||
|
"value" : "0x0",
|
||||||
|
"v" : "0x0",
|
||||||
|
"r" : "0x0",
|
||||||
|
"s" : "0x0",
|
||||||
|
"secretKey" : "0x41f6e321b31e72173f8ff2e292359e1862f24fba42fe6f97efaf641980eff298",
|
||||||
|
"chainId" : "0x1",
|
||||||
|
"type" : "0x2",
|
||||||
|
"maxFeePerGas" : "0xfa0",
|
||||||
|
"maxPriorityFeePerGas" : "0x0",
|
||||||
|
"accessList" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"input" : "0x",
|
||||||
|
"gas" : "0x84d0",
|
||||||
|
"nonce" : "0x2",
|
||||||
|
"to" : "0x1111111111111111111111111111111111111111",
|
||||||
|
"value" : "0x0",
|
||||||
|
"v" : "0x0",
|
||||||
|
"r" : "0x0",
|
||||||
|
"s" : "0x0",
|
||||||
|
"secretKey" : "0x41f6e321b31e72173f8ff2e292359e1862f24fba42fe6f97efaf641980eff298",
|
||||||
|
"chainId" : "0x1",
|
||||||
|
"type" : "0x2",
|
||||||
|
"maxFeePerGas" : "0xfa0",
|
||||||
|
"maxPriorityFeePerGas" : "0x0",
|
||||||
|
"accessList" : []
|
||||||
|
}
|
||||||
|
]
|
@ -11,6 +11,8 @@ function showjson(){
|
|||||||
function demo(){
|
function demo(){
|
||||||
echo "$ticks"
|
echo "$ticks"
|
||||||
echo "$1"
|
echo "$1"
|
||||||
|
$1
|
||||||
|
echo ""
|
||||||
echo "$ticks"
|
echo "$ticks"
|
||||||
echo ""
|
echo ""
|
||||||
}
|
}
|
||||||
@ -152,9 +154,7 @@ echo ""
|
|||||||
echo "The \`BLOCKHASH\` opcode requires blockhashes to be provided by the caller, inside the \`env\`."
|
echo "The \`BLOCKHASH\` opcode requires blockhashes to be provided by the caller, inside the \`env\`."
|
||||||
echo "If a required blockhash is not provided, the exit code should be \`4\`:"
|
echo "If a required blockhash is not provided, the exit code should be \`4\`:"
|
||||||
echo "Example where blockhashes are provided: "
|
echo "Example where blockhashes are provided: "
|
||||||
cmd="./evm t8n --input.alloc=./testdata/3/alloc.json --input.txs=./testdata/3/txs.json --input.env=./testdata/3/env.json --trace"
|
demo "./evm --verbosity=1 t8n --input.alloc=./testdata/3/alloc.json --input.txs=./testdata/3/txs.json --input.env=./testdata/3/env.json --trace"
|
||||||
tick && echo $cmd && tick
|
|
||||||
$cmd 2>&1 >/dev/null
|
|
||||||
cmd="cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2"
|
cmd="cat trace-0-0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81.jsonl | grep BLOCKHASH -C2"
|
||||||
tick && echo $cmd && tick
|
tick && echo $cmd && tick
|
||||||
echo "$ticks"
|
echo "$ticks"
|
||||||
@ -164,13 +164,11 @@ echo ""
|
|||||||
|
|
||||||
echo "In this example, the caller has not provided the required blockhash:"
|
echo "In this example, the caller has not provided the required blockhash:"
|
||||||
cmd="./evm t8n --input.alloc=./testdata/4/alloc.json --input.txs=./testdata/4/txs.json --input.env=./testdata/4/env.json --trace"
|
cmd="./evm t8n --input.alloc=./testdata/4/alloc.json --input.txs=./testdata/4/txs.json --input.env=./testdata/4/env.json --trace"
|
||||||
tick && echo $cmd && tick
|
tick && echo $cmd && $cmd
|
||||||
tick
|
|
||||||
$cmd
|
|
||||||
errc=$?
|
errc=$?
|
||||||
tick
|
tick
|
||||||
echo "Error code: $errc"
|
echo "Error code: $errc"
|
||||||
|
echo ""
|
||||||
|
|
||||||
echo "### Chaining"
|
echo "### Chaining"
|
||||||
echo ""
|
echo ""
|
||||||
@ -189,3 +187,28 @@ echo ""
|
|||||||
echo "In order to meaningfully chain invocations, one would need to provide meaningful new \`env\`, otherwise the"
|
echo "In order to meaningfully chain invocations, one would need to provide meaningful new \`env\`, otherwise the"
|
||||||
echo "actual blocknumber (exposed to the EVM) would not increase."
|
echo "actual blocknumber (exposed to the EVM) would not increase."
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
echo "### Transactions in RLP form"
|
||||||
|
echo ""
|
||||||
|
echo "It is possible to provide already-signed transactions as input to, using an \`input.txs\` which ends with the \`rlp\` suffix."
|
||||||
|
echo "The input format for RLP-form transactions is _identical_ to the _output_ format for block bodies. Therefore, it's fully possible"
|
||||||
|
echo "to use the evm to go from \`json\` input to \`rlp\` input."
|
||||||
|
echo ""
|
||||||
|
echo "The following command takes **json** the transactions in \`./testdata/13/txs.json\` and signs them. After execution, they are output to \`signed_txs.rlp\`.:"
|
||||||
|
demo "./evm t8n --state.fork=London --input.alloc=./testdata/13/alloc.json --input.txs=./testdata/13/txs.json --input.env=./testdata/13/env.json --output.result=alloc_jsontx.json --output.body=signed_txs.rlp"
|
||||||
|
echo "The \`output.body\` is the rlp-list of transactions, encoded in hex and placed in a string a'la \`json\` encoding rules:"
|
||||||
|
demo "cat signed_txs.rlp"
|
||||||
|
echo "We can use \`rlpdump\` to check what the contents are: "
|
||||||
|
echo "$ticks"
|
||||||
|
echo "rlpdump -hex \$(cat signed_txs.rlp | jq -r )"
|
||||||
|
rlpdump -hex $(cat signed_txs.rlp | jq -r )
|
||||||
|
echo "$ticks"
|
||||||
|
echo "Now, we can now use those (or any other already signed transactions), as input, like so: "
|
||||||
|
demo "./evm t8n --state.fork=London --input.alloc=./testdata/13/alloc.json --input.txs=./signed_txs.rlp --input.env=./testdata/13/env.json --output.result=alloc_rlptx.json"
|
||||||
|
|
||||||
|
echo "You might have noticed that the results from these two invocations were stored in two separate files. "
|
||||||
|
echo "And we can now finally check that they match."
|
||||||
|
echo "$ticks"
|
||||||
|
echo "cat alloc_jsontx.json | jq .stateRoot && cat alloc_rlptx.json | jq .stateRoot"
|
||||||
|
cat alloc_jsontx.json | jq .stateRoot && cat alloc_rlptx.json | jq .stateRoot
|
||||||
|
echo "$ticks"
|
||||||
|
@ -121,7 +121,7 @@ var (
|
|||||||
utils.MiningEnabledFlag,
|
utils.MiningEnabledFlag,
|
||||||
utils.MinerThreadsFlag,
|
utils.MinerThreadsFlag,
|
||||||
utils.MinerNotifyFlag,
|
utils.MinerNotifyFlag,
|
||||||
utils.MinerGasTargetFlag,
|
utils.LegacyMinerGasTargetFlag,
|
||||||
utils.MinerGasLimitFlag,
|
utils.MinerGasLimitFlag,
|
||||||
utils.MinerGasPriceFlag,
|
utils.MinerGasPriceFlag,
|
||||||
utils.MinerEtherbaseFlag,
|
utils.MinerEtherbaseFlag,
|
||||||
|
55
cmd/geth/testdata/vcheck/vulnerabilities.json
vendored
55
cmd/geth/testdata/vcheck/vulnerabilities.json
vendored
@ -52,13 +52,16 @@
|
|||||||
"check": "Geth\\/v1\\.9\\.(7|8|9|10|11|12|13|14|15|16).*$"
|
"check": "Geth\\/v1\\.9\\.(7|8|9|10|11|12|13|14|15|16).*$"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "GethCrash",
|
"name": "Geth DoS via MULMOD",
|
||||||
"uid": "GETH-2020-04",
|
"uid": "GETH-2020-04",
|
||||||
"summary": "A denial-of-service issue can be used to crash Geth nodes during block processing",
|
"summary": "A denial-of-service issue can be used to crash Geth nodes during block processing",
|
||||||
"description": "Full details to be disclosed at a later date",
|
"description": "Affected versions suffer from a vulnerability which can be exploited through the `MULMOD` operation, by specifying a modulo of `0`: `mulmod(a,b,0)`, causing a `panic` in the underlying library. \nThe crash was in the `uint256` library, where a buffer [underflowed](https://github.com/holiman/uint256/blob/4ce82e695c10ddad57215bdbeafb68b8c5df2c30/uint256.go#L442).\n\n\tif `d == 0`, `dLen` remains `0`\n\nand https://github.com/holiman/uint256/blob/4ce82e695c10ddad57215bdbeafb68b8c5df2c30/uint256.go#L451 will try to access index `[-1]`.\n\nThe `uint256` library was first merged in this [commit](https://github.com/ethereum/go-ethereum/commit/cf6674539c589f80031f3371a71c6a80addbe454), on 2020-06-08. \nExploiting this vulnerabilty would cause all vulnerable nodes to drop off the network. \n\nThe issue was brought to our attention through a [bug report](https://github.com/ethereum/go-ethereum/issues/21367), showing a `panic` occurring on sync from genesis on the Ropsten network.\n \nIt was estimated that the least obvious way to fix this would be to merge the fix into `uint256`, make a new release of that library and then update the geth-dependency.\n",
|
||||||
"links": [
|
"links": [
|
||||||
"https://blog.ethereum.org/2020/11/12/geth_security_release/",
|
"https://blog.ethereum.org/2020/11/12/geth_security_release/",
|
||||||
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-jm5c-rv3w-w83m"
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-jm5c-rv3w-w83m",
|
||||||
|
"https://github.com/holiman/uint256/releases/tag/v1.1.1",
|
||||||
|
"https://github.com/holiman/uint256/pull/80",
|
||||||
|
"https://github.com/ethereum/go-ethereum/pull/21368"
|
||||||
],
|
],
|
||||||
"introduced": "v1.9.16",
|
"introduced": "v1.9.16",
|
||||||
"fixed": "v1.9.18",
|
"fixed": "v1.9.18",
|
||||||
@ -66,5 +69,51 @@
|
|||||||
"severity": "Critical",
|
"severity": "Critical",
|
||||||
"CVE": "CVE-2020-26242",
|
"CVE": "CVE-2020-26242",
|
||||||
"check": "Geth\\/v1\\.9.(16|17).*$"
|
"check": "Geth\\/v1\\.9.(16|17).*$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "LES Server DoS via GetProofsV2",
|
||||||
|
"uid": "GETH-2020-05",
|
||||||
|
"summary": "A DoS vulnerability can make a LES server crash.",
|
||||||
|
"description": "A DoS vulnerability can make a LES server crash via malicious GetProofsV2 request from a connected LES client.\n\nThe vulnerability was patched in #21896.\n\nThis vulnerability only concern users explicitly running geth as a light server",
|
||||||
|
"links": [
|
||||||
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-r33q-22hv-j29q",
|
||||||
|
"https://github.com/ethereum/go-ethereum/pull/21896"
|
||||||
|
],
|
||||||
|
"introduced": "v1.8.0",
|
||||||
|
"fixed": "v1.9.25",
|
||||||
|
"published": "2020-12-10",
|
||||||
|
"severity": "Medium",
|
||||||
|
"CVE": "CVE-2020-26264",
|
||||||
|
"check": "(Geth\\/v1\\.8\\.*)|(Geth\\/v1\\.9\\.\\d-.*)|(Geth\\/v1\\.9\\.1\\d-.*)|(Geth\\/v1\\.9\\.(20|21|22|23|24)-.*)$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "SELFDESTRUCT-recreate consensus flaw",
|
||||||
|
"uid": "GETH-2020-06",
|
||||||
|
"introduced": "v1.9.4",
|
||||||
|
"fixed": "v1.9.20",
|
||||||
|
"summary": "A consensus-vulnerability in Geth could cause a chain split, where vulnerable versions refuse to accept the canonical chain.",
|
||||||
|
"description": "A flaw was repoted at 2020-08-11 by John Youngseok Yang (Software Platform Lab), where a particular sequence of transactions could cause a consensus failure.\n\n- Tx 1:\n - `sender` invokes `caller`.\n - `caller` invokes `0xaa`. `0xaa` has 3 wei, does a self-destruct-to-self\n - `caller` does a `1 wei` -call to `0xaa`, who thereby has 1 wei (the code in `0xaa` still executed, since the tx is still ongoing, but doesn't redo the selfdestruct, it takes a different path if callvalue is non-zero)\n\n-Tx 2:\n - `sender` does a 5-wei call to 0xaa. No exec (since no code). \n\nIn geth, the result would be that `0xaa` had `6 wei`, whereas OE reported (correctly) `5` wei. Furthermore, in geth, if the second tx was not executed, the `0xaa` would be destructed, resulting in `0 wei`. Thus obviously wrong. \n\nIt was determined that the root cause was this [commit](https://github.com/ethereum/go-ethereum/commit/223b950944f494a5b4e0957fd9f92c48b09037ad) from [this PR](https://github.com/ethereum/go-ethereum/pull/19953). The semantics of `createObject` was subtly changd, into returning a non-nil object (with `deleted=true`) where it previously did not if the account had been destructed. This return value caused the new object to inherit the old `balance`.\n",
|
||||||
|
"links": [
|
||||||
|
"https://github.com/ethereum/go-ethereum/security/advisories/GHSA-xw37-57qp-9mm4"
|
||||||
|
],
|
||||||
|
"published": "2020-12-10",
|
||||||
|
"severity": "High",
|
||||||
|
"CVE": "CVE-2020-26265",
|
||||||
|
"check": "(Geth\\/v1\\.9\\.(4|5|6|7|8|9)-.*)|(Geth\\/v1\\.9\\.1\\d-.*)$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Not ready for London upgrade",
|
||||||
|
"uid": "GETH-2021-01",
|
||||||
|
"summary": "The client is not ready for the 'London' technical upgrade, and will deviate from the canonical chain when the London upgrade occurs (at block '12965000' around August 4, 2021.",
|
||||||
|
"description": "At (or around) August 4, Ethereum will undergo a technical upgrade called 'London'. Clients not upgraded will fail to progress on the canonical chain.",
|
||||||
|
"links": [
|
||||||
|
"https://github.com/ethereum/eth1.0-specs/blob/master/network-upgrades/mainnet-upgrades/london.md",
|
||||||
|
"https://notes.ethereum.org/@timbeiko/ropsten-postmortem"
|
||||||
|
],
|
||||||
|
"introduced": "v1.10.1",
|
||||||
|
"fixed": "v1.10.6",
|
||||||
|
"published": "2020-12-10",
|
||||||
|
"severity": "High",
|
||||||
|
"check": "(Geth\\/v1\\.10\\.(1|2|3|4|5)-.*)$"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -182,7 +182,6 @@ var AppHelpFlagGroups = []flags.FlagGroup{
|
|||||||
utils.MinerNotifyFlag,
|
utils.MinerNotifyFlag,
|
||||||
utils.MinerNotifyFullFlag,
|
utils.MinerNotifyFullFlag,
|
||||||
utils.MinerGasPriceFlag,
|
utils.MinerGasPriceFlag,
|
||||||
utils.MinerGasTargetFlag,
|
|
||||||
utils.MinerGasLimitFlag,
|
utils.MinerGasLimitFlag,
|
||||||
utils.MinerEtherbaseFlag,
|
utils.MinerEtherbaseFlag,
|
||||||
utils.MinerExtraDataFlag,
|
utils.MinerExtraDataFlag,
|
||||||
@ -226,6 +225,7 @@ var AppHelpFlagGroups = []flags.FlagGroup{
|
|||||||
utils.LegacyRPCCORSDomainFlag,
|
utils.LegacyRPCCORSDomainFlag,
|
||||||
utils.LegacyRPCVirtualHostsFlag,
|
utils.LegacyRPCVirtualHostsFlag,
|
||||||
utils.LegacyRPCApiFlag,
|
utils.LegacyRPCApiFlag,
|
||||||
|
utils.LegacyMinerGasTargetFlag,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -158,7 +158,7 @@ func checkEthstats(client *sshClient, network string) (*ethstatsInfos, error) {
|
|||||||
if port != 80 && port != 443 {
|
if port != 80 && port != 443 {
|
||||||
config += fmt.Sprintf(":%d", port)
|
config += fmt.Sprintf(":%d", port)
|
||||||
}
|
}
|
||||||
// Retrieve the IP blacklist
|
// Retrieve the IP banned list
|
||||||
banned := strings.Split(infos.envvars["BANNED"], ",")
|
banned := strings.Split(infos.envvars["BANNED"], ",")
|
||||||
|
|
||||||
// Run a sanity check to see if the port is reachable
|
// Run a sanity check to see if the port is reachable
|
||||||
|
@ -63,20 +63,20 @@ func (w *wizard) deployEthstats() {
|
|||||||
fmt.Printf("What should be the secret password for the API? (default = %s)\n", infos.secret)
|
fmt.Printf("What should be the secret password for the API? (default = %s)\n", infos.secret)
|
||||||
infos.secret = w.readDefaultString(infos.secret)
|
infos.secret = w.readDefaultString(infos.secret)
|
||||||
}
|
}
|
||||||
// Gather any blacklists to ban from reporting
|
// Gather any banned lists to ban from reporting
|
||||||
if existed {
|
if existed {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Printf("Keep existing IP %v blacklist (y/n)? (default = yes)\n", infos.banned)
|
fmt.Printf("Keep existing IP %v in the banned list (y/n)? (default = yes)\n", infos.banned)
|
||||||
if !w.readDefaultYesNo(true) {
|
if !w.readDefaultYesNo(true) {
|
||||||
// The user might want to clear the entire list, although generally probably not
|
// The user might want to clear the entire list, although generally probably not
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Printf("Clear out blacklist and start over (y/n)? (default = no)\n")
|
fmt.Printf("Clear out the banned list and start over (y/n)? (default = no)\n")
|
||||||
if w.readDefaultYesNo(false) {
|
if w.readDefaultYesNo(false) {
|
||||||
infos.banned = nil
|
infos.banned = nil
|
||||||
}
|
}
|
||||||
// Offer the user to explicitly add/remove certain IP addresses
|
// Offer the user to explicitly add/remove certain IP addresses
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println("Which additional IP addresses should be blacklisted?")
|
fmt.Println("Which additional IP addresses should be in the banned list?")
|
||||||
for {
|
for {
|
||||||
if ip := w.readIPAddress(); ip != "" {
|
if ip := w.readIPAddress(); ip != "" {
|
||||||
infos.banned = append(infos.banned, ip)
|
infos.banned = append(infos.banned, ip)
|
||||||
@ -85,7 +85,7 @@ func (w *wizard) deployEthstats() {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println("Which IP addresses should not be blacklisted?")
|
fmt.Println("Which IP addresses should not be in the banned list?")
|
||||||
for {
|
for {
|
||||||
if ip := w.readIPAddress(); ip != "" {
|
if ip := w.readIPAddress(); ip != "" {
|
||||||
for i, addr := range infos.banned {
|
for i, addr := range infos.banned {
|
||||||
|
@ -444,11 +444,6 @@ var (
|
|||||||
Name: "miner.notify.full",
|
Name: "miner.notify.full",
|
||||||
Usage: "Notify with pending block headers instead of work packages",
|
Usage: "Notify with pending block headers instead of work packages",
|
||||||
}
|
}
|
||||||
MinerGasTargetFlag = cli.Uint64Flag{
|
|
||||||
Name: "miner.gastarget",
|
|
||||||
Usage: "Target gas floor for mined blocks",
|
|
||||||
Value: ethconfig.Defaults.Miner.GasFloor,
|
|
||||||
}
|
|
||||||
MinerGasLimitFlag = cli.Uint64Flag{
|
MinerGasLimitFlag = cli.Uint64Flag{
|
||||||
Name: "miner.gaslimit",
|
Name: "miner.gaslimit",
|
||||||
Usage: "Target gas ceiling for mined blocks",
|
Usage: "Target gas ceiling for mined blocks",
|
||||||
@ -1386,9 +1381,6 @@ func setMiner(ctx *cli.Context, cfg *miner.Config) {
|
|||||||
if ctx.GlobalIsSet(MinerExtraDataFlag.Name) {
|
if ctx.GlobalIsSet(MinerExtraDataFlag.Name) {
|
||||||
cfg.ExtraData = []byte(ctx.GlobalString(MinerExtraDataFlag.Name))
|
cfg.ExtraData = []byte(ctx.GlobalString(MinerExtraDataFlag.Name))
|
||||||
}
|
}
|
||||||
if ctx.GlobalIsSet(MinerGasTargetFlag.Name) {
|
|
||||||
cfg.GasFloor = ctx.GlobalUint64(MinerGasTargetFlag.Name)
|
|
||||||
}
|
|
||||||
if ctx.GlobalIsSet(MinerGasLimitFlag.Name) {
|
if ctx.GlobalIsSet(MinerGasLimitFlag.Name) {
|
||||||
cfg.GasCeil = ctx.GlobalUint64(MinerGasLimitFlag.Name)
|
cfg.GasCeil = ctx.GlobalUint64(MinerGasLimitFlag.Name)
|
||||||
}
|
}
|
||||||
@ -1401,6 +1393,9 @@ func setMiner(ctx *cli.Context, cfg *miner.Config) {
|
|||||||
if ctx.GlobalIsSet(MinerNoVerfiyFlag.Name) {
|
if ctx.GlobalIsSet(MinerNoVerfiyFlag.Name) {
|
||||||
cfg.Noverify = ctx.GlobalBool(MinerNoVerfiyFlag.Name)
|
cfg.Noverify = ctx.GlobalBool(MinerNoVerfiyFlag.Name)
|
||||||
}
|
}
|
||||||
|
if ctx.GlobalIsSet(LegacyMinerGasTargetFlag.Name) {
|
||||||
|
log.Warn("The generic --miner.gastarget flag is deprecated and will be removed in the future!")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setWhitelist(ctx *cli.Context, cfg *ethconfig.Config) {
|
func setWhitelist(ctx *cli.Context, cfg *ethconfig.Config) {
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"gopkg.in/urfave/cli.v1"
|
||||||
)
|
)
|
||||||
@ -33,7 +34,9 @@ var ShowDeprecated = cli.Command{
|
|||||||
Description: "Show flags that have been deprecated and will soon be removed",
|
Description: "Show flags that have been deprecated and will soon be removed",
|
||||||
}
|
}
|
||||||
|
|
||||||
var DeprecatedFlags = []cli.Flag{}
|
var DeprecatedFlags = []cli.Flag{
|
||||||
|
LegacyMinerGasTargetFlag,
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// (Deprecated May 2020, shown in aliased flags section)
|
// (Deprecated May 2020, shown in aliased flags section)
|
||||||
@ -66,6 +69,12 @@ var (
|
|||||||
Usage: "API's offered over the HTTP-RPC interface (deprecated and will be removed June 2021, use --http.api)",
|
Usage: "API's offered over the HTTP-RPC interface (deprecated and will be removed June 2021, use --http.api)",
|
||||||
Value: "",
|
Value: "",
|
||||||
}
|
}
|
||||||
|
// (Deprecated July 2021, shown in aliased flags section)
|
||||||
|
LegacyMinerGasTargetFlag = cli.Uint64Flag{
|
||||||
|
Name: "miner.gastarget",
|
||||||
|
Usage: "Target gas floor for mined blocks (deprecated)",
|
||||||
|
Value: ethconfig.Defaults.Miner.GasFloor,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// showDeprecated displays deprecated flags that will be soon removed from the codebase.
|
// showDeprecated displays deprecated flags that will be soon removed from the codebase.
|
||||||
@ -74,7 +83,8 @@ func showDeprecated(*cli.Context) {
|
|||||||
fmt.Println("The following flags are deprecated and will be removed in the future!")
|
fmt.Println("The following flags are deprecated and will be removed in the future!")
|
||||||
fmt.Println("--------------------------------------------------------------------")
|
fmt.Println("--------------------------------------------------------------------")
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
// TODO remove when there are newly deprecated flags
|
for _, flag := range DeprecatedFlags {
|
||||||
fmt.Println("no deprecated flags to show at this time")
|
fmt.Println(flag.String())
|
||||||
|
}
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
|
@ -215,7 +215,7 @@ func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Blo
|
|||||||
ancestors[parent] = ancestorHeader
|
ancestors[parent] = ancestorHeader
|
||||||
// If the ancestor doesn't have any uncles, we don't have to iterate them
|
// If the ancestor doesn't have any uncles, we don't have to iterate them
|
||||||
if ancestorHeader.UncleHash != types.EmptyUncleHash {
|
if ancestorHeader.UncleHash != types.EmptyUncleHash {
|
||||||
// Need to add those uncles to the blacklist too
|
// Need to add those uncles to the banned list too
|
||||||
ancestor := chain.GetBlock(parent, number)
|
ancestor := chain.GetBlock(parent, number)
|
||||||
if ancestor == nil {
|
if ancestor == nil {
|
||||||
break
|
break
|
||||||
|
@ -142,6 +142,7 @@ func (ethash *Ethash) mine(block *types.Block, id int, seed uint64, abort chan s
|
|||||||
var (
|
var (
|
||||||
attempts = int64(0)
|
attempts = int64(0)
|
||||||
nonce = seed
|
nonce = seed
|
||||||
|
powBuffer = new(big.Int)
|
||||||
)
|
)
|
||||||
logger := ethash.config.Log.New("miner", id)
|
logger := ethash.config.Log.New("miner", id)
|
||||||
logger.Trace("Started ethash search for new nonces", "seed", seed)
|
logger.Trace("Started ethash search for new nonces", "seed", seed)
|
||||||
@ -163,7 +164,7 @@ search:
|
|||||||
}
|
}
|
||||||
// Compute the PoW value of this nonce
|
// Compute the PoW value of this nonce
|
||||||
digest, result := hashimotoFull(dataset.dataset, hash, nonce)
|
digest, result := hashimotoFull(dataset.dataset, hash, nonce)
|
||||||
if new(big.Int).SetBytes(result).Cmp(target) <= 0 {
|
if powBuffer.SetBytes(result).Cmp(target) <= 0 {
|
||||||
// Correct nonce found, create a new header with it
|
// Correct nonce found, create a new header with it
|
||||||
header = types.CopyHeader(header)
|
header = types.CopyHeader(header)
|
||||||
header.Nonce = types.EncodeNonce(nonce)
|
header.Nonce = types.EncodeNonce(nonce)
|
||||||
|
@ -103,44 +103,9 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CalcGasLimit computes the gas limit of the next block after parent. It aims
|
// CalcGasLimit computes the gas limit of the next block after parent. It aims
|
||||||
// to keep the baseline gas above the provided floor, and increase it towards the
|
// to keep the baseline gas close to the provided target, and increase it towards
|
||||||
// ceil if the blocks are full. If the ceil is exceeded, it will always decrease
|
// the target if the baseline gas is lower.
|
||||||
// the gas allowance.
|
func CalcGasLimit(parentGasLimit, desiredLimit uint64) uint64 {
|
||||||
func CalcGasLimit(parentGasUsed, parentGasLimit, gasFloor, gasCeil uint64) uint64 {
|
|
||||||
// contrib = (parentGasUsed * 3 / 2) / 1024
|
|
||||||
contrib := (parentGasUsed + parentGasUsed/2) / params.GasLimitBoundDivisor
|
|
||||||
|
|
||||||
// decay = parentGasLimit / 1024 -1
|
|
||||||
decay := parentGasLimit/params.GasLimitBoundDivisor - 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
strategy: gasLimit of block-to-mine is set based on parent's
|
|
||||||
gasUsed value. if parentGasUsed > parentGasLimit * (2/3) then we
|
|
||||||
increase it, otherwise lower it (or leave it unchanged if it's right
|
|
||||||
at that usage) the amount increased/decreased depends on how far away
|
|
||||||
from parentGasLimit * (2/3) parentGasUsed is.
|
|
||||||
*/
|
|
||||||
limit := parentGasLimit - decay + contrib
|
|
||||||
if limit < params.MinGasLimit {
|
|
||||||
limit = params.MinGasLimit
|
|
||||||
}
|
|
||||||
// If we're outside our allowed gas range, we try to hone towards them
|
|
||||||
if limit < gasFloor {
|
|
||||||
limit = parentGasLimit + decay
|
|
||||||
if limit > gasFloor {
|
|
||||||
limit = gasFloor
|
|
||||||
}
|
|
||||||
} else if limit > gasCeil {
|
|
||||||
limit = parentGasLimit - decay
|
|
||||||
if limit < gasCeil {
|
|
||||||
limit = gasCeil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return limit
|
|
||||||
}
|
|
||||||
|
|
||||||
// CalcGasLimit1559 calculates the next block gas limit under 1559 rules.
|
|
||||||
func CalcGasLimit1559(parentGasLimit, desiredLimit uint64) uint64 {
|
|
||||||
delta := parentGasLimit/params.GasLimitBoundDivisor - 1
|
delta := parentGasLimit/params.GasLimitBoundDivisor - 1
|
||||||
limit := parentGasLimit
|
limit := parentGasLimit
|
||||||
if desiredLimit < params.MinGasLimit {
|
if desiredLimit < params.MinGasLimit {
|
||||||
|
@ -198,8 +198,7 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCalcGasLimit1559(t *testing.T) {
|
func TestCalcGasLimit(t *testing.T) {
|
||||||
|
|
||||||
for i, tc := range []struct {
|
for i, tc := range []struct {
|
||||||
pGasLimit uint64
|
pGasLimit uint64
|
||||||
max uint64
|
max uint64
|
||||||
@ -209,23 +208,23 @@ func TestCalcGasLimit1559(t *testing.T) {
|
|||||||
{40000000, 40039061, 39960939},
|
{40000000, 40039061, 39960939},
|
||||||
} {
|
} {
|
||||||
// Increase
|
// Increase
|
||||||
if have, want := CalcGasLimit1559(tc.pGasLimit, 2*tc.pGasLimit), tc.max; have != want {
|
if have, want := CalcGasLimit(tc.pGasLimit, 2*tc.pGasLimit), tc.max; have != want {
|
||||||
t.Errorf("test %d: have %d want <%d", i, have, want)
|
t.Errorf("test %d: have %d want <%d", i, have, want)
|
||||||
}
|
}
|
||||||
// Decrease
|
// Decrease
|
||||||
if have, want := CalcGasLimit1559(tc.pGasLimit, 0), tc.min; have != want {
|
if have, want := CalcGasLimit(tc.pGasLimit, 0), tc.min; have != want {
|
||||||
t.Errorf("test %d: have %d want >%d", i, have, want)
|
t.Errorf("test %d: have %d want >%d", i, have, want)
|
||||||
}
|
}
|
||||||
// Small decrease
|
// Small decrease
|
||||||
if have, want := CalcGasLimit1559(tc.pGasLimit, tc.pGasLimit-1), tc.pGasLimit-1; have != want {
|
if have, want := CalcGasLimit(tc.pGasLimit, tc.pGasLimit-1), tc.pGasLimit-1; have != want {
|
||||||
t.Errorf("test %d: have %d want %d", i, have, want)
|
t.Errorf("test %d: have %d want %d", i, have, want)
|
||||||
}
|
}
|
||||||
// Small increase
|
// Small increase
|
||||||
if have, want := CalcGasLimit1559(tc.pGasLimit, tc.pGasLimit+1), tc.pGasLimit+1; have != want {
|
if have, want := CalcGasLimit(tc.pGasLimit, tc.pGasLimit+1), tc.pGasLimit+1; have != want {
|
||||||
t.Errorf("test %d: have %d want %d", i, have, want)
|
t.Errorf("test %d: have %d want %d", i, have, want)
|
||||||
}
|
}
|
||||||
// No change
|
// No change
|
||||||
if have, want := CalcGasLimit1559(tc.pGasLimit, tc.pGasLimit), tc.pGasLimit; have != want {
|
if have, want := CalcGasLimit(tc.pGasLimit, tc.pGasLimit), tc.pGasLimit; have != want {
|
||||||
t.Errorf("test %d: have %d want %d", i, have, want)
|
t.Errorf("test %d: have %d want %d", i, have, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1787,8 +1787,8 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, er
|
|||||||
}
|
}
|
||||||
// If the header is a banned one, straight out abort
|
// If the header is a banned one, straight out abort
|
||||||
if BadHashes[block.Hash()] {
|
if BadHashes[block.Hash()] {
|
||||||
bc.reportBlock(block, nil, ErrBlacklistedHash)
|
bc.reportBlock(block, nil, ErrBannedHash)
|
||||||
return it.index, ErrBlacklistedHash
|
return it.index, ErrBannedHash
|
||||||
}
|
}
|
||||||
// If the block is known (in the middle of the chain), it's a special case for
|
// If the block is known (in the middle of the chain), it's a special case for
|
||||||
// Clique blocks where they can share state among each other, so importing an
|
// Clique blocks where they can share state among each other, so importing an
|
||||||
@ -2420,12 +2420,22 @@ func (bc *BlockChain) GetTdByHash(hash common.Hash) *big.Int {
|
|||||||
// GetHeader retrieves a block header from the database by hash and number,
|
// GetHeader retrieves a block header from the database by hash and number,
|
||||||
// caching it if found.
|
// caching it if found.
|
||||||
func (bc *BlockChain) GetHeader(hash common.Hash, number uint64) *types.Header {
|
func (bc *BlockChain) GetHeader(hash common.Hash, number uint64) *types.Header {
|
||||||
|
// Blockchain might have cached the whole block, only if not go to headerchain
|
||||||
|
if block, ok := bc.blockCache.Get(hash); ok {
|
||||||
|
return block.(*types.Block).Header()
|
||||||
|
}
|
||||||
|
|
||||||
return bc.hc.GetHeader(hash, number)
|
return bc.hc.GetHeader(hash, number)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHeaderByHash retrieves a block header from the database by hash, caching it if
|
// GetHeaderByHash retrieves a block header from the database by hash, caching it if
|
||||||
// found.
|
// found.
|
||||||
func (bc *BlockChain) GetHeaderByHash(hash common.Hash) *types.Header {
|
func (bc *BlockChain) GetHeaderByHash(hash common.Hash) *types.Header {
|
||||||
|
// Blockchain might have cached the whole block, only if not go to headerchain
|
||||||
|
if block, ok := bc.blockCache.Get(hash); ok {
|
||||||
|
return block.(*types.Block).Header()
|
||||||
|
}
|
||||||
|
|
||||||
return bc.hc.GetHeaderByHash(hash)
|
return bc.hc.GetHeaderByHash(hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,8 +473,8 @@ func testBadHashes(t *testing.T, full bool) {
|
|||||||
|
|
||||||
_, err = blockchain.InsertHeaderChain(headers, 1)
|
_, err = blockchain.InsertHeaderChain(headers, 1)
|
||||||
}
|
}
|
||||||
if !errors.Is(err, ErrBlacklistedHash) {
|
if !errors.Is(err, ErrBannedHash) {
|
||||||
t.Errorf("error mismatch: have: %v, want: %v", err, ErrBlacklistedHash)
|
t.Errorf("error mismatch: have: %v, want: %v", err, ErrBannedHash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,11 +273,10 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
|
|||||||
}
|
}
|
||||||
if chain.Config().IsLondon(header.Number) {
|
if chain.Config().IsLondon(header.Number) {
|
||||||
header.BaseFee = misc.CalcBaseFee(chain.Config(), parent.Header())
|
header.BaseFee = misc.CalcBaseFee(chain.Config(), parent.Header())
|
||||||
parentGasLimit := parent.GasLimit()
|
|
||||||
if !chain.Config().IsLondon(parent.Number()) {
|
if !chain.Config().IsLondon(parent.Number()) {
|
||||||
parentGasLimit = parent.GasLimit() * params.ElasticityMultiplier
|
parentGasLimit := parent.GasLimit() * params.ElasticityMultiplier
|
||||||
|
header.GasLimit = CalcGasLimit(parentGasLimit, parentGasLimit)
|
||||||
}
|
}
|
||||||
header.GasLimit = CalcGasLimit1559(parentGasLimit, parentGasLimit)
|
|
||||||
}
|
}
|
||||||
return header
|
return header
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,8 @@ var (
|
|||||||
// ErrKnownBlock is returned when a block to import is already known locally.
|
// ErrKnownBlock is returned when a block to import is already known locally.
|
||||||
ErrKnownBlock = errors.New("block already known")
|
ErrKnownBlock = errors.New("block already known")
|
||||||
|
|
||||||
// ErrBlacklistedHash is returned if a block to import is on the blacklist.
|
// ErrBannedHash is returned if a block to import is on the banned list.
|
||||||
ErrBlacklistedHash = errors.New("blacklisted hash")
|
ErrBannedHash = errors.New("banned hash")
|
||||||
|
|
||||||
// ErrNoGenesis is returned when there is no Genesis Block.
|
// ErrNoGenesis is returned when there is no Genesis Block.
|
||||||
ErrNoGenesis = errors.New("genesis not found in chain")
|
ErrNoGenesis = errors.New("genesis not found in chain")
|
||||||
@ -87,4 +87,7 @@ var (
|
|||||||
// ErrFeeCapTooLow is returned if the transaction fee cap is less than the
|
// ErrFeeCapTooLow is returned if the transaction fee cap is less than the
|
||||||
// the base fee of the block.
|
// the base fee of the block.
|
||||||
ErrFeeCapTooLow = errors.New("max fee per gas less than block base fee")
|
ErrFeeCapTooLow = errors.New("max fee per gas less than block base fee")
|
||||||
|
|
||||||
|
// ErrSenderNoEOA is returned if the sender of a transaction is a contract.
|
||||||
|
ErrSenderNoEOA = errors.New("sender not an eoa")
|
||||||
)
|
)
|
||||||
|
@ -315,11 +315,11 @@ func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int)
|
|||||||
}
|
}
|
||||||
// If the header is a banned one, straight out abort
|
// If the header is a banned one, straight out abort
|
||||||
if BadHashes[chain[i].ParentHash] {
|
if BadHashes[chain[i].ParentHash] {
|
||||||
return i - 1, ErrBlacklistedHash
|
return i - 1, ErrBannedHash
|
||||||
}
|
}
|
||||||
// If it's the last header in the cunk, we need to check it too
|
// If it's the last header in the cunk, we need to check it too
|
||||||
if i == len(chain)-1 && BadHashes[chain[i].Hash()] {
|
if i == len(chain)-1 && BadHashes[chain[i].Hash()] {
|
||||||
return i, ErrBlacklistedHash
|
return i, ErrBannedHash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,6 +444,7 @@ func TestAncientStorage(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create database with ancient backend")
|
t.Fatalf("failed to create database with ancient backend")
|
||||||
}
|
}
|
||||||
|
defer db.Close()
|
||||||
// Create a test block
|
// Create a test block
|
||||||
block := types.NewBlockWithHeader(&types.Header{
|
block := types.NewBlockWithHeader(&types.Header{
|
||||||
Number: big.NewInt(0),
|
Number: big.NewInt(0),
|
||||||
|
@ -106,7 +106,7 @@ func ReadTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, com
|
|||||||
}
|
}
|
||||||
body := ReadBody(db, blockHash, *blockNumber)
|
body := ReadBody(db, blockHash, *blockNumber)
|
||||||
if body == nil {
|
if body == nil {
|
||||||
log.Error("Transaction referenced missing", "number", blockNumber, "hash", blockHash)
|
log.Error("Transaction referenced missing", "number", *blockNumber, "hash", blockHash)
|
||||||
return nil, common.Hash{}, 0, 0
|
return nil, common.Hash{}, 0, 0
|
||||||
}
|
}
|
||||||
for txIndex, tx := range body.Transactions {
|
for txIndex, tx := range body.Transactions {
|
||||||
@ -114,7 +114,7 @@ func ReadTransaction(db ethdb.Reader, hash common.Hash) (*types.Transaction, com
|
|||||||
return tx, blockHash, *blockNumber, uint64(txIndex)
|
return tx, blockHash, *blockNumber, uint64(txIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Error("Transaction not found", "number", blockNumber, "hash", blockHash, "txhash", hash)
|
log.Error("Transaction not found", "number", *blockNumber, "hash", blockHash, "txhash", hash)
|
||||||
return nil, common.Hash{}, 0, 0
|
return nil, common.Hash{}, 0, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ func ReadReceipt(db ethdb.Reader, hash common.Hash, config *params.ChainConfig)
|
|||||||
return receipt, blockHash, *blockNumber, uint64(receiptIndex)
|
return receipt, blockHash, *blockNumber, uint64(receiptIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Error("Receipt not found", "number", blockNumber, "hash", blockHash, "txhash", hash)
|
log.Error("Receipt not found", "number", *blockNumber, "hash", blockHash, "txhash", hash)
|
||||||
return nil, common.Hash{}, 0, 0
|
return nil, common.Hash{}, 0, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ func (bloom *stateBloom) Commit(filename, tempname string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Ensure the file is synced to disk
|
// Ensure the file is synced to disk
|
||||||
f, err := os.Open(tempname)
|
f, err := os.OpenFile(tempname, os.O_RDWR, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -169,11 +169,17 @@ type Tree struct {
|
|||||||
// store (with a number of memory layers from a journal), ensuring that the head
|
// store (with a number of memory layers from a journal), ensuring that the head
|
||||||
// of the snapshot matches the expected one.
|
// of the snapshot matches the expected one.
|
||||||
//
|
//
|
||||||
// If the snapshot is missing or the disk layer is broken, the entire is deleted
|
// If the snapshot is missing or the disk layer is broken, the snapshot will be
|
||||||
// and will be reconstructed from scratch based on the tries in the key-value
|
// reconstructed using both the existing data and the state trie.
|
||||||
// store, on a background thread. If the memory layers from the journal is not
|
// The repair happens on a background thread.
|
||||||
// continuous with disk layer or the journal is missing, all diffs will be discarded
|
//
|
||||||
// iff it's in "recovery" mode, otherwise rebuild is mandatory.
|
// If the memory layers in the journal do not match the disk layer (e.g. there is
|
||||||
|
// a gap) or the journal is missing, there are two repair cases:
|
||||||
|
//
|
||||||
|
// - if the 'recovery' parameter is true, all memory diff-layers will be discarded.
|
||||||
|
// This case happens when the snapshot is 'ahead' of the state trie.
|
||||||
|
// - otherwise, the entire snapshot is considered invalid and will be recreated on
|
||||||
|
// a background thread.
|
||||||
func New(diskdb ethdb.KeyValueStore, triedb *trie.Database, cache int, root common.Hash, async bool, rebuild bool, recovery bool) (*Tree, error) {
|
func New(diskdb ethdb.KeyValueStore, triedb *trie.Database, cache int, root common.Hash, async bool, rebuild bool, recovery bool) (*Tree, error) {
|
||||||
// Create a new, empty snapshot tree
|
// Create a new, empty snapshot tree
|
||||||
snap := &Tree{
|
snap := &Tree{
|
||||||
@ -469,7 +475,7 @@ func (t *Tree) cap(diff *diffLayer, layers int) *diskLayer {
|
|||||||
if flattened.memory < aggregatorMemoryLimit {
|
if flattened.memory < aggregatorMemoryLimit {
|
||||||
// Accumulator layer is smaller than the limit, so we can abort, unless
|
// Accumulator layer is smaller than the limit, so we can abort, unless
|
||||||
// there's a snapshot being generated currently. In that case, the trie
|
// there's a snapshot being generated currently. In that case, the trie
|
||||||
// will move fron underneath the generator so we **must** merge all the
|
// will move from underneath the generator so we **must** merge all the
|
||||||
// partial data down into the snapshot and restart the generation.
|
// partial data down into the snapshot and restart the generation.
|
||||||
if flattened.parent.(*diskLayer).genAbort == nil {
|
if flattened.parent.(*diskLayer).genAbort == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -878,7 +878,7 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
|||||||
return s.trie.Hash()
|
return s.trie.Hash()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare sets the current transaction hash and index and block hash which is
|
// Prepare sets the current transaction hash and index which are
|
||||||
// used when the EVM emits new state logs.
|
// used when the EVM emits new state logs.
|
||||||
func (s *StateDB) Prepare(thash common.Hash, ti int) {
|
func (s *StateDB) Prepare(thash common.Hash, ti int) {
|
||||||
s.thash = thash
|
s.thash = thash
|
||||||
|
110
core/state/trie_prefetcher_test.go
Normal file
110
core/state/trie_prefetcher_test.go
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
// Copyright 2021 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library 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 Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package state
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
|
)
|
||||||
|
|
||||||
|
func filledStateDB() *StateDB {
|
||||||
|
state, _ := New(common.Hash{}, NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||||
|
|
||||||
|
// Create an account and check if the retrieved balance is correct
|
||||||
|
addr := common.HexToAddress("0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe")
|
||||||
|
skey := common.HexToHash("aaa")
|
||||||
|
sval := common.HexToHash("bbb")
|
||||||
|
|
||||||
|
state.SetBalance(addr, big.NewInt(42)) // Change the account trie
|
||||||
|
state.SetCode(addr, []byte("hello")) // Change an external metadata
|
||||||
|
state.SetState(addr, skey, sval) // Change the storage trie
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
sk := common.BigToHash(big.NewInt(int64(i)))
|
||||||
|
state.SetState(addr, sk, sk) // Change the storage trie
|
||||||
|
}
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCopyAndClose(t *testing.T) {
|
||||||
|
db := filledStateDB()
|
||||||
|
prefetcher := newTriePrefetcher(db.db, db.originalRoot, "")
|
||||||
|
skey := common.HexToHash("aaa")
|
||||||
|
prefetcher.prefetch(db.originalRoot, [][]byte{skey.Bytes()})
|
||||||
|
prefetcher.prefetch(db.originalRoot, [][]byte{skey.Bytes()})
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
a := prefetcher.trie(db.originalRoot)
|
||||||
|
prefetcher.prefetch(db.originalRoot, [][]byte{skey.Bytes()})
|
||||||
|
b := prefetcher.trie(db.originalRoot)
|
||||||
|
cpy := prefetcher.copy()
|
||||||
|
cpy.prefetch(db.originalRoot, [][]byte{skey.Bytes()})
|
||||||
|
cpy.prefetch(db.originalRoot, [][]byte{skey.Bytes()})
|
||||||
|
c := cpy.trie(db.originalRoot)
|
||||||
|
prefetcher.close()
|
||||||
|
cpy2 := cpy.copy()
|
||||||
|
cpy2.prefetch(db.originalRoot, [][]byte{skey.Bytes()})
|
||||||
|
d := cpy2.trie(db.originalRoot)
|
||||||
|
cpy.close()
|
||||||
|
cpy2.close()
|
||||||
|
if a.Hash() != b.Hash() || a.Hash() != c.Hash() || a.Hash() != d.Hash() {
|
||||||
|
t.Fatalf("Invalid trie, hashes should be equal: %v %v %v %v", a.Hash(), b.Hash(), c.Hash(), d.Hash())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUseAfterClose(t *testing.T) {
|
||||||
|
db := filledStateDB()
|
||||||
|
prefetcher := newTriePrefetcher(db.db, db.originalRoot, "")
|
||||||
|
skey := common.HexToHash("aaa")
|
||||||
|
prefetcher.prefetch(db.originalRoot, [][]byte{skey.Bytes()})
|
||||||
|
a := prefetcher.trie(db.originalRoot)
|
||||||
|
prefetcher.close()
|
||||||
|
b := prefetcher.trie(db.originalRoot)
|
||||||
|
if a == nil {
|
||||||
|
t.Fatal("Prefetching before close should not return nil")
|
||||||
|
}
|
||||||
|
if b != nil {
|
||||||
|
t.Fatal("Trie after close should return nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCopyClose(t *testing.T) {
|
||||||
|
db := filledStateDB()
|
||||||
|
prefetcher := newTriePrefetcher(db.db, db.originalRoot, "")
|
||||||
|
skey := common.HexToHash("aaa")
|
||||||
|
prefetcher.prefetch(db.originalRoot, [][]byte{skey.Bytes()})
|
||||||
|
cpy := prefetcher.copy()
|
||||||
|
a := prefetcher.trie(db.originalRoot)
|
||||||
|
b := cpy.trie(db.originalRoot)
|
||||||
|
prefetcher.close()
|
||||||
|
c := prefetcher.trie(db.originalRoot)
|
||||||
|
d := cpy.trie(db.originalRoot)
|
||||||
|
if a == nil {
|
||||||
|
t.Fatal("Prefetching before close should not return nil")
|
||||||
|
}
|
||||||
|
if b == nil {
|
||||||
|
t.Fatal("Copy trie should return nil")
|
||||||
|
}
|
||||||
|
if c != nil {
|
||||||
|
t.Fatal("Trie after close should return nil")
|
||||||
|
}
|
||||||
|
if d == nil {
|
||||||
|
t.Fatal("Copy trie should not return nil")
|
||||||
|
}
|
||||||
|
}
|
@ -195,7 +195,7 @@ func TestStateProcessorErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// One final error is ErrTxTypeNotSupported. For this, we need an older chain
|
// ErrTxTypeNotSupported, For this, we need an older chain
|
||||||
{
|
{
|
||||||
var (
|
var (
|
||||||
db = rawdb.NewMemoryDatabase()
|
db = rawdb.NewMemoryDatabase()
|
||||||
@ -244,6 +244,46 @@ func TestStateProcessorErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrSenderNoEOA, for this we need the sender to have contract code
|
||||||
|
{
|
||||||
|
var (
|
||||||
|
db = rawdb.NewMemoryDatabase()
|
||||||
|
gspec = &Genesis{
|
||||||
|
Config: config,
|
||||||
|
Alloc: GenesisAlloc{
|
||||||
|
common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: 0,
|
||||||
|
Code: common.FromHex("0xB0B0FACE"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
genesis = gspec.MustCommit(db)
|
||||||
|
blockchain, _ = NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
|
||||||
|
)
|
||||||
|
defer blockchain.Stop()
|
||||||
|
for i, tt := range []struct {
|
||||||
|
txs []*types.Transaction
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{ // ErrSenderNoEOA
|
||||||
|
txs: []*types.Transaction{
|
||||||
|
mkDynamicTx(0, common.Address{}, params.TxGas-1000, big.NewInt(0), big.NewInt(0)),
|
||||||
|
},
|
||||||
|
want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: sender not an eoa: address 0x71562b71999873DB5b286dF957af199Ec94617F7, codehash: 0x9280914443471259d4570a8661015ae4a5b80186dbc619658fb494bebc3da3d1",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
block := GenerateBadBlock(genesis, ethash.NewFaker(), tt.txs, gspec.Config)
|
||||||
|
_, err := blockchain.InsertChain(types.Blocks{block})
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("block imported without errors")
|
||||||
|
}
|
||||||
|
if have, want := err.Error(), tt.want; have != want {
|
||||||
|
t.Errorf("test %d:\nhave \"%v\"\nwant \"%v\"\n", i, have, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateBadBlock constructs a "block" which contains the transactions. The transactions are not expected to be
|
// GenerateBadBlock constructs a "block" which contains the transactions. The transactions are not expected to be
|
||||||
|
@ -25,9 +25,12 @@ import (
|
|||||||
cmath "github.com/ethereum/go-ethereum/common/math"
|
cmath "github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var emptyCodeHash = crypto.Keccak256Hash(nil)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The State Transitioning Model
|
The State Transitioning Model
|
||||||
|
|
||||||
@ -220,6 +223,11 @@ func (st *StateTransition) preCheck() error {
|
|||||||
st.msg.From().Hex(), msgNonce, stNonce)
|
st.msg.From().Hex(), msgNonce, stNonce)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Make sure the sender is an EOA
|
||||||
|
if codeHash := st.state.GetCodeHash(st.msg.From()); codeHash != emptyCodeHash && codeHash != (common.Hash{}) {
|
||||||
|
return fmt.Errorf("%w: address %v, codehash: %s", ErrSenderNoEOA,
|
||||||
|
st.msg.From().Hex(), codeHash)
|
||||||
|
}
|
||||||
// Make sure that transaction gasFeeCap is greater than the baseFee (post london)
|
// Make sure that transaction gasFeeCap is greater than the baseFee (post london)
|
||||||
if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
|
if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
|
||||||
// Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call)
|
// Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call)
|
||||||
@ -279,6 +287,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
|||||||
sender := vm.AccountRef(msg.From())
|
sender := vm.AccountRef(msg.From())
|
||||||
homestead := st.evm.ChainConfig().IsHomestead(st.evm.Context.BlockNumber)
|
homestead := st.evm.ChainConfig().IsHomestead(st.evm.Context.BlockNumber)
|
||||||
istanbul := st.evm.ChainConfig().IsIstanbul(st.evm.Context.BlockNumber)
|
istanbul := st.evm.ChainConfig().IsIstanbul(st.evm.Context.BlockNumber)
|
||||||
|
london := st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber)
|
||||||
contractCreation := msg.To() == nil
|
contractCreation := msg.To() == nil
|
||||||
|
|
||||||
// Check clauses 4-5, subtract intrinsic gas if everything is correct
|
// Check clauses 4-5, subtract intrinsic gas if everything is correct
|
||||||
@ -311,7 +320,8 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
|||||||
st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
|
st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
|
||||||
ret, st.gas, vmerr = st.evm.Call(sender, st.to(), st.data, st.gas, st.value)
|
ret, st.gas, vmerr = st.evm.Call(sender, st.to(), st.data, st.gas, st.value)
|
||||||
}
|
}
|
||||||
if !st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
|
|
||||||
|
if !london {
|
||||||
// Before EIP-3529: refunds were capped to gasUsed / 2
|
// Before EIP-3529: refunds were capped to gasUsed / 2
|
||||||
st.refundGas(params.RefundQuotient)
|
st.refundGas(params.RefundQuotient)
|
||||||
} else {
|
} else {
|
||||||
@ -319,7 +329,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
|
|||||||
st.refundGas(params.RefundQuotientEIP3529)
|
st.refundGas(params.RefundQuotientEIP3529)
|
||||||
}
|
}
|
||||||
effectiveTip := st.gasPrice
|
effectiveTip := st.gasPrice
|
||||||
if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
|
if london {
|
||||||
effectiveTip = cmath.BigMin(st.gasTipCap, new(big.Int).Sub(st.gasFeeCap, st.evm.Context.BaseFee))
|
effectiveTip = cmath.BigMin(st.gasTipCap, new(big.Int).Sub(st.gasFeeCap, st.evm.Context.BaseFee))
|
||||||
}
|
}
|
||||||
st.state.AddBalance(st.evm.Context.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), effectiveTip))
|
st.state.AddBalance(st.evm.Context.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), effectiveTip))
|
||||||
|
@ -635,8 +635,8 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
|
|||||||
// pending or queued one, it overwrites the previous transaction if its price is higher.
|
// pending or queued one, it overwrites the previous transaction if its price is higher.
|
||||||
//
|
//
|
||||||
// If a newly added transaction is marked as local, its sending account will be
|
// If a newly added transaction is marked as local, its sending account will be
|
||||||
// whitelisted, preventing any associated transaction from being dropped out of the pool
|
// be added to the allowlist, preventing any associated transaction from being dropped
|
||||||
// due to pricing constraints.
|
// out of the pool due to pricing constraints.
|
||||||
func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err error) {
|
func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err error) {
|
||||||
// If the transaction is already known, discard it
|
// If the transaction is already known, discard it
|
||||||
hash := tx.Hash()
|
hash := tx.Hash()
|
||||||
|
@ -96,7 +96,7 @@ func (al accessList) equal(other accessList) bool {
|
|||||||
func (al accessList) accessList() types.AccessList {
|
func (al accessList) accessList() types.AccessList {
|
||||||
acl := make(types.AccessList, 0, len(al))
|
acl := make(types.AccessList, 0, len(al))
|
||||||
for addr, slots := range al {
|
for addr, slots := range al {
|
||||||
tuple := types.AccessTuple{Address: addr}
|
tuple := types.AccessTuple{Address: addr, StorageKeys: []common.Hash{}}
|
||||||
for slot := range slots {
|
for slot := range slots {
|
||||||
tuple.StorageKeys = append(tuple.StorageKeys, slot)
|
tuple.StorageKeys = append(tuple.StorageKeys, slot)
|
||||||
}
|
}
|
||||||
|
@ -287,7 +287,7 @@ func (b *EthAPIBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error)
|
|||||||
return b.gpo.SuggestTipCap(ctx)
|
return b.gpo.SuggestTipCap(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) FeeHistory(ctx context.Context, blockCount int, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (firstBlock rpc.BlockNumber, reward [][]*big.Int, baseFee []*big.Int, gasUsedRatio []float64, err error) {
|
func (b *EthAPIBackend) FeeHistory(ctx context.Context, blockCount int, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (firstBlock *big.Int, reward [][]*big.Int, baseFee []*big.Int, gasUsedRatio []float64, err error) {
|
||||||
return b.gpo.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles)
|
return b.gpo.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,6 @@ var Defaults = Config{
|
|||||||
TrieTimeout: 60 * time.Minute,
|
TrieTimeout: 60 * time.Minute,
|
||||||
SnapshotCache: 102,
|
SnapshotCache: 102,
|
||||||
Miner: miner.Config{
|
Miner: miner.Config{
|
||||||
GasFloor: 8000000,
|
|
||||||
GasCeil: 8000000,
|
GasCeil: 8000000,
|
||||||
GasPrice: big.NewInt(params.GWei),
|
GasPrice: big.NewInt(params.GWei),
|
||||||
Recommit: 3 * time.Second,
|
Recommit: 3 * time.Second,
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
@ -48,7 +49,7 @@ const (
|
|||||||
// blockFees represents a single block for processing
|
// blockFees represents a single block for processing
|
||||||
type blockFees struct {
|
type blockFees struct {
|
||||||
// set by the caller
|
// set by the caller
|
||||||
blockNumber rpc.BlockNumber
|
blockNumber uint64
|
||||||
header *types.Header
|
header *types.Header
|
||||||
block *types.Block // only set if reward percentiles are requested
|
block *types.Block // only set if reward percentiles are requested
|
||||||
receipts types.Receipts
|
receipts types.Receipts
|
||||||
@ -133,7 +134,7 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
|
|||||||
// also returned if requested and available.
|
// also returned if requested and available.
|
||||||
// Note: an error is only returned if retrieving the head header has failed. If there are no
|
// Note: an error is only returned if retrieving the head header has failed. If there are no
|
||||||
// retrievable blocks in the specified range then zero block count is returned with no error.
|
// retrievable blocks in the specified range then zero block count is returned with no error.
|
||||||
func (oracle *Oracle) resolveBlockRange(ctx context.Context, lastBlock rpc.BlockNumber, blocks, maxHistory int) (*types.Block, []*types.Receipt, rpc.BlockNumber, int, error) {
|
func (oracle *Oracle) resolveBlockRange(ctx context.Context, lastBlock rpc.BlockNumber, blocks, maxHistory int) (*types.Block, []*types.Receipt, uint64, int, error) {
|
||||||
var (
|
var (
|
||||||
headBlock rpc.BlockNumber
|
headBlock rpc.BlockNumber
|
||||||
pendingBlock *types.Block
|
pendingBlock *types.Block
|
||||||
@ -181,7 +182,7 @@ func (oracle *Oracle) resolveBlockRange(ctx context.Context, lastBlock rpc.Block
|
|||||||
if rpc.BlockNumber(blocks) > lastBlock+1 {
|
if rpc.BlockNumber(blocks) > lastBlock+1 {
|
||||||
blocks = int(lastBlock + 1)
|
blocks = int(lastBlock + 1)
|
||||||
}
|
}
|
||||||
return pendingBlock, pendingReceipts, lastBlock, blocks, nil
|
return pendingBlock, pendingReceipts, uint64(lastBlock), blocks, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FeeHistory returns data relevant for fee estimation based on the specified range of blocks.
|
// FeeHistory returns data relevant for fee estimation based on the specified range of blocks.
|
||||||
@ -197,9 +198,9 @@ func (oracle *Oracle) resolveBlockRange(ctx context.Context, lastBlock rpc.Block
|
|||||||
// - gasUsedRatio: gasUsed/gasLimit in the given block
|
// - gasUsedRatio: gasUsed/gasLimit in the given block
|
||||||
// Note: baseFee includes the next block after the newest of the returned range, because this
|
// Note: baseFee includes the next block after the newest of the returned range, because this
|
||||||
// value can be derived from the newest block.
|
// value can be derived from the newest block.
|
||||||
func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (rpc.BlockNumber, [][]*big.Int, []*big.Int, []float64, error) {
|
func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, unresolvedLastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error) {
|
||||||
if blocks < 1 {
|
if blocks < 1 {
|
||||||
return 0, nil, nil, nil, nil // returning with no data and no error means there are no retrievable blocks
|
return common.Big0, nil, nil, nil, nil // returning with no data and no error means there are no retrievable blocks
|
||||||
}
|
}
|
||||||
if blocks > maxFeeHistory {
|
if blocks > maxFeeHistory {
|
||||||
log.Warn("Sanitizing fee history length", "requested", blocks, "truncated", maxFeeHistory)
|
log.Warn("Sanitizing fee history length", "requested", blocks, "truncated", maxFeeHistory)
|
||||||
@ -207,10 +208,10 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, lastBlock rpc.
|
|||||||
}
|
}
|
||||||
for i, p := range rewardPercentiles {
|
for i, p := range rewardPercentiles {
|
||||||
if p < 0 || p > 100 {
|
if p < 0 || p > 100 {
|
||||||
return 0, nil, nil, nil, fmt.Errorf("%w: %f", errInvalidPercentile, p)
|
return common.Big0, nil, nil, nil, fmt.Errorf("%w: %f", errInvalidPercentile, p)
|
||||||
}
|
}
|
||||||
if i > 0 && p < rewardPercentiles[i-1] {
|
if i > 0 && p < rewardPercentiles[i-1] {
|
||||||
return 0, nil, nil, nil, fmt.Errorf("%w: #%d:%f > #%d:%f", errInvalidPercentile, i-1, rewardPercentiles[i-1], i, p)
|
return common.Big0, nil, nil, nil, fmt.Errorf("%w: #%d:%f > #%d:%f", errInvalidPercentile, i-1, rewardPercentiles[i-1], i, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Only process blocks if reward percentiles were requested
|
// Only process blocks if reward percentiles were requested
|
||||||
@ -223,36 +224,36 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, lastBlock rpc.
|
|||||||
pendingReceipts []*types.Receipt
|
pendingReceipts []*types.Receipt
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
pendingBlock, pendingReceipts, lastBlock, blocks, err = oracle.resolveBlockRange(ctx, lastBlock, blocks, maxHistory)
|
pendingBlock, pendingReceipts, lastBlock, blocks, err := oracle.resolveBlockRange(ctx, unresolvedLastBlock, blocks, maxHistory)
|
||||||
if err != nil || blocks == 0 {
|
if err != nil || blocks == 0 {
|
||||||
return 0, nil, nil, nil, err
|
return common.Big0, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
oldestBlock := lastBlock + 1 - rpc.BlockNumber(blocks)
|
oldestBlock := lastBlock + 1 - uint64(blocks)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
next = int64(oldestBlock)
|
next = oldestBlock
|
||||||
results = make(chan *blockFees, blocks)
|
results = make(chan *blockFees, blocks)
|
||||||
)
|
)
|
||||||
for i := 0; i < maxBlockFetchers && i < blocks; i++ {
|
for i := 0; i < maxBlockFetchers && i < blocks; i++ {
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
// Retrieve the next block number to fetch with this goroutine
|
// Retrieve the next block number to fetch with this goroutine
|
||||||
blockNumber := rpc.BlockNumber(atomic.AddInt64(&next, 1) - 1)
|
blockNumber := atomic.AddUint64(&next, 1) - 1
|
||||||
if blockNumber > lastBlock {
|
if blockNumber > lastBlock {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fees := &blockFees{blockNumber: blockNumber}
|
fees := &blockFees{blockNumber: blockNumber}
|
||||||
if pendingBlock != nil && blockNumber >= rpc.BlockNumber(pendingBlock.NumberU64()) {
|
if pendingBlock != nil && blockNumber >= pendingBlock.NumberU64() {
|
||||||
fees.block, fees.receipts = pendingBlock, pendingReceipts
|
fees.block, fees.receipts = pendingBlock, pendingReceipts
|
||||||
} else {
|
} else {
|
||||||
if len(rewardPercentiles) != 0 {
|
if len(rewardPercentiles) != 0 {
|
||||||
fees.block, fees.err = oracle.backend.BlockByNumber(ctx, blockNumber)
|
fees.block, fees.err = oracle.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNumber))
|
||||||
if fees.block != nil && fees.err == nil {
|
if fees.block != nil && fees.err == nil {
|
||||||
fees.receipts, fees.err = oracle.backend.GetReceipts(ctx, fees.block.Hash())
|
fees.receipts, fees.err = oracle.backend.GetReceipts(ctx, fees.block.Hash())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fees.header, fees.err = oracle.backend.HeaderByNumber(ctx, blockNumber)
|
fees.header, fees.err = oracle.backend.HeaderByNumber(ctx, rpc.BlockNumber(blockNumber))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fees.block != nil {
|
if fees.block != nil {
|
||||||
@ -275,7 +276,7 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, lastBlock rpc.
|
|||||||
for ; blocks > 0; blocks-- {
|
for ; blocks > 0; blocks-- {
|
||||||
fees := <-results
|
fees := <-results
|
||||||
if fees.err != nil {
|
if fees.err != nil {
|
||||||
return 0, nil, nil, nil, fees.err
|
return common.Big0, nil, nil, nil, fees.err
|
||||||
}
|
}
|
||||||
i := int(fees.blockNumber - oldestBlock)
|
i := int(fees.blockNumber - oldestBlock)
|
||||||
if fees.header != nil {
|
if fees.header != nil {
|
||||||
@ -288,7 +289,7 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, lastBlock rpc.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if firstMissing == 0 {
|
if firstMissing == 0 {
|
||||||
return 0, nil, nil, nil, nil
|
return common.Big0, nil, nil, nil, nil
|
||||||
}
|
}
|
||||||
if len(rewardPercentiles) != 0 {
|
if len(rewardPercentiles) != 0 {
|
||||||
reward = reward[:firstMissing]
|
reward = reward[:firstMissing]
|
||||||
@ -296,5 +297,5 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, lastBlock rpc.
|
|||||||
reward = nil
|
reward = nil
|
||||||
}
|
}
|
||||||
baseFee, gasUsedRatio = baseFee[:firstMissing+1], gasUsedRatio[:firstMissing]
|
baseFee, gasUsedRatio = baseFee[:firstMissing+1], gasUsedRatio[:firstMissing]
|
||||||
return oldestBlock, reward, baseFee, gasUsedRatio, nil
|
return new(big.Int).SetUint64(oldestBlock), reward, baseFee, gasUsedRatio, nil
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ func TestFeeHistory(t *testing.T) {
|
|||||||
count int
|
count int
|
||||||
last rpc.BlockNumber
|
last rpc.BlockNumber
|
||||||
percent []float64
|
percent []float64
|
||||||
expFirst rpc.BlockNumber
|
expFirst uint64
|
||||||
expCount int
|
expCount int
|
||||||
expErr error
|
expErr error
|
||||||
}{
|
}{
|
||||||
@ -70,7 +70,7 @@ func TestFeeHistory(t *testing.T) {
|
|||||||
expBaseFee++
|
expBaseFee++
|
||||||
}
|
}
|
||||||
|
|
||||||
if first != c.expFirst {
|
if first.Uint64() != c.expFirst {
|
||||||
t.Fatalf("Test case %d: first block mismatch, want %d, got %d", i, c.expFirst, first)
|
t.Fatalf("Test case %d: first block mismatch, want %d, got %d", i, c.expFirst, first)
|
||||||
}
|
}
|
||||||
if len(reward) != expReward {
|
if len(reward) != expReward {
|
||||||
|
@ -417,24 +417,24 @@ func TestOverriddenTraceCall(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, testspec := range testSuite {
|
for i, testspec := range testSuite {
|
||||||
result, err := api.TraceCall(context.Background(), testspec.call, rpc.BlockNumberOrHash{BlockNumber: &testspec.blockNumber}, testspec.config)
|
result, err := api.TraceCall(context.Background(), testspec.call, rpc.BlockNumberOrHash{BlockNumber: &testspec.blockNumber}, testspec.config)
|
||||||
if testspec.expectErr != nil {
|
if testspec.expectErr != nil {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("Expect error %v, get nothing", testspec.expectErr)
|
t.Errorf("test %d: want error %v, have nothing", i, testspec.expectErr)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !errors.Is(err, testspec.expectErr) {
|
if !errors.Is(err, testspec.expectErr) {
|
||||||
t.Errorf("Error mismatch, want %v, get %v", testspec.expectErr, err)
|
t.Errorf("test %d: error mismatch, want %v, have %v", i, testspec.expectErr, err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Expect no error, get %v", err)
|
t.Errorf("test %d: want no error, have %v", i, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ret := new(callTrace)
|
ret := new(callTrace)
|
||||||
if err := json.Unmarshal(result.(json.RawMessage), ret); err != nil {
|
if err := json.Unmarshal(result.(json.RawMessage), ret); err != nil {
|
||||||
t.Fatalf("failed to unmarshal trace result: %v", err)
|
t.Fatalf("test %d: failed to unmarshal trace result: %v", i, err)
|
||||||
}
|
}
|
||||||
if !jsonEqual(ret, testspec.expect) {
|
if !jsonEqual(ret, testspec.expect) {
|
||||||
// uncomment this for easier debugging
|
// uncomment this for easier debugging
|
||||||
|
@ -138,7 +138,7 @@ func testAccessList(t *testing.T, client *rpc.Client) {
|
|||||||
From: testAddr,
|
From: testAddr,
|
||||||
To: &common.Address{},
|
To: &common.Address{},
|
||||||
Gas: 21000,
|
Gas: 21000,
|
||||||
GasPrice: big.NewInt(1),
|
GasPrice: big.NewInt(765625000),
|
||||||
Value: big.NewInt(1),
|
Value: big.NewInt(1),
|
||||||
}
|
}
|
||||||
al, gas, vmErr, err := ec.CreateAccessList(context.Background(), msg)
|
al, gas, vmErr, err := ec.CreateAccessList(context.Background(), msg)
|
||||||
|
4
go.mod
4
go.mod
@ -1,6 +1,6 @@
|
|||||||
module github.com/ethereum/go-ethereum
|
module github.com/ethereum/go-ethereum
|
||||||
|
|
||||||
go 1.16
|
go 1.15
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Azure/azure-pipeline-go v0.2.2 // indirect
|
github.com/Azure/azure-pipeline-go v0.2.2 // indirect
|
||||||
@ -37,7 +37,7 @@ require (
|
|||||||
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
|
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
|
||||||
github.com/holiman/bloomfilter/v2 v2.0.3
|
github.com/holiman/bloomfilter/v2 v2.0.3
|
||||||
github.com/holiman/uint256 v1.2.0
|
github.com/holiman/uint256 v1.2.0
|
||||||
github.com/huin/goupnp v1.0.1-0.20210626160114-33cdcbb30dda
|
github.com/huin/goupnp v1.0.2
|
||||||
github.com/influxdata/influxdb v1.8.3
|
github.com/influxdata/influxdb v1.8.3
|
||||||
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458
|
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458
|
||||||
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e
|
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e
|
||||||
|
4
go.sum
4
go.sum
@ -213,8 +213,8 @@ github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iU
|
|||||||
github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM=
|
github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM=
|
||||||
github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw=
|
github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/huin/goupnp v1.0.1-0.20210626160114-33cdcbb30dda h1:Vofqyy/Ysqit++X33unU0Gr08b6P35hKm3juytDrBVI=
|
github.com/huin/goupnp v1.0.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI=
|
||||||
github.com/huin/goupnp v1.0.1-0.20210626160114-33cdcbb30dda/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM=
|
github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM=
|
||||||
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
|
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
|
@ -81,19 +81,19 @@ func (s *PublicEthereumAPI) MaxPriorityFeePerGas(ctx context.Context) (*hexutil.
|
|||||||
}
|
}
|
||||||
|
|
||||||
type feeHistoryResult struct {
|
type feeHistoryResult struct {
|
||||||
OldestBlock rpc.BlockNumber `json:"oldestBlock"`
|
OldestBlock *hexutil.Big `json:"oldestBlock"`
|
||||||
Reward [][]*hexutil.Big `json:"reward,omitempty"`
|
Reward [][]*hexutil.Big `json:"reward,omitempty"`
|
||||||
BaseFee []*hexutil.Big `json:"baseFeePerGas,omitempty"`
|
BaseFee []*hexutil.Big `json:"baseFeePerGas,omitempty"`
|
||||||
GasUsedRatio []float64 `json:"gasUsedRatio"`
|
GasUsedRatio []float64 `json:"gasUsedRatio"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublicEthereumAPI) FeeHistory(ctx context.Context, blockCount int, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*feeHistoryResult, error) {
|
func (s *PublicEthereumAPI) FeeHistory(ctx context.Context, blockCount rpc.DecimalOrHex, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*feeHistoryResult, error) {
|
||||||
oldest, reward, baseFee, gasUsed, err := s.b.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles)
|
oldest, reward, baseFee, gasUsed, err := s.b.FeeHistory(ctx, int(blockCount), lastBlock, rewardPercentiles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
results := &feeHistoryResult{
|
results := &feeHistoryResult{
|
||||||
OldestBlock: oldest,
|
OldestBlock: (*hexutil.Big)(oldest),
|
||||||
GasUsedRatio: gasUsed,
|
GasUsedRatio: gasUsed,
|
||||||
}
|
}
|
||||||
if reward != nil {
|
if reward != nil {
|
||||||
@ -477,7 +477,7 @@ func (s *PrivateAccountAPI) SignTransaction(ctx context.Context, args Transactio
|
|||||||
if args.Nonce == nil {
|
if args.Nonce == nil {
|
||||||
return nil, fmt.Errorf("nonce not specified")
|
return nil, fmt.Errorf("nonce not specified")
|
||||||
}
|
}
|
||||||
// Before actually sign the transaction, ensure the transaction fee is reasonable.
|
// Before actually signing the transaction, ensure the transaction fee is reasonable.
|
||||||
tx := args.toTransaction()
|
tx := args.toTransaction()
|
||||||
if err := checkTxFee(tx.GasPrice(), tx.Gas(), s.b.RPCTxFeeCap()); err != nil {
|
if err := checkTxFee(tx.GasPrice(), tx.Gas(), s.b.RPCTxFeeCap()); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -1008,8 +1008,19 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
|
|||||||
}
|
}
|
||||||
hi = block.GasLimit()
|
hi = block.GasLimit()
|
||||||
}
|
}
|
||||||
|
// Normalize the max fee per gas the call is willing to spend.
|
||||||
|
var feeCap *big.Int
|
||||||
|
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
|
||||||
|
return 0, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
|
||||||
|
} else if args.GasPrice != nil {
|
||||||
|
feeCap = args.GasPrice.ToInt()
|
||||||
|
} else if args.MaxFeePerGas != nil {
|
||||||
|
feeCap = args.MaxFeePerGas.ToInt()
|
||||||
|
} else {
|
||||||
|
feeCap = common.Big0
|
||||||
|
}
|
||||||
// Recap the highest gas limit with account's available balance.
|
// Recap the highest gas limit with account's available balance.
|
||||||
if args.GasPrice != nil && args.GasPrice.ToInt().BitLen() != 0 {
|
if feeCap.BitLen() != 0 {
|
||||||
state, _, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
state, _, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@ -1022,7 +1033,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
|
|||||||
}
|
}
|
||||||
available.Sub(available, args.Value.ToInt())
|
available.Sub(available, args.Value.ToInt())
|
||||||
}
|
}
|
||||||
allowance := new(big.Int).Div(available, args.GasPrice.ToInt())
|
allowance := new(big.Int).Div(available, feeCap)
|
||||||
|
|
||||||
// If the allowance is larger than maximum uint64, skip checking
|
// If the allowance is larger than maximum uint64, skip checking
|
||||||
if allowance.IsUint64() && hi > allowance.Uint64() {
|
if allowance.IsUint64() && hi > allowance.Uint64() {
|
||||||
@ -1031,7 +1042,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
|
|||||||
transfer = new(hexutil.Big)
|
transfer = new(hexutil.Big)
|
||||||
}
|
}
|
||||||
log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance,
|
log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance,
|
||||||
"sent", transfer.ToInt(), "gasprice", args.GasPrice.ToInt(), "fundable", allowance)
|
"sent", transfer.ToInt(), "maxFeePerGas", feeCap, "fundable", allowance)
|
||||||
hi = allowance.Uint64()
|
hi = allowance.Uint64()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1120,7 +1131,7 @@ type StructLogRes struct {
|
|||||||
Gas uint64 `json:"gas"`
|
Gas uint64 `json:"gas"`
|
||||||
GasCost uint64 `json:"gasCost"`
|
GasCost uint64 `json:"gasCost"`
|
||||||
Depth int `json:"depth"`
|
Depth int `json:"depth"`
|
||||||
Error error `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
Stack *[]string `json:"stack,omitempty"`
|
Stack *[]string `json:"stack,omitempty"`
|
||||||
Memory *[]string `json:"memory,omitempty"`
|
Memory *[]string `json:"memory,omitempty"`
|
||||||
Storage *map[string]string `json:"storage,omitempty"`
|
Storage *map[string]string `json:"storage,omitempty"`
|
||||||
@ -1136,7 +1147,7 @@ func FormatLogs(logs []vm.StructLog) []StructLogRes {
|
|||||||
Gas: trace.Gas,
|
Gas: trace.Gas,
|
||||||
GasCost: trace.GasCost,
|
GasCost: trace.GasCost,
|
||||||
Depth: trace.Depth,
|
Depth: trace.Depth,
|
||||||
Error: trace.Err,
|
Error: trace.ErrorString(),
|
||||||
}
|
}
|
||||||
if trace.Stack != nil {
|
if trace.Stack != nil {
|
||||||
stack := make([]string, len(trace.Stack))
|
stack := make([]string, len(trace.Stack))
|
||||||
@ -1323,7 +1334,7 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
|
|||||||
price := math.BigMin(new(big.Int).Add(tx.GasTipCap(), baseFee), tx.GasFeeCap())
|
price := math.BigMin(new(big.Int).Add(tx.GasTipCap(), baseFee), tx.GasFeeCap())
|
||||||
result.GasPrice = (*hexutil.Big)(price)
|
result.GasPrice = (*hexutil.Big)(price)
|
||||||
} else {
|
} else {
|
||||||
result.GasPrice = nil
|
result.GasPrice = (*hexutil.Big)(tx.GasFeeCap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
@ -1441,7 +1452,12 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
|
|||||||
}
|
}
|
||||||
// Copy the original db so we don't modify it
|
// Copy the original db so we don't modify it
|
||||||
statedb := db.Copy()
|
statedb := db.Copy()
|
||||||
msg := types.NewMessage(args.from(), args.To, uint64(*args.Nonce), args.Value.ToInt(), uint64(*args.Gas), args.GasPrice.ToInt(), big.NewInt(0), big.NewInt(0), args.data(), accessList, false)
|
// Set the accesslist to the last al
|
||||||
|
args.AccessList = &accessList
|
||||||
|
msg, err := args.ToMessage(b.RPCGasCap(), header.BaseFee)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Apply the transaction with the access list tracer
|
// Apply the transaction with the access list tracer
|
||||||
tracer := vm.NewAccessListTracer(accessList, args.from(), to, precompiles)
|
tracer := vm.NewAccessListTracer(accessList, args.from(), to, precompiles)
|
||||||
|
@ -42,7 +42,7 @@ type Backend interface {
|
|||||||
// General Ethereum API
|
// General Ethereum API
|
||||||
Downloader() *downloader.Downloader
|
Downloader() *downloader.Downloader
|
||||||
SuggestGasTipCap(ctx context.Context) (*big.Int, error)
|
SuggestGasTipCap(ctx context.Context) (*big.Int, error)
|
||||||
FeeHistory(ctx context.Context, blockCount int, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (rpc.BlockNumber, [][]*big.Int, []*big.Int, []float64, error)
|
FeeHistory(ctx context.Context, blockCount int, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error)
|
||||||
ChainDb() ethdb.Database
|
ChainDb() ethdb.Database
|
||||||
AccountManager() *accounts.Manager
|
AccountManager() *accounts.Manager
|
||||||
ExtRPCEnabled() bool
|
ExtRPCEnabled() bool
|
||||||
|
@ -80,6 +80,10 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
|
|||||||
}
|
}
|
||||||
// After london, default to 1559 unless gasPrice is set
|
// After london, default to 1559 unless gasPrice is set
|
||||||
head := b.CurrentHeader()
|
head := b.CurrentHeader()
|
||||||
|
// If user specifies both maxPriorityfee and maxFee, then we do not
|
||||||
|
// need to consult the chain for defaults. It's definitely a London tx.
|
||||||
|
if args.MaxPriorityFeePerGas == nil || args.MaxFeePerGas == nil {
|
||||||
|
// In this clause, user left some fields unspecified.
|
||||||
if b.ChainConfig().IsLondon(head.Number) && args.GasPrice == nil {
|
if b.ChainConfig().IsLondon(head.Number) && args.GasPrice == nil {
|
||||||
if args.MaxPriorityFeePerGas == nil {
|
if args.MaxPriorityFeePerGas == nil {
|
||||||
tip, err := b.SuggestGasTipCap(ctx)
|
tip, err := b.SuggestGasTipCap(ctx)
|
||||||
@ -116,6 +120,12 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
|
|||||||
args.GasPrice = (*hexutil.Big)(price)
|
args.GasPrice = (*hexutil.Big)(price)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Both maxPriorityfee and maxFee set by caller. Sanity-check their internal relation
|
||||||
|
if args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 {
|
||||||
|
return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", args.MaxFeePerGas, args.MaxPriorityFeePerGas)
|
||||||
|
}
|
||||||
|
}
|
||||||
if args.Value == nil {
|
if args.Value == nil {
|
||||||
args.Value = new(hexutil.Big)
|
args.Value = new(hexutil.Big)
|
||||||
}
|
}
|
||||||
|
@ -269,7 +269,7 @@ func (b *LesApiBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error)
|
|||||||
return b.gpo.SuggestTipCap(ctx)
|
return b.gpo.SuggestTipCap(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LesApiBackend) FeeHistory(ctx context.Context, blockCount int, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (firstBlock rpc.BlockNumber, reward [][]*big.Int, baseFee []*big.Int, gasUsedRatio []float64, err error) {
|
func (b *LesApiBackend) FeeHistory(ctx context.Context, blockCount int, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (firstBlock *big.Int, reward [][]*big.Int, baseFee []*big.Int, gasUsedRatio []float64, err error) {
|
||||||
return b.gpo.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles)
|
return b.gpo.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,8 +322,8 @@ func TestBadHeaderHashes(t *testing.T) {
|
|||||||
var err error
|
var err error
|
||||||
headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 4}, 10)
|
headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 4}, 10)
|
||||||
core.BadHashes[headers[2].Hash()] = true
|
core.BadHashes[headers[2].Hash()] = true
|
||||||
if _, err = bc.InsertHeaderChain(headers, 1); !errors.Is(err, core.ErrBlacklistedHash) {
|
if _, err = bc.InsertHeaderChain(headers, 1); !errors.Is(err, core.ErrBannedHash) {
|
||||||
t.Errorf("error mismatch: have: %v, want %v", err, core.ErrBlacklistedHash)
|
t.Errorf("error mismatch: have: %v, want %v", err, core.ErrBannedHash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +242,6 @@ func makeMiner(genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) {
|
|||||||
GPO: ethconfig.Defaults.GPO,
|
GPO: ethconfig.Defaults.GPO,
|
||||||
Ethash: ethconfig.Defaults.Ethash,
|
Ethash: ethconfig.Defaults.Ethash,
|
||||||
Miner: miner.Config{
|
Miner: miner.Config{
|
||||||
GasFloor: genesis.GasLimit * 9 / 10,
|
|
||||||
GasCeil: genesis.GasLimit * 11 / 10,
|
GasCeil: genesis.GasLimit * 11 / 10,
|
||||||
GasPrice: big.NewInt(1),
|
GasPrice: big.NewInt(1),
|
||||||
Recommit: time.Second,
|
Recommit: time.Second,
|
||||||
|
@ -193,7 +193,6 @@ func makeSealer(genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) {
|
|||||||
TxPool: core.DefaultTxPoolConfig,
|
TxPool: core.DefaultTxPoolConfig,
|
||||||
GPO: ethconfig.Defaults.GPO,
|
GPO: ethconfig.Defaults.GPO,
|
||||||
Miner: miner.Config{
|
Miner: miner.Config{
|
||||||
GasFloor: genesis.GasLimit * 9 / 10,
|
|
||||||
GasCeil: genesis.GasLimit * 11 / 10,
|
GasCeil: genesis.GasLimit * 11 / 10,
|
||||||
GasPrice: big.NewInt(1),
|
GasPrice: big.NewInt(1),
|
||||||
Recommit: time.Second,
|
Recommit: time.Second,
|
||||||
|
@ -171,7 +171,6 @@ func makeMiner(genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) {
|
|||||||
GPO: ethconfig.Defaults.GPO,
|
GPO: ethconfig.Defaults.GPO,
|
||||||
Ethash: ethconfig.Defaults.Ethash,
|
Ethash: ethconfig.Defaults.Ethash,
|
||||||
Miner: miner.Config{
|
Miner: miner.Config{
|
||||||
GasFloor: genesis.GasLimit * 9 / 10,
|
|
||||||
GasCeil: genesis.GasLimit * 11 / 10,
|
GasCeil: genesis.GasLimit * 11 / 10,
|
||||||
GasPrice: big.NewInt(1),
|
GasPrice: big.NewInt(1),
|
||||||
Recommit: time.Second,
|
Recommit: time.Second,
|
||||||
|
@ -897,19 +897,17 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64)
|
|||||||
header := &types.Header{
|
header := &types.Header{
|
||||||
ParentHash: parent.Hash(),
|
ParentHash: parent.Hash(),
|
||||||
Number: num.Add(num, common.Big1),
|
Number: num.Add(num, common.Big1),
|
||||||
GasLimit: core.CalcGasLimit(parent.GasUsed(), parent.GasLimit(), w.config.GasFloor, w.config.GasCeil),
|
GasLimit: core.CalcGasLimit(parent.GasLimit(), w.config.GasCeil),
|
||||||
Extra: w.extra,
|
Extra: w.extra,
|
||||||
Time: uint64(timestamp),
|
Time: uint64(timestamp),
|
||||||
}
|
}
|
||||||
// Set baseFee and GasLimit if we are on an EIP-1559 chain
|
// Set baseFee and GasLimit if we are on an EIP-1559 chain
|
||||||
if w.chainConfig.IsLondon(header.Number) {
|
if w.chainConfig.IsLondon(header.Number) {
|
||||||
header.BaseFee = misc.CalcBaseFee(w.chainConfig, parent.Header())
|
header.BaseFee = misc.CalcBaseFee(w.chainConfig, parent.Header())
|
||||||
parentGasLimit := parent.GasLimit()
|
|
||||||
if !w.chainConfig.IsLondon(parent.Number()) {
|
if !w.chainConfig.IsLondon(parent.Number()) {
|
||||||
// Bump by 2x
|
parentGasLimit := parent.GasLimit() * params.ElasticityMultiplier
|
||||||
parentGasLimit = parent.GasLimit() * params.ElasticityMultiplier
|
header.GasLimit = core.CalcGasLimit(parentGasLimit, w.config.GasCeil)
|
||||||
}
|
}
|
||||||
header.GasLimit = core.CalcGasLimit1559(parentGasLimit, w.config.GasCeil)
|
|
||||||
}
|
}
|
||||||
// Only set the coinbase if our consensus engine is running (avoid spurious block rewards)
|
// Only set the coinbase if our consensus engine is running (avoid spurious block rewards)
|
||||||
if w.isRunning() {
|
if w.isRunning() {
|
||||||
|
@ -67,7 +67,6 @@ var (
|
|||||||
|
|
||||||
testConfig = &Config{
|
testConfig = &Config{
|
||||||
Recommit: time.Second,
|
Recommit: time.Second,
|
||||||
GasFloor: params.GenesisGasLimit,
|
|
||||||
GasCeil: params.GenesisGasLimit,
|
GasCeil: params.GenesisGasLimit,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -292,19 +292,6 @@ func (tx *Transaction) GetNonce() int64 { return int64(tx.tx.Nonce()) }
|
|||||||
func (tx *Transaction) GetHash() *Hash { return &Hash{tx.tx.Hash()} }
|
func (tx *Transaction) GetHash() *Hash { return &Hash{tx.tx.Hash()} }
|
||||||
func (tx *Transaction) GetCost() *BigInt { return &BigInt{tx.tx.Cost()} }
|
func (tx *Transaction) GetCost() *BigInt { return &BigInt{tx.tx.Cost()} }
|
||||||
|
|
||||||
// Deprecated: GetSigHash cannot know which signer to use.
|
|
||||||
func (tx *Transaction) GetSigHash() *Hash { return &Hash{types.HomesteadSigner{}.Hash(tx.tx)} }
|
|
||||||
|
|
||||||
// Deprecated: use EthereumClient.TransactionSender
|
|
||||||
func (tx *Transaction) GetFrom(chainID *BigInt) (address *Address, _ error) {
|
|
||||||
var signer types.Signer = types.HomesteadSigner{}
|
|
||||||
if chainID != nil {
|
|
||||||
signer = types.NewEIP155Signer(chainID.bigint)
|
|
||||||
}
|
|
||||||
from, err := types.Sender(signer, tx.tx)
|
|
||||||
return &Address{from}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tx *Transaction) GetTo() *Address {
|
func (tx *Transaction) GetTo() *Address {
|
||||||
if to := tx.tx.To(); to != nil {
|
if to := tx.tx.To(); to != nil {
|
||||||
return &Address{*to}
|
return &Address{*to}
|
||||||
|
@ -280,7 +280,7 @@ func (h *httpServer) enableRPC(apis []rpc.API, config httpConfig) error {
|
|||||||
|
|
||||||
// Create RPC server and handler.
|
// Create RPC server and handler.
|
||||||
srv := rpc.NewServer()
|
srv := rpc.NewServer()
|
||||||
if err := RegisterApisFromWhitelist(apis, config.Modules, srv, false); err != nil {
|
if err := RegisterApis(apis, config.Modules, srv, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
h.httpConfig = config
|
h.httpConfig = config
|
||||||
@ -312,7 +312,7 @@ func (h *httpServer) enableWS(apis []rpc.API, config wsConfig) error {
|
|||||||
|
|
||||||
// Create RPC server and handler.
|
// Create RPC server and handler.
|
||||||
srv := rpc.NewServer()
|
srv := rpc.NewServer()
|
||||||
if err := RegisterApisFromWhitelist(apis, config.Modules, srv, false); err != nil {
|
if err := RegisterApis(apis, config.Modules, srv, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
h.wsConfig = config
|
h.wsConfig = config
|
||||||
@ -515,20 +515,20 @@ func (is *ipcServer) stop() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterApisFromWhitelist checks the given modules' availability, generates a whitelist based on the allowed modules,
|
// RegisterApis checks the given modules' availability, generates an allowlist based on the allowed modules,
|
||||||
// and then registers all of the APIs exposed by the services.
|
// and then registers all of the APIs exposed by the services.
|
||||||
func RegisterApisFromWhitelist(apis []rpc.API, modules []string, srv *rpc.Server, exposeAll bool) error {
|
func RegisterApis(apis []rpc.API, modules []string, srv *rpc.Server, exposeAll bool) error {
|
||||||
if bad, available := checkModuleAvailability(modules, apis); len(bad) > 0 {
|
if bad, available := checkModuleAvailability(modules, apis); len(bad) > 0 {
|
||||||
log.Error("Unavailable modules in HTTP API list", "unavailable", bad, "available", available)
|
log.Error("Unavailable modules in HTTP API list", "unavailable", bad, "available", available)
|
||||||
}
|
}
|
||||||
// Generate the whitelist based on the allowed modules
|
// Generate the allow list based on the allowed modules
|
||||||
whitelist := make(map[string]bool)
|
allowList := make(map[string]bool)
|
||||||
for _, module := range modules {
|
for _, module := range modules {
|
||||||
whitelist[module] = true
|
allowList[module] = true
|
||||||
}
|
}
|
||||||
// Register all the APIs exposed by the services
|
// Register all the APIs exposed by the services
|
||||||
for _, api := range apis {
|
for _, api := range apis {
|
||||||
if exposeAll || whitelist[api.Namespace] || (len(whitelist) == 0 && api.Public) {
|
if exposeAll || allowList[api.Namespace] || (len(allowList) == 0 && api.Public) {
|
||||||
if err := srv.RegisterName(api.Namespace, api.Service); err != nil {
|
if err := srv.RegisterName(api.Namespace, api.Service); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ var (
|
|||||||
errAlreadyDialing = errors.New("already dialing")
|
errAlreadyDialing = errors.New("already dialing")
|
||||||
errAlreadyConnected = errors.New("already connected")
|
errAlreadyConnected = errors.New("already connected")
|
||||||
errRecentlyDialed = errors.New("recently dialed")
|
errRecentlyDialed = errors.New("recently dialed")
|
||||||
errNotWhitelisted = errors.New("not contained in netrestrict whitelist")
|
errNetRestrict = errors.New("not contained in netrestrict list")
|
||||||
errNoPort = errors.New("node does not provide TCP port")
|
errNoPort = errors.New("node does not provide TCP port")
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ type dialConfig struct {
|
|||||||
self enode.ID // our own ID
|
self enode.ID // our own ID
|
||||||
maxDialPeers int // maximum number of dialed peers
|
maxDialPeers int // maximum number of dialed peers
|
||||||
maxActiveDials int // maximum number of active dials
|
maxActiveDials int // maximum number of active dials
|
||||||
netRestrict *netutil.Netlist // IP whitelist, disabled if nil
|
netRestrict *netutil.Netlist // IP netrestrict list, disabled if nil
|
||||||
resolver nodeResolver
|
resolver nodeResolver
|
||||||
dialer NodeDialer
|
dialer NodeDialer
|
||||||
log log.Logger
|
log log.Logger
|
||||||
@ -402,7 +402,7 @@ func (d *dialScheduler) checkDial(n *enode.Node) error {
|
|||||||
return errAlreadyConnected
|
return errAlreadyConnected
|
||||||
}
|
}
|
||||||
if d.netRestrict != nil && !d.netRestrict.Contains(n.IP()) {
|
if d.netRestrict != nil && !d.netRestrict.Contains(n.IP()) {
|
||||||
return errNotWhitelisted
|
return errNetRestrict
|
||||||
}
|
}
|
||||||
if d.history.contains(string(n.ID().Bytes())) {
|
if d.history.contains(string(n.ID().Bytes())) {
|
||||||
return errRecentlyDialed
|
return errRecentlyDialed
|
||||||
|
@ -41,7 +41,7 @@ type Config struct {
|
|||||||
PrivateKey *ecdsa.PrivateKey
|
PrivateKey *ecdsa.PrivateKey
|
||||||
|
|
||||||
// These settings are optional:
|
// These settings are optional:
|
||||||
NetRestrict *netutil.Netlist // network whitelist
|
NetRestrict *netutil.Netlist // list of allowed IP networks
|
||||||
Bootnodes []*enode.Node // list of bootstrap nodes
|
Bootnodes []*enode.Node // list of bootstrap nodes
|
||||||
Unhandled chan<- ReadPacket // unhandled packets are sent on this channel
|
Unhandled chan<- ReadPacket // unhandled packets are sent on this channel
|
||||||
Log log.Logger // if set, log messages go here
|
Log log.Logger // if set, log messages go here
|
||||||
|
@ -583,7 +583,7 @@ func (t *UDPv4) nodeFromRPC(sender *net.UDPAddr, rn v4wire.Node) (*node, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if t.netrestrict != nil && !t.netrestrict.Contains(rn.IP) {
|
if t.netrestrict != nil && !t.netrestrict.Contains(rn.IP) {
|
||||||
return nil, errors.New("not contained in netrestrict whitelist")
|
return nil, errors.New("not contained in netrestrict list")
|
||||||
}
|
}
|
||||||
key, err := v4wire.DecodePubkey(crypto.S256(), rn.ID)
|
key, err := v4wire.DecodePubkey(crypto.S256(), rn.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -353,7 +353,7 @@ func (srv *Server) RemovePeer(node *enode.Node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddTrustedPeer adds the given node to a reserved whitelist which allows the
|
// AddTrustedPeer adds the given node to a reserved trusted list which allows the
|
||||||
// node to always connect, even if the slot are full.
|
// node to always connect, even if the slot are full.
|
||||||
func (srv *Server) AddTrustedPeer(node *enode.Node) {
|
func (srv *Server) AddTrustedPeer(node *enode.Node) {
|
||||||
select {
|
select {
|
||||||
@ -903,7 +903,7 @@ func (srv *Server) checkInboundConn(remoteIP net.IP) error {
|
|||||||
}
|
}
|
||||||
// Reject connections that do not match NetRestrict.
|
// Reject connections that do not match NetRestrict.
|
||||||
if srv.NetRestrict != nil && !srv.NetRestrict.Contains(remoteIP) {
|
if srv.NetRestrict != nil && !srv.NetRestrict.Contains(remoteIP) {
|
||||||
return fmt.Errorf("not whitelisted in NetRestrict")
|
return fmt.Errorf("not in netrestrict list")
|
||||||
}
|
}
|
||||||
// Reject Internet peers that try too often.
|
// Reject Internet peers that try too often.
|
||||||
now := srv.clock.Now()
|
now := srv.clock.Now()
|
||||||
|
@ -123,20 +123,12 @@ func probabilistic(net *Network, quit chan struct{}, nodeCount int) {
|
|||||||
randWait := time.Duration(rand.Intn(5000)+1000) * time.Millisecond
|
randWait := time.Duration(rand.Intn(5000)+1000) * time.Millisecond
|
||||||
rand1 := rand.Intn(nodeCount - 1)
|
rand1 := rand.Intn(nodeCount - 1)
|
||||||
rand2 := rand.Intn(nodeCount - 1)
|
rand2 := rand.Intn(nodeCount - 1)
|
||||||
if rand1 < rand2 {
|
if rand1 <= rand2 {
|
||||||
lowid = rand1
|
lowid = rand1
|
||||||
highid = rand2
|
highid = rand2
|
||||||
} else if rand1 > rand2 {
|
} else if rand1 > rand2 {
|
||||||
highid = rand1
|
highid = rand1
|
||||||
lowid = rand2
|
lowid = rand2
|
||||||
} else {
|
|
||||||
if rand1 == 0 {
|
|
||||||
rand2 = 9
|
|
||||||
} else if rand1 == 9 {
|
|
||||||
rand1 = 0
|
|
||||||
}
|
|
||||||
lowid = rand1
|
|
||||||
highid = rand2
|
|
||||||
}
|
}
|
||||||
var steps = highid - lowid
|
var steps = highid - lowid
|
||||||
wg.Add(steps)
|
wg.Add(steps)
|
||||||
|
@ -75,10 +75,10 @@ var (
|
|||||||
|
|
||||||
// MainnetTrustedCheckpoint contains the light client trusted checkpoint for the main network.
|
// MainnetTrustedCheckpoint contains the light client trusted checkpoint for the main network.
|
||||||
MainnetTrustedCheckpoint = &TrustedCheckpoint{
|
MainnetTrustedCheckpoint = &TrustedCheckpoint{
|
||||||
SectionIndex: 389,
|
SectionIndex: 395,
|
||||||
SectionHead: common.HexToHash("0x8f96e510cf64abf34095c5aa3937acdf5316de5540945b9688f4a2e083cddc73"),
|
SectionHead: common.HexToHash("0xbfca95b8c1de014e252288e9c32029825fadbff58285f5b54556525e480dbb5b"),
|
||||||
CHTRoot: common.HexToHash("0xa2362493848d6dbc50dcbbf74c017ea808b8938bfb129217d507bd276950d7ac"),
|
CHTRoot: common.HexToHash("0x2ccf3dbb58eb6375e037fdd981ca5778359e4b8fa0270c2878b14361e64161e7"),
|
||||||
BloomRoot: common.HexToHash("0x72fc78a841bde7e08e1fb7c187b622c49dc8271db12db748ff5d0f27bdb41413"),
|
BloomRoot: common.HexToHash("0x2d46ec65a6941a2dc1e682f8f81f3d24192021f492fdf6ef0fdd51acb0f4ba0f"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// MainnetCheckpointOracle contains a set of configs for the main network oracle.
|
// MainnetCheckpointOracle contains a set of configs for the main network oracle.
|
||||||
@ -116,10 +116,10 @@ var (
|
|||||||
|
|
||||||
// RopstenTrustedCheckpoint contains the light client trusted checkpoint for the Ropsten test network.
|
// RopstenTrustedCheckpoint contains the light client trusted checkpoint for the Ropsten test network.
|
||||||
RopstenTrustedCheckpoint = &TrustedCheckpoint{
|
RopstenTrustedCheckpoint = &TrustedCheckpoint{
|
||||||
SectionIndex: 322,
|
SectionIndex: 329,
|
||||||
SectionHead: common.HexToHash("0xe3f2fb70acd752bbcac06b67688db8430815c788a31213011ed51b966108a5f4"),
|
SectionHead: common.HexToHash("0xe66f7038333a01fb95dc9ea03e5a2bdaf4b833cdcb9e393b9127e013bd64d39b"),
|
||||||
CHTRoot: common.HexToHash("0xb2993a6bc28b23b84159cb477c38c0ec5607434faae6b3657ad44cbcf116f288"),
|
CHTRoot: common.HexToHash("0x1b0c883338ac0d032122800c155a2e73105fbfebfaa50436893282bc2d9feec5"),
|
||||||
BloomRoot: common.HexToHash("0x871841e5c2ada9dab2011a550d38e9fe0a30047cfc81f1ffc7ebc09f4f230732"),
|
BloomRoot: common.HexToHash("0x3cc98c88d283bf002378246f22c653007655cbcea6ed89f98d739f73bd341a01"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// RopstenCheckpointOracle contains a set of configs for the Ropsten test network oracle.
|
// RopstenCheckpointOracle contains a set of configs for the Ropsten test network oracle.
|
||||||
@ -160,10 +160,10 @@ var (
|
|||||||
|
|
||||||
// RinkebyTrustedCheckpoint contains the light client trusted checkpoint for the Rinkeby test network.
|
// RinkebyTrustedCheckpoint contains the light client trusted checkpoint for the Rinkeby test network.
|
||||||
RinkebyTrustedCheckpoint = &TrustedCheckpoint{
|
RinkebyTrustedCheckpoint = &TrustedCheckpoint{
|
||||||
SectionIndex: 270,
|
SectionIndex: 276,
|
||||||
SectionHead: common.HexToHash("0x03ef8982c93bbf18c859bc1b20ae05b439f04cf1ff592656e941d2c3fcff5d68"),
|
SectionHead: common.HexToHash("0xea89a4b04e3da9bd688e316f8de669396b6d4a38a19d2cd96a00b70d58b836aa"),
|
||||||
CHTRoot: common.HexToHash("0x9eb80685e8ece479e105b170439779bc0f89997ab7f4dee425f85c4234e8a6b5"),
|
CHTRoot: common.HexToHash("0xd6889d0bf6673c0d2c1cf6e9098a6fe5b30888a115b6112796aa8ee8efc4a723"),
|
||||||
BloomRoot: common.HexToHash("0xc3673721c5697efe5fe4cb825d178f4a335dbfeda6a197fb75c9256a767379dc"),
|
BloomRoot: common.HexToHash("0x6009a9256b34b8bde3a3f094afb647ba5d73237546017b9025d64ac1ff54c47c"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// RinkebyCheckpointOracle contains a set of configs for the Rinkeby test network oracle.
|
// RinkebyCheckpointOracle contains a set of configs for the Rinkeby test network oracle.
|
||||||
@ -202,10 +202,10 @@ var (
|
|||||||
|
|
||||||
// GoerliTrustedCheckpoint contains the light client trusted checkpoint for the Görli test network.
|
// GoerliTrustedCheckpoint contains the light client trusted checkpoint for the Görli test network.
|
||||||
GoerliTrustedCheckpoint = &TrustedCheckpoint{
|
GoerliTrustedCheckpoint = &TrustedCheckpoint{
|
||||||
SectionIndex: 154,
|
SectionIndex: 160,
|
||||||
SectionHead: common.HexToHash("0xf4cb74cc0e3683589f4992902184241fb892d7c3859d0044c16ec864605ff80d"),
|
SectionHead: common.HexToHash("0xb5a666c790dc35a5613d04ebba8ba47a850b45a15d9b95ad7745c35ae034b5a5"),
|
||||||
CHTRoot: common.HexToHash("0xead95f9f2504b2c7c6d82c51d30e50b40631c3ea2f590cddcc9721cfc0ae79de"),
|
CHTRoot: common.HexToHash("0x6b4e00df52bdc38fa6c26c8ef595c2ad6184963ea36ab08ee744af460aa735e1"),
|
||||||
BloomRoot: common.HexToHash("0xc6dd6cfe88ac9c4a6d19c9a8651944fa9d941a2340a8f5ddaf673d4d39779d81"),
|
BloomRoot: common.HexToHash("0x8fa88f5e50190cb25243aeee262a1a9e4434a06f8d455885dcc1b5fc48c33836"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// GoerliCheckpointOracle contains a set of configs for the Goerli test network oracle.
|
// GoerliCheckpointOracle contains a set of configs for the Goerli test network oracle.
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
VersionMajor = 1 // Major version component of the current release
|
VersionMajor = 1 // Major version component of the current release
|
||||||
VersionMinor = 10 // Minor version component of the current release
|
VersionMinor = 10 // Minor version component of the current release
|
||||||
VersionPatch = 6 // Patch version component of the current release
|
VersionPatch = 7 // Patch version component of the current release
|
||||||
VersionMeta = "stable" // Version metadata to append to the version string
|
VersionMeta = "stable" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
22
rpc/types.go
22
rpc/types.go
@ -21,6 +21,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -191,3 +192,24 @@ func BlockNumberOrHashWithHash(hash common.Hash, canonical bool) BlockNumberOrHa
|
|||||||
RequireCanonical: canonical,
|
RequireCanonical: canonical,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecimalOrHex unmarshals a non-negative decimal or hex parameter into a uint64.
|
||||||
|
type DecimalOrHex uint64
|
||||||
|
|
||||||
|
// UnmarshalJSON implements json.Unmarshaler.
|
||||||
|
func (dh *DecimalOrHex) UnmarshalJSON(data []byte) error {
|
||||||
|
input := strings.TrimSpace(string(data))
|
||||||
|
if len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' {
|
||||||
|
input = input[1 : len(input)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
value, err := strconv.ParseUint(input, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
value, err = hexutil.DecodeUint64(input)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*dh = DecimalOrHex(value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -96,7 +96,7 @@ func wsHandshakeValidator(allowedOrigins []string) func(*http.Request) bool {
|
|||||||
if _, ok := req.Header["Origin"]; !ok {
|
if _, ok := req.Header["Origin"]; !ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// Verify origin against whitelist.
|
// Verify origin against allow list.
|
||||||
origin := strings.ToLower(req.Header.Get("Origin"))
|
origin := strings.ToLower(req.Header.Get("Origin"))
|
||||||
if allowAllOrigins || originIsAllowed(origins, origin) {
|
if allowAllOrigins || originIsAllowed(origins, origin) {
|
||||||
return true
|
return true
|
||||||
|
@ -33,6 +33,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
"github.com/ethereum/go-ethereum/signer/storage"
|
"github.com/ethereum/go-ethereum/signer/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ type ExternalAPI interface {
|
|||||||
// New request to create a new account
|
// New request to create a new account
|
||||||
New(ctx context.Context) (common.Address, error)
|
New(ctx context.Context) (common.Address, error)
|
||||||
// SignTransaction request to sign the specified transaction
|
// SignTransaction request to sign the specified transaction
|
||||||
SignTransaction(ctx context.Context, args SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error)
|
SignTransaction(ctx context.Context, args apitypes.SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error)
|
||||||
// SignData - request to sign the given data (plus prefix)
|
// SignData - request to sign the given data (plus prefix)
|
||||||
SignData(ctx context.Context, contentType string, addr common.MixedcaseAddress, data interface{}) (hexutil.Bytes, error)
|
SignData(ctx context.Context, contentType string, addr common.MixedcaseAddress, data interface{}) (hexutil.Bytes, error)
|
||||||
// SignTypedData - request to sign the given structured data (plus prefix)
|
// SignTypedData - request to sign the given structured data (plus prefix)
|
||||||
@ -104,7 +105,7 @@ type Validator interface {
|
|||||||
// ValidateTransaction does a number of checks on the supplied transaction, and
|
// ValidateTransaction does a number of checks on the supplied transaction, and
|
||||||
// returns either a list of warnings, or an error (indicating that the transaction
|
// returns either a list of warnings, or an error (indicating that the transaction
|
||||||
// should be immediately rejected).
|
// should be immediately rejected).
|
||||||
ValidateTransaction(selector *string, tx *SendTxArgs) (*ValidationMessages, error)
|
ValidateTransaction(selector *string, tx *apitypes.SendTxArgs) (*apitypes.ValidationMessages, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignerAPI defines the actual implementation of ExternalAPI
|
// SignerAPI defines the actual implementation of ExternalAPI
|
||||||
@ -220,14 +221,14 @@ func (m Metadata) String() string {
|
|||||||
type (
|
type (
|
||||||
// SignTxRequest contains info about a Transaction to sign
|
// SignTxRequest contains info about a Transaction to sign
|
||||||
SignTxRequest struct {
|
SignTxRequest struct {
|
||||||
Transaction SendTxArgs `json:"transaction"`
|
Transaction apitypes.SendTxArgs `json:"transaction"`
|
||||||
Callinfo []ValidationInfo `json:"call_info"`
|
Callinfo []apitypes.ValidationInfo `json:"call_info"`
|
||||||
Meta Metadata `json:"meta"`
|
Meta Metadata `json:"meta"`
|
||||||
}
|
}
|
||||||
// SignTxResponse result from SignTxRequest
|
// SignTxResponse result from SignTxRequest
|
||||||
SignTxResponse struct {
|
SignTxResponse struct {
|
||||||
//The UI may make changes to the TX
|
//The UI may make changes to the TX
|
||||||
Transaction SendTxArgs `json:"transaction"`
|
Transaction apitypes.SendTxArgs `json:"transaction"`
|
||||||
Approved bool `json:"approved"`
|
Approved bool `json:"approved"`
|
||||||
}
|
}
|
||||||
SignDataRequest struct {
|
SignDataRequest struct {
|
||||||
@ -235,7 +236,7 @@ type (
|
|||||||
Address common.MixedcaseAddress `json:"address"`
|
Address common.MixedcaseAddress `json:"address"`
|
||||||
Rawdata []byte `json:"raw_data"`
|
Rawdata []byte `json:"raw_data"`
|
||||||
Messages []*NameValueType `json:"messages"`
|
Messages []*NameValueType `json:"messages"`
|
||||||
Callinfo []ValidationInfo `json:"call_info"`
|
Callinfo []apitypes.ValidationInfo `json:"call_info"`
|
||||||
Hash hexutil.Bytes `json:"hash"`
|
Hash hexutil.Bytes `json:"hash"`
|
||||||
Meta Metadata `json:"meta"`
|
Meta Metadata `json:"meta"`
|
||||||
}
|
}
|
||||||
@ -537,7 +538,7 @@ func (api *SignerAPI) lookupOrQueryPassword(address common.Address, title, promp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SignTransaction signs the given Transaction and returns it both as json and rlp-encoded form
|
// SignTransaction signs the given Transaction and returns it both as json and rlp-encoded form
|
||||||
func (api *SignerAPI) SignTransaction(ctx context.Context, args SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error) {
|
func (api *SignerAPI) SignTransaction(ctx context.Context, args apitypes.SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
result SignTxResponse
|
result SignTxResponse
|
||||||
@ -548,7 +549,7 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, args SendTxArgs, meth
|
|||||||
}
|
}
|
||||||
// If we are in 'rejectMode', then reject rather than show the user warnings
|
// If we are in 'rejectMode', then reject rather than show the user warnings
|
||||||
if api.rejectMode {
|
if api.rejectMode {
|
||||||
if err := msgs.getWarnings(); err != nil {
|
if err := msgs.GetWarnings(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -585,7 +586,7 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, args SendTxArgs, meth
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Convert fields into a real transaction
|
// Convert fields into a real transaction
|
||||||
var unsignedTx = result.Transaction.toTransaction()
|
var unsignedTx = result.Transaction.ToTransaction()
|
||||||
// Get the password for the transaction
|
// Get the password for the transaction
|
||||||
pw, err := api.lookupOrQueryPassword(acc.Address, "Account password",
|
pw, err := api.lookupOrQueryPassword(acc.Address, "Account password",
|
||||||
fmt.Sprintf("Please enter the password for account %s", acc.Address.String()))
|
fmt.Sprintf("Please enter the password for account %s", acc.Address.String()))
|
||||||
@ -621,7 +622,7 @@ func (api *SignerAPI) SignGnosisSafeTx(ctx context.Context, signerAddress common
|
|||||||
}
|
}
|
||||||
// If we are in 'rejectMode', then reject rather than show the user warnings
|
// If we are in 'rejectMode', then reject rather than show the user warnings
|
||||||
if api.rejectMode {
|
if api.rejectMode {
|
||||||
if err := msgs.getWarnings(); err != nil {
|
if err := msgs.GetWarnings(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/signer/core"
|
"github.com/ethereum/go-ethereum/signer/core"
|
||||||
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
"github.com/ethereum/go-ethereum/signer/fourbyte"
|
"github.com/ethereum/go-ethereum/signer/fourbyte"
|
||||||
"github.com/ethereum/go-ethereum/signer/storage"
|
"github.com/ethereum/go-ethereum/signer/storage"
|
||||||
)
|
)
|
||||||
@ -223,14 +224,14 @@ func TestNewAcc(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func mkTestTx(from common.MixedcaseAddress) core.SendTxArgs {
|
func mkTestTx(from common.MixedcaseAddress) apitypes.SendTxArgs {
|
||||||
to := common.NewMixedcaseAddress(common.HexToAddress("0x1337"))
|
to := common.NewMixedcaseAddress(common.HexToAddress("0x1337"))
|
||||||
gas := hexutil.Uint64(21000)
|
gas := hexutil.Uint64(21000)
|
||||||
gasPrice := (hexutil.Big)(*big.NewInt(2000000000))
|
gasPrice := (hexutil.Big)(*big.NewInt(2000000000))
|
||||||
value := (hexutil.Big)(*big.NewInt(1e18))
|
value := (hexutil.Big)(*big.NewInt(1e18))
|
||||||
nonce := (hexutil.Uint64)(0)
|
nonce := (hexutil.Uint64)(0)
|
||||||
data := hexutil.Bytes(common.Hex2Bytes("01020304050607080a"))
|
data := hexutil.Bytes(common.Hex2Bytes("01020304050607080a"))
|
||||||
tx := core.SendTxArgs{
|
tx := apitypes.SendTxArgs{
|
||||||
From: from,
|
From: from,
|
||||||
To: &to,
|
To: &to,
|
||||||
Gas: gas,
|
Gas: gas,
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package core
|
package apitypes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -52,7 +52,7 @@ func (vs *ValidationMessages) Info(msg string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// getWarnings returns an error with all messages of type WARN of above, or nil if no warnings were present
|
/// getWarnings returns an error with all messages of type WARN of above, or nil if no warnings were present
|
||||||
func (v *ValidationMessages) getWarnings() error {
|
func (v *ValidationMessages) GetWarnings() error {
|
||||||
var messages []string
|
var messages []string
|
||||||
for _, msg := range v.Messages {
|
for _, msg := range v.Messages {
|
||||||
if msg.Typ == WARN || msg.Typ == CRIT {
|
if msg.Typ == WARN || msg.Typ == CRIT {
|
||||||
@ -97,7 +97,7 @@ func (args SendTxArgs) String() string {
|
|||||||
return err.Error()
|
return err.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (args *SendTxArgs) toTransaction() *types.Transaction {
|
func (args *SendTxArgs) ToTransaction() *types.Transaction {
|
||||||
txArgs := ethapi.TransactionArgs{
|
txArgs := ethapi.TransactionArgs{
|
||||||
Gas: &args.Gas,
|
Gas: &args.Gas,
|
||||||
GasPrice: args.GasPrice,
|
GasPrice: args.GasPrice,
|
@ -24,6 +24,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AuditLogger struct {
|
type AuditLogger struct {
|
||||||
@ -43,7 +44,7 @@ func (l *AuditLogger) New(ctx context.Context) (common.Address, error) {
|
|||||||
return l.api.New(ctx)
|
return l.api.New(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *AuditLogger) SignTransaction(ctx context.Context, args SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error) {
|
func (l *AuditLogger) SignTransaction(ctx context.Context, args apitypes.SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error) {
|
||||||
sel := "<nil>"
|
sel := "<nil>"
|
||||||
if methodSelector != nil {
|
if methodSelector != nil {
|
||||||
sel = *methodSelector
|
sel = *methodSelector
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GnosisSafeTx is a type to parse the safe-tx returned by the relayer,
|
// GnosisSafeTx is a type to parse the safe-tx returned by the relayer,
|
||||||
@ -76,9 +77,9 @@ func (tx *GnosisSafeTx) ToTypedData() TypedData {
|
|||||||
|
|
||||||
// ArgsForValidation returns a SendTxArgs struct, which can be used for the
|
// ArgsForValidation returns a SendTxArgs struct, which can be used for the
|
||||||
// common validations, e.g. look up 4byte destinations
|
// common validations, e.g. look up 4byte destinations
|
||||||
func (tx *GnosisSafeTx) ArgsForValidation() *SendTxArgs {
|
func (tx *GnosisSafeTx) ArgsForValidation() *apitypes.SendTxArgs {
|
||||||
gp := hexutil.Big(tx.GasPrice)
|
gp := hexutil.Big(tx.GasPrice)
|
||||||
args := &SendTxArgs{
|
args := &apitypes.SendTxArgs{
|
||||||
From: tx.Safe,
|
From: tx.Safe,
|
||||||
To: &tx.To,
|
To: &tx.To,
|
||||||
Gas: hexutil.Uint64(tx.SafeTxGas.Uint64()),
|
Gas: hexutil.Uint64(tx.SafeTxGas.Uint64()),
|
||||||
|
@ -38,6 +38,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SigFormat struct {
|
type SigFormat struct {
|
||||||
@ -323,7 +324,7 @@ func (api *SignerAPI) SignTypedData(ctx context.Context, addr common.MixedcaseAd
|
|||||||
// signTypedData is identical to the capitalized version, except that it also returns the hash (preimage)
|
// signTypedData is identical to the capitalized version, except that it also returns the hash (preimage)
|
||||||
// - the signature preimage (hash)
|
// - the signature preimage (hash)
|
||||||
func (api *SignerAPI) signTypedData(ctx context.Context, addr common.MixedcaseAddress,
|
func (api *SignerAPI) signTypedData(ctx context.Context, addr common.MixedcaseAddress,
|
||||||
typedData TypedData, validationMessages *ValidationMessages) (hexutil.Bytes, hexutil.Bytes, error) {
|
typedData TypedData, validationMessages *apitypes.ValidationMessages) (hexutil.Bytes, hexutil.Bytes, error) {
|
||||||
domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map())
|
domainSeparator, err := typedData.HashStruct("EIP712Domain", typedData.Domain.Map())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -23,14 +23,14 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/signer/core"
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ValidateTransaction does a number of checks on the supplied transaction, and
|
// ValidateTransaction does a number of checks on the supplied transaction, and
|
||||||
// returns either a list of warnings, or an error (indicating that the transaction
|
// returns either a list of warnings, or an error (indicating that the transaction
|
||||||
// should be immediately rejected).
|
// should be immediately rejected).
|
||||||
func (db *Database) ValidateTransaction(selector *string, tx *core.SendTxArgs) (*core.ValidationMessages, error) {
|
func (db *Database) ValidateTransaction(selector *string, tx *apitypes.SendTxArgs) (*apitypes.ValidationMessages, error) {
|
||||||
messages := new(core.ValidationMessages)
|
messages := new(apitypes.ValidationMessages)
|
||||||
|
|
||||||
// Prevent accidental erroneous usage of both 'input' and 'data' (show stopper)
|
// Prevent accidental erroneous usage of both 'input' and 'data' (show stopper)
|
||||||
if tx.Data != nil && tx.Input != nil && !bytes.Equal(*tx.Data, *tx.Input) {
|
if tx.Data != nil && tx.Input != nil && !bytes.Equal(*tx.Data, *tx.Input) {
|
||||||
@ -90,7 +90,7 @@ func (db *Database) ValidateTransaction(selector *string, tx *core.SendTxArgs) (
|
|||||||
|
|
||||||
// ValidateCallData checks if the ABI call-data + method selector (if given) can
|
// ValidateCallData checks if the ABI call-data + method selector (if given) can
|
||||||
// be parsed and seems to match.
|
// be parsed and seems to match.
|
||||||
func (db *Database) ValidateCallData(selector *string, data []byte, messages *core.ValidationMessages) {
|
func (db *Database) ValidateCallData(selector *string, data []byte, messages *apitypes.ValidationMessages) {
|
||||||
// If the data is empty, we have a plain value transfer, nothing more to do
|
// If the data is empty, we have a plain value transfer, nothing more to do
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return
|
return
|
||||||
|
@ -22,7 +22,7 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/signer/core"
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
func mixAddr(a string) (*common.MixedcaseAddress, error) {
|
func mixAddr(a string) (*common.MixedcaseAddress, error) {
|
||||||
@ -36,7 +36,7 @@ func toHexUint(h string) hexutil.Uint64 {
|
|||||||
b := big.NewInt(0).SetBytes(common.FromHex(h))
|
b := big.NewInt(0).SetBytes(common.FromHex(h))
|
||||||
return hexutil.Uint64(b.Uint64())
|
return hexutil.Uint64(b.Uint64())
|
||||||
}
|
}
|
||||||
func dummyTxArgs(t txtestcase) *core.SendTxArgs {
|
func dummyTxArgs(t txtestcase) *apitypes.SendTxArgs {
|
||||||
to, _ := mixAddr(t.to)
|
to, _ := mixAddr(t.to)
|
||||||
from, _ := mixAddr(t.from)
|
from, _ := mixAddr(t.from)
|
||||||
n := toHexUint(t.n)
|
n := toHexUint(t.n)
|
||||||
@ -55,7 +55,7 @@ func dummyTxArgs(t txtestcase) *core.SendTxArgs {
|
|||||||
input = &a
|
input = &a
|
||||||
|
|
||||||
}
|
}
|
||||||
return &core.SendTxArgs{
|
return &apitypes.SendTxArgs{
|
||||||
From: *from,
|
From: *from,
|
||||||
To: to,
|
To: to,
|
||||||
Value: value,
|
Value: value,
|
||||||
|
@ -28,6 +28,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
"github.com/ethereum/go-ethereum/signer/core"
|
"github.com/ethereum/go-ethereum/signer/core"
|
||||||
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
"github.com/ethereum/go-ethereum/signer/storage"
|
"github.com/ethereum/go-ethereum/signer/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -180,7 +181,7 @@ func TestSignTxRequest(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Logf("to %v", to.Address().String())
|
t.Logf("to %v", to.Address().String())
|
||||||
resp, err := r.ApproveTx(&core.SignTxRequest{
|
resp, err := r.ApproveTx(&core.SignTxRequest{
|
||||||
Transaction: core.SendTxArgs{
|
Transaction: apitypes.SendTxArgs{
|
||||||
From: *from,
|
From: *from,
|
||||||
To: to},
|
To: to},
|
||||||
Callinfo: nil,
|
Callinfo: nil,
|
||||||
@ -432,7 +433,7 @@ func dummyTx(value hexutil.Big) *core.SignTxRequest {
|
|||||||
gasPrice := hexutil.Big(*big.NewInt(2000000))
|
gasPrice := hexutil.Big(*big.NewInt(2000000))
|
||||||
|
|
||||||
return &core.SignTxRequest{
|
return &core.SignTxRequest{
|
||||||
Transaction: core.SendTxArgs{
|
Transaction: apitypes.SendTxArgs{
|
||||||
From: *from,
|
From: *from,
|
||||||
To: to,
|
To: to,
|
||||||
Value: value,
|
Value: value,
|
||||||
@ -440,7 +441,7 @@ func dummyTx(value hexutil.Big) *core.SignTxRequest {
|
|||||||
GasPrice: &gasPrice,
|
GasPrice: &gasPrice,
|
||||||
Gas: gas,
|
Gas: gas,
|
||||||
},
|
},
|
||||||
Callinfo: []core.ValidationInfo{
|
Callinfo: []apitypes.ValidationInfo{
|
||||||
{Typ: "Warning", Message: "All your base are bellong to us"},
|
{Typ: "Warning", Message: "All your base are bellong to us"},
|
||||||
},
|
},
|
||||||
Meta: core.Metadata{Remote: "remoteip", Local: "localip", Scheme: "inproc"},
|
Meta: core.Metadata{Remote: "remoteip", Local: "localip", Scheme: "inproc"},
|
||||||
|
@ -85,7 +85,7 @@ type btHeader struct {
|
|||||||
GasLimit uint64
|
GasLimit uint64
|
||||||
GasUsed uint64
|
GasUsed uint64
|
||||||
Timestamp uint64
|
Timestamp uint64
|
||||||
BaseFee *big.Int
|
BaseFeePerGas *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
type btHeaderMarshaling struct {
|
type btHeaderMarshaling struct {
|
||||||
@ -95,7 +95,7 @@ type btHeaderMarshaling struct {
|
|||||||
GasLimit math.HexOrDecimal64
|
GasLimit math.HexOrDecimal64
|
||||||
GasUsed math.HexOrDecimal64
|
GasUsed math.HexOrDecimal64
|
||||||
Timestamp math.HexOrDecimal64
|
Timestamp math.HexOrDecimal64
|
||||||
BaseFee *math.HexOrDecimal256
|
BaseFeePerGas *math.HexOrDecimal256
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *BlockTest) Run(snapshotter bool) error {
|
func (t *BlockTest) Run(snapshotter bool) error {
|
||||||
@ -170,7 +170,7 @@ func (t *BlockTest) genesis(config *params.ChainConfig) *core.Genesis {
|
|||||||
Mixhash: t.json.Genesis.MixHash,
|
Mixhash: t.json.Genesis.MixHash,
|
||||||
Coinbase: t.json.Genesis.Coinbase,
|
Coinbase: t.json.Genesis.Coinbase,
|
||||||
Alloc: t.json.Pre,
|
Alloc: t.json.Pre,
|
||||||
BaseFee: t.json.Genesis.BaseFee,
|
BaseFee: t.json.Genesis.BaseFeePerGas,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ func (b btHeader) MarshalJSON() ([]byte, error) {
|
|||||||
GasLimit math.HexOrDecimal64
|
GasLimit math.HexOrDecimal64
|
||||||
GasUsed math.HexOrDecimal64
|
GasUsed math.HexOrDecimal64
|
||||||
Timestamp math.HexOrDecimal64
|
Timestamp math.HexOrDecimal64
|
||||||
BaseFee *math.HexOrDecimal256
|
BaseFeePerGas *math.HexOrDecimal256
|
||||||
}
|
}
|
||||||
var enc btHeader
|
var enc btHeader
|
||||||
enc.Bloom = b.Bloom
|
enc.Bloom = b.Bloom
|
||||||
@ -52,7 +52,7 @@ func (b btHeader) MarshalJSON() ([]byte, error) {
|
|||||||
enc.GasLimit = math.HexOrDecimal64(b.GasLimit)
|
enc.GasLimit = math.HexOrDecimal64(b.GasLimit)
|
||||||
enc.GasUsed = math.HexOrDecimal64(b.GasUsed)
|
enc.GasUsed = math.HexOrDecimal64(b.GasUsed)
|
||||||
enc.Timestamp = math.HexOrDecimal64(b.Timestamp)
|
enc.Timestamp = math.HexOrDecimal64(b.Timestamp)
|
||||||
enc.BaseFee = (*math.HexOrDecimal256)(b.BaseFee)
|
enc.BaseFeePerGas = (*math.HexOrDecimal256)(b.BaseFeePerGas)
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ func (b *btHeader) UnmarshalJSON(input []byte) error {
|
|||||||
GasLimit *math.HexOrDecimal64
|
GasLimit *math.HexOrDecimal64
|
||||||
GasUsed *math.HexOrDecimal64
|
GasUsed *math.HexOrDecimal64
|
||||||
Timestamp *math.HexOrDecimal64
|
Timestamp *math.HexOrDecimal64
|
||||||
BaseFee *math.HexOrDecimal256
|
BaseFeePerGas *math.HexOrDecimal256
|
||||||
}
|
}
|
||||||
var dec btHeader
|
var dec btHeader
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
@ -129,8 +129,8 @@ func (b *btHeader) UnmarshalJSON(input []byte) error {
|
|||||||
if dec.Timestamp != nil {
|
if dec.Timestamp != nil {
|
||||||
b.Timestamp = uint64(*dec.Timestamp)
|
b.Timestamp = uint64(*dec.Timestamp)
|
||||||
}
|
}
|
||||||
if dec.BaseFee != nil {
|
if dec.BaseFeePerGas != nil {
|
||||||
b.BaseFee = (*big.Int)(dec.BaseFee)
|
b.BaseFeePerGas = (*big.Int)(dec.BaseFeePerGas)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ var (
|
|||||||
baseDir = filepath.Join(".", "testdata")
|
baseDir = filepath.Join(".", "testdata")
|
||||||
blockTestDir = filepath.Join(baseDir, "BlockchainTests")
|
blockTestDir = filepath.Join(baseDir, "BlockchainTests")
|
||||||
stateTestDir = filepath.Join(baseDir, "GeneralStateTests")
|
stateTestDir = filepath.Join(baseDir, "GeneralStateTests")
|
||||||
legacyStateTestDir = filepath.Join(baseDir, "LegacyTests", "Constantinople", "GeneralStateTests")
|
//legacyStateTestDir = filepath.Join(baseDir, "LegacyTests", "Constantinople", "GeneralStateTests")
|
||||||
transactionTestDir = filepath.Join(baseDir, "TransactionTests")
|
transactionTestDir = filepath.Join(baseDir, "TransactionTests")
|
||||||
vmTestDir = filepath.Join(baseDir, "VMTests")
|
vmTestDir = filepath.Join(baseDir, "VMTests")
|
||||||
rlpTestDir = filepath.Join(baseDir, "RLPTests")
|
rlpTestDir = filepath.Join(baseDir, "RLPTests")
|
||||||
@ -93,7 +93,7 @@ type testMatcher struct {
|
|||||||
failpat []testFailure
|
failpat []testFailure
|
||||||
skiploadpat []*regexp.Regexp
|
skiploadpat []*regexp.Regexp
|
||||||
slowpat []*regexp.Regexp
|
slowpat []*regexp.Regexp
|
||||||
whitelistpat *regexp.Regexp
|
runonlylistpat *regexp.Regexp
|
||||||
}
|
}
|
||||||
|
|
||||||
type testConfig struct {
|
type testConfig struct {
|
||||||
@ -124,8 +124,8 @@ func (tm *testMatcher) fails(pattern string, reason string) {
|
|||||||
tm.failpat = append(tm.failpat, testFailure{regexp.MustCompile(pattern), reason})
|
tm.failpat = append(tm.failpat, testFailure{regexp.MustCompile(pattern), reason})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tm *testMatcher) whitelist(pattern string) {
|
func (tm *testMatcher) runonly(pattern string) {
|
||||||
tm.whitelistpat = regexp.MustCompile(pattern)
|
tm.runonlylistpat = regexp.MustCompile(pattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
// config defines chain config for tests matching the pattern.
|
// config defines chain config for tests matching the pattern.
|
||||||
@ -217,9 +217,9 @@ func (tm *testMatcher) runTestFile(t *testing.T, path, name string, runTest inte
|
|||||||
if r, _ := tm.findSkip(name); r != "" {
|
if r, _ := tm.findSkip(name); r != "" {
|
||||||
t.Skip(r)
|
t.Skip(r)
|
||||||
}
|
}
|
||||||
if tm.whitelistpat != nil {
|
if tm.runonlylistpat != nil {
|
||||||
if !tm.whitelistpat.MatchString(name) {
|
if !tm.runonlylistpat.MatchString(name) {
|
||||||
t.Skip("Skipped by whitelist")
|
t.Skip("Skipped by runonly")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
@ -276,10 +276,10 @@ func runTestFunc(runTest interface{}, t *testing.T, name string, m reflect.Value
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMatcherWhitelist(t *testing.T) {
|
func TestMatcherRunonlylist(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
tm := new(testMatcher)
|
tm := new(testMatcher)
|
||||||
tm.whitelist("invalid*")
|
tm.runonly("invalid*")
|
||||||
tm.walk(t, rlpTestDir, func(t *testing.T, name string, test *RLPTest) {
|
tm.walk(t, rlpTestDir, func(t *testing.T, name string, test *RLPTest) {
|
||||||
if name[:len("invalidRLPTest.json")] != "invalidRLPTest.json" {
|
if name[:len("invalidRLPTest.json")] != "invalidRLPTest.json" {
|
||||||
t.Fatalf("invalid test found: %s != invalidRLPTest.json", name)
|
t.Fatalf("invalid test found: %s != invalidRLPTest.json", name)
|
||||||
|
@ -45,7 +45,8 @@ func TestState(t *testing.T) {
|
|||||||
|
|
||||||
// Uses 1GB RAM per tested fork
|
// Uses 1GB RAM per tested fork
|
||||||
st.skipLoad(`^stStaticCall/static_Call1MB`)
|
st.skipLoad(`^stStaticCall/static_Call1MB`)
|
||||||
|
// Un-skip this when https://github.com/ethereum/tests/issues/908 is closed
|
||||||
|
st.skipLoad(`^stQuadraticComplexityTest/QuadraticComplexitySolidity_CallDataCopy`)
|
||||||
// Broken tests:
|
// Broken tests:
|
||||||
// Expected failures:
|
// Expected failures:
|
||||||
//st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/Byzantium/0`, "bug in test")
|
//st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/Byzantium/0`, "bug in test")
|
||||||
@ -58,7 +59,9 @@ func TestState(t *testing.T) {
|
|||||||
// For Istanbul, older tests were moved into LegacyTests
|
// For Istanbul, older tests were moved into LegacyTests
|
||||||
for _, dir := range []string{
|
for _, dir := range []string{
|
||||||
stateTestDir,
|
stateTestDir,
|
||||||
legacyStateTestDir,
|
// legacy state tests are disabled, due to them not being
|
||||||
|
// regenerated for the no-sender-eoa change.
|
||||||
|
//legacyStateTestDir,
|
||||||
} {
|
} {
|
||||||
st.walk(t, dir, func(t *testing.T, name string, test *StateTest) {
|
st.walk(t, dir, func(t *testing.T, name string, test *StateTest) {
|
||||||
for _, subtest := range test.Subtests() {
|
for _, subtest := range test.Subtests() {
|
||||||
@ -68,6 +71,10 @@ func TestState(t *testing.T) {
|
|||||||
t.Run(key+"/trie", func(t *testing.T) {
|
t.Run(key+"/trie", func(t *testing.T) {
|
||||||
withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
|
withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
|
||||||
_, _, err := test.Run(subtest, vmconfig, false)
|
_, _, err := test.Run(subtest, vmconfig, false)
|
||||||
|
if err != nil && len(test.json.Post[subtest.Fork][subtest.Index].ExpectException) > 0 {
|
||||||
|
// Ignore expected errors (TODO MariusVanDerWijden check error string)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return st.checkFailure(t, err)
|
return st.checkFailure(t, err)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -79,6 +86,10 @@ func TestState(t *testing.T) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err != nil && len(test.json.Post[subtest.Fork][subtest.Index].ExpectException) > 0 {
|
||||||
|
// Ignore expected errors (TODO MariusVanDerWijden check error string)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return st.checkFailure(t, err)
|
return st.checkFailure(t, err)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -67,6 +67,8 @@ type stJSON struct {
|
|||||||
type stPostState struct {
|
type stPostState struct {
|
||||||
Root common.UnprefixedHash `json:"hash"`
|
Root common.UnprefixedHash `json:"hash"`
|
||||||
Logs common.UnprefixedHash `json:"logs"`
|
Logs common.UnprefixedHash `json:"logs"`
|
||||||
|
TxBytes hexutil.Bytes `json:"txbytes"`
|
||||||
|
ExpectException string `json:"expectException"`
|
||||||
Indexes struct {
|
Indexes struct {
|
||||||
Data int `json:"data"`
|
Data int `json:"data"`
|
||||||
Gas int `json:"gas"`
|
Gas int `json:"gas"`
|
||||||
@ -198,6 +200,19 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
|
|||||||
return nil, nil, common.Hash{}, err
|
return nil, nil, common.Hash{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to recover tx with current signer
|
||||||
|
if len(post.TxBytes) != 0 {
|
||||||
|
var ttx types.Transaction
|
||||||
|
err := ttx.UnmarshalBinary(post.TxBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, common.Hash{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := types.Sender(types.LatestSigner(config), &ttx); err != nil {
|
||||||
|
return nil, nil, common.Hash{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare the EVM.
|
// Prepare the EVM.
|
||||||
txContext := core.NewEVMTxContext(msg)
|
txContext := core.NewEVMTxContext(msg)
|
||||||
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
|
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 6b85703b568f4456582a00665d8a3e5c3b20b484
|
Subproject commit 5d534e37b80e9310e8c7751f805ca481a451123e
|
Loading…
Reference in New Issue
Block a user