示例#1
0
        public void CommitChildOfUncommittedParent()
        {
            _chain = new SimpleBlockchain();
            _chain.OpenFirstBlock();
            var id = _chain.OpenBlock(_1).Alias;

            Assert.Throws <ArgumentException>(() => _chain.CommitBlock(id, _hash1));
        }
示例#2
0
        public void AddBlockToCommittedParent()
        {
            _chain = new SimpleBlockchain();
            var id = _chain.OpenFirstBlock().Alias;

            _chain.CommitBlock(id, BlockId.Genesis);

            _chain.OpenBlock(_1);
        }
示例#3
0
        public void AddValidBlocksWithFork()
        {
            _chain = new SimpleBlockchain();
            var id = _chain.OpenFirstBlock().Alias;

            Assert.Equal(0, _chain.BlockchainHeight);
            _chain.CommitBlock(id, BlockId.Genesis);
            Assert.Equal(0, _chain.BlockchainHeight);

            id = _chain.OpenBlock(_1).Alias;
            Assert.Equal(1, _chain.BlockchainHeight);
            _chain.CommitBlock(id, _hash1);
            Assert.Equal(1, _chain.BlockchainHeight);
            id = _chain.OpenBlock(_2).Alias;
            Assert.Equal(2, _chain.BlockchainHeight);
            _chain.CommitBlock(id, _hash2);
            Assert.Equal(2, _chain.BlockchainHeight);
            // Second child for second block
            id = _chain.OpenBlock(_2).Alias;
            Assert.Equal(2, _chain.BlockchainHeight);
            _chain.CommitBlock(id, _hash3);
            Assert.Equal(2, _chain.BlockchainHeight);
        }
示例#4
0
        public void Setup()
        {
            var id = _chain.OpenFirstBlock().Alias;

            _chain.CommitBlock(id, BlockId.Genesis);

            id = _chain.OpenBlock(_1).Alias;
            _chain.CommitBlock(id, new BlockId(new Hash256(0x11111111UL, 0x22222222UL, 0x33333333UL, 0x44444444UL)));
            id = _chain.OpenBlock(_2).Alias;
            _chain.CommitBlock(id, new BlockId(new Hash256(0xFFFFFFFFUL, 0xEEEEEEEEUL, 0xDDDDDDDDUL, 0xCCCCCCCCUL)));
            // Second child for block 2
            id = _chain.OpenBlock(_2).Alias;
            _chain.CommitBlock(id,
                               new BlockId(new Hash256(0x1111111122UL, 0x2222222233UL, 0x3333333344UL, 0x4444444455UL)));
            // main chain prolonged
            id = _chain.OpenBlock(_3).Alias;
            _chain.CommitBlock(id,
                               new BlockId(new Hash256(0x1111111122UL, 0x2222222233UL, 0x3333333344UL, 0x4444444455UL)));
            // side chain prolonged
            id = _chain.OpenBlock(_4).Alias;
            _chain.CommitBlock(id,
                               new BlockId(new Hash256(0x1111111122UL, 0x2222222233UL, 0x3333333344UL, 0x4444444455UL)));
            // fork on end of main chain
            id = _chain.OpenBlock(_5).Alias;
            _chain.CommitBlock(id,
                               new BlockId(new Hash256(0x1111111122UL, 0x2222222233UL, 0x3333333344UL, 0x4444444455UL)));
            id = _chain.OpenBlock(_5).Alias;
            _chain.CommitBlock(id,
                               new BlockId(new Hash256(0x1111111122UL, 0x2222222233UL, 0x3333333344UL, 0x4444444455UL)));

            var chainStrategy = new BlockchainStrategies();
            var opti          = new OptimizedLineage(chainStrategy.GetQuasiOrphans(_chain), _2);

            _controller = new ControllerThread(_chain, opti, _inbox = BoundedInbox.Create(),
                                               _outbox = BoundedInbox.Create());
        }
