diff --git a/CHANGELOG.md b/CHANGELOG.md index dc85b21bee..a9bc019019 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## v1.1.14 +IMPROVEMENT +* [\#1057](https://github.com/bnb-chain/bsc/pull/1057) ci: allow merge pull request +* [\#1063](https://github.com/bnb-chain/bsc/pull/1063) ci: fix the pattern of commit lint + +BUGFIX +* [\#1062](https://github.com/bnb-chain/bsc/pull/1062) test: fix TestOfflineBlockPrune failed randomly +* [\#1076](https://github.com/bnb-chain/bsc/pull/1076) bug: pick some patches from go-ethereum on v1.10.18 +* [\#1079](https://github.com/bnb-chain/bsc/pull/1079) core: fix potential goroutine leak + ## v1.1.13 FEATURE diff --git a/Dockerfile b/Dockerfile index 7c67861f7c..2d46357ca8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,10 @@ ARG BUILDNUM="" FROM golang:1.17-alpine as builder RUN apk add --no-cache make gcc musl-dev linux-headers git bash +# Get dependencies - will also be cached if we won't change go.mod/go.sum +COPY go.mod /go-ethereum/ +COPY go.sum /go-ethereum/ +RUN cd /go-ethereum && go mod download ADD . /go-ethereum RUN cd /go-ethereum && go run build/ci.go install ./cmd/geth diff --git a/Dockerfile.alltools b/Dockerfile.alltools index 3ae5377e4f..3205b412e4 100644 --- a/Dockerfile.alltools +++ b/Dockerfile.alltools @@ -7,6 +7,10 @@ ARG BUILDNUM="" FROM golang:1.17-alpine as builder RUN apk add --no-cache gcc musl-dev linux-headers git +# Get dependencies - will also be cached if we won't change go.mod/go.sum +COPY go.mod /go-ethereum/ +COPY go.sum /go-ethereum/ +RUN cd /go-ethereum && go mod download ADD . /go-ethereum RUN cd /go-ethereum && go run build/ci.go install diff --git a/accounts/abi/argument.go b/accounts/abi/argument.go index e6c117fe5f..c5326d5700 100644 --- a/accounts/abi/argument.go +++ b/accounts/abi/argument.go @@ -78,7 +78,7 @@ func (arguments Arguments) isTuple() bool { // Unpack performs the operation hexdata -> Go format. func (arguments Arguments) Unpack(data []byte) ([]interface{}, error) { if len(data) == 0 { - if len(arguments) != 0 { + if len(arguments.NonIndexed()) != 0 { return nil, fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected") } return make([]interface{}, 0), nil @@ -93,7 +93,7 @@ func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) return fmt.Errorf("abi: cannot unpack into a nil map") } if len(data) == 0 { - if len(arguments) != 0 { + if len(arguments.NonIndexed()) != 0 { return fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected") } return nil // Nothing to unmarshal, return @@ -115,8 +115,8 @@ func (arguments Arguments) Copy(v interface{}, values []interface{}) error { return fmt.Errorf("abi: Unpack(non-pointer %T)", v) } if len(values) == 0 { - if len(arguments) != 0 { - return fmt.Errorf("abi: attempting to copy no values while %d arguments are expected", len(arguments)) + if len(arguments.NonIndexed()) != 0 { + return fmt.Errorf("abi: attempting to copy no values while arguments are expected") } return nil // Nothing to copy, return } diff --git a/accounts/abi/unpack_test.go b/accounts/abi/unpack_test.go index e617f8abc5..bf40c301b5 100644 --- a/accounts/abi/unpack_test.go +++ b/accounts/abi/unpack_test.go @@ -201,6 +201,23 @@ var unpackTests = []unpackTest{ IntOne *big.Int }{big.NewInt(1)}, }, + { + def: `[{"type":"bool"}]`, + enc: "", + want: false, + err: "abi: attempting to unmarshall an empty string while arguments are expected", + }, + { + def: `[{"type":"bytes32","indexed":true},{"type":"uint256","indexed":false}]`, + enc: "", + want: false, + err: "abi: attempting to unmarshall an empty string while arguments are expected", + }, + { + def: `[{"type":"bool","indexed":true},{"type":"uint64","indexed":true}]`, + enc: "", + want: false, + }, } // TestLocalUnpackTests runs test specially designed only for unpacking. diff --git a/build/ci.go b/build/ci.go index d11f87c889..c6859ea31a 100644 --- a/build/ci.go +++ b/build/ci.go @@ -961,10 +961,10 @@ func doWindowsInstaller(cmdline []string) { build.Render("build/nsis.pathupdate.nsh", filepath.Join(*workdir, "PathUpdate.nsh"), 0644, nil) build.Render("build/nsis.envvarupdate.nsh", filepath.Join(*workdir, "EnvVarUpdate.nsh"), 0644, nil) if err := cp.CopyFile(filepath.Join(*workdir, "SimpleFC.dll"), "build/nsis.simplefc.dll"); err != nil { - log.Fatal("Failed to copy SimpleFC.dll: %v", err) + log.Fatalf("Failed to copy SimpleFC.dll: %v", err) } if err := cp.CopyFile(filepath.Join(*workdir, "COPYING"), "COPYING"); err != nil { - log.Fatal("Failed to copy copyright note: %v", err) + log.Fatalf("Failed to copy copyright note: %v", err) } // Build the installer. This assumes that all the needed files have been previously // built (don't mix building and packaging to keep cross compilation complexity to a diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index 6f2d97320d..d57602f8d5 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -246,7 +246,12 @@ func runCmd(ctx *cli.Context) error { } else { hexInput = []byte(ctx.GlobalString(InputFlag.Name)) } - input := common.FromHex(string(bytes.TrimSpace(hexInput))) + hexInput = bytes.TrimSpace(hexInput) + if len(hexInput)%2 != 0 { + fmt.Println("input length must be even") + os.Exit(1) + } + input := common.FromHex(string(hexInput)) var execFunc func() ([]byte, uint64, error) if ctx.GlobalBool(CreateFlag.Name) { diff --git a/cmd/geth/consolecmd_test.go b/cmd/geth/consolecmd_test.go index 845ede2f9c..6abf7a7ecb 100644 --- a/cmd/geth/consolecmd_test.go +++ b/cmd/geth/consolecmd_test.go @@ -43,7 +43,8 @@ func runMinimalGeth(t *testing.T, args ...string) *testgeth { // --networkid=1337 to avoid cache bump // --syncmode=full to avoid allocating fast sync bloom allArgs := []string{"--ropsten", "--networkid", "1337", "--syncmode=full", "--port", "0", - "--nat", "none", "--nodiscover", "--maxpeers", "0", "--cache", "64"} + "--nat", "none", "--nodiscover", "--maxpeers", "0", "--cache", "64", + "--datadir.minfreedisk", "0"} return runGeth(t, append(allArgs, args...)...) } diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index f8e40b187c..47ad3b22c8 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -77,11 +77,11 @@ func StartNode(ctx *cli.Context, stack *node.Node, isConsole bool) { signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM) defer signal.Stop(sigc) - minFreeDiskSpace := ethconfig.Defaults.TrieDirtyCache + minFreeDiskSpace := 2 * ethconfig.Defaults.TrieDirtyCache // Default 2 * 256Mb if ctx.GlobalIsSet(MinFreeDiskSpaceFlag.Name) { minFreeDiskSpace = ctx.GlobalInt(MinFreeDiskSpaceFlag.Name) } else if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { - minFreeDiskSpace = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 + minFreeDiskSpace = 2 * ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 } if minFreeDiskSpace > 0 { go monitorFreeDiskSpace(sigc, stack.InstanceDir(), uint64(minFreeDiskSpace)*1024*1024) @@ -131,7 +131,7 @@ func monitorFreeDiskSpace(sigc chan os.Signal, path string, freeDiskSpaceCritica } else if freeSpace < 2*freeDiskSpaceCritical { log.Warn("Disk space is running low. Geth will shutdown if disk space runs below critical level.", "available", common.StorageSize(freeSpace), "critical_level", common.StorageSize(freeDiskSpaceCritical)) } - time.Sleep(60 * time.Second) + time.Sleep(30 * time.Second) } } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 41582d1fde..376817356a 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1050,8 +1050,10 @@ func SplitAndTrim(input string) (ret []string) { // setHTTP creates the HTTP RPC listener interface string from the set // command line flags, returning empty if the HTTP endpoint is disabled. func setHTTP(ctx *cli.Context, cfg *node.Config) { - if ctx.GlobalBool(HTTPEnabledFlag.Name) && cfg.HTTPHost == "" { - cfg.HTTPHost = "127.0.0.1" + if ctx.GlobalBool(HTTPEnabledFlag.Name) { + if cfg.HTTPHost == "" { + cfg.HTTPHost = "127.0.0.1" + } if ctx.GlobalIsSet(HTTPListenAddrFlag.Name) { cfg.HTTPHost = ctx.GlobalString(HTTPListenAddrFlag.Name) } diff --git a/console/prompt/prompter.go b/console/prompt/prompter.go index 810b6c3e14..2a20b6906a 100644 --- a/console/prompt/prompter.go +++ b/console/prompt/prompter.go @@ -143,7 +143,7 @@ func (p *terminalPrompter) PromptPassword(prompt string) (passwd string, err err // choice to be made, returning that choice. func (p *terminalPrompter) PromptConfirm(prompt string) (bool, error) { input, err := p.Prompt(prompt + " [y/n] ") - if len(input) > 0 && strings.ToUpper(input[:1]) == "Y" { + if len(input) > 0 && strings.EqualFold(input[:1], "y") { return true, nil } return false, err diff --git a/core/asm/asm.go b/core/asm/asm.go index 4257198cc7..f3f129714d 100644 --- a/core/asm/asm.go +++ b/core/asm/asm.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . -// Provides support for dealing with EVM assembly instructions (e.g., disassembling them). +// Package asm provides support for dealing with EVM assembly instructions (e.g., disassembling them). package asm import ( @@ -34,14 +34,14 @@ type instructionIterator struct { started bool } -// Create a new instruction iterator. +// NewInstructionIterator create a new instruction iterator. func NewInstructionIterator(code []byte) *instructionIterator { it := new(instructionIterator) it.code = code return it } -// Returns true if there is a next instruction and moves on. +// Next returns true if there is a next instruction and moves on. func (it *instructionIterator) Next() bool { if it.error != nil || uint64(len(it.code)) <= it.pc { // We previously reached an error or the end. @@ -79,27 +79,27 @@ func (it *instructionIterator) Next() bool { return true } -// Returns any error that may have been encountered. +// Error returns any error that may have been encountered. func (it *instructionIterator) Error() error { return it.error } -// Returns the PC of the current instruction. +// PC returns the PC of the current instruction. func (it *instructionIterator) PC() uint64 { return it.pc } -// Returns the opcode of the current instruction. +// Op returns the opcode of the current instruction. func (it *instructionIterator) Op() vm.OpCode { return it.op } -// Returns the argument of the current instruction. +// Arg returns the argument of the current instruction. func (it *instructionIterator) Arg() []byte { return it.arg } -// Pretty-print all disassembled EVM instructions to stdout. +// PrintDisassembled pretty-print all disassembled EVM instructions to stdout. func PrintDisassembled(code string) error { script, err := hex.DecodeString(code) if err != nil { @@ -117,7 +117,7 @@ func PrintDisassembled(code string) error { return it.Error() } -// Return all disassembled EVM instructions in human-readable format. +// Disassemble returns all disassembled EVM instructions in human-readable format. func Disassemble(script []byte) ([]string, error) { instrs := make([]string, 0) diff --git a/core/asm/compiler.go b/core/asm/compiler.go index 7997099298..ce2d23abd0 100644 --- a/core/asm/compiler.go +++ b/core/asm/compiler.go @@ -39,7 +39,7 @@ type Compiler struct { debug bool } -// newCompiler returns a new allocated compiler. +// NewCompiler returns a new allocated compiler. func NewCompiler(debug bool) *Compiler { return &Compiler{ labels: make(map[string]int), @@ -105,16 +105,16 @@ func (c *Compiler) Compile() (string, []error) { } // turn the binary to hex - var bin string + var bin strings.Builder for _, v := range c.binary { switch v := v.(type) { case vm.OpCode: - bin += fmt.Sprintf("%x", []byte{byte(v)}) + bin.WriteString(fmt.Sprintf("%x", []byte{byte(v)})) case []byte: - bin += fmt.Sprintf("%x", v) + bin.WriteString(fmt.Sprintf("%x", v)) } } - return bin, errors + return bin.String(), errors } // next returns the next token and increments the @@ -243,12 +243,12 @@ func (c *Compiler) pushBin(v interface{}) { // isPush returns whether the string op is either any of // push(N). func isPush(op string) bool { - return strings.ToUpper(op) == "PUSH" + return strings.EqualFold(op, "PUSH") } // isJump returns whether the string op is jump(i) func isJump(op string) bool { - return strings.ToUpper(op) == "JUMPI" || strings.ToUpper(op) == "JUMP" + return strings.EqualFold(op, "JUMPI") || strings.EqualFold(op, "JUMP") } // toBinary converts text to a vm.OpCode diff --git a/core/asm/lexer.go b/core/asm/lexer.go index 7a052393f5..fb705848d2 100644 --- a/core/asm/lexer.go +++ b/core/asm/lexer.go @@ -95,7 +95,7 @@ type lexer struct { debug bool // flag for triggering debug output } -// lex lexes the program by name with the given source. It returns a +// Lex lexes the program by name with the given source. It returns a // channel on which the tokens are delivered. func Lex(source []byte, debug bool) <-chan token { ch := make(chan token) diff --git a/core/bench_test.go b/core/bench_test.go index 959979763d..06333033c4 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -162,7 +162,7 @@ func genTxRing(naccounts int) func(int, *BlockGen) { // genUncles generates blocks with two uncle headers. func genUncles(i int, gen *BlockGen) { - if i >= 6 { + if i >= 7 { b2 := gen.PrevBlock(i - 6).Header() b2.Extra = []byte("foo") gen.AddUncle(b2) diff --git a/core/state/snapshot/difflayer.go b/core/state/snapshot/difflayer.go index ca20b3ea4b..4db994c20b 100644 --- a/core/state/snapshot/difflayer.go +++ b/core/state/snapshot/difflayer.go @@ -297,6 +297,9 @@ func (dl *diffLayer) CorrectAccounts(accounts map[common.Hash][]byte) { // Parent returns the subsequent layer of a diff layer. func (dl *diffLayer) Parent() snapshot { + dl.lock.RLock() + defer dl.lock.RUnlock() + return dl.parent } @@ -527,7 +530,6 @@ func (dl *diffLayer) flatten() snapshot { for storageHash, data := range storage { comboData[storageHash] = data } - parent.storageData[accountHash] = comboData } // Return the combo parent return &diffLayer{ diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go index fdc141c474..4ec9fc3ecd 100644 --- a/core/state_prefetcher.go +++ b/core/state_prefetcher.go @@ -86,7 +86,11 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c // it should be in a separate goroutine, to avoid blocking the critical path. for i := 0; i < len(transactions); i++ { - txChan <- i + select { + case txChan <- i: + case <-interruptCh: + return + } } } diff --git a/core/state_prefetcher_test.go b/core/state_prefetcher_test.go new file mode 100644 index 0000000000..d5d69e9cda --- /dev/null +++ b/core/state_prefetcher_test.go @@ -0,0 +1,148 @@ +package core + +import ( + "math/big" + "testing" + "time" + + "bytes" + "context" + "errors" + "fmt" + "runtime/pprof" + "strings" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" + + "github.com/google/pprof/profile" +) + +func TestPrefetchLeaking(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + var ( + gendb = rawdb.NewMemoryDatabase() + key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + address = crypto.PubkeyToAddress(key.PublicKey) + funds = big.NewInt(100000000000000000) + gspec = &Genesis{ + Config: params.TestChainConfig, + Alloc: GenesisAlloc{address: {Balance: funds}}, + BaseFee: big.NewInt(params.InitialBaseFee), + } + genesis = gspec.MustCommit(gendb) + signer = types.LatestSigner(gspec.Config) + ) + blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), gendb, 1, func(i int, block *BlockGen) { + block.SetCoinbase(common.Address{0x00}) + for j := 0; j < 100; j++ { + tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, block.header.BaseFee, nil), signer, key) + if err != nil { + panic(err) + } + block.AddTx(tx) + } + }) + archiveDb := rawdb.NewMemoryDatabase() + gspec.MustCommit(archiveDb) + archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) + defer archive.Stop() + + block := blocks[0] + parent := archive.GetHeader(block.ParentHash(), block.NumberU64()-1) + statedb, _ := state.NewWithSharedPool(parent.Root, archive.stateCache, archive.snaps) + inter := make(chan struct{}) + + Track(ctx, t, func(ctx context.Context) { + close(inter) + go archive.prefetcher.Prefetch(block, statedb, &archive.vmConfig, inter) + time.Sleep(1 * time.Second) + }) +} + +func Track(ctx context.Context, t *testing.T, fn func(context.Context)) { + label := t.Name() + pprof.Do(ctx, pprof.Labels("test", label), fn) + if err := CheckNoGoroutines("test", label); err != nil { + t.Fatal("Leaked goroutines\n", err) + } +} + +func CheckNoGoroutines(key, value string) error { + var pb bytes.Buffer + profiler := pprof.Lookup("goroutine") + if profiler == nil { + return fmt.Errorf("unable to find profile") + } + err := profiler.WriteTo(&pb, 0) + if err != nil { + return fmt.Errorf("unable to read profile: %w", err) + } + + p, err := profile.ParseData(pb.Bytes()) + if err != nil { + return fmt.Errorf("unable to parse profile: %w", err) + } + + return summarizeGoroutines(p, key, value) +} + +func summarizeGoroutines(p *profile.Profile, key, expectedValue string) error { + var b strings.Builder + + for _, sample := range p.Sample { + if !matchesLabel(sample, key, expectedValue) { + continue + } + + fmt.Fprintf(&b, "count %d @", sample.Value[0]) + // format the stack trace for each goroutine + for _, loc := range sample.Location { + for i, ln := range loc.Line { + if i == 0 { + fmt.Fprintf(&b, "# %#8x", loc.Address) + if loc.IsFolded { + fmt.Fprint(&b, " [F]") + } + } else { + fmt.Fprint(&b, "# ") + } + if fn := ln.Function; fn != nil { + fmt.Fprintf(&b, " %-50s %s:%d", fn.Name, fn.Filename, ln.Line) + } else { + fmt.Fprintf(&b, " ???") + } + fmt.Fprintf(&b, "\n") + } + } + fmt.Fprintf(&b, "\n") + } + + if b.Len() == 0 { + return nil + } + + return errors.New(b.String()) +} + +func matchesLabel(sample *profile.Sample, key, expectedValue string) bool { + values, hasLabel := sample.Label[key] + if !hasLabel { + return false + } + + for _, value := range values { + if value == expectedValue { + return true + } + } + + return false +} diff --git a/core/tx_pool.go b/core/tx_pool.go index 31b0690739..cceb56530e 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -1529,7 +1529,7 @@ func (pool *TxPool) truncateQueue() { addresses = append(addresses, addressByHeartbeat{addr, pool.beats[addr]}) } } - sort.Sort(addresses) + sort.Sort(sort.Reverse(addresses)) // Drop transactions until the total is below the limit or only locals remain for drop := queued - pool.config.GlobalQueue; drop > 0 && len(addresses) > 0; { diff --git a/core/types/block.go b/core/types/block.go index 634ac219e3..a63666a76d 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -100,7 +100,7 @@ func (n *BlockNonce) UnmarshalText(input []byte) error { type Header struct { ParentHash common.Hash `json:"parentHash" gencodec:"required"` UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` - Coinbase common.Address `json:"miner" gencodec:"required"` + Coinbase common.Address `json:"miner"` Root common.Hash `json:"stateRoot" gencodec:"required"` TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` diff --git a/core/types/gen_header_json.go b/core/types/gen_header_json.go index 75e24b34d6..74746d033a 100644 --- a/core/types/gen_header_json.go +++ b/core/types/gen_header_json.go @@ -18,7 +18,7 @@ func (h Header) MarshalJSON() ([]byte, error) { type Header struct { ParentHash common.Hash `json:"parentHash" gencodec:"required"` UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` - Coinbase common.Address `json:"miner" gencodec:"required"` + Coinbase common.Address `json:"miner"` Root common.Hash `json:"stateRoot" gencodec:"required"` TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` @@ -60,7 +60,7 @@ func (h *Header) UnmarshalJSON(input []byte) error { type Header struct { ParentHash *common.Hash `json:"parentHash" gencodec:"required"` UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"` - Coinbase *common.Address `json:"miner" gencodec:"required"` + Coinbase *common.Address `json:"miner"` Root *common.Hash `json:"stateRoot" gencodec:"required"` TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"` ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"` @@ -87,10 +87,9 @@ func (h *Header) UnmarshalJSON(input []byte) error { return errors.New("missing required field 'sha3Uncles' for Header") } h.UncleHash = *dec.UncleHash - if dec.Coinbase == nil { - return errors.New("missing required field 'miner' for Header") + if dec.Coinbase != nil { + h.Coinbase = *dec.Coinbase } - h.Coinbase = *dec.Coinbase if dec.Root == nil { return errors.New("missing required field 'stateRoot' for Header") } diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go index e88dd3e852..3177a04d45 100644 --- a/core/types/transaction_test.go +++ b/core/types/transaction_test.go @@ -548,14 +548,18 @@ func TestTransactionCoding(t *testing.T) { if err != nil { t.Fatal(err) } - assertEqual(parsedTx, tx) + if err := assertEqual(parsedTx, tx); err != nil { + t.Fatal(err) + } // JSON parsedTx, err = encodeDecodeJSON(tx) if err != nil { t.Fatal(err) } - assertEqual(parsedTx, tx) + if err := assertEqual(parsedTx, tx); err != nil { + t.Fatal(err) + } } } diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 07e125dbf7..ee75dd9771 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -594,7 +594,7 @@ func (c *blake2F) Run(input []byte) ([]byte, error) { // Parse the input into the Blake2b call parameters var ( rounds = binary.BigEndian.Uint32(input[0:4]) - final = (input[212] == blake2FFinalBlockBytes) + final = input[212] == blake2FFinalBlockBytes h [8]uint64 m [16]uint64 diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go index 30d9b49f71..aa8d2f1eb3 100644 --- a/core/vm/contracts_test.go +++ b/core/vm/contracts_test.go @@ -185,7 +185,7 @@ func benchmarkPrecompiled(addr string, test precompiledTest, bench *testing.B) { return } if common.Bytes2Hex(res) != test.Expected { - bench.Error(fmt.Sprintf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res))) + bench.Errorf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res)) return } }) diff --git a/core/vm/instructions.go b/core/vm/instructions.go index db507c4811..92be3bf259 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -478,7 +478,7 @@ func opDifficulty(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) } func opRandom(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - v := new(uint256.Int).SetBytes((interpreter.evm.Context.Random.Bytes())) + v := new(uint256.Int).SetBytes(interpreter.evm.Context.Random.Bytes()) scope.Stack.push(v) return nil, nil } diff --git a/core/vm/memory.go b/core/vm/memory.go index ba5f8485dc..7db2308187 100644 --- a/core/vm/memory.go +++ b/core/vm/memory.go @@ -17,8 +17,6 @@ package vm import ( - "fmt" - "github.com/holiman/uint256" ) @@ -68,7 +66,7 @@ func (m *Memory) Resize(size uint64) { } } -// Get returns offset + size as a new slice +// GetCopy returns offset + size as a new slice func (m *Memory) GetCopy(offset, size int64) (cpy []byte) { if size == 0 { return nil @@ -106,18 +104,3 @@ func (m *Memory) Len() int { func (m *Memory) Data() []byte { return m.store } - -// Print dumps the content of the memory. -func (m *Memory) Print() { - fmt.Printf("### mem %d bytes ###\n", len(m.store)) - if len(m.store) > 0 { - addr := 0 - for i := 0; i+32 <= len(m.store); i += 32 { - fmt.Printf("%03d: % x\n", addr, m.store[i:i+32]) - addr++ - } - } else { - fmt.Println("-- empty --") - } - fmt.Println("####################") -} diff --git a/core/vm/stack.go b/core/vm/stack.go index 9e7e887ccd..e1a957e244 100644 --- a/core/vm/stack.go +++ b/core/vm/stack.go @@ -17,7 +17,6 @@ package vm import ( - "fmt" "sync" "github.com/holiman/uint256" @@ -81,16 +80,3 @@ func (st *Stack) peek() *uint256.Int { func (st *Stack) Back(n int) *uint256.Int { return &st.data[st.len()-n-1] } - -// Print dumps the content of the stack -func (st *Stack) Print() { - fmt.Println("### stack ###") - if len(st.data) > 0 { - for i, val := range st.data { - fmt.Printf("%-3d %s\n", i, val.String()) - } - } else { - fmt.Println("-- empty --") - } - fmt.Println("#############") -} diff --git a/eth/fetcher/block_fetcher.go b/eth/fetcher/block_fetcher.go index b18397563f..027ac16044 100644 --- a/eth/fetcher/block_fetcher.go +++ b/eth/fetcher/block_fetcher.go @@ -508,10 +508,21 @@ func (f *BlockFetcher) loop() { } defer req.Close() - res := <-resCh - res.Done <- nil - - f.FilterHeaders(peer, *res.Res.(*eth.BlockHeadersPacket), time.Now().Add(res.Time)) + timeout := time.NewTimer(2 * fetchTimeout) // 2x leeway before dropping the peer + defer timeout.Stop() + + select { + case res := <-resCh: + res.Done <- nil + f.FilterHeaders(peer, *res.Res.(*eth.BlockHeadersPacket), time.Now().Add(res.Time)) + + case <-timeout.C: + // The peer didn't respond in time. The request + // was already rescheduled at this point, we were + // waiting for a catchup. With an unresponsive + // peer however, it's a protocol violation. + f.dropPeer(peer) + } }(hash) } }(peer) @@ -554,11 +565,23 @@ func (f *BlockFetcher) loop() { } defer req.Close() - res := <-resCh - res.Done <- nil + timeout := time.NewTimer(2 * fetchTimeout) // 2x leeway before dropping the peer + defer timeout.Stop() + + select { + case res := <-resCh: + res.Done <- nil - txs, uncles := res.Res.(*eth.BlockBodiesPacket).Unpack() - f.FilterBodies(peer, txs, uncles, time.Now()) + txs, uncles := res.Res.(*eth.BlockBodiesPacket).Unpack() + f.FilterBodies(peer, txs, uncles, time.Now()) + + case <-timeout.C: + // The peer didn't respond in time. The request + // was already rescheduled at this point, we were + // waiting for a catchup. With an unresponsive + // peer however, it's a protocol violation. + f.dropPeer(peer) + } }(peer, hashes) } // Schedule the next fetch if blocks are still pending diff --git a/eth/fetcher/tx_fetcher_test.go b/eth/fetcher/tx_fetcher_test.go index 796d4caf0f..e13d68ffd1 100644 --- a/eth/fetcher/tx_fetcher_test.go +++ b/eth/fetcher/tx_fetcher_test.go @@ -304,7 +304,6 @@ func TestTransactionFetcherSingletonRequesting(t *testing.T) { func TestTransactionFetcherFailedRescheduling(t *testing.T) { // Create a channel to control when tx requests can fail proceed := make(chan struct{}) - testTransactionFetcherParallel(t, txFetcherTest{ init: func() *TxFetcher { return NewTxFetcher( @@ -1263,6 +1262,16 @@ func testTransactionFetcher(t *testing.T, tt txFetcherTest) { fetcher.Start() defer fetcher.Stop() + defer func() { // drain the wait chan on exit + for { + select { + case <-wait: + default: + return + } + } + }() + // Crunch through all the test steps and execute them for i, step := range tt.steps { switch step := step.(type) { diff --git a/eth/filters/api.go b/eth/filters/api.go index e154a8304c..56ee044274 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -30,7 +30,6 @@ import ( "github.com/ethereum/go-ethereum/common/gopool" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/rpc" ) @@ -49,8 +48,6 @@ type filter struct { // information related to the Ethereum protocol such als blocks, transactions and logs. type PublicFilterAPI struct { backend Backend - mux *event.TypeMux - quit chan struct{} events *EventSystem filtersMu sync.Mutex filters map[rpc.ID]*filter diff --git a/eth/filters/filter.go b/eth/filters/filter.go index 1f281a4ee1..e3ccf7d892 100644 --- a/eth/filters/filter.go +++ b/eth/filters/filter.go @@ -308,7 +308,7 @@ Logs: } // If the to filtered topics is greater than the amount of topics in logs, skip. if len(topics) > len(log.Topics) { - continue Logs + continue } for i, sub := range topics { match := len(sub) == 0 // empty rule set == wildcard diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go index cb6649d56c..220513405e 100644 --- a/eth/filters/filter_system_test.go +++ b/eth/filters/filter_system_test.go @@ -301,12 +301,15 @@ func TestLogFilterCreation(t *testing.T) { ) for i, test := range testCases { - _, err := api.NewFilter(test.crit) - if test.success && err != nil { + id, err := api.NewFilter(test.crit) + if err != nil && test.success { t.Errorf("expected filter creation for case %d to success, got %v", i, err) } - if !test.success && err == nil { - t.Errorf("expected testcase %d to fail with an error", i) + if err == nil { + api.UninstallFilter(id) + if !test.success { + t.Errorf("expected testcase %d to fail with an error", i) + } } } } diff --git a/eth/handler.go b/eth/handler.go index aa01b444ef..5924f1bd49 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -493,7 +493,7 @@ func (h *handler) runSnapExtension(peer *snap.Peer, handler snap.Handler) error defer h.peerWG.Done() if err := h.peers.registerSnapExtension(peer); err != nil { - peer.Log().Error("Snapshot extension registration failed", "err", err) + peer.Log().Warn("Snapshot extension registration failed", "err", err) return err } return handler(peer) diff --git a/eth/protocols/snap/sync.go b/eth/protocols/snap/sync.go index 9a1af86cd4..684e8d2c4a 100644 --- a/eth/protocols/snap/sync.go +++ b/eth/protocols/snap/sync.go @@ -423,6 +423,8 @@ type Syncer struct { storageSynced uint64 // Number of storage slots downloaded storageBytes common.StorageSize // Number of storage trie bytes persisted to disk + extProgress *SyncProgress // progress that can be exposed to external caller. + // Request tracking during healing phase trienodeHealIdlers map[string]struct{} // Peers that aren't serving trie node requests bytecodeHealIdlers map[string]struct{} // Peers that aren't serving bytecode requests @@ -478,6 +480,8 @@ func NewSyncer(db ethdb.KeyValueStore) *Syncer { trienodeHealReqs: make(map[uint64]*trienodeHealRequest), bytecodeHealReqs: make(map[uint64]*bytecodeHealRequest), stateWriter: db.NewBatch(), + + extProgress: new(SyncProgress), } } @@ -634,6 +638,21 @@ func (s *Syncer) Sync(root common.Hash, cancel chan struct{}) error { s.assignTrienodeHealTasks(trienodeHealResps, trienodeHealReqFails, cancel) s.assignBytecodeHealTasks(bytecodeHealResps, bytecodeHealReqFails, cancel) } + // Update sync progress + s.lock.Lock() + s.extProgress = &SyncProgress{ + AccountSynced: s.accountSynced, + AccountBytes: s.accountBytes, + BytecodeSynced: s.bytecodeSynced, + BytecodeBytes: s.bytecodeBytes, + StorageSynced: s.storageSynced, + StorageBytes: s.storageBytes, + TrienodeHealSynced: s.trienodeHealSynced, + TrienodeHealBytes: s.trienodeHealBytes, + BytecodeHealSynced: s.bytecodeHealSynced, + BytecodeHealBytes: s.bytecodeHealBytes, + } + s.lock.Unlock() // Wait for something to happen select { case <-s.update: @@ -706,6 +725,9 @@ func (s *Syncer) loadSyncStatus() { } } } + s.lock.Lock() + defer s.lock.Unlock() + s.snapped = len(s.tasks) == 0 s.accountSynced = progress.AccountSynced @@ -803,25 +825,12 @@ func (s *Syncer) saveSyncStatus() { func (s *Syncer) Progress() (*SyncProgress, *SyncPending) { s.lock.Lock() defer s.lock.Unlock() - - progress := &SyncProgress{ - AccountSynced: s.accountSynced, - AccountBytes: s.accountBytes, - BytecodeSynced: s.bytecodeSynced, - BytecodeBytes: s.bytecodeBytes, - StorageSynced: s.storageSynced, - StorageBytes: s.storageBytes, - TrienodeHealSynced: s.trienodeHealSynced, - TrienodeHealBytes: s.trienodeHealBytes, - BytecodeHealSynced: s.bytecodeHealSynced, - BytecodeHealBytes: s.bytecodeHealBytes, - } pending := new(SyncPending) if s.healer != nil { pending.TrienodeHeal = uint64(len(s.healer.trieTasks)) pending.BytecodeHeal = uint64(len(s.healer.codeTasks)) } - return progress, pending + return s.extProgress, pending } // cleanAccountTasks removes account range retrieval tasks that have already been diff --git a/eth/tracers/logger/access_list_tracer.go b/eth/tracers/logger/access_list_tracer.go index 181fc47acb..bb1097d8e2 100644 --- a/eth/tracers/logger/access_list_tracer.go +++ b/eth/tracers/logger/access_list_tracer.go @@ -62,16 +62,14 @@ func (al accessList) equal(other accessList) bool { if len(al) != len(other) { return false } + // Given that len(al) == len(other), we only need to check that + // all the items from al are in other. for addr := range al { if _, ok := other[addr]; !ok { return false } } - for addr := range other { - if _, ok := al[addr]; !ok { - return false - } - } + // Accounts match, cross reference the storage slots too for addr, slots := range al { otherslots := other[addr] @@ -79,16 +77,13 @@ func (al accessList) equal(other accessList) bool { if len(slots) != len(otherslots) { return false } + // Given that len(slots) == len(otherslots), we only need to check that + // all the items from slots are in otherslots. for hash := range slots { if _, ok := otherslots[hash]; !ok { return false } } - for hash := range otherslots { - if _, ok := slots[hash]; !ok { - return false - } - } } return true } diff --git a/eth/tracers/logger/gen_structlog.go b/eth/tracers/logger/gen_structlog.go index e28c2ad94c..d9143dd23c 100644 --- a/eth/tracers/logger/gen_structlog.go +++ b/eth/tracers/logger/gen_structlog.go @@ -22,16 +22,16 @@ func (s StructLog) MarshalJSON() ([]byte, error) { Op vm.OpCode `json:"op"` Gas math.HexOrDecimal64 `json:"gas"` GasCost math.HexOrDecimal64 `json:"gasCost"` - Memory hexutil.Bytes `json:"memory"` + Memory hexutil.Bytes `json:"memory,omitempty"` MemorySize int `json:"memSize"` Stack []uint256.Int `json:"stack"` - ReturnData hexutil.Bytes `json:"returnData"` + ReturnData hexutil.Bytes `json:"returnData,omitempty"` Storage map[common.Hash]common.Hash `json:"-"` Depth int `json:"depth"` RefundCounter uint64 `json:"refund"` Err error `json:"-"` OpName string `json:"opName"` - ErrorString string `json:"error"` + ErrorString string `json:"error,omitempty"` } var enc StructLog enc.Pc = s.Pc @@ -58,10 +58,10 @@ func (s *StructLog) UnmarshalJSON(input []byte) error { Op *vm.OpCode `json:"op"` Gas *math.HexOrDecimal64 `json:"gas"` GasCost *math.HexOrDecimal64 `json:"gasCost"` - Memory *hexutil.Bytes `json:"memory"` + Memory *hexutil.Bytes `json:"memory,omitempty"` MemorySize *int `json:"memSize"` Stack []uint256.Int `json:"stack"` - ReturnData *hexutil.Bytes `json:"returnData"` + ReturnData *hexutil.Bytes `json:"returnData,omitempty"` Storage map[common.Hash]common.Hash `json:"-"` Depth *int `json:"depth"` RefundCounter *uint64 `json:"refund"` diff --git a/eth/tracers/logger/logger.go b/eth/tracers/logger/logger.go index 8461935822..d0c7bff893 100644 --- a/eth/tracers/logger/logger.go +++ b/eth/tracers/logger/logger.go @@ -66,10 +66,10 @@ type StructLog struct { Op vm.OpCode `json:"op"` Gas uint64 `json:"gas"` GasCost uint64 `json:"gasCost"` - Memory []byte `json:"memory"` + Memory []byte `json:"memory,omitempty"` MemorySize int `json:"memSize"` Stack []uint256.Int `json:"stack"` - ReturnData []byte `json:"returnData"` + ReturnData []byte `json:"returnData,omitempty"` Storage map[common.Hash]common.Hash `json:"-"` Depth int `json:"depth"` RefundCounter uint64 `json:"refund"` @@ -82,8 +82,8 @@ type structLogMarshaling struct { GasCost math.HexOrDecimal64 Memory hexutil.Bytes ReturnData hexutil.Bytes - OpName string `json:"opName"` // adds call to OpName() in MarshalJSON - ErrorString string `json:"error"` // adds call to ErrorString() in MarshalJSON + OpName string `json:"opName"` // adds call to OpName() in MarshalJSON + ErrorString string `json:"error,omitempty"` // adds call to ErrorString() in MarshalJSON } // OpName formats the operand name in a human-readable format. diff --git a/eth/tracers/logger/logger_test.go b/eth/tracers/logger/logger_test.go index 205ee31120..6b1e740814 100644 --- a/eth/tracers/logger/logger_test.go +++ b/eth/tracers/logger/logger_test.go @@ -17,6 +17,8 @@ package logger import ( + "encoding/json" + "fmt" "math/big" "testing" @@ -72,3 +74,34 @@ func TestStoreCapture(t *testing.T) { t.Errorf("expected %x, got %x", exp, logger.storage[contract.Address()][index]) } } + +// Tests that blank fields don't appear in logs when JSON marshalled, to reduce +// logs bloat and confusion. See https://github.com/ethereum/go-ethereum/issues/24487 +func TestStructLogMarshalingOmitEmpty(t *testing.T) { + tests := []struct { + name string + log *StructLog + want string + }{ + {"empty err and no fields", &StructLog{}, + `{"pc":0,"op":0,"gas":"0x0","gasCost":"0x0","memSize":0,"stack":null,"depth":0,"refund":0,"opName":"STOP"}`}, + {"with err", &StructLog{Err: fmt.Errorf("this failed")}, + `{"pc":0,"op":0,"gas":"0x0","gasCost":"0x0","memSize":0,"stack":null,"depth":0,"refund":0,"opName":"STOP","error":"this failed"}`}, + {"with mem", &StructLog{Memory: make([]byte, 2), MemorySize: 2}, + `{"pc":0,"op":0,"gas":"0x0","gasCost":"0x0","memory":"0x0000","memSize":2,"stack":null,"depth":0,"refund":0,"opName":"STOP"}`}, + {"with 0-size mem", &StructLog{Memory: make([]byte, 0)}, + `{"pc":0,"op":0,"gas":"0x0","gasCost":"0x0","memSize":0,"stack":null,"depth":0,"refund":0,"opName":"STOP"}`}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + blob, err := json.Marshal(tt.log) + if err != nil { + t.Fatal(err) + } + if have, want := string(blob), tt.want; have != want { + t.Fatalf("mismatched results\n\thave: %v\n\twant: %v", have, want) + } + }) + } +} diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go index 538e23727d..7af2bf45d7 100644 --- a/ethclient/gethclient/gethclient.go +++ b/ethclient/gethclient/gethclient.go @@ -114,6 +114,7 @@ func (ec *Client) GetProof(ctx context.Context, account common.Address, keys []s Nonce: uint64(res.Nonce), CodeHash: res.CodeHash, StorageHash: res.StorageHash, + StorageProof: storageResults, } return &result, err } diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index 0ebd0c82dd..d8f9385690 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -40,6 +40,8 @@ import ( var ( testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") testAddr = crypto.PubkeyToAddress(testKey.PublicKey) + testSlot = common.HexToHash("0xdeadbeef") + testValue = crypto.Keccak256Hash(testSlot[:]) testBalance = big.NewInt(2e15) ) @@ -73,7 +75,7 @@ func generateTestChain() (*core.Genesis, []*types.Block) { config := params.AllEthashProtocolChanges genesis := &core.Genesis{ Config: config, - Alloc: core.GenesisAlloc{testAddr: {Balance: testBalance}}, + Alloc: core.GenesisAlloc{testAddr: {Balance: testBalance, Storage: map[common.Hash]common.Hash{testSlot: testValue}}}, ExtraData: []byte("test genesis"), Timestamp: 9000, } @@ -191,7 +193,7 @@ func testAccessList(t *testing.T, client *rpc.Client) { func testGetProof(t *testing.T, client *rpc.Client) { ec := New(client) ethcl := ethclient.NewClient(client) - result, err := ec.GetProof(context.Background(), testAddr, []string{}, nil) + result, err := ec.GetProof(context.Background(), testAddr, []string{testSlot.String()}, nil) if err != nil { t.Fatal(err) } @@ -208,6 +210,19 @@ func testGetProof(t *testing.T, client *rpc.Client) { if result.Balance.Cmp(balance) != 0 { t.Fatalf("invalid balance, want: %v got: %v", balance, result.Balance) } + // test storage + if len(result.StorageProof) != 1 { + t.Fatalf("invalid storage proof, want 1 proof, got %v proof(s)", len(result.StorageProof)) + } + proof := result.StorageProof[0] + slotValue, _ := ethcl.StorageAt(context.Background(), testAddr, testSlot, nil) + if !bytes.Equal(slotValue, proof.Value.Bytes()) { + t.Fatalf("invalid storage proof value, want: %v, got: %v", slotValue, proof.Value.Bytes()) + } + if proof.Key != testSlot.String() { + t.Fatalf("invalid storage proof key, want: %v, got: %v", testSlot.String(), proof.Key) + } + } func testGCStats(t *testing.T, client *rpc.Client) { diff --git a/go.mod b/go.mod index 0e357fb564..a9849b51f1 100644 --- a/go.mod +++ b/go.mod @@ -35,6 +35,7 @@ require ( github.com/golang/protobuf v1.4.3 github.com/golang/snappy v0.0.4 github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa + github.com/google/pprof v0.0.0-20220829040838-70bd9ae97f40 github.com/google/uuid v1.1.5 github.com/gorilla/websocket v1.4.2 github.com/graph-gophers/graphql-go v1.3.0 @@ -42,7 +43,7 @@ require ( github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/holiman/bloomfilter/v2 v2.0.3 github.com/holiman/uint256 v1.2.0 - github.com/huin/goupnp v1.0.2 + github.com/huin/goupnp v1.0.3 github.com/influxdata/influxdb v1.8.3 github.com/influxdata/influxdb-client-go/v2 v2.4.0 github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect @@ -77,10 +78,10 @@ require ( golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c - golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 golang.org/x/text v0.3.6 golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba - golang.org/x/tools v0.1.0 + golang.org/x/tools v0.1.5 gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 gopkg.in/urfave/cli.v1 v1.20.0 diff --git a/go.sum b/go.sum index e47c562f49..4f2b39c893 100644 --- a/go.sum +++ b/go.sum @@ -99,8 +99,11 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cloudflare-go v0.14.0 h1:gFqGlGl/5f9UGXAaKapCGUfaTCgRKKnzu2VvzMZlOFA= github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304= @@ -214,6 +217,8 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20220829040838-70bd9ae97f40 h1:ykKxL12NZd3JmWZnyqarJGsF73M9Xhtrik/FEtEeFRE= +github.com/google/pprof v0.0.0-20220829040838-70bd9ae97f40/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I= github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -236,10 +241,11 @@ 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/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/huin/goupnp v1.0.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= -github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= +github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= +github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= 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-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/flux v0.65.1/go.mod h1:J754/zds0vvpfwuq7Gc2wRdVwEodfpCFM7mYlOw2LqY= github.com/influxdata/influxdb v1.8.3 h1:WEypI1BQFTT4teLM+1qkEcvUi0dAvopAI/ir0vAiBg8= @@ -440,6 +446,7 @@ github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPyS github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -513,6 +520,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -565,10 +573,12 @@ golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5PPKjRbXKRa6IBjkzmU= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -612,8 +622,9 @@ golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/graphql/graphql.go b/graphql/graphql.go index 68ac63b5dc..cc3d36235d 100644 --- a/graphql/graphql.go +++ b/graphql/graphql.go @@ -64,6 +64,8 @@ func (b *Long) UnmarshalGraphQL(input interface{}) error { *b = Long(input) case int64: *b = Long(input) + case float64: + *b = Long(input) default: err = fmt.Errorf("unexpected type %T for Long", input) } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index cf2108fcd9..d7c01be1f6 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -35,7 +35,6 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/consensus" - "github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core" @@ -2312,45 +2311,6 @@ func (api *PublicDebugAPI) GetBlockRlp(ctx context.Context, number uint64) (hexu return rlp.EncodeToBytes(block) } -// TestSignCliqueBlock fetches the given block number, and attempts to sign it as a clique header with the -// given address, returning the address of the recovered signature -// -// This is a temporary method to debug the externalsigner integration, -// TODO: Remove this method when the integration is mature -func (api *PublicDebugAPI) TestSignCliqueBlock(ctx context.Context, address common.Address, number uint64) (common.Address, error) { - block, _ := api.b.BlockByNumber(ctx, rpc.BlockNumber(number)) - if block == nil { - return common.Address{}, fmt.Errorf("block #%d not found", number) - } - header := block.Header() - header.Extra = make([]byte, 32+65) - encoded := clique.CliqueRLP(header) - - // Look up the wallet containing the requested signer - account := accounts.Account{Address: address} - wallet, err := api.b.AccountManager().Find(account) - if err != nil { - return common.Address{}, err - } - - signature, err := wallet.SignData(account, accounts.MimetypeClique, encoded) - if err != nil { - return common.Address{}, err - } - sealHash := clique.SealHash(header).Bytes() - log.Info("test signing of clique block", - "Sealhash", fmt.Sprintf("%x", sealHash), - "signature", fmt.Sprintf("%x", signature)) - pubkey, err := crypto.Ecrecover(sealHash, signature) - if err != nil { - return common.Address{}, err - } - var signer common.Address - copy(signer[:], crypto.Keccak256(pubkey[1:])[12:]) - - return signer, nil -} - // PrintBlock retrieves a block and returns its pretty printed form. func (api *PublicDebugAPI) PrintBlock(ctx context.Context, number uint64) (string, error) { block, _ := api.b.BlockByNumber(ctx, rpc.BlockNumber(number)) diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index 6a36460022..b3853a99f8 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -233,12 +233,6 @@ web3._extend({ call: 'debug_getBlockRlp', params: 1 }), - new web3._extend.Method({ - name: 'testSignCliqueBlock', - call: 'debug_testSignCliqueBlock', - params: 2, - inputFormatter: [web3._extend.formatters.inputAddressFormatter, null], - }), new web3._extend.Method({ name: 'setHead', call: 'debug_setHead', diff --git a/les/fetcher.go b/les/fetcher.go index bfe3aa16ec..cf62c8f707 100644 --- a/les/fetcher.go +++ b/les/fetcher.go @@ -441,6 +441,14 @@ func (f *lightFetcher) mainloop() { if ulc { head := f.chain.CurrentHeader() ancestor := rawdb.FindCommonAncestor(f.chaindb, origin, head) + + // Recap the ancestor with genesis header in case the ancestor + // is not found. It can happen the original head is before the + // checkpoint while the synced headers are after it. In this + // case there is no ancestor between them. + if ancestor == nil { + ancestor = f.chain.Genesis().Header() + } var untrusted []common.Hash for head.Number.Cmp(ancestor.Number) > 0 { hash, number := head.Hash(), head.Number.Uint64() @@ -449,6 +457,9 @@ func (f *lightFetcher) mainloop() { } untrusted = append(untrusted, hash) head = f.chain.GetHeader(head.ParentHash, number-1) + if head == nil { + break // all the synced headers will be dropped + } } if len(untrusted) > 0 { for i, j := 0, len(untrusted)-1; i < j; i, j = i+1, j-1 { @@ -514,7 +525,7 @@ func (f *lightFetcher) requestHeaderByHash(peerid enode.ID) func(common.Hash) er } } -// requestResync invokes synchronisation callback to start syncing. +// startSync invokes synchronisation callback to start syncing. func (f *lightFetcher) startSync(id enode.ID) { defer func(header *types.Header) { f.syncDone <- header diff --git a/les/fetcher_test.go b/les/fetcher_test.go index a922ab0f83..8d402393df 100644 --- a/les/fetcher_test.go +++ b/les/fetcher_test.go @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/params" ) @@ -152,6 +153,7 @@ func TestTrustedAnnouncementsLes2(t *testing.T) { testTrustedAnnouncement(t, 2) func TestTrustedAnnouncementsLes3(t *testing.T) { testTrustedAnnouncement(t, 3) } func testTrustedAnnouncement(t *testing.T, protocol int) { + //log.Root().SetHandler(log.LvlFilterHandler(log.LvlDebug, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) var ( servers []*testServer teardowns []func() @@ -159,16 +161,28 @@ func testTrustedAnnouncement(t *testing.T, protocol int) { ids []string cpeers []*clientPeer speers []*serverPeer + + config = light.TestServerIndexerConfig + waitIndexers = func(cIndexer, bIndexer, btIndexer *core.ChainIndexer) { + for { + cs, _, _ := cIndexer.Sections() + bts, _, _ := btIndexer.Sections() + if cs >= 2 && bts >= 2 { + break + } + time.Sleep(10 * time.Millisecond) + } + } ) - for i := 0; i < 10; i++ { - s, n, teardown := newTestServerPeer(t, 10, protocol) + for i := 0; i < 4; i++ { + s, n, teardown := newTestServerPeer(t, int(2*config.ChtSize+config.ChtConfirms), protocol, waitIndexers) servers = append(servers, s) nodes = append(nodes, n) teardowns = append(teardowns, teardown) // A half of them are trusted servers. - if i < 5 { + if i < 2 { ids = append(ids, n.String()) } } @@ -185,6 +199,18 @@ func testTrustedAnnouncement(t *testing.T, protocol int) { teardowns[i]() } }() + + // Register the assembled checkpoint as hardcoded one. + head := servers[0].chtIndexer.SectionHead(0) + cp := ¶ms.TrustedCheckpoint{ + SectionIndex: 0, + SectionHead: head, + CHTRoot: light.GetChtRoot(servers[0].db, 0, head), + BloomRoot: light.GetBloomTrieRoot(servers[0].db, 0, head), + } + c.handler.checkpoint = cp + c.handler.backend.blockchain.AddTrustedCheckpoint(cp) + // Connect all server instances. for i := 0; i < len(servers); i++ { sp, cp, err := connect(servers[i].handler, nodes[i].ID(), c.handler, protocol, true) @@ -218,9 +244,9 @@ func testTrustedAnnouncement(t *testing.T, protocol int) { } verifyChainHeight(t, c.handler.fetcher, expected) } - check([]uint64{1}, 1, func() { <-newHead }) // Sequential announcements - check([]uint64{4}, 4, func() { <-newHead }) // ULC-style light syncing, rollback untrusted headers - check([]uint64{10}, 10, func() { <-newHead }) // Sync the whole chain. + check([]uint64{1}, 1, func() { <-newHead }) // Sequential announcements + check([]uint64{config.ChtSize + config.ChtConfirms}, config.ChtSize+config.ChtConfirms, func() { <-newHead }) // ULC-style light syncing, rollback untrusted headers + check([]uint64{2*config.ChtSize + config.ChtConfirms}, 2*config.ChtSize+config.ChtConfirms, func() { <-newHead }) // Sync the whole chain. } func TestInvalidAnnouncesLES2(t *testing.T) { testInvalidAnnounces(t, lpv2) } diff --git a/les/ulc_test.go b/les/ulc_test.go index ecef58d979..a4df0795b4 100644 --- a/les/ulc_test.go +++ b/les/ulc_test.go @@ -55,7 +55,7 @@ func testULCAnnounceThreshold(t *testing.T, protocol int) { ids []string ) for i := 0; i < len(testcase.height); i++ { - s, n, teardown := newTestServerPeer(t, 0, protocol) + s, n, teardown := newTestServerPeer(t, 0, protocol, nil) servers = append(servers, s) nodes = append(nodes, n) @@ -132,10 +132,11 @@ func connect(server *serverHandler, serverId enode.ID, client *clientHandler, pr } // newTestServerPeer creates server peer. -func newTestServerPeer(t *testing.T, blocks int, protocol int) (*testServer, *enode.Node, func()) { +func newTestServerPeer(t *testing.T, blocks int, protocol int, indexFn indexerCallback) (*testServer, *enode.Node, func()) { netconfig := testnetConfig{ blocks: blocks, protocol: protocol, + indexFn: indexFn, nopruning: true, } s, _, teardown := newClientServerEnv(t, netconfig) diff --git a/mobile/types.go b/mobile/types.go index d1427ac11d..a224f12ab2 100644 --- a/mobile/types.go +++ b/mobile/types.go @@ -358,7 +358,7 @@ func NewReceiptFromJSON(data string) (*Receipt, error) { // EncodeJSON encodes a transaction receipt into a JSON data dump. func (r *Receipt) EncodeJSON() (string, error) { - data, err := rlp.EncodeToBytes(r.receipt) + data, err := json.Marshal(r.receipt) return string(data), err } diff --git a/node/rpcstack.go b/node/rpcstack.go index 2c55a070b2..30957c46d4 100644 --- a/node/rpcstack.go +++ b/node/rpcstack.go @@ -357,7 +357,7 @@ func (h *httpServer) wsAllowed() bool { // isWebsocket checks the header of an http request for a websocket upgrade request. func isWebsocket(r *http.Request) bool { - return strings.ToLower(r.Header.Get("Upgrade")) == "websocket" && + return strings.EqualFold(r.Header.Get("Upgrade"), "websocket") && strings.Contains(strings.ToLower(r.Header.Get("Connection")), "upgrade") } diff --git a/node/rpcstack_test.go b/node/rpcstack_test.go index f92f0ba396..013ca038c7 100644 --- a/node/rpcstack_test.go +++ b/node/rpcstack_test.go @@ -276,7 +276,7 @@ func rpcRequest(t *testing.T, url string, extraHeaders ...string) *http.Response } for i := 0; i < len(extraHeaders); i += 2 { key, value := extraHeaders[i], extraHeaders[i+1] - if strings.ToLower(key) == "host" { + if strings.EqualFold(key, "host") { req.Host = value } else { req.Header.Set(key, value) diff --git a/p2p/peer_error.go b/p2p/peer_error.go index aad1a65c7a..3028685041 100644 --- a/p2p/peer_error.go +++ b/p2p/peer_error.go @@ -69,7 +69,7 @@ const ( DiscUnexpectedIdentity DiscSelf DiscReadTimeout - DiscSubprotocolError = 0x10 + DiscSubprotocolError = DiscReason(0x10) ) var discReasonToString = [...]string{ diff --git a/p2p/simulations/http.go b/p2p/simulations/http.go index 27ed5b75d2..45c12f7433 100644 --- a/p2p/simulations/http.go +++ b/p2p/simulations/http.go @@ -22,6 +22,7 @@ import ( "context" "encoding/json" "fmt" + "html" "io" "io/ioutil" "net/http" @@ -336,7 +337,7 @@ func (s *Server) StartMocker(w http.ResponseWriter, req *http.Request) { mockerType := req.FormValue("mocker-type") mockerFn := LookupMocker(mockerType) if mockerFn == nil { - http.Error(w, fmt.Sprintf("unknown mocker type %q", mockerType), http.StatusBadRequest) + http.Error(w, fmt.Sprintf("unknown mocker type %q", html.EscapeString(mockerType)), http.StatusBadRequest) return } nodeCount, err := strconv.Atoi(req.FormValue("node-count")) diff --git a/params/version.go b/params/version.go index 9cffddc7d2..57a10226a5 100644 --- a/params/version.go +++ b/params/version.go @@ -23,7 +23,7 @@ import ( const ( VersionMajor = 1 // Major version component of the current release VersionMinor = 1 // Minor version component of the current release - VersionPatch = 13 // Patch version component of the current release + VersionPatch = 14 // Patch version component of the current release VersionMeta = "" // Version metadata to append to the version string ) diff --git a/trie/committer.go b/trie/committer.go index db753e2fa0..221681f2e2 100644 --- a/trie/committer.go +++ b/trie/committer.go @@ -22,8 +22,6 @@ import ( "sync" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "golang.org/x/crypto/sha3" ) // leafChanSize is the size of the leafCh. It's a pretty arbitrary number, to allow @@ -44,8 +42,6 @@ type leaf struct { // By 'some level' of parallelism, it's still the case that all leaves will be // processed sequentially - onleaf will never be called in parallel or out of order. type committer struct { - sha crypto.KeccakState - onleaf LeafCallback leafCh chan *leaf } @@ -53,9 +49,7 @@ type committer struct { // committers live in a global sync.Pool var committerPool = sync.Pool{ New: func() interface{} { - return &committer{ - sha: sha3.NewLegacyKeccak256().(crypto.KeccakState), - } + return &committer{} }, } @@ -236,14 +230,6 @@ func (c *committer) commitLoop(db *Database) { } } -func (c *committer) makeHashNode(data []byte) hashNode { - n := make(hashNode, c.sha.Size()) - c.sha.Reset() - c.sha.Write(data) - c.sha.Read(n) - return n -} - // estimateSize estimates the size of an rlp-encoded node, without actually // rlp-encoding it (zero allocs). This method has been experimentally tried, and with a trie // with 1000 leafs, the only errors above 1% are on small shortnodes, where this