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); }
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); }
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)); } }
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); }
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); }
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()); }
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); }
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)); } }
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)); } }
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); } } }
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); }