예제 #1
0
        public void AddOversizedProductionTest()
        {
            var volatileStore = new VolatilePackStore(1, new[] { 4096, 4096 });
            var hash          = GetMockHash().Object;
            var rand          = new Random(2);

            var sozu = GetSozuTable(volatileStore, hash);

            var context = new BlockAlias(123, 0);

            for (var i = 0; i < 3; ++i)
            {
                var coin = GetCoin(rand);
                var ret  = sozu.AddProduction(hash.Hash(ref coin.Outpoint), ref coin.Outpoint, false, coin.Payload,
                                              context,
                                              new MockLineage());
                Assert.Equal(CoinChangeStatus.Success, ret);
            }

            var coin2 = GetCoin(rand, SozuTable.PayloadOversizeInBytes + 10, new BlockAlias(123, 0));

            var ret2 = sozu.AddProduction(hash.Hash(ref coin2.Outpoint), ref coin2.Outpoint, false, coin2.Payload,
                                          context,
                                          new MockLineage());

            Assert.Equal(CoinChangeStatus.Success, ret2);
            var pl = volatileStore.Read(volatileStore.LayerCount - 1, 0);

            Assert.True(pl.TryGet(ref coin2.Outpoint, out var coin2_p0));
            Assert.True(coin2.Span.SequenceEqual(coin2_p0.Span));
        }
예제 #2
0
        public void AddProductionThenOverflowTest()
        {
            var volatileStore = new VolatilePackStore(1, new[] { 4096, 4096 });
            var hash          = GetMockHash().Object;
            var rand          = new Random(2);

            var sozu = GetSozuTable(volatileStore, hash);

            int cumulSize = 0;

            do
            {
                var coin    = GetCoin(rand);
                var context = new BlockAlias(123, 0);
                var ret     = sozu.AddProduction(hash.Hash(ref coin.Outpoint), ref coin.Outpoint, false, coin.Payload,
                                                 context,
                                                 new MockLineage());

                Assert.Equal(CoinChangeStatus.Success, ret);
                cumulSize += coin.SizeInBytes;
            } while (cumulSize <= 4096);

            var p0 = volatileStore.Read(0, 0);

            Assert.True(p0.OutpointSigCount > 0);
        }
예제 #3
0
        public void OverflowToLastLayerTest()
        {
            var volatileStore = new VolatilePackStore(1, new[] { 4096, 4096 });
            var hash          = GetMockHash().Object;
            var rand          = new Random(2);

            var sozu = GetSozuTable(volatileStore, hash);

            int cumulSize = 0;

            do
            {
                var coin    = GetCoin(rand);
                var context = new BlockAlias(123, 0);
                var ret     = sozu.AddProduction(hash.Hash(ref coin.Outpoint), ref coin.Outpoint, false, coin.Payload,
                                                 context,
                                                 new MockLineage());

                Assert.Equal(CoinChangeStatus.Success, ret);
                cumulSize += coin.SizeInBytes;
            } while (cumulSize <= 4096 * 2);

            var p0 = volatileStore.Read(0, 0);

            Assert.True(p0.OutpointSigCount > 0, "First layer doesn't have probabilistic filter.");

            var p1 = volatileStore.Read(1, 0);

            var pl = volatileStore.Read(volatileStore.LayerCount - 1, 0);

            Assert.True(pl.CoinCount > 0, "Last layer doesn't have any coin.");

            Assert.True(p1.CoinCount + pl.CoinCount == p0.OutpointSigCount, "probabilistic filter count mismatches" +
                        "deeper layers coins count.");
        }
예제 #4
0
        public void AddConsumption_InConsistentContext_Test()
        {
            var volatileStore = new VolatilePackStore(1, new[] { 4096 });
            var hash          = GetMockHash().Object;
            var rand          = new Random(2);

            var sozu = GetSozuTable(volatileStore, hash);

            var context = new BlockAlias(123, 0);
            var coin1   = GetCoin(rand);

            var ret1 = sozu.AddProduction(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, false, coin1.Payload,
                                          context,
                                          new MockLineage());

            Assert.Equal(CoinChangeStatus.Success, ret1);

            for (var i = 0; i < 3; ++i)
            {
                var coin = GetCoin(rand);
                var ret  = sozu.AddProduction(hash.Hash(ref coin.Outpoint), ref coin.Outpoint, false, coin.Payload,
                                              context,
                                              new MockLineage());
                Assert.Equal(CoinChangeStatus.Success, ret);
            }

            ret1 = sozu.AddConsumption(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, context,
                                       new MockLineage(() => false));

            Assert.Equal(CoinChangeStatus.InvalidContext, ret1);
        }
