mirror of
				https://github.com/Qortal/altcoinj.git
				synced 2025-11-03 05:57:21 +00:00 
			
		
		
		
	TransactionBroadcast: refactor
This commit is contained in:
		
				
					committed by
					
						
						Andreas Schildbach
					
				
			
			
				
	
			
			
			
						parent
						
							b73c48d0ef
						
					
				
				
					commit
					2fe658d261
				
			@@ -55,7 +55,11 @@ public class TransactionBroadcast {
 | 
			
		||||
    public ListenableFuture<Transaction> broadcast() {
 | 
			
		||||
        log.info("Waiting for {} peers required for broadcast ...", minConnections);
 | 
			
		||||
        ListenableFuture<PeerGroup> peerAvailabilityFuture = peerGroup.waitForPeers(minConnections);
 | 
			
		||||
        peerAvailabilityFuture.addListener(new Runnable() {
 | 
			
		||||
        peerAvailabilityFuture.addListener(new EnoughAvailablePeers(), Threading.SAME_THREAD);
 | 
			
		||||
        return future;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private class EnoughAvailablePeers implements Runnable {
 | 
			
		||||
        public void run() {
 | 
			
		||||
            // We now have enough connected peers to send the transaction.
 | 
			
		||||
            // This can be called immediately if we already have enough. Otherwise it'll be called from a peer
 | 
			
		||||
@@ -68,8 +72,38 @@ public class TransactionBroadcast {
 | 
			
		||||
            final Transaction pinnedTx = peerGroup.getMemoryPool().seen(tx, somePeer.getAddress());
 | 
			
		||||
            // Prepare to send the transaction by adding a listener that'll be called when confidence changes.
 | 
			
		||||
            // Only bother with this if we might actually hear back:
 | 
			
		||||
                if (minConnections > 1) pinnedTx.getConfidence().addEventListener(new TransactionConfidence.Listener() {
 | 
			
		||||
                    public void onConfidenceChanged(Transaction tx, TransactionConfidence.Listener.ChangeReason reason) {
 | 
			
		||||
            if (minConnections > 1)
 | 
			
		||||
                pinnedTx.getConfidence().addEventListener(new ConfidenceChange(pinnedTx));
 | 
			
		||||
            // Satoshis code sends an inv in this case and then lets the peer request the tx data. We just
 | 
			
		||||
            // blast out the TX here for a couple of reasons. Firstly it's simpler: in the case where we have
 | 
			
		||||
            // just a single connection we don't have to wait for getdata to be received and handled before
 | 
			
		||||
            // completing the future in the code immediately below. Secondly, it's faster. The reason the
 | 
			
		||||
            // Satoshi client sends an inv is privacy - it means you can't tell if the peer originated the
 | 
			
		||||
            // transaction or not. However, we are not a fully validating node and this is advertised in
 | 
			
		||||
            // our version message, as SPV nodes cannot relay it doesn't give away any additional information
 | 
			
		||||
            // to skip the inv here - we wouldn't send invs anyway.
 | 
			
		||||
            //
 | 
			
		||||
            // TODO: The peer we picked might be dead by now. If we can't write the message, pick again and retry.
 | 
			
		||||
            somePeer.sendMessage(pinnedTx);
 | 
			
		||||
            // If we've been limited to talk to only one peer, we can't wait to hear back because the
 | 
			
		||||
            // remote peer won't tell us about transactions we just announced to it for obvious reasons.
 | 
			
		||||
            // So we just have to assume we're done, at that point. This happens when we're not given
 | 
			
		||||
            // any peer discovery source and the user just calls connectTo() once.
 | 
			
		||||
            if (minConnections == 1) {
 | 
			
		||||
                future.set(pinnedTx);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private class ConfidenceChange implements TransactionConfidence.Listener {
 | 
			
		||||
        private final Transaction pinnedTx;
 | 
			
		||||
 | 
			
		||||
        public ConfidenceChange(Transaction pinnedTx) {
 | 
			
		||||
            this.pinnedTx = pinnedTx;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void onConfidenceChanged(Transaction tx, ChangeReason reason) {
 | 
			
		||||
            // The number of peers that announced this tx has gone up.
 | 
			
		||||
            final TransactionConfidence conf = tx.getConfidence();
 | 
			
		||||
            int numSeenPeers = conf.numBroadcastPeers();
 | 
			
		||||
@@ -95,28 +129,5 @@ public class TransactionBroadcast {
 | 
			
		||||
            tx.getConfidence().removeEventListener(this);
 | 
			
		||||
            future.set(pinnedTx);  // RE-ENTRANCY POINT
 | 
			
		||||
        }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                // Satoshis code sends an inv in this case and then lets the peer request the tx data. We just
 | 
			
		||||
                // blast out the TX here for a couple of reasons. Firstly it's simpler: in the case where we have
 | 
			
		||||
                // just a single connection we don't have to wait for getdata to be received and handled before
 | 
			
		||||
                // completing the future in the code immediately below. Secondly, it's faster. The reason the
 | 
			
		||||
                // Satoshi client sends an inv is privacy - it means you can't tell if the peer originated the
 | 
			
		||||
                // transaction or not. However, we are not a fully validating node and this is advertised in
 | 
			
		||||
                // our version message, as SPV nodes cannot relay it doesn't give away any additional information
 | 
			
		||||
                // to skip the inv here - we wouldn't send invs anyway.
 | 
			
		||||
                //
 | 
			
		||||
                // TODO: The peer we picked might be dead by now. If we can't write the message, pick again and retry.
 | 
			
		||||
                somePeer.sendMessage(pinnedTx);
 | 
			
		||||
                // If we've been limited to talk to only one peer, we can't wait to hear back because the
 | 
			
		||||
                // remote peer won't tell us about transactions we just announced to it for obvious reasons.
 | 
			
		||||
                // So we just have to assume we're done, at that point. This happens when we're not given
 | 
			
		||||
                // any peer discovery source and the user just calls connectTo() once.
 | 
			
		||||
                if (minConnections == 1) {
 | 
			
		||||
                    future.set(pinnedTx);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }, Threading.SAME_THREAD);
 | 
			
		||||
        return future;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user