@@ -5892,3 +5892,98 @@ func TestSplitReceiptsAndDeriveFields(t *testing.T) {
58925892 require .Equal (t , rlp .RawValue (stateSyncEncoded ), stateSync , fmt .Sprintf ("case: %s, state-sync receipts mismatch, got: %v, expected: %v" , test .name , stateSync , stateSyncEncoded ))
58935893 }
58945894}
5895+
5896+ // TestWitnessCache tests the witness caching functionality to ensure witnesses
5897+ // are properly cached during writes and retrieved from cache during reads.
5898+ func TestWitnessCache (t * testing.T ) {
5899+ // Setup: Create a test blockchain
5900+ engine := ethash .NewFaker ()
5901+ gspec := & Genesis {
5902+ Config : params .TestChainConfig ,
5903+ }
5904+ cfg := DefaultConfig ()
5905+ chain , err := NewBlockChain (rawdb .NewMemoryDatabase (), gspec , engine , cfg )
5906+ if err != nil {
5907+ t .Fatalf ("failed to create blockchain: %v" , err )
5908+ }
5909+ defer chain .Stop ()
5910+
5911+ // Create test witness data
5912+ testHash := common .HexToHash ("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" )
5913+ testWitness1 := []byte ("test witness data 1" )
5914+ testWitness2 := []byte ("test witness data 2 - different" )
5915+
5916+ // Test 1: Write witness and verify it's cached
5917+ rawdb .WriteWitness (chain .db , testHash , testWitness1 )
5918+ // Manually add to cache to simulate what happens during block import
5919+ chain .witnessCache .Add (testHash , testWitness1 )
5920+
5921+ // Verify witness can be retrieved from cache
5922+ retrieved := chain .GetWitness (testHash )
5923+ require .NotNil (t , retrieved , "witness should be retrieved" )
5924+ require .Equal (t , testWitness1 , retrieved , "retrieved witness should match written witness" )
5925+
5926+ // Test 2: Verify cache hit (witness should be in cache, not read from DB)
5927+ // We can verify this by checking the cache directly
5928+ cached , ok := chain .witnessCache .Get (testHash )
5929+ require .True (t , ok , "witness should be in cache" )
5930+ require .Equal (t , testWitness1 , cached , "cached witness should match" )
5931+
5932+ // Test 3: Update witness in cache and verify GetWitness returns cached version
5933+ chain .witnessCache .Add (testHash , testWitness2 )
5934+ retrieved = chain .GetWitness (testHash )
5935+ require .Equal (t , testWitness2 , retrieved , "GetWitness should return cached version" )
5936+
5937+ // Test 4: Test cache miss - witness not in cache but in DB
5938+ testHash2 := common .HexToHash ("0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890" )
5939+ testWitness3 := []byte ("test witness data 3" )
5940+ rawdb .WriteWitness (chain .db , testHash2 , testWitness3 )
5941+ // Don't add to cache - simulate cache miss
5942+
5943+ // GetWitness should read from DB and cache it
5944+ retrieved = chain .GetWitness (testHash2 )
5945+ require .NotNil (t , retrieved , "witness should be retrieved from DB" )
5946+ require .Equal (t , testWitness3 , retrieved , "retrieved witness should match DB witness" )
5947+
5948+ // Verify it's now in cache
5949+ cached , ok = chain .witnessCache .Get (testHash2 )
5950+ require .True (t , ok , "witness should be cached after GetWitness" )
5951+ require .Equal (t , testWitness3 , cached , "cached witness should match" )
5952+
5953+ // Test 5: Test non-existent witness
5954+ nonExistentHash := common .HexToHash ("0x0000000000000000000000000000000000000000000000000000000000000000" )
5955+ retrieved = chain .GetWitness (nonExistentHash )
5956+ require .Nil (t , retrieved , "non-existent witness should return nil" )
5957+
5958+ // Test 6: Test cache purge
5959+ chain .witnessCache .Purge ()
5960+ _ , ok = chain .witnessCache .Get (testHash )
5961+ require .False (t , ok , "witness should not be in cache after purge" )
5962+ _ , ok = chain .witnessCache .Get (testHash2 )
5963+ require .False (t , ok , "witness should not be in cache after purge" )
5964+
5965+ // After purge, GetWitness should still work by reading from DB
5966+ retrieved = chain .GetWitness (testHash2 )
5967+ require .NotNil (t , retrieved , "witness should still be retrievable from DB after cache purge" )
5968+ require .Equal (t , testWitness3 , retrieved , "retrieved witness should match DB witness" )
5969+
5970+ // Test 7: Test that witness is cached during block import
5971+ // Create a block and witness, then import it
5972+ testChain , testBlock , testWitness := createTestBlockAndWitness (t )
5973+ defer testChain .Stop ()
5974+
5975+ // Import the block with witness - this should cache the witness
5976+ blockHash := testBlock .Hash ()
5977+ _ , err = testChain .InsertChainStateless (types.Blocks {testBlock }, []* stateless.Witness {testWitness })
5978+ require .NoError (t , err , "block import should succeed" )
5979+
5980+ // Verify witness is in cache after import
5981+ cached , ok = testChain .witnessCache .Get (blockHash )
5982+ require .True (t , ok , "witness should be cached after block import" )
5983+ require .NotNil (t , cached , "cached witness should not be nil" )
5984+
5985+ // Verify GetWitness retrieves from cache
5986+ retrieved = testChain .GetWitness (blockHash )
5987+ require .NotNil (t , retrieved , "witness should be retrievable after import" )
5988+ require .Equal (t , cached , retrieved , "GetWitness should return cached witness" )
5989+ }
0 commit comments