예제 #1
0
        private ILineage MakeLineage()
        {
            var blockId1   = CommittedBlockId.ReadFromHex("0000000000000000000000000000000000000000000000000000000000AAA333");
            var commBlock1 = new CommittedBlock(blockId1, BlockAlias.Genesis, BlockAlias.GenesisParent);
            var blockId2   = CommittedBlockId.ReadFromHex("0000000000000000000000000000000000000000000000000000000000BBB444");
            var commBlock2 = new CommittedBlock(blockId2, new BlockAlias(2), BlockAlias.Genesis);
            var blockId3   = CommittedBlockId.ReadFromHex("0000000000000000000000000000000000000000000000000000000000CCC555");
            var commBlock3 = new CommittedBlock(blockId3, new BlockAlias(3), new BlockAlias(2));

            var uncommBlock = new UncommittedBlock(UncommittedBlockId.Create(), new BlockAlias(4), new BlockAlias(3));

            var committedBlocks = new List <CommittedBlock>();

            committedBlocks.Add(commBlock1);
            committedBlocks.Add(commBlock2);
            committedBlocks.Add(commBlock3);

            var uncommittedBlocks = new List <UncommittedBlock>();

            uncommittedBlocks.Add(uncommBlock);

            return(new Lineage(committedBlocks, uncommittedBlocks, 100));
        }
예제 #2
0
        public OpenBlockStatus TryOpenBlock(CommittedBlockId parent, out UncommittedBlock freshBlock)
        {
            var blocks     = GetBlocks();
            var blockCount = AsHeader.BlockCount;
            var lowerIndex = Math.Max(0, blockCount - BlockScanLimit);

            freshBlock = default;

            if (blockCount == 0 && !parent.Equals(CommittedBlockId.GenesisParent))
            {
                return(OpenBlockStatus.ParentNotFound);
            }

            // Find the parent, and assess the block height
            int parentBlockHeight = -1;
            var parentAlias       = BlockAlias.Undefined;

            for (var i = blockCount - 1; i >= lowerIndex; i--)
            {
                ref var candidate = ref blocks[i];
                if (candidate.IsDeleted)
                {
                    continue;
                }

                if (candidate.BlockId.Equals(parent))
                {
                    parentBlockHeight = candidate.BlockHeight;
                    parentAlias       = candidate.Alias;
                    break;
                }

                if (i == 0)
                {
                    return(OpenBlockStatus.ParentNotFound);
                }
            }
예제 #3
0
        /// <summary>
        /// Reads blockchain information from a stream in the following order:
        ///  - number of blocks to read
        ///  - blocks with Hash256 representing the blockId first, then int
        ///         representing the parentAlias
        /// The blockHeight is calculated for each block based on the
        /// blockHeight of its parent, so it should not be stored.
        /// The corresponding Serialization method is <see cref="WriteTo"/>.
        /// </summary>
        /// <returns>A new list representing the blockchain.</returns>
        public static SimpleBlockchain ReadFrom(BinaryReader reader)
        {
            var committedBlocks   = new List <CommittedBlock>();
            var uncommittedBlocks = new List <UncommittedBlock>();
            var maxBlockHeight    = 0; // track the blockHeight so that it doesn't have to be recalculated afterward

            // Read blocks
            var committedBlockCount = reader.ReadInt32();

            for (var i = 0; i < committedBlockCount; i++)
            {
                var blockId     = new BlockId(reader.ReadHash256());
                var blockAlias  = new BlockAlias(reader.ReadUInt32());
                var parentAlias = new BlockAlias(reader.ReadUInt32());

                // Only the first block can have parentAlias 0.
                if (parentAlias == BlockAlias.GenesisParent && !blockId.Equals(BlockId.Genesis) ||
                    blockAlias.IsPrior(parentAlias))
                {
                    throw new FormatException(
                              $"Parent alias {parentAlias} is an invalid parent for block {blockAlias}.");
                }

                if (!TryFindCommitted(parentAlias, committedBlocks, out var parentBlock) &&
                    !blockId.Equals(BlockId.Genesis))
                {
                    throw new ArgumentNullException($"No parent {parentAlias} found.");
                }

                // The first block, which is the only one to have parent 0, has block height 0.
                var blockHeight = parentAlias == BlockAlias.GenesisParent
                    ? 0
                    : parentBlock.BlockHeight + 1;
                var newBlock = new CommittedBlock(blockHeight, blockId, blockAlias, parentAlias);

                if (blockHeight > maxBlockHeight)
                {
                    maxBlockHeight = blockHeight;
                }

                committedBlocks.Add(newBlock);
            }

            var numUncommmittedBlocks = reader.ReadInt32();

            for (var i = 0; i < numUncommmittedBlocks; i++)
            {
                var blockId     = new TempBlockId(reader.ReadHash128());
                var blockAlias  = new BlockAlias(reader.ReadUInt32());
                var parentAlias = new BlockAlias(reader.ReadUInt32());

                // Only the first block can have parentAlias 0.
                if ((uncommittedBlocks.Count != 0 || committedBlocks.Count != 0) &&
                    parentAlias == BlockAlias.GenesisParent || blockAlias.IsPrior(parentAlias))
                {
                    throw new FormatException(
                              $"Parent alias {parentAlias} is an invalid parent for block {blockAlias}.");
                }

                int blockHeight;
                if (TryFindCommitted(parentAlias, committedBlocks, out var parentBlock))
                {
                    blockHeight = parentBlock.BlockHeight + 1;
                }
                else
                {
                    if (uncommittedBlocks.Count == 0 && committedBlocks.Count == 0 &&
                        parentAlias == BlockAlias.GenesisParent) // we're adding the first block
                    {
                        blockHeight = 1;
                    }
                    else
                    {
                        if (!TryFindUncommitted(parentAlias, uncommittedBlocks, out var uParentBlock))
                        {
                            throw new ArgumentNullException($"No parent {parentAlias} found.");
                        }
                        blockHeight = uParentBlock.BlockHeight + 1;
                    }
                }

                var newBlock = new UncommittedBlock(blockHeight, blockId, blockAlias, parentAlias);

                if (blockHeight > maxBlockHeight)
                {
                    maxBlockHeight = blockHeight;
                }

                uncommittedBlocks.Add(newBlock);
            }

            return(new SimpleBlockchain(committedBlocks, uncommittedBlocks, maxBlockHeight));
        }