コード例 #1
0
ファイル: UtxoTest.cs プロジェクト: sph001/BitSharp
        public void TestCanSpend_NegativeIndex()
        {
            // prepare utxo storage
            var chain = new Chain(ImmutableList.Create(new FakeHeaders().GenesisChained()));
            var unspentTransactions = ImmutableSortedDictionary.CreateBuilder <UInt256, UnspentTx>();

            // prepare unspent output
            var txHash = new UInt256(0);

            unspentTransactions.Add(txHash, new UnspentTx(txHash, blockIndex: 0, txIndex: 0, length: 1, state: OutputState.Unspent));

            // prepare utxo
            var memoryStorage     = new MemoryStorageManager(unspentTransactions: unspentTransactions.ToImmutable());
            var chainStateStorage = memoryStorage.OpenChainStateCursor().Item;

            chainStateStorage.AddChainedHeader(chain.GenesisBlock);
            var utxo = new ChainState(chain, memoryStorage);

            // prepare output reference
            var prevTxOutput = new TxOutputKey(txHash, txOutputIndex: UInt32.MaxValue);

            // check if output can be spent
            var canSpend = utxo.CanSpend(prevTxOutput);

            // verify output cannot be spent
            Assert.IsFalse(canSpend);
        }
コード例 #2
0
ファイル: ExamplePrograms.cs プロジェクト: yonglehou/BitSharp
        private CoreDaemon CreateExampleDaemon(out BlockProvider embeddedBlocks, out IStorageManager storageManager, int?maxHeight = null)
        {
            // retrieve first 10,000 testnet3 blocks
            embeddedBlocks = new BlockProvider("BitSharp.Examples.Blocks.TestNet3.zip");

            // initialize in-memory storage
            storageManager = new MemoryStorageManager();

            // intialize testnet3 rules (ignore script errors, script engine is not and is not intended to be complete)
            var chainParams = new Testnet3Params();
            var rules       = new CoreRules(chainParams)
            {
                IgnoreScriptErrors = true
            };

            // initialize & start core daemon
            var coreDaemon = new CoreDaemon(rules, storageManager)
            {
                MaxHeight = maxHeight, IsStarted = true
            };

            // add embedded blocks
            coreDaemon.CoreStorage.AddBlocks(embeddedBlocks.ReadBlocks());

            // wait for core daemon to finish processing any available data
            coreDaemon.WaitForUpdate();

            return(coreDaemon);
        }
コード例 #3
0
ファイル: UtxoTest.cs プロジェクト: yonglehou/BitSharp
        public void TestCanSpend_Spent()
        {
            // prepare utxo storage
            var chain = Chain.CreateForGenesisBlock(new FakeHeaders().GenesisChained());
            var unspentTransactions = ImmutableSortedDictionary.CreateBuilder <UInt256, UnspentTx>();

            // prepare spent output
            var txHash = new UInt256(0);

            unspentTransactions.Add(txHash, new UnspentTx(txHash, blockIndex: 0, txIndex: 0, txVersion: 0, isCoinbase: false, length: 1, state: OutputState.Spent));

            // prepare utxo
            var memoryStorage     = new MemoryStorageManager(unspentTransactions: unspentTransactions.ToImmutable());
            var chainStateStorage = memoryStorage.OpenChainStateCursor().Item;

            chainStateStorage.BeginTransaction();
            chainStateStorage.ChainTip = chain.GenesisBlock;
            chainStateStorage.CommitTransaction();
            var utxo = new ChainState(chain, memoryStorage);

            // prepare output reference
            var prevTxOutput = new TxOutputKey(txHash, txOutputIndex: 0);

            // check if output can be spent
            var canSpend = utxo.CanSpend(prevTxOutput);

            // verify output cannot be spent
            Assert.IsFalse(canSpend);
        }
コード例 #4
0
        public void DoABunchOfStuff()
        {
            var stopWatch = new Stopwatch();

            // create the new storage manager
            using (var storageManager = new MemoryStorageManager())
            {
                var rand = new Random();
                using (var rtree = GetAFullTree(storageManager))
                {
                    // sanity check
                    Assert.Equal(10000, rtree.Count);

                    stopWatch.Start();

                    long totalMatch = 0;
                    for (int i = 0; i < 10000; ++i)
                    {
                        var count = CountAnIntersection(rtree, rand);
                        Assert.True(count < 10000);
                        totalMatch += count;
                    }
                    stopWatch.Stop();

                    PrintPerformanceReport(stopWatch.ElapsedMilliseconds, 500, totalMatch);
                }
            }
        }
