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() { public synchronized TransactionConfidence getConfidence() {
if (confidence == null) { if (confidence == null) {
confidence = new TransactionConfidence(this); confidence = new TransactionConfidence(getHash());
} }
return confidence; return confidence;
} }

View File

@ -143,9 +143,8 @@ public class TransactionBroadcast {
private class ConfidenceChange implements TransactionConfidence.Listener { private class ConfidenceChange implements TransactionConfidence.Listener {
@Override @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. // The number of peers that announced this tx has gone up.
final TransactionConfidence conf = tx.getConfidence();
int numSeenPeers = conf.numBroadcastPeers(); int numSeenPeers = conf.numBroadcastPeers();
boolean mined = tx.getAppearsInHashes() != null; boolean mined = tx.getAppearsInHashes() != null;
log.info("broadcastTransaction: {}: TX {} seen by {} peers{}", reason, pinnedTx.getHashAsString(), 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 // 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. // point to avoid triggering inversions when the Future completes.
log.info("broadcastTransaction: {} complete", pinnedTx.getHashAsString()); log.info("broadcastTransaction: {} complete", pinnedTx.getHashAsString());
tx.getConfidence().removeEventListener(this);
peerGroup.removeEventListener(rejectionListener); peerGroup.removeEventListener(rejectionListener);
conf.removeEventListener(this);
future.set(pinnedTx); // RE-ENTRANCY POINT future.set(pinnedTx); // RE-ENTRANCY POINT
} }
} }

View File

