Example #1
0
        /// <summary>
        /// Gets the state of the given <paramref name="address"/> in the
        /// <see cref="BlockChain{T}"/> from <paramref name="offset"/>.
        /// </summary>
        /// <param name="address">An <see cref="Address"/> to get
        /// the states of.</param>
        /// <param name="offset">The <see cref="HashDigest{T}"/> of the block to
        /// start finding the state. It will be The tip of the
        /// <see cref="BlockChain{T}"/> if it is <c>null</c>.</param>
        /// <param name="completeStates">When the <see cref="BlockChain{T}"/>
        /// instance does not contain states dirty of the block which lastly
        /// updated states of a requested address, this option makes
        /// the incomplete states calculated and filled on the fly.
        /// If this option is turned off (which is default) this method throws
        /// <see cref="IncompleteBlockStatesException"/> instead
        /// for the same situation.
        /// Just-in-time calculation of states could take a long time so that
        /// the overall latency of an application may rise.</param>
        /// <returns>The <see cref="AddressStateMap"/> of given
        /// <paramref name="address"/>.</returns>
        /// <exception cref="IncompleteBlockStatesException">Thrown when
        /// the <see cref="BlockChain{T}"/> instance does not contain
        /// states dirty of the block which lastly updated states of a requested
        /// address, because actions in the block have never been executed.
        /// If <paramref name="completeStates"/> option is turned on
        /// this exception is not thrown and incomplete states are calculated
        /// and filled on the fly instead.
        /// </exception>
        public AddressStateMap GetState(
            Address address,
            HashDigest <SHA256>?offset = null,
            bool completeStates        = false
            )
        {
            _rwlock.EnterReadLock();
            try
            {
                if (offset == null)
                {
                    offset = Store.IndexBlockHash(Id, -1);
                }
            }
            finally
            {
                _rwlock.ExitReadLock();
            }

            var states = new AddressStateMap();

            if (offset == null)
            {
                return(states);
            }

            Block <T> block = Blocks[offset.Value];
            Tuple <HashDigest <SHA256>, long> stateReference;

            _rwlock.EnterReadLock();
            try
            {
                stateReference = Store.LookupStateReference(Id, address, block);
            }
            finally
            {
                _rwlock.ExitReadLock();
            }

            if (stateReference is null)
            {
                return(states);
            }

            HashDigest <SHA256> hashValue = stateReference.Item1;

            AddressStateMap blockStates = Store.GetBlockStates(hashValue);

            if (blockStates is null)
            {
                if (completeStates)
                {
                    // Calculates and fills the incomplete states
                    // on the fly.
                    foreach (Block <T> b in this)
                    {
                        if (!(Store.GetBlockStates(b.Hash) is null))
                        {
                            continue;
                        }

                        List <ActionEvaluation> evaluations =
                            b.Evaluate(
                                DateTimeOffset.UtcNow,
                                a => GetState(
                                    a,
                                    b.PreviousHash
                                    ).GetValueOrDefault(a)
                                ).ToList();

                        if (Policy.BlockAction is IAction)
                        {
                            evaluations.Add(EvaluateBlockAction(b, evaluations));
                        }

                        _rwlock.EnterWriteLock();

                        try
                        {
                            SetStates(b, evaluations, buildStateReferences: false);
                        }
                        finally
                        {
                            _rwlock.ExitWriteLock();
                        }
                    }

                    blockStates = Store.GetBlockStates(hashValue);
                    if (blockStates is null)
                    {
                        throw new NullReferenceException();
                    }
                }
                else
                {
                    throw new IncompleteBlockStatesException(hashValue);
                }
            }

            states = (AddressStateMap)states.SetItems(
                blockStates.Where(kv => address.Equals(kv.Key))
                );

            return(states);
        }
