Skip to content

Commit

Permalink
feat: add tx action evaluation
Browse files Browse the repository at this point in the history
  • Loading branch information
limebell committed Apr 17, 2024
1 parent 6d33ccc commit 9fb7bce
Show file tree
Hide file tree
Showing 4 changed files with 262 additions and 35 deletions.
18 changes: 12 additions & 6 deletions Libplanet.Action.Tests/Common/UpdateValueAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,27 @@ namespace Libplanet.Action.Tests.Common
{
public sealed class UpdateValueAction : IAction
{
public static readonly Address ValueAddress =
new Address("0000000000000000000000000000000000000123");

public UpdateValueAction()
{
}

public UpdateValueAction(int increment)
public UpdateValueAction(Address address, int increment)
{
Address = address;
Increment = increment;
}

public Address Address { get; set; }

public int Increment { get; set; }

public IValue PlainValue => Bencodex.Types.Dictionary.Empty
.Add("address", Address.Bencoded)
.Add("value", new Bencodex.Types.Integer(Increment));

public void LoadPlainValue(IValue plainValue)
{
Address = new Address(((Dictionary)plainValue)["address"]);
Increment = (int)(Bencodex.Types.Integer)((Dictionary)plainValue)["value"];
}

Expand All @@ -35,12 +37,16 @@ public IWorld Execute(IActionContext ctx)
int value = 0;
int increment = Increment;

if (account.GetState(ValueAddress) is Integer integer)
if (account.GetState(Address) is Integer integer)
{
value = (int)integer.Value + increment;
}
else
{
value = increment;
}

account = account.SetState(ValueAddress, new Integer(value));
account = account.SetState(Address, new Integer(value));
return states.SetAccount(ReservedAddresses.LegacyAccount, account);
}
}
Expand Down
95 changes: 87 additions & 8 deletions Libplanet.Action/ActionEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -482,27 +482,48 @@ internal IEnumerable<ActionEvaluation> EvaluateTx(
ITransaction tx,
IWorld previousState)
{
var evaluations = ImmutableList<ActionEvaluation>.Empty;
if (_policyActionsGetterCollection.BeginTxActionsGetter(blockHeader) is { } beginTxActions &&
beginTxActions.Length > 0)
{
evaluations = evaluations.AddRange(
EvaluatePolicyBeginTxActions(blockHeader, previousState));
previousState = evaluations.Last().OutputState;
}

ImmutableList<IAction> actions =
ImmutableList.CreateRange(LoadActions(blockHeader.Index, tx));
return EvaluateActions(
evaluations = evaluations.AddRange(EvaluateActions(
blockHeader: blockHeader,
tx: tx,
previousState: previousState,
actions: actions,
stateStore: _stateStore,
logger: _logger);
logger: _logger));

if (_policyActionsGetterCollection.EndTxActionsGetter(blockHeader) is { } endTxActions &&
endTxActions.Length > 0)
{
previousState = evaluations.Count > 0
? evaluations.Last().OutputState
: previousState;
evaluations = evaluations.AddRange(
EvaluatePolicyEndTxActions(blockHeader, previousState));
}

return evaluations;
}

