Пример #1
0
        private JObject GetUnconfirmedBalance(string id, JObject response)
        {
            var transactions = MemoryPool.Instance().GetTransactions();
            var wallet       = WalletStore.Instance().GetAuthenticatedWallet();

            if (wallet == null)
            {
                return(CreateErrorResponse(id, (int)RpcErrorCodes.RPC_WALLET_NOT_FOUND, "No authenticated wallet"));
            }

            long unconfirmedBalance = 0;

            if (wallet.Addresses != null)
            {
                var bcAddrs = wallet.Addresses.Select(addr => BlockChainAddress.Deserialize(addr.Hash));
                foreach (var memTx in transactions)
                {
                    var mBcTx = memTx.Transaction as BcBaseTransaction;
                    if (mBcTx == null)
                    {
                        continue;
                    }

                    var balance = _transactionHelper.CalculateBalance(mBcTx, bcAddrs, _network);
                    unconfirmedBalance += balance;
                }
            }

            response["result"] = unconfirmedBalance;
            return(response);
        }
Пример #2
0
        private Message Execute(InventoryMessage msg)
        {
            var blockChain  = _blockChainStore.GetBlockChain();
            var inventories = new List <Inventory>();

            if (msg.Inventories.Any())
            {
                foreach (var inventory in msg.Inventories)
                {
                    bool addIntoInventory = false;
                    switch (inventory.Type)
                    {
                    case InventoryTypes.MSG_TX:
                        addIntoInventory = !MemoryPool.Instance().GetTransactions().Any(t => t.Transaction.GetTxId() == inventory.Hash);
                        break;

                    case InventoryTypes.MSG_BLOCK:
                        addIntoInventory = !blockChain.ContainsBlock(inventory.Hash);
                        break;
                    }

                    if (addIntoInventory)
                    {
                        inventories.Add(new Inventory(inventory.Type, inventory.Hash));
                    }
                }
            }

            if (inventories.Any())
            {
                return(new GetDataMessage(inventories, msg.MessageHeader.Network));
            }

            return(null);
        }
Пример #3
0
        private JObject SendRawTransaction(IEnumerable <string> parameters, JObject response, string id)
        {
            var blockChain = _blockChainStore.GetBlockChain();

            if (parameters == null || !parameters.Any())
            {
                return(CreateErrorResponse(id, (int)RpcErrorCodes.RPC_INVALID_PARAMS, "The transaction is missing"));
            }

            var txPayload     = parameters.First().FromHexString();
            var allowHighFees = false;

            if (parameters.Count() >= 2)
            {
                if (bool.TryParse(parameters.ElementAt(1), out allowHighFees))
                {
                }
            }

            var kvp = BaseTransaction.Deserialize(txPayload);

            try
            {
                var tx = kvp.Key;
                _transactionValidator.Check(tx);
                MemoryPool.Instance().AddTransaction(tx, blockChain.GetCurrentBlockHeight());
                P2PConnectorEventStore.Instance().Broadcast(tx);
                response["result"] = tx.GetTxId().ToHexString();
                return(response);
            }
            catch (ValidationException ex)
            {
                return(CreateErrorResponse(id, (int)RpcErrorCodes.RPC_VERIFY_ERROR, ex.Message));
            }
        }
