mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-13 02:35:52 +00:00
SendRequest: New .childPaysForParent() method that constructs a CPFP transaction.
This commit is contained in:
parent
85f7c39aa5
commit
2ab367b4e4
@ -33,6 +33,7 @@ import org.bitcoinj.signers.*;
|
||||
import org.bitcoinj.store.*;
|
||||
import org.bitcoinj.utils.*;
|
||||
import org.bitcoinj.wallet.*;
|
||||
import org.bitcoinj.wallet.KeyChain.KeyPurpose;
|
||||
import org.bitcoinj.wallet.Protos.Wallet.*;
|
||||
import org.bitcoinj.wallet.WalletTransaction.*;
|
||||
import org.slf4j.*;
|
||||
@ -3835,6 +3836,32 @@ public class Wallet extends BaseTaggableObject
|
||||
return req;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a SendRequest for a CPFP (child-pays-for-parent) transaction. The resulting transaction is already
|
||||
* completed, so you should directly proceed to signing and broadcasting/committing the transaction. CPFP is
|
||||
* currently only supported by a few miners, so use with care.
|
||||
*/
|
||||
public static SendRequest childPaysForParent(Wallet wallet, Transaction parentTransaction, Coin feeRaise) {
|
||||
TransactionOutput outputToSpend = null;
|
||||
for (final TransactionOutput output : parentTransaction.getOutputs()) {
|
||||
if (output.isMine(wallet) && output.isAvailableForSpending()
|
||||
&& output.getValue().isGreaterThan(feeRaise)) {
|
||||
outputToSpend = output;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// TODO spend another confirmed output of own wallet if needed
|
||||
checkNotNull(outputToSpend, "Can't find adequately sized output that spends to us");
|
||||
|
||||
final Transaction tx = new Transaction(parentTransaction.getParams());
|
||||
tx.addInput(outputToSpend);
|
||||
tx.addOutput(outputToSpend.getValue().subtract(feeRaise), wallet.freshAddress(KeyPurpose.CHANGE));
|
||||
tx.setPurpose(Transaction.Purpose.RAISE_FEE);
|
||||
final SendRequest req = forTx(tx);
|
||||
req.completed = true;
|
||||
return req;
|
||||
}
|
||||
|
||||
public static SendRequest toCLTVPaymentChannel(NetworkParameters params, Date releaseTime, ECKey from, ECKey to, Coin value) {
|
||||
long time = releaseTime.getTime() / 1000L;
|
||||
checkArgument(time >= Transaction.LOCKTIME_THRESHOLD, "Release time was too small");
|
||||
|
@ -22,6 +22,7 @@ import org.bitcoinj.core.listeners.WalletCoinsReceivedEventListener;
|
||||
import org.bitcoinj.core.listeners.WalletCoinsSentEventListener;
|
||||
import org.bitcoinj.core.listeners.TransactionConfidenceEventListener;
|
||||
import org.bitcoinj.core.TransactionConfidence.ConfidenceType;
|
||||
import org.bitcoinj.core.Wallet.BalanceType;
|
||||
import org.bitcoinj.core.Wallet.SendRequest;
|
||||
import org.bitcoinj.crypto.*;
|
||||
import org.bitcoinj.script.Script;
|
||||
@ -3062,6 +3063,29 @@ public class WalletTest extends TestWithWallet {
|
||||
assertEquals(outputValue, request.tx.getOutput(0).getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void childPaysForParent() throws Exception {
|
||||
// Receive confirmed balance to play with.
|
||||
Transaction toMe = createFakeTxWithoutChangeAddress(PARAMS, COIN, myAddress);
|
||||
wallet.receiveFromBlock(toMe, createFakeBlock(blockStore, toMe).storedBlock,
|
||||
AbstractBlockChain.NewBlockType.BEST_CHAIN, 0);
|
||||
assertEquals(Coin.COIN, wallet.getBalance(BalanceType.ESTIMATED_SPENDABLE));
|
||||
assertEquals(Coin.COIN, wallet.getBalance(BalanceType.AVAILABLE_SPENDABLE));
|
||||
// Receive unconfirmed coin without fee.
|
||||
Transaction toMeWithoutFee = createFakeTxWithoutChangeAddress(PARAMS, COIN, myAddress);
|
||||
wallet.receivePending(toMeWithoutFee, null);
|
||||
assertEquals(Coin.COIN.multiply(2), wallet.getBalance(BalanceType.ESTIMATED_SPENDABLE));
|
||||
assertEquals(Coin.COIN, wallet.getBalance(BalanceType.AVAILABLE_SPENDABLE));
|
||||
// Craft a child-pays-for-parent transaction.
|
||||
final Coin feeRaise = MILLICOIN;
|
||||
final SendRequest sendRequest = SendRequest.childPaysForParent(wallet, toMeWithoutFee, feeRaise);
|
||||
wallet.signTransaction(sendRequest);
|
||||
wallet.commitTx(sendRequest.tx);
|
||||
assertEquals(Transaction.Purpose.RAISE_FEE, sendRequest.tx.getPurpose());
|
||||
assertEquals(Coin.COIN.multiply(2).subtract(feeRaise), wallet.getBalance(BalanceType.ESTIMATED_SPENDABLE));
|
||||
assertEquals(Coin.COIN, wallet.getBalance(BalanceType.AVAILABLE_SPENDABLE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void keyRotationRandom() throws Exception {
|
||||
Utils.setMockClock();
|
||||
|
Loading…
x
Reference in New Issue
Block a user