Example #1
0
        internal ActionEvaluation EvaluateBlockAction(
            Block <T> block,
            IReadOnlyList <ActionEvaluation> txActionEvaluations)
        {
            if (Policy.BlockAction is null)
            {
                var message = "To evaluate block action, Policy.BlockAction must not be null.";
                throw new InvalidOperationException(message);
            }

            IAccountStateDelta lastStates = null;

            if (!(txActionEvaluations is null) && txActionEvaluations.Count > 0)
            {
                lastStates = txActionEvaluations[txActionEvaluations.Count - 1].OutputStates;
            }

            Address miner = block.Miner.GetValueOrDefault();

            if (lastStates is null)
            {
                lastStates = new AccountStateDeltaImpl(
                    a => GetStates(new[] { a }, block.PreviousHash).GetValueOrDefault(a));
            }

            return(ActionEvaluation.EvaluateActionsGradually(
                       block.Hash,
                       block.Index,
                       null,
                       lastStates,
                       miner,
                       miner,
                       Array.Empty <byte>(),
                       new[] { Policy.BlockAction }.ToImmutableList()).First());
        }
Example #2
0
        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;
            }
        }
Example #3
0
        EvaluateActionsPerTx(AccountStateGetter accountStateGetter = null)
        {
            IAccountStateDelta delta =
                new AccountStateDeltaImpl(
                    accountStateGetter ?? (a => null)
                    );

            foreach (Transaction <T> tx in Transactions)
            {
                IEnumerable <ActionEvaluation> evaluations =
                    tx.EvaluateActionsGradually(
                        Hash,
                        Index,
                        delta,
                        Miner.Value);
                foreach (var evaluation in evaluations)
                {
                    yield return(Tuple.Create(tx, evaluation));

                    delta = evaluation.OutputStates;
                }

                delta = new AccountStateDeltaImpl(delta.GetState);
            }
        }
Example #4
0
        public void CreateNullDelta()
        {
            IAccountStateDelta delta = new AccountStateDeltaImpl(GetState);

            Assert.Empty(delta.UpdatedAddresses);
            Assert.Equal("a", delta.GetState(_addr[0]));
            Assert.Equal("b", delta.GetState(_addr[1]));
            Assert.Null(delta.GetState(_addr[2]));
        }
Example #5
0
        internal ActionEvaluation EvaluateBlockAction(
            Block <T> block,
            IReadOnlyList <ActionEvaluation> txActionEvaluations,
            StateCompleterSet <T> stateCompleters
            )
        {
            if (block == null)
            {
                throw new ArgumentNullException(nameof(block));
            }

            if (_blockAction is null)
            {
                var message = "To evaluate block action, Policy.BlockAction must not be null.";
                throw new InvalidOperationException(message);
            }

            _logger.Debug(
                "Evaluating block action in block {blockIndex}: {block}", block?.Index, block);

            IAccountStateDelta?lastStates = null;

            if (!(txActionEvaluations is null) && txActionEvaluations.Count > 0)
            {
                lastStates = txActionEvaluations[txActionEvaluations.Count - 1].OutputStates;
            }

            Address miner = block !.Miner.GetValueOrDefault();

            if (lastStates is null)
            {
                lastStates = new AccountStateDeltaImpl(
                    a => _stateGetter(a, block.PreviousHash, stateCompleters.StateCompleter),
                    (address, currency) => _balanceGetter(
                        address,
                        currency,
                        block.PreviousHash,
                        stateCompleters.FungibleAssetStateCompleter
                        ),
                    miner
                    );
            }

            return(ActionEvaluation.EvaluateActionsGradually(
                       block.PreEvaluationHash,
                       block.Index,
                       null,
                       lastStates,
                       miner,
                       miner,
                       Array.Empty <byte>(),
                       new[] { _blockAction }.ToImmutableList()).First());
        }
Example #6
0
        public IEnumerable <IAccountStateDelta> EvaluateActions(
            AccountStateGetter accountStateGetter = null
            )
        {
            IAccountStateDelta delta =
                new AccountStateDeltaImpl(
                    accountStateGetter ?? (a => null)
                    );

            foreach (Transaction <T> tx in Transactions)
            {
                delta = tx.EvaluateActions(
                    Hash, Index, delta, Miner.Value);
                yield return(delta);

                delta = new AccountStateDeltaImpl(delta.GetState);
            }
        }