コード例 #5
0
        public void TestDoubleSpend()
        {
            // prepare block
            var fakeHeaders      = new FakeHeaders();
            var chainedHeader0   = fakeHeaders.GenesisChained();
            var chainedHeader1   = fakeHeaders.NextChained();
            var chainedHeader2   = fakeHeaders.NextChained();
            var chain            = Chain.CreateForGenesisBlock(chainedHeader0).ToBuilder();
            var emptyCoinbaseTx0 = BlockTx.Create(0, Transaction.Create(0, ImmutableArray.Create <TxInput>(), ImmutableArray.Create <TxOutput>(), 0));
            var emptyCoinbaseTx1 = BlockTx.Create(0, Transaction.Create(1, ImmutableArray.Create <TxInput>(), ImmutableArray.Create <TxOutput>(), 0));

            // initialize memory utxo builder storage
            var memoryStorage          = new MemoryStorageManager();
            var memoryChainStateCursor = memoryStorage.OpenChainStateCursor().Item;

            memoryChainStateCursor.BeginTransaction();

            // initialize utxo builder
            var utxoBuilder = new UtxoBuilder();

            // prepare an unspent transaction
            var txHash      = new UInt256(100);
            var unspentTx   = new UnspentTx(txHash, chainedHeader1.Height, 0, 0, false, 1, OutputState.Unspent);
            var txOutputKey = new TxOutputKey(txHash, 0);
            var txOutput    = new TxOutput(0, ImmutableArray <byte> .Empty);

            // add the unspent transaction
            memoryChainStateCursor.TryAddUnspentTx(unspentTx);
            memoryChainStateCursor.TryAddUnspentTxOutput(txOutputKey, txOutput);

            // create an input to spend the unspent transaction
            var input = new TxInput(txHash, 0, ImmutableArray.Create <byte>(), 0);
            var tx    = BlockTx.Create(1, Transaction.Create(0, ImmutableArray.Create(input), ImmutableArray.Create <TxOutput>(), 0));

            // spend the input
            chain.AddBlock(chainedHeader1);
            utxoBuilder.CalculateUtxo(memoryChainStateCursor, chain.ToImmutable(), new[] { emptyCoinbaseTx0, tx }.ToBufferBlock()).ToEnumerable().ToList();

            // verify utxo storage
            UnspentTx actualUnspentTx; TxOutput actualTxOutput;

            Assert.IsTrue(memoryChainStateCursor.TryGetUnspentTx(txHash, out actualUnspentTx));
            Assert.IsTrue(actualUnspentTx.IsFullySpent);
            Assert.IsTrue(memoryChainStateCursor.TryGetUnspentTxOutput(txOutputKey, out actualTxOutput));
            Assert.AreEqual(txOutput, actualTxOutput);

            // attempt to spend the input again, validation exception should be thrown
            chain.AddBlock(chainedHeader2);
            AssertMethods.AssertAggregateThrows <ValidationException>(() =>
                                                                      utxoBuilder.CalculateUtxo(memoryChainStateCursor, chain.ToImmutable(), new[] { emptyCoinbaseTx1, tx }.ToBufferBlock()).ToEnumerable().ToList());
        }
コード例 #6
0
        public LevelDbStorageManager(string baseDirectory,
                                     ulong?blocksCacheSize              = null, ulong?blocksWriteCacheSize     = null,
                                     ulong?blockTxesCacheSize           = null, ulong?blockTxesWriteCacheSize  = null,
                                     ulong?chainStateCacheSize          = null, ulong?chainStateWriteCacheSize = null,
                                     string[] blockTxesStorageLocations = null)
        {
            this.baseDirectory             = baseDirectory;
            this.blockTxesStorageLocations = blockTxesStorageLocations;

            blockStorage = new Lazy <LevelDb.LevelDbBlockStorage>(() => new LevelDbBlockStorage(this.baseDirectory, blocksCacheSize, blocksWriteCacheSize));

            blockTxesStorage = new Lazy <IBlockTxesStorage>(() =>
            {
                if (blockTxesStorageLocations == null)
                {
                    return(new LevelDbBlockTxesStorage(this.baseDirectory, blockTxesCacheSize, blockTxesWriteCacheSize));
                }
                else
                {
                    return(new SplitBlockTxesStorage(blockTxesStorageLocations, path => new LevelDbBlockTxesStorage(path, blockTxesCacheSize, blockTxesWriteCacheSize)));
                }
            });

            chainStateManager         = new Lazy <LevelDbChainStateManager>(() => new LevelDbChainStateManager(this.baseDirectory, chainStateCacheSize, chainStateWriteCacheSize));
            this.memoryStorageManager = new Lazy <MemoryStorageManager>(() =>
            {
                // create memory storage with the unconfirmed txes chain tip already in sync with chain state
                ChainedHeader chainTip;
                using (var handle = OpenChainStateCursor())
                {
                    handle.Item.BeginTransaction(readOnly: true);
                    chainTip = handle.Item.ChainTip;
                }

                var memoryStorageManager = new MemoryStorageManager();
                using (var handle = memoryStorageManager.OpenUnconfirmedTxesCursor())
                {
                    handle.Item.BeginTransaction();
                    handle.Item.ChainTip = chainTip;
                    handle.Item.CommitTransaction();
                }

                return(memoryStorageManager);
            });
        }
