Beispiel #1
0
        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.");
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
            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);
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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);
            }
        }
Beispiel #7
0
            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());
            }