Beispiel #1
0
 public SozuFactory(ILineage lineage,
                    Hash256 start, Hash256 end, SozuFactoryConfig[] sozuFactoryConfig,
                    string path)
 {
     _lineage           = lineage;
     _start             = start;
     _end               = end;
     _sozuFactoryConfig = sozuFactoryConfig;
     _path              = path;
 }
Beispiel #2
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);
        }
Beispiel #3
0
        public CoinChangeStatus AddConsumption(ulong outpointHash, ref Outpoint outpoint, BlockAlias context,
                                               ILineage lineage)
        {
            if (!_coins.TryGetValue(outpoint, out var fatCoin))
            {
                return(CoinChangeStatus.OutpointNotFound);
            }

            var consumption = new CoinEvent(context, CoinEventKind.Consumption);

            if (fatCoin.Events.Contains(consumption))
            {
                return(CoinChangeStatus.Success);
            }

            fatCoin.Events.Add(consumption);
            return(CoinChangeStatus.Success);
        }
Beispiel #4
0
        /// <param name="config"></param>
        /// <param name="lineage"></param>
        /// <param name="store"></param>
        /// <param name="subTable"></param>
        public SozuTable(SozuConfig config, ILineage lineage, ISectorStore store, SozuTable subTable = null)
        {
            _config   = config;
            _lineage  = lineage;
            _store    = store;
            _subTable = subTable;

            _residue      = TxoPack.Create();
            _rangeOutputs = TxoPack.Create();
            _deserialized = TxoPack.Create();
            _complement   = TxoPack.Create();
            _kept         = TxoPack.Create();
            _flowDown     = TxoPack.Create();
            _merged       = TxoPack.Create(2);
            store.Initialize();
            if (config.ImplicitSectors && !store.HasSectors())
            {
                store.AllocateSectors(1 << config.SectorBitDepth);
                EnsurePersistence();
            }
        }
Beispiel #5
0
        public CoinChangeStatus AddProduction(ulong outpointHash, ref Outpoint outpoint, bool isCoinBase, Payload payload,
                                              BlockAlias context, ILineage lineage)
        {
            var production = new CoinEvent(context, CoinEventKind.Production);

            if (_coins.TryGetValue(outpoint, out var fatCoin))
            {
                if (fatCoin.Events.Contains(production))
                {
                    return(CoinChangeStatus.Success); // done
                }
                fatCoin.Events.Add(production);

                return(CoinChangeStatus.Success);
            }

            var coin = new Coin(ref outpoint, isCoinBase, payload, production, _pool);

            _coins.Add(outpoint, new FatCoin(coin, production));

            return(CoinChangeStatus.Success);
        }
Beispiel #6
0
        // HACK: [vermorel] Constructor used as the setup of the unit tests, should be refactored.
        public LineageTests()
        {
            var store = new VolatileChainStore();

            //var chain = new SimpleBlockchain();
            store.TryOpenBlock(CommittedBlockId.GenesisParent, out var b0);
            var id = b0.Alias;

            // U(0)
            store.TryCommitBlock(id, CommittedBlockId.Genesis, out _);
            // C(0)
            store.TryOpenBlock(CommittedBlockId.Genesis, out var b1);
            Assert.Equal(_1, b1.Alias);
            // C(0) -> U(1)
            store.TryCommitBlock(_1, _id_1, out _);
            // C(0) -> C(1)
            store.TryOpenBlock(_id_1, out var b2);
            Assert.Equal(_2_0, b2.Alias);
            // C(0) -> C(1) -> U(2)
            store.TryCommitBlock(_2_0, _id_2_0, out _);
            // C(0) -> C(1) -> C(2)
            // Second child for second block
            store.TryOpenBlock(_id_1, out var b21);
            Assert.Equal(_2_1, b21.Alias);
            // C(0) -> C(1) -> C(2)
            //             \-> U(2-1)
            store.TryCommitBlock(_2_1, _id_2_1, out _);
            // C(0) -> C(1) -> C(2)
            //             \-> C(2-1)

            var lineage = (Lineage)store.GetLineage();

            lineage.CoinPruneHeight = _1.BlockHeight;

            _lineage = lineage;
        }