コード例 #7
0
ファイル: UtxoTest.cs プロジェクト: sph001/BitSharp
        public void TestCanSpend_Missing()
        {
            // prepare utxo
            var chain             = new Chain(ImmutableList.Create(new FakeHeaders().GenesisChained()));
            var memoryStorage     = new MemoryStorageManager();
            var chainStateStorage = memoryStorage.OpenChainStateCursor().Item;

            chainStateStorage.AddChainedHeader(chain.GenesisBlock);
            var utxo = new ChainState(chain, memoryStorage);

            // prepare output reference
            var prevTxOutput = new TxOutputKey(txHash: 0, txOutputIndex: 0);

            // check if output can be spent
            var canSpend = utxo.CanSpend(prevTxOutput);

            // verify output cannot be spent
            Assert.IsFalse(canSpend);
        }
コード例 #8
0
        /// <summary>
        /// Creates Storage Manager according to StorageType value in Settings file.
        /// </summary>
        /// <returns>Storame Manager</returns>
        public static IStorageManager CreateStorageManager()
        {
            //Get a reference to the settings
            var settings = MDSSettings.Instance;

            //Create storage manager according to the settings
            var             storageType = settings["StorageType"];
            IStorageManager storageManager;

            if (storageType.Equals("MySQL-ODBC", StringComparison.OrdinalIgnoreCase))
            {
                storageManager = new MySqlOdbcStorageManager {
                    ConnectionString = settings["ConnectionString"]
                };
            }
            else if (storageType.Equals("MySQL-Net", StringComparison.OrdinalIgnoreCase))
            {
                storageManager = new MySqlNetStorageManager {
                    ConnectionString = settings["ConnectionString"]
                };
            }
            else if (storageType.Equals("MSSQL", StringComparison.OrdinalIgnoreCase))
            {
                storageManager = new MsSqlStorageManager {
                    ConnectionString = settings["ConnectionString"]
                };
            }
            else if (storageType.Equals("SQLite", StringComparison.OrdinalIgnoreCase))
            {
                storageManager = new SqliteStorageManager();
            }
            else if (storageType.Equals("MongoDB", StringComparison.OrdinalIgnoreCase))
            {
                storageManager = new MongoDBStorageManager();
            }
            else //Default storage manager
            {
                storageManager = new MemoryStorageManager();
            }

            //Wrap storageManager with FaultToleratedStorageManagerWrapper and return it
            return(new FaultToleratedStorageManagerWrapper(storageManager));
        }
コード例 #9
0
        public void MemoryStorageManager_CanStoreAndLoad()
        {
            var storageManager = new MemoryStorageManager();

            // a random but repeatable seed
            var buffer  = DataHelpers.GenerateSomeBytes(9087449);
            var nAccess = new StorageManagerAccess(storageManager);
            var page1   = nAccess.Store(-1, buffer);

            var buffer2 = DataHelpers.GenerateSomeBytes(37900452);
            var page2   = nAccess.Store(-1, buffer2);

            Assert.True(buffer.SequenceEqual(nAccess.Load(page1)));
            Assert.True(buffer2.SequenceEqual(nAccess.Load(page2)));

            buffer = DataHelpers.GenerateSomeBytes(678000023);
            page1  = nAccess.Store(page1, buffer);
            Assert.True(buffer.SequenceEqual(nAccess.Load(page1)));
        }
