From 2a79ac162237bec8923b8703d7e71340360ee3eb Mon Sep 17 00:00:00 2001 From: Slava Karpenko Date: Wed, 11 Nov 2020 21:13:12 +0100 Subject: [PATCH 1/8] consensus/ethash: use 64bit indexes for the DAG generation (#21793) * Bit boundary fix for the DAG generation routine * Fix unnecessary conversion warnings Co-authored-by: Sergey Pavlov --- consensus/ethash/algorithm.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/consensus/ethash/algorithm.go b/consensus/ethash/algorithm.go index d6c871092e..eb94d136b9 100644 --- a/consensus/ethash/algorithm.go +++ b/consensus/ethash/algorithm.go @@ -304,16 +304,16 @@ func generateDataset(dest []uint32, epoch uint64, cache []uint32) { keccak512 := makeHasher(sha3.NewLegacyKeccak512()) // Calculate the data segment this thread should generate - batch := uint32((size + hashBytes*uint64(threads) - 1) / (hashBytes * uint64(threads))) - first := uint32(id) * batch + batch := (size + hashBytes*uint64(threads) - 1) / (hashBytes * uint64(threads)) + first := uint64(id) * batch limit := first + batch - if limit > uint32(size/hashBytes) { - limit = uint32(size / hashBytes) + if limit > size/hashBytes { + limit = size / hashBytes } // Calculate the dataset segment percent := uint32(size / hashBytes / 100) for index := first; index < limit; index++ { - item := generateDatasetItem(cache, index, keccak512) + item := generateDatasetItem(cache, uint32(index), keccak512) if swapped { swap(item) } From 0a64615f1e17a8c36cca5302da24dfc804ffbe2b Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Tue, 28 Jul 2020 11:47:05 +0200 Subject: [PATCH 2/8] signer/storage: fix a badly ordered error check (#21379) --- cmd/clef/docs/setup.md | 2 +- signer/storage/aes_gcm_storage.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/clef/docs/setup.md b/cmd/clef/docs/setup.md index a25f87ce64..cbdd8808d3 100644 --- a/cmd/clef/docs/setup.md +++ b/cmd/clef/docs/setup.md @@ -94,7 +94,7 @@ with minimal requirements. On the `client` qube, we need to create a listener which will receive the request from the Dapp, and proxy it. -[qubes-client.py](qubes/client/qubes-client.py): +[qubes-client.py](qubes/qubes-client.py): ```python diff --git a/signer/storage/aes_gcm_storage.go b/signer/storage/aes_gcm_storage.go index 8c5e147ac6..1dad34a3eb 100644 --- a/signer/storage/aes_gcm_storage.go +++ b/signer/storage/aes_gcm_storage.go @@ -151,11 +151,11 @@ func encrypt(key []byte, plaintext []byte, additionalData []byte) ([]byte, []byt return nil, nil, err } aesgcm, err := cipher.NewGCM(block) - nonce := make([]byte, aesgcm.NonceSize()) - if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + if err != nil { return nil, nil, err } - if err != nil { + nonce := make([]byte, aesgcm.NonceSize()) + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { return nil, nil, err } ciphertext := aesgcm.Seal(nil, nonce, plaintext, additionalData) From ad3ff6452d9e05db73920092b52bce9461a6c160 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 9 Oct 2020 11:23:46 +0200 Subject: [PATCH 3/8] core: fix txpool off-by-one error (#21683) --- core/tx_pool.go | 1 + 1 file changed, 1 insertion(+) diff --git a/core/tx_pool.go b/core/tx_pool.go index e4e3c41cee..f35e1d8d7c 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -814,6 +814,7 @@ func (pool *TxPool) addTxs(txs []*types.Transaction, local, sync bool) []error { nilSlot++ } errs[nilSlot] = err + nilSlot++ } // Reorg the pool internals if needed and return done := pool.requestPromoteExecutables(dirtyAddrs) From d1f95d5fd32510b92b3075e26c6aa8cb3923f8dc Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Wed, 23 Sep 2020 13:08:40 +0200 Subject: [PATCH 4/8] internal/ethapi: fix nil deref + fix estimateGas console bindings (#21601) * tried to fix * fix for js api * fix for nil pointer ex * rev space * rev space * input call formatter --- internal/ethapi/api.go | 3 +++ internal/web3ext/web3ext.go | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index b0641c2515..f3dcad0ed9 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -900,6 +900,9 @@ func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNrOrHash if err != nil { return 0, err } + if block == nil { + return 0, errors.New("block not found") + } hi = block.GasLimit() } // Recap the highest gas limit with account's available balance. diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index 4d85f0597d..c978667715 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -493,6 +493,13 @@ web3._extend({ params: 1, inputFormatter: [web3._extend.formatters.inputTransactionFormatter] }), + new web3._extend.Method({ + name: 'estimateGas', + call: 'eth_estimateGas', + params: 2, + inputFormatter: [web3._extend.formatters.inputCallFormatter, web3._extend.formatters.inputBlockNumberFormatter], + outputFormatter: web3._extend.utils.toDecimal + }), new web3._extend.Method({ name: 'submitTransaction', call: 'eth_submitTransaction', From 4608da6c13621b00a2c84b2d237744610df0ae76 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Fri, 28 Aug 2020 16:27:58 +0200 Subject: [PATCH 5/8] rpc: fix issue with null JSON-RPC messages (#21497) --- rpc/json.go | 13 ++++++++++--- rpc/testdata/invalid-batch.js | 3 +++ rpc/testdata/invalid-nonobj.js | 3 +++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/rpc/json.go b/rpc/json.go index 61631a3d76..f0250fa4a5 100644 --- a/rpc/json.go +++ b/rpc/json.go @@ -194,15 +194,22 @@ func (c *jsonCodec) remoteAddr() string { return c.remote } -func (c *jsonCodec) readBatch() (msg []*jsonrpcMessage, batch bool, err error) { +func (c *jsonCodec) readBatch() (messages []*jsonrpcMessage, batch bool, err error) { // Decode the next JSON object in the input stream. // This verifies basic syntax, etc. var rawmsg json.RawMessage if err := c.decode(&rawmsg); err != nil { return nil, false, err } - msg, batch = parseMessage(rawmsg) - return msg, batch, nil + messages, batch = parseMessage(rawmsg) + for i, msg := range messages { + if msg == nil { + // Message is JSON 'null'. Replace with zero value so it + // will be treated like any other invalid message. + messages[i] = new(jsonrpcMessage) + } + } + return messages, batch, nil } func (c *jsonCodec) writeJSON(ctx context.Context, v interface{}) error { diff --git a/rpc/testdata/invalid-batch.js b/rpc/testdata/invalid-batch.js index f470574fb5..768dbc837e 100644 --- a/rpc/testdata/invalid-batch.js +++ b/rpc/testdata/invalid-batch.js @@ -10,5 +10,8 @@ --> [1,2,3] <-- [{"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"invalid request"}},{"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"invalid request"}},{"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"invalid request"}}] +--> [null] +<-- [{"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"invalid request"}}] + --> [{"jsonrpc":"2.0","id":1,"method":"test_echo","params":["foo",1]},55,{"jsonrpc":"2.0","id":2,"method":"unknown_method"},{"foo":"bar"}] <-- [{"jsonrpc":"2.0","id":1,"result":{"String":"foo","Int":1,"Args":null}},{"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"invalid request"}},{"jsonrpc":"2.0","id":2,"error":{"code":-32601,"message":"the method unknown_method does not exist/is not available"}},{"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"invalid request"}}] diff --git a/rpc/testdata/invalid-nonobj.js b/rpc/testdata/invalid-nonobj.js index 4b9f4d994c..ffdd4a5b87 100644 --- a/rpc/testdata/invalid-nonobj.js +++ b/rpc/testdata/invalid-nonobj.js @@ -2,3 +2,6 @@ --> 1 <-- {"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"invalid request"}} + +--> null +<-- {"jsonrpc":"2.0","id":null,"error":{"code":-32600,"message":"invalid request"}} From 670009d1e17b6df4d226499005bdc5cb937bf185 Mon Sep 17 00:00:00 2001 From: Fuyang Deng Date: Tue, 1 Sep 2020 15:29:54 +0800 Subject: [PATCH 6/8] accounts/abi: fix a bug in getTypeSize method (#21501) * accounts/abi: fix a bug in getTypeSize method e.g. for "Tuple[2]" type, the element of the array is a tuple type and the size of the tuple may not be 32. * accounts/abi: add unit test of getTypeSize method --- accounts/abi/type.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accounts/abi/type.go b/accounts/abi/type.go index 4792283ee8..baa29dd267 100644 --- a/accounts/abi/type.go +++ b/accounts/abi/type.go @@ -350,7 +350,7 @@ func isDynamicType(t Type) bool { func getTypeSize(t Type) int { if t.T == ArrayTy && !isDynamicType(*t.Elem) { // Recursively calculate type size if it is a nested array - if t.Elem.T == ArrayTy { + if t.Elem.T == ArrayTy || t.Elem.T == TupleTy { return t.Size * getTypeSize(*t.Elem) } return t.Size * 32 From ca1d1cb08dc6ac41f42a9bc935db539ddf3b8b8d Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 9 Dec 2020 20:21:31 +0100 Subject: [PATCH 7/8] p2p/enode: avoid crashing for invalid IP (#21981) The database panicked for invalid IPs. This is usually no problem because all code paths leading to node DB access verify the IP, but it's dangerous because improper validation can turn this panic into a DoS vulnerability. The quick fix here is to just turn database accesses using invalid IP into a noop. This isn't great, but I'm planning to remove the node DB for discv5 long-term, so it should be fine to have this quick fix for half a year. Fixes #21849 --- p2p/enode/nodedb.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/p2p/enode/nodedb.go b/p2p/enode/nodedb.go index bd066ce857..08a0511494 100644 --- a/p2p/enode/nodedb.go +++ b/p2p/enode/nodedb.go @@ -61,6 +61,10 @@ const ( dbVersion = 9 ) +var ( + errInvalidIP = errors.New("invalid IP") +) + var zeroIP = make(net.IP, 16) // DB is the node database, storing previously seen nodes and any collected metadata about @@ -359,16 +363,25 @@ func (db *DB) expireNodes() { // LastPingReceived retrieves the time of the last ping packet received from // a remote node. func (db *DB) LastPingReceived(id ID, ip net.IP) time.Time { + if ip = ip.To16(); ip == nil { + return time.Time{} + } return time.Unix(db.fetchInt64(nodeItemKey(id, ip, dbNodePing)), 0) } // UpdateLastPingReceived updates the last time we tried contacting a remote node. func (db *DB) UpdateLastPingReceived(id ID, ip net.IP, instance time.Time) error { + if ip = ip.To16(); ip == nil { + return errInvalidIP + } return db.storeInt64(nodeItemKey(id, ip, dbNodePing), instance.Unix()) } // LastPongReceived retrieves the time of the last successful pong from remote node. func (db *DB) LastPongReceived(id ID, ip net.IP) time.Time { + if ip = ip.To16(); ip == nil { + return time.Time{} + } // Launch expirer db.ensureExpirer() return time.Unix(db.fetchInt64(nodeItemKey(id, ip, dbNodePong)), 0) @@ -376,26 +389,41 @@ func (db *DB) LastPongReceived(id ID, ip net.IP) time.Time { // UpdateLastPongReceived updates the last pong time of a node. func (db *DB) UpdateLastPongReceived(id ID, ip net.IP, instance time.Time) error { + if ip = ip.To16(); ip == nil { + return errInvalidIP + } return db.storeInt64(nodeItemKey(id, ip, dbNodePong), instance.Unix()) } // FindFails retrieves the number of findnode failures since bonding. func (db *DB) FindFails(id ID, ip net.IP) int { + if ip = ip.To16(); ip == nil { + return 0 + } return int(db.fetchInt64(nodeItemKey(id, ip, dbNodeFindFails))) } // UpdateFindFails updates the number of findnode failures since bonding. func (db *DB) UpdateFindFails(id ID, ip net.IP, fails int) error { + if ip = ip.To16(); ip == nil { + return errInvalidIP + } return db.storeInt64(nodeItemKey(id, ip, dbNodeFindFails), int64(fails)) } // FindFailsV5 retrieves the discv5 findnode failure counter. func (db *DB) FindFailsV5(id ID, ip net.IP) int { + if ip = ip.To16(); ip == nil { + return 0 + } return int(db.fetchInt64(v5Key(id, ip, dbNodeFindFails))) } // UpdateFindFailsV5 stores the discv5 findnode failure counter. func (db *DB) UpdateFindFailsV5(id ID, ip net.IP, fails int) error { + if ip = ip.To16(); ip == nil { + return errInvalidIP + } return db.storeInt64(v5Key(id, ip, dbNodeFindFails), int64(fails)) } From 9e8ee517d71a8fdf4a5c8236e5f7c0200c6df561 Mon Sep 17 00:00:00 2001 From: Nishant Das Date: Thu, 26 Nov 2020 05:16:36 +0800 Subject: [PATCH 8/8] p2p/discover: fix deadlock in discv5 message dispatch (#21858) This fixes a deadlock that could occur when a response packet arrived after a call had already received enough responses and was about to signal completion to the dispatch loop. Co-authored-by: Felix Lange --- p2p/discover/v5_udp.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/p2p/discover/v5_udp.go b/p2p/discover/v5_udp.go index e667be1690..65550fc65f 100644 --- a/p2p/discover/v5_udp.go +++ b/p2p/discover/v5_udp.go @@ -419,9 +419,20 @@ func (t *UDPv5) call(node *enode.Node, responseType byte, packet packetV5) *call // callDone tells dispatch that the active call is done. func (t *UDPv5) callDone(c *callV5) { - select { - case t.callDoneCh <- c: - case <-t.closeCtx.Done(): + // This needs a loop because further responses may be incoming until the + // send to callDoneCh has completed. Such responses need to be discarded + // in order to avoid blocking the dispatch loop. + for { + select { + case <-c.ch: + // late response, discard. + case <-c.err: + // late error, discard. + case t.callDoneCh <- c: + return + case <-t.closeCtx.Done(): + return + } } }