3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-01-31 07:12:17 +00:00

Remove tx from TransactionConfidence

This commit is contained in:
Devrandom 2014-11-05 10:56:07 -08:00 committed by Mike Hearn
parent ec7cec67a7
commit b9bca58f26
10 changed files with 44 additions and 39 deletions

View File

@ -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;
}

View File

@ -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
}
}

View File

@ -70,7 +70,7 @@ public class TransactionConfidence implements Serializable {
*/
private CopyOnWriteArrayList<PeerAddress> 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<ListenerRegistration<Listener>> 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<PeerAddress>();
listeners = new CopyOnWriteArrayList<ListenerRegistration<Listener>>();
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<Transaction> getDepthFuture(final int depth, Executor executor) {
final SettableFuture<Transaction> result = SettableFuture.create();
public synchronized ListenableFuture<TransactionConfidence> getDepthFuture(final int depth, Executor executor) {
final SettableFuture<TransactionConfidence> 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<Transaction> getDepthFuture(final int depth) {
public synchronized ListenableFuture<TransactionConfidence> getDepthFuture(final int depth) {
return getDepthFuture(depth, Threading.USER_THREAD);
}
public Sha256Hash getTransactionHash() {
return hash;
}
}

View File

@ -271,7 +271,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
ignoreNextNewBlock = new HashSet<Sha256Hash>();
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 {

View File

@ -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);
}

View File

@ -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<Transaction> future = confidence.getDepthFuture(CONFIRMATIONS_FOR_DELETE, Threading.SAME_THREAD);
Futures.addCallback(future, new FutureCallback<Transaction>() {
ListenableFuture<TransactionConfidence> future = confidence.getDepthFuture(CONFIRMATIONS_FOR_DELETE, Threading.SAME_THREAD);
Futures.addCallback(future, new FutureCallback<TransactionConfidence>() {
@Override
public void onSuccess(Transaction result) {
public void onSuccess(TransactionConfidence result) {
deleteChannelFromWallet();
}

View File

@ -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);

View File

@ -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()));
}

View File

@ -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<Transaction> depthFuture = t1.getConfidence().getDepthFuture(1);
final ListenableFuture<TransactionConfidence> 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<Transaction> dead = new LinkedList<Transaction>();
final LinkedList<TransactionConfidence> dead = new LinkedList<TransactionConfidence>();
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;
}

View File

@ -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<Transaction>() {
Futures.addCallback(tx.getConfidence().getDepthFuture(1), new FutureCallback<TransactionConfidence>() {
@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