Example #7
0
        /// <summary>
        /// Validates the integrity of the <see cref="Block{T}"/>.
        /// <para>It throws an <see cref="InvalidBlockException"/> or
        /// an <see cref="InvalidTxException"/> if there is any
        /// integrity error.</para>
        /// <para>Otherwise it returns an <see cref="IAccountStateDelta"/>
        /// which represents the final states and maintains the changes
        /// from the states of the previous <see cref="Block{T}"/>.</para>
        /// </summary>
        /// <param name="currentTime">The current time to validate
        /// time-wise conditions.</param>
        /// <param name="accountStateGetter">The getter of previous states.
        /// This affects the execution of <see cref="Transaction{T}.Actions"/>.
        /// </param>
        /// <returns>An <see cref="IAccountStateDelta"/> of the states
        /// right after all <see cref="Transaction{T}.Actions"/> of
        /// <see cref="Transactions"/>, which maintains the changes from
        /// the states of the previous <see cref="Block{T}"/>.</returns>
        /// <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="InvalidTxSignatureException">Thrown when its
        /// <see cref="Transaction{T}.Signature"/> is invalid or not signed by
        /// the account who corresponds to its
        /// <see cref="Transaction{T}.PublicKey"/>.</exception>
        /// <exception cref="InvalidTxPublicKeyException">Thrown when its
        /// <see cref="Transaction{T}.Signer"/> is not derived from its
        /// <see cref="Transaction{T}.PublicKey"/>.</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>
        public IAccountStateDelta Validate(
            DateTimeOffset currentTime,
            AccountStateGetter accountStateGetter
            )
        {
            Validate(currentTime);
            IEnumerable <IAccountStateDelta> deltas =
                EvaluateActions(accountStateGetter);
            IAccountStateDelta result = new AccountStateDeltaImpl(
                accountStateGetter
                );

            var txUpdatedAddressesPairs = Transactions.Zip(
                deltas,
                (tx, d) => (tx, d)
                );

            foreach (var(tx, delta) in txUpdatedAddressesPairs)
            {
                IImmutableSet <Address> updatedAddresses =
                    delta.UpdatedAddresses;

                if (!tx.UpdatedAddresses.IsSupersetOf(updatedAddresses))
                {
                    var msg =
                        "Actions in the transaction try to update " +
                        "the addresses not granted.";
                    throw new InvalidTxUpdatedAddressesException(
                              tx.Id,
                              tx.UpdatedAddresses,
                              updatedAddresses,
                              msg
                              );
                }

                foreach (var pair in delta.GetUpdatedStates())
                {
                    result = result.SetState(pair.Key, pair.Value);
                }
            }

            return(result);
        }
Example #8
0
        public void GetSetState()
        {
            IAccountStateDelta init = new AccountStateDeltaImpl(GetState);
            IAccountStateDelta a    = init.SetState(_addr[0], "A");

            Assert.Equal("A", a.GetState(_addr[0]));
            Assert.Equal("a", init.GetState(_addr[0]));
            Assert.Equal("b", a.GetState(_addr[1]));
            Assert.Equal("b", init.GetState(_addr[1]));
            Assert.Null(a.GetState(_addr[2]));
            Assert.Null(init.GetState(_addr[2]));
            Assert.Equal(
                new[] { _addr[0] }.ToImmutableHashSet(),
                a.UpdatedAddresses
                );
            Assert.Empty(init.UpdatedAddresses);

            IAccountStateDelta b = a.SetState(_addr[0], "z");

            Assert.Equal("z", b.GetState(_addr[0]));
            Assert.Equal("A", a.GetState(_addr[0]));
            Assert.Equal("a", init.GetState(_addr[0]));
            Assert.Equal("b", b.GetState(_addr[1]));
            Assert.Equal("b", a.GetState(_addr[1]));
            Assert.Null(b.GetState(_addr[2]));
            Assert.Null(a.GetState(_addr[2]));
            Assert.Equal(
                new[] { _addr[0] }.ToImmutableHashSet(),
                a.UpdatedAddresses
                );
            Assert.Empty(init.UpdatedAddresses);

            IAccountStateDelta c = b.SetState(_addr[0], "a");

            Assert.Equal("a", c.GetState(_addr[0]));
            Assert.Equal("z", b.GetState(_addr[0]));
            Assert.Empty(c.UpdatedAddresses);
            Assert.Empty(init.UpdatedAddresses);
        }