Example #2
0
        /// <summary>
        /// Gets the state of the given <paramref name="addresses"/> in the
        /// <see cref="BlockChain{T}"/> from <paramref name="offset"/>.
        /// </summary>
        /// <param name="addresses">The list of <see cref="Address"/>es to get
        /// their states.</param>
        /// <param name="offset">The <see cref="HashDigest{T}"/> of the block to
        /// start finding the state. It will be The tip of the
        /// <see cref="BlockChain{T}"/> if it is <c>null</c>.</param>
        /// <param name="completeStates">When the <see cref="BlockChain{T}"/>
        /// instance does not contain states dirty of the block which lastly
        /// updated states of a requested address, this option makes
        /// the incomplete states calculated and filled on the fly.
        /// If this option is turned off (which is default) this method throws
        /// <see cref="IncompleteBlockStatesException"/> instead
        /// for the same situation.
        /// Just-in-time calculation of states could take a long time so that
        /// the overall latency of an application may rise.</param>
        /// <returns>The <see cref="AddressStateMap"/> of given
        /// <paramref name="addresses"/>.</returns>
        /// <exception cref="IncompleteBlockStatesException">Thrown when
        /// the <see cref="BlockChain{T}"/> instance does not contain
        /// states dirty of the block which lastly updated states of a requested
        /// address, because actions in the block have never been executed.
        /// If <paramref name="completeStates"/> option is turned on
        /// this exception is not thrown and incomplete states are calculated
        /// and filled on the fly instead.
        /// </exception>
        public AddressStateMap GetStates(
            IEnumerable <Address> addresses,
            HashDigest <SHA256>?offset = null,
            bool completeStates        = false
            )
        {
            _rwlock.EnterReadLock();
            try
            {
                if (offset == null)
                {
                    offset = Store.IndexBlockHash(Id, -1);
                }
            }
            finally
            {
                _rwlock.ExitReadLock();
            }

            var states = new AddressStateMap();

            if (offset == null)
            {
                return(states);
            }

            Block <T> block = Blocks[offset.Value];

            ImmutableHashSet <Address> requestedAddresses =
                addresses.ToImmutableHashSet();
            var stateReferences = new HashSet <Tuple <HashDigest <SHA256>, long> >();

            foreach (var address in requestedAddresses)
            {
                Tuple <HashDigest <SHA256>, long> sr;
                _rwlock.EnterReadLock();
                try
                {
                    sr = Store.LookupStateReference(Id, address, block);
                }
                finally
                {
                    _rwlock.ExitReadLock();
                }

                if (!(sr is null))
                {
                    stateReferences.Add(sr);
                }
            }

            IEnumerable <HashDigest <SHA256> > hashValues = stateReferences
                                                            .OrderByDescending(sr => sr.Item2)
                                                            .Select(sr => sr.Item1);

            foreach (var hashValue in hashValues)
            {
                AddressStateMap blockStates = Store.GetBlockStates(hashValue);
                if (blockStates is null)
                {
                    if (completeStates)
                    {
                        // Calculates and fills the incomplete states
                        // on the fly.
                        foreach (Block <T> b in this)
                        {
                            if (!(Store.GetBlockStates(b.Hash) is null))
                            {
                                continue;
                            }

                            List <ActionEvaluation> evaluations =
                                b.Evaluate(
                                    DateTimeOffset.UtcNow,
                                    a => GetStates(
                                        new[] { a },
                                        b.PreviousHash
                                        ).GetValueOrDefault(a)
                                    ).ToList();

                            if (Policy.BlockAction is IAction)
                            {
                                evaluations.Add(EvaluateBlockAction(b, evaluations));
                            }

                            _rwlock.EnterWriteLock();

                            try
                            {
                                SetStates(b, evaluations, buildStateReferences: false);
                            }
                            finally
                            {
                                _rwlock.ExitWriteLock();
                            }
                        }

                        blockStates = Store.GetBlockStates(hashValue);
                        if (blockStates is null)
                        {
                            throw new NullReferenceException();
                        }
                    }
                    else
                    {
                        throw new IncompleteBlockStatesException(hashValue);
                    }
                }

                states = (AddressStateMap)states.SetItems(
                    blockStates.Where(kv =>
                                      requestedAddresses.Contains(kv.Key) &&
                                      !states.ContainsKey(kv.Key)
                                      )
                    );
            }

            return(states);
        }
Example #3
0
        /// <summary>
        /// Gets the state of the given <paramref name="address"/> in the
        /// <see cref="BlockChain{T}"/> from <paramref name="offset"/>.
        /// </summary>
        /// <param name="address">An <see cref="Address"/> to get
        /// the states of.</param>
        /// <param name="offset">The <see cref="HashDigest{T}"/> of the block to
        /// start finding the state. It will be The tip of the
        /// <see cref="BlockChain{T}"/> if it is <c>null</c>.</param>
        /// <param name="completeStates">When the <see cref="BlockChain{T}"/>
        /// instance does not contain states dirty of the block which lastly
        /// updated states of a requested address, this option makes
        /// the incomplete states calculated and filled on the fly.
        /// If this option is turned off (which is default) this method throws
        /// <see cref="IncompleteBlockStatesException"/> instead
        /// for the same situation.
        /// Just-in-time calculation of states could take a long time so that
        /// the overall latency of an application may rise.</param>
        /// <returns>The <see cref="AddressStateMap"/> of given
        /// <paramref name="address"/>.</returns>
        /// <exception cref="IncompleteBlockStatesException">Thrown when
        /// the <see cref="BlockChain{T}"/> instance does not contain
        /// states dirty of the block which lastly updated states of a requested
        /// address, because actions in the block have never been executed.
        /// If <paramref name="completeStates"/> option is turned on
        /// this exception is not thrown and incomplete states are calculated
        /// and filled on the fly instead.
        /// </exception>
        public AddressStateMap GetState(
            Address address,
            HashDigest <SHA256>?offset = null,
            bool completeStates        = false
            )
        {
            _rwlock.EnterReadLock();
            try
            {
                if (offset == null)
                {
                    offset = Store.IndexBlockHash(Id, -1);
                }
            }
            finally
            {
                _rwlock.ExitReadLock();
            }

            var states = new AddressStateMap();

            if (offset == null)
            {
                return(states);
            }

            Block <T> block = this[offset.Value];
            Tuple <HashDigest <SHA256>, long> stateReference;

            _rwlock.EnterReadLock();
            try
            {
                stateReference = Store.LookupStateReference(Id, address, block);
            }
            finally
            {
                _rwlock.ExitReadLock();
            }

            if (stateReference is null)
            {
                return(states);
            }

            HashDigest <SHA256> hashValue = stateReference.Item1;

            AddressStateMap blockStates = Store.GetBlockStates(hashValue);

            if (blockStates is null)
            {
                if (completeStates)
                {
                    // Calculates and fills the incomplete states
                    // on the fly.
                    foreach (HashDigest <SHA256> hash in BlockHashes)
                    {
                        Block <T> b = this[hash];
                        if (!(Store.GetBlockStates(b.Hash) is null))
                        {
                            continue;
                        }

                        IReadOnlyList <ActionEvaluation> evaluations = EvaluateActions(b);

                        _rwlock.EnterWriteLock();

                        try
                        {
                            SetStates(b, evaluations, buildStateReferences: false);
                        }
                        finally
                        {
                            _rwlock.ExitWriteLock();
                        }
                    }

                    blockStates = Store.GetBlockStates(hashValue);
                    if (blockStates is null)
                    {
                        throw new NullReferenceException();
                    }
                }
                else
                {
                    throw new IncompleteBlockStatesException(hashValue);
                }
            }

            states = (AddressStateMap)states.SetItems(
                blockStates.Where(kv => address.Equals(kv.Key))
                );

            return(states);
        }