mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-01-31 15:22:16 +00:00
Married wallets: extending fee calculation
This commit is contained in:
parent
fd0c6a27f4
commit
12bfa5f5ee
@ -491,7 +491,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
|
|||||||
|
|
||||||
/** Returns the address used for change outputs. Note: this will probably go away in future. */
|
/** Returns the address used for change outputs. Note: this will probably go away in future. */
|
||||||
public Address getChangeAddress() {
|
public Address getChangeAddress() {
|
||||||
return currentKey(KeyChain.KeyPurpose.CHANGE).toAddress(params);
|
return keychain.currentAddress(KeyChain.KeyPurpose.CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3895,14 +3895,17 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
|
|||||||
int size = 0;
|
int size = 0;
|
||||||
for (TransactionOutput output : selection.gathered) {
|
for (TransactionOutput output : selection.gathered) {
|
||||||
try {
|
try {
|
||||||
if (output.getScriptPubKey().isSentToAddress()) {
|
Script script = output.getScriptPubKey();
|
||||||
// Send-to-address spends usually take maximum pubkey.length (as it may be compressed or not) + 75 bytes
|
ECKey key = null;
|
||||||
final ECKey key = findKeyFromPubHash(output.getScriptPubKey().getPubKeyHash());
|
Script redeemScript = null;
|
||||||
size += checkNotNull(key, "Coin selection includes unspendable outputs").getPubKey().length + 75;
|
if (script.isSentToAddress()) {
|
||||||
} else if (output.getScriptPubKey().isSentToRawPubKey())
|
key = findKeyFromPubHash(script.getPubKeyHash());
|
||||||
size += 74; // Send-to-pubkey spends usually take maximum 74 bytes to spend
|
checkNotNull(key, "Coin selection includes unspendable outputs");
|
||||||
else
|
} else if (script.isPayToScriptHash()) {
|
||||||
throw new IllegalStateException("Unknown output type returned in coin selection");
|
redeemScript = keychain.findRedeemScriptFromPubHash(script.getPubKeyHash());
|
||||||
|
checkNotNull(redeemScript, "Coin selection includes unspendable outputs");
|
||||||
|
}
|
||||||
|
size += script.getNumberOfBytesRequiredToSpend(key, redeemScript);
|
||||||
} catch (ScriptException e) {
|
} catch (ScriptException e) {
|
||||||
// If this happens it means an output script in a wallet tx could not be understood. That should never
|
// If this happens it means an output script in a wallet tx could not be understood. That should never
|
||||||
// happen, if it does it means the wallet has got into an inconsistent state.
|
// happen, if it does it means the wallet has got into an inconsistent state.
|
||||||
|
@ -25,6 +25,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.spongycastle.crypto.digests.RIPEMD160Digest;
|
import org.spongycastle.crypto.digests.RIPEMD160Digest;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -54,6 +55,7 @@ import static com.google.common.base.Preconditions.checkState;
|
|||||||
public class Script {
|
public class Script {
|
||||||
private static final Logger log = LoggerFactory.getLogger(Script.class);
|
private static final Logger log = LoggerFactory.getLogger(Script.class);
|
||||||
public static final long MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
|
public static final long MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
|
||||||
|
public static final int SIG_SIZE = 75;
|
||||||
|
|
||||||
// The program is a set of chunks where each element is either [opcode] or [data, data, data ...]
|
// The program is a set of chunks where each element is either [opcode] or [data, data, data ...]
|
||||||
protected List<ScriptChunk> chunks;
|
protected List<ScriptChunk> chunks;
|
||||||
@ -446,6 +448,36 @@ public class Script {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns number of bytes required to spend this script. It accepts optional ECKey and redeemScript that may
|
||||||
|
* be required for certain types of script to estimate target size.
|
||||||
|
*/
|
||||||
|
public int getNumberOfBytesRequiredToSpend(@Nullable ECKey pubKey, @Nullable Script redeemScript) {
|
||||||
|
if (isPayToScriptHash()) {
|
||||||
|
// scriptSig: <sig> [sig] [sig...] <redeemscript>
|
||||||
|
checkArgument(redeemScript != null, "P2SH script requires redeemScript to be spent");
|
||||||
|
// for N of M CHECKMULTISIG redeem script we will need N signatures to spend
|
||||||
|
ScriptChunk nChunk = redeemScript.getChunks().get(0);
|
||||||
|
int n = Script.decodeFromOpN(nChunk.opcode);
|
||||||
|
return n * SIG_SIZE + getProgram().length;
|
||||||
|
} else if (isSentToMultiSig()) {
|
||||||
|
// scriptSig: OP_0 <sig> [sig] [sig...]
|
||||||
|
// for N of M CHECKMULTISIG script we will need N signatures to spend
|
||||||
|
ScriptChunk nChunk = chunks.get(0);
|
||||||
|
int n = Script.decodeFromOpN(nChunk.opcode);
|
||||||
|
return n * SIG_SIZE + 1;
|
||||||
|
} else if (isSentToRawPubKey()) {
|
||||||
|
// scriptSig: <sig>
|
||||||
|
return SIG_SIZE;
|
||||||
|
} else if (isSentToAddress()) {
|
||||||
|
// scriptSig: <sig> <pubkey>
|
||||||
|
int uncompressedPubKeySize = 65;
|
||||||
|
return SIG_SIZE + (pubKey != null ? pubKey.getPubKey().length : uncompressedPubKeySize);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Unsupported script type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Whether or not this is a scriptPubKey representing a pay-to-script-hash output. In such outputs, the logic that
|
* <p>Whether or not this is a scriptPubKey representing a pay-to-script-hash output. In such outputs, the logic that
|
||||||
* controls reclamation is not actually in the output at all. Instead there's just a hash, and it's up to the
|
* controls reclamation is not actually in the output at all. Instead there's just a hash, and it's up to the
|
||||||
|
Loading…
Reference in New Issue
Block a user