Skip to content

Instantly share code, notes, and snippets.

@riemannulus
Last active May 4, 2023 10:21
Show Gist options
  • Save riemannulus/4f213628bba047974e08586a4297e394 to your computer and use it in GitHub Desktop.
Save riemannulus/4f213628bba047974e08586a4297e394 to your computer and use it in GitHub Desktop.
Psuedo ActionEvaluator
IEnumerable<ActionEvaluation> EvaluateBlock(IPreEvaluationBlock block, IAccountStateDelta prevState)
{
UInt256 remainingGasPerBlock = block.GasLimit();
IEnumerable<ActionEvaluation> evaluations
= ExecuteActions(_beginBlockActions, prevState, remainingGasPerBlock, 0);
foreach(ActionEvaluation eval in evaluations)
{
yield return eval;
prevState = eval.OutputState.UseGas(0);
}
foreach(ITransaction tx in block.Transactions)
{
evaluations = ExecuteTx(tx, prevState, remainingGasPerBlock);
foreach(ActionEvaluation eval in evaluations)
{
yield return eval;
prevState = eval.OutputState;
}
UInt256 usedGas = evaluations.Select(x => x.OutputStates.GasUsed).Sum();
remainingGasPerBlock -= usedGas;
}
evaluations = ExecuteActions(_endBlockActions, prevState, remainingGasPerBlock, 0);
foreach(ActionEvaluation eval in evaluations)
{
yield return eval;
prevState = eval.OutputState;
}
}
IEnumerable<ActionEvaluation> EvaluateTx(ITransaction tx, IAccountStateDelta prevState, UInt256 gasLimit, FungibleAssetValue baseGasPrice)
{
UInt256 gasLimitPerTransaction = tx.GasLimit();
if(gasLimit < gasLimitPerTransaction) throw InvalidTransaction();
FungibleAssetValue commissionGasPrice = Min(tx.CommissionGasPrice(), tx.MaxGasPrice() - baseGasPrice);
FungibleAssetValue gasPrice = commissionGasPrice + baseGasPrice;
return EvaluateActions(tx.Actions, prevState, gasLimitPerTransaction, gasPrice);
}
IEnumerable<ActionEvaluation> EvaluateActions(IImmutableList<IAction> actions, IAccountStateDelta prevState, UInt256 gasLimit, FungibleAssetValue commissionGasPrice, FungibleAssetValue gasPrice)
{
foreach(IAction action in actions)
{
// Burn reserve fee first for prevent collect minus fee
FungibleAssetValue reserveFee = gasPrice * gasLimit;
IAccountStateDelta nextState = prevState.BurnAsset(signer, reserveFee);
// Execute Action
// If gasLimit is less then used gas in action, it throw OutOfGasException
ActionContext context = CreateContext(state, seed, gasLimit);
nextState = action.Execute(nextState);
// Refund unused gas
UInt256 unusedGas = gasLimit - nextState.GasUsed();
nextState = nextState.MintAsset(signer, gasPrice * unusedGas);
// Calculate gas fee for collect
FungibleAssetValue commissionFee = commissionGasPrice * nextState.GasUsed();
FungibleAssetValue totalFee = gasPrice * nextState.GasUsed();
// Collect gas fee
// It distribute on next `BeginBlock` timing
nextState = nextState.MintAsset(feeCollectPool, commissionFee)
// Burn or transfer to community pool
// If burn, do nothing
// If transfer to community pool, mint to community pool
nextState = nextState.MintAsset(communityPool, totalFee - commissionFee)
yield return new ActionEvaluation(nextState);
// calculate next action gas limit
gasLimit = gasLimit - nextState.GasUsed();
// initialize useGas state to 0
prevState = nextState.UseGas(0);
}
}
UInt256 EstimateGas(ITransaction tx, IAccountStateDelta prevState, UInt256 gasLimit, FungibleAssetValue baseGasPrice)
{
evaluations = ExecuteTx(tx, prevState, remainingGasPerBlock);
foreach(ActionEvaluation eval in evaluations)
{
yield return eval;
prevState = eval.OutputState;
}
return evaluations.Select(x => x.OutputStates.GasUsed).Sum();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment