示例#1
0
        public static bool CanSpend(this IChainState chainState, TxOutputKey txOutputKey)
        {
            if (txOutputKey == null)
            {
                throw new ArgumentNullException("prevTxOutput");
            }

            UnspentTx unspentTx;

            if (chainState.TryGetUnspentTx(txOutputKey.TxHash, out unspentTx))
            {
                var outputIndex = unchecked ((int)txOutputKey.TxOutputIndex);

                if (outputIndex < 0 || outputIndex >= unspentTx.OutputStates.Length)
                {
                    return(false);
                }

                return(unspentTx.OutputStates[outputIndex] == OutputState.Unspent);
            }
            else
            {
                return(false);
            }
        }
示例#2
0
        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);
        }
示例#3
0
        public void TestTxOutputKeyEquality()
        {
            var randomTxOutputKey = RandomData.RandomTxOutputKey();

            var sameTxOutputKey = new TxOutputKey
            (
                txHash: randomTxOutputKey.TxHash,
                txOutputIndex: randomTxOutputKey.TxOutputIndex
            );

            var differentTxOutputKeyTxHash = new TxOutputKey
            (
                txHash: ~randomTxOutputKey.TxHash,
                txOutputIndex: randomTxOutputKey.TxOutputIndex
            );

            var differentTxOutputKeyTxOutputIndex = new TxOutputKey
            (
                txHash: randomTxOutputKey.TxHash,
                txOutputIndex: ~randomTxOutputKey.TxOutputIndex
            );

            Assert.IsTrue(randomTxOutputKey.Equals(sameTxOutputKey));
            Assert.IsTrue(randomTxOutputKey == sameTxOutputKey);
            Assert.IsFalse(randomTxOutputKey != sameTxOutputKey);

            Assert.IsFalse(randomTxOutputKey.Equals(differentTxOutputKeyTxHash));
            Assert.IsFalse(randomTxOutputKey == differentTxOutputKeyTxHash);
            Assert.IsTrue(randomTxOutputKey != differentTxOutputKeyTxHash);

            Assert.IsFalse(randomTxOutputKey.Equals(differentTxOutputKeyTxOutputIndex));
            Assert.IsFalse(randomTxOutputKey == differentTxOutputKeyTxOutputIndex);
            Assert.IsTrue(randomTxOutputKey != differentTxOutputKeyTxOutputIndex);
        }
示例#4
0
        public static byte[] EncodeTxOutputKey(TxOutputKey txOutputKey)
        {
            var txOutputKeyBytes = new byte[36];
            Buffer.BlockCopy(DbEncoder.EncodeUInt256(txOutputKey.TxHash), 0, txOutputKeyBytes, 0, 32);
            Buffer.BlockCopy(DbEncoder.EncodeInt32(txOutputKey.TxOutputIndex.ToIntChecked()), 0, txOutputKeyBytes, 32, 4);

            return txOutputKeyBytes;
        }
示例#5
0
 public bool TryGetUnspentTxOutput(TxOutputKey txOutputKey, out TxOutput txOutput)
 {
     using (var handle = this.cursorCache.TakeItem())
     {
         var cursor = handle.Item.Item;
         return(cursor.TryGetUnspentTxOutput(txOutputKey, out txOutput));
     }
 }
示例#6
0
 public ImmutableDictionary <UInt256, UnconfirmedTx> GetTransactionsSpending(TxOutputKey txOutputKey)
 {
     using (var handle = this.cursorCache.TakeItem())
     {
         var cursor = handle.Item.Item;
         return(cursor.GetTransactionsSpending(txOutputKey));
     }
 }
示例#7
0
        //public static void DecodeBlockHashTxIndex(byte[] bytes, out UInt256 blockHash, out int txIndex)
        //{
        //    var blockHashBytes = new byte[32];
        //    var txIndexBytes = new byte[4];

        //    Buffer.BlockCopy(bytes, 0, blockHashBytes, 0, 32);
        //    Buffer.BlockCopy(bytes, 32, txIndexBytes, 0, 4);

        //    blockHash = DbEncoder.DecodeUInt256(blockHashBytes);
        //    txIndex = DbEncoder.DecodeInt32(txIndexBytes);
        //}

        //public static byte[] EncodeBlockHashTxIndex(UInt256 blockHash, int txIndex)
        //{
        //    var blockHashTxIndexBytes = new byte[36];
        //    Buffer.BlockCopy(DbEncoder.EncodeUInt256(blockHash), 0, blockHashTxIndexBytes, 0, 32);
        //    Buffer.BlockCopy(DbEncoder.EncodeInt32(txIndex), 0, blockHashTxIndexBytes, 32, 4);

        //    return blockHashTxIndexBytes;
        //}

        public static byte[] EncodeTxOutputKey(TxOutputKey txOutputKey)
        {
            var buffer = new byte[36];
            txOutputKey.TxHash.ToByteArrayBE(buffer, 0);
            Buffer.BlockCopy(EncodeInt32((int)txOutputKey.TxOutputIndex), 0, buffer, 32, 4);

            return buffer;
        }
示例#8
0
 public TxInput With(TxOutputKey previousTxOutput = null, ImmutableArray<byte>? scriptSignature = null, UInt32? sequence = null)
 {
     return new TxInput
     (
         previousTxOutput ?? this.PreviousTxOutputKey,
         scriptSignature ?? this.ScriptSignature,
         sequence ?? this.Sequence
     );
 }
示例#9
0
        public bool ContainsUnspentTxOutput(TxOutputKey txOutputKey)
        {
            using (var handle = this.cursorCache.TakeItem())
            {
                var cursor = handle.Item.Item;

                return(cursor.ContainsUnspentTxOutput(txOutputKey));
            }
        }
示例#10
0
 public TxInput With(TxOutputKey previousTxOutput = null, ImmutableArray <byte>?scriptSignature = null, UInt32?sequence = null)
 {
     return(new TxInput
            (
                previousTxOutput ?? this.PreviousTxOutputKey,
                scriptSignature ?? this.ScriptSignature,
                sequence ?? this.Sequence
            ));
 }
示例#11
0
        private static TransformManyBlock<DecodedBlockTx, Tuple<TxOutputKey, CompletionCount, DecodedBlockTx>> InitQueueUnspentTxLookup(CancellationToken cancelToken)
        {
            return new TransformManyBlock<DecodedBlockTx, Tuple<TxOutputKey, CompletionCount, DecodedBlockTx>>(
                blockTx =>
                {
                    var tx = blockTx.Transaction;

                    var outputCount = tx.Outputs.Length;
                    var inputCount = !blockTx.IsCoinbase ? tx.Inputs.Length * 2 : 0;

                    var txOutputKeys = new Tuple<TxOutputKey, CompletionCount, DecodedBlockTx>[1 + outputCount + inputCount];
                    var completionCount = new CompletionCount(txOutputKeys.Length);
                    var keyIndex = 0;

                    // warm-up the UnspentTx entry that will be added for the new tx
                    txOutputKeys[keyIndex++] = Tuple.Create(new TxOutputKey(blockTx.Hash, uint.MaxValue), completionCount, blockTx);

                    // warm-up the TxOutput entries that will be added for each of the tx's outputs
                    for (var outputIndex = 0; outputIndex < tx.Outputs.Length; outputIndex++)
                    {
                        var txOutputKey = new TxOutputKey(blockTx.Hash, (uint)outputIndex);
                        txOutputKeys[keyIndex++] = Tuple.Create(txOutputKey, completionCount, blockTx);
                    }

                    // warm-up the previous UnspentTx and TxOutput entries that will be needed for each of the tx's inputs
                    if (!blockTx.IsCoinbase)
                    {
                        for (var inputIndex = 0; inputIndex < tx.Inputs.Length; inputIndex++)
                        {
                            var input = tx.Inputs[inputIndex];

                            // input's previous tx's UnspentTx entry
                            var txOutputKey = new TxOutputKey(input.PrevTxHash, uint.MaxValue);
                            txOutputKeys[keyIndex++] = Tuple.Create(txOutputKey, completionCount, blockTx);

                            // input's previous tx outputs's TxOutput entry
                            txOutputKey = input.PrevTxOutputKey;
                            txOutputKeys[keyIndex++] = Tuple.Create(txOutputKey, completionCount, blockTx);
                        }
                    }

                    Debug.Assert(txOutputKeys.All(x => x != null));

                    return txOutputKeys;
                },
                new ExecutionDataflowBlockOptions { CancellationToken = cancelToken });
        }
示例#12
0
        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);
        }
示例#13
0
        public ImmutableDictionary<UInt256, UnconfirmedTx> GetTransactionsSpending(TxOutputKey txOutputKey)
        {
            using (var handle = storageManager.OpenUnconfirmedTxesCursor())
            {
                var unconfirmedTxesCursor = handle.Item;
                unconfirmedTxesCursor.BeginTransaction(readOnly: true);

                return unconfirmedTxesCursor.GetTransactionsSpending(txOutputKey);
            }
        }
