Beispiel #1
0
        public NoneCoinbaseTransactionBuilder Spend(BcBaseTransaction transaction, UInt32 index, IEnumerable <byte> signatureScript, uint sequence = 0xffffffff)
        {
            if (transaction == null)
            {
                throw new ArgumentNullException(nameof(transaction));
            }

            if (index < 0)
            {
                // TODO : THROW
            }

            if (transaction.TransactionOut.Count() > index)
            {
                // TODO : THROW
            }

            if (signatureScript == null)
            {
                throw new ArgumentNullException(nameof(signatureScript));
            }

            var txId = transaction.GetTxId();

            return(Spend(txId, index, signatureScript, sequence));
        }
Beispiel #2
0
        public void WhenGetUnspentTransactionsTwoBlocks()
        {
            RemoveBlockChain();
            var serviceProvider     = BuildServiceProvider();
            var blockChainFactory   = serviceProvider.GetService <IBlockChainFactory>();
            var blockChain          = blockChainFactory.Build(_network);
            var genesisBlock        = blockChain.GetCurrentBlock();
            var firstTransaction    = genesisBlock.Transactions.First() as BcBaseTransaction;
            var firstTransactionOut = firstTransaction.TransactionOut.First();

            var genesisKey = KeyStore.GetGenesisKey();
            var genesisAdr = new BlockChainAddress(_scriptTypes, _network, genesisKey); // Create block chain address.
            var destinationBlockChainAddress = GenerateBlockChainAddress();
            var minerBlockChainAddress       = GenerateBlockChainAddress();

            var signature     = genesisKey.GetSignature(); // Create the script.
            var scriptBuilder = new ScriptBuilder();
            var genesisScript = scriptBuilder
                                .New()
                                .AddToStack(signature)
                                .AddToStack(genesisKey.GetPublicKey())
                                .Build();
            var destinationScript = Script.CreateP2PKHScript(destinationBlockChainAddress.PublicKeyHash);
            var minerScript       = Script.CreateP2PKHScript(minerBlockChainAddress.PublicKeyHash);
            var genesisScriptDest = Script.CreateP2PKHScript(genesisKey.GetPublicKeyHashed());

            var transactionBuilder  = new TransactionBuilder();
            var coinBaseTransaction = transactionBuilder // Add COIN-BASE TRANSACTION.
                                      .NewCoinbaseTransaction()
                                      .SetBlockNumber(1)
                                      .AddOutput(1, minerScript)
                                      .Build();
            var noneCoinBaseTransaction = transactionBuilder // ADD GENESIS (10 BTC) => DESTINATION TRANSACTION.
                                          .NewNoneCoinbaseTransaction()
                                          .Spend(firstTransaction, 0, genesisScript.Serialize())
                                          .AddOutput(10, destinationScript)
                                          .Build();
            var otherCoinBaseTransaction = transactionBuilder
                                           .NewNoneCoinbaseTransaction()
                                           .Spend(firstTransaction, 0, genesisScript.Serialize())
                                           .AddOutput(39, genesisScriptDest)
                                           .Build();

            var nonce = NonceHelper.GetNonceUInt32(); // CREATE A BLOCK.
            var block = new Block(genesisBlock.GetHashHeader(), Constants.DEFAULT_NBITS, nonce);

            block.Transactions.Add(coinBaseTransaction);
            block.Transactions.Add(noneCoinBaseTransaction);
            block.Transactions.Add(otherCoinBaseTransaction);
            var a = noneCoinBaseTransaction.Serialize().ToArray();
            var b = BcBaseTransaction.Deserialize(a);

            block.UpdateMerkleRoot();
            blockChain.AddBlock(block);
            var unspentTransactions = blockChain.GetUnspentTransactions();

            Assert.IsNotNull(unspentTransactions);
            Assert.IsTrue(unspentTransactions.Count() == 3);
            Assert.IsTrue(unspentTransactions.Sum(t => t.Value) == 50);
        }
