Skip to content

Commit

Permalink
Merge pull request #3748 from limebell/feature/tx-action
Browse files Browse the repository at this point in the history
Introduce Transaction-Actions
  • Loading branch information
limebell authored Apr 18, 2024
2 parents 1620267 + 65a88de commit 5cbb2c6
Show file tree
Hide file tree
Showing 32 changed files with 730 additions and 174 deletions.
20 changes: 13 additions & 7 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,18 @@ Version DPoS
- (Libplanet) Removed `IBlockPolicy.BlockAction` property. [[#3701]]
- (Libplanet) Added `IBlockPolicy.BeginBlockActions`. property. [[#3701]]
- (Libplanet) Added `IBlockPolicy.EndBlockActions`. property. [[#3701]]
- (Libplanet) `BlockPolicy` constructor requires `beginBlockActions` and
`endBlockActions` parameters instead of the `blockAction` parameter.
[[#3701]]
- (Libplanet) Added `IBlockPolicy.BeginTxActions`. property. [[#3748]]
- (Libplanet) Added `IBlockPolicy.EndTxActions`. property. [[#3748]]
- (Libplanet) `BlockPolicy` constructor requires `beginBlockActions`,
`endBlockActions`, `beginTxActions` and `endTxActions` parameters
instead of the `blockAction` parameter.
[[#3701], [#3748]]
- (Libplanet.Action) Renamed `PolicyBlockActionGetter` delegate to
`PolicyBlockActionGetter` and changed return type to
`ImmutableArray<IAction>`. [[#3701]]
`PolicyActionsGetter` and changed return type to
`ImmutableArray<IAction>`. [[#3701], [#3748]]
- (Libplanet.Action) `ActionEvaluator` constructor requires
`policyBeginBlockActionGetter` and `policyEndBlockActionGetter`
parameters instead of the `policyBlockActionGetter` parameter. [[#3701]]
`PolicyActionsRegistry` parameter instead of the
`policyBlockActionGetter` parameter. [[#3701], [#3748]]
- (Libplanet.Action) Added `SetValidatorSet` method to `IAccount` interface
and its implementations. [[#3730]]
- (Libplanet.Explorer) Added `ValidatorPower` field to `VoteType`. [[#3737]]
Expand All @@ -32,6 +35,8 @@ Version DPoS

### Added APIs

- (Libplanet.Action) Added `PolicyActionsRegistry` class. [[#3748]]

### Behavioral changes

### Bug fixes
Expand All @@ -43,6 +48,7 @@ Version DPoS
[#3701]: https://github.com/planetarium/libplanet/pull/3701
[#3730]: https://github.com/planetarium/libplanet/pull/3730
[#3737]: https://github.com/planetarium/libplanet/pull/3737
[#3748]: https://github.com/planetarium/libplanet/pull/3748


Version 4.1.0
Expand Down
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
127 changes: 100 additions & 27 deletions Libplanet.Action/ActionEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
using Libplanet.Action.Loader;
using Libplanet.Action.State;
using Libplanet.Common;
using Libplanet.Crypto;
using Libplanet.Store;
using Libplanet.Store.Trie;
using Libplanet.Types.Blocks;
Expand All @@ -26,37 +25,29 @@ namespace Libplanet.Action
public class ActionEvaluator : IActionEvaluator
{
private readonly ILogger _logger;
private readonly PolicyBlockActionsGetter _policyBeginBlockActionsGetter;
private readonly PolicyBlockActionsGetter _policyEndBlockActionsGetter;
private readonly PolicyActionsRegistry _policyActionsRegistry;
private readonly IStateStore _stateStore;
private readonly IActionLoader _actionLoader;

/// <summary>
/// Creates a new <see cref="ActionEvaluator"/>.
/// </summary>
/// <param name="policyBeginBlockActionsGetter">A delegator to get policy block actions to
/// evaluate at the beginning for each <see cref="IPreEvaluationBlock"/>
/// that gets evaluated.
/// Note the order of the returned list determines the execution order.
/// </param>
/// <param name="policyEndBlockActionsGetter">A delegator to get policy block actions to
/// evaluate at the end for each <see cref="IPreEvaluationBlock"/> that gets evaluated.
/// Note the order of the returned list determines the execution order.
/// <param name="policyActionsRegistry">
/// A <see cref="PolicyActionsRegistry"/> containing delegators
/// to get policy actions to evaluate at each situation.
/// </param>
/// <param name="stateStore">The <see cref="IStateStore"/> to use to retrieve
/// the states for a provided <see cref="HashDigest{SHA256}"/>.</param>
/// <param name="actionTypeLoader"> A <see cref="IActionLoader"/> implementation using
/// action type lookup.</param>
public ActionEvaluator(
PolicyBlockActionsGetter policyBeginBlockActionsGetter,
PolicyBlockActionsGetter policyEndBlockActionsGetter,
PolicyActionsRegistry policyActionsRegistry,
IStateStore stateStore,
IActionLoader actionTypeLoader)
{
_logger = Log.ForContext<ActionEvaluator>()
.ForContext("Source", nameof(ActionEvaluator));
_policyBeginBlockActionsGetter = policyBeginBlockActionsGetter;
_policyEndBlockActionsGetter = policyEndBlockActionsGetter;
_policyActionsRegistry = policyActionsRegistry;
_stateStore = stateStore;
_actionLoader = actionTypeLoader;
}
Expand Down Expand Up @@ -134,7 +125,8 @@ public IReadOnlyList<ICommittedActionEvaluation> Evaluate(
}

var evaluations = ImmutableList<ActionEvaluation>.Empty;
if (_policyBeginBlockActionsGetter(block) is { } beginBlockActions &&
if (_policyActionsRegistry.BeginBlockActionsGetter(block) is
{ } beginBlockActions &&
beginBlockActions.Length > 0)
{
evaluations = evaluations.AddRange(EvaluatePolicyBeginBlockActions(
Expand All @@ -147,7 +139,7 @@ public IReadOnlyList<ICommittedActionEvaluation> Evaluate(
EvaluateBlock(block, previousState).ToImmutableList()
);

if (_policyEndBlockActionsGetter(block) is { } endBlockActions &&
if (_policyActionsRegistry.EndBlockActionsGetter(block) is { } endBlockActions &&
endBlockActions.Length > 0)
{
previousState = evaluations.Count > 0
Expand Down Expand Up @@ -491,27 +483,50 @@ internal IEnumerable<ActionEvaluation> EvaluateTx(
ITransaction tx,
IWorld previousState)
{
var evaluations = ImmutableList<ActionEvaluation>.Empty;
if (_policyActionsRegistry.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 (_policyActionsRegistry.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 @@ -526,21 +541,21 @@ internal ActionEvaluation[] EvaluatePolicyBeginBlockActions(
blockHeader: blockHeader,
tx: null,
previousState: previousState,
actions: _policyBeginBlockActionsGetter(blockHeader),
actions: _policyActionsRegistry.BeginBlockActionsGetter(blockHeader),
stateStore: _stateStore,
logger: _logger).ToArray();
}

/// <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 @@ -555,7 +570,65 @@ internal ActionEvaluation[] EvaluatePolicyEndBlockActions(
blockHeader: blockHeader,
tx: null,
previousState: previousState,
actions: _policyEndBlockActionsGetter(blockHeader),
actions: _policyActionsRegistry.EndBlockActionsGetter(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[] 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: _policyActionsRegistry.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: _policyActionsRegistry.EndTxActionsGetter(blockHeader),
stateStore: _stateStore,
logger: _logger).ToArray();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Libplanet.Action
{
public delegate ImmutableArray<IAction> PolicyBlockActionsGetter(
public delegate ImmutableArray<IAction> PolicyActionsGetter(
IPreEvaluationBlockHeader blockHeader
);
}
49 changes: 49 additions & 0 deletions Libplanet.Action/PolicyActionsRegistry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using Libplanet.Types.Blocks;
using Libplanet.Types.Tx;

namespace Libplanet.Action
{
public class PolicyActionsRegistry
{
/// <summary>
/// A class containing delegators
/// to get policy actions to evaluate at each situation.
/// </summary>
/// <param name="beginBlockActionsGetter">A delegator to get policy block actions to
/// evaluate at the beginning for each <see cref="IPreEvaluationBlock"/> that gets
/// evaluated.
/// Note the order of the returned list determines the execution order.
/// </param>
/// <param name="endBlockActionsGetter">A delegator to get policy block actions to
/// evaluate at the end for each <see cref="IPreEvaluationBlock"/> that gets evaluated.
/// Note the order of the returned list determines the execution order.
/// </param>
/// <param name="beginTxActionsGetter">A delegator to get policy block actions to
/// evaluate at the beginning for each <see cref="Transaction"/> that gets evaluated.
/// Note the order of the returned list determines the execution order.
/// </param>
/// <param name="endTxActionsGetter">A delegator to get policy block actions to
/// evaluate at the end for each <see cref="Transaction"/> that gets evaluated.
/// Note the order of the returned list determines the execution order.
/// </param>
public PolicyActionsRegistry(
PolicyActionsGetter beginBlockActionsGetter,
PolicyActionsGetter endBlockActionsGetter,
PolicyActionsGetter beginTxActionsGetter,
PolicyActionsGetter endTxActionsGetter)
{
BeginBlockActionsGetter = beginBlockActionsGetter;
EndBlockActionsGetter = endBlockActionsGetter;
BeginTxActionsGetter = beginTxActionsGetter;
EndTxActionsGetter = endTxActionsGetter;
}

public PolicyActionsGetter BeginBlockActionsGetter { get; }

public PolicyActionsGetter EndBlockActionsGetter { get; }

public PolicyActionsGetter BeginTxActionsGetter { get; }

public PolicyActionsGetter EndTxActionsGetter { get; }
}
}
8 changes: 5 additions & 3 deletions Libplanet.Benchmarks/AppendBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using Libplanet.Action;
using Libplanet.Action.Loader;
using Libplanet.Action.Tests.Common;
using Libplanet.Blockchain;
using Libplanet.Blockchain.Policies;
using Libplanet.Crypto;
using Libplanet.Types.Blocks;
Expand Down Expand Up @@ -30,8 +29,11 @@ public AppendBlock()
fx.StateStore,
fx.GenesisBlock,
new ActionEvaluator(
policyBeginBlockActionsGetter: _ => ImmutableArray<IAction>.Empty,
policyEndBlockActionsGetter: _ => ImmutableArray<IAction>.Empty,
policyActionsRegistry: new PolicyActionsRegistry(
beginBlockActionsGetter: _ => ImmutableArray<IAction>.Empty,
endBlockActionsGetter: _ => ImmutableArray<IAction>.Empty,
beginTxActionsGetter: _ => ImmutableArray<IAction>.Empty,
endTxActionsGetter: _ => ImmutableArray<IAction>.Empty),
stateStore: fx.StateStore,
actionTypeLoader: new SingleActionLoader(typeof(DumbAction))));
_privateKey = new PrivateKey();
Expand Down
Loading

0 comments on commit 5cbb2c6

Please sign in to comment.