예제 #5
0
        public void AliasHandleRoundTrip()
        {
            var rand = new Random(42);

            for (var i = 0; i < 70000; i++)
            {
                for (var j = 0; j < 64; j++)
                {
                    var alias = new BlockAlias(i, j);

                    Assert.True(alias.IsDefined);
                    Assert.Equal(i, alias.BlockHeight);
                    Assert.Equal(j, alias.SubIndex);

                    var mask = new ClientId((uint)rand.Next()).Mask;

                    var handle = alias.ConvertToBlockHandle(mask);

                    Assert.True(handle.IsDefined);

                    var aliasBis = handle.ConvertToBlockAlias(mask);

                    Assert.Equal(alias, aliasBis);
                }
            }
        }
예제 #6
0
        public void TryGetTest()
        {
            var volatileStore = new VolatilePackStore(1, new[] { 4096 });
            var hash          = GetMockHash().Object;
            var rand          = new Random(2);

            var pack = volatileStore.Read(0, 0);

            pack.Append(GetCoin(rand, new BlockAlias(123, 0)));
            pack.Append(GetCoin(rand, new BlockAlias(123, 0)));
            var coin1 = GetCoin(rand, new BlockAlias(123, 0));

            pack.Append(coin1);
            var context = new BlockAlias(123, 0);

            Coin coin2;
            var  sozu = GetSozuTable(volatileStore, hash);
            bool res  = sozu.TryGet(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, context,
                                    new MockLineage((out BlockAlias result) => result = context, MockLineage.Undefined),
                                    out coin2, out var production, out var consumption);

            Assert.True(res, "Sozu2 TryGet failed to get an existing outpoint.");
            Assert.True(coin1.Span.SequenceEqual(coin2.Span), "Sozu2 TryGet mismatch.");
            Assert.Equal(production, context);
            Assert.False(consumption.IsDefined);

            Coin coin3 = GetCoin(rand);

            res = sozu.TryGet(hash.Hash(ref coin3.Outpoint), ref coin3.Outpoint, context, new MockLineage(),
                              out coin2, out var production3, out var consumption3);
            Assert.False(res, "Sozu2 TryGet returns an nonexistent outpoint.");
        }
예제 #7
0
        public bool TryGet(ulong outpointHash, ref Outpoint outpoint, BlockAlias context, ILineage lineage, out Coin coin,
                           out BlockAlias production, out BlockAlias consumption)
        {
            production  = BlockAlias.Undefined;
            consumption = BlockAlias.Undefined;

            if (_coins.TryGetValue(outpoint, out var fatCoin))
            {
                foreach (var ev in fatCoin.Events)
                {
                    if (ev.Kind == CoinEventKind.Production)
                    {
                        production = ev.BlockAlias;
                    }

                    if (ev.Kind == CoinEventKind.Consumption)
                    {
                        consumption = ev.BlockAlias;
                    }
                }

                if (lineage == null || lineage.TryGetEventsInContext(fatCoin.Events.ToArray(), context, out production, out consumption))
                {
                    coin = fatCoin.Coin;

                    return(true);
                }
            }

            coin = Coin.Empty;
            return(false);
        }
예제 #8
0
        private static unsafe Coin GetCoin(Random rand, BlockAlias production)
        {
            var coin = new Coin(new byte[4096]);

            var outpoint = new Outpoint();

            for (var i = 0; i < 32; i++)
            {
                outpoint.TxId[i] = (byte)rand.Next();
            }
            outpoint.TxIndex = rand.Next();

            coin.Outpoint = outpoint;

            var events = new[] { new CoinEvent(production, CoinEventKind.Production) };

            coin.SetEvents(events);

            var script = new byte[100];

            rand.NextBytes(script);

            var payload = new Payload(new byte[100 + sizeof(uint) + sizeof(ulong) + sizeof(int)]);

            payload.NLockTime = (uint)rand.Next();
            payload.Satoshis  = (ulong)rand.Next();
            payload.Append(script);

            coin.SetPayload(payload);

            return(coin);
        }
예제 #9
0
 public bool TryGetEventsInContext(Span <CoinEvent> events, BlockAlias context, out BlockAlias production,
                                   out BlockAlias consumption)
 {
     _readProduction(out production);
     _readConsumption(out consumption);
     return(true);
 }
예제 #10
0
        public GetCoinResponse(
            RequestId requestId,
            ClientId clientId,
            GetCoinStatus status,
            ref Outpoint outpoint,
            OutpointFlags flags,
            BlockAlias context,
            BlockAlias production,
            BlockAlias consumption,
            ulong satoshis,
            uint nLockTime,
            Span <byte> script,
            BlockHandleMask mask,
            SpanPool <byte> pool)
        {
            var messageSizeInBytes = Header.SizeInBytes + script.Length;

            _buffer = pool.GetSpan(messageSizeInBytes);

            AsHeader.ResponseHeader.MessageSizeInBytes = messageSizeInBytes;
            AsHeader.ResponseHeader.RequestId          = requestId;
            AsHeader.ResponseHeader.ClientId           = clientId;
            AsHeader.ResponseHeader.MessageKind        = MessageKind.GetCoinResponse;

            AsHeader.Status      = status;
            AsHeader.Outpoint    = outpoint;
            AsHeader.Flags       = flags;
            AsHeader.Context     = context.ConvertToBlockHandle(mask);
            AsHeader.Production  = production.ConvertToBlockHandle(mask);
            AsHeader.Consumption = consumption.ConvertToBlockHandle(mask);
            AsHeader.Satoshis    = satoshis;
            AsHeader.NLockTime   = nLockTime;

            script.CopyTo(_buffer.Slice(Header.SizeInBytes));
        }
예제 #11
0
        /// <summary>
        /// Allocate an array. Intended for testing purposes only.
        /// </summary>
        internal static ProduceCoinRequest From(
            RequestId requestId,
            ClientId clientId,
            Outpoint outpoint,
            OutpointFlags flags,
            BlockAlias context,
            ulong satoshis,
            uint nLockTime,
            Span <byte> script,
            BlockHandleMask mask)
        {
            var request = new ProduceCoinRequest
            {
                _buffer = new Span <byte>(new byte[Header.SizeInBytes + script.Length])
            };

            request.MessageHeader.MessageSizeInBytes = Header.SizeInBytes + script.Length;
            request.MessageHeader.RequestId          = requestId;
            request.MessageHeader.ClientId           = clientId;
            request.MessageHeader.MessageKind        = MessageKind.ProduceCoin;

            request.AsHeader.Outpoint  = outpoint;
            request.AsHeader.Flags     = flags;
            request.AsHeader.Context   = context.ConvertToBlockHandle(mask);
            request.AsHeader.Satoshis  = satoshis;
            request.AsHeader.NLockTime = nLockTime;

            script.CopyTo(request._buffer.Slice(Header.SizeInBytes));

            return(request);
        }