Пример #4
0
        private JObject GetRawMemPool(IEnumerable <string> parameters, JObject response)
        {
            var memPool       = MemoryPool.Instance();
            var transactions  = memPool.GetTransactions();
            var verboseOutput = false;

            if (parameters.Any())
            {
                var parameter = parameters.First();
                int f         = 0;
                if (int.TryParse(parameter, out f))
                {
                    verboseOutput = f == 0;
                }
            }

            if (!verboseOutput)
            {
                response["result"] = new JArray(transactions.Select(t => t.Transaction.GetTxId()));
                return(response);
            }

            JArray jTxs = new JArray();

            if (transactions != null)
            {
                foreach (var transaction in transactions.Select(t => t))
                {
                    var jTxContentObj = new JObject();
                    var depends       = new List <string>();
                    transaction.GetDepends(depends);
                    var bcTx       = transaction.Transaction as BcBaseTransaction;
                    var arrDepends = JArray.FromObject(depends);
                    jTxContentObj.Add("size", transaction.Transaction.Serialize().Count());
                    jTxContentObj.Add("fee", bcTx == null ? 0 : _transactionHelper.GetFee(bcTx, _network));
                    jTxContentObj.Add("modifiedfee", bcTx == null ? 0 : _transactionHelper.GetFee(bcTx, _network));
                    jTxContentObj.Add("time", transaction.InsertTime.ToUnixTime());
                    jTxContentObj.Add("height", transaction.BlockHeight);
                    jTxContentObj.Add("startingpriority", null);
                    jTxContentObj.Add("currentpriority", null);
                    jTxContentObj.Add("descendantcount", memPool.CountDescendants(transaction)); // Nombre of descendants.
                    jTxContentObj.Add("descendantsize", null);
                    jTxContentObj.Add("descendantfees", null);
                    jTxContentObj.Add("ancestorcount", memPool.CountAncestors(transaction));
                    jTxContentObj.Add("ancestorsize", null);
                    jTxContentObj.Add("ancestorfees", null);
                    jTxContentObj.Add("depends", arrDepends);
                    var rec = new JObject();
                    rec.Add(transaction.Transaction.GetTxId().ToHexString(), jTxContentObj);
                    jTxs.Add(rec);
                }
            }

            response["result"] = jTxs;
            return(response);
        }
        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);
        }
Пример #6
0
        private JObject GetBlockTemplate(JObject response)
        {
            var transactions = MemoryPool.Instance().GetTransactions();
            var blockChain   = _blockChainStore.GetBlockChain();

            if (transactions == null || !transactions.Any())
            {
                response["result"] = null;
                return(response);
            }

            var currentBlock       = blockChain.GetCurrentBlock();
            var height             = blockChain.GetCurrentBlockHeight();
            var previousBlockHash  = currentBlock.GetHashHeader().ToHexString();
            var transactionBuilder = new TransactionBuilder();
            var nonce = BitConverter.GetBytes(NonceHelper.GetNonceUInt64());
            var value = transactions.Sum(t => _transactionHelper.GetFee(t.Transaction, _network));
            var coinBaseTransaction = transactionBuilder.NewCoinbaseTransaction()
                                      .SetInput((uint)height + 1, nonce)
                                      .AddOutput(value, Script.CreateCorrectScript())
                                      .Build();
            var result        = new JObject();
            var jTransactions = new JArray();

            foreach (var transaction in transactions)
            {
                jTransactions.Add(transaction.Transaction.Serialize().ToHexString());
            }


            var currentTime    = DateTime.UtcNow.ToUnixTimeUInt32();
            var coinBaseTxnObj = new JObject();

            coinBaseTxnObj.Add("data", coinBaseTransaction.Serialize().ToHexString());
            result.Add("coinbasetxn", coinBaseTxnObj);
            result.Add("expires", "120");
            result.Add("longpollid", "");
            result.Add("height", blockChain.GetCurrentBlockHeight() + 1);
            result.Add("curtime", currentTime);
            result.Add("previousblockhash", previousBlockHash);
            result.Add("transactions", jTransactions);
            result.Add("version", BlockHeader.CURRENT_VERSION);
            result.Add("target", TargetHelper.GetTarget(Constants.DEFAULT_NBITS).ToHexString());
            result.Add("bits", Constants.DEFAULT_NBITS);
            response["result"] = result;
            return(response);
        }