示例#14
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());
        }
示例#15
0
        public bool ContainsUnspentTxOutput(TxOutputKey txOutputKey)
        {
            using (var handle = this.cursorCache.TakeItem())
            {
                var cursor = handle.Item.Item;

                return cursor.ContainsUnspentTxOutput(txOutputKey);
            }
        }
示例#16
0
        public bool TryRemoveUnspentTxOutput(TxOutputKey txOutputKey)
        {
            CheckWriteTransaction();

            using (SetSessionContext())
            {
                Api.JetSetCurrentIndex(this.jetSession, this.unspentTxOutputTableId, "IX_TxOutputKey");
                Api.MakeKey(this.jetSession, this.unspentTxOutputTableId, DbEncoder.EncodeTxOutputKey(txOutputKey), MakeKeyGrbit.NewKey);
                if (Api.TrySeek(this.jetSession, this.unspentTxOutputTableId, SeekGrbit.SeekEQ))
                {
                    Api.JetDelete(this.jetSession, this.unspentTxOutputTableId);

                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
示例#17
0
        public bool TryGetUnspentTxOutput(TxOutputKey txOutputKey, out TxOutput txOutput)
        {
            CheckTransaction();

            using (SetSessionContext())
            {
                Api.JetSetCurrentIndex(this.jetSession, this.unspentTxOutputTableId, "IX_TxOutputKey");
                Api.MakeKey(this.jetSession, this.unspentTxOutputTableId, DbEncoder.EncodeTxOutputKey(txOutputKey), MakeKeyGrbit.NewKey);
                if (Api.TrySeek(this.jetSession, this.unspentTxOutputTableId, SeekGrbit.SeekEQ))
                {
                    var txOutputBytesColumn = new BytesColumnValue { Columnid = this.txOutputBytesColumnId };
                    Api.RetrieveColumns(this.jetSession, this.unspentTxOutputTableId, txOutputBytesColumn);

                    txOutput = DataDecoder.DecodeTxOutput(txOutputBytesColumn.Value);
                    return true;
                }

                txOutput = default(TxOutput);
                return false;
            }
        }
 public void WarmUnspentTxOutput(TxOutputKey txOutputKey)
 {
     unspentTxOutputs.WarmupValue(txOutputKey);
 }
示例#19
0
 public static byte[] EncodeTxOutputKey(TxOutputKey txOutputKey)
 {
     using (var stream = new MemoryStream())
     using (var writer = new BinaryWriter(stream))
     {
         EncodeTxOutputKey(writer, txOutputKey);
         return stream.ToArray();
     }
 }
示例#20
0
        private void TestContainsUnspentTxOutput(ITestStorageProvider provider)
        {
            var random = new Random();

            var txOutput0Key = new TxOutputKey(UInt256.Zero, 0);
            var txOutput0 = new TxOutput(0, random.NextBytes(100).ToImmutableArray());
            var txOutput1Key = new TxOutputKey(UInt256.One, 1);
            var txOutput1 = new TxOutput(1, random.NextBytes(100).ToImmutableArray());

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

                // begin transaction
                chainStateCursor.BeginTransaction();

                // verify presence
                Assert.IsFalse(chainStateCursor.ContainsUnspentTxOutput(txOutput0Key));
                Assert.IsFalse(chainStateCursor.ContainsUnspentTxOutput(txOutput1Key));

                // add unspent tx 0
                chainStateCursor.TryAddUnspentTxOutput(txOutput0Key, txOutput0);

                // verify presence
                Assert.IsTrue(chainStateCursor.ContainsUnspentTxOutput(txOutput0Key));
                Assert.IsFalse(chainStateCursor.ContainsUnspentTxOutput(txOutput1Key));

                // add unspent tx 1
                chainStateCursor.TryAddUnspentTxOutput(txOutput1Key, txOutput1);

                // verify presence
                Assert.IsTrue(chainStateCursor.ContainsUnspentTxOutput(txOutput0Key));
                Assert.IsTrue(chainStateCursor.ContainsUnspentTxOutput(txOutput1Key));

                // remove unspent tx 1
                chainStateCursor.TryRemoveUnspentTxOutput(txOutput1Key);

                // verify presence
                Assert.IsTrue(chainStateCursor.ContainsUnspentTxOutput(txOutput0Key));
                Assert.IsFalse(chainStateCursor.ContainsUnspentTxOutput(txOutput1Key));

                // remove unspent tx 0
                chainStateCursor.TryRemoveUnspentTxOutput(txOutput0Key);

                // verify presence
                Assert.IsFalse(chainStateCursor.ContainsUnspentTxOutput(txOutput0Key));
                Assert.IsFalse(chainStateCursor.ContainsUnspentTxOutput(txOutput1Key));
            }
        }
示例#21
0
 public bool ContainsUnspentTxOutput(TxOutputKey txOutputKey)
 {
     CheckTransaction();
     return unspentTxOutputs.Value.ContainsKey(txOutputKey);
 }
示例#22
0
 public bool TryGetUnspentTxOutput(TxOutputKey txOutputKey, out TxOutput txOutput)
 {
     CheckTransaction();
     return unspentTxOutputs.Value.TryGetValue(txOutputKey, out txOutput);
 }
示例#23
0
        public bool TryAddUnspentTxOutput(TxOutputKey txOutputKey, TxOutput txOutput)
        {
            CheckWriteTransaction();

            try
            {
                unspentTxOutputs.Modify(x => x.Add(txOutputKey, txOutput));
                return true;
            }
            catch (ArgumentException)
            {
                return false;
            }
        }
示例#24
0
 public static void EncodeTxOutputKey(BinaryWriter writer, TxOutputKey txOutputKey)
 {
     writer.WriteUInt256(txOutputKey.TxHash);
     writer.WriteUInt32(txOutputKey.TxOutputIndex);
 }
示例#25
0
        private void TestTryAddGetRemoveUnspentTxOutput(ITestStorageProvider provider)
        {
            var random = new Random();

            var txOutput0Key = new TxOutputKey(UInt256.Zero, 0);
            var txOutput0 = new TxOutput(0, random.NextBytes(100).ToImmutableArray());
            var txOutput1Key = new TxOutputKey(UInt256.One, 1);
            var txOutput1 = new TxOutput(1, random.NextBytes(100).ToImmutableArray());

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

                // begin transaction
                chainStateCursor.BeginTransaction();

                // verify initial empty state
                TxOutput actualTxOutput0, actualTxOutput1;
                Assert.IsFalse(chainStateCursor.TryGetUnspentTxOutput(txOutput0Key, out actualTxOutput0));
                Assert.IsFalse(chainStateCursor.TryGetUnspentTxOutput(txOutput1Key, out actualTxOutput1));

                // add unspent tx 0
                Assert.IsTrue(chainStateCursor.TryAddUnspentTxOutput(txOutput0Key, txOutput0));

                // verify unspent txes
                Assert.IsTrue(chainStateCursor.TryGetUnspentTxOutput(txOutput0Key, out actualTxOutput0));
                Assert.AreEqual(txOutput0, actualTxOutput0);
                Assert.IsFalse(chainStateCursor.TryGetUnspentTxOutput(txOutput1Key, out actualTxOutput1));

                // add unspent tx 1
                Assert.IsTrue(chainStateCursor.TryAddUnspentTxOutput(txOutput1Key, txOutput1));

                // verify unspent txes
                Assert.IsTrue(chainStateCursor.TryGetUnspentTxOutput(txOutput0Key, out actualTxOutput0));
                Assert.AreEqual(txOutput0, actualTxOutput0);
                Assert.IsTrue(chainStateCursor.TryGetUnspentTxOutput(txOutput1Key, out actualTxOutput1));
                Assert.AreEqual(txOutput1, actualTxOutput1);

                // remove unspent tx 1
                Assert.IsTrue(chainStateCursor.TryRemoveUnspentTxOutput(txOutput1Key));

                // verify unspent txes
                Assert.IsTrue(chainStateCursor.TryGetUnspentTxOutput(txOutput0Key, out actualTxOutput0));
                Assert.AreEqual(txOutput0, actualTxOutput0);
                Assert.IsFalse(chainStateCursor.TryGetUnspentTxOutput(txOutput1Key, out actualTxOutput1));

                // remove unspent tx 0
                Assert.IsTrue(chainStateCursor.TryRemoveUnspentTxOutput(txOutput0Key));

                // verify unspent txes
                Assert.IsFalse(chainStateCursor.TryGetUnspentTxOutput(txOutput0Key, out actualTxOutput0));
                Assert.IsFalse(chainStateCursor.TryGetUnspentTxOutput(txOutput1Key, out actualTxOutput1));
            }
        }
示例#26
0
 public ImmutableDictionary<UInt256, UnconfirmedTx> GetTransactionsSpending(TxOutputKey txOutputKey)
 {
     using (var handle = this.cursorCache.TakeItem())
     {
         var cursor = handle.Item.Item;
         return cursor.GetTransactionsSpending(txOutputKey);
     }
 }
 public ImmutableDictionary<UInt256, UnconfirmedTx> GetTransactionsSpending(TxOutputKey prevTxOutputKey)
 {
     ImmutableDictionary<UInt256, UnconfirmedTx>.Builder unconfirmedTxes;
     if (unconfirmedTxesByPrevTxOutputKey.Value.TryGetValue(prevTxOutputKey, out unconfirmedTxes))
         return unconfirmedTxes.ToImmutable();
     else
         return ImmutableDictionary<UInt256, UnconfirmedTx>.Empty;
 }
示例#28
0
        public bool ContainsUnspentTxOutput(TxOutputKey txOutputKey)
        {
            CheckTransaction();

            using (SetSessionContext())
            {
                Api.JetSetCurrentIndex(this.jetSession, this.unspentTxOutputTableId, "IX_TxOutputKey");
                Api.MakeKey(this.jetSession, this.unspentTxOutputTableId, DbEncoder.EncodeTxOutputKey(txOutputKey), MakeKeyGrbit.NewKey);
                return Api.TrySeek(this.jetSession, this.unspentTxOutputTableId, SeekGrbit.SeekEQ);
            }
        }
示例#29
0
 public TxInput(TxOutputKey previousTxOutputKey, ImmutableArray<byte> scriptSignature, UInt32 sequence)
 {
     PreviousTxOutputKey = previousTxOutputKey;
     ScriptSignature = scriptSignature;
     Sequence = sequence;
 }
示例#30
0
        public bool TryAddUnspentTxOutput(TxOutputKey txOutputKey, TxOutput txOutput)
        {
            CheckWriteTransaction();

            using (SetSessionContext())
            {
                try
                {
                    using (var jetUpdate = this.jetSession.BeginUpdate(this.unspentTxOutputTableId, JET_prep.Insert))
                    {
                        Api.SetColumns(this.jetSession, this.unspentTxOutputTableId,
                            new BytesColumnValue { Columnid = this.txOutputKeyColumnId, Value = DbEncoder.EncodeTxOutputKey(txOutputKey) },
                            new BytesColumnValue { Columnid = this.txOutputBytesColumnId, Value = DataEncoder.EncodeTxOutput(txOutput) });

                        jetUpdate.Save();
                    }

                    return true;
                }
                catch (EsentKeyDuplicateException)
                {
                    return false;
                }
            }
        }
示例#31
0
 public TxInput(TxOutputKey prevTxOutputKey, ImmutableArray <byte> scriptSignature, UInt32 sequence)
 {
     PrevTxOutputKey = prevTxOutputKey;
     ScriptSignature = scriptSignature;
     Sequence        = sequence;
 }
示例#32
0
 public void RemoveUnspentTxOutput(TxOutputKey txOutputKey)
 {
     TryRemoveUnspentTxOutput(txOutputKey);
 }
示例#33
0
        public static bool CanSpend(this IChainState chainState, TxOutputKey txOutputKey)
        {
            if (txOutputKey == null)
                throw new ArgumentNullException("prevTxOutput");

            UnspentTx unspentTx;
            if (chainState.TryGetUnspentTx(txOutputKey.TxHash, out unspentTx))
            {
                var outputIndex = unchecked((int)txOutputKey.TxOutputIndex);

                if (outputIndex < 0 || outputIndex >= unspentTx.OutputStates.Length)
                    return false;

                return unspentTx.OutputStates[outputIndex] == OutputState.Unspent;
            }
            else
            {
                return false;
            }
        }
示例#34
0
 public bool TryGetUnspentTxOutput(TxOutputKey txOutputKey, out TxOutput txOutput)
 {
     using (var handle = this.cursorCache.TakeItem())
     {
         var cursor = handle.Item.Item;
         return cursor.TryGetUnspentTxOutput(txOutputKey, out txOutput);
     }
 }
示例#35
0
 public TxInput(TxOutputKey previousTxOutputKey, ImmutableArray <byte> scriptSignature, UInt32 sequence)
 {
     this._previousTxOutputKey = previousTxOutputKey;
     this._scriptSignature     = scriptSignature;
     this._sequence            = sequence;
 }
示例#36
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);
        }
示例#37
0
 public bool TryRemoveUnspentTxOutput(TxOutputKey txOutputKey)
 {
     CheckWriteTransaction();
     return unspentTxOutputs.TryModify(x => x.Remove(txOutputKey));
 }