コード例 #10
0
ファイル: UtxoBuilderTest.cs プロジェクト: sph001/BitSharp
        public void TestDoubleSpend()
        {
            // prepare block
            var fakeHeaders      = new FakeHeaders();
            var chainedHeader0   = fakeHeaders.GenesisChained();
            var chainedHeader1   = fakeHeaders.NextChained();
            var chain            = new ChainBuilder();
            var emptyCoinbaseTx0 = new Transaction(0, ImmutableArray.Create <TxInput>(), ImmutableArray.Create <TxOutput>(), 0);
            var emptyCoinbaseTx1 = new Transaction(1, ImmutableArray.Create <TxInput>(), ImmutableArray.Create <TxOutput>(), 0);

            // initialize memory utxo builder storage
            var memoryStorage          = new MemoryStorageManager();
            var memoryChainStateCursor = memoryStorage.OpenChainStateCursor().Item;

            // initialize utxo builder
            var utxoBuilder = new UtxoBuilder(memoryChainStateCursor, LogManager.CreateNullLogger());

            // prepare an unspent transaction
            var txHash    = new UInt256(100);
            var unspentTx = new UnspentTx(txHash, chainedHeader0.Height, 0, 1, OutputState.Unspent);

            // add the unspent transaction
            memoryChainStateCursor.TryAddUnspentTx(unspentTx);

            // create an input to spend the unspent transaction
            var input = new TxInput(new TxOutputKey(txHash, txOutputIndex: 0), ImmutableArray.Create <byte>(), 0);
            var tx    = new Transaction(0, ImmutableArray.Create(input), ImmutableArray.Create <TxOutput>(), 0);

            // spend the input
            chain.AddBlock(chainedHeader0);
            utxoBuilder.CalculateUtxo(chain.ToImmutable(), new[] { emptyCoinbaseTx0, tx }).ToList();

            // verify utxo storage
            Assert.IsFalse(memoryChainStateCursor.ContainsUnspentTx(txHash));

            // attempt to spend the input again
            chain.AddBlock(chainedHeader1);
            utxoBuilder.CalculateUtxo(chain.ToImmutable(), new[] { emptyCoinbaseTx1, tx }).ToList();

            // validation exception should be thrown
        }
コード例 #11
0
        public void DoABunchOfStuffAsync()
        {
            var stopWatch = new Stopwatch();

            // create the new storage manager
            using (var storageManager = new MemoryStorageManager())
            {
                var rand = new Random();
                using (var rtree = GetAFullTree(storageManager))
                {
                    // sanity check
                    Assert.Equal(10000, rtree.Count);

                    stopWatch.Start();
                    long totalCount = 0;

                    var tasks = new Task <bool> [10];
                    for (var taskIndex = 0; taskIndex < 10; ++taskIndex)
                    {
                        tasks[taskIndex] = Task.Factory.StartNew(() => {
                            for (int i = 0; i < 1000; ++i)
                            {
                                var count = CountAnIntersection(rtree, rand);
                                Interlocked.Add(ref totalCount, count);
                                if (count > 10000)
                                {
                                    return(false);
                                }
                            }
                            return(true);
                        });
                    }

                    Task.WaitAll(tasks);
                    Assert.True(tasks.All(tsk => tsk.Result));
                    stopWatch.Stop();

                    PrintPerformanceReport(stopWatch.ElapsedMilliseconds, 500, totalCount);
                }
            }
        }
コード例 #12
0
        public EsentStorageManager(string baseDirectory, string[] blockTxesStorageLocations = null)
        {
            this.baseDirectory             = baseDirectory;
            this.blockTxesStorageLocations = blockTxesStorageLocations;

            this.blockStorage = new Lazy <Esent.EsentBlockStorage>(() => new EsentBlockStorage(this.baseDirectory));

            this.blockTxesStorage = new Lazy <IBlockTxesStorage>(() =>
            {
                if (blockTxesStorageLocations == null)
                {
                    return(new EsentBlockTxesStorage(this.baseDirectory));
                }
                else
                {
                    return(new SplitBlockTxesStorage(blockTxesStorageLocations, path => new EsentBlockTxesStorage(path)));
                }
            });

            this.chainStateManager    = new Lazy <EsentChainStateManager>(() => new EsentChainStateManager(this.baseDirectory));
            this.memoryStorageManager = new Lazy <MemoryStorageManager>(() =>
            {
                // create memory storage with the unconfirmed txes chain tip already in sync with chain state
                ChainedHeader chainTip;
                using (var handle = OpenChainStateCursor())
                {
                    handle.Item.BeginTransaction(readOnly: true);
                    chainTip = handle.Item.ChainTip;
                }

                var memoryStorageManager = new MemoryStorageManager();
                using (var handle = memoryStorageManager.OpenUnconfirmedTxesCursor())
                {
                    handle.Item.BeginTransaction();
                    handle.Item.ChainTip = chainTip;
                    handle.Item.CommitTransaction();
                }

                return(memoryStorageManager);
            });
        }