Beispiel #3
0
        public void Broadcast(BcBaseTransaction transaction)
        {
            if (transaction == null)
            {
                throw new ArgumentNullException(nameof(transaction));
            }

            _p2pNetworkConnector.Broadcast(transaction);
        }
 public void WhenBuildNoneCoinbaseTransaction()
 {
     var ba          = BuildBlockChainAddress();
     var builder     = new TransactionBuilder();
     var transaction = builder.NewNoneCoinbaseTransaction()
                       .AddOutput(20, Script.CreateP2PKHScript(ba.PublicKeyHash))
                       .Build();
     var serializedTransaction   = transaction.Serialize();
     var deserializedTransaction = BcBaseTransaction.Deserialize(serializedTransaction);
 }
        public TransactionOut GetTransactionIn(BcBaseTransaction transaction, IEnumerable <BlockChainAddress> bcAddrs, Networks network)
        {
            if (transaction == null)
            {
                throw new ArgumentNullException(nameof(transaction));
            }

            if (bcAddrs == null)
            {
                throw new ArgumentNullException(nameof(bcAddrs));
            }

            var publicKeyHashes = bcAddrs.Select(bcAddr => bcAddr.PublicKeyHash);
            var blockChain      = _blockChainStore.GetBlockChain();
            var memPool         = MemoryPool.Instance();

            foreach (var txIn in transaction.TransactionIn)
            {
                var nCbtxIn = txIn as TransactionInNoneCoinbase;
                if (nCbtxIn == null || nCbtxIn.Outpoint == null)
                {
                    continue;
                }

                var               previousTx          = blockChain.GetTransaction(nCbtxIn.Outpoint.Hash);
                TransactionOut    previousTxOut       = null;
                BcBaseTransaction monetaryTransaction = null;
                if (previousTx == null || (monetaryTransaction = (previousTx as BcBaseTransaction)) == null || monetaryTransaction.TransactionOut == null)
                {
                    previousTxOut = memPool.GetUnspentTransaction(nCbtxIn.Outpoint.Hash, nCbtxIn.Outpoint.Index);
                    if (previousTxOut == null || (monetaryTransaction = (previousTx as BcBaseTransaction)) == null)
                    {
                        continue;
                    }
                }
                else
                {
                    previousTxOut = monetaryTransaction.TransactionOut.ElementAtOrDefault((int)nCbtxIn.Outpoint.Index);
                }

                if (previousTxOut == null || previousTxOut.Script == null || publicKeyHashes.All(publicKeyHash => !previousTxOut.Script.ContainsPublicKeyHash(publicKeyHash)))
                {
                    continue;
                }

                return(previousTxOut);
            }

            return(null);
        }