Пример #7
0
        private void AddTransaction(BaseTransaction transaction)
        {
            if (transaction == null)
            {
                return;
            }

            var instance     = MemoryPool.Instance();
            var transactions = instance.GetTransactions();

            if (transactions.Any(t => t.Transaction.GetTxId().SequenceEqual(transaction.GetTxId())))
            {
                return;
            }

            _transactionValidator.Check(transaction);
            instance.AddTransaction(transaction, _blockChainStore.GetBlockChain().GetCurrentBlockHeight());
        }
Пример #8
0
        private IEnumerable <Message> Execute(GetDataMessage msg)
        {
            var blockChain        = _blockChainStore.GetBlockChain();
            var messages          = new List <Message>();
            var notFoundInventory = new List <Inventory>();

            if (msg.Inventories.Any())
            {
                foreach (var inventory in msg.Inventories)
                {
                    switch (inventory.Type)
                    {
                    case InventoryTypes.MSG_TX:
                        var tx = MemoryPool.Instance().GetTransactions().FirstOrDefault(t => t.Transaction.GetTxId().SequenceEqual(inventory.Hash));
                        if (tx != null)
                        {
                            messages.Add(new TransactionMessage(tx.Transaction, msg.MessageHeader.Network));
                            continue;
                        }
                        break;

                    case InventoryTypes.MSG_BLOCK:
                        var block = blockChain.GetBlock(inventory.Hash);
                        if (block != null)
                        {
                            messages.Add(new BlockMessage(block, msg.MessageHeader.Network));
                            continue;
                        }
                        break;
                    }

                    notFoundInventory.Add(inventory);
                }
            }


            if (notFoundInventory.Any())
            {
                var notFoundMessage = new NotFoundMessage(notFoundInventory, msg.MessageHeader.Network);
                messages.Add(notFoundMessage);
            }

            return(messages);
        }
        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);
        }
Пример #10
0
        private JObject SubmitBlock(IEnumerable <string> parameters, string id, JObject response)
        {
            var blockChain    = _blockChainStore.GetBlockChain();
            var smartContract = _smartContractStore.GetSmartContracts();

            if (!parameters.Any())
            {
                return(CreateErrorResponse(id, (int)RpcErrorCodes.RPC_INVALID_PARAMS, "The block is missing"));
            }

            var payload = parameters.First().FromHexString();
            var block   = Block.Deserialize(payload);

            try
            {
                _blockValidator.Check(block);
                if (block.Transactions != null)
                {
                    MemoryPool.Instance().Remove(block.Transactions.Select(tx => tx.GetTxId()));
                }

                smartContract.AddBlock(block);
                smartContract.Commit();
                blockChain.AddBlock(block);
                P2PConnectorEventStore.Instance().Broadcast(block);
                response["result"] = null;
                return(response);
            }
            catch (ValidationException ex)
            {
                return(CreateErrorResponse(id, (int)RpcErrorCodes.RPC_VERIFY_ERROR, ex.Message));
            }
            catch (Exception ex)
            {
                return(CreateErrorResponse(id, (int)RpcErrorCodes.RPC_INVALID_REQUEST, ex.Message));
            }
        }