@ -70,7 +70,7 @@ public class TransactionConfidence implements Serializable {
*/ */
private CopyOnWriteArrayList<PeerAddress> broadcastBy; private CopyOnWriteArrayList<PeerAddress> broadcastBy;
/** The Transaction that this confidence object is associated with. */ /** The Transaction that this confidence object is associated with. */
private final Transaction transaction; private final Sha256Hash hash;
// Lazily created listeners array. // Lazily created listeners array.
private transient CopyOnWriteArrayList<ListenerRegistration<Listener>> listeners; private transient CopyOnWriteArrayList<ListenerRegistration<Listener>> listeners;
@ -135,11 +135,11 @@ public class TransactionConfidence implements Serializable {
} }
private Source source = Source.UNKNOWN; private Source source = Source.UNKNOWN;
public TransactionConfidence(Transaction tx) { public TransactionConfidence(Sha256Hash hash) {
// Assume a default number of peers for our set. // Assume a default number of peers for our set.
broadcastBy = new CopyOnWriteArrayList<PeerAddress>(); broadcastBy = new CopyOnWriteArrayList<PeerAddress>();
listeners = new CopyOnWriteArrayList<ListenerRegistration<Listener>>(); listeners = new CopyOnWriteArrayList<ListenerRegistration<Listener>>();
transaction = tx; this.hash = hash;
} }
/** /**
@ -175,7 +175,7 @@ public class TransactionConfidence implements Serializable {
*/ */
SEEN_PEERS, 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. */ /** Returns a copy of this object. Event listeners are not duplicated. */
public synchronized TransactionConfidence duplicate() { 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. // There is no point in this sync block, it's just to help FindBugs.
synchronized (c) { synchronized (c) {
c.broadcastBy.addAll(broadcastBy); c.broadcastBy.addAll(broadcastBy);
@ -404,7 +404,7 @@ public class TransactionConfidence implements Serializable {
registration.executor.execute(new Runnable() { registration.executor.execute(new Runnable() {
@Override @Override
public void run() { 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 * 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. * on the network.
*/ */
public synchronized ListenableFuture<Transaction> getDepthFuture(final int depth, Executor executor) { public synchronized ListenableFuture<TransactionConfidence> getDepthFuture(final int depth, Executor executor) {
final SettableFuture<Transaction> result = SettableFuture.create(); final SettableFuture<TransactionConfidence> result = SettableFuture.create();
if (getDepthInBlocks() >= depth) { if (getDepthInBlocks() >= depth) {
result.set(transaction); result.set(this);
} }
addEventListener(new Listener() { addEventListener(new Listener() {
@Override public void onConfidenceChanged(Transaction tx, ChangeReason reason) { @Override public void onConfidenceChanged(TransactionConfidence confidence, ChangeReason reason) {
if (getDepthInBlocks() >= depth) { if (getDepthInBlocks() >= depth) {
removeEventListener(this); removeEventListener(this);
result.set(transaction); result.set(confidence);
} }
} }
}, executor); }, executor);
return result; return result;
} }
public synchronized ListenableFuture<Transaction> getDepthFuture(final int depth) { public synchronized ListenableFuture<TransactionConfidence> getDepthFuture(final int depth) {
return getDepthFuture(depth, Threading.USER_THREAD); 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>(); ignoreNextNewBlock = new HashSet<Sha256Hash>();
txConfidenceListener = new TransactionConfidence.Listener() { txConfidenceListener = new TransactionConfidence.Listener() {
@Override @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. // 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 // 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 // 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(); lock.lock();
try { try {
checkBalanceFuturesLocked(null); checkBalanceFuturesLocked(null);
Transaction tx = getTransaction(confidence.getTransactionHash());
queueOnTransactionConfidenceChanged(tx); queueOnTransactionConfidenceChanged(tx);
maybeQueueOnWalletChanged(); maybeQueueOnWalletChanged();
} finally { } finally {

View File

@ -16,6 +16,7 @@
package org.bitcoinj.jni; package org.bitcoinj.jni;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Transaction; import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionConfidence; import org.bitcoinj.core.TransactionConfidence;
@ -28,5 +29,5 @@ public class NativeTransactionConfidenceListener implements TransactionConfidenc
public long ptr; public long ptr;
@Override @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 // of this channel along with the refund tx from the wallet, because we're not going to need
// any of that any more. // any of that any more.
final TransactionConfidence confidence = storedChannel.close.getConfidence(); final TransactionConfidence confidence = storedChannel.close.getConfidence();
ListenableFuture<Transaction> future = confidence.getDepthFuture(CONFIRMATIONS_FOR_DELETE, Threading.SAME_THREAD); ListenableFuture<TransactionConfidence> future = confidence.getDepthFuture(CONFIRMATIONS_FOR_DELETE, Threading.SAME_THREAD);
Futures.addCallback(future, new FutureCallback<Transaction>() { Futures.addCallback(future, new FutureCallback<TransactionConfidence>() {
@Override @Override
public void onSuccess(Transaction result) { public void onSuccess(TransactionConfidence result) {
deleteChannelFromWallet(); deleteChannelFromWallet();
} }

View File

@ -604,8 +604,8 @@ public class ChainSplitTest {
final AtomicBoolean fodderIsDead = new AtomicBoolean(false); final AtomicBoolean fodderIsDead = new AtomicBoolean(false);
fodder.getConfidence().addEventListener(new TransactionConfidence.Listener() { fodder.getConfidence().addEventListener(new TransactionConfidence.Listener() {
@Override @Override
public void onConfidenceChanged(Transaction tx, ChangeReason reason) { public void onConfidenceChanged(TransactionConfidence confidence, ChangeReason reason) {
fodderIsDead.set(tx.getConfidence().getConfidenceType() == ConfidenceType.DEAD); fodderIsDead.set(confidence.getConfidenceType() == ConfidenceType.DEAD);
} }
}, Threading.SAME_THREAD); }, Threading.SAME_THREAD);

View File

@ -355,7 +355,8 @@ public class PeerGroupTest extends TestWithPeerGroup {
// its trustworthyness assuming an untampered with internet connection. // its trustworthyness assuming an untampered with internet connection.
peerGroup.start(); peerGroup.start();
final Transaction[] event = new Transaction[2]; final Transaction[] event = new Transaction[1];
final TransactionConfidence[] confEvent = new TransactionConfidence[1];
peerGroup.addEventListener(new AbstractPeerEventListener() { peerGroup.addEventListener(new AbstractPeerEventListener() {
@Override @Override
public void onTransaction(Peer peer, Transaction t) { public void onTransaction(Peer peer, Transaction t) {
@ -397,15 +398,15 @@ public class PeerGroupTest extends TestWithPeerGroup {
tx.getConfidence().addEventListener(new TransactionConfidence.Listener() { tx.getConfidence().addEventListener(new TransactionConfidence.Listener() {
@Override @Override
public void onConfidenceChanged(Transaction tx, TransactionConfidence.Listener.ChangeReason reason) { public void onConfidenceChanged(TransactionConfidence confidence, TransactionConfidence.Listener.ChangeReason reason) {
event[1] = tx; confEvent[0] = confidence;
} }
}); });
// A straggler reports in. // A straggler reports in.
inbound(p3, inv); inbound(p3, inv);
pingAndWait(p3); pingAndWait(p3);
Threading.waitForUserCode(); Threading.waitForUserCode();
assertEquals(tx, event[1]); assertEquals(tx.getHash(), confEvent[0].getTransactionHash());
assertEquals(3, tx.getConfidence().numBroadcastPeers()); assertEquals(3, tx.getConfidence().numBroadcastPeers());
assertTrue(tx.getConfidence().wasBroadcastBy(peerOf(p3).getAddress())); 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. // Send some pending coins to the wallet.
Transaction t1 = sendMoneyToWallet(wallet, amount, toAddress, null); Transaction t1 = sendMoneyToWallet(wallet, amount, toAddress, null);
Threading.waitForUserCode(); Threading.waitForUserCode();
final ListenableFuture<Transaction> depthFuture = t1.getConfidence().getDepthFuture(1); final ListenableFuture<TransactionConfidence> depthFuture = t1.getConfidence().getDepthFuture(1);
assertFalse(depthFuture.isDone()); assertFalse(depthFuture.isDone());
assertEquals(ZERO, wallet.getBalance()); assertEquals(ZERO, wallet.getBalance());
assertEquals(amount, wallet.getBalance(Wallet.BalanceType.ESTIMATED)); assertEquals(amount, wallet.getBalance(Wallet.BalanceType.ESTIMATED));
@ -764,13 +764,13 @@ public class WalletTest extends TestWithWallet {
Transaction send3 = checkNotNull(wallet.createSend(address, value)); Transaction send3 = checkNotNull(wallet.createSend(address, value));
wallet.commitTx(send3); wallet.commitTx(send3);
assertEquals(ZERO, wallet.getBalance()); 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() { final TransactionConfidence.Listener listener = new TransactionConfidence.Listener() {
@Override @Override
public void onConfidenceChanged(Transaction tx, ChangeReason reason) { public void onConfidenceChanged(TransactionConfidence confidence, ChangeReason reason) {
final TransactionConfidence.ConfidenceType type = tx.getConfidence().getConfidenceType(); final TransactionConfidence.ConfidenceType type = confidence.getConfidenceType();
if (reason == ChangeReason.TYPE && type == TransactionConfidence.ConfidenceType.DEAD) if (reason == ChangeReason.TYPE && type == TransactionConfidence.ConfidenceType.DEAD)
dead.add(tx); dead.add(confidence);
} }
}; };
send2.getConfidence().addEventListener(listener, Threading.SAME_THREAD); send2.getConfidence().addEventListener(listener, Threading.SAME_THREAD);
@ -779,8 +779,8 @@ public class WalletTest extends TestWithWallet {
sendMoneyToWallet(send1, AbstractBlockChain.NewBlockType.BEST_CHAIN); sendMoneyToWallet(send1, AbstractBlockChain.NewBlockType.BEST_CHAIN);
// Back to having one coin. // Back to having one coin.
assertEquals(value, wallet.getBalance()); assertEquals(value, wallet.getBalance());
assertEquals(send2, dead.poll()); assertEquals(send2.getHash(), dead.poll().getTransactionHash());
assertEquals(send3, dead.poll()); assertEquals(send3.getHash(), dead.poll().getTransactionHash());
} }
@Test @Test
@ -892,7 +892,7 @@ public class WalletTest extends TestWithWallet {
final TransactionConfidence.Listener.ChangeReason[] reasons = new TransactionConfidence.Listener.ChangeReason[1]; final TransactionConfidence.Listener.ChangeReason[] reasons = new TransactionConfidence.Listener.ChangeReason[1];
notifiedTx[0].getConfidence().addEventListener(new TransactionConfidence.Listener() { notifiedTx[0].getConfidence().addEventListener(new TransactionConfidence.Listener() {
@Override @Override
public void onConfidenceChanged(Transaction tx, TransactionConfidence.Listener.ChangeReason reason) { public void onConfidenceChanged(TransactionConfidence confidence, TransactionConfidence.Listener.ChangeReason reason) {
flags[1] = true; flags[1] = true;
reasons[0] = reason; reasons[0] = reason;
} }

View File

@ -93,11 +93,10 @@ public class ForwardingService {
// to be double spent, no harm done. Wallet.allowSpendingUnconfirmedTransactions() would have to // 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 // be called in onSetupCompleted() above. But we don't do that here to demonstrate the more common
// case of waiting for a block. // 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 @Override
public void onSuccess(Transaction result) { public void onSuccess(TransactionConfidence result) {
// "result" here is the same as "tx" above, but we use it anyway for clarity. forwardCoins(tx);
forwardCoins(result);
} }
@Override @Override