示例#5
0
        public void RetrieveBlock()
        {
            AddValidBlocksWithForkAllUncommitted();

            Assert.True(_chain.RetrieveUncommittedBlock(_1, out var genesisBlockU));
            Assert.True(_chain.RetrieveUncommittedBlock(_2, out var firstBlockU));
            Assert.True(_chain.RetrieveUncommittedBlock(_3, out var secondBlockU));
            Assert.True(_chain.RetrieveUncommittedBlock(_4, out var forkU));

            Assert.Equal(_tmpId1, genesisBlockU.BlockId);
            Assert.Equal(_tmpId2, firstBlockU.BlockId);
            Assert.Equal(_tmpId3, secondBlockU.BlockId);
            Assert.Equal(_tmpId4, forkU.BlockId);
            Assert.Equal(_1, firstBlockU.Parent);
            Assert.Equal(_2, secondBlockU.Parent);
            Assert.Equal(_2, forkU.Parent);
            Assert.Equal(0, genesisBlockU.BlockHeight);
            Assert.Equal(1, firstBlockU.BlockHeight);
            Assert.Equal(2, secondBlockU.BlockHeight);
            Assert.Equal(2, forkU.BlockHeight);

            _chain.CommitBlock(_1, BlockId.Genesis);
            _chain.CommitBlock(_2, _hash1);
            _chain.CommitBlock(_3, _hash2);
            _chain.CommitBlock(_4, _hash3);

            Assert.True(_chain.RetrieveCommittedBlock(_1, out var genesisBlock));
            Assert.True(_chain.RetrieveCommittedBlock(_2, out var firstBlock));
            Assert.True(_chain.RetrieveCommittedBlock(_3, out var secondBlock));
            Assert.True(_chain.RetrieveCommittedBlock(_4, out var fork));

            Assert.Equal(BlockId.Genesis, genesisBlock.BlockId);
            Assert.Equal(_hash1, firstBlock.BlockId);
            Assert.Equal(_hash2, secondBlock.BlockId);
            Assert.Equal(_hash3, fork.BlockId);
            Assert.Equal(_1, firstBlock.Parent);
            Assert.Equal(_2, secondBlock.Parent);
            Assert.Equal(_2, fork.Parent);
            Assert.Equal(0, genesisBlock.BlockHeight);
            Assert.Equal(1, firstBlock.BlockHeight);
            Assert.Equal(2, secondBlock.BlockHeight);
            Assert.Equal(2, fork.BlockHeight);
        }
