Skip to content

Commit

Permalink
Receipts: Add option to not recover sender and write flags (#7680)
Browse files Browse the repository at this point in the history
  • Loading branch information
asdacap authored Oct 30, 2024
1 parent a1b9a39 commit efe8dba
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Threading;
using System.Threading.Tasks;
using FluentAssertions;
using FluentAssertions.Equivalency;
using Nethermind.Blockchain.Blocks;
using Nethermind.Blockchain.Receipts;
using Nethermind.Core;
Expand All @@ -18,6 +19,7 @@
using Nethermind.Db;
using Nethermind.Serialization.Rlp;
using Nethermind.Specs;
using Nethermind.Specs.Forks;
using NSubstitute;
using NSubstitute.Core;
using NUnit.Framework;
Expand All @@ -29,6 +31,7 @@ namespace Nethermind.Blockchain.Test.Receipts;
[TestFixture(false)]
public class PersistentReceiptStorageTests
{
private TestSpecProvider _specProvider = new TestSpecProvider(Byzantium.Instance);
private TestMemColumnsDb<ReceiptsColumns> _receiptsDb = null!;
private ReceiptsRecovery _receiptsRecovery = null!;
private IBlockTree _blockTree = null!;
Expand All @@ -46,10 +49,9 @@ public PersistentReceiptStorageTests(bool useCompactReceipts)
[SetUp]
public void SetUp()
{
MainnetSpecProvider specProvider = MainnetSpecProvider.Instance;
EthereumEcdsa ethereumEcdsa = new(specProvider.ChainId);
EthereumEcdsa ethereumEcdsa = new(_specProvider.ChainId);
_receiptConfig = new ReceiptConfig();
_receiptsRecovery = new(ethereumEcdsa, specProvider);
_receiptsRecovery = new(ethereumEcdsa, _specProvider);
_receiptsDb = new TestMemColumnsDb<ReceiptsColumns>();
_receiptsDb.GetColumnDb(ReceiptsColumns.Blocks).Set(Keccak.Zero, Array.Empty<byte>());
_blockTree = Substitute.For<IBlockTree>();
Expand All @@ -68,7 +70,7 @@ private void CreateStorage()
_decoder = new ReceiptArrayStorageDecoder(_useCompactReceipts);
_storage = new PersistentReceiptStorage(
_receiptsDb,
MainnetSpecProvider.Instance,
_specProvider,
_receiptsRecovery,
_blockTree,
_blockStore,
Expand Down Expand Up @@ -111,9 +113,10 @@ public void Adds_and_retrieves_receipts_for_block()
{
var (block, receipts) = InsertBlock();

_storage.Get(block).Should().BeEquivalentTo(receipts);
_storage.ClearCache();
_storage.Get(block).Should().BeEquivalentTo(receipts, ReceiptCompareOpt);
// second should be from cache
_storage.Get(block).Should().BeEquivalentTo(receipts);
_storage.Get(block).Should().BeEquivalentTo(receipts, ReceiptCompareOpt);
}

[Test]
Expand All @@ -128,6 +131,38 @@ public void Adds_should_prefix_key_with_blockNumber()
_receiptsDb.GetColumnDb(ReceiptsColumns.Blocks)[blockNumPrefixed].Should().NotBeNull();
}

[Test]
public void Adds_should_forward_write_flags()
{
(Block block, _) = InsertBlock(writeFlags: WriteFlags.DisableWAL);

Span<byte> blockNumPrefixed = stackalloc byte[40];
block.Number.ToBigEndianByteArray().CopyTo(blockNumPrefixed); // TODO: We don't need to create an array here...
block.Hash!.Bytes.CopyTo(blockNumPrefixed[8..]);

TestMemDb blockDb = (TestMemDb)_receiptsDb.GetColumnDb(ReceiptsColumns.Blocks);

blockDb.KeyWasWrittenWithFlags(blockNumPrefixed.ToArray(), WriteFlags.DisableWAL);
}

[Test, MaxTime(Timeout.MaxTestTime)]
public void Get_receipts_for_block_without_recovering_sender()
{
var (block, receipts) = InsertBlock();
foreach (Transaction tx in block.Transactions)
{
tx.SenderAddress = null;
}

_storage.ClearCache();
_storage.Get(block, recoverSender: false).Should().BeEquivalentTo(receipts, ReceiptCompareOpt);

foreach (Transaction tx in block.Transactions)
{
tx.SenderAddress.Should().BeNull();
}
}

[Test]
public void Adds_should_attempt_hash_key_first_if_inserted_with_hashkey()
{
Expand Down Expand Up @@ -455,12 +490,18 @@ public void When_NewHeadBlock_ClearOldTxIndex()
return (block, receipts);
}

private (Block block, TxReceipt[] receipts) InsertBlock(Block? block = null, bool isFinalized = false, long? headNumber = null)
private (Block block, TxReceipt[] receipts) InsertBlock(Block? block = null, bool isFinalized = false, long? headNumber = null, WriteFlags writeFlags = WriteFlags.None)
{
(block, TxReceipt[] receipts) = PrepareBlock(block, isFinalized, headNumber);
_storage.Insert(block, receipts);
_storage.Insert(block, receipts, writeFlags: writeFlags);
_receiptsRecovery.TryRecover(new ReceiptRecoveryBlock(block), receipts);

return (block, receipts);
}

private EquivalencyAssertionOptions<TxReceipt> ReceiptCompareOpt(EquivalencyAssertionOptions<TxReceipt> opts)
{
return opts
.Excluding(su => su.Error);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ public FullInfoReceiptFinder(IReceiptStorage receiptStorage, IReceiptsRecovery r

public Hash256 FindBlockHash(Hash256 txHash) => _receiptStorage.FindBlockHash(txHash);

public TxReceipt[] Get(Block block, bool recover = true)
public TxReceipt[] Get(Block block, bool recover = true, bool recoverSender = true)
{
var receipts = _receiptStorage.Get(block);
if (recover && _receiptsRecovery.TryRecover(block, receipts) == ReceiptsRecoveryResult.NeedReinsert)
if (recover && _receiptsRecovery.TryRecover(block, receipts, recoverSender) == ReceiptsRecoveryResult.NeedReinsert)
{
_receiptStorage.Insert(block, receipts);
}
Expand All @@ -41,7 +41,7 @@ public TxReceipt[] Get(Hash256 blockHash, bool recover = true)
if (recover && _receiptsRecovery.NeedRecover(receipts))
{
var block = _blockFinder.FindBlock(blockHash, BlockTreeLookupOptions.TotalDifficultyNotNeeded);
if (_receiptsRecovery.TryRecover(block, receipts) == ReceiptsRecoveryResult.NeedReinsert)
if (_receiptsRecovery.TryRecover(block, receipts, forceRecoverSender: false) == ReceiptsRecoveryResult.NeedReinsert)
{
_receiptStorage.Insert(block, receipts);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Nethermind.Blockchain.Receipts
public interface IReceiptFinder
{
Hash256? FindBlockHash(Hash256 txHash);
TxReceipt[] Get(Block block, bool recover = true);
TxReceipt[] Get(Block block, bool recover = true, bool recoverSender = true);
TxReceipt[] Get(Hash256 blockHash, bool recover = true);
bool CanGetReceiptsByHash(long blockNumber);
bool TryGetReceiptsIterator(long blockNumber, Hash256 blockHash, out ReceiptsIterator iterator);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Nethermind.Blockchain.Receipts
public interface IReceiptStorage : IReceiptFinder
{
void Insert(Block block, params TxReceipt[]? txReceipts) => Insert(block, txReceipts, true);
void Insert(Block block, TxReceipt[]? txReceipts, bool ensureCanonical);
void Insert(Block block, TxReceipt[]? txReceipts, bool ensureCanonical, WriteFlags writeFlags = WriteFlags.None);
long? LowestInsertedReceiptBlockNumber { get; set; }
long MigratedBlockNumber { get; set; }
bool HasBlock(long blockNumber, Hash256 hash);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public Hash256 FindBlockHash(Hash256 txHash)
return receipt?.BlockHash;
}

public TxReceipt[] Get(Block block, bool recover = true) => Get(block.Hash);
public TxReceipt[] Get(Block block, bool recover = true, bool recoverSender = true) => Get(block.Hash);

public TxReceipt[] Get(Hash256 blockHash, bool recover = true) =>
_receipts.TryGetValue(blockHash, out TxReceipt[] receipts) ? receipts : Array.Empty<TxReceipt>();
Expand All @@ -62,7 +62,7 @@ public bool TryGetReceiptsIterator(long blockNumber, Hash256 blockHash, out Rece
}
}

public void Insert(Block block, TxReceipt[] txReceipts, bool ensureCanonical = true)
public void Insert(Block block, TxReceipt[] txReceipts, bool ensureCanonical = true, WriteFlags writeFlags = WriteFlags.None)
{
_receipts[block.Hash] = txReceipts;
if (ensureCanonical)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ private NullReceiptStorage()
{
}

public void Insert(Block block, TxReceipt[] txReceipts, bool ensureCanonical) { }
public void Insert(Block block, TxReceipt[] txReceipts, bool ensureCanonical, WriteFlags writeFlags) { }

public TxReceipt[] Get(Block block, bool recover = true) => Array.Empty<TxReceipt>();
public TxReceipt[] Get(Block block, bool recover = true, bool recoverSender = false) => Array.Empty<TxReceipt>();
public TxReceipt[] Get(Hash256 blockHash, bool recover = true) => Array.Empty<TxReceipt>();
public bool CanGetReceiptsByHash(long blockNumber) => true;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ private TxReceipt DeserializeReceiptObsolete(Hash256 hash, Span<byte> receiptDat
return null;
}

public TxReceipt[] Get(Block block, bool recover = true)
public TxReceipt[] Get(Block block, bool recover = true, bool recoverSender = true)
{
if (block.ReceiptsRoot == Keccak.EmptyTreeHash)
{
Expand All @@ -164,7 +164,7 @@ public TxReceipt[] Get(Block block, bool recover = true)

if (recover)
{
_receiptsRecovery.TryRecover(block, receipts);
_receiptsRecovery.TryRecover(block, receipts, forceRecoverSender: recoverSender);
_receiptsCache.Set(blockHash, receipts);
}

Expand Down Expand Up @@ -223,7 +223,7 @@ public TxReceipt[] Get(Hash256 blockHash, bool recover = true)
{
Block? block = _blockTree.FindBlock(blockHash);
if (block is null) return Array.Empty<TxReceipt>();
return Get(block, recover);
return Get(block, recover, false);
}

public bool CanGetReceiptsByHash(long blockNumber) => blockNumber >= MigratedBlockNumber;
Expand Down Expand Up @@ -263,7 +263,7 @@ public bool TryGetReceiptsIterator(long blockNumber, Hash256 blockHash, out Rece
}

[SkipLocalsInit]
public void Insert(Block block, TxReceipt[]? txReceipts, bool ensureCanonical = true)
public void Insert(Block block, TxReceipt[]? txReceipts, bool ensureCanonical = true, WriteFlags writeFlags = WriteFlags.None)
{
txReceipts ??= Array.Empty<TxReceipt>();
int txReceiptsLength = txReceipts.Length;
Expand All @@ -286,7 +286,7 @@ public void Insert(Block block, TxReceipt[]? txReceipts, bool ensureCanonical =
Span<byte> blockNumPrefixed = stackalloc byte[40];
GetBlockNumPrefixedKey(blockNumber, block.Hash!, blockNumPrefixed);

_blocksDb.PutSpan(blockNumPrefixed, stream.AsSpan());
_blocksDb.PutSpan(blockNumPrefixed, stream.AsSpan(), writeFlags);
}

if (blockNumber < MigratedBlockNumber)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,14 @@ public TestReceiptStorage(IReceiptStorage inStorage, IReceiptStorage outStorage)

public Hash256 FindBlockHash(Hash256 txHash) => _inStorage.FindBlockHash(txHash);

public TxReceipt[] Get(Block block, bool recover = true) => _inStorage.Get(block, recover);
public TxReceipt[] Get(Block block, bool recover = true, bool recoverSender = true) => _inStorage.Get(block, recover, recoverSender);

public TxReceipt[] Get(Hash256 blockHash, bool recover = true) => _inStorage.Get(blockHash, recover);

public bool CanGetReceiptsByHash(long blockNumber) => _inStorage.CanGetReceiptsByHash(blockNumber);
public bool TryGetReceiptsIterator(long blockNumber, Hash256 blockHash, out ReceiptsIterator iterator) => _inStorage.TryGetReceiptsIterator(blockNumber, blockHash, out iterator);

public void Insert(Block block, TxReceipt[] txReceipts, bool ensureCanonical) => _outStorage.Insert(block, txReceipts);
public void Insert(Block block, TxReceipt[] txReceipts, bool ensureCanonical, WriteFlags writeFlags) => _outStorage.Insert(block, txReceipts, ensureCanonical, writeFlags);

public long? LowestInsertedReceiptBlockNumber
{
Expand Down

0 comments on commit efe8dba

Please sign in to comment.