From b9bca58f26e96ff2fb8e13b5a975b76eb9fdd60a Mon Sep 17 00:00:00 2001 From: Devrandom Date: Wed, 5 Nov 2014 10:56:07 -0800 Subject: [PATCH] Remove tx from TransactionConfidence --- .../java/org/bitcoinj/core/Transaction.java | 2 +- .../bitcoinj/core/TransactionBroadcast.java | 5 ++-- .../bitcoinj/core/TransactionConfidence.java | 28 +++++++++++-------- .../main/java/org/bitcoinj/core/Wallet.java | 3 +- .../NativeTransactionConfidenceListener.java | 3 +- .../channels/PaymentChannelClientState.java | 6 ++-- .../org/bitcoinj/core/ChainSplitTest.java | 4 +-- .../java/org/bitcoinj/core/PeerGroupTest.java | 9 +++--- .../java/org/bitcoinj/core/WalletTest.java | 16 +++++------ .../bitcoinj/examples/ForwardingService.java | 7 ++--- 10 files changed, 44 insertions(+), 39 deletions(-) diff --git a/core/src/main/java/org/bitcoinj/core/Transaction.java b/core/src/main/java/org/bitcoinj/core/Transaction.java index 75aff269..9b793993 100644 --- a/core/src/main/java/org/bitcoinj/core/Transaction.java +++ b/core/src/main/java/org/bitcoinj/core/Transaction.java @@ -1127,7 +1127,7 @@ public class Transaction extends ChildMessage implements Serializable { public synchronized TransactionConfidence getConfidence() { if (confidence == null) { - confidence = new TransactionConfidence(this); + confidence = new TransactionConfidence(getHash()); } return confidence; } diff --git a/core/src/main/java/org/bitcoinj/core/TransactionBroadcast.java b/core/src/main/java/org/bitcoinj/core/TransactionBroadcast.java index 2e337c25..ce33230a 100644 --- a/core/src/main/java/org/bitcoinj/core/TransactionBroadcast.java +++ b/core/src/main/java/org/bitcoinj/core/TransactionBroadcast.java @@ -143,9 +143,8 @@ public class TransactionBroadcast { private class ConfidenceChange implements TransactionConfidence.Listener { @Override - public void onConfidenceChanged(Transaction tx, ChangeReason reason) { + public void onConfidenceChanged(TransactionConfidence conf, ChangeReason reason) { // The number of peers that announced this tx has gone up. - final TransactionConfidence conf = tx.getConfidence(); int numSeenPeers = conf.numBroadcastPeers(); boolean mined = tx.getAppearsInHashes() != null; log.info("broadcastTransaction: {}: TX {} seen by {} peers{}", reason, pinnedTx.getHashAsString(), @@ -165,8 +164,8 @@ public class TransactionBroadcast { // We're done! It's important that the PeerGroup lock is not held (by this thread) at this // point to avoid triggering inversions when the Future completes. log.info("broadcastTransaction: {} complete", pinnedTx.getHashAsString()); - tx.getConfidence().removeEventListener(this); peerGroup.removeEventListener(rejectionListener); + conf.removeEventListener(this); future.set(pinnedTx); // RE-ENTRANCY POINT } } diff --git a/core/src/main/java/org/bitcoinj/core/TransactionConfidence.java b/core/src/main/java/org/bitcoinj/core/TransactionConfidence.java index 766fa5cc..0e2546ba 100644 --- a/core/src/main/java/org/bitcoinj/core/TransactionConfidence.java +++ b/core/src/main/java/org/bitcoinj/core/TransactionConfidence.java @@ -70,7 +70,7 @@ public class TransactionConfidence implements Serializable { */ private CopyOnWriteArrayList broadcastBy; /** The Transaction that this confidence object is associated with. */ - private final Transaction transaction; + private final Sha256Hash hash; // Lazily created listeners array. private transient CopyOnWriteArrayList> listeners; @@ -135,11 +135,11 @@ public class TransactionConfidence implements Serializable { } private Source source = Source.UNKNOWN; - public TransactionConfidence(Transaction tx) { + public TransactionConfidence(Sha256Hash hash) { // Assume a default number of peers for our set. broadcastBy = new CopyOnWriteArrayList(); listeners = new CopyOnWriteArrayList>(); - transaction = tx; + this.hash = hash; } /** @@ -175,7 +175,7 @@ public class TransactionConfidence implements Serializable { */ SEEN_PEERS, } - public void onConfidenceChanged(Transaction tx, ChangeReason reason); + public void onConfidenceChanged(TransactionConfidence confidence, ChangeReason reason); } /** @@ -382,7 +382,7 @@ public class TransactionConfidence implements Serializable { /** Returns a copy of this object. Event listeners are not duplicated. */ public synchronized TransactionConfidence duplicate() { - TransactionConfidence c = new TransactionConfidence(transaction); + TransactionConfidence c = new TransactionConfidence(hash); // There is no point in this sync block, it's just to help FindBugs. synchronized (c) { c.broadcastBy.addAll(broadcastBy); @@ -404,7 +404,7 @@ public class TransactionConfidence implements Serializable { registration.executor.execute(new Runnable() { @Override public void run() { - registration.listener.onConfidenceChanged(transaction, reason); + registration.listener.onConfidenceChanged(TransactionConfidence.this, reason); } }); } @@ -435,23 +435,27 @@ public class TransactionConfidence implements Serializable { * depth to one will wait until it appears in a block on the best chain, and zero will wait until it has been seen * on the network. */ - public synchronized ListenableFuture getDepthFuture(final int depth, Executor executor) { - final SettableFuture result = SettableFuture.create(); + public synchronized ListenableFuture getDepthFuture(final int depth, Executor executor) { + final SettableFuture result = SettableFuture.create(); if (getDepthInBlocks() >= depth) { - result.set(transaction); + result.set(this); } addEventListener(new Listener() { - @Override public void onConfidenceChanged(Transaction tx, ChangeReason reason) { + @Override public void onConfidenceChanged(TransactionConfidence confidence, ChangeReason reason) { if (getDepthInBlocks() >= depth) { removeEventListener(this); - result.set(transaction); + result.set(confidence); } } }, executor); return result; } - public synchronized ListenableFuture getDepthFuture(final int depth) { + public synchronized ListenableFuture getDepthFuture(final int depth) { return getDepthFuture(depth, Threading.USER_THREAD); } + + public Sha256Hash getTransactionHash() { + return hash; + } } diff --git a/core/src/main/java/org/bitcoinj/core/Wallet.java b/core/src/main/java/org/bitcoinj/core/Wallet.java index e4d98044..5bfa2d10 100644 --- a/core/src/main/java/org/bitcoinj/core/Wallet.java +++ b/core/src/main/java/org/bitcoinj/core/Wallet.java @@ -271,7 +271,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha ignoreNextNewBlock = new HashSet(); txConfidenceListener = new TransactionConfidence.Listener() { @Override - public void onConfidenceChanged(Transaction tx, TransactionConfidence.Listener.ChangeReason reason) { + public void onConfidenceChanged(TransactionConfidence confidence, TransactionConfidence.Listener.ChangeReason reason) { // This will run on the user code thread so we shouldn't do anything too complicated here. // We only want to queue a wallet changed event and auto-save if the number of peers announcing // the transaction has changed, as that confidence change is made by the networking code which @@ -282,6 +282,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha lock.lock(); try { checkBalanceFuturesLocked(null); + Transaction tx = getTransaction(confidence.getTransactionHash()); queueOnTransactionConfidenceChanged(tx); maybeQueueOnWalletChanged(); } finally { diff --git a/core/src/main/java/org/bitcoinj/jni/NativeTransactionConfidenceListener.java b/core/src/main/java/org/bitcoinj/jni/NativeTransactionConfidenceListener.java index 065d29aa..0cb22c09 100644 --- a/core/src/main/java/org/bitcoinj/jni/NativeTransactionConfidenceListener.java +++ b/core/src/main/java/org/bitcoinj/jni/NativeTransactionConfidenceListener.java @@ -16,6 +16,7 @@ package org.bitcoinj.jni; +import org.bitcoinj.core.Sha256Hash; import org.bitcoinj.core.Transaction; import org.bitcoinj.core.TransactionConfidence; @@ -28,5 +29,5 @@ public class NativeTransactionConfidenceListener implements TransactionConfidenc public long ptr; @Override - public native void onConfidenceChanged(Transaction tx, ChangeReason reason); + public native void onConfidenceChanged(TransactionConfidence confidence, ChangeReason reason); } diff --git a/core/src/main/java/org/bitcoinj/protocols/channels/PaymentChannelClientState.java b/core/src/main/java/org/bitcoinj/protocols/channels/PaymentChannelClientState.java index 2f1e7ffb..4dd02eef 100644 --- a/core/src/main/java/org/bitcoinj/protocols/channels/PaymentChannelClientState.java +++ b/core/src/main/java/org/bitcoinj/protocols/channels/PaymentChannelClientState.java @@ -197,10 +197,10 @@ public class PaymentChannelClientState { // of this channel along with the refund tx from the wallet, because we're not going to need // any of that any more. final TransactionConfidence confidence = storedChannel.close.getConfidence(); - ListenableFuture future = confidence.getDepthFuture(CONFIRMATIONS_FOR_DELETE, Threading.SAME_THREAD); - Futures.addCallback(future, new FutureCallback() { + ListenableFuture future = confidence.getDepthFuture(CONFIRMATIONS_FOR_DELETE, Threading.SAME_THREAD); + Futures.addCallback(future, new FutureCallback() { @Override - public void onSuccess(Transaction result) { + public void onSuccess(TransactionConfidence result) { deleteChannelFromWallet(); } diff --git a/core/src/test/java/org/bitcoinj/core/ChainSplitTest.java b/core/src/test/java/org/bitcoinj/core/ChainSplitTest.java index cf103968..c9432c13 100644 --- a/core/src/test/java/org/bitcoinj/core/ChainSplitTest.java +++ b/core/src/test/java/org/bitcoinj/core/ChainSplitTest.java @@ -604,8 +604,8 @@ public class ChainSplitTest { final AtomicBoolean fodderIsDead = new AtomicBoolean(false); fodder.getConfidence().addEventListener(new TransactionConfidence.Listener() { @Override - public void onConfidenceChanged(Transaction tx, ChangeReason reason) { - fodderIsDead.set(tx.getConfidence().getConfidenceType() == ConfidenceType.DEAD); + public void onConfidenceChanged(TransactionConfidence confidence, ChangeReason reason) { + fodderIsDead.set(confidence.getConfidenceType() == ConfidenceType.DEAD); } }, Threading.SAME_THREAD); diff --git a/core/src/test/java/org/bitcoinj/core/PeerGroupTest.java b/core/src/test/java/org/bitcoinj/core/PeerGroupTest.java index 9589546e..537f25ea 100644 --- a/core/src/test/java/org/bitcoinj/core/PeerGroupTest.java +++ b/core/src/test/java/org/bitcoinj/core/PeerGroupTest.java @@ -355,7 +355,8 @@ public class PeerGroupTest extends TestWithPeerGroup { // its trustworthyness assuming an untampered with internet connection. peerGroup.start(); - final Transaction[] event = new Transaction[2]; + final Transaction[] event = new Transaction[1]; + final TransactionConfidence[] confEvent = new TransactionConfidence[1]; peerGroup.addEventListener(new AbstractPeerEventListener() { @Override public void onTransaction(Peer peer, Transaction t) { @@ -397,15 +398,15 @@ public class PeerGroupTest extends TestWithPeerGroup { tx.getConfidence().addEventListener(new TransactionConfidence.Listener() { @Override - public void onConfidenceChanged(Transaction tx, TransactionConfidence.Listener.ChangeReason reason) { - event[1] = tx; + public void onConfidenceChanged(TransactionConfidence confidence, TransactionConfidence.Listener.ChangeReason reason) { + confEvent[0] = confidence; } }); // A straggler reports in. inbound(p3, inv); pingAndWait(p3); Threading.waitForUserCode(); - assertEquals(tx, event[1]); + assertEquals(tx.getHash(), confEvent[0].getTransactionHash()); assertEquals(3, tx.getConfidence().numBroadcastPeers()); assertTrue(tx.getConfidence().wasBroadcastBy(peerOf(p3).getAddress())); } diff --git a/core/src/test/java/org/bitcoinj/core/WalletTest.java b/core/src/test/java/org/bitcoinj/core/WalletTest.java index 3563f1e3..2c3a72d3 100644 --- a/core/src/test/java/org/bitcoinj/core/WalletTest.java +++ b/core/src/test/java/org/bitcoinj/core/WalletTest.java @@ -368,7 +368,7 @@ public class WalletTest extends TestWithWallet { // Send some pending coins to the wallet. Transaction t1 = sendMoneyToWallet(wallet, amount, toAddress, null); Threading.waitForUserCode(); - final ListenableFuture depthFuture = t1.getConfidence().getDepthFuture(1); + final ListenableFuture depthFuture = t1.getConfidence().getDepthFuture(1); assertFalse(depthFuture.isDone()); assertEquals(ZERO, wallet.getBalance()); assertEquals(amount, wallet.getBalance(Wallet.BalanceType.ESTIMATED)); @@ -764,13 +764,13 @@ public class WalletTest extends TestWithWallet { Transaction send3 = checkNotNull(wallet.createSend(address, value)); wallet.commitTx(send3); assertEquals(ZERO, wallet.getBalance()); - final LinkedList dead = new LinkedList(); + final LinkedList dead = new LinkedList(); final TransactionConfidence.Listener listener = new TransactionConfidence.Listener() { @Override - public void onConfidenceChanged(Transaction tx, ChangeReason reason) { - final TransactionConfidence.ConfidenceType type = tx.getConfidence().getConfidenceType(); + public void onConfidenceChanged(TransactionConfidence confidence, ChangeReason reason) { + final TransactionConfidence.ConfidenceType type = confidence.getConfidenceType(); if (reason == ChangeReason.TYPE && type == TransactionConfidence.ConfidenceType.DEAD) - dead.add(tx); + dead.add(confidence); } }; send2.getConfidence().addEventListener(listener, Threading.SAME_THREAD); @@ -779,8 +779,8 @@ public class WalletTest extends TestWithWallet { sendMoneyToWallet(send1, AbstractBlockChain.NewBlockType.BEST_CHAIN); // Back to having one coin. assertEquals(value, wallet.getBalance()); - assertEquals(send2, dead.poll()); - assertEquals(send3, dead.poll()); + assertEquals(send2.getHash(), dead.poll().getTransactionHash()); + assertEquals(send3.getHash(), dead.poll().getTransactionHash()); } @Test @@ -892,7 +892,7 @@ public class WalletTest extends TestWithWallet { final TransactionConfidence.Listener.ChangeReason[] reasons = new TransactionConfidence.Listener.ChangeReason[1]; notifiedTx[0].getConfidence().addEventListener(new TransactionConfidence.Listener() { @Override - public void onConfidenceChanged(Transaction tx, TransactionConfidence.Listener.ChangeReason reason) { + public void onConfidenceChanged(TransactionConfidence confidence, TransactionConfidence.Listener.ChangeReason reason) { flags[1] = true; reasons[0] = reason; } diff --git a/examples/src/main/java/org/bitcoinj/examples/ForwardingService.java b/examples/src/main/java/org/bitcoinj/examples/ForwardingService.java index 4011c32c..8b2385ba 100644 --- a/examples/src/main/java/org/bitcoinj/examples/ForwardingService.java +++ b/examples/src/main/java/org/bitcoinj/examples/ForwardingService.java @@ -93,11 +93,10 @@ public class ForwardingService { // to be double spent, no harm done. Wallet.allowSpendingUnconfirmedTransactions() would have to // be called in onSetupCompleted() above. But we don't do that here to demonstrate the more common // case of waiting for a block. - Futures.addCallback(tx.getConfidence().getDepthFuture(1), new FutureCallback() { + Futures.addCallback(tx.getConfidence().getDepthFuture(1), new FutureCallback() { @Override - public void onSuccess(Transaction result) { - // "result" here is the same as "tx" above, but we use it anyway for clarity. - forwardCoins(result); + public void onSuccess(TransactionConfidence result) { + forwardCoins(tx); } @Override