mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-07-31 20:11:23 +00:00
Teach SendRequest and Wallet to send to native segwit addresses.
WalletTool and FakeTxBuilder can do it, too.
This commit is contained in:
@@ -900,7 +900,7 @@ public class Block extends Message {
|
|||||||
* Returns a solved block that builds on top of this one. This exists for unit tests.
|
* Returns a solved block that builds on top of this one. This exists for unit tests.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public Block createNextBlock(LegacyAddress to, long version, long time, int blockHeight) {
|
public Block createNextBlock(Address to, long version, long time, int blockHeight) {
|
||||||
return createNextBlock(to, version, null, time, pubkeyForTesting, FIFTY_COINS, blockHeight);
|
return createNextBlock(to, version, null, time, pubkeyForTesting, FIFTY_COINS, blockHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -910,7 +910,7 @@ public class Block extends Message {
|
|||||||
*
|
*
|
||||||
* @param height block height, if known, or -1 otherwise.
|
* @param height block height, if known, or -1 otherwise.
|
||||||
*/
|
*/
|
||||||
Block createNextBlock(@Nullable final LegacyAddress to, final long version,
|
Block createNextBlock(@Nullable final Address to, final long version,
|
||||||
@Nullable TransactionOutPoint prevOut, final long time,
|
@Nullable TransactionOutPoint prevOut, final long time,
|
||||||
final byte[] pubKey, final Coin coinbaseValue,
|
final byte[] pubKey, final Coin coinbaseValue,
|
||||||
final int height) {
|
final int height) {
|
||||||
@@ -958,17 +958,17 @@ public class Block extends Message {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public Block createNextBlock(@Nullable LegacyAddress to, TransactionOutPoint prevOut) {
|
public Block createNextBlock(@Nullable Address to, TransactionOutPoint prevOut) {
|
||||||
return createNextBlock(to, BLOCK_VERSION_GENESIS, prevOut, getTimeSeconds() + 5, pubkeyForTesting, FIFTY_COINS, BLOCK_HEIGHT_UNKNOWN);
|
return createNextBlock(to, BLOCK_VERSION_GENESIS, prevOut, getTimeSeconds() + 5, pubkeyForTesting, FIFTY_COINS, BLOCK_HEIGHT_UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public Block createNextBlock(@Nullable LegacyAddress to, Coin value) {
|
public Block createNextBlock(@Nullable Address to, Coin value) {
|
||||||
return createNextBlock(to, BLOCK_VERSION_GENESIS, null, getTimeSeconds() + 5, pubkeyForTesting, value, BLOCK_HEIGHT_UNKNOWN);
|
return createNextBlock(to, BLOCK_VERSION_GENESIS, null, getTimeSeconds() + 5, pubkeyForTesting, value, BLOCK_HEIGHT_UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public Block createNextBlock(@Nullable LegacyAddress to) {
|
public Block createNextBlock(@Nullable Address to) {
|
||||||
return createNextBlock(to, FIFTY_COINS);
|
return createNextBlock(to, FIFTY_COINS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -884,7 +884,7 @@ public class Transaction extends ChildMessage {
|
|||||||
/**
|
/**
|
||||||
* Creates an output based on the given address and value, adds it to this transaction, and returns the new output.
|
* Creates an output based on the given address and value, adds it to this transaction, and returns the new output.
|
||||||
*/
|
*/
|
||||||
public TransactionOutput addOutput(Coin value, LegacyAddress address) {
|
public TransactionOutput addOutput(Coin value, Address address) {
|
||||||
return addOutput(new TransactionOutput(params, this, value, address));
|
return addOutput(new TransactionOutput(params, this, value, address));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -84,9 +84,9 @@ public class TransactionOutput extends ChildMessage {
|
|||||||
/**
|
/**
|
||||||
* Creates an output that sends 'value' to the given address (public key hash). The amount should be created with
|
* Creates an output that sends 'value' to the given address (public key hash). The amount should be created with
|
||||||
* something like {@link Coin#valueOf(int, int)}. Typically you would use
|
* something like {@link Coin#valueOf(int, int)}. Typically you would use
|
||||||
* {@link Transaction#addOutput(Coin, LegacyAddress)} instead of creating a TransactionOutput directly.
|
* {@link Transaction#addOutput(Coin, Address)} instead of creating a TransactionOutput directly.
|
||||||
*/
|
*/
|
||||||
public TransactionOutput(NetworkParameters params, @Nullable Transaction parent, Coin value, LegacyAddress to) {
|
public TransactionOutput(NetworkParameters params, @Nullable Transaction parent, Coin value, Address to) {
|
||||||
this(params, parent, value, ScriptBuilder.createOutputScript(to).getProgram());
|
this(params, parent, value, ScriptBuilder.createOutputScript(to).getProgram());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,6 +24,7 @@ import java.math.BigInteger;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.bitcoin.protocols.payments.Protos.PaymentDetails;
|
import org.bitcoin.protocols.payments.Protos.PaymentDetails;
|
||||||
|
import org.bitcoinj.core.Address;
|
||||||
import org.bitcoinj.core.LegacyAddress;
|
import org.bitcoinj.core.LegacyAddress;
|
||||||
import org.bitcoinj.core.Coin;
|
import org.bitcoinj.core.Coin;
|
||||||
import org.bitcoinj.core.Context;
|
import org.bitcoinj.core.Context;
|
||||||
@@ -163,7 +164,7 @@ public class SendRequest {
|
|||||||
* <p>Be very careful when value is smaller than {@link Transaction#MIN_NONDUST_OUTPUT} as the transaction will
|
* <p>Be very careful when value is smaller than {@link Transaction#MIN_NONDUST_OUTPUT} as the transaction will
|
||||||
* likely be rejected by the network in this case.</p>
|
* likely be rejected by the network in this case.</p>
|
||||||
*/
|
*/
|
||||||
public static SendRequest to(LegacyAddress destination, Coin value) {
|
public static SendRequest to(Address destination, Coin value) {
|
||||||
SendRequest req = new SendRequest();
|
SendRequest req = new SendRequest();
|
||||||
final NetworkParameters parameters = destination.getParameters();
|
final NetworkParameters parameters = destination.getParameters();
|
||||||
checkNotNull(parameters, "Address is for an unknown network");
|
checkNotNull(parameters, "Address is for an unknown network");
|
||||||
@@ -177,7 +178,7 @@ public class SendRequest {
|
|||||||
*
|
*
|
||||||
* <p>Be careful to check the output's value is reasonable using
|
* <p>Be careful to check the output's value is reasonable using
|
||||||
* {@link TransactionOutput#getMinNonDustValue(Coin)} afterwards or you risk having the transaction
|
* {@link TransactionOutput#getMinNonDustValue(Coin)} afterwards or you risk having the transaction
|
||||||
* rejected by the network. Note that using {@link SendRequest#to(LegacyAddress, Coin)} will result
|
* rejected by the network. Note that using {@link SendRequest#to(Address, Coin)} will result
|
||||||
* in a smaller output, and thus the ability to use a smaller output value without rejection.</p>
|
* in a smaller output, and thus the ability to use a smaller output value without rejection.</p>
|
||||||
*/
|
*/
|
||||||
public static SendRequest to(NetworkParameters params, ECKey destination, Coin value) {
|
public static SendRequest to(NetworkParameters params, ECKey destination, Coin value) {
|
||||||
@@ -194,7 +195,7 @@ public class SendRequest {
|
|||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SendRequest emptyWallet(LegacyAddress destination) {
|
public static SendRequest emptyWallet(Address destination) {
|
||||||
SendRequest req = new SendRequest();
|
SendRequest req = new SendRequest();
|
||||||
final NetworkParameters parameters = destination.getParameters();
|
final NetworkParameters parameters = destination.getParameters();
|
||||||
checkNotNull(parameters, "Address is for an unknown network");
|
checkNotNull(parameters, "Address is for an unknown network");
|
||||||
|
@@ -25,6 +25,7 @@ import com.google.common.util.concurrent.*;
|
|||||||
import com.google.protobuf.*;
|
import com.google.protobuf.*;
|
||||||
import net.jcip.annotations.*;
|
import net.jcip.annotations.*;
|
||||||
import org.bitcoinj.core.listeners.*;
|
import org.bitcoinj.core.listeners.*;
|
||||||
|
import org.bitcoinj.core.Address;
|
||||||
import org.bitcoinj.core.AbstractBlockChain;
|
import org.bitcoinj.core.AbstractBlockChain;
|
||||||
import org.bitcoinj.core.LegacyAddress;
|
import org.bitcoinj.core.LegacyAddress;
|
||||||
import org.bitcoinj.core.BlockChain;
|
import org.bitcoinj.core.BlockChain;
|
||||||
@@ -3779,11 +3780,11 @@ public class Wallet extends BaseTaggableObject
|
|||||||
* {@link Wallet#currentChangeAddress()}, so you must have added at least one key.</p>
|
* {@link Wallet#currentChangeAddress()}, so you must have added at least one key.</p>
|
||||||
*
|
*
|
||||||
* <p>If you just want to send money quickly, you probably want
|
* <p>If you just want to send money quickly, you probably want
|
||||||
* {@link Wallet#sendCoins(TransactionBroadcaster, LegacyAddress, Coin)} instead. That will create the sending
|
* {@link Wallet#sendCoins(TransactionBroadcaster, Address, Coin)} instead. That will create the sending
|
||||||
* transaction, commit to the wallet and broadcast it to the network all in one go. This method is lower level
|
* transaction, commit to the wallet and broadcast it to the network all in one go. This method is lower level
|
||||||
* and lets you see the proposed transaction before anything is done with it.</p>
|
* and lets you see the proposed transaction before anything is done with it.</p>
|
||||||
*
|
*
|
||||||
* <p>This is a helper method that is equivalent to using {@link SendRequest#to(LegacyAddress, Coin)}
|
* <p>This is a helper method that is equivalent to using {@link SendRequest#to(Address, Coin)}
|
||||||
* followed by {@link Wallet#completeTx(SendRequest)} and returning the requests transaction object.
|
* followed by {@link Wallet#completeTx(SendRequest)} and returning the requests transaction object.
|
||||||
* Note that this means a fee may be automatically added if required, if you want more control over the process,
|
* Note that this means a fee may be automatically added if required, if you want more control over the process,
|
||||||
* just do those two steps yourself.</p>
|
* just do those two steps yourself.</p>
|
||||||
@@ -3805,7 +3806,7 @@ public class Wallet extends BaseTaggableObject
|
|||||||
* @throws ExceededMaxTransactionSize if the resultant transaction is too big for Bitcoin to process.
|
* @throws ExceededMaxTransactionSize if the resultant transaction is too big for Bitcoin to process.
|
||||||
* @throws MultipleOpReturnRequested if there is more than one OP_RETURN output for the resultant transaction.
|
* @throws MultipleOpReturnRequested if there is more than one OP_RETURN output for the resultant transaction.
|
||||||
*/
|
*/
|
||||||
public Transaction createSend(LegacyAddress address, Coin value) throws InsufficientMoneyException {
|
public Transaction createSend(Address address, Coin value) throws InsufficientMoneyException {
|
||||||
SendRequest req = SendRequest.to(address, value);
|
SendRequest req = SendRequest.to(address, value);
|
||||||
if (params.getId().equals(NetworkParameters.ID_UNITTESTNET))
|
if (params.getId().equals(NetworkParameters.ID_UNITTESTNET))
|
||||||
req.shuffleOutputs = false;
|
req.shuffleOutputs = false;
|
||||||
@@ -3864,7 +3865,7 @@ public class Wallet extends BaseTaggableObject
|
|||||||
* @throws ExceededMaxTransactionSize if the resultant transaction is too big for Bitcoin to process.
|
* @throws ExceededMaxTransactionSize if the resultant transaction is too big for Bitcoin to process.
|
||||||
* @throws MultipleOpReturnRequested if there is more than one OP_RETURN output for the resultant transaction.
|
* @throws MultipleOpReturnRequested if there is more than one OP_RETURN output for the resultant transaction.
|
||||||
*/
|
*/
|
||||||
public SendResult sendCoins(TransactionBroadcaster broadcaster, LegacyAddress to, Coin value) throws InsufficientMoneyException {
|
public SendResult sendCoins(TransactionBroadcaster broadcaster, Address to, Coin value) throws InsufficientMoneyException {
|
||||||
SendRequest request = SendRequest.to(to, value);
|
SendRequest request = SendRequest.to(to, value);
|
||||||
return sendCoins(broadcaster, request);
|
return sendCoins(broadcaster, request);
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,23 @@
|
|||||||
|
|
||||||
package org.bitcoinj.testing;
|
package org.bitcoinj.testing;
|
||||||
|
|
||||||
import org.bitcoinj.core.*;
|
import org.bitcoinj.core.Address;
|
||||||
|
import org.bitcoinj.core.Block;
|
||||||
|
import org.bitcoinj.core.Coin;
|
||||||
|
import org.bitcoinj.core.ECKey;
|
||||||
|
import org.bitcoinj.core.LegacyAddress;
|
||||||
|
import org.bitcoinj.core.MessageSerializer;
|
||||||
|
import org.bitcoinj.core.NetworkParameters;
|
||||||
|
import org.bitcoinj.core.ProtocolException;
|
||||||
|
import org.bitcoinj.core.Sha256Hash;
|
||||||
|
import org.bitcoinj.core.StoredBlock;
|
||||||
|
import org.bitcoinj.core.Transaction;
|
||||||
|
import org.bitcoinj.core.TransactionConfidence;
|
||||||
|
import org.bitcoinj.core.TransactionInput;
|
||||||
|
import org.bitcoinj.core.TransactionOutPoint;
|
||||||
|
import org.bitcoinj.core.TransactionOutput;
|
||||||
|
import org.bitcoinj.core.Utils;
|
||||||
|
import org.bitcoinj.core.VerificationException;
|
||||||
import org.bitcoinj.crypto.TransactionSignature;
|
import org.bitcoinj.crypto.TransactionSignature;
|
||||||
import org.bitcoinj.script.ScriptBuilder;
|
import org.bitcoinj.script.ScriptBuilder;
|
||||||
import org.bitcoinj.store.BlockStore;
|
import org.bitcoinj.store.BlockStore;
|
||||||
@@ -64,7 +80,7 @@ public class FakeTxBuilder {
|
|||||||
* Create a fake TX of sufficient realism to exercise the unit tests. Two outputs, one to us, one to somewhere
|
* Create a fake TX of sufficient realism to exercise the unit tests. Two outputs, one to us, one to somewhere
|
||||||
* else to simulate change. There is one random input.
|
* else to simulate change. There is one random input.
|
||||||
*/
|
*/
|
||||||
public static Transaction createFakeTxWithChangeAddress(NetworkParameters params, Coin value, LegacyAddress to, LegacyAddress changeOutput) {
|
public static Transaction createFakeTxWithChangeAddress(NetworkParameters params, Coin value, Address to, Address changeOutput) {
|
||||||
Transaction t = new Transaction(params);
|
Transaction t = new Transaction(params);
|
||||||
TransactionOutput outputToMe = new TransactionOutput(params, t, value, to);
|
TransactionOutput outputToMe = new TransactionOutput(params, t, value, to);
|
||||||
t.addOutput(outputToMe);
|
t.addOutput(outputToMe);
|
||||||
@@ -86,7 +102,7 @@ public class FakeTxBuilder {
|
|||||||
* Create a fake TX for unit tests, for use with unit tests that need greater control. One outputs, 2 random inputs,
|
* Create a fake TX for unit tests, for use with unit tests that need greater control. One outputs, 2 random inputs,
|
||||||
* split randomly to create randomness.
|
* split randomly to create randomness.
|
||||||
*/
|
*/
|
||||||
public static Transaction createFakeTxWithoutChangeAddress(NetworkParameters params, Coin value, LegacyAddress to) {
|
public static Transaction createFakeTxWithoutChangeAddress(NetworkParameters params, Coin value, Address to) {
|
||||||
Transaction t = new Transaction(params);
|
Transaction t = new Transaction(params);
|
||||||
TransactionOutput outputToMe = new TransactionOutput(params, t, value, to);
|
TransactionOutput outputToMe = new TransactionOutput(params, t, value, to);
|
||||||
t.addOutput(outputToMe);
|
t.addOutput(outputToMe);
|
||||||
@@ -122,7 +138,7 @@ public class FakeTxBuilder {
|
|||||||
* Create a fake TX of sufficient realism to exercise the unit tests. Two outputs, one to us, one to somewhere
|
* Create a fake TX of sufficient realism to exercise the unit tests. Two outputs, one to us, one to somewhere
|
||||||
* else to simulate change. There is one random input.
|
* else to simulate change. There is one random input.
|
||||||
*/
|
*/
|
||||||
public static Transaction createFakeTx(NetworkParameters params, Coin value, LegacyAddress to) {
|
public static Transaction createFakeTx(NetworkParameters params, Coin value, Address to) {
|
||||||
return createFakeTxWithChangeAddress(params, value, to, LegacyAddress.fromKey(params, new ECKey()));
|
return createFakeTxWithChangeAddress(params, value, to, LegacyAddress.fromKey(params, new ECKey()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +167,7 @@ public class FakeTxBuilder {
|
|||||||
* Transaction[0] is a feeder transaction, supplying BTC to Transaction[1]
|
* Transaction[0] is a feeder transaction, supplying BTC to Transaction[1]
|
||||||
*/
|
*/
|
||||||
public static Transaction[] createFakeTx(NetworkParameters params, Coin value,
|
public static Transaction[] createFakeTx(NetworkParameters params, Coin value,
|
||||||
LegacyAddress to, LegacyAddress from) {
|
Address to, Address from) {
|
||||||
// Create fake TXes of sufficient realism to exercise the unit tests. This transaction send BTC from the
|
// Create fake TXes of sufficient realism to exercise the unit tests. This transaction send BTC from the
|
||||||
// from address, to the to address with to one to somewhere else to simulate change.
|
// from address, to the to address with to one to somewhere else to simulate change.
|
||||||
Transaction t = new Transaction(params);
|
Transaction t = new Transaction(params);
|
||||||
@@ -200,7 +216,7 @@ public class FakeTxBuilder {
|
|||||||
* Creates two transactions that spend the same (fake) output. t1 spends to "to". t2 spends somewhere else.
|
* Creates two transactions that spend the same (fake) output. t1 spends to "to". t2 spends somewhere else.
|
||||||
* The fake output goes to the same address as t2.
|
* The fake output goes to the same address as t2.
|
||||||
*/
|
*/
|
||||||
public static DoubleSpends createFakeDoubleSpendTxns(NetworkParameters params, LegacyAddress to) {
|
public static DoubleSpends createFakeDoubleSpendTxns(NetworkParameters params, Address to) {
|
||||||
DoubleSpends doubleSpends = new DoubleSpends();
|
DoubleSpends doubleSpends = new DoubleSpends();
|
||||||
Coin value = COIN;
|
Coin value = COIN;
|
||||||
LegacyAddress someBadGuy = LegacyAddress.fromKey(params, new ECKey());
|
LegacyAddress someBadGuy = LegacyAddress.fromKey(params, new ECKey());
|
||||||
@@ -290,7 +306,7 @@ public class FakeTxBuilder {
|
|||||||
return createFakeBlock(blockStore, Block.BLOCK_VERSION_GENESIS, Utils.currentTimeSeconds(), 0, transactions);
|
return createFakeBlock(blockStore, Block.BLOCK_VERSION_GENESIS, Utils.currentTimeSeconds(), 0, transactions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Block makeSolvedTestBlock(BlockStore blockStore, LegacyAddress coinsTo) throws BlockStoreException {
|
public static Block makeSolvedTestBlock(BlockStore blockStore, Address coinsTo) throws BlockStoreException {
|
||||||
Block b = blockStore.getChainHead().getHeader().createNextBlock(coinsTo);
|
Block b = blockStore.getChainHead().getHeader().createNextBlock(coinsTo);
|
||||||
b.solve();
|
b.solve();
|
||||||
return b;
|
return b;
|
||||||
@@ -307,7 +323,7 @@ public class FakeTxBuilder {
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Block makeSolvedTestBlock(Block prev, LegacyAddress to, Transaction... transactions) throws BlockStoreException {
|
public static Block makeSolvedTestBlock(Block prev, Address to, Transaction... transactions) throws BlockStoreException {
|
||||||
Block b = prev.createNextBlock(to);
|
Block b = prev.createNextBlock(to);
|
||||||
// Coinbase tx already exists.
|
// Coinbase tx already exists.
|
||||||
for (Transaction tx : transactions) {
|
for (Transaction tx : transactions) {
|
||||||
|
@@ -680,7 +680,7 @@ public class WalletTool {
|
|||||||
|
|
||||||
static class OutputSpec {
|
static class OutputSpec {
|
||||||
public final Coin value;
|
public final Coin value;
|
||||||
public final LegacyAddress addr;
|
public final Address addr;
|
||||||
public final ECKey key;
|
public final ECKey key;
|
||||||
|
|
||||||
public OutputSpec(String spec) throws IllegalArgumentException {
|
public OutputSpec(String spec) throws IllegalArgumentException {
|
||||||
@@ -700,7 +700,7 @@ public class WalletTool {
|
|||||||
addr = null;
|
addr = null;
|
||||||
} else {
|
} else {
|
||||||
// Treat as an address.
|
// Treat as an address.
|
||||||
addr = LegacyAddress.fromBase58(params, destination);
|
addr = Address.fromString(params, destination);
|
||||||
key = null;
|
key = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -38,6 +38,7 @@ Usage: wallet-tool --flags action-name
|
|||||||
You can repeat --output=address:value multiple times.
|
You can repeat --output=address:value multiple times.
|
||||||
There is a magic value ALL which empties the wallet to that address, e.g.:
|
There is a magic value ALL which empties the wallet to that address, e.g.:
|
||||||
--output=1GthXFQMktFLWdh5EPNGqbq3H6WdG8zsWj:ALL
|
--output=1GthXFQMktFLWdh5EPNGqbq3H6WdG8zsWj:ALL
|
||||||
|
The output destination can also be a native segwit address.
|
||||||
If the output destination starts with 04 and is 65 or 33 bytes long it will be
|
If the output destination starts with 04 and is 65 or 33 bytes long it will be
|
||||||
treated as a public key instead of an address and the send will use
|
treated as a public key instead of an address and the send will use
|
||||||
<key> CHECKSIG as the script.
|
<key> CHECKSIG as the script.
|
||||||
|
Reference in New Issue
Block a user