コード例 #13
0
ファイル: UtxoTest.cs プロジェクト: yonglehou/BitSharp
        public void TestCanSpend_Missing()
        {
            // prepare utxo
            var chain             = Chain.CreateForGenesisBlock(new FakeHeaders().GenesisChained());
            var memoryStorage     = new MemoryStorageManager();
            var chainStateStorage = memoryStorage.OpenChainStateCursor().Item;

            chainStateStorage.BeginTransaction();
            chainStateStorage.ChainTip = chain.GenesisBlock;
            chainStateStorage.CommitTransaction();
            var utxo = new ChainState(chain, memoryStorage);

            // prepare output reference
            var prevTxOutput = new TxOutputKey(txHash: UInt256.Zero, txOutputIndex: 0);

            // check if output can be spent
            var canSpend = utxo.CanSpend(prevTxOutput);

            // verify output cannot be spent
            Assert.IsFalse(canSpend);
        }
コード例 #14
0
        public void TestPruneAllData()
        {
            // create genesis block
            var genesisblock  = CreateFakeBlock(1);
            var genesisHeader = new ChainedHeader(genesisblock.Header, height: 0, totalWork: genesisblock.Header.CalculateWork().ToBigInteger(), dateSeen: DateTimeOffset.Now);

            // create a block
            var txCount       = 100;
            var block         = CreateFakeBlock(txCount, genesisblock.Hash);
            var chainedHeader = ChainedHeader.CreateFromPrev(genesisHeader, block.Header, dateSeen: DateTimeOffset.Now);

            // create a long chain based off the block, to account for pruning buffer
            var fakeHeaders = new FakeHeaders(new[] { genesisHeader, chainedHeader });
            var chain       = new ChainBuilder(Enumerable.Concat(new[] { genesisHeader, chainedHeader }, Enumerable.Range(0, 2000).Select(x => fakeHeaders.NextChained()))).ToImmutable();

            // mock core daemon to return the chain
            var coreDaemon = new Mock <ICoreDaemon>();

            coreDaemon.Setup(x => x.CurrentChain).Returns(chain);

            // create memory storage with the block
            var storageManager = new MemoryStorageManager();

            storageManager.BlockTxesStorage.TryAddBlockTransactions(block.Hash, block.BlockTxes);

            // initialize the pruning worker
            var workerConfig = new WorkerConfig(initialNotify: false, minIdleTime: TimeSpan.Zero, maxIdleTime: TimeSpan.MaxValue);

            using (var pruningWorker = new PruningWorker(workerConfig, coreDaemon.Object, storageManager, null))
                // get a chain state cursor
                using (var handle = storageManager.OpenChainStateCursor())
                {
                    var chainStateCursor = handle.Item;

                    // set the pruning worker to prune all data
                    pruningWorker.Mode = PruningMode.TxIndex | PruningMode.BlockSpentIndex | PruningMode.BlockTxesPreserveMerkle;

                    // wire event to wait for work
                    var workFinishedEvent = new AutoResetEvent(false);
                    pruningWorker.OnWorkFinished += () => workFinishedEvent.Set();

                    // wire event to track exceptions
                    Exception workException = null;
                    pruningWorker.OnWorkError += e => workException = e;

                    // start the worker
                    pruningWorker.Start();

                    // pick a random pruning order
                    var random           = new Random();
                    var pruneOrderSource = Enumerable.Range(0, txCount).ToList();
                    var pruneOrder       = new List <int>(txCount);
                    while (pruneOrderSource.Count > 0)
                    {
                        var randomIndex = random.Next(pruneOrderSource.Count);

                        pruneOrder.Add(pruneOrderSource[randomIndex]);
                        pruneOrderSource.RemoveAt(randomIndex);
                    }

                    // add an unspent tx for each transaction to storage
                    var unspentTxes = new UnspentTx[block.Transactions.Length];
                    chainStateCursor.BeginTransaction();
                    for (var txIndex = 0; txIndex < block.Transactions.Length; txIndex++)
                    {
                        var tx        = block.Transactions[txIndex];
                        var unspentTx = new UnspentTx(tx.Hash, blockIndex: 1, txIndex: txIndex, txVersion: tx.Version, isCoinbase: txIndex == 0, outputStates: new OutputStates(1, OutputState.Spent));
                        unspentTxes[txIndex] = unspentTx;
                        chainStateCursor.TryAddUnspentTx(unspentTx);
                    }
                    chainStateCursor.CommitTransaction();

                    // create a memory pruning cursor to verify expected pruning results
                    var pruneCursor = new MemoryMerkleTreePruningCursor <BlockTxNode>(block.BlockTxes.Select(x => (BlockTxNode)x));

                    // prune each transaction in random order
                    var pruneHeight = 0;
                    foreach (var pruneTxIndex in pruneOrder)
                    {
                        // create a spent tx to prune the transaction
                        var pruneTx   = block.Transactions[pruneTxIndex];
                        var spentTxes = BlockSpentTxes.CreateRange(new[] { unspentTxes[pruneTxIndex].ToSpentTx() });

                        // store the spent txes for the current pruning block
                        pruneHeight++;
                        chainStateCursor.BeginTransaction();
                        Assert.IsTrue(chainStateCursor.TryAddBlockSpentTxes(pruneHeight, spentTxes));
                        pruningWorker.PrunableHeight = pruneHeight;

                        // verify unspent tx is present before pruning
                        Assert.IsTrue(chainStateCursor.ContainsUnspentTx(pruneTx.Hash));
                        chainStateCursor.CommitTransaction();

                        // notify the pruning worker and wait
                        pruningWorker.NotifyWork();
                        workFinishedEvent.WaitOne();

                        // verify unspent tx is removed after pruning
                        chainStateCursor.BeginTransaction();
                        Assert.IsFalse(chainStateCursor.ContainsUnspentTx(pruneTx.Hash));

                        // verify unspent tx outputs are removed after pruning
                        for (var outputIndex = 0; outputIndex < pruneTx.Outputs.Length; outputIndex++)
                        {
                            Assert.IsFalse(chainStateCursor.ContainsUnspentTxOutput(new TxOutputKey(pruneTx.Hash, (uint)outputIndex)));
                        }

                        // verify the spent txes were removed
                        Assert.IsFalse(chainStateCursor.ContainsBlockSpentTxes(pruneHeight));
                        chainStateCursor.RollbackTransaction();

                        // prune to determine expected results
                        MerkleTree.PruneNode(pruneCursor, pruneTxIndex);
                        var expectedPrunedTxes = pruneCursor.ReadNodes().ToList();

                        // retrieve the actual transaction after pruning
                        IEnumerator <BlockTxNode> actualPrunedTxNodes;
                        Assert.IsTrue(storageManager.BlockTxesStorage.TryReadBlockTxNodes(block.Hash, out actualPrunedTxNodes));

                        // verify the actual pruned transactions match the expected results
                        CollectionAssert.AreEqual(expectedPrunedTxes, actualPrunedTxNodes.UsingAsEnumerable().ToList());
                    }

                    // verify all unspent txes were removed
                    chainStateCursor.BeginTransaction();
                    Assert.AreEqual(0, chainStateCursor.ReadUnspentTransactions().Count());
                    chainStateCursor.CommitTransaction();

                    // verify final block with all transactions pruned
                    IEnumerator <BlockTxNode> finalPrunedTxNodes;
                    Assert.IsTrue(storageManager.BlockTxesStorage.TryReadBlockTxNodes(block.Hash, out finalPrunedTxNodes));
                    var finalPrunedTxesList = finalPrunedTxNodes.UsingAsEnumerable().ToList();
                    Assert.AreEqual(1, finalPrunedTxesList.Count);
                    Assert.AreEqual(block.Header.MerkleRoot, finalPrunedTxesList.Single().Hash);

                    // verify no work exceptions occurred
                    Assert.IsNull(workException);
                }
        }
