3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-07 14:54:15 +00:00

PeerGroup/Wallet: give the wallet a reference to a transaction broadcaster, so it can make its own transactions and broadcast them outside the context of a user initiated spend.

Later, we can change the mechanism used to broadcast pending transactions so the wallet does that itself.
This commit is contained in:
Mike Hearn 2013-08-08 11:46:09 +02:00
parent 6b1c208f1e
commit 33f48d3e22
2 changed files with 52 additions and 8 deletions

View File

@ -618,13 +618,14 @@ public class PeerGroup extends AbstractIdleService implements TransactionBroadca
public void addWallet(Wallet wallet) {
lock.lock();
try {
Preconditions.checkNotNull(wallet);
Preconditions.checkState(!wallets.contains(wallet));
checkNotNull(wallet);
checkState(!wallets.contains(wallet));
wallets.add(wallet);
wallet.setTransactionBroadcaster(this);
// TODO: Make wallets announce their own pending transactions.
// The only reason it's not done that way now is to try and reduce late, risky changes before 0.10
announcePendingWalletTransactions(Collections.singletonList(wallet), peers);
wallet.addEventListener(walletEventListener); // TODO: Run this in the current peer thread.
addPeerFilterProvider(wallet);
} finally {
lock.unlock();
@ -641,8 +642,8 @@ public class PeerGroup extends AbstractIdleService implements TransactionBroadca
public void addPeerFilterProvider(PeerFilterProvider provider) {
lock.lock();
try {
Preconditions.checkNotNull(provider);
Preconditions.checkState(!peerFilterProviders.contains(provider));
checkNotNull(provider);
checkState(!peerFilterProviders.contains(provider));
peerFilterProviders.add(provider);
// Don't bother downloading block bodies before the oldest keys in all our wallets. Make sure we recalculate

View File

@ -139,6 +139,8 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
private Map<Transaction, TransactionConfidence.Listener.ChangeReason> confidenceChanged;
private volatile WalletFiles vFileManager;
private TransactionBroadcaster vTransactionBroadcaster;
/** Represents the results of a {@link CoinSelector#select(java.math.BigInteger, java.util.LinkedList)} operation */
public static class CoinSelection {
public BigInteger valueGathered;
@ -1746,7 +1748,7 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
}
/**
* <p>Sends coins according to the given request, via the given {@link PeerGroup}.</p>
* <p>Sends coins according to the given request, via the given {@link TransactionBroadcaster}.</p>
*
* <p>The returned object provides both the transaction, and a future that can be used to learn when the broadcast
* is complete. Complete means, if the PeerGroup is limited to only one connection, when it was written out to
@ -1762,7 +1764,9 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
*/
@Nullable
public SendResult sendCoins(TransactionBroadcaster broadcaster, SendRequest request) {
// Does not need to be synchronized as sendCoinsOffline is and the rest is all thread-local.
// Should not be locked here, as we're going to call into the broadcaster and that might want to hold its
// own lock. sendCoinsOffline handles everything that needs to be locked.
checkState(!lock.isHeldByCurrentThread());
// Commit the TX to the wallet immediately so the spent coins won't be reused.
// TODO: We should probably allow the request to specify tx commit only after the network has accepted it.
@ -1780,6 +1784,21 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
return result;
}
/**
* Satisfies the given {@link SendRequest} using the default transaction broadcaster configured either via
* {@link PeerGroup#addWallet(Wallet)} or directly with {@link #setTransactionBroadcaster(TransactionBroadcaster)}.
*
* @param request the SendRequest that describes what to do, get one using static methods on SendRequest itself.
* @return An object containing the transaction that was created, and a future for the broadcast of it.
* @throws IllegalStateException if no transaction broadcaster has been configured.
*/
@Nullable
public SendResult sendCoins(SendRequest request) {
TransactionBroadcaster broadcaster = vTransactionBroadcaster;
checkState(broadcaster != null, "No transaction broadcaster is configured");
return sendCoins(broadcaster, request);
}
/**
* Sends coins to the given address, via the given {@link Peer}. Change is returned to {@link Wallet#getChangeAddress()}.
* If an exception is thrown by {@link Peer#sendMessage(Message)} the transaction is still committed, so the
@ -3090,6 +3109,10 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Fee calculation code.
private class FeeCalculation {
private CoinSelection bestCoinSelection;
private TransactionOutput bestChangeOutput;
@ -3297,4 +3320,24 @@ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvi
}
return size;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Managing wallet-triggered transaction broadcast.
/**
* <p>Specifies that the given {@link TransactionBroadcaster}, typically a {@link PeerGroup}, should be used for
* sending transactions to the Bitcoin network by default. Some sendCoins methods let you specify a broadcaster
* explicitly, in that case, they don't use this broadcaster. If null is specified then the wallet won't attempt
* to broadcast transactions itself.</p>
*
* <p>You don't normally need to call this. A {@link PeerGroup} will automatically set itself as the wallets
* broadcaster when you use {@link PeerGroup#addWallet(Wallet)}. A wallet can use the broadcaster when you ask
* it to send money, but in future also at other times to implement various features that may require asynchronous
* re-organisation of the wallet contents on the block chain. For instance, in future the wallet may choose to
* optimise itself to reduce fees or improve privacy.</p>
*/
public void setTransactionBroadcaster(@Nullable TransactionBroadcaster broadcaster) {
vTransactionBroadcaster = broadcaster;
}
}