IEnumerable <Tuple <Transaction <T>, ActionEvaluation> > EvaluateActionsPerTx( AccountStateGetter accountStateGetter = null, AccountBalanceGetter accountBalanceGetter = null ) { accountStateGetter ??= a => null; accountBalanceGetter ??= (a, c) => 0; IAccountStateDelta delta; foreach (Transaction <T> tx in Transactions) { delta = new AccountStateDeltaImpl( accountStateGetter, accountBalanceGetter, tx.Signer ); IEnumerable <ActionEvaluation> evaluations = tx.EvaluateActionsGradually( Hash, Index, delta, Miner.Value); foreach (var evaluation in evaluations) { yield return(Tuple.Create(tx, evaluation)); delta = evaluation.OutputStates; } accountStateGetter = delta.GetState; accountBalanceGetter = delta.GetBalance; } }
IEnumerable <Tuple <Transaction <T>, ActionEvaluation> > EvaluateActionsPerTx( AccountStateGetter accountStateGetter = null, AccountBalanceGetter accountBalanceGetter = null, ITrie previousBlockStatesTrie = null ) { accountStateGetter ??= a => null; accountBalanceGetter ??= (a, c) => new FungibleAssetValue(c); IAccountStateDelta delta; foreach (Transaction <T> tx in Transactions) { delta = ProtocolVersion > 0 ? new AccountStateDeltaImpl(accountStateGetter, accountBalanceGetter, tx.Signer) : new AccountStateDeltaImplV0( accountStateGetter, accountBalanceGetter, tx.Signer); IEnumerable <ActionEvaluation> evaluations = tx.EvaluateActionsGradually( PreEvaluationHash, Index, delta, Miner.Value, previousBlockStatesTrie: previousBlockStatesTrie); foreach (var evaluation in evaluations) { yield return(Tuple.Create(tx, evaluation)); delta = evaluation.OutputStates; } accountStateGetter = delta.GetState; accountBalanceGetter = delta.GetBalance; } }
internal AccountStateDeltaImplV0( AccountStateGetter accountStateGetter, AccountBalanceGetter accountBalanceGetter, Address signer ) : base(accountStateGetter, accountBalanceGetter, signer) { }
/// <summary> /// Creates a null delta from the given <paramref name="accountStateGetter"/>. /// </summary> /// <param name="accountStateGetter">A view to the “epoch” states.</param> /// <param name="accountBalanceGetter">A view to the “epoch” asset balances. /// </param> /// <param name="signer">A signer address. Used for authenticating if a signer is allowed /// to mint a currency.</param> internal AccountStateDeltaImpl( AccountStateGetter accountStateGetter, AccountBalanceGetter accountBalanceGetter, Address signer ) { StateGetter = accountStateGetter; BalanceGetter = accountBalanceGetter; UpdatedStates = ImmutableDictionary <Address, IValue> .Empty; UpdatedFungibles = ImmutableDictionary <(Address, Currency), BigInteger> .Empty; Signer = signer; }
/// <summary> /// Executes every <see cref="IAction"/> in the /// <see cref="Transactions"/> and gets result states of each step of /// every <see cref="Transaction{T}"/>. /// <para>It throws an <see cref="InvalidBlockException"/> or /// an <see cref="InvalidTxException"/> if there is any /// integrity error.</para> /// <para>Otherwise it enumerates an <see cref="ActionEvaluation"/> /// for each <see cref="IAction"/>.</para> /// </summary> /// <param name="currentTime">The current time to validate /// time-wise conditions.</param> /// <param name="accountStateGetter">An <see cref="AccountStateGetter"/> delegate to get /// a previous state. A <c>null</c> value, which is default, means a constant function /// that returns <c>null</c>. /// This affects the execution of <see cref="Transaction{T}.Actions"/>. /// </param> /// <param name="accountBalanceGetter">An <see cref="AccountBalanceGetter"/> delegate to /// get previous account balance. /// A <c>null</c> value, which is default, means a constant function that returns zero. /// This affects the execution of <see cref="Transaction{T}.Actions"/>. /// </param> /// <param name="previousBlockStatesTrie">The trie to contain states at previous block. /// </param> /// <returns>An <see cref="ActionEvaluation"/> for each /// <see cref="IAction"/>.</returns> /// <exception cref="InvalidBlockHashException">Thrown when /// the <see cref="Hash"/> is invalid.</exception> /// <exception cref="InvalidBlockTimestampException">Thrown when /// the <see cref="Timestamp"/> is invalid, for example, it is the far /// future than the given <paramref name="currentTime"/>.</exception> /// <exception cref="InvalidBlockIndexException">Thrown when /// the <see cref="Index"/>is invalid, for example, it is a negative /// integer.</exception> /// <exception cref="InvalidBlockDifficultyException">Thrown when /// the <see cref="Difficulty"/> is not properly configured, /// for example, it is too easy.</exception> /// <exception cref="InvalidBlockPreviousHashException">Thrown when /// <see cref="PreviousHash"/> is invalid so that /// the <see cref="Block{T}"/>s are not continuous.</exception> /// <exception cref="InvalidBlockNonceException">Thrown when /// the <see cref="Nonce"/> does not satisfy its /// <see cref="Difficulty"/> level.</exception> /// <exception cref="InvalidBlockTxHashException">Thrown when /// the <see cref="TxHash" /> does not match with its /// <see cref="Transactions"/>.</exception> /// <exception cref="InvalidTxUpdatedAddressesException">Thrown when /// any <see cref="IAction"/> of <see cref="Transactions"/> tries /// to update the states of <see cref="Address"/>es not included /// in <see cref="Transaction{T}.UpdatedAddresses"/>.</exception> /// <exception cref="InvalidTxSignatureException">Thrown when its /// <see cref="Transaction{T}.Signature"/> is invalid or not signed by /// the account who corresponds to its <see cref="PublicKey"/>. /// </exception> /// <exception cref="InvalidTxPublicKeyException">Thrown when its /// <see cref="Transaction{T}.Signer"/> is not derived from its /// <see cref="Transaction{T}.PublicKey"/>.</exception> public IEnumerable <ActionEvaluation> Evaluate( DateTimeOffset currentTime, AccountStateGetter accountStateGetter = null, AccountBalanceGetter accountBalanceGetter = null, ITrie previousBlockStatesTrie = null ) { accountStateGetter ??= a => null; accountBalanceGetter ??= (a, c) => new FungibleAssetValue(c); Validate(currentTime); Tuple <Transaction <T>, ActionEvaluation>[] txEvaluations = EvaluateActionsPerTx( accountStateGetter, accountBalanceGetter, previousBlockStatesTrie).ToArray(); var txUpdatedAddressesPairs = txEvaluations .GroupBy(tuple => tuple.Item1) .Select( grp => ( grp.Key, grp.Last().Item2.OutputStates.UpdatedAddresses ) ); foreach ( (Transaction <T> tx, IImmutableSet <Address> updatedAddresses) in txUpdatedAddressesPairs) { if (!tx.UpdatedAddresses.IsSupersetOf(updatedAddresses)) { const string msg = "Actions in the transaction try to update " + "the addresses not granted."; throw new InvalidTxUpdatedAddressesException( tx.Id, tx.UpdatedAddresses, updatedAddresses, msg ); } } return(txEvaluations.Select(te => te.Item2)); }
public override IAccountStateDelta CreateInstance( AccountStateGetter accountStateGetter, AccountBalanceGetter accountBalanceGetter, Address signer ) => new AccountStateDeltaImpl(accountStateGetter, accountBalanceGetter, signer);