コード例 #15
0
ファイル: UtxoBuilderTest.cs プロジェクト: sph001/BitSharp
        public void TestSimpleSpend()
        {
            // prepare block
            var fakeHeaders      = new FakeHeaders();
            var chainedHeader0   = fakeHeaders.GenesisChained();
            var chainedHeader1   = fakeHeaders.NextChained();
            var chainedHeader2   = fakeHeaders.NextChained();
            var chain            = new ChainBuilder();
            var emptyCoinbaseTx0 = new Transaction(0, ImmutableArray.Create <TxInput>(), ImmutableArray.Create <TxOutput>(), 0);
            var emptyCoinbaseTx1 = new Transaction(1, ImmutableArray.Create <TxInput>(), ImmutableArray.Create <TxOutput>(), 0);
            var emptyCoinbaseTx2 = new Transaction(2, ImmutableArray.Create <TxInput>(), ImmutableArray.Create <TxOutput>(), 0);

            // initialize memory utxo builder storage
            var memoryStorage          = new MemoryStorageManager();
            var memoryChainStateCursor = memoryStorage.OpenChainStateCursor().Item;

            // initialize utxo builder
            var utxoBuilder = new UtxoBuilder(memoryChainStateCursor, LogManager.CreateNullLogger());

            // prepare an unspent transaction
            var txHash    = new UInt256(100);
            var unspentTx = new UnspentTx(txHash, chainedHeader0.Height, 0, 3, OutputState.Unspent);

            // prepare unspent output
            var unspentTransactions = ImmutableDictionary.Create <UInt256, UnspentTx>().Add(txHash, unspentTx);

            // add the unspent transaction
            memoryChainStateCursor.TryAddUnspentTx(unspentTx);

            // create an input to spend the unspent transaction's first output
            var input0 = new TxInput(new TxOutputKey(txHash, txOutputIndex: 0), ImmutableArray.Create <byte>(), 0);
            var tx0    = new Transaction(0, ImmutableArray.Create(input0), ImmutableArray.Create <TxOutput>(), 0);

            // spend the input
            chain.AddBlock(chainedHeader0);
            utxoBuilder.CalculateUtxo(chain.ToImmutable(), new[] { emptyCoinbaseTx0, tx0 }).ToList();

            // verify utxo storage
            UnspentTx actualUnspentTx;

            Assert.IsTrue(memoryChainStateCursor.TryGetUnspentTx(txHash, out actualUnspentTx));
            Assert.IsTrue(actualUnspentTx.OutputStates.Length == 3);
            Assert.IsTrue(actualUnspentTx.OutputStates[0] == OutputState.Spent);
            Assert.IsTrue(actualUnspentTx.OutputStates[1] == OutputState.Unspent);
            Assert.IsTrue(actualUnspentTx.OutputStates[2] == OutputState.Unspent);

            // create an input to spend the unspent transaction's second output
            var input1 = new TxInput(new TxOutputKey(txHash, txOutputIndex: 1), ImmutableArray.Create <byte>(), 0);
            var tx1    = new Transaction(0, ImmutableArray.Create(input1), ImmutableArray.Create <TxOutput>(), 0);

            // spend the input
            chain.AddBlock(chainedHeader1);
            utxoBuilder.CalculateUtxo(chain.ToImmutable(), new[] { emptyCoinbaseTx1, tx1 }).ToList();

            // verify utxo storage
            Assert.IsTrue(memoryChainStateCursor.TryGetUnspentTx(txHash, out actualUnspentTx));
            Assert.IsTrue(actualUnspentTx.OutputStates.Length == 3);
            Assert.IsTrue(actualUnspentTx.OutputStates[0] == OutputState.Spent);
            Assert.IsTrue(actualUnspentTx.OutputStates[1] == OutputState.Spent);
            Assert.IsTrue(actualUnspentTx.OutputStates[2] == OutputState.Unspent);

            // create an input to spend the unspent transaction's third output
            var input2 = new TxInput(new TxOutputKey(txHash, txOutputIndex: 2), ImmutableArray.Create <byte>(), 0);
            var tx2    = new Transaction(0, ImmutableArray.Create(input2), ImmutableArray.Create <TxOutput>(), 0);

            // spend the input
            chain.AddBlock(chainedHeader2);
            utxoBuilder.CalculateUtxo(chain.ToImmutable(), new[] { emptyCoinbaseTx2, tx2 }).ToList();

            // verify utxo storage
            Assert.IsFalse(memoryChainStateCursor.ContainsUnspentTx(txHash));
        }
