/// <summary>
 /// Broadcast the partial transaction request to federation members.
 /// </summary>
 /// <param name="payload">The payload to broadcast.</param>
 private async Task BroadcastAsync(RequestPartialTransactionPayload payload)
 {
     if (this.AttachedPeer.IsConnected && this.federatedPegSettings.FederationNodeIpEndPoints.Contains(Utils.EnsureIPv6(this.AttachedPeer.PeerEndPoint)))
     {
         await this.AttachedPeer.SendMessageAsync(payload).ConfigureAwait(false);
     }
 }
        /// <inheritdoc />
        public async Task BroadcastAsync(RequestPartialTransactionPayload payload)
        {
            List <INetworkPeer> peers = this.connectionManager.ConnectedPeers.ToList();

            var ipAddressComparer = new IPAddressComparer();

            foreach (INetworkPeer peer in peers)
            {
                // Broadcast to peers.
                if (!peer.IsConnected)
                {
                    continue;
                }

                if (this.federationGatewaySettings.FederationNodeIpEndPoints.Any(e => ipAddressComparer.Equals(e.Address, peer.PeerEndPoint.Address)))
                {
                    try
                    {
                        await peer.SendMessageAsync(payload).ConfigureAwait(false);
                    }
                    catch (OperationCanceledException)
                    {
                    }
                }
            }
        }
Beispiel #3
0
 /// <summary>
 /// Broadcast the partial transaction request to federation members.
 /// </summary>
 /// <param name="payload">The payload to broadcast.</param>
 private async Task BroadcastAsync(RequestPartialTransactionPayload payload)
 {
     if (this.federatedPegSettings.FederationNodeIpEndPoints.Any(e => this.ipAddressComparer.Equals(e.Address, this.AttachedPeer.PeerEndPoint.Address)))
     {
         await this.AttachedPeer.SendMessageAsync(payload).ConfigureAwait(false);
     }
 }
        private async Task HandleConsolidationTransactionRequest(INetworkPeer peer, RequestPartialTransactionPayload payload)
        {
            ConsolidationSignatureResult result = this.inputConsolidator.CombineSignatures(payload.PartialTransaction);

            if (result.Signed)
            {
                this.logger.LogDebug("Signed consolidating transaction to produce {0} from {1}", result.TransactionResult.GetHash(), payload.PartialTransaction.GetHash());
                await this.BroadcastAsync(payload.AddPartial(result.TransactionResult));
            }
        }
 /// <summary>
 /// Broadcast the partial transaction request to federation members.
 /// </summary>
 /// <param name="payload">The payload to broadcast.</param>
 private async Task BroadcastAsync(RequestPartialTransactionPayload payload)
 {
     this.logger.Debug("Broadcasting to {0}", this.AttachedPeer.PeerEndPoint.Address);
     await this.AttachedPeer.SendMessageAsync(payload).ConfigureAwait(false);
 }
        ///<inheritdoc/>
        public async Task <uint256> ProcessCounterChainSession(int blockHeight)
        {
            //todo this method is doing too much. factor some of this into private methods after we added the counterchainid.
            this.logger.LogTrace("({0}:'{1}'", nameof(blockHeight), blockHeight);
            this.logger.LogInformation("Session Registered.");

            // Check if this has already been done then we just return the transactionId
            if (this.sessions.TryGetValue(blockHeight, out var counterchainSession))
            {
                // This is the mechanism that tells the round robin not to continue and also
                // notifies the monitorChain of the completed transactionId from the counterChain transaction.
                if (counterchainSession.CounterChainTransactionId != uint256.Zero)
                {
                    // If we get here:
                    // 1. One of the nodes became the boss and successfully broadcast a completed transaction.
                    // 2. The monitor in this node received the block with the transaction (identified by the sessionId in the op_return).
                    // 3. The monitor wrote the CounterChainTransactionId into the counterChainSession to indicate all was done.
                    // This method then does not try to process the transaction and instead signals to the monitorChain that this
                    // transaction already completed by passing back the transactionId.
                    this.logger.LogInformation($"Counterchain Session for block: {blockHeight} was already completed. Doing nothing.");
                    return(counterchainSession.CounterChainTransactionId);
                }
            }
            else
            {
                throw new InvalidOperationException($"No CounterChainSession found in the counter chain for block height {blockHeight}.");
            }

            // Check if the password has been added. If not, no need to go further.
            if (this.federationWalletManager.Secret == null || string.IsNullOrEmpty(this.federationWalletManager.Secret.WalletPassword))
            {
                string errorMessage = "The password needed for signing multisig transactions is missing.";
                this.logger.LogError(errorMessage);
                throw new WalletException(errorMessage);
            }

            var wallet          = this.federationWalletManager.GetWallet();
            var multiSigAddress = wallet.MultiSigAddress;

            var recipients = counterchainSession.CrossChainTransactions.Select(s =>
                                                                               new Recipient.Recipient
            {
                Amount       = s.Amount,
                ScriptPubKey = BitcoinAddress.Create(s.DestinationAddress, this.network).ScriptPubKey
            }).ToList();

            // We are the Boss so first I build the multisig transaction template.
            var multiSigContext = new TransactionBuildContext(recipients, this.federationWalletManager.Secret.WalletPassword, Encoding.UTF8.GetBytes(blockHeight.ToString()))
            {
                TransactionFee   = Money.Coins(0.01m),
                MinConfirmations = 1,
                Shuffle          = true,
                MultiSig         = multiSigAddress,
                IgnoreVerify     = true,
                Sign             = false
            };

            this.logger.LogInformation("Building template Transaction.");
            var templateTransaction = this.federationWalletTransactionHandler.BuildTransaction(multiSigContext);

            //add my own partial
            this.logger.LogInformation("Verify own partial.");
            var counterChainSession = this.VerifySession(blockHeight, templateTransaction);

            if (counterChainSession == null)
            {
                var exists = this.sessions.TryGetValue(blockHeight, out counterChainSession);
                if (exists)
                {
                    return(counterChainSession.CounterChainTransactionId);
                }
                throw new InvalidOperationException($"No CounterChainSession found in the counter chain for block height {blockHeight}.");
            }
            this.MarkSessionAsSigned(counterChainSession);
            var partialTransaction = wallet.SignPartialTransaction(templateTransaction, this.federationWalletManager.Secret.WalletPassword);

            uint256 bossCard = BossTable.MakeBossTableEntry(blockHeight, this.federationGatewaySettings.PublicKey);

            this.logger.LogInformation("My bossCard: {0}.", bossCard);
            this.ReceivePartial(blockHeight, partialTransaction, bossCard);

            //now build the requests for the partials
            var requestPartialTransactionPayload = new RequestPartialTransactionPayload(templateTransaction, blockHeight);

            // Only broadcast to the federation members.
            var federationNetworkPeers =
                this.connectionManager.ConnectedPeers
                .Where(p => !p.Inbound && federationGatewaySettings.FederationNodeIpEndPoints.Any(e => this.ipAddressComparer.Equals(e.Address, p.PeerEndPoint.Address)));

            foreach (INetworkPeer peer in federationNetworkPeers)
            {
                try
                {
                    this.logger.LogInformation("Broadcasting Partial Transaction Request to {0}.", peer.PeerEndPoint);
                    await peer.SendMessageAsync(requestPartialTransactionPayload).ConfigureAwait(false);
                }
                catch (OperationCanceledException)
                {
                }
            }
            this.logger.LogTrace("(-)");
            // We don't want to say this is complete yet.  We wait until we get the transaction back in a block.
            return(uint256.Zero);
        }