Skip to content

Commit

Permalink
Merge pull request #96 from NethermindEth/merkle-foundations
Browse files Browse the repository at this point in the history
Merkle foundations with pre-commit hook
  • Loading branch information
emlautarom1 committed Jun 19, 2023
2 parents 3368caf + b7d7ecb commit 8f38acd
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/Paprika.Runner/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public static async Task Main(String[] args)
ctx.Refresh();
}));

await using (var blockchain = new Blockchain(db, FlushEvery, 1000, reporter.Observe))
await using (var blockchain = new Blockchain(db, null, FlushEvery, 1000, reporter.Observe))
{
counter = Writer(blockchain, bigStorageAccount, random, layout[writing]);
}
Expand Down
15 changes: 12 additions & 3 deletions src/Paprika/Chain/Blockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public class Blockchain : IAsyncDisposable
private readonly MetricsExtensions.IAtomicIntGauge _flusherQueueCount;

private readonly PagedDb _db;
private readonly IPreCommitBehavior? _preCommit;
private readonly TimeSpan _minFlushDelay;
private readonly Action? _beforeMetricsDisposed;
private readonly Task _flusher;
Expand All @@ -52,9 +53,10 @@ public class Blockchain : IAsyncDisposable

private static readonly TimeSpan DefaultFlushDelay = TimeSpan.FromSeconds(1);

public Blockchain(PagedDb db, TimeSpan? minFlushDelay = null, int? finalizationQueueLimit = null, Action? beforeMetricsDisposed = null)
public Blockchain(PagedDb db, IPreCommitBehavior? preCommit = null, TimeSpan? minFlushDelay = null, int? finalizationQueueLimit = null, Action? beforeMetricsDisposed = null)
{
_db = db;
_preCommit = preCommit;
_minFlushDelay = minFlushDelay ?? DefaultFlushDelay;
_beforeMetricsDisposed = beforeMetricsDisposed;

Expand Down Expand Up @@ -270,7 +272,7 @@ public bool TryGet(in Key key, out ReadOnlySpan<byte> result)
/// <summary>
/// Represents a block that is a result of ExecutionPayload, storing it in a in-memory trie
/// </summary>
private class Block : RefCountingDisposable, IWorldState
private class Block : RefCountingDisposable, IWorldState, ICommit
{
public Keccak Hash { get; }
public Keccak ParentHash { get; }
Expand Down Expand Up @@ -316,6 +318,9 @@ public void Commit()
// acquires one more lease for this block as it is stored in the blockchain
AcquireLease();

// run pre-commit
_blockchain._preCommit?.BeforeCommit(this);

// set to blocks in number and in blocks by hash
_blockchain._blocksByNumber.AddOrUpdate(BlockNumber,
static (_, block) => new[] { block },
Expand Down Expand Up @@ -391,7 +396,9 @@ public void SetStorage(in Keccak key, in Keccak address, UInt256 value)
Set(Key.StorageCell(path, address), payload);
}

private void Set(in Key key, in ReadOnlySpan<byte> payload)
public bool TryGet(in Key key, out ReadOnlySpanOwner<byte> result) => throw new NotImplementedException("Not implemented yet");

public void Set(in Key key, in ReadOnlySpan<byte> payload)
{
InBlockMap map;

Expand All @@ -417,6 +424,8 @@ private void Set(in Key key, in ReadOnlySpan<byte> payload)
map.TrySet(key, payload);
}

public IKeyEnumerator GetEnumerator() => throw new NotImplementedException("Not implemented yet");

private ReadOnlySpanOwner<byte> Get(int bloom, in Key key)
{
if (TryAcquireLease() == false)
Expand Down
74 changes: 74 additions & 0 deletions src/Paprika/Chain/IPreCommitBehavior.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using Paprika.Data;
using Paprika.Utils;

namespace Paprika.Chain;

/// <summary>
/// A pre-commit behavior run by <see cref="Blockchain"/> component just before commiting a <see cref="IWorldState"/>
/// with <see cref="IWorldState.Commit"/>. Useful to provide concerns, like the Merkle construct and others.
/// </summary>
public interface IPreCommitBehavior
{
/// <summary>
/// Executed just before commit.
/// </summary>
/// <param name="commit">The object representing the commit.</param>
public void BeforeCommit(ICommit commit);
}

/// <summary>
/// The set of changes applied by <see cref="IWorldState"/>.
/// Allows for additional modifications of the data just before the commit.
/// </summary>
/// <remarks>
/// To access all the keys use the enumerator:
///
/// public static void Foreach(this ICommit commit)
/// {
/// foreach (var key in commit)
/// {
/// key.
/// }
/// }
/// </remarks>
public interface ICommit
{
/// <summary>
/// Tries to retrieve the result stored under the given key.
/// </summary>
/// <returns>
/// Whether the retrieval was successful.
/// </returns>
/// <remarks>
/// If successful, returns a result as an owner. Must be disposed properly.
/// </remarks>
public bool TryGet(in Key key, out ReadOnlySpanOwner<byte> result);

/// <summary>
/// Sets the value under the given key.
/// </summary>
void Set(in Key key, in ReadOnlySpan<byte> payload);

/// <summary>
/// Gets the enumerator for the keys in the given commit.
/// </summary>
/// <returns></returns>
IKeyEnumerator GetEnumerator();
}

/// <summary>
/// The <see cref="Key"/> enumerator.
/// </summary>
public interface IKeyEnumerator : IDisposable
{
/// <summary>
/// The current key.
/// </summary>
ref readonly Key Current { get; }

/// <summary>
/// Moves to the next.
/// </summary>
public bool MoveNext();
}

0 comments on commit 8f38acd

Please sign in to comment.