Пример #1
0
        public void TestDoubleSpend()
        {
            // prepare test kernel
            var kernel = new StandardKernel(new MemoryStorageModule());

            // prepare block
            var fakeHeaders   = new FakeHeaders();
            var chainedHeader = new ChainedHeader(fakeHeaders.Genesis(), height: 0, totalWork: 0);

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

            // mock a parent utxo containing the unspent transaction
            var unspentTransactions         = ImmutableDictionary.Create <UInt256, UnspentTx>().Add(txHash, unspentTx);
            var mockParentChainStateStorage = new Mock <IChainStateStorage>();

            mockParentChainStateStorage.Setup(utxo => utxo.UnspentTransactions()).Returns(unspentTransactions);
            var parentUtxo = new Utxo(mockParentChainStateStorage.Object);

            // initialize memory utxo builder storage
            var memoryChainStateBuilderStorage = new MemoryChainStateBuilderStorage(mockParentChainStateStorage.Object);

            kernel.Rebind <IChainStateBuilderStorage>().ToConstant(memoryChainStateBuilderStorage);

            // initialize utxo builder
            var chainStateBuilder = new ChainStateBuilder(null, parentUtxo, LogManager.CreateNullLogger(), kernel, null, null, null, null, null);

            // 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
            chainStateBuilder.Spend(0, tx, 0, input, chainedHeader);

            // verify utxo storage
            Assert.IsFalse(memoryChainStateBuilderStorage.UnspentTransactionsDictionary.ContainsKey(txHash));

            // attempt to spend the input again
            chainStateBuilder.Spend(0, tx, 0, input, chainedHeader);

            // validation exception should be thrown
        }
Пример #2
0
        public void TestSimpleSpend()
        {
            // prepare test kernel
            var kernel = new StandardKernel(new MemoryStorageModule());

            // prepare block
            var fakeHeaders   = new FakeHeaders();
            var chainedHeader = new ChainedHeader(fakeHeaders.Genesis(), height: 0, totalWork: 0);

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

            // prepare unspent output
            var unspentTransactions = ImmutableDictionary.Create <UInt256, UnspentTx>().Add(txHash, unspentTx);
            var unspentOutputs      = ImmutableDictionary.Create <TxOutputKey, TxOutput>()
                                      .Add(new TxOutputKey(txHash, 0), new TxOutput(0, ImmutableArray.Create <byte>()))
                                      .Add(new TxOutputKey(txHash, 1), new TxOutput(0, ImmutableArray.Create <byte>()))
                                      .Add(new TxOutputKey(txHash, 2), new TxOutput(0, ImmutableArray.Create <byte>()));

            // mock a parent utxo containing the unspent transaction
            var mockParentChainStateStorage = new Mock <IChainStateStorage>();

            mockParentChainStateStorage.Setup(utxo => utxo.UnspentTransactions()).Returns(unspentTransactions);
            mockParentChainStateStorage.Setup(utxo => utxo.UnspentOutputs()).Returns(unspentOutputs);
            var parentUtxo = new Utxo(mockParentChainStateStorage.Object);

            // initialize memory utxo builder storage
            var memoryChainStateBuilderStorage = new MemoryChainStateBuilderStorage(mockParentChainStateStorage.Object);

            kernel.Rebind <IChainStateBuilderStorage>().ToConstant(memoryChainStateBuilderStorage);

            // initialize utxo builder
            var chainStateBuilder = new ChainStateBuilder(null, parentUtxo, LogManager.CreateNullLogger(), kernel, null, null, null, null, null);

            // 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
            chainStateBuilder.Spend(0, tx0, 0, input0, chainedHeader);

            // verify utxo storage
            Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary.ContainsKey(txHash));
            Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary[txHash].OutputStates.Length == 3);
            Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary[txHash].OutputStates[0] == OutputState.Spent);
            Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary[txHash].OutputStates[1] == OutputState.Unspent);
            Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary[txHash].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
            chainStateBuilder.Spend(1, tx1, 1, input1, chainedHeader);

            // verify utxo storage
            Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary.ContainsKey(txHash));
            Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary[txHash].OutputStates.Length == 3);
            Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary[txHash].OutputStates[0] == OutputState.Spent);
            Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary[txHash].OutputStates[1] == OutputState.Spent);
            Assert.IsTrue(memoryChainStateBuilderStorage.UnspentTransactionsDictionary[txHash].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
            chainStateBuilder.Spend(2, tx2, 2, input2, chainedHeader);

            // verify utxo storage
            Assert.IsFalse(memoryChainStateBuilderStorage.UnspentTransactionsDictionary.ContainsKey(txHash));
        }