Пример #11
0
        private JObject SendSmartContractTransaction(IEnumerable <string> parameters, string id, JObject response)
        {
            var blockChain = _blockChainStore.GetBlockChain();

            if (parameters == null || !parameters.Any())
            {
                return(CreateErrorResponse(id, (int)RpcErrorCodes.RPC_INVALID_PARAMS, "The from & data are not specified"));
            }

            if (parameters.Count() < 2)
            {
                return(CreateErrorResponse(id, (int)RpcErrorCodes.RPC_INVALID_PARAMS, "The data is not specified"));
            }

            IEnumerable <byte> fromPayload = null;
            IEnumerable <byte> dataPayload = null;
            IEnumerable <byte> toPayload   = null;
            double             gas         = 0,
                               gasPrice = 0,
                               scValue  = 0;
            int scNonce                 = 0;

            try
            {
                fromPayload = parameters.First().FromHexString();
            }
            catch (Exception)
            {
                return(CreateErrorResponse(id, (int)RpcErrorCodes.RPC_INVALID_PARAMS, "The from cannot be decoded"));
            }

            try
            {
                dataPayload = parameters.ElementAt(1).FromHexString();
            }
            catch (Exception)
            {
                return(CreateErrorResponse(id, (int)RpcErrorCodes.RPC_INVALID_PARAMS, "The data cannot be decoded"));
            }

            if (parameters.Count() >= 3)
            {
                try
                {
                    toPayload = parameters.ElementAt(2).FromHexString();
                }
                catch (Exception)
                {
                    return(CreateErrorResponse(id, (int)RpcErrorCodes.RPC_INVALID_PARAMS, "The to cannot be decoded"));
                }
            }

            if (parameters.Count() >= 4)
            {
                try
                {
                    gas = double.Parse(parameters.ElementAt(3));
                }
                catch (Exception) { }
            }

            if (parameters.Count() >= 5)
            {
                try
                {
                    gasPrice = double.Parse(parameters.ElementAt(4));
                }
                catch (Exception) { }
            }

            if (parameters.Count() >= 6)
            {
                try
                {
                    scValue = double.Parse(parameters.ElementAt(5));
                }
                catch (Exception) { }
            }

            if (parameters.Count() >= 7)
            {
                try
                {
                    scNonce = int.Parse(parameters.ElementAt(6));
                }
                catch (Exception) { }
            }

            var smartContractTx = new SmartContractTransaction
            {
                Data     = dataPayload,
                From     = fromPayload,
                To       = toPayload,
                Gas      = gas,
                GasPrice = gasPrice,
                Nonce    = scNonce,
                Value    = scValue
            };

            try
            {
                _transactionValidator.Check(smartContractTx);
                MemoryPool.Instance().AddTransaction(smartContractTx, blockChain.GetCurrentBlockHeight());
                P2PConnectorEventStore.Instance().Broadcast(smartContractTx);
                response["result"] = smartContractTx.GetTxId().ToHexString();
                return(response);
            }
            catch (ValidationException ex)
            {
                return(CreateErrorResponse(id, (int)RpcErrorCodes.RPC_VERIFY_ERROR, ex.Message));
            }
        }