/// <summary>
/// Evaluates the <see cref="IBlockPolicy.BlockAction"/> set by the policy when
/// Evaluates the <see cref="IBlockPolicy.BeginBlockActions"/> set by the policy when
/// this <see cref="ActionEvaluator"/> was instantiated for a given
/// <see cref="IPreEvaluationBlockHeader"/>.
/// </summary>
/// <param name="blockHeader">The header of the block to evaluate.</param>
/// <param name="previousState">The states immediately before the evaluation of
/// the <see cref="IBlockPolicy.BlockAction"/> held by the instance.</param>
/// the <see cref="IBlockPolicy.BeginBlockActions"/> held by the instance.</param>
/// <returns>The <see cref="ActionEvaluation"/> of evaluating
/// the <see cref="IBlockPolicy.BlockAction"/> held by the instance
/// the <see cref="IBlockPolicy.BeginBlockActions"/> held by the instance
/// for the <paramref name="blockHeader"/>.</returns>
[Pure]
internal ActionEvaluation[] EvaluatePolicyBeginBlockActions(
Expand All @@ -523,15 +544,15 @@ internal ActionEvaluation[] EvaluatePolicyBeginBlockActions(
}

/// <summary>
/// Evaluates the <see cref="IBlockPolicy.BlockAction"/> set by the policy when
/// Evaluates the <see cref="IBlockPolicy.EndBlockActions"/> set by the policy when
/// this <see cref="ActionEvaluator"/> was instantiated for a given
/// <see cref="IPreEvaluationBlockHeader"/>.
/// </summary>
/// <param name="blockHeader">The header of the block to evaluate.</param>
/// <param name="previousState">The states immediately before the evaluation of
/// the <see cref="IBlockPolicy.BlockAction"/> held by the instance.</param>
/// the <see cref="IBlockPolicy.EndBlockActions"/> held by the instance.</param>
/// <returns>The <see cref="ActionEvaluation"/> of evaluating
/// the <see cref="IBlockPolicy.BlockAction"/> held by the instance
/// the <see cref="IBlockPolicy.EndBlockActions"/> held by the instance
/// for the <paramref name="blockHeader"/>.</returns>
[Pure]
internal ActionEvaluation[] EvaluatePolicyEndBlockActions(
Expand All @@ -551,6 +572,64 @@ internal ActionEvaluation[] EvaluatePolicyEndBlockActions(
logger: _logger).ToArray();
}

/// <summary>
/// Evaluates the <see cref="IBlockPolicy.BeginTxActions"/> set by the policy when
/// this <see cref="ActionEvaluator"/> was instantiated for a given
/// <see cref="IPreEvaluationBlockHeader"/>.
/// </summary>
/// <param name="blockHeader">The header of the block to evaluate.</param>
/// <param name="previousState">The states immediately before the evaluation of
/// the <see cref="IBlockPolicy.BlockAction"/> held by the instance.</param>
/// <returns>The <see cref="ActionEvaluation"/> of evaluating
/// the <see cref="IBlockPolicy.BlockAction"/> held by the instance
/// for the <paramref name="blockHeader"/>.</returns>
[Pure]
internal ActionEvaluation[] EvaluatePolicyBeginTxActions(
IPreEvaluationBlockHeader blockHeader,
IWorld previousState)
{
_logger.Information(
$"Evaluating policy begin tx actions for block #{blockHeader.Index} " +
$"{ByteUtil.Hex(blockHeader.PreEvaluationHash.ByteArray)}");

return EvaluateActions(
blockHeader: blockHeader,
tx: null,
previousState: previousState,
actions: _policyActionsGetterCollection.BeginTxActionsGetter(blockHeader),
stateStore: _stateStore,
logger: _logger).ToArray();
}

/// <summary>
/// Evaluates the <see cref="IBlockPolicy.BeginTxActions"/> set by the policy when
/// this <see cref="ActionEvaluator"/> was instantiated for a given
/// <see cref="IPreEvaluationBlockHeader"/>.
/// </summary>
/// <param name="blockHeader">The header of the block to evaluate.</param>
/// <param name="previousState">The states immediately before the evaluation of
/// the <see cref="IBlockPolicy.BlockAction"/> held by the instance.</param>
/// <returns>The <see cref="ActionEvaluation"/> of evaluating
/// the <see cref="IBlockPolicy.BlockAction"/> held by the instance
/// for the <paramref name="blockHeader"/>.</returns>
[Pure]
internal ActionEvaluation[] EvaluatePolicyEndTxActions(
IPreEvaluationBlockHeader blockHeader,
IWorld previousState)
{
_logger.Information(
$"Evaluating policy end tx actions for block #{blockHeader.Index} " +
$"{ByteUtil.Hex(blockHeader.PreEvaluationHash.ByteArray)}");

return EvaluateActions(
blockHeader: blockHeader,
tx: null,
previousState: previousState,
actions: _policyActionsGetterCollection.EndTxActionsGetter(blockHeader),
stateStore: _stateStore,
logger: _logger).ToArray();
}

internal IWorld PrepareInitialDelta(HashDigest<SHA256>? stateRootHash)
{
return new World(
Expand Down
Loading

0 comments on commit 9fb7bce

Please sign in to comment.