Beispiel #6
0
        public MemoryPoolRecord GetUnspentMemoryRecord(IEnumerable <byte> txId, uint index)
        {
            if (index < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }

            var referencedTx = GetUnspentMemoryRecord(txId);
            BcBaseTransaction transaction = null;

            if (referencedTx == null || (transaction = referencedTx.Transaction as BcBaseTransaction) == null || index >= transaction.TransactionOut.Count())
            {
                return(null);
            }

            return(referencedTx);
        }
        public long CalculateBalance(BcBaseTransaction transaction, IEnumerable <BlockChainAddress> bcAddrs, Networks network)
        {
            if (transaction == null)
            {
                throw new ArgumentNullException(nameof(transaction));
            }

            if (bcAddrs == null)
            {
                throw new ArgumentNullException(nameof(bcAddrs));
            }

            var            txIn            = GetTransactionIn(transaction, bcAddrs, network) as TransactionOut;
            var            publicKeyHashes = bcAddrs.Select(bcAddr => bcAddr.PublicKeyHash);
            TransactionOut txOut           = null;

            foreach (var transactionOut in transaction.TransactionOut)
            {
                var script = transactionOut.Script;
                if (publicKeyHashes.Any(publicKeyHash => script.ContainsPublicKeyHash(publicKeyHash)))
                {
                    txOut = transactionOut as TransactionOut;
                }
            }

            var noneCoinBaseTransaction = transaction as NoneCoinbaseTransaction;

            if (noneCoinBaseTransaction != null)
            {
                if (txOut == null)
                {
                    return(0);
                }

                return(-(txIn.Value - txOut.Value));
            }

            if (txOut == null)
            {
                return(0);
            }

            return(txOut.Value);
        }
        public TransactionOut GetTransactionIn(BcBaseTransaction transaction, Networks network)
        {
            if (transaction == null)
            {
                throw new ArgumentNullException(nameof(transaction));
            }

            var blockChain = _blockChainStore.GetBlockChain();

            foreach (var txIn in transaction.TransactionIn)
            {
                var nCbtxIn = txIn as TransactionInNoneCoinbase;
                if (nCbtxIn == null || nCbtxIn.Outpoint == null)
                {
                    continue;
                }

                var               previousTx          = blockChain.GetTransaction(nCbtxIn.Outpoint.Hash);
                TransactionOut    previousTxOut       = null;
                BcBaseTransaction monetaryTransaction = null;
                if (previousTx == null || (monetaryTransaction = (previousTx as BcBaseTransaction)) == null || monetaryTransaction.TransactionOut == null)
                {
                    previousTxOut = MemoryPool.Instance().GetUnspentTransaction(nCbtxIn.Outpoint.Hash, nCbtxIn.Outpoint.Index);
                    if (previousTxOut == null || (monetaryTransaction = (previousTx as BcBaseTransaction)) == null)
                    {
                        continue;
                    }
                }
                else
                {
                    previousTxOut = monetaryTransaction.TransactionOut.ElementAtOrDefault((int)nCbtxIn.Outpoint.Index);
                    if (previousTxOut == null || previousTxOut.Script == null)
                    {
                        continue;
                    }
                }


                return(previousTxOut);
            }

            return(null);
        }
        public long GetFee(BcBaseTransaction transaction, Networks network)
        {
            if (transaction == null)
            {
                throw new ArgumentNullException(nameof(transaction));
            }

            var  outputValue = transaction.TransactionOut.Where(t => t is TransactionOut).Sum(t => (t as TransactionOut).Value); // TRANSACTION FEE + REWARD.
            long inputValue  = 0;
            var  txIn        = GetTransactionIn(transaction, network) as TransactionOut;

            if (txIn != null)
            {
                inputValue = txIn.Value;
            }

            var leftValue = inputValue - outputValue;
            var reward    = GetReward(transaction);
            var result    = reward + leftValue;

            return(result);
        }
        public void Check(BcBaseTransaction transaction)
        {
            if (transaction == null)
            {
                throw new ArgumentNullException(nameof(transaction));
            }

            var blockChain            = _blockChainStore.GetBlockChain();
            var memoryPool            = MemoryPool.Instance();
            var isCoinBaseTransaction = transaction is CoinbaseTransaction; // https://bitcoin.org/en/developer-guide#block-chain-overview

            if (!isCoinBaseTransaction && (transaction.TransactionIn == null || !transaction.TransactionIn.Any()))
            {
                throw new ValidationException(ErrorCodes.NoTransactionIn);
            }

            if (!isCoinBaseTransaction)
            {
                long totalOutput = 0;
                foreach (var txIn in transaction.TransactionIn)
                {
                    var noneCoinBaseTxIn = txIn as TransactionInNoneCoinbase; // Check TRANSACTION EXISTS IN BLOCK CHAIN & MEMORY POOL.
                    var previousTxId     = noneCoinBaseTxIn.Outpoint.Hash;
                    var previousIndex    = noneCoinBaseTxIn.Outpoint.Index;

                    /*
                     * if (memoryPool.ContainsTransactions(previousTxId, previousIndex))
                     * {
                     *  throw new ValidationException(ErrorCodes.AlreadySpentInMemoryPool);
                     * }
                     */

                    var previousTxOut = blockChain.GetUnspentTransaction(previousTxId, previousIndex);
                    if (previousTxOut == null)
                    {
                        var r = memoryPool.GetUnspentTransaction(previousTxId, previousIndex) as TransactionOut;
                        if (r == null)
                        {
                            throw new ValidationException(ErrorCodes.ReferencedTransactionNotValid);
                        }

                        previousTxOut = new UTXO
                        {
                            Index  = (int)previousIndex,
                            Script = r.Script,
                            TxId   = transaction.GetTxId(),
                            Value  = r.Value
                        };
                    }

                    var sigScript = Script.Deserialize(noneCoinBaseTxIn.SignatureScript);  // Check SCRIPT.
                    var pkScript  = previousTxOut.Script;
                    if (!_scriptInterpreter.Check(sigScript, pkScript))
                    {
                        throw new ValidationException(ErrorCodes.TransactionSignatureNotCorrect);
                    }

                    totalOutput += previousTxOut.Value;
                }

                var sumOutput = transaction.TransactionOut.Where(t => t is TransactionOut).Sum(t => ((TransactionOut)t).Value);
                if (sumOutput > totalOutput)
                {
                    throw new ValidationException(ErrorCodes.TransactionOutputExceedInput);
                }
            }
        }
Beispiel #11
0
 public TransactionBuilder(BcBaseTransaction transaction)
 {
     Transaction = transaction;
 }