Пример #12
0
        private JObject ListUnspent(IEnumerable <string> parameters, JObject response, string id)
        {
            var transactions           = MemoryPool.Instance().GetTransactions();
            var blockChain             = _blockChainStore.GetBlockChain();
            var wallet                 = WalletStore.Instance().GetAuthenticatedWallet();
            int confirmationScore      = 1;
            var maxConfirmations       = 9999999;
            IEnumerable <string> addrs = new List <string>();

            if (parameters.Any())
            {
                if (int.TryParse(parameters.First().ToString(), out confirmationScore))
                {
                }
                if (parameters.Count() >= 2 && int.TryParse(parameters.ElementAt(1), out maxConfirmations))
                {
                }
                if (parameters.Count() >= 3)
                {
                    var jArr = JArray.Parse(parameters.ElementAt(2));
                    if (jArr != null)
                    {
                        addrs = jArr.Select(j => j.ToString());
                    }
                }
            }

            if (wallet == null)
            {
                return(CreateErrorResponse(id, (int)RpcErrorCodes.RPC_WALLET_NOT_FOUND, "No authenticated wallet"));
            }

            var res = new JArray();

            if (addrs == null || !addrs.Any())
            {
                addrs = wallet.Addresses.Select(a => a.Hash);
            }

            var walletBlockChainAddrs = addrs.Select(a => new { bca = BlockChainAddress.Deserialize(a), hash = a });

            if (maxConfirmations >= 0) // CONFIRMATION 0.
            {
                if (transactions != null && transactions.Any())
                {
                    foreach (var unconfirmedTransaction in transactions)
                    {
                        if (unconfirmedTransaction.Transaction != null)
                        {
                            var lBcTx = unconfirmedTransaction.Transaction as BcBaseTransaction;
                            if (lBcTx == null)
                            {
                                continue;
                            }

                            foreach (var unconfirmedUTXO in lBcTx.TransactionOut.Where(t => t is TransactionOut).Select(t => t as TransactionOut))
                            {
                                var bcAdr = walletBlockChainAddrs.FirstOrDefault(wph => unconfirmedUTXO.Script.ContainsPublicKeyHash(wph.bca.PublicKeyHash));
                                if (bcAdr == null)
                                {
                                    continue;
                                }

                                var record = new JObject();
                                record.Add("txid", unconfirmedTransaction.Transaction.GetTxId().ToHexString());
                                record.Add("vout", lBcTx.TransactionOut.IndexOf(unconfirmedUTXO));
                                record.Add("amount", unconfirmedUTXO.Value);
                                record.Add("address", bcAdr.hash);
                                record.Add("scriptPubKey", unconfirmedUTXO.Script.Serialize().ToHexString());
                                record.Add("confirmations", 0);
                                record.Add("spendable", true);
                                record.Add("solvable", true);
                                res.Add(record);
                            }
                        }
                    }
                }
            }

            if (maxConfirmations >= 1)  // CONFIRMATION 1.
            {
                var utxos = blockChain.GetUnspentTransactions();
                foreach (var utxo in utxos)
                {
                    var bcAdr = walletBlockChainAddrs.FirstOrDefault(wph => utxo.Script.ContainsPublicKeyHash(wph.bca.PublicKeyHash));
                    if (bcAdr == null)
                    {
                        continue;
                    }

                    var record = new JObject();
                    record.Add("txid", utxo.TxId.ToHexString());
                    record.Add("vout", utxo.Index);
                    record.Add("address", bcAdr.hash);
                    record.Add("scriptPubKey", utxo.Script.Serialize().ToHexString());
                    record.Add("amount", utxo.Value);
                    record.Add("confirmations", 1);
                    record.Add("spendable", true);
                    record.Add("solvable", true);
                    res.Add(record);
                }
            }

            response["result"] = res;
            return(response);
        }
        public void WhenCountAncestors()
        {
            var scriptBuilder     = new ScriptBuilder();
            var firstClient       = BuildBlockChainAddress();
            var secondClient      = BuildBlockChainAddress();
            var thirdClient       = BuildBlockChainAddress();
            var fourthClient      = BuildBlockChainAddress();
            var fifthClient       = BuildBlockChainAddress();
            var sixClient         = BuildBlockChainAddress();
            var sevenClient       = BuildBlockChainAddress();
            var firstClientScript = scriptBuilder
                                    .New()
                                    .AddToStack(firstClient.Value.GetSignature())
                                    .AddToStack(firstClient.Value.GetPublicKey())
                                    .Build();
            var fifthClientScript = scriptBuilder
                                    .New()
                                    .AddToStack(fifthClient.Value.GetSignature())
                                    .AddToStack(fifthClient.Value.GetPublicKey())
                                    .Build();
            var builder          = new TransactionBuilder();
            var firstTransaction = builder.NewCoinbaseTransaction()
                                   .AddOutput(20, Script.CreateP2PKHScript(firstClient.Key.PublicKeyHash))
                                   .AddOutput(10, Script.CreateP2PKHScript(secondClient.Key.PublicKeyHash))
                                   .Build();
            var secondTransaction = builder.NewNoneCoinbaseTransaction()
                                    .Spend(firstTransaction, 0, firstClientScript.Serialize())
                                    .AddOutput(20, Script.CreateP2PKHScript(thirdClient.Key.PublicKeyHash))
                                    .Build();
            var thirdTransaction = builder.NewNoneCoinbaseTransaction()
                                   .Spend(firstTransaction, 1, firstClientScript.Serialize())
                                   .AddOutput(5, Script.CreateP2PKHScript(fourthClient.Key.PublicKeyHash))
                                   .AddOutput(5, Script.CreateP2PKHScript(fifthClient.Key.PublicKeyHash))
                                   .Build();
            var fourthTransaction = builder.NewNoneCoinbaseTransaction()
                                    .Spend(thirdTransaction, 1, fifthClientScript.Serialize())
                                    .AddOutput(2, Script.CreateP2PKHScript(sixClient.Key.PublicKeyHash))
                                    .AddOutput(2, Script.CreateP2PKHScript(sevenClient.Key.PublicKeyHash))
                                    .Build();


            var memPool = MemoryPool.Instance();

            memPool.AddTransaction(firstTransaction, 1);
            memPool.AddTransaction(secondTransaction, 1);
            memPool.AddTransaction(thirdTransaction, 1);
            memPool.AddTransaction(fourthTransaction, 1);

            var firstUnspentTx      = memPool.GetUnspentMemoryRecord(firstTransaction.GetTxId());
            var secondUnspentTx     = memPool.GetUnspentMemoryRecord(secondTransaction.GetTxId());
            var thirdUnspentTx      = memPool.GetUnspentMemoryRecord(thirdTransaction.GetTxId());
            var fourthUnspentTx     = memPool.GetUnspentMemoryRecord(fourthTransaction.GetTxId());
            var firstNbDescendants  = memPool.CountAncestors(firstUnspentTx);
            var secondNbDescendants = memPool.CountAncestors(secondUnspentTx);
            var thirdNbDescendants  = memPool.CountAncestors(thirdUnspentTx);
            var fourthNbDescendants = memPool.CountAncestors(fourthUnspentTx);

            Assert.IsTrue(firstNbDescendants == 1);
            Assert.IsTrue(secondNbDescendants == 2);
            Assert.IsTrue(thirdNbDescendants == 2);
            Assert.IsTrue(fourthNbDescendants == 3);
        }
        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);
                }
            }
        }
