From eae228f0d8b23322b259dd525c945c3cd9462a24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Thu, 9 May 2024 10:38:31 +0300 Subject: [PATCH] trie: fix closure error, work around upstream Go issue --- core/state/database.go | 2 +- trie/secure_trie.go | 4 ++-- trie/trie.go | 26 ++++++++++++++++++++++---- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/core/state/database.go b/core/state/database.go index 8b6c4695c8..f02e64df4d 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -98,7 +98,7 @@ type Trie interface { GetStorage(addr common.Address, key []byte) ([]byte, error) // GetStorageBatch is a batched version of GetStorage that simultaneously looks - // up multiple slots. The advantage vs. teh singleton version is the potential + // up multiple slots. The advantage vs. the singleton version is the potential // for concurrent disk lookups. GetStorageBatch(addrs []common.Address, keys [][]byte) ([][]byte, error) diff --git a/trie/secure_trie.go b/trie/secure_trie.go index 04794a4395..af538081c3 100644 --- a/trie/secure_trie.go +++ b/trie/secure_trie.go @@ -101,7 +101,7 @@ func (t *StateTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) { func (t *StateTrie) GetStorageBatch(_ []common.Address, keys [][]byte) ([][]byte, error) { hashes := make([][]byte, len(keys)) for i, key := range keys { - hashes[i] = t.hashKey(key) + hashes[i] = common.CopyBytes(t.hashKey(key)) } encs, err := t.trie.GetBatch(hashes) if err != nil { @@ -138,7 +138,7 @@ func (t *StateTrie) GetAccount(address common.Address) (*types.StateAccount, err func (t *StateTrie) GetAccountBatch(addrs []common.Address) ([]*types.StateAccount, error) { hashes := make([][]byte, len(addrs)) for i, addr := range addrs { - hashes[i] = t.hashKey(addr.Bytes()) + hashes[i] = common.CopyBytes(t.hashKey(addr.Bytes())) } encs, err := t.trie.GetBatch(hashes) if err != nil { diff --git a/trie/trie.go b/trie/trie.go index 217892c766..287196346f 100644 --- a/trie/trie.go +++ b/trie/trie.go @@ -279,10 +279,28 @@ func (t *Trie) getBatch(origNode node, keys [][]byte, pos int) ([][]byte, node, n = n.copy() n.Val = newnode } - values = append(make([][]byte, first), values...) - values = append(values, make([][]byte, len(keys)-last)...) - - return values, n, didResolve, err + if first == 0 && last == len(keys) { + // If all the keys are the same (or there's only 1 key), return the + // result values without padding them on the two sides with nils. + // + // A bit of a weird clause, but this is the default, it is possibly + // insiginificantly faster, and it avoids a rare Go crash prior to + // v1.22.4 per https://github.com/golang/go/issues/67255. + // + // TODO(karalabe): Simplify when Go v1.24.0 is out. + return values, n, didResolve, err + } else { + // Only a subset of the keys are existent in the trie, pad the value + // return slice with nils for the rest. + // + // We could also use append here, but that can potentially hit the + // above Go issue: https://github.com/golang/go/issues/67255. + // + // TODO(karalabe): Simplify when Go v1.24.0 is out. + result := make([][]byte, len(keys)) + copy(result[first:], values) + return result, n, didResolve, err + } case *fullNode: var (