Skip to content

Commit 8baee41

Browse files
committed
feat: Add begin/end block actions.
1 parent 13f3e50 commit 8baee41

File tree

6 files changed

+95
-32
lines changed

6 files changed

+95
-32
lines changed

Libplanet.Action/ActionEvaluator.cs

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,34 @@ namespace Libplanet.Action
2626
public class ActionEvaluator : IActionEvaluator
2727
{
2828
private readonly ILogger _logger;
29-
private readonly PolicyBlockActionGetter _policyBlockActionGetter;
29+
private readonly PolicyBlockActionGetter _policyBeginBlockActionGetter;
30+
private readonly PolicyBlockActionGetter _policyEndBlockActionGetter;
3031
private readonly IStateStore _stateStore;
3132
private readonly IActionLoader _actionLoader;
3233

3334
/// <summary>
3435
/// Creates a new <see cref="ActionEvaluator"/>.
3536
/// </summary>
36-
/// <param name="policyBlockActionGetter">A delegator to get policy block action to evaluate
37-
/// at the end for each <see cref="IPreEvaluationBlock"/> that gets evaluated.</param>
37+
/// <param name="policyBeginBlockActionGetter">A delegator to get policy block actions to
38+
/// evaluate at the beginning for each <see cref="IPreEvaluationBlock"/>
39+
/// that gets evaluated.</param>
40+
/// <param name="policyEndBlockActionGetter">A delegator to get policy block actions to
41+
/// evaluate at the end for each <see cref="IPreEvaluationBlock"/> that gets evaluated.
42+
/// </param>
3843
/// <param name="stateStore">The <see cref="IStateStore"/> to use to retrieve
3944
/// the states for a provided <see cref="HashDigest{SHA256}"/>.</param>
4045
/// <param name="actionTypeLoader"> A <see cref="IActionLoader"/> implementation using
4146
/// action type lookup.</param>
4247
public ActionEvaluator(
43-
PolicyBlockActionGetter policyBlockActionGetter,
48+
PolicyBlockActionGetter policyBeginBlockActionGetter,
49+
PolicyBlockActionGetter policyEndBlockActionGetter,
4450
IStateStore stateStore,
4551
IActionLoader actionTypeLoader)
4652
{
4753
_logger = Log.ForContext<ActionEvaluator>()
4854
.ForContext("Source", nameof(ActionEvaluator));
49-
_policyBlockActionGetter = policyBlockActionGetter;
55+
_policyBeginBlockActionGetter = policyBeginBlockActionGetter;
56+
_policyEndBlockActionGetter = policyEndBlockActionGetter;
5057
_stateStore = stateStore;
5158
_actionLoader = actionTypeLoader;
5259
}
@@ -123,16 +130,29 @@ public IReadOnlyList<ICommittedActionEvaluation> Evaluate(
123130
throw new ApplicationException("World cannot be mutated from modern to legacy");
124131
}
125132

126-
ImmutableList<ActionEvaluation> evaluations =
127-
EvaluateBlock(block, previousState).ToImmutableList();
133+
var evaluations = ImmutableList<ActionEvaluation>.Empty;
134+
if (_policyBeginBlockActionGetter(block) is { } beginBlockActions &&
135+
beginBlockActions.Length > 0)
136+
{
137+
evaluations = evaluations.AddRange(EvaluatePolicyBeginBlockActions(
138+
block, previousState
139+
));
140+
previousState = evaluations.Last().OutputState;
141+
}
142+
143+
evaluations = evaluations.AddRange(
144+
EvaluateBlock(block, previousState).ToImmutableList()
145+
);
128146

129-
var policyBlockAction = _policyBlockActionGetter(block);
130-
if (policyBlockAction is { } blockAction)
147+
if (_policyEndBlockActionGetter(block) is { } endBlockActions &&
148+
endBlockActions.Length > 0)
131149
{
132150
previousState = evaluations.Count > 0
133151
? evaluations.Last().OutputState
134152
: previousState;
135-
evaluations = evaluations.Add(EvaluatePolicyBlockAction(block, previousState));
153+
evaluations = evaluations.AddRange(EvaluatePolicyEndBlockActions(
154+
block, previousState
155+
));
136156
}
137157

138158
var committed = ToCommittedEvaluation(block, evaluations, baseStateRootHash);
@@ -491,30 +511,50 @@ internal IEnumerable<ActionEvaluation> EvaluateTx(
491511
/// the <see cref="IBlockPolicy.BlockAction"/> held by the instance
492512
/// for the <paramref name="blockHeader"/>.</returns>
493513
[Pure]
494-
internal ActionEvaluation EvaluatePolicyBlockAction(
514+
internal ActionEvaluation[] EvaluatePolicyBeginBlockActions(
495515
IPreEvaluationBlockHeader blockHeader,
496516
IWorld previousState)
497517
{
498-
var policyBlockAction = _policyBlockActionGetter(blockHeader);
499-
if (policyBlockAction is null)
500-
{
501-
var message =
502-
"To evaluate policy block action, " +
503-
"policyBlockAction must not be null.";
504-
throw new InvalidOperationException(message);
505-
}
518+
_logger.Information(
519+
$"Evaluating policy begin block actions for block #{blockHeader.Index} " +
520+
$"{ByteUtil.Hex(blockHeader.PreEvaluationHash.ByteArray)}");
521+
522+
return EvaluateActions(
523+
blockHeader: blockHeader,
524+
tx: null,
525+
previousState: previousState,
526+
actions: _policyBeginBlockActionGetter(blockHeader),
527+
stateStore: _stateStore,
528+
logger: _logger).ToArray();
529+
}
506530

531+
/// <summary>
532+
/// Evaluates the <see cref="IBlockPolicy.BlockAction"/> set by the policy when
533+
/// this <see cref="ActionEvaluator"/> was instantiated for a given
534+
/// <see cref="IPreEvaluationBlockHeader"/>.
535+
/// </summary>
536+
/// <param name="blockHeader">The header of the block to evaluate.</param>
537+
/// <param name="previousState">The states immediately before the evaluation of
538+
/// the <see cref="IBlockPolicy.BlockAction"/> held by the instance.</param>
539+
/// <returns>The <see cref="ActionEvaluation"/> of evaluating
540+
/// the <see cref="IBlockPolicy.BlockAction"/> held by the instance
541+
/// for the <paramref name="blockHeader"/>.</returns>
542+
[Pure]
543+
internal ActionEvaluation[] EvaluatePolicyEndBlockActions(
544+
IPreEvaluationBlockHeader blockHeader,
545+
IWorld previousState)
546+
{
507547
_logger.Information(
508-
$"Evaluating policy block action for block #{blockHeader.Index} " +
548+
$"Evaluating policy end block actions for block #{blockHeader.Index} " +
509549
$"{ByteUtil.Hex(blockHeader.PreEvaluationHash.ByteArray)}");
510550

511551
return EvaluateActions(
512552
blockHeader: blockHeader,
513553
tx: null,
514554
previousState: previousState,
515-
actions: new[] { policyBlockAction }.ToImmutableList(),
555+
actions: _policyEndBlockActionGetter(blockHeader),
516556
stateStore: _stateStore,
517-
logger: _logger).Single();
557+
logger: _logger).ToArray();
518558
}
519559

520560
internal IWorld PrepareInitialDelta(HashDigest<SHA256>? stateRootHash)
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
using System.Collections.Immutable;
12
using Libplanet.Types.Blocks;
23

34
namespace Libplanet.Action
45
{
5-
public delegate IAction? PolicyBlockActionGetter(IPreEvaluationBlockHeader blockHeader);
6+
public delegate ImmutableArray<IAction> PolicyBlockActionGetter(
7+
IPreEvaluationBlockHeader blockHeader
8+
);
69
}

Libplanet/Blockchain/BlockChain.Evaluate.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ public IReadOnlyList<ICommittedActionEvaluation> EvaluateBlock(IPreEvaluationBlo
147147

148148
/// <summary>
149149
/// Evaluates all actions in the <see cref="PreEvaluationBlock.Transactions"/> and
150-
/// an optional <see cref="Blockchain.Policies.IBlockPolicy.BlockAction"/>, and returns
150+
/// optional <see cref="Policies.IBlockPolicy.BeginBlockActions"/>,
151+
/// <see cref="Policies.IBlockPolicy.EndBlockActions"/>, and returns
151152
/// a <see cref="Block"/> instance combined with the <see cref="Block.StateRootHash"/>
152153
/// The returned <see cref="Block"/> is signed by the given <paramref name="privateKey"/>.
153154
/// </summary>

Libplanet/Blockchain/Policies/BlockPolicy.cs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Immutable;
23
using System.Diagnostics.Contracts;
34
using System.Linq;
45
using Libplanet.Action;
@@ -34,7 +35,11 @@ public class BlockPolicy : IBlockPolicy
3435
/// description for more detail.
3536
/// </para>
3637
/// </summary>
37-
/// <param name="blockAction">A <see cref="IAction"/> to executed for
38+
/// <param name="beginBlockActions">Array of <see cref="IAction"/> to executed for
39+
/// every <see cref="Block"/>. Set to <see langword="null"/> by default, which results
40+
/// in no additional execution other than those included in <see cref="Transaction"/>s.
41+
/// </param>
42+
/// <param name="endBlockActions">A <see cref="IAction"/> to executed for
3843
/// every <see cref="Block"/>. Set to <see langword="null"/> by default, which results
3944
/// in no additional execution other than those included in <see cref="Transaction"/>s.
4045
/// </param>
@@ -66,7 +71,8 @@ public class BlockPolicy : IBlockPolicy
6671
/// Goes to <see cref="GetMaxTransactionsPerSignerPerBlock"/>. Set to
6772
/// <see cref="GetMaxTransactionsPerBlock"/> by default.</param>
6873
public BlockPolicy(
69-
IAction? blockAction = null,
74+
ImmutableArray<IAction>? beginBlockActions = null,
75+
ImmutableArray<IAction>? endBlockActions = null,
7076
TimeSpan? blockInterval = null,
7177
Func<BlockChain, Transaction, TxPolicyViolationException?>?
7278
validateNextBlockTx = null,
@@ -77,7 +83,8 @@ public BlockPolicy(
7783
Func<long, int>? getMaxTransactionsPerBlock = null,
7884
Func<long, int>? getMaxTransactionsPerSignerPerBlock = null)
7985
{
80-
BlockAction = blockAction;
86+
BeginBlockActions = beginBlockActions ?? ImmutableArray<IAction>.Empty;
87+
EndBlockActions = endBlockActions ?? ImmutableArray<IAction>.Empty;
8188
BlockInterval = blockInterval ?? DefaultTargetBlockInterval;
8289
_getMaxTransactionsBytes = getMaxTransactionsBytes ?? (_ => 100L * 1024L);
8390
_getMinTransactionsPerBlock = getMinTransactionsPerBlock ?? (_ => 0);
@@ -152,7 +159,10 @@ public BlockPolicy(
152159
}
153160

154161
/// <inheritdoc/>
155-
public IAction? BlockAction { get; }
162+
public ImmutableArray<IAction> BeginBlockActions { get; }
163+
164+
/// <inheritdoc/>
165+
public ImmutableArray<IAction> EndBlockActions { get; }
156166

157167
/// <summary>
158168
/// Targeted time interval between two consecutive <see cref="Block"/>s.

Libplanet/Blockchain/Policies/IBlockPolicy.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Collections.Immutable;
12
using System.Diagnostics.Contracts;
23
using Libplanet.Action;
34
using Libplanet.Types.Blocks;
@@ -21,9 +22,14 @@ namespace Libplanet.Blockchain.Policies
2122
public interface IBlockPolicy
2223
{
2324
/// <summary>
24-
/// An <see cref="IAction"/> to execute and be rendered for every block, if any.
25-
/// </summary>
26-
IAction? BlockAction { get; }
25+
/// An array of <see cref="IAction"/> to execute and be rendered at the beginning
26+
/// for every block, if any.</summary>
27+
ImmutableArray<IAction> BeginBlockActions { get; }
28+
29+
/// <summary>
30+
/// An array of <see cref="IAction"/> to execute and be rendered at the end for every block,
31+
/// if any.</summary>
32+
ImmutableArray<IAction> EndBlockActions { get; }
2733

2834
/// <summary>
2935
/// Checks if a <see cref="Transaction"/> can be included in a yet to be mined

Libplanet/Blockchain/Policies/NullBlockPolicy.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#nullable disable
22
using System.Collections.Generic;
3+
using System.Collections.Immutable;
34
using Libplanet.Action;
45
using Libplanet.Crypto;
56
using Libplanet.Types.Blocks;
@@ -22,7 +23,9 @@ public NullBlockPolicy(
2223

2324
public ISet<Address> BlockedMiners { get; } = new HashSet<Address>();
2425

25-
public IAction BlockAction => null;
26+
public ImmutableArray<IAction> BeginBlockActions => ImmutableArray<IAction>.Empty;
27+
28+
public ImmutableArray<IAction> EndBlockActions => ImmutableArray<IAction>.Empty;
2629

2730
public int GetMinTransactionsPerBlock(long index) => 0;
2831

0 commit comments

Comments
 (0)