Пример #15
0
        public Message Receive(Message message, PeerConnector peer, P2PNetworkConnector p2pNetworkConnector)
        {
            var blockChain    = _blockChainStore.GetBlockChain();
            var smartContract = _smartContractStore.GetSmartContracts();

            if (message.GetCommandName() == Constants.MessageNames.Version) // RETURNS VERSION.
            {
                var msg              = message as VersionMessage;
                var instance         = PeersStore.Instance();
                var transmittingNode = instance.GetMyIpAddress();
                var receivingNode    = msg.TransmittingNode;
                return(new VersionMessage(transmittingNode, receivingNode, msg.Nonce, msg.UserAgent, msg.StartHeight, msg.Relay, msg.MessageHeader.Network));
            }

            if (message.GetCommandName() == Constants.MessageNames.Ping) // RETURNS PONG.
            {
                var msg  = message as PingMessage;
                var pong = new PongMessage(msg.Nonce, msg.MessageHeader.Network);
                return(pong);
            }

            if (message.GetCommandName() == Constants.MessageNames.Verack) // RETURNS VERACK MESSAGE.
            {
                var msg = message as VerackMessage;
                return(new VerackMessage(msg.MessageHeader.Network));
            }

            if (message.GetCommandName() == Constants.MessageNames.Addr) // RETURNS THE ADDRS.
            {
                var msg = message as AddrMessage;
                if (msg.IpAddresses != null)
                {
                    foreach (var ipAddress in msg.IpAddresses)
                    {
                        PeerEventStore.Instance().NewPeer(ipAddress);
                    }
                }

                return(null);
            }

            if (message.GetCommandName() == Constants.MessageNames.GetAddr) // RETURNS THE ADDRS.
            {
                var msg      = message as GetAddressMessage;
                var ipAdrLst = _peersStorage.GetAll();
                var response = new AddrMessage(new CompactSize {
                    Size = (ulong)ipAdrLst.Count()
                }, msg.MessageHeader.Network);
                foreach (var ipAdr in ipAdrLst)
                {
                    response.IpAddresses.Add(ipAdr);
                }

                return(response);
            }

            if (message.GetCommandName() == Constants.MessageNames.MemPool) // RETURNS THE INVENTORY.
            {
                var msg         = message as MemPoolMessage;
                var memoryPool  = MemoryPool.Instance();
                var txIds       = memoryPool.GetTransactions().Select(t => t.Transaction.GetTxId());
                var inventories = new List <Inventory>();
                foreach (var txId in txIds)
                {
                    inventories.Add(new Inventory(InventoryTypes.MSG_TX, txId));
                }

                return(new InventoryMessage(inventories, msg.MessageHeader.Network));
            }

            if (message.GetCommandName() == Constants.MessageNames.GetData) // RETURNS ALL THE DATA TO THE PEER.
            {
                var msg      = message as GetDataMessage;
                var messages = Execute(msg);
                if (messages != null)
                {
                    foreach (var m in messages)
                    {
                        peer.Execute(m.Serialize());
                    }
                }

                return(null);
            }

            if (message.GetCommandName() == Constants.MessageNames.Transaction) // ADD TRANSACTION INTO MEMORY POOL & BROADCAST IT.
            {
                var msg = message as TransactionMessage;
                AddTransaction(msg.Transaction);
                MemoryPool.Instance().Remove(msg.Transaction);
                p2pNetworkConnector.Broadcast(msg.Transaction, msg.MessageHeader.Ipv6);
                return(null);
            }

            if (message.GetCommandName() == Constants.MessageNames.Block) // ADD THE BLOCK.
            {
                var msg = message as BlockMessage;
                _blockValidator.Check(msg.Block);
                if (msg.Block.Transactions != null)
                {
                    MemoryPool.Instance().Remove(msg.Block.Transactions.Select(tx => tx.GetTxId()));
                }

                smartContract.AddBlock(msg.Block);
                smartContract.Commit();
                blockChain.AddBlock(msg.Block);
            }

            if (message.GetCommandName() == Constants.MessageNames.NotFound) //  SOME INVENTORIES ARE NOT FOUND.
            {
                return(null);
            }

            if (message.GetCommandName() == Constants.MessageNames.GetBlocks) // RETURN THE BLOCKS : https://bitcoin.org/en/developer-reference#getblocks
            {
                var msg             = message as GetBlocksMessage;
                int lastBlockHeight = -1;
                foreach (var blockHash in msg.BlockHashes)
                {
                    lastBlockHeight = blockChain.GetBlockHeight(blockHash);
                    if (lastBlockHeight != -1)
                    {
                        goto Found;
                    }
                }

Found:
                var currentBlockHeight = blockChain.GetCurrentBlockHeight();
                if (currentBlockHeight == lastBlockHeight)
                {
                    return(new InventoryMessage(new List <Inventory>(), msg.MessageHeader.Network));
                }

                var nbBlocks = currentBlockHeight - lastBlockHeight;
                if (lastBlockHeight == -1)
                {
                    nbBlocks = currentBlockHeight - 1;
                }

                if (nbBlocks > Constants.DEFAULT_MAX_GET_INVENTORIES)
                {
                    nbBlocks = Constants.DEFAULT_MAX_GET_INVENTORIES;
                }

                var blocks      = blockChain.GetLastBlocks(nbBlocks);
                var inventories = new List <Inventory>();
                foreach (var block in blocks)
                {
                    inventories.Add(new Inventory(InventoryTypes.MSG_BLOCK, block.GetHashHeader()));
                }

                return(new InventoryMessage(inventories, msg.MessageHeader.Network));
            }

            return(null);
        }