示例#6
0
        public void DoWork()
        // TODO: [vermorel] method should return 'true' if any work has been done
        {
            var nextMessage = _inbox.Peek();

            if (nextMessage.Length != 0)
            {
                // get message type and deserialize accordingly
                var reqType = ClientServerMessage.GetMessageType(nextMessage);
                switch (reqType)
                {
// TODO: [vermorel] I don't like to too much the code below, it's highly repetitive, factorization is needed.

                case MessageType.OpenBlock:
                    var openBlock = MessageSerializers.DeserializeOpenBlock(nextMessage);
                    UncommittedBlock block;
                    if (openBlock.ParentHandle == BlockAlias.GenesisParent && _chain.BlockchainLength == 0)
                    {
                        block = _chain.OpenFirstBlock();
                    }
                    else
                    {
                        block = _chain.OpenBlock(openBlock.ParentHandle);
                    }
                    var blockHandle =
                        new OpenedBlock(openBlock.RequestId, openBlock.ClientId, block.BlockId, block.Alias);
                    MessageSerializers.SerializeOpenedBlock(blockHandle, _responseBuffer);
                    _outbox.TryWrite(new Span <byte>(_responseBuffer, 0, OpenedBlock.SizeInBytes));
                    break;

                case MessageType.GetBlockHandle:
                    var getBlockHandle  = MessageSerializers.DeserializeGetBlockHandle(nextMessage);
                    var retrievedHandle = _chain.RetrieveAlias(getBlockHandle.BlockId);
                    var returnMessage   = new BlockHandleResponse(getBlockHandle.RequestId, getBlockHandle.ClientId,
                                                                  retrievedHandle);
                    MessageSerializers.SerializeBlockHandleResponse(returnMessage, _responseBuffer);
                    _outbox.TryWrite(new Span <byte>(_responseBuffer, 0, BlockHandleResponse.SizeInBytes));
                    break;

                case MessageType.GetUncommittedBlockHandle:
                    var getUBlockHandle  = MessageSerializers.DeserializeGetUncommittedBlockHandle(nextMessage);
                    var retrievedUHandle = _chain.RetrieveAlias(getUBlockHandle.UncommittedBlockId);
                    var returnMes        = new BlockHandleResponse(getUBlockHandle.RequestId, getUBlockHandle.ClientId,
                                                                   retrievedUHandle);
                    MessageSerializers.SerializeBlockHandleResponse(returnMes, _responseBuffer);
                    _outbox.TryWrite(new Span <byte>(_responseBuffer, 0, BlockHandleResponse.SizeInBytes));
                    break;

                case MessageType.CommitBlock:
                    var commitBlock = MessageSerializers.DeserializeCommitBlock(nextMessage);
                    _chain.CommitBlock(commitBlock.BlockHandle, commitBlock.BlockId);
                    var committedMessage =
                        new EverythingOkResponse(commitBlock.RequestId, commitBlock.ClientId);
                    MessageSerializers.SerializeEverythingOk(committedMessage, _responseBuffer);
                    _outbox.TryWrite(new Span <byte>(_responseBuffer, 0, EverythingOkResponse.SizeInBytes));
                    break;

                case MessageType.IsAncestor:
                    var isAncestor        = MessageSerializers.DeserializeIsAncestor(nextMessage);
                    var res               = _opti.IsAncestor(isAncestor.BlockHandle, isAncestor.MaybeAncestorHandle);
                    var isAncestorMessage = new AncestorResponse(isAncestor.RequestId, isAncestor.ClientId, res);
                    MessageSerializers.SerializeAncestorResponse(isAncestorMessage, _responseBuffer);
                    _outbox.TryWrite(new Span <byte>(_responseBuffer, 0, AncestorResponse.SizeInBytes));
                    break;

                case MessageType.IsPruneable:
                    var isPruneable        = MessageSerializers.DeserializeIsPruneable(nextMessage);
                    var result             = _opti.IsPruneable(isPruneable.BlockHandle);
                    var isPruneableMessage = new PruneableResponse(isPruneable.RequestId, isPruneable.ClientId, result);
                    MessageSerializers.SerializePruneableResponse(isPruneableMessage, _responseBuffer);
                    _outbox.TryWrite(new Span <byte>(_responseBuffer, 0, PruneableResponse.SizeInBytes));
                    break;

                case MessageType.GetBlockInfo:
                    var blockInfoReq = MessageSerializers.DeserializeGetBlockInfo(nextMessage);

                    // TODO: [vermorel] clarify the purpose of this test, unclear
                    if (_chain.RetrieveCommittedBlock(blockInfoReq.BlockHandle, out var blockInfoC))
                    {
                        var blockInfo =
                            new CommittedBlockInformation(blockInfoReq.RequestId, blockInfoReq.ClientId,
                                                          blockInfoC.BlockId, blockInfoC.Alias, blockInfoC.BlockHeight, blockInfoC.Parent);
                        MessageSerializers.SerializeCommittedBlockInfo(blockInfo, _responseBuffer);
                        _outbox.TryWrite(new Span <byte>(_responseBuffer, 0, CommittedBlockInformation.SizeInBytes));
                        break;
                    }
                    else
                    {
                        _chain.RetrieveUncommittedBlock(blockInfoReq.BlockHandle, out var blockInfoU);
                        var blockInfo =
                            new UncommittedBlockInformation(blockInfoReq.RequestId, blockInfoReq.ClientId,
                                                            blockInfoU.BlockId, blockInfoU.Alias, blockInfoU.BlockHeight, blockInfoU.Parent);
                        MessageSerializers.SerializeUncommittedBlockInfo(blockInfo, _responseBuffer);
                        _outbox.TryWrite(new Span <byte>(_responseBuffer, 0, UncommittedBlockInformation.SizeInBytes));
                        break;
                    }

// TODO: [vermorel] the 'default:' case should be covered with an NotSupportedException.
                }
                _inbox.Next();
                // TODO: errors are not yet handled.
            }
        }