예제 #12
0
        public void RemoveSigsAfterPruningTest()
        {
            var hash          = GetMockHash().Object;
            var rand          = new Random(2);
            var volatileStore = new VolatilePackStore(1, new[] { 4096, 4096 });
            var sozu          = GetSozuTable(volatileStore, hash);
            var lineage       = new MockLineage();
            var pruneCount    = 3;

            int cumulSize = 0;

            for (var i = 0; i < pruneCount; i++)
            {
                var coin1 = GetCoin(rand);
                var ret1  = sozu.AddProduction(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, false, coin1.Payload,
                                               MockLineage.CoinEventToPrune.BlockAlias, lineage);
                Assert.Equal(CoinChangeStatus.Success, ret1);
                cumulSize += coin1.SizeInBytes;
            }

            do
            {
                var coin    = GetCoin(rand);
                var context = new BlockAlias(123, 0);
                var ret     = sozu.AddProduction(hash.Hash(ref coin.Outpoint), ref coin.Outpoint, false, coin.Payload,
                                                 context, lineage);

                Assert.Equal(CoinChangeStatus.Success, ret);
                cumulSize += coin.SizeInBytes;
            } while (cumulSize <= 4096);

            var p0 = volatileStore.Read(0, 0);

            cumulSize = p0.SizeInBytes;
            int sigsCount = 0;
            int opCount   = 0;

            do
            {
                var coin    = GetCoin(rand);
                var context = new BlockAlias(123, 0);
                if (cumulSize + coin.SizeInBytes > 4096)
                {
                    p0                    = volatileStore.Read(0, 0);
                    sigsCount             = p0.OutpointSigCount;
                    opCount               = p0.CoinCount + 1;
                    lineage.PruningActive = true;
                }

                var ret = sozu.AddProduction(hash.Hash(ref coin.Outpoint), ref coin.Outpoint, false, coin.Payload,
                                             context, lineage);

                Assert.Equal(CoinChangeStatus.Success, ret);
                cumulSize += coin.SizeInBytes;
            } while (cumulSize <= 4096);

            p0 = volatileStore.Read(0, 0);
            Assert.True(opCount - p0.CoinCount + sigsCount - p0.OutpointSigCount == pruneCount);
        }
예제 #13
0
        public void ConvertToBlockAlias()
        {
            var alias           = new BlockAlias(100, 1);
            var handle          = alias.ConvertToBlockHandle(new BlockHandleMask(0x5678abcd));
            var aliasFromHandle = handle.ConvertToBlockAlias(new BlockHandleMask(0x5678abcd));

            Assert.Equal(alias, aliasFromHandle);
        }
예제 #14
0
 /// <summary>
 /// Allocate an array. Intended for testing purposes only.
 /// </summary>
 internal static ConsumeCoinRequest From(RequestId requestId,
                                         ref Outpoint outpoint,
                                         BlockAlias context,
                                         BlockHandleMask mask)
 {
     return(new ConsumeCoinRequest(requestId, ref outpoint,
                                   context.ConvertToBlockHandle(mask), new SpanPool <byte>(Header.SizeInBytes)));
 }
예제 #15
0
        public static GetBlockInformation DeserializeGetBlockInfo(ReadOnlySpan <byte> message)
        {
            var editor = new SpanBinaryReader(message);
            var header = ParseMessageHeader(ref editor, GetBlockInformation.Info);

            var blockHandle = new BlockAlias(editor.ReadUInt32());

            return(new GetBlockInformation(header.RequestId, header.ClientId, blockHandle));
        }
예제 #16
0
        public static OpenBlock DeserializeOpenBlock(ReadOnlySpan <byte> message)
        {
            var editor = new SpanBinaryReader(message);

            var header      = ParseMessageHeader(ref editor, OpenBlock.Info);
            var parentAlias = new BlockAlias(editor.ReadUInt32());

            return(new OpenBlock(header.RequestId, header.ClientId, parentAlias));
        }
예제 #17
0
        public static BlockHandle ConvertToBlockHandle(this BlockAlias alias, BlockHandleMask mask)
        {
            if (!alias.IsDefined)
            {
                return(BlockHandle.Undefined);
            }

            // Idem, see above.
            return(new BlockHandle(alias.Value ^ (~0x01u & (BlockHandle.DefaultMask ^ mask.Value))));
        }
예제 #18
0
 public OpenedBlock(
     uint requestId,
     uint clientId,
     TempBlockId uncommittedBlockId,
     BlockAlias alias)
     : base(requestId, clientId, MessageType.OpenedBlock)
 {
     UncommittedBlockId = uncommittedBlockId;
     Alias = alias;
 }
예제 #19
0
        public static CommitBlock DeserializeCommitBlock(ReadOnlySpan <byte> message)
        {
            var editor = new SpanBinaryReader(message);

            var header = ParseMessageHeader(ref editor, CommitBlock.Info);

            var blockHandle = new BlockAlias(editor.ReadUInt32());
            var blockId     = BlockId.Create(ref editor);

            return(new CommitBlock(header.RequestId, header.ClientId, blockHandle, blockId));
        }
