private async Task ProcessTxIds <T>( TxIds message, Blockchain <T> blockchain, CancellationToken cancellationToken = default(CancellationToken)) where T : IAction { _logger.Debug("Trying to fetch txs..."); IEnumerable <TxId> unknownTxIds = message.Ids .Where(id => !blockchain.Transactions.ContainsKey(id)); if (!(message.Identity is Address from)) { throw new NullReferenceException( "TxIds doesn't have sender address."); } if (!_dealers.TryGetValue(from, out DealerSocket sock)) { _logger.Information( "TxIds was sent from unknown peer. ignored."); return; } IAsyncEnumerable <Transaction <T> > fetched = GetTxsAsync <T>(sock, unknownTxIds, cancellationToken); var toStage = new HashSet <Transaction <T> >( await fetched.ToListAsync(cancellationToken)); blockchain.StageTransactions(toStage); TxReceived.Set(); _logger.Debug("Txs staged successfully."); }
internal async Task BroadcastTxsAsync <T>( IEnumerable <Transaction <T> > txs, CancellationToken cancellationToken = default(CancellationToken)) where T : IAction { _logger.Debug("Broadcast Txs."); var message = new TxIds(txs.Select(tx => tx.Id)); await BroadcastMessage( message.ToNetMQMessage(_privateKey), TimeSpan.FromMilliseconds(300), cancellationToken); }
void GetTransactions(ExtKey key) { List <TxId> txIds = new List <TxId>(); List <uint256> Inputs = new List <uint256>(); var balance = Spend.Api.GetBalance(key.PrivateKey.GetWif(Spend.Api.Network).GetAddress(ScriptPubKeyType.Legacy).ScriptPubKey, false).Result; foreach (var op in balance.Operations) { TxId txid = new TxId(op.TransactionId) { Status = Node.TxStatus.Spent }; foreach (var coin in op.ReceivedCoins) { if (coin.TxOut.ScriptPubKey == key.PrivateKey.ScriptPubKey) { txid.MoneyIn += (Money)coin.Amount; } } var transactionResponse = Spend.Api.GetTransaction(op.TransactionId).Result; Transaction transaction = transactionResponse.Transaction; var inputs = transaction.Inputs; foreach (TxIn input in inputs) { OutPoint previousOutpoint = input.PrevOut; if (input.ScriptSig == key.PrivateKey.ScriptPubKey) { Inputs.Add(previousOutpoint.Hash); } } if (txid.MoneyIn != Money.Zero) { txIds.Add(txid); } } foreach (TxId txId in txIds) { if (!(Inputs.Contains(txId.TransactionId))) //|| txId.MoneyOut == Money.Zero)) { TxIds.Add(txId); } } }
private void ProcessTxIds(TxIds message) { if (!(message.Remote is BoundPeer peer)) { _logger.Information( $"Ignores a {nameof(TxIds)} message because it was sent by an invalid peer: " + "{PeerAddress}.", message.Remote?.Address.ToHex() ); return; } _logger.Debug( $"Received a {nameof(TxIds)} message: {{@TxIds}}.", message.Ids.Select(txid => txid.ToString()) ); TxCompletion.Demand(peer, message.Ids); }
private void ProcessTxIds(TxIds message) { if (!(message.Remote is BoundPeer peer)) { _logger.Information( "Ignoring a {MessageType} message because it was sent by an invalid peer: " + "{PeerAddress}.", nameof(Messages.TxIds), message.Remote?.Address.ToHex() ); return; } _logger.Debug( "Received a {MessageType} message with {TxIdCount} txIds.", nameof(Messages.TxIds), message.Ids.Count() ); TxCompletion.Demand(peer, message.Ids); }
private void ProcessTxIds(TxIds message) { if (!(message.Remote is BoundPeer peer)) { _logger.Information( $"Ignores a {nameof(TxIds)} message because it was sent by an invalid peer: " + "{PeerAddress}.", message.Remote?.Address.ToHex() ); return; } _logger.Debug( $"Received a {nameof(TxIds)} message: {{@TxIds}}.", message.Ids.Select(txid => txid.ToString()) ); IStagePolicy <T> stagePolicy = BlockChain.StagePolicy; ImmutableHashSet <TxId> newTxIds = message.Ids .Where(id => !_demandTxIds.ContainsKey(id)) .Where(id => !stagePolicy.HasStaged(BlockChain, id, true)) .ToImmutableHashSet(); if (!newTxIds.Any()) { _logger.Debug("No unaware transactions to receive."); return; } _logger.Debug( "Unaware transactions to receive: {@TxIds}.", newTxIds.Select(txid => txid.ToString()) ); foreach (TxId txid in newTxIds) { _demandTxIds.TryAdd(txid, peer); } }
public KeyTx(SpendTx spend, ExtKey spendKey, ExtKey changeKey, Money minerFee) { Spend = spend; MinerFee = minerFee; PaymentAddress = spendKey.PrivateKey.GetWif(Spend.Api.Network).GetAddress(ScriptPubKeyType.Legacy).ToString(); Tx = Transaction.Create(Spend.Api.Network); var ReceiverAddress = BitcoinAddress.Create(Spend.ToAddress, Spend.Api.Network); Tx.Outputs.Add(SpendAmount, ReceiverAddress.ScriptPubKey); Tx.Outputs.Add(ChangeAmount, changeKey.PrivateKey.GetWif(Spend.Api.Network).GetAddress(ScriptPubKeyType.Legacy).ScriptPubKey); if (Spend.TxMessage.Length > 0) { Tx.Outputs.Add(Money.Zero, TxNullDataTemplate.Instance.GenerateScriptPubKey(Encoding.UTF8.GetBytes(Spend.TxMessage))); } GetTransactions(spendKey); List <TxId> inputs = new List <TxId>(); foreach (var txId in TxIds) { if (!AddTransaction(spendKey, txId)) { continue; } else { inputs.Add(txId); } var totalSpend = Spend.SpendAmount + TxInAmount - MinerFee; var remainingAmount = Spend.TargetAmount - totalSpend; SpendAmount = remainingAmount > Money.Zero ? TxInAmount - MinerFee : TxInAmount - MinerFee + remainingAmount; ChangeAmount = TxInAmount - SpendAmount - MinerFee; if (Spend.TargetAmount <= (Spend.TxInAmount + TxInAmount - Spend.MinerFee - MinerFee)) { break; } } List <TxId> unusedTx = TxIds.Where(tx => !inputs.Contains(tx)).ToList(); foreach (var tx in unusedTx) { TxIds.Remove(tx); } Tx.Outputs.Clear(); Tx.Outputs.Add(SpendAmount, ReceiverAddress.ScriptPubKey); if (ChangeAmount > Money.Zero) { Tx.Outputs.Add(ChangeAmount, changeKey.PrivateKey.GetWif(Spend.Api.Network).GetAddress(ScriptPubKeyType.Legacy).ScriptPubKey); } if (Spend.TxMessage.Length > 0) { Tx.Outputs.Add(Money.Zero, TxNullDataTemplate.Instance.GenerateScriptPubKey(Encoding.UTF8.GetBytes(Spend.TxMessage))); } Tx.Sign(spendKey.PrivateKey.GetBitcoinSecret(Spend.Api.Network), coins.ToArray()); }