Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ Commit from IActionEvaluator #3445

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,49 @@ To be released.

### Backward-incompatible API changes

- Changed `IActionEvaluator.Evaluate()`'s return type to
`IReadOnlyList<ICommittedActionEvaluation>` from
`IReadOnlyList<IActionEvaluation>`. [[#3445]]
- Changed `BlockChain.DetermineStateRootHash(IActionEvaluator,
IPreEvaluationBlock, out IReadOnlyList<IActionEvaluation>)` to
`BlockChain.DetermineStateRootHash(IActionEvaluator,
IPreEvaluationBlock, out IReadOnlyList<ICommittedActionEvaluation>)`.
[[#3445]]
- Changed `BlockChain.EvaluateGenesis()`'s return type to
`IReadOnlyList<ICommittedActionEvaluation>` from
`IReadOnlyList<IActionEvaluation>`. [[#3445]]
- Changed `BlockChain.EvaluateBlock()`'s return type to
`IReadOnlyList<ICommittedActionEvaluation>` from
`IReadOnlyList<IActionEvaluation>`. [[#3445]]

### Backward-incompatible network protocol changes

### Backward-incompatible storage format changes

### Added APIs

- (Libplanet.Explorer) Added `TxResult.InputState` of type
- (Libplanet.Explorer) Added `TxResult.InputState` of type
`HashDigest<SHA256>?`. [[#3446], [#3447]]
- (Libplanet.Explorer) Added `TxResult.OutputState` of type
- (Libplanet.Explorer) Added `TxResult.OutputState` of type
`HashDigest<SHA256>?`. [[#3446], [#3447]]

### Behavioral changes

- `IActionEvaluator.Evaluate()`, `BlockChain.EvaluateGenesis()`,
and `BlockChain.EvaluateBlock()` have a side-effect of storing
data to `IStateStore` when called. [[#3445]]

### Bug fixes

### Dependencies

### CLI tools

[#3445]: https://github.com/planetarium/libplanet/pull/3445
[#3446]: https://github.com/planetarium/libplanet/issues/3446
[#3447]: https://github.com/planetarium/libplanet/pull/3447


Version 3.5.0
-------------

Expand Down
73 changes: 64 additions & 9 deletions Libplanet.Action/ActionEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Libplanet.Action.State;
using Libplanet.Common;
using Libplanet.Store;
using Libplanet.Store.Trie;
using Libplanet.Types.Blocks;
using Libplanet.Types.Tx;
using Serilog;
Expand Down Expand Up @@ -76,7 +77,7 @@ public static int GenerateRandomSeed(

/// <inheritdoc cref="IActionEvaluator.Evaluate"/>
[Pure]
public IReadOnlyList<IActionEvaluation> Evaluate(
public IReadOnlyList<ICommittedActionEvaluation> Evaluate(
IPreEvaluationBlock block,
HashDigest<SHA256>? baseStateRootHash)
{
Expand All @@ -95,19 +96,15 @@ public IReadOnlyList<IActionEvaluation> Evaluate(
EvaluateBlock(block, previousState).ToImmutableList();

var policyBlockAction = _policyBlockActionGetter(block);
if (policyBlockAction is null)
{
return evaluations;
}
else
if (policyBlockAction is { } blockAction)
{
previousState = evaluations.Count > 0
? evaluations.Last().OutputState
: previousState;
return evaluations.Add(
EvaluatePolicyBlockAction(block, previousState)
);
evaluations = evaluations.Add(EvaluatePolicyBlockAction(block, previousState));
}

return ToCommittedEvaluation(block, evaluations, baseStateRootHash);
}
finally
{
Expand Down Expand Up @@ -479,6 +476,64 @@ internal IAccount PrepareInitialDelta(HashDigest<SHA256>? stateRootHash)
return new Account(new AccountState(_stateStore.GetStateRoot(stateRootHash)));
}

internal IReadOnlyList<ICommittedActionEvaluation>
ToCommittedEvaluation(
IPreEvaluationBlock block,
IReadOnlyList<IActionEvaluation> evaluations,
HashDigest<SHA256>? baseStateRootHash)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();

ITrie trie = _stateStore.GetStateRoot(baseStateRootHash);
var committedEvaluations = new List<CommittedActionEvaluation>();

int setCount = 0;
foreach (var evaluation in evaluations)
{
ITrie nextTrie = trie;
foreach (var kv in evaluation.OutputState.Delta.ToRawDelta())
{
nextTrie = nextTrie.Set(kv.Key, kv.Value);
setCount++;
}

nextTrie = _stateStore.Commit(nextTrie);
var committedEvaluation = new CommittedActionEvaluation(
riemannulus marked this conversation as resolved.
Show resolved Hide resolved
action: evaluation.Action,
inputContext: new CommittedActionContext(
signer: evaluation.InputContext.Signer,
txId: evaluation.InputContext.TxId,
miner: evaluation.InputContext.Miner,
blockIndex: evaluation.InputContext.BlockIndex,
blockProtocolVersion: evaluation.InputContext.BlockProtocolVersion,
rehearsal: evaluation.InputContext.Rehearsal,
previousState: trie.Hash,
randomSeed: evaluation.InputContext.RandomSeed,
blockAction: evaluation.InputContext.BlockAction),
outputState: nextTrie.Hash,
exception: evaluation.Exception);
committedEvaluations.Add(committedEvaluation);

trie = nextTrie;
}

_logger
.ForContext("Tag", "Metric")
.ForContext("Subtag", "StateUpdateDuration")
.Information(
"Took {DurationMs} ms to update the states with {Count} key changes " +
"and resulting in state root hash {StateRootHash} for " +
"block #{BlockIndex} pre-evaluation hash {PreEvaluationHash}",
stopwatch.ElapsedMilliseconds,
setCount,
trie.Hash,
block.Index,
block.PreEvaluationHash);

return committedEvaluations;
}

[Pure]
private static IEnumerable<ITransaction> OrderTxsForEvaluationV0(
IEnumerable<ITransaction> txs,
Expand Down
15 changes: 10 additions & 5 deletions Libplanet.Action/IActionEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Security.Cryptography;
using Libplanet.Action.Loader;
using Libplanet.Common;
using Libplanet.Store;
using Libplanet.Types.Blocks;

namespace Libplanet.Action
Expand All @@ -24,16 +25,20 @@ public interface IActionEvaluator
/// <paramref name="block"/>.</param>
/// <returns> The result of evaluating every <see cref="IAction"/> related to
/// <paramref name="block"/> as an <see cref="IReadOnlyList{T}"/> of
/// <see cref="IActionEvaluation"/>s.</returns>
/// <see cref="ICommittedActionEvaluation"/>s.</returns>
/// <remarks>
/// <para>Publicly exposed for benchmarking.</para>
/// <para>First evaluates all <see cref="IAction"/>s in
riemannulus marked this conversation as resolved.
Show resolved Hide resolved
/// <para>
/// This has a side-effect of writing data to internally held <see cref="IStateStore"/>.
/// </para>
/// <para>
/// First evaluates all <see cref="IAction"/>s in
/// <see cref="IBlockContent.Transactions"/> of <paramref name="block"/> and appends the
/// evaluation of the <see cref="IBlockPolicy.BlockAction"/> held by the instance at
/// the end.</para>
/// the end.
/// </para>
/// </remarks>
[Pure]
IReadOnlyList<IActionEvaluation> Evaluate(
IReadOnlyList<ICommittedActionEvaluation> Evaluate(
IPreEvaluationBlock block,
HashDigest<SHA256>? baseStateRootHash);
}
Expand Down
31 changes: 19 additions & 12 deletions Libplanet.Tests/Action/ActionEvaluatorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,14 @@ public void Idempotent()
transactions: txs).Propose();
var actionEvaluator = new ActionEvaluator(
_ => null,
new TrieStateStore(new MemoryKeyValueStore()),
stateStore,
new SingleActionLoader(typeof(RandomAction)));
Block stateRootBlock = noStateRootBlock.Sign(
GenesisProposer,
BlockChain.DetermineGenesisStateRootHash(
actionEvaluator,
noStateRootBlock,
out IReadOnlyList<IActionEvaluation> evals));
stateStore.Commit(null, evals.GetRawTotalDelta());
out IReadOnlyList<ICommittedActionEvaluation> evals));
var generatedRandomNumbers = new List<int>();

AssertPreEvaluationBlocksEqual(stateRootBlock, noStateRootBlock);
Expand All @@ -103,10 +102,14 @@ public void Idempotent()
{
var actionEvaluations = actionEvaluator.Evaluate(noStateRootBlock, null);
generatedRandomNumbers.Add(
(Integer)actionEvaluations[0].OutputState.GetState(txAddress));
(Integer)new AccountState(
stateStore.GetStateRoot(actionEvaluations[0].OutputState))
.GetState(txAddress));
actionEvaluations = actionEvaluator.Evaluate(stateRootBlock, null);
generatedRandomNumbers.Add(
(Integer)actionEvaluations[0].OutputState.GetState(txAddress));
(Integer)new AccountState(
stateStore.GetStateRoot(actionEvaluations[0].OutputState))
.GetState(txAddress));
}

for (int i = 1; i < generatedRandomNumbers.Count; ++i)
Expand Down Expand Up @@ -921,10 +924,12 @@ public void TotalUpdatedFungibleAssets()
var block = chain.ProposeBlock(
GenesisProposer, txs.ToImmutableList(), CreateBlockCommit(chain.Tip));

var evals = chain.EvaluateBlock(block);
var evals = actionEvaluator.EvaluateBlock(
block,
new Account(chain.GetAccountState(block.PreviousHash)));

// Includes policy block action
Assert.Equal(4, evals.Count);
// Does not include policy block action
Assert.Equal(3, evals.Count());
var latest = evals.Last().OutputState;

// Only addresses[0] and addresses[1] succeeded in minting
Expand Down Expand Up @@ -991,10 +996,11 @@ public void EvaluateActionAndCollectFee()
Assert.Null(evaluations.Single().Exception);
Assert.Equal(
FungibleAssetValue.FromRawValue(foo, 9),
evaluations.Single().OutputState.GetBalance(address, foo));
chain.GetAccountState(evaluations.Single().OutputState).GetBalance(address, foo));
Assert.Equal(
FungibleAssetValue.FromRawValue(foo, 1),
evaluations.Single().OutputState.GetBalance(miner.ToAddress(), foo));
chain.GetAccountState(
evaluations.Single().OutputState).GetBalance(miner.ToAddress(), foo));
}

[Fact]
Expand Down Expand Up @@ -1060,10 +1066,11 @@ public void EvaluateThrowingExceedGasLimit()
evaluations.Single().Exception?.InnerException?.GetType());
Assert.Equal(
FungibleAssetValue.FromRawValue(foo, 5),
evaluations.Single().OutputState.GetBalance(address, foo));
chain.GetAccountState(evaluations.Single().OutputState).GetBalance(address, foo));
Assert.Equal(
FungibleAssetValue.FromRawValue(foo, 5),
evaluations.Single().OutputState.GetBalance(miner.ToAddress(), foo));
chain.GetAccountState(
evaluations.Single().OutputState).GetBalance(miner.ToAddress(), foo));
}

[Fact]
Expand Down
4 changes: 2 additions & 2 deletions Libplanet.Tests/Blockchain/BlockChainTest.Append.cs
Original file line number Diff line number Diff line change
Expand Up @@ -608,8 +608,8 @@ public void CachedActionEvaluationWrittenOnAppend()
_blockChain.StageTransaction(txA0);
_blockChain.StageTransaction(txA1);
Block block = _blockChain.ProposeBlock(miner);
(IReadOnlyList<ICommittedActionEvaluation> actionEvaluations, _) =
_blockChain.ToCommittedEvaluation(block, _blockChain.EvaluateBlock(block));
IReadOnlyList<ICommittedActionEvaluation> actionEvaluations =
_blockChain.EvaluateBlock(block);
Assert.Equal(0L, _blockChain.Tip.Index);
_blockChain.Append(
block,
Expand Down
2 changes: 1 addition & 1 deletion Libplanet.Tests/Blocks/PreEvaluationBlockTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public void DetermineStateRootHash()
actionTypeLoader: new SingleActionLoader(typeof(Arithmetic)));
HashDigest<SHA256> genesisStateRootHash =
BlockChain.DetermineGenesisStateRootHash(
actionEvaluator, preEvalGenesis, out _);
actionEvaluator, preEvalGenesis, out var _);
_output.WriteLine("#0 StateRootHash: {0}", genesisStateRootHash);
Block genesis =
preEvalGenesis.Sign(_contents.GenesisKey, genesisStateRootHash);
Expand Down
3 changes: 1 addition & 2 deletions Libplanet.Tests/Store/StoreFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,7 @@ protected StoreFixture(IAction blockAction = null)
BlockChain.DetermineGenesisStateRootHash(
actionEvaluator,
preEval,
out IReadOnlyList<IActionEvaluation> evals));
stateStore.Commit(null, evals.GetRawTotalDelta());
out IReadOnlyList<ICommittedActionEvaluation> evals));
stateRootHashes[GenesisBlock.Hash] = GenesisBlock.StateRootHash;
Block1 = TestUtils.ProposeNextBlock(
GenesisBlock,
Expand Down
Loading
Loading