예제 #20
0
        public GetBlockHandleResponse(
            ref MessageHeader requestHeader, BlockHandleMask mask, BlockAlias alias, SpanPool <byte> pool)
        {
            _buffer = pool.GetSpan(Header.SizeInBytes);

            AsHeader.ResponseHeader = requestHeader;

            AsHeader.ResponseHeader.MessageKind        = MessageKind.BlockHandleResponse;
            AsHeader.ResponseHeader.MessageSizeInBytes = Header.SizeInBytes;

            AsHeader.Status = GetBlockHandleStatus.Success;
            AsHeader.Handle = alias.ConvertToBlockHandle(mask);
        }
예제 #21
0
 public UncommittedBlockInformation(
     uint requestId,
     uint clientId,
     TempBlockId uncommittedBlockId,
     BlockAlias alias,
     int height,
     BlockAlias parent) :
     base(requestId, clientId, MessageType.UncommittedBlockInfo)
 {
     BlockHeight        = height;
     UncommittedBlockId = uncommittedBlockId;
     Alias  = alias;
     Parent = parent;
 }
예제 #22
0
 public CommittedBlockInformation(
     uint requestId,
     uint clientId,
     BlockId blockId,
     BlockAlias alias,
     int height,
     BlockAlias parent) :
     base(requestId, clientId, MessageType.CommittedBlockInfo)
 {
     BlockHeight = height;
     BlockId     = blockId;
     Alias       = alias;
     Parent      = parent;
 }
예제 #23
0
        public OpenBlockResponse(
            ref MessageHeader requestHeader, BlockHandleMask mask, BlockAlias alias, UncommittedBlockId uncommittedBlockId, SpanPool <byte> pool)
        {
            _buffer = pool.GetSpan(Header.SizeInBytes);

            AsHeader.ResponseHeader = requestHeader;

            AsHeader.ResponseHeader.MessageKind        = MessageKind.OpenBlockResponse;
            AsHeader.ResponseHeader.MessageSizeInBytes = Header.SizeInBytes;

            AsHeader.Status             = OpenBlockStatus.Success;
            AsHeader.Handle             = alias.ConvertToBlockHandle(mask);
            AsHeader.UncommittedBlockId = uncommittedBlockId;
        }
예제 #24
0
        public CoinChangeStatus Remove(ulong outpointHash, ref Outpoint outpoint, BlockAlias context, CoinRemoveOption option,
                                       ILineage lineage)
        {
            if (!_coins.TryGetValue(outpoint, out var fatCoin))
            {
                return(CoinChangeStatus.OutpointNotFound);
            }

            fatCoin.Events.RemoveAll(ev => ev.BlockAlias == context &&
                                     (((option & CoinRemoveOption.RemoveProduction) != 0 &&
                                       ev.Kind == CoinEventKind.Production) ||
                                      ((option & CoinRemoveOption.RemoveConsumption) != 0 &&
                                       ev.Kind == CoinEventKind.Consumption)));

            return(CoinChangeStatus.Success);
        }
예제 #25
0
        public void TryAddConsumptionInSideChainTest()
        {
            var volatileStore = new VolatilePackStore(1, new[] { 4096 });
            var hash          = GetMockHash().Object;
            var rand          = new Random(2);

            // Create a real lineage
            var cBlocks = new List <CommittedBlock>();

            cBlocks.Add(new CommittedBlock(CommittedBlockId.Genesis, BlockAlias.Genesis, BlockAlias.GenesisParent));

            var uncBlocks = new List <UncommittedBlock>();

            var firstBlockAlias = new BlockAlias(1, 0);
            var uncId           = new byte[16];

            rand.NextBytes(uncId);

            uncBlocks.Add(new UncommittedBlock(
                              UncommittedBlockId.ReadFrom(uncId),
                              firstBlockAlias, BlockAlias.Genesis));

            var parallelBlockAlias = new BlockAlias(1, 1);

            rand.NextBytes(uncId);

            uncBlocks.Add(new UncommittedBlock(
                              UncommittedBlockId.ReadFrom(uncId),
                              parallelBlockAlias, BlockAlias.Genesis));

            var realLineage = new Lineage(cBlocks, uncBlocks, 100);

            var sozu = GetSozuTable(volatileStore, hash);

            var coin1 = GetCoin(rand);

            var ret = sozu.AddProduction(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, false, coin1.Payload,
                                         firstBlockAlias,
                                         realLineage);

            Assert.Equal(CoinChangeStatus.Success, ret);

            var cons = sozu.AddConsumption(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, parallelBlockAlias,
                                           realLineage);

            Assert.Equal(CoinChangeStatus.InvalidContext, cons);
        }