Beispiel #7
0
        public CoinChangeStatus AddProduction(
            ulong outpointHash,
            ref Outpoint outpoint,
            bool isCoinBase,
            Payload payload,
            BlockAlias context,
            ILineage lineage)
        {
            try
            {
                var sectorIndex = (uint)(outpointHash % (uint)_store.SectorCount);
                var sig         = OutpointSig.From(outpointHash);
                var evt         = new CoinEvent(context, CoinEventKind.Production);

                // Oversized payload, insert in the last layer directly.
                if (payload.SizeInBytes > PayloadOversizeInBytes)
                {
                    // HACK: [vermorel] edge-case, is-it possible to have an oversized coinbase?
                    return(AddOversizedProduction(sectorIndex, sig, ref outpoint, isCoinBase, payload, evt, lineage));
                }

                // Layer 0, the only layer to have outpoint signatures.
                var pack0 = _store.Read(layerIndex: 0, sectorIndex);

                var extendedPack = CoinPack.Empty;

                // The coin already exists on another chain.
                if (pack0.TryGet(ref outpoint, out var coin, out var coinOffset))
                {
                    if (coin.HasEvent(evt))
                    {
                        return(CoinChangeStatus.Success);
                    }

                    if (!lineage.IsAddConsistent(coin.Events, evt))
                    {
                        return(CoinChangeStatus.InvalidContext);
                    }

                    // HACK: [vermorel] edge-case, is-it possible to have the same coinbase on multiple chains?
                    extendedPack = CoinPack.WithExtraCoinEvent(pack0, coin, coinOffset, evt, _pool);
                }
                // A probabilistic match exists, checking deeper layers.
                else if (pack0.PositiveMatch(sig))
                {
                    for (var layerIndex = 1; layerIndex < _store.LayerCount; layerIndex++)
                    {
                        // Check deeper layers
                        var packN = _store.Read(layerIndex: layerIndex, sectorIndex);
                        if (packN.TryGet(ref outpoint, out coin, out coinOffset))
                        {
                            if (coin.HasEvent(evt))
                            {
                                return(CoinChangeStatus.Success);
                            }

                            if (!lineage.IsAddConsistent(coin.Events, evt))
                            {
                                return(CoinChangeStatus.InvalidContext);
                            }

                            extendedPack = CoinPack.WithExtraCoinEvent(packN, coin, coinOffset, evt, _pool);
                            break;
                        }

                        // False-positive match, adding the coin as new in layer 0.
                        if (layerIndex == _store.LayerCount - 1)
                        {
                            var newCoin = new Coin(ref outpoint, isCoinBase, payload, evt, _pool);
                            extendedPack = CoinPack.WithExtraCoin(pack0, newCoin, _pool);
                        }
                    }

                    // 'for' loop above should not exit without assigned a value to 'extendedPack'.
                    Debug.Assert(!extendedPack.IsEmpty);
                }
                else // The coin does not exist on any chain.
                {
                    var newCoin = new Coin(ref outpoint, isCoinBase, payload, evt, _pool);
                    extendedPack = CoinPack.WithExtraCoin(pack0, newCoin, _pool);
                }

                // Check of overflow
                var packs = extendedPack.SizeInBytes < _store.SectorSizeInBytes[extendedPack.LayerIndex]
                    ? new ShortCoinPackCollection(extendedPack)
                    : GetOverflow(extendedPack, lineage, _hash);

                // Persist the pack(s), several coin packs in case of overflow.
                _store.Write(packs);

                return(CoinChangeStatus.Success);
            }
Beispiel #8
0
        public bool TryGet(ulong outpointHash, ref Outpoint outpoint, BlockAlias context, ILineage lineage,
                           out Coin coin, out BlockAlias production, out BlockAlias consumption)
        {
            var sectorIndex = (uint)(outpointHash % (uint)_store.SectorCount);

            production  = BlockAlias.Undefined;
            consumption = BlockAlias.Undefined;

            // Check layer 0.
            var pack0 = _store.Read(layerIndex: 0, sectorIndex);

            if (pack0.TryGet(ref outpoint, out coin))
            {
                return(lineage.TryGetEventsInContext(coin.Events, context, out production, out consumption));
            }

            var sig = OutpointSig.From(outpointHash);

            // Layer 0 has a probabilistic filter. No false negative are possible.
            if (!pack0.PositiveMatch(sig))
            {
                return(false);
            }

            // Check next layers.
            for (var layerIndex = 1; layerIndex < _store.LayerCount; layerIndex++)
            {
                var packN = _store.Read(layerIndex: layerIndex, sectorIndex);

                if (packN.TryGet(ref outpoint, out coin))
                {
                    return(lineage.TryGetEventsInContext(coin.Events, context, out production, out consumption));
                }
            }

            // Not found, it was a false positive on the probabilistic filter.
            return(false);
        }
Beispiel #9
0
        // HACK: [vermorel] Constructor used as the setup of the unit tests, should be refactored.
        public LineagePruneTests()
        {
            var store = new VolatileChainStore();

            UncommittedBlock freshBlock;

            store.TryOpenBlock(CommittedBlockId.GenesisParent, out var b0);
            var id = b0.Alias;

            // U(0)
            store.TryCommitBlock(id, CommittedBlockId.Genesis, out _);
            // C(0)

            store.TryOpenBlock(CommittedBlockId.Genesis, out freshBlock);
            Assert.Equal(_1, freshBlock.Alias);
            // C(0) -> U(1)
            store.TryCommitBlock(_1, _id_1, out _);
            // C(0) -> C(1)
            store.TryOpenBlock(_id_1, out freshBlock);
            Assert.Equal(_2, freshBlock.Alias);
            // C(0) -> C(1) -> U(2)
            store.TryCommitBlock(_2, _id_2, out _);
            // C(0) -> C(1) -> C(2)
            // Second child for second block
            store.TryOpenBlock(_id_1, out freshBlock);
            Assert.Equal(_2_1, freshBlock.Alias);
            // C(0) -> C(1) -> C(2)
            //             \-> U(2-1)
            store.TryCommitBlock(_2_1, _id_2_1, out _);
            // C(0) -> C(1) -> C(2)
            //             \-> C(2-1)
            store.TryOpenBlock(_id_2, out freshBlock);
            Assert.Equal(_3, freshBlock.Alias);
            store.TryCommitBlock(_3, _id_3, out _);

            store.TryOpenBlock(_id_2_1, out freshBlock);
            Assert.Equal(_3_1, freshBlock.Alias);
            store.TryCommitBlock(_3_1, _id_3_1, out _);
            // C(0) -> C(1) -> C(2)   -> C(3)
            //             \-> C(2-1) -> C(3-1)

            store.TryOpenBlock(_id_3_1, out freshBlock);
            Assert.Equal(_4, freshBlock.Alias);
            store.TryCommitBlock(_4, _id_4, out _);

            store.TryOpenBlock(_id_4, out freshBlock);
            Assert.Equal(_5, freshBlock.Alias);
            store.TryCommitBlock(_5, _id_5, out _);

            store.TryOpenBlock(_id_4, out freshBlock);
            Assert.Equal(_5_1, freshBlock.Alias);
            store.TryCommitBlock(_5_1, _id_5_1, out _);

            // C(0) -> C(1) -> C(2)   -> C(3)
            //             \-> C(2-1) -> C(3-1) -> C(4) -> C(5)
            //                                        \ -> C(5-1)

            // pruning limit is _3_1
            var lineage = (Lineage)store.GetLineage();

            lineage.CoinPruneHeight = _3_1.BlockHeight;

            _lineage = lineage;
        }
Beispiel #10
0
 private void RefreshAndPropagateLineage()
 {
     _lineage = _store.GetLineage();
     _propagateLineage(_lineage);
 }
Beispiel #11
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);
        }