/// <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); }
/// <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); }