예제 #26
0
        public void ReadExistingCoin()
        {
            var sozu = new VolatileCoinStore();

            var inbox      = new BoundedInbox();
            var outbox     = new BoundedInbox();
            var controller = new CoinController(inbox, outbox, sozu, _hash);

            var coin = GetCoin(_rand);

            sozu.AddProduction(
                _hash.Hash(ref coin.Outpoint),
                ref coin.Outpoint,
                false, coin.Payload,
                new BlockAlias(3),
                null); // lineage is not used in VolatileCoinStore

            var clientId = new ClientId();
            var reqId    = new RequestId(1);

            var context = new BlockAlias(3);

            var readCoinRequest = GetCoinRequest.From(reqId, clientId, coin.Outpoint, context, clientId.Mask);

            inbox.TryWrite(readCoinRequest.Span);
            controller.HandleRequest();

            var raw      = outbox.Peek();
            var response = new GetCoinResponse(raw.Span);

            Assert.Equal(response.MessageHeader.MessageSizeInBytes, raw.Length);

            // verify response contents
            Assert.Equal(reqId, response.MessageHeader.RequestId);
            Assert.Equal(clientId, response.MessageHeader.ClientId);
            Assert.Equal(MessageKind.GetCoinResponse, response.MessageHeader.MessageKind);
            Assert.Equal(coin.Outpoint, response.Outpoint);
            Assert.Equal(OutpointFlags.None, response.OutpointFlags);
            Assert.Equal(context, response.Context.ConvertToBlockAlias(clientId.Mask));
            Assert.Equal(context, response.Production.ConvertToBlockAlias(clientId.Mask));
            Assert.Equal(BlockAlias.Undefined.ConvertToBlockHandle(clientId.Mask), response.Consumption);
            Assert.Equal(coin.Payload.Satoshis, response.Satoshis);
            Assert.Equal(coin.Payload.NLockTime, response.NLockTime);
            Assert.True(coin.Payload.Script.SequenceEqual(response.Script));
        }
예제 #27
0
        public void RemoveConsumption_Test()
        {
            var volatileStore = new VolatilePackStore(1, new[] { 4096 });
            var hash          = GetMockHash().Object;
            var rand          = new Random(2);

            var sozu = GetSozuTable(volatileStore, hash);

            var context = new BlockAlias(123, 0);
            var coin1   = GetCoin(rand);

            var ret1 = sozu.AddProduction(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, false, coin1.Payload,
                                          context,
                                          new MockLineage());

            Assert.Equal(CoinChangeStatus.Success, ret1);

            ret1 = sozu.AddConsumption(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, context,
                                       new MockLineage());

            Assert.Equal(CoinChangeStatus.Success, ret1);

            for (var i = 0; i < 3; ++i)
            {
                var coin = GetCoin(rand);
                var ret  = sozu.AddProduction(hash.Hash(ref coin.Outpoint), ref coin.Outpoint, false, coin.Payload,
                                              context,
                                              new MockLineage());
                Assert.Equal(CoinChangeStatus.Success, ret);
            }

            ret1 = sozu.Remove(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, context,
                               CoinRemoveOption.RemoveConsumption,
                               new MockLineage(MockLineage.Undefined, (out BlockAlias result) => result = context));

            Assert.Equal(CoinChangeStatus.Success, ret1);
            var p0 = volatileStore.Read(0, 0);

            Assert.True(p0.TryGet(ref coin1.Outpoint, out var coin1_p0));
            Assert.Equal(1, coin1_p0.Events.Length);
            Assert.Equal(coin1_p0.Events[0], new CoinEvent(context, CoinEventKind.Production));
            Assert.True(coin1_p0.Payload.Span.SequenceEqual(coin1.Payload.Span));
        }
