Skip to content

Commit

Permalink
Merge pull request #3842 from greymistcube/refactor/memory-next-state…
Browse files Browse the repository at this point in the history
…-root-hash

♻️ In memory "next state root hash"
  • Loading branch information
greymistcube authored Jun 21, 2024
2 parents cc268b0 + 48e13a9 commit 87c5fdf
Show file tree
Hide file tree
Showing 24 changed files with 203 additions and 285 deletions.
10 changes: 0 additions & 10 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,13 @@ To be released.
parameter `IActionEvaluator actionEvaluator` any more. [[#3811]]
- (Libplanet) `BlockChain.ProposeBlock()` receives parameter
`HashDigest<SHA256> stateRootHash`. [[#3811]]
- (Libplanet) Added `BlockChain.GetNextWorldState()` and
`BlockChain.GetNextWorldState(BlockHash?)` methods. [[#3821]]

### Backward-incompatible network protocol changes

### Backward-incompatible storage format changes

### Added APIs

- (Libplanet.Store) Added `IStore.GetNextStateRootHash()` method.
[[#3811]]
- (Libplanet.Store) Added `IStore.PutNextStateRootHash()` method.
[[#3811]]
- (Libplanet.Store) Added `IStore.DeleteNextStateRootHash()` method.
[[#3811]]
- (Libplanet) Added `BlockChain.DetermineNextBlockStateRootHash()`
method. [[#3811]]

Expand All @@ -51,8 +43,6 @@ To be released.
- `BlockHeader.StateRootHash` now means state root hash calculated by
`BlockChain.DetermineNextBlockStateRootHash(previousBlockHash)`.
[[#Sloth]]
- `IBlockChainStates.GetWorldState(BlockHash)` now means the `IWorldState`
before state transition from the `Block`. [[#3811]]
- `Context.ProcessHeightOrRoundUponRules()` now appends block asynchronously,
as a manner of fire-and-forget. [[#3808]]

Expand Down
6 changes: 3 additions & 3 deletions Libplanet.Action/State/IBlockChainStates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ public interface IBlockChainStates
/// The <see cref="IWorldState"/> at <paramref name="offset"/>, which is the identical
/// to what <see cref="Block.StateRootHash"/> of <paramref name="offset"/> indicates.
/// </returns>
/// <exception cref="ArgumentException">Thrown when <paramref name="offset"/>
/// one of the following is true.
/// <exception cref="ArgumentException">Thrown when one of the following is true
/// for <paramref name="offset"/>.
/// <list type="bullet">
/// <item><description>
/// Corresponding <see cref="Block"/> is not found in the <see cref="IStore"/>.
Expand All @@ -46,7 +46,7 @@ public interface IBlockChainStates
/// <returns>
/// The <see cref="IWorldState"/> with <paramref name="stateRootHash"/>.
/// If <paramref name="stateRootHash"/> is <see langword="null"/>,
/// returns the hash of the empty state root.
/// returns an empty <see cref="IWorldState"/>.
/// </returns>
/// <exception cref="ArgumentException">Thrown when no <see cref="ITrie"/> with
/// <paramref name="hash"/> as its state root hash is found.
Expand Down
7 changes: 5 additions & 2 deletions Libplanet.Net.Tests/Consensus/ContextTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Diagnostics;
using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Bencodex;
using Bencodex.Types;
Expand All @@ -16,6 +17,7 @@
using Libplanet.Net.Messages;
using Libplanet.Store;
using Libplanet.Store.Trie;
using Libplanet.Tests;
using Libplanet.Tests.Store;
using Libplanet.Types.Blocks;
using Libplanet.Types.Consensus;
Expand Down Expand Up @@ -321,7 +323,7 @@ void BroadcastMessage(ConsensusMsg message) =>
1L,
TestUtils.PrivateKeys[0],
blockChain
.GetNextWorldState(blockChain[0L].Hash)!
.GetNextWorldState(0L)
.GetValidatorSet(),
contextTimeoutOptions: new ContextTimeoutOption());

Expand Down Expand Up @@ -623,7 +625,7 @@ void BroadcastMessage(ConsensusMsg message) =>
1L,
TestUtils.PrivateKeys[0],
blockChain
.GetNextWorldState(blockChain[0L].Hash)!
.GetNextWorldState(0L)
.GetValidatorSet(),
contextTimeoutOptions: new ContextTimeoutOption());

Expand Down Expand Up @@ -687,6 +689,7 @@ void BroadcastMessage(ConsensusMsg message) =>
var watch = Stopwatch.StartNew();
await onTipChanged.WaitAsync();
Assert.True(watch.ElapsedMilliseconds < (actionDelay * 0.5));
Thread.Sleep(100); // Wait for votes to get collected.

Assert.Equal(
4,
Expand Down
3 changes: 2 additions & 1 deletion Libplanet.Net.Tests/TestUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using Libplanet.Net.Transports;
using Libplanet.Store;
using Libplanet.Store.Trie;
using Libplanet.Tests;
using Libplanet.Tests.Store;
using Libplanet.Types.Blocks;
using Libplanet.Types.Consensus;
Expand Down Expand Up @@ -288,7 +289,7 @@ void BroadcastMessage(ConsensusMsg message) =>
height,
privateKey,
validatorSet ?? blockChain
.GetNextWorldState(blockChain[height - 1].Hash)!
.GetNextWorldState(height - 1)
.GetValidatorSet(),
contextTimeoutOptions: contextTimeoutOptions ?? new ContextTimeoutOption());

Expand Down
22 changes: 15 additions & 7 deletions Libplanet.Net/Consensus/ConsensusContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -452,20 +452,28 @@ private Context CreateContext(long height)
{
// blockchain may not contain block of Height - 1?
ValidatorSet validatorSet;
if (_blockChain.Tip.ProtocolVersion
< BlockMetadata.SlothProtocolVersion)
if (_blockChain.Tip.ProtocolVersion < BlockMetadata.SlothProtocolVersion)
{
validatorSet = _blockChain
.GetWorldState(_blockChain[Height - 1].StateRootHash)
.GetValidatorSet();
}
else
{
validatorSet = _blockChain
.GetWorldState(
_blockChain.GetNextStateRootHash(
_blockChain[Height - 1].Hash, TimeSpan.Zero))
.GetValidatorSet();
while (true)
{
var nextStateRootHash = _blockChain.GetNextStateRootHash(Height - 1);
if (nextStateRootHash is { } nsrh)
{
validatorSet = _blockChain
.GetWorldState(nsrh)
.GetValidatorSet();
break;
}

// FIXME: Maybe this should be adjustable?
Thread.Sleep(100);
}
}

Context context = new Context(
Expand Down
2 changes: 1 addition & 1 deletion Libplanet.Net/Consensus/Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ private bool IsValid(Block block)
}
}

_blockChain.ValidateBlockStateRootHash(block, TimeSpan.Zero);
_blockChain.ValidateBlockStateRootHash(block);
}
catch (Exception e) when (
e is InvalidBlockException ||
Expand Down
28 changes: 0 additions & 28 deletions Libplanet.Store/IStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -348,33 +348,5 @@ public interface IStore : IDisposable
/// <returns>Returns an <see cref="IEnumerable{T}"/> of <see cref="BlockHash"/>es
/// of all <see cref="BlockCommit"/>s.</returns>
IEnumerable<BlockHash> GetBlockCommitHashes();

/// <summary>
/// Gets the next state root hash for given <paramref name="blockHash"/> from the store.
/// </summary>
/// <param name="blockHash">The <see cref="BlockHash"/> of the <see cref="Block"/>
/// to retrieve next state root hash.</param>
/// <returns>Returns <see cref="HashDigest{SHA256}"/> if next state root hash of given
/// <paramref name="blockHash"/> is stored and available,
/// otherwise returns <see langword="null"/>.</returns>
HashDigest<SHA256>? GetNextStateRootHash(BlockHash blockHash);

/// <summary>
/// Puts a next state root hash of <see cref="Block"/> corresponding to the
/// <paramref name="blockHash"/> to the store.
/// </summary>
/// <param name="blockHash">The <see cref="BlockHash"/> of the <see cref="Block"/>
/// where <paramref name="nextStateRootHash"/> evaluated.</param>
/// <param name="nextStateRootHash">The <see cref="HashDigest{SHA256}"/> that represents
/// state root hash of the next state.</param>
void PutNextStateRootHash(BlockHash blockHash, HashDigest<SHA256> nextStateRootHash);

/// <summary>
/// Deletes the next state root hash of <see cref="Block"/> corresponding to the given
/// <paramref name="blockHash"/> from the store.
/// </summary>
/// <param name="blockHash">The <see cref="BlockHash"/> of a next state root hash
/// to delete.</param>
void DeleteNextStateRootHash(BlockHash blockHash);
}
}
14 changes: 0 additions & 14 deletions Libplanet.Store/MemoryStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -301,20 +301,6 @@ public void DeleteBlockCommit(BlockHash blockHash) =>
public IEnumerable<BlockHash> GetBlockCommitHashes()
=> _blockCommits.Keys;

/// <inheritdoc />
public HashDigest<SHA256>? GetNextStateRootHash(BlockHash blockHash)
=> _nextStateRootHashes.TryGetValue(blockHash, out var nextStateRootHash)
? (HashDigest<SHA256>?)nextStateRootHash
: null;

/// <inheritdoc />
public void PutNextStateRootHash(BlockHash blockHash, HashDigest<SHA256> nextStateRootHash)
=> _nextStateRootHashes[blockHash] = nextStateRootHash;

/// <inheritdoc />
public void DeleteNextStateRootHash(BlockHash blockHash)
=> _nextStateRootHashes.TryRemove(blockHash, out _);

[StoreLoader("memory")]
private static (IStore Store, IStateStore StateStore) Loader(Uri storeUri)
{
Expand Down
2 changes: 1 addition & 1 deletion Libplanet.Tests/Action/ActionEvaluatorTest.Migration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ public void MigrateThroughBlockWorldState()
var block3 = chain.ProposeBlock(miner, blockCommit);
chain.Append(block3, CreateBlockCommit(block3));
Assert.Equal(BlockMetadata.CurrentProtocolVersion, chain.GetNextWorldState().Version);
var accountStateRoot = stateStore.GetStateRoot(store.GetNextStateRootHash(block3.Hash))
var accountStateRoot = stateStore.GetStateRoot(chain.GetNextStateRootHash(block3.Hash))
.Get(KeyConverters.ToStateKey(ModernAction.AccountAddress));
Assert.NotNull(accountStateRoot);
var accountTrie = stateStore.GetStateRoot(new HashDigest<SHA256>(accountStateRoot));
Expand Down
4 changes: 2 additions & 2 deletions Libplanet.Tests/Action/ActionEvaluatorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1009,7 +1009,7 @@ public void EvaluateActionAndCollectFee()
Block block = chain.ProposeBlock(miner);

var evaluations = chain.ActionEvaluator.Evaluate(
block, chain.Store.GetNextStateRootHash((BlockHash)block.PreviousHash));
block, chain.GetNextStateRootHash((BlockHash)block.PreviousHash));

Assert.False(evaluations[0].InputContext.BlockAction);
Assert.Single(evaluations);
Expand Down Expand Up @@ -1079,7 +1079,7 @@ public void EvaluateThrowingExceedGasLimit()

var evaluations = chain.ActionEvaluator.Evaluate(
block,
chain.Store.GetNextStateRootHash((BlockHash)block.PreviousHash));
chain.GetNextStateRootHash((BlockHash)block.PreviousHash));

Assert.False(evaluations[0].InputContext.BlockAction);
Assert.Single(evaluations);
Expand Down
17 changes: 8 additions & 9 deletions Libplanet.Tests/Action/WorldTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,13 @@ public virtual void TransferAssetInBlock()
chain.Append(block1, TestUtils.CreateBlockCommit(block1));
Assert.Equal(
DumbAction.DumbCurrency * 0,
GetLatestWorldState(chain)
chain
.GetNextWorldState()
.GetBalance(_addr[0], DumbAction.DumbCurrency));
Assert.Equal(
DumbAction.DumbCurrency * 20,
GetLatestWorldState(chain)
chain
.GetNextWorldState()
.GetBalance(_addr[1], DumbAction.DumbCurrency));

// Transfer
Expand All @@ -288,11 +290,13 @@ public virtual void TransferAssetInBlock()
chain.Append(block2, TestUtils.CreateBlockCommit(block2));
Assert.Equal(
DumbAction.DumbCurrency * 5,
GetLatestWorldState(chain)
chain
.GetNextWorldState()
.GetBalance(_addr[0], DumbAction.DumbCurrency));
Assert.Equal(
DumbAction.DumbCurrency * 15,
GetLatestWorldState(chain)
chain
.GetNextWorldState()
.GetBalance(_addr[1], DumbAction.DumbCurrency));

// Transfer bugged
Expand Down Expand Up @@ -504,11 +508,6 @@ public virtual void TotalSupplyTracking()
world.GetTotalSupply(_currencies[4]));
}

protected static IWorldState GetLatestWorldState(BlockChain blockChain) =>
blockChain.Tip.ProtocolVersion < BlockMetadata.SlothProtocolVersion
? blockChain.GetWorldState()
: blockChain.GetNextWorldState();

protected FungibleAssetValue Value(int currencyIndex, BigInteger quantity) =>
new FungibleAssetValue(_currencies[currencyIndex], quantity, 0);
}
Expand Down
53 changes: 53 additions & 0 deletions Libplanet.Tests/BlockChainExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.Security.Cryptography;
using Libplanet.Action.State;
using Libplanet.Blockchain;
using Libplanet.Common;
using Libplanet.Types.Blocks;

namespace Libplanet.Tests
{
public static class BlockChainExtensions
{
/// <summary>
/// Returns an <see cref="IWorldState"/> resulting from the execution of
/// the tip of <paramref name="blockChain"/>.
/// </summary>
/// <param name="blockChain">The <see cref="BlockChain"/> to search.</param>
/// <returns>An <see cref="IWorldState"/> resulting from the execution of
/// the tip of <paramref name="blockChain"/>.</returns>
public static IWorldState GetNextWorldState(this BlockChain blockChain) =>
blockChain.GetNextStateRootHash() is HashDigest<SHA256> stateRootHash
? blockChain.GetWorldState(stateRootHash)
: null;

/// <summary>
/// Returns an <see cref="IWorldState"/> resulting from the execution of
/// a <see cref="Block"/> associated with given <paramref name="index"/>
/// from <paramref name="blockChain"/>.
/// </summary>
/// <param name="blockChain">The <see cref="BlockChain"/> to search.</param>
/// <param name="index">The index of a <see cref="Block"/> to search.</param>
/// <returns>An <see cref="IWorldState"/> resulting from the execution of
/// a <see cref="Block"/> associated with given <paramref name="index"/>.</returns>
public static IWorldState GetNextWorldState(this BlockChain blockChain, long index) =>
blockChain.GetNextStateRootHash(index) is HashDigest<SHA256> stateRootHash
? blockChain.GetWorldState(stateRootHash)
: null;

/// <summary>
/// Returns an <see cref="IWorldState"/> resulting from the execution of
/// a <see cref="Block"/> associated with given <paramref name="blockHash"/>
/// from <paramref name="blockChain"/>.
/// </summary>
/// <param name="blockChain">The <see cref="BlockChain"/> to search.</param>
/// <param name="blockHash">The <see cref="BlockHash"/> to search.</param>
/// <returns>An <see cref="IWorldState"/> resulting from the execution of
/// a <see cref="Block"/> associated with given <paramref name="blockHash"/>.</returns>
public static IWorldState GetNextWorldState(
this BlockChain blockChain,
BlockHash blockHash) =>
blockChain.GetNextStateRootHash(blockHash) is HashDigest<SHA256> stateRootHash
? blockChain.GetWorldState(stateRootHash)
: null;
}
}
5 changes: 2 additions & 3 deletions Libplanet.Tests/Blockchain/BlockChainTest.Internals.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,7 @@ Transaction MkTx(PrivateKey key, long nonce, DateTimeOffset? ts = null) =>
[SkippableFact]
public void ExecuteActions()
{
(var addresses, Transaction[] txs) =
MakeFixturesForAppendTests();
(var addresses, Transaction[] txs) = MakeFixturesForAppendTests();
var genesis = _blockChain.Genesis;

Block block1 = _blockChain.ProposeBlock(
Expand All @@ -126,7 +125,7 @@ public void ExecuteActions()
};

IValue legacyStateRootRaw =
_fx.StateStore.GetStateRoot(_fx.Store.GetNextStateRootHash(block1.Hash))
_fx.StateStore.GetStateRoot(_blockChain.GetNextStateRootHash())
.Get(ToStateKey(ReservedAddresses.LegacyAccount));
Assert.NotNull(legacyStateRootRaw);
var legacyStateRoot =
Expand Down
6 changes: 2 additions & 4 deletions Libplanet.Tests/Blockchain/BlockChainTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1862,8 +1862,6 @@ void BuildIndex(Guid id, Block block)
.ToList();
Assert.NotEmpty(dirty);
store.PutBlock(b);
store.PutNextStateRootHash(
b.Hash, evals.Last().OutputState.Trie.Hash);
BuildIndex(chain.Id, b);
Assert.Equal(b, chain[b.Hash]);
if (presentIndices.Contains((int)b.Index))
Expand Down Expand Up @@ -2316,15 +2314,15 @@ private void ValidateNextBlockCommitOnValidatorSetChange()

Assert.Equal(
blockChain
.GetNextWorldState(blockChain[0].Hash)
.GetNextWorldState(0L)
.GetValidatorSet(),
new ValidatorSet(
ValidatorPrivateKeys.Select(
pk => new Validator(pk.PublicKey, BigInteger.One)).ToList()));

Assert.Equal(
blockChain
.GetNextWorldState(blockChain[1].Hash)
.GetNextWorldState(1L)
.GetValidatorSet(),
new ValidatorSet(
newValidators.Select(
Expand Down
Loading

0 comments on commit 87c5fdf

Please sign in to comment.