コード例 #16
0
        public void TestSimpleSpend()
        {
            // prepare block
            var fakeHeaders      = new FakeHeaders();
            var chainedHeader0   = fakeHeaders.GenesisChained();
            var chainedHeader1   = fakeHeaders.NextChained();
            var chainedHeader2   = fakeHeaders.NextChained();
            var chainedHeader3   = fakeHeaders.NextChained();
            var chain            = Chain.CreateForGenesisBlock(chainedHeader0).ToBuilder();
            var emptyCoinbaseTx0 = BlockTx.Create(0, Transaction.Create(0, ImmutableArray.Create <TxInput>(), ImmutableArray.Create <TxOutput>(), 0));
            var emptyCoinbaseTx1 = BlockTx.Create(1, Transaction.Create(1, ImmutableArray.Create <TxInput>(), ImmutableArray.Create <TxOutput>(), 0));
            var emptyCoinbaseTx2 = BlockTx.Create(2, Transaction.Create(2, ImmutableArray.Create <TxInput>(), ImmutableArray.Create <TxOutput>(), 0));

            // initialize memory utxo builder storage
            var memoryStorage          = new MemoryStorageManager();
            var memoryChainStateCursor = memoryStorage.OpenChainStateCursor().Item;

            memoryChainStateCursor.BeginTransaction();

            // initialize utxo builder
            var utxoBuilder = new UtxoBuilder();

            // prepare an unspent transaction
            var txHash       = new UInt256(100);
            var unspentTx    = new UnspentTx(txHash, chainedHeader1.Height, 0, 0, false, 3, OutputState.Unspent);
            var txOutput1Key = new TxOutputKey(txHash, 0);
            var txOutput1    = new TxOutput(0, ImmutableArray <byte> .Empty);
            var txOutput2Key = new TxOutputKey(txHash, 1);
            var txOutput2    = new TxOutput(1, ImmutableArray <byte> .Empty);
            var txOutput3Key = new TxOutputKey(txHash, 2);
            var txOutput3    = new TxOutput(2, ImmutableArray <byte> .Empty);

            // prepare unspent output
            var unspentTransactions = ImmutableDictionary.Create <UInt256, UnspentTx>().Add(txHash, unspentTx);

            // add the unspent transaction
            memoryChainStateCursor.TryAddUnspentTx(unspentTx);
            memoryChainStateCursor.TryAddUnspentTxOutput(txOutput1Key, txOutput1);
            memoryChainStateCursor.TryAddUnspentTxOutput(txOutput2Key, txOutput2);
            memoryChainStateCursor.TryAddUnspentTxOutput(txOutput3Key, txOutput3);

            // create an input to spend the unspent transaction's first output
            var input0 = new TxInput(txHash, 0, ImmutableArray.Create <byte>(), 0);
            var tx0    = BlockTx.Create(1, Transaction.Create(0, ImmutableArray.Create(input0), ImmutableArray.Create <TxOutput>(), 0));

            // spend the input
            chain.AddBlock(chainedHeader1);
            utxoBuilder.CalculateUtxo(memoryChainStateCursor, chain.ToImmutable(), new[] { emptyCoinbaseTx0, tx0 }.ToBufferBlock()).ToEnumerable().ToList();

            // verify utxo storage
            UnspentTx actualUnspentTx; TxOutput actualTxOutput;

            Assert.IsTrue(memoryChainStateCursor.TryGetUnspentTx(txHash, out actualUnspentTx));
            Assert.IsTrue(actualUnspentTx.OutputStates.Length == 3);
            Assert.IsTrue(actualUnspentTx.OutputStates[0] == OutputState.Spent);
            Assert.IsTrue(actualUnspentTx.OutputStates[1] == OutputState.Unspent);
            Assert.IsTrue(actualUnspentTx.OutputStates[2] == OutputState.Unspent);

            Assert.IsTrue(memoryChainStateCursor.TryGetUnspentTxOutput(txOutput1Key, out actualTxOutput));
            Assert.AreEqual(txOutput1, actualTxOutput);
            Assert.IsTrue(memoryChainStateCursor.TryGetUnspentTxOutput(txOutput2Key, out actualTxOutput));
            Assert.AreEqual(txOutput2, actualTxOutput);
            Assert.IsTrue(memoryChainStateCursor.TryGetUnspentTxOutput(txOutput3Key, out actualTxOutput));
            Assert.AreEqual(txOutput3, actualTxOutput);

            // create an input to spend the unspent transaction's second output
            var input1 = new TxInput(txHash, 1, ImmutableArray.Create <byte>(), 0);
            var tx1    = BlockTx.Create(1, Transaction.Create(0, ImmutableArray.Create(input1), ImmutableArray.Create <TxOutput>(), 0));

            // spend the input
            chain.AddBlock(chainedHeader2);
            utxoBuilder.CalculateUtxo(memoryChainStateCursor, chain.ToImmutable(), new[] { emptyCoinbaseTx1, tx1 }.ToBufferBlock()).ToEnumerable().ToList();

            // verify utxo storage
            Assert.IsTrue(memoryChainStateCursor.TryGetUnspentTx(txHash, out actualUnspentTx));
            Assert.IsTrue(actualUnspentTx.OutputStates.Length == 3);
            Assert.IsTrue(actualUnspentTx.OutputStates[0] == OutputState.Spent);
            Assert.IsTrue(actualUnspentTx.OutputStates[1] == OutputState.Spent);
            Assert.IsTrue(actualUnspentTx.OutputStates[2] == OutputState.Unspent);

            // create an input to spend the unspent transaction's third output
            var input2 = new TxInput(txHash, 2, ImmutableArray.Create <byte>(), 0);
            var tx2    = BlockTx.Create(2, Transaction.Create(0, ImmutableArray.Create(input2), ImmutableArray.Create <TxOutput>(), 0));

            // spend the input
            chain.AddBlock(chainedHeader3);
            utxoBuilder.CalculateUtxo(memoryChainStateCursor, chain.ToImmutable(), new[] { emptyCoinbaseTx2, tx2 }.ToBufferBlock()).ToEnumerable().ToList();

            // verify utxo storage
            Assert.IsTrue(memoryChainStateCursor.TryGetUnspentTx(txHash, out actualUnspentTx));
            Assert.IsTrue(actualUnspentTx.IsFullySpent);
        }