From 8d1aa01c69aba6d5c0d2ce09711f2c1c1aa0cadd Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Thu, 7 Mar 2024 15:24:00 +0900 Subject: [PATCH 1/2] blockchain: add another mapslice duplicate entry case Duplicate entries are currently possible in the following scenario: 1: Add entries to the mapslice. 2: 1st map is full. Move onto the 2nd map. 3: Delete any entry in the first map. 4: Attempt to add an entry in the 2nd map. When attempting (4), the entry should just be overwritten but a duplicate gets added. --- blockchain/utxocache_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/blockchain/utxocache_test.go b/blockchain/utxocache_test.go index 45116655..a66d6dc5 100644 --- a/blockchain/utxocache_test.go +++ b/blockchain/utxocache_test.go @@ -69,6 +69,26 @@ func TestMapSlice(t *testing.T) { t.Fatalf("expected len of %d, got %d", len(m), ms.length()) } + // Delete the first element in the first map. + ms.delete(test.keys[0]) + delete(m, test.keys[0]) + + // Try to insert the last element in the mapslice again. + ms.put(test.keys[len(test.keys)-1], &UtxoEntry{}, 0) + m[test.keys[len(test.keys)-1]] = &UtxoEntry{} + + // Check that the duplicate didn't make it in. + if len(m) != ms.length() { + t.Fatalf("expected len of %d, got %d", len(m), ms.length()) + } + + ms.put(test.keys[0], &UtxoEntry{}, 0) + m[test.keys[0]] = &UtxoEntry{} + + if len(m) != ms.length() { + t.Fatalf("expected len of %d, got %d", len(m), ms.length()) + } + for _, key := range test.keys { expected, found := m[key] if !found { From 059a668e888fd1d9a06d1c53d91117997ca51c4d Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Thu, 7 Mar 2024 15:27:44 +0900 Subject: [PATCH 2/2] blockchain: check all the maps first before adding an entry When attempting to insert an entry to the mapslice, we check all the underlying maps to ensure that the entry doesn't exist. --- blockchain/utxocache.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/blockchain/utxocache.go b/blockchain/utxocache.go index 07dc698a..ebc9dc73 100644 --- a/blockchain/utxocache.go +++ b/blockchain/utxocache.go @@ -99,7 +99,8 @@ func (ms *mapSlice) put(op wire.OutPoint, entry *UtxoEntry, totalEntryMemory uin ms.mtx.Lock() defer ms.mtx.Unlock() - for i, maxNum := range ms.maxEntries { + // Look for the key in the maps. + for i := range ms.maxEntries { m := ms.maps[i] _, found := m[op] if found { @@ -107,6 +108,10 @@ func (ms *mapSlice) put(op wire.OutPoint, entry *UtxoEntry, totalEntryMemory uin m[op] = entry return // Return as we were successful in adding the entry. } + } + + for i, maxNum := range ms.maxEntries { + m := ms.maps[i] if len(m) >= maxNum { // Don't try to insert if the map already at max since // that'll force the map to allocate double the memory it's