예제 #28
0
        public void AddConsumptionTest()
        {
            var volatileStore = new VolatilePackStore(1, new[] { 4096 });
            var hash          = GetMockHash().Object;
            var rand          = new Random(2);

            var sozu = GetSozuTable(volatileStore, hash);

            var context = new BlockAlias(123, 0);
            var coin1   = GetCoin(rand);

            var ret1 = sozu.AddProduction(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, false, coin1.Payload,
                                          context,
                                          new MockLineage());

            Assert.Equal(CoinChangeStatus.Success, ret1);

            for (var i = 0; i < 3; ++i)
            {
                var coin = GetCoin(rand);
                var ret  = sozu.AddProduction(hash.Hash(ref coin.Outpoint), ref coin.Outpoint, false, coin.Payload,
                                              context,
                                              new MockLineage());
                Assert.Equal(CoinChangeStatus.Success, ret);
            }

            ret1 = sozu.AddConsumption(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, context,
                                       new MockLineage());

            Assert.Equal(CoinChangeStatus.Success, ret1);

            // test add consumption idempotence
            ret1 = sozu.AddConsumption(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, context,
                                       new MockLineage(() => false));

            Assert.Equal(CoinChangeStatus.Success, ret1);

            var p0 = volatileStore.Read(0, 0);

            Assert.True(p0.TryGet(ref coin1.Outpoint, out var coin1_p0));
            Assert.Equal(2, coin1_p0.Events.Length);
            Assert.True(coin1_p0.Payload.Span.SequenceEqual(coin1.Payload.Span));
        }
예제 #29
0
        public void GetPriorAlias()
        {
            var alias      = new BlockAlias(100, 1);
            var priorAlias = alias.GetPriorAlias(50);

            Assert.Equal(priorAlias, new BlockAlias(50, 0));

            priorAlias = alias.GetPriorAlias(100);
            Assert.Equal(priorAlias, new BlockAlias(0, 0));

            priorAlias = alias.GetPriorAlias(101);
            Assert.Equal(priorAlias, BlockAlias.GenesisParent);

            priorAlias = alias.GetPriorAlias(0);
            Assert.Equal(priorAlias, new BlockAlias(100, 0));

            // negative values are not allowed anymore
            //Assert.Throws<ArgumentException>(() => alias.GetPriorAlias(-1));
            //Assert.Throws<ArgumentException>(() => alias.GetPriorAlias(-100));
        }
예제 #30
0
        public void TryAddConsumptionInPastTest()
        {
            var volatileStore = new VolatilePackStore(1, new[] { 4096 });
            var hash          = GetMockHash().Object;
            var rand          = new Random(2);

            // Create a real lineage
            var cBlocks = new List <CommittedBlock>();

            cBlocks.Add(new CommittedBlock(CommittedBlockId.Genesis, BlockAlias.Genesis, BlockAlias.GenesisParent));
            var firstBlockAlias = new BlockAlias(1, 0);

            cBlocks.Add(new CommittedBlock(
                            CommittedBlockId.ReadFromHex("AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDAAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD"),
                            firstBlockAlias, BlockAlias.Genesis));
            var futureBlockAlias = new BlockAlias(2, 0);

            cBlocks.Add(new CommittedBlock(
                            CommittedBlockId.ReadFromHex("AAAABBBBBBBBCCCCCCCCDDDDDDDDAAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDAAAA"),
                            futureBlockAlias, firstBlockAlias));

            var realLineage = new Lineage(cBlocks, new List <UncommittedBlock>(), 100);

            var sozu = GetSozuTable(volatileStore, hash);

            var coin1 = GetCoin(rand);

            // The next two commands will work because the fact that a block is uncommitted is not verified anymore.
            // If this test is moved into the ICoinStore at any point, adding a previous consumption should fail
            // already because a 'previous' block always has to be committed.
            var ret = sozu.AddProduction(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, false, coin1.Payload,
                                         futureBlockAlias,
                                         realLineage);

            Assert.Equal(CoinChangeStatus.Success, ret);

            var cons = sozu.AddConsumption(hash.Hash(ref coin1.Outpoint), ref coin1.Outpoint, firstBlockAlias,
                                           realLineage);

            Assert.Equal(CoinChangeStatus.InvalidContext, cons);
        }