Example #1
0
        /// <summary>
        /// Starts a new blockchain with one block.
        /// All data possibly in the committedBlocks
        /// before the call of this method is going to be deleted.
        /// </summary>
        /// <returns>The alias of the added block.</returns>
        public UncommittedBlock OpenFirstBlock()
        {
            _committed.Clear();
            _uncommitted.Clear();

            var newBlockIdentifier = TempBlockId.Create();

            var newBlock = new UncommittedBlock(0, newBlockIdentifier, BlockAlias.Genesis, BlockAlias.GenesisParent);

            _uncommitted.Add(newBlock);

            return(newBlock);
        }
Example #2
0
        /// <summary>
        /// Appends a new block to the end of the current committedBlocks.
        /// The first block cannot be added via this method,
        /// <see cref="OpenFirstBlock"/> will have to be used instead.
        /// </summary>
        /// <returns>The alias of the added block.</returns>
        public UncommittedBlock OpenBlock(BlockAlias parentAlias)
        {
            // Verify if block to add is empty
            if (parentAlias == BlockAlias.GenesisParent)
            {
                throw new ArgumentException("Blocks cannot have GenesisParent as parent.");
            }

            var parentIsNotInCBlock = !FindCommitted(block => block.Alias == parentAlias, out var parent);
            // Parent has to be a valid block.

            var parentIsNotInUBlock = !FindUncommitted(block => block.Alias == parentAlias, out var parentUnc);

            if (parentIsNotInCBlock && parentIsNotInUBlock)
            {
                throw new ArgumentException($"{parentAlias} does not exist.");
            }

            // TOOD: [vermorel] Why do we have this small forest of tests? Comment needed
            // TODO: [vermorel] Introduce a Linq-like helper 'QuickLast' to avoid the pattern '_array[_array.Length - 1]'.

            BlockAlias newBlockAlias;

            if (_uncommitted.Count == 0)
            {
                newBlockAlias = _committed[_committed.Count - 1].Alias.GetNext();
            }
            else if (_committed.Count == 0)
            {
                newBlockAlias = _uncommitted[_uncommitted.Count - 1].Alias.GetNext();
            }
            else // a committed block can have a higher alias than a non-committed one if they are on different forked chains
            {
                newBlockAlias = BlockAlias.GetJoinNext(_committed[_committed.Count - 1].Alias,
                                                       _uncommitted[_uncommitted.Count - 1].Alias);
            }

            var newBlockIdentifier  = TempBlockId.Create();
            int newBlockBlockHeight = 1 + (parentIsNotInCBlock ? parentUnc.BlockHeight : parent.BlockHeight);

            var newBlock = new UncommittedBlock(newBlockBlockHeight, newBlockIdentifier, newBlockAlias, parentAlias);

            _uncommitted.Add(newBlock);
            if (newBlockBlockHeight > BlockchainHeight)
            {
                BlockchainHeight = newBlockBlockHeight;
            }

            return(newBlock);
        }
Example #3
0
 private bool FindUncommitted(Predicate <UncommittedBlock> p, out UncommittedBlock foundBlock)
 {
     foundBlock = _uncommitted.FindLast(p);
     return(!foundBlock.Equals(default(UncommittedBlock)));
 }
Example #4
0
 /// <summary>
 /// Returns the block metadata of the uncommitted block
 /// identified by the alias given as argument.
 /// </summary>
 public bool RetrieveUncommittedBlock(BlockAlias alias, out UncommittedBlock block)
 {
     return(FindUncommitted(b => b.Alias == alias, out block));
 }