Exemplo n.º 1
0
        public bool TryAddUnspentTx(UnspentTx unspentTx)
        {
            if (!this.inTransaction)
            {
                throw new InvalidOperationException();
            }

            try
            {
                using (var jetUpdate = this.jetSession.BeginUpdate(this.unspentTxTableId, JET_prep.Insert))
                {
                    Api.SetColumn(this.jetSession, this.unspentTxTableId, this.txHashColumnId, DbEncoder.EncodeUInt256(unspentTx.TxHash));
                    Api.SetColumn(this.jetSession, this.unspentTxTableId, this.blockIndexColumnId, unspentTx.BlockIndex);
                    Api.SetColumn(this.jetSession, this.unspentTxTableId, this.txIndexColumnId, unspentTx.TxIndex);
                    Api.SetColumn(this.jetSession, this.unspentTxTableId, this.outputStatesColumnId, DataEncoder.EncodeOutputStates(unspentTx.OutputStates));

                    jetUpdate.Save();

                    // increase unspent tx count
                    Api.EscrowUpdate(this.jetSession, this.globalsTableId, this.unspentTxCountColumnId, +1);

                    return(true);
                }
            }
            catch (EsentKeyDuplicateException)
            {
                return(false);
            }
        }
Exemplo n.º 2
0
        public bool TryGetTransaction(UInt256 txHash, out UnspentTx unspentTx)
        {
            Api.JetBeginTransaction2(this.jetSession, BeginTransactionGrbit.ReadOnly);
            try
            {
                //Api.JetSetCurrentIndex(this.jetSession, this.unspentTxTableId, "IX_TxHash");
                Api.MakeKey(this.jetSession, this.unspentTxTableId, txHash.ToByteArray(), MakeKeyGrbit.NewKey);
                if (Api.TrySeek(this.jetSession, this.unspentTxTableId, SeekGrbit.SeekEQ))
                {
                    var confirmedBlockHash = new UInt256(Api.RetrieveColumn(this.jetSession, this.unspentTxTableId, this.confirmedBlockHashColumnId));
                    var outputStates       = DataEncoder.DecodeOutputStates(Api.RetrieveColumn(this.jetSession, this.unspentTxTableId, this.outputStatesColumnId));

                    unspentTx = new UnspentTx(confirmedBlockHash, outputStates);
                    return(true);
                }
                else
                {
                    unspentTx = default(UnspentTx);
                    return(false);
                }
            }
            finally
            {
                Api.JetCommitTransaction(this.jetSession, CommitTransactionGrbit.LazyFlush);
            }
        }
Exemplo n.º 3
0
        public void UpdateTransaction(UInt256 txHash, UnspentTx unspentTx)
        {
            Api.JetBeginTransaction(this.jetSession);
            try
            {
                //Api.JetSetCurrentIndex(this.jetSession, this.unspentTxTableId, "IX_TxHash");
                Api.MakeKey(this.jetSession, this.unspentTxTableId, txHash.ToByteArray(), MakeKeyGrbit.NewKey);
                if (!Api.TrySeek(this.jetSession, this.unspentTxTableId, SeekGrbit.SeekEQ))
                {
                    throw new KeyNotFoundException();
                }

                Api.JetPrepareUpdate(this.jetSession, this.unspentTxTableId, JET_prep.Replace);
                try
                {
                    Api.SetColumn(this.jetSession, this.unspentTxTableId, this.outputStatesColumnId, DataEncoder.EncodeOutputStates(unspentTx.OutputStates));

                    Api.JetUpdate(this.jetSession, this.unspentTxTableId);
                    Api.JetCommitTransaction(this.jetSession, CommitTransactionGrbit.LazyFlush);
                }
                catch (Exception)
                {
                    Api.JetPrepareUpdate(this.jetSession, this.unspentTxTableId, JET_prep.Cancel);
                    throw;
                }
            }
            catch (Exception)
            {
                Api.JetRollback(this.jetSession, RollbackTransactionGrbit.None);
                throw;
            }
        }
Exemplo n.º 4
0
        public void AddTransaction(UInt256 txHash, UnspentTx unspentTx)
        {
            Api.JetBeginTransaction(this.jetSession);
            try
            {
                Api.JetPrepareUpdate(this.jetSession, this.unspentTxTableId, JET_prep.Insert);
                try
                {
                    Api.SetColumn(this.jetSession, this.unspentTxTableId, this.txHashColumnId, txHash.ToByteArray());
                    Api.SetColumn(this.jetSession, this.unspentTxTableId, this.confirmedBlockHashColumnId, unspentTx.ConfirmedBlockHash.ToByteArray());
                    Api.SetColumn(this.jetSession, this.unspentTxTableId, this.outputStatesColumnId, DataEncoder.EncodeOutputStates(unspentTx.OutputStates));

                    Api.JetUpdate(this.jetSession, this.unspentTxTableId);
                    Api.JetCommitTransaction(this.jetSession, CommitTransactionGrbit.LazyFlush);
                    this.unspentTxCount++;
                }
                catch (Exception)
                {
                    Api.JetPrepareUpdate(this.jetSession, this.unspentTxTableId, JET_prep.Cancel);
                    throw;
                }
            }
            catch (Exception)
            {
                Api.JetRollback(this.jetSession, RollbackTransactionGrbit.None);
                throw;
            }
        }
Exemplo n.º 5
0
        public bool TryUpdateUnspentTx(UnspentTx unspentTx)
        {
            CheckWriteTransaction();

            using (SetSessionContext())
            {
                Api.JetSetCurrentIndex(this.jetSession, this.unspentTxTableId, "IX_TxHash");
                Api.MakeKey(this.jetSession, this.unspentTxTableId, DbEncoder.EncodeUInt256(unspentTx.TxHash), MakeKeyGrbit.NewKey);

                if (Api.TrySeek(this.jetSession, this.unspentTxTableId, SeekGrbit.SeekEQ))
                {
                    using (var jetUpdate = this.jetSession.BeginUpdate(this.unspentTxTableId, JET_prep.Replace))
                    {
                        Api.SetColumn(this.jetSession, this.unspentTxTableId, this.outputStatesColumnId, DataEncoder.EncodeOutputStates(unspentTx.OutputStates));

                        jetUpdate.Save();
                    }

                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }
Exemplo n.º 6
0
        private void Unspend(TxInput input, ChainedHeader chainedHeader, ImmutableDictionary <UInt256, SpentTx> spentTxes)
        {
            bool wasRestored;

            UnspentTx unspentTx;

            if (this.chainStateCursor.TryGetUnspentTx(input.PreviousTxOutputKey.TxHash, out unspentTx))
            {
                wasRestored = false;
            }
            else
            {
                // lookup fully spent transaction
                SpentTx spentTx;
                if (!spentTxes.TryGetValue(input.PreviousTxOutputKey.TxHash, out spentTx))
                {
                    throw new ValidationException(chainedHeader.Hash);
                }

                // restore fully spent transaction
                unspentTx   = new UnspentTx(spentTx.TxHash, spentTx.ConfirmedBlockIndex, spentTx.TxIndex, new OutputStates(spentTx.OutputCount, OutputState.Spent));
                wasRestored = true;
            }

            // retrieve previous output index
            var outputIndex = unchecked ((int)input.PreviousTxOutputKey.TxOutputIndex);

            if (outputIndex < 0 || outputIndex >= unspentTx.OutputStates.Length)
            {
                throw new Exception("TODO - corruption");
            }

            // check that output isn't already considered unspent
            if (unspentTx.OutputStates[outputIndex] == OutputState.Unspent)
            {
                throw new ValidationException(chainedHeader.Hash);
            }

            // mark output as unspent
            unspentTx = unspentTx.SetOutputState(outputIndex, OutputState.Unspent);

            // update storage
            if (!wasRestored)
            {
                var wasUpdated = this.chainStateCursor.TryUpdateUnspentTx(unspentTx);
                if (!wasUpdated)
                {
                    throw new ValidationException(chainedHeader.Hash);
                }
            }
            else
            {
                // a restored fully spent transaction must be added back
                var wasAdded = this.chainStateCursor.TryAddUnspentTx(unspentTx);
                if (!wasAdded)
                {
                    throw new ValidationException(chainedHeader.Hash);
                }
            }
        }
Exemplo n.º 7
0
 public static byte[] EncodeUnspentTx(UnspentTx unspentTx)
 {
     using (var stream = new MemoryStream())
     {
         EncodeUnspentTx(stream, unspentTx);
         return(stream.ToArray());
     }
 }
Exemplo n.º 8
0
        public void TestAddBlockConfirmingTx()
        {
            // create tx spending a previous output that exists
            var decodedTx = Transaction.Create(
                0,
                ImmutableArray.Create(new TxInput(UInt256.One, 0, ImmutableArray <byte> .Empty, 0)),
                ImmutableArray.Create(new TxOutput(0, ImmutableArray <byte> .Empty)),
                0);
            var tx = decodedTx.Transaction;

            // create prev output tx
            var unspentTx = new UnspentTx(tx.Inputs[0].PrevTxHash, 0, 1, 0, false, new OutputStates(1, OutputState.Unspent));
            var txOutput  = new TxOutput(0, ImmutableArray <byte> .Empty);

            // create a fake chain
            var fakeHeaders   = new FakeHeaders();
            var genesisHeader = fakeHeaders.GenesisChained();

            // create a block confirming the tx
            var block         = Block.Create(RandomData.RandomBlockHeader().With(PreviousBlock: genesisHeader.Hash), ImmutableArray.Create(tx));
            var chainedHeader = new ChainedHeader(block.Header, 1, 0, DateTimeOffset.Now);

            // mock core storage with chained header
            var coreStorage  = new Mock <ICoreStorage>();
            var initialChain = new ChainBuilder().ToImmutable();

            coreStorage.Setup(x => x.TryReadChain(null, out initialChain)).Returns(true);
            coreStorage.Setup(x => x.TryGetChainedHeader(chainedHeader.Hash, out chainedHeader)).Returns(true);

            // mock chain state with prev output
            var chainState = new Mock <IChainState>();

            chainState.Setup(x => x.TryGetUnspentTx(tx.Inputs[0].PrevTxHash, out unspentTx)).Returns(true);
            chainState.Setup(x => x.TryGetUnspentTxOutput(tx.Inputs[0].PrevTxOutputKey, out txOutput)).Returns(true);

            // mock core daemon for chain state retrieval
            var coreDaemon = new Mock <ICoreDaemon>();

            coreDaemon.Setup(x => x.GetChainState()).Returns(chainState.Object);

            using (var unconfirmedTxesBuilder = new UnconfirmedTxesBuilder(coreDaemon.Object, coreStorage.Object, storageManager))
            {
                // add the tx
                Assert.IsTrue(unconfirmedTxesBuilder.TryAddTransaction(decodedTx));

                // add the block
                unconfirmedTxesBuilder.AddBlock(genesisHeader, Enumerable.Empty <BlockTx>());
                unconfirmedTxesBuilder.AddBlock(chainedHeader, block.BlockTxes);

                // verify the confirmed tx was removed
                UnconfirmedTx unconfirmedTx;
                Assert.IsFalse(unconfirmedTxesBuilder.TryGetTransaction(tx.Hash, out unconfirmedTx));
                Assert.IsNull(unconfirmedTx);

                // verify the confirmed tx was de-indexed against its input
                Assert.AreEqual(0, unconfirmedTxesBuilder.GetTransactionsSpending(tx.Inputs[0].PrevTxOutputKey).Count);
            }
        }
Exemplo n.º 9
0
 public static byte[] EncodeUnspentTx(UnspentTx unspentTx)
 {
     using (var stream = new MemoryStream())
         using (var writer = new BinaryWriter(stream))
         {
             EncodeUnspentTx(writer, unspentTx);
             return(stream.ToArray());
         }
 }
Exemplo n.º 10
0
 public static void EncodeUnspentTx(Stream stream, UnspentTx unspentTx)
 {
     using (var writer = new BinaryWriter(stream, Encoding.ASCII, leaveOpen: true))
     {
         writer.WriteUInt256(unspentTx.ConfirmedBlockHash);
         writer.WriteVarBytes(unspentTx.OutputStates.ToByteArray());
         writer.WriteInt32(unspentTx.OutputStates.Length);
     }
 }
Exemplo n.º 11
0
 public static void EncodeUnspentTx(BinaryWriter writer, UnspentTx unspentTx)
 {
     writer.WriteUInt256(unspentTx.TxHash);
     writer.WriteInt32(unspentTx.BlockIndex);
     writer.WriteInt32(unspentTx.TxIndex);
     writer.WriteUInt32(unspentTx.TxVersion);
     writer.WriteBool(unspentTx.IsCoinbase);
     writer.WriteVarBytes(unspentTx.OutputStates.ToByteArray());
     writer.WriteInt32(unspentTx.OutputStates.Length);
 }
Exemplo n.º 12
0
        public void TestReadUnspentTransactions(ITestStorageProvider provider)
        {
            var unspentTx0 = new UnspentTx(txHash: 0, blockIndex: 0, txIndex: 0, outputStates: new OutputStates(1, OutputState.Unspent));
            var unspentTx1 = new UnspentTx(txHash: 1, blockIndex: 0, txIndex: 0, outputStates: new OutputStates(1, OutputState.Unspent));
            var unspentTx2 = new UnspentTx(txHash: 2, blockIndex: 0, txIndex: 0, outputStates: new OutputStates(1, OutputState.Unspent));

            using (var storageManager = provider.OpenStorageManager())
                using (var handle = storageManager.OpenChainStateCursor())
                {
                    var chainStateCursor = handle.Item;

                    // begin transaction
                    chainStateCursor.BeginTransaction();

                    // verify initial empty state
                    Assert.AreEqual(0, chainStateCursor.ReadUnspentTransactions().Count());

                    // add unspent tx 0
                    Assert.IsTrue(chainStateCursor.TryAddUnspentTx(unspentTx0));

                    // verify unspent txes
                    CollectionAssert.AreEquivalent(new[] { unspentTx0 }, chainStateCursor.ReadUnspentTransactions().ToList());

                    // add unspent tx 1
                    Assert.IsTrue(chainStateCursor.TryAddUnspentTx(unspentTx1));

                    // verify unspent txes
                    CollectionAssert.AreEquivalent(new[] { unspentTx0, unspentTx1 }, chainStateCursor.ReadUnspentTransactions().ToList());

                    // add unspent tx 2
                    Assert.IsTrue(chainStateCursor.TryAddUnspentTx(unspentTx2));

                    // verify unspent txes
                    CollectionAssert.AreEquivalent(new[] { unspentTx0, unspentTx1, unspentTx2 }, chainStateCursor.ReadUnspentTransactions().ToList());

                    // remove unspent tx 2
                    Assert.IsTrue(chainStateCursor.TryRemoveUnspentTx(unspentTx2.TxHash));

                    // verify unspent txes
                    CollectionAssert.AreEquivalent(new[] { unspentTx0, unspentTx1 }, chainStateCursor.ReadUnspentTransactions().ToList());

                    // remove unspent tx 1
                    Assert.IsTrue(chainStateCursor.TryRemoveUnspentTx(unspentTx1.TxHash));

                    // verify unspent txes
                    CollectionAssert.AreEquivalent(new[] { unspentTx0 }, chainStateCursor.ReadUnspentTransactions().ToList());

                    // remove unspent tx 0
                    Assert.IsTrue(chainStateCursor.TryRemoveUnspentTx(unspentTx0.TxHash));

                    // verify unspent txes
                    Assert.AreEqual(0, chainStateCursor.ReadUnspentTransactions().Count());
                }
        }
Exemplo n.º 13
0
        private void TestUnspentTxCount(ITestStorageProvider provider)
        {
            var unspentTx0 = new UnspentTx(txHash: 0, blockIndex: 0, txIndex: 0, outputStates: new OutputStates(1, OutputState.Unspent));
            var unspentTx1 = new UnspentTx(txHash: 1, blockIndex: 0, txIndex: 0, outputStates: new OutputStates(1, OutputState.Unspent));
            var unspentTx2 = new UnspentTx(txHash: 2, blockIndex: 0, txIndex: 0, outputStates: new OutputStates(1, OutputState.Unspent));

            using (var storageManager = provider.OpenStorageManager())
                using (var handle = storageManager.OpenChainStateCursor())
                {
                    var chainStateCursor = handle.Item;

                    // begin transaction
                    chainStateCursor.BeginTransaction();

                    // verify initial count
                    Assert.AreEqual(0, chainStateCursor.UnspentTxCount);

                    // add unspent tx 0
                    chainStateCursor.TryAddUnspentTx(unspentTx0);

                    // verify count
                    Assert.AreEqual(1, chainStateCursor.UnspentTxCount);

                    // add unspent tx 1
                    chainStateCursor.TryAddUnspentTx(unspentTx1);

                    // verify count
                    Assert.AreEqual(2, chainStateCursor.UnspentTxCount);

                    // add unspent tx 2
                    chainStateCursor.TryAddUnspentTx(unspentTx2);

                    // verify count
                    Assert.AreEqual(3, chainStateCursor.UnspentTxCount);

                    // remove unspent tx 2
                    chainStateCursor.TryRemoveUnspentTx(unspentTx2.TxHash);

                    // verify count
                    Assert.AreEqual(2, chainStateCursor.UnspentTxCount);

                    // remove unspent tx 1
                    chainStateCursor.TryRemoveUnspentTx(unspentTx1.TxHash);

                    // verify count
                    Assert.AreEqual(1, chainStateCursor.UnspentTxCount);

                    // remove unspent tx 0
                    chainStateCursor.TryRemoveUnspentTx(unspentTx0.TxHash);

                    // verify count
                    Assert.AreEqual(0, chainStateCursor.UnspentTxCount);
                }
        }
Exemplo n.º 14
0
        private void TestRollbackTransaction(ITestStorageProvider provider)
        {
            var fakeHeaders    = new FakeHeaders();
            var chainedHeader0 = fakeHeaders.GenesisChained();
            var chainedHeader1 = fakeHeaders.NextChained();
            var chainedHeader2 = fakeHeaders.NextChained();

            var unspentTx = new UnspentTx(txHash: 0, blockIndex: 0, txIndex: 0, outputStates: new OutputStates(1, OutputState.Unspent));

            var spentTxes = ImmutableList.Create(new SpentTx(txHash: 1, confirmedBlockIndex: 0, txIndex: 0, outputCount: 1, spentBlockIndex: 0));

            using (var storageManager = provider.OpenStorageManager())
                using (var handle = storageManager.OpenChainStateCursor())
                {
                    var chainStateCursor = handle.Item;

                    // begin transaction
                    chainStateCursor.BeginTransaction();

                    // add header 0
                    chainStateCursor.AddChainedHeader(chainedHeader0);

                    // verify chain
                    CollectionAssert.AreEqual(new[] { chainedHeader0 }, chainStateCursor.ReadChain().ToList());

                    // add unspent tx
                    chainStateCursor.TryAddUnspentTx(unspentTx);

                    // verify unspent tx
                    Assert.IsTrue(chainStateCursor.ContainsUnspentTx(unspentTx.TxHash));
                    Assert.AreEqual(1, chainStateCursor.UnspentTxCount);

                    // add spent txes
                    chainStateCursor.TryAddBlockSpentTxes(0, spentTxes);

                    // verify spent txes
                    IImmutableList <SpentTx> actualSpentTxes;
                    Assert.IsTrue(chainStateCursor.TryGetBlockSpentTxes(0, out actualSpentTxes));
                    CollectionAssert.AreEqual(spentTxes, (ICollection)actualSpentTxes);

                    // rollback transaction
                    chainStateCursor.RollbackTransaction();

                    // verify chain
                    Assert.AreEqual(0, chainStateCursor.ReadChain().Count());

                    // verify unspent tx
                    Assert.IsFalse(chainStateCursor.ContainsUnspentTx(unspentTx.TxHash));
                    Assert.AreEqual(0, chainStateCursor.UnspentTxCount);

                    // verify spent txes
                    Assert.IsFalse(chainStateCursor.TryGetBlockSpentTxes(0, out actualSpentTxes));
                }
        }
Exemplo n.º 15
0
 public bool TryGetUnspentTx(UInt256 txHash, out UnspentTx unspentTx)
 {
     if (this.inTransaction)
     {
         return(this.unspentTransactions.TryGetValue(txHash, out unspentTx));
     }
     else
     {
         return(this.chainStateStorage.TryGetUnspentTx(txHash, out unspentTx));
     }
 }
Exemplo n.º 16
0
        private void Mint(Transaction tx, int txIndex, ChainedHeader chainedHeader)
        {
            // add transaction to the utxo
            var unspentTx = new UnspentTx(tx.Hash, chainedHeader.Height, txIndex, tx.Outputs.Length, OutputState.Unspent);

            if (!this.chainStateCursor.TryAddUnspentTx(unspentTx))
            {
                // duplicate transaction
                this.logger.Warn("Duplicate transaction at block {0:#,##0}, {1}, coinbase".Format2(chainedHeader.Height, chainedHeader.Hash.ToHexNumberString()));
                throw new ValidationException(chainedHeader.Hash);
            }
        }
Exemplo n.º 17
0
 public bool TryGetUnspentTx(UInt256 txHash, out UnspentTx unspentTx)
 {
     this.semaphore.Wait();
     try
     {
         return(this.unspentTransactions.TryGetValue(txHash, out unspentTx));
     }
     finally
     {
         this.semaphore.Release();
     }
 }
Exemplo n.º 18
0
        public bool TryAddUnspentTx(UnspentTx unspentTx)
        {
            return(this.semaphore.Do(() =>
            {
                var wasAdded = this.unspentTransactions.TryAdd(unspentTx.TxHash, unspentTx);
                if (wasAdded)
                {
                    this.unspentTxesVersion++;
                }

                return wasAdded;
            }));
        }
Exemplo n.º 19
0
        private void TestTryAddGetRemoveUnspentTx(ITestStorageProvider provider)
        {
            var unspentTx0 = new UnspentTx(txHash: 0, blockIndex: 0, txIndex: 0, outputStates: new OutputStates(1, OutputState.Unspent));
            var unspentTx1 = new UnspentTx(txHash: 1, blockIndex: 0, txIndex: 0, outputStates: new OutputStates(1, OutputState.Unspent));

            using (var storageManager = provider.OpenStorageManager())
                using (var handle = storageManager.OpenChainStateCursor())
                {
                    var chainStateCursor = handle.Item;

                    // begin transaction
                    chainStateCursor.BeginTransaction();

                    // verify initial empty state
                    UnspentTx actualUnspentTx0, actualUnspentTx1;
                    Assert.IsFalse(chainStateCursor.TryGetUnspentTx(unspentTx0.TxHash, out actualUnspentTx0));
                    Assert.IsFalse(chainStateCursor.TryGetUnspentTx(unspentTx1.TxHash, out actualUnspentTx1));

                    // add unspent tx 0
                    Assert.IsTrue(chainStateCursor.TryAddUnspentTx(unspentTx0));

                    // verify unspent txes
                    Assert.IsTrue(chainStateCursor.TryGetUnspentTx(unspentTx0.TxHash, out actualUnspentTx0));
                    Assert.AreEqual(unspentTx0, actualUnspentTx0);
                    Assert.IsFalse(chainStateCursor.TryGetUnspentTx(unspentTx1.TxHash, out actualUnspentTx1));

                    // add unspent tx 1
                    Assert.IsTrue(chainStateCursor.TryAddUnspentTx(unspentTx1));

                    // verify unspent txes
                    Assert.IsTrue(chainStateCursor.TryGetUnspentTx(unspentTx0.TxHash, out actualUnspentTx0));
                    Assert.AreEqual(unspentTx0, actualUnspentTx0);
                    Assert.IsTrue(chainStateCursor.TryGetUnspentTx(unspentTx1.TxHash, out actualUnspentTx1));
                    Assert.AreEqual(unspentTx1, actualUnspentTx1);

                    // remove unspent tx 1
                    Assert.IsTrue(chainStateCursor.TryRemoveUnspentTx(unspentTx1.TxHash));

                    // verify unspent txes
                    Assert.IsTrue(chainStateCursor.TryGetUnspentTx(unspentTx0.TxHash, out actualUnspentTx0));
                    Assert.AreEqual(unspentTx0, actualUnspentTx0);
                    Assert.IsFalse(chainStateCursor.TryGetUnspentTx(unspentTx1.TxHash, out actualUnspentTx1));

                    // remove unspent tx 0
                    Assert.IsTrue(chainStateCursor.TryRemoveUnspentTx(unspentTx0.TxHash));

                    // verify unspent txes
                    Assert.IsFalse(chainStateCursor.TryGetUnspentTx(unspentTx0.TxHash, out actualUnspentTx0));
                    Assert.IsFalse(chainStateCursor.TryGetUnspentTx(unspentTx1.TxHash, out actualUnspentTx1));
                }
        }
Exemplo n.º 20
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());
        }
Exemplo n.º 21
0
        public bool TryUpdateUnspentTx(UnspentTx unspentTx)
        {
            CheckWriteTransaction();

            if (unspentTransactions.Value.ContainsKey(unspentTx.TxHash))
            {
                unspentTransactions.Modify(x => x[unspentTx.TxHash] = unspentTx);
                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemplo n.º 22
0
        public bool TryAddUnspentTx(UnspentTx unspentTx)
        {
            CheckWriteTransaction();

            try
            {
                unspentTransactions.Modify(x => x.Add(unspentTx.TxHash, unspentTx));
                return(true);
            }
            catch (ArgumentException)
            {
                return(false);
            }
        }
Exemplo n.º 23
0
 public bool TryUpdateUnspentTx(UnspentTx unspentTx)
 {
     return(this.semaphore.Do(() =>
     {
         if (this.unspentTransactions.ContainsKey(unspentTx.TxHash))
         {
             this.unspentTransactions[unspentTx.TxHash] = unspentTx;
             this.unspentTxesVersion++;
             return true;
         }
         else
         {
             return false;
         }
     }));
 }
Exemplo n.º 24
0
        public bool TryGetUnspentTx(UInt256 txHash, out UnspentTx unspentTx)
        {
            Api.JetSetCurrentIndex(this.jetSession, this.unspentTxTableId, "IX_TxHash");
            Api.MakeKey(this.jetSession, this.unspentTxTableId, DbEncoder.EncodeUInt256(txHash), MakeKeyGrbit.NewKey);
            if (Api.TrySeek(this.jetSession, this.unspentTxTableId, SeekGrbit.SeekEQ))
            {
                var blockIndex   = Api.RetrieveColumnAsInt32(this.jetSession, this.unspentTxTableId, this.blockIndexColumnId).Value;
                var txIndex      = Api.RetrieveColumnAsInt32(this.jetSession, this.unspentTxTableId, this.txIndexColumnId).Value;
                var outputStates = DataEncoder.DecodeOutputStates(Api.RetrieveColumn(this.jetSession, this.unspentTxTableId, this.outputStatesColumnId));

                unspentTx = new UnspentTx(txHash, blockIndex, txIndex, outputStates);
                return(true);
            }

            unspentTx = default(UnspentTx);
            return(false);
        }
Exemplo n.º 25
0
        private void TestCommitTransaction(ITestStorageProvider provider)
        {
            var fakeHeaders    = new FakeHeaders();
            var chainedHeader0 = fakeHeaders.GenesisChained();
            var unspentTx      = new UnspentTx(txHash: 0, blockIndex: 0, txIndex: 0, outputStates: new OutputStates(1, OutputState.Unspent));
            var spentTxes      = ImmutableList.Create(new SpentTx(txHash: 1, confirmedBlockIndex: 0, txIndex: 0, outputCount: 1, spentBlockIndex: 0));

            using (var storageManager = provider.OpenStorageManager())
                using (var handle = storageManager.OpenChainStateCursor())
                {
                    var chainStateCursor = handle.Item;

                    // begin transaction
                    chainStateCursor.BeginTransaction();

                    // add data
                    chainStateCursor.AddChainedHeader(chainedHeader0);
                    chainStateCursor.TryAddUnspentTx(unspentTx);
                    chainStateCursor.TryAddBlockSpentTxes(0, spentTxes);

                    // verify data
                    Assert.AreEqual(chainedHeader0, chainStateCursor.GetChainTip());
                    Assert.AreEqual(1, chainStateCursor.UnspentTxCount);

                    UnspentTx actualUnspentTx;
                    Assert.IsTrue(chainStateCursor.TryGetUnspentTx(unspentTx.TxHash, out actualUnspentTx));
                    Assert.AreEqual(unspentTx, actualUnspentTx);

                    IImmutableList <SpentTx> actualSpentTxes;
                    Assert.IsTrue(chainStateCursor.TryGetBlockSpentTxes(0, out actualSpentTxes));
                    CollectionAssert.AreEqual((ICollection)spentTxes, (ICollection)actualSpentTxes);

                    // commit transaction
                    chainStateCursor.CommitTransaction();

                    // verify data
                    Assert.AreEqual(chainedHeader0, chainStateCursor.GetChainTip());
                    Assert.AreEqual(1, chainStateCursor.UnspentTxCount);

                    Assert.IsTrue(chainStateCursor.TryGetUnspentTx(unspentTx.TxHash, out actualUnspentTx));
                    Assert.AreEqual(unspentTx, actualUnspentTx);

                    Assert.IsTrue(chainStateCursor.TryGetBlockSpentTxes(0, out actualSpentTxes));
                    CollectionAssert.AreEqual((ICollection)spentTxes, (ICollection)actualSpentTxes);
                }
        }
Exemplo n.º 26
0
        private void TestContainsUnspentTx(ITestStorageProvider provider)
        {
            var unspentTx0 = new UnspentTx(txHash: 0, blockIndex: 0, txIndex: 0, outputStates: new OutputStates(1, OutputState.Unspent));
            var unspentTx1 = new UnspentTx(txHash: 1, blockIndex: 0, txIndex: 0, outputStates: new OutputStates(1, OutputState.Unspent));

            using (var storageManager = provider.OpenStorageManager())
                using (var handle = storageManager.OpenChainStateCursor())
                {
                    var chainStateCursor = handle.Item;

                    // begin transaction
                    chainStateCursor.BeginTransaction();

                    // verify presence
                    Assert.IsFalse(chainStateCursor.ContainsUnspentTx(unspentTx0.TxHash));
                    Assert.IsFalse(chainStateCursor.ContainsUnspentTx(unspentTx1.TxHash));

                    // add unspent tx 0
                    chainStateCursor.TryAddUnspentTx(unspentTx0);

                    // verify presence
                    Assert.IsTrue(chainStateCursor.ContainsUnspentTx(unspentTx0.TxHash));
                    Assert.IsFalse(chainStateCursor.ContainsUnspentTx(unspentTx1.TxHash));

                    // add unspent tx 1
                    chainStateCursor.TryAddUnspentTx(unspentTx1);

                    // verify presence
                    Assert.IsTrue(chainStateCursor.ContainsUnspentTx(unspentTx0.TxHash));
                    Assert.IsTrue(chainStateCursor.ContainsUnspentTx(unspentTx1.TxHash));

                    // remove unspent tx 1
                    chainStateCursor.TryRemoveUnspentTx(unspentTx1.TxHash);

                    // verify presence
                    Assert.IsTrue(chainStateCursor.ContainsUnspentTx(unspentTx0.TxHash));
                    Assert.IsFalse(chainStateCursor.ContainsUnspentTx(unspentTx1.TxHash));

                    // remove unspent tx 0
                    chainStateCursor.TryRemoveUnspentTx(unspentTx0.TxHash);

                    // verify presence
                    Assert.IsFalse(chainStateCursor.ContainsUnspentTx(unspentTx0.TxHash));
                    Assert.IsFalse(chainStateCursor.ContainsUnspentTx(unspentTx1.TxHash));
                }
        }
Exemplo n.º 27
0
        public bool TryGetUnspentTx(UInt256 txHash, out UnspentTx unspentTx)
        {
            CheckTransaction();

            using (SetSessionContext())
            {
                Api.JetSetCurrentIndex(this.jetSession, this.unspentTxTableId, "IX_TxHash");
                Api.MakeKey(this.jetSession, this.unspentTxTableId, DbEncoder.EncodeUInt256(txHash), MakeKeyGrbit.NewKey);
                if (Api.TrySeek(this.jetSession, this.unspentTxTableId, SeekGrbit.SeekEQ))
                {
                    var blockIndexColumn = new Int32ColumnValue {
                        Columnid = this.blockIndexColumnId
                    };
                    var txIndexColumn = new Int32ColumnValue {
                        Columnid = this.txIndexColumnId
                    };
                    var txVersionColumn = new UInt32ColumnValue {
                        Columnid = this.txVersionColumnId
                    };
                    var isCoinbaseColumn = new BoolColumnValue {
                        Columnid = this.isCoinbaseColumnId
                    };
                    var outputStatesColumn = new BytesColumnValue {
                        Columnid = this.outputStatesColumnId
                    };
                    var txOutputBytesColumn = new BytesColumnValue {
                        Columnid = this.txOutputBytesColumnId
                    };
                    Api.RetrieveColumns(this.jetSession, this.unspentTxTableId, blockIndexColumn, txIndexColumn, txVersionColumn, isCoinbaseColumn, outputStatesColumn, txOutputBytesColumn);

                    var blockIndex   = blockIndexColumn.Value.Value;
                    var txIndex      = txIndexColumn.Value.Value;
                    var txVersion    = txVersionColumn.Value.Value;
                    var isCoinbase   = isCoinbaseColumn.Value.Value;
                    var outputStates = DataDecoder.DecodeOutputStates(outputStatesColumn.Value);

                    unspentTx = new UnspentTx(txHash, blockIndex, txIndex, txVersion, isCoinbase, outputStates);
                    return(true);
                }

                unspentTx = default(UnspentTx);
                return(false);
            }
        }
Exemplo n.º 28
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
        }
Exemplo n.º 29
0
 public bool TryAddUnspentTx(UnspentTx unspentTx)
 {
     if (this.inTransaction)
     {
         try
         {
             this.unspentTransactions.Add(unspentTx.TxHash, unspentTx);
             this.unspentTxesModified = true;
             return(true);
         }
         catch (ArgumentException)
         {
             return(false);
         }
     }
     else
     {
         return(this.chainStateStorage.TryAddUnspentTx(unspentTx));
     }
 }
Exemplo n.º 30
0
 public bool TryUpdateUnspentTx(UnspentTx unspentTx)
 {
     if (this.inTransaction)
     {
         if (this.unspentTransactions.ContainsKey(unspentTx.TxHash))
         {
             this.unspentTransactions[unspentTx.TxHash] = unspentTx;
             this.unspentTxesModified = true;
             return(true);
         }
         else
         {
             return(false);
         }
     }
     else
     {
         return(this.chainStateStorage.TryUpdateUnspentTx(unspentTx));
     }
 }
Exemplo n.º 31
0
        public void TestUnspentTxEquality()
        {
            var randomUnspentTx = RandomData.RandomUnspentTx();

            var sameUnspentTx = new UnspentTx
            (
                txHash: randomUnspentTx.TxHash,
                blockHash: randomUnspentTx.BlockHash,
                txIndex: randomUnspentTx.TxIndex,
                unspentOutputs: randomUnspentTx.UnspentOutputs
            );

            var differentUnspentTxBlockHash = new UnspentTx
            (
                txHash: randomUnspentTx.TxHash,
                blockHash: ~randomUnspentTx.BlockHash,
                txIndex: randomUnspentTx.TxIndex,
                unspentOutputs: randomUnspentTx.UnspentOutputs
            );

            var differentUnspentTxTxIndex = new UnspentTx
            (
                txHash: randomUnspentTx.TxHash,
                blockHash: randomUnspentTx.BlockHash,
                txIndex: ~randomUnspentTx.TxIndex,
                unspentOutputs: randomUnspentTx.UnspentOutputs
            );

            var differentUnspentTxTxHash = new UnspentTx
            (
                txHash: ~randomUnspentTx.TxHash,
                blockHash: randomUnspentTx.BlockHash,
                txIndex: randomUnspentTx.TxIndex,
                unspentOutputs: randomUnspentTx.UnspentOutputs
            );

            var differentUnspentTxUnpsentOutputs = new UnspentTx
            (
                txHash: ~randomUnspentTx.TxHash,
                blockHash: randomUnspentTx.BlockHash,
                txIndex: randomUnspentTx.TxIndex,
                unspentOutputs: randomUnspentTx.UnspentOutputs
            );

            Assert.IsTrue(randomUnspentTx.Equals(sameUnspentTx));
            Assert.IsTrue(randomUnspentTx == sameUnspentTx);
            Assert.IsFalse(randomUnspentTx != sameUnspentTx);

            Assert.IsFalse(randomUnspentTx.Equals(differentUnspentTxBlockHash));
            Assert.IsFalse(randomUnspentTx == differentUnspentTxBlockHash);
            Assert.IsTrue(randomUnspentTx != differentUnspentTxBlockHash);

            Assert.IsFalse(randomUnspentTx.Equals(differentUnspentTxTxIndex));
            Assert.IsFalse(randomUnspentTx == differentUnspentTxTxIndex);
            Assert.IsTrue(randomUnspentTx != differentUnspentTxTxIndex);

            Assert.IsFalse(randomUnspentTx.Equals(differentUnspentTxTxHash));
            Assert.IsFalse(randomUnspentTx == differentUnspentTxTxHash);
            Assert.IsTrue(randomUnspentTx != differentUnspentTxTxHash);

            Assert.IsFalse(randomUnspentTx.Equals(differentUnspentTxUnpsentOutputs));
            Assert.IsFalse(randomUnspentTx == differentUnspentTxUnpsentOutputs);
            Assert.IsTrue(randomUnspentTx != differentUnspentTxUnpsentOutputs);
        }