diff --git a/Dockerfile b/Dockerfile index 409ba02b39..df3fa9a9ab 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/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/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..6dd0e7e284 100644 --- a/go.mod +++ b/go.mod @@ -42,7 +42,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 diff --git a/go.sum b/go.sum index e47c562f49..60e0e09946 100644 --- a/go.sum +++ b/go.sum @@ -236,8 +236,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/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/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 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/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