Пример #1
0
 public Lineage(
     IReadOnlyList <CommittedBlock> committed,
     IReadOnlyList <UncommittedBlock> uncommitted,
     int coinPruneLimitDistance)
 {
     _quasiOrphans   = GetQuasiOrphans(committed, uncommitted);
     ChainTip        = GetCommittedBlockOfMaxHeight(committed);
     CoinPruneHeight = ChainTip.BlockHeight - coinPruneLimitDistance;
     _uncommitted    = new HashSet <BlockAlias>(uncommitted.Select(x => x.Alias));
 }
Пример #2
0
        /// <summary>
        /// Returns whether <see cref="block"/> is considered prunable (i.e. it can
        /// be removed from the chain). The necessary criteria for this decision
        /// are that it is not on the main chain and that its first ancestor on
        /// the main chain is below or equal to the prune limit.
        /// </summary>
        private bool IsBlockPermanentlyOrphaned(BlockAlias block)
        {
            var current       = block;
            var isInMainChain = true;

            while (_quasiOrphans.TryGetValue(current, out var parent))
            {
                isInMainChain = false;
                current       = parent;
            }

            return(!isInMainChain && current.BlockHeight <= CoinPruneHeight);
        }
Пример #3
0
        /// <summary>
        /// Returns true if <see cref="maybeAncestor"/> is an ancestor of
        /// <see cref="subject"/>, meaning they are on the same branch of the
        /// blockchain with <see cref="subject"/> being younger.
        /// </summary>
        private bool IsAncestor(BlockAlias subject, BlockAlias maybeAncestor)
        {
            if (subject.IsPrior(maybeAncestor))
            {
                return(false);
            }

            // We climb down the side chain until we find the parent,
            // a block that is lower than the maybeAncestor or we reach the main chain
            var parent = subject;

            do
            {
                // Move up the side chain looking for an ancestor on the main branch
                // A block counts as its own ancestor
                if (parent == maybeAncestor)
                {
                    return(true);
                }
                // The ancestor has to have a smaller number than anything that comes afterward.
                if (parent.IsPrior(maybeAncestor))
                {
                    return(false);
                }
            } while (_quasiOrphans.TryGetValue(parent, out parent));

            /*
             *                 o
             *                 |
             *                 o
             *                 |
             *                 o----o <- maybeAncestorAlias
             *                 |
             *                 o <- parent
             *                / \
             *  mainChain -> o   o <- subject
             */

            // Here, 'parent' is the most recent ancestor of the original block
            // ('subject') on the main chain, and 'maybeAncestor < parent', so the
            // ancestor will be an ancestor if and only if it is also on the
            // main chain.

            return(!_quasiOrphans.ContainsKey(maybeAncestor));
        }
Пример #4
0
        public bool TryGetEventsInContext(Span <CoinEvent> events, BlockAlias context, out BlockAlias production,
                                          out BlockAlias consumption)
        {
            production  = BlockAlias.Undefined;
            consumption = BlockAlias.Undefined;
            foreach (var coinEvent in events)
            {
                if (IsAncestor(context, coinEvent.BlockAlias))
                {
                    if (coinEvent.Kind == CoinEventKind.Production)
                    {
                        production = coinEvent.BlockAlias;
                    }
                    else
                    {
                        consumption = coinEvent.BlockAlias;
                    }
                }
            }

            return(production.IsDefined || consumption.IsDefined);
        }
Пример #5
0
 public bool IsUncommitted(BlockAlias block)
 {
     return(_uncommitted.Contains(block));
 }
Пример #6
0
 public CommittedBlock(CommittedBlockId blockId, BlockAlias alias, BlockAlias parent)
 {
     BlockId = blockId;
     Alias   = alias;
     Parent  = parent;
 }