mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-15 11:45:51 +00:00
Be aware of opt-in full replace-by-fee.
This commit is contained in:
parent
ee1aa05460
commit
786a11187e
@ -24,6 +24,8 @@ import org.bitcoinj.script.ScriptBuilder;
|
|||||||
import org.bitcoinj.script.ScriptOpCodes;
|
import org.bitcoinj.script.ScriptOpCodes;
|
||||||
import org.bitcoinj.utils.ExchangeRate;
|
import org.bitcoinj.utils.ExchangeRate;
|
||||||
import org.bitcoinj.wallet.WalletTransaction.Pool;
|
import org.bitcoinj.wallet.WalletTransaction.Pool;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.primitives.Ints;
|
import com.google.common.primitives.Ints;
|
||||||
import com.google.common.primitives.Longs;
|
import com.google.common.primitives.Longs;
|
||||||
@ -641,6 +643,9 @@ public class Transaction extends ChildMessage {
|
|||||||
}
|
}
|
||||||
s.append(String.format(Locale.US, " time locked until %s%n", time));
|
s.append(String.format(Locale.US, " time locked until %s%n", time));
|
||||||
}
|
}
|
||||||
|
if (isOptInFullRBF()) {
|
||||||
|
s.append(" opts into full replace-by-fee%n");
|
||||||
|
}
|
||||||
if (inputs.size() == 0) {
|
if (inputs.size() == 0) {
|
||||||
s.append(String.format(Locale.US, " INCOMPLETE: No inputs!%n"));
|
s.append(String.format(Locale.US, " INCOMPLETE: No inputs!%n"));
|
||||||
return s.toString();
|
return s.toString();
|
||||||
@ -680,6 +685,10 @@ public class Transaction extends ChildMessage {
|
|||||||
s.append(Utils.HEX.encode(scriptPubKey.getPubKeyHash()));
|
s.append(Utils.HEX.encode(scriptPubKey.getPubKeyHash()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
String flags = Joiner.on(", ").skipNulls().join(in.hasSequence() ? "has sequence" : null,
|
||||||
|
in.isOptInFullRBF() ? "opts into full RBF" : null);
|
||||||
|
if (!flags.isEmpty())
|
||||||
|
s.append("\n (").append(flags).append(')');
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
s.append("[exception: ").append(e.getMessage()).append("]");
|
s.append("[exception: ").append(e.getMessage()).append("]");
|
||||||
}
|
}
|
||||||
@ -1281,6 +1290,17 @@ public class Transaction extends ChildMessage {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this transaction will opt into the
|
||||||
|
* <a href="https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki">full replace-by-fee </a> semantics.
|
||||||
|
*/
|
||||||
|
public boolean isOptInFullRBF() {
|
||||||
|
for (TransactionInput input : getInputs())
|
||||||
|
if (input.isOptInFullRBF())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Returns true if this transaction is considered finalized and can be placed in a block. Non-finalized
|
* <p>Returns true if this transaction is considered finalized and can be placed in a block. Non-finalized
|
||||||
* transactions won't be included by miners and can be replaced with newer versions using sequence numbers.
|
* transactions won't be included by miners and can be replaced with newer versions using sequence numbers.
|
||||||
|
@ -21,6 +21,8 @@ import org.bitcoinj.script.Script;
|
|||||||
import org.bitcoinj.wallet.DefaultRiskAnalysis;
|
import org.bitcoinj.wallet.DefaultRiskAnalysis;
|
||||||
import org.bitcoinj.wallet.KeyBag;
|
import org.bitcoinj.wallet.KeyBag;
|
||||||
import org.bitcoinj.wallet.RedeemData;
|
import org.bitcoinj.wallet.RedeemData;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -46,7 +48,7 @@ public class TransactionInput extends ChildMessage {
|
|||||||
// Magic outpoint index that indicates the input is in fact unconnected.
|
// Magic outpoint index that indicates the input is in fact unconnected.
|
||||||
private static final long UNCONNECTED = 0xFFFFFFFFL;
|
private static final long UNCONNECTED = 0xFFFFFFFFL;
|
||||||
|
|
||||||
// Allows for altering transactions after they were broadcast.
|
// Allows for altering transactions after they were broadcast. Values below NO_SEQUENCE-1 mean it can be altered.
|
||||||
private long sequence;
|
private long sequence;
|
||||||
// Data needed to connect to the output of the transaction we're gathering coins from.
|
// Data needed to connect to the output of the transaction we're gathering coins from.
|
||||||
private TransactionOutPoint outpoint;
|
private TransactionOutPoint outpoint;
|
||||||
@ -259,18 +261,6 @@ public class TransactionInput extends ChildMessage {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a human readable debug string.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
try {
|
|
||||||
return isCoinBase() ? "TxIn: COINBASE" : "TxIn for [" + outpoint + "]: " + getScriptSig();
|
|
||||||
} catch (ScriptException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ConnectionResult {
|
public enum ConnectionResult {
|
||||||
NO_SUCH_TX,
|
NO_SUCH_TX,
|
||||||
ALREADY_SPENT,
|
ALREADY_SPENT,
|
||||||
@ -385,6 +375,14 @@ public class TransactionInput extends ChildMessage {
|
|||||||
return sequence != NO_SEQUENCE;
|
return sequence != NO_SEQUENCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this input will cause a transaction to opt into the
|
||||||
|
* <a href="https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki">full replace-by-fee </a> semantics.
|
||||||
|
*/
|
||||||
|
public boolean isOptInFullRBF() {
|
||||||
|
return sequence < NO_SEQUENCE - 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For a connected transaction, runs the script against the connected pubkey and verifies they are correct.
|
* For a connected transaction, runs the script against the connected pubkey and verifies they are correct.
|
||||||
* @throws ScriptException if the script did not verify.
|
* @throws ScriptException if the script did not verify.
|
||||||
@ -467,4 +465,26 @@ public class TransactionInput extends ChildMessage {
|
|||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hashCode(sequence, outpoint, Arrays.hashCode(scriptBytes));
|
return Objects.hashCode(sequence, outpoint, Arrays.hashCode(scriptBytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a human readable debug string.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder s = new StringBuilder("TxIn");
|
||||||
|
try {
|
||||||
|
if (isCoinBase()) {
|
||||||
|
s.append(": COINBASE");
|
||||||
|
} else {
|
||||||
|
s.append(" for [").append(outpoint).append("]: ").append(getScriptSig());
|
||||||
|
String flags = Joiner.on(", ").skipNulls().join(hasSequence() ? "has sequence" : null,
|
||||||
|
isOptInFullRBF() ? "opts into full RBF" : null);
|
||||||
|
if (!flags.isEmpty())
|
||||||
|
s.append(" (").append(flags).append(')');
|
||||||
|
}
|
||||||
|
return s.toString();
|
||||||
|
} catch (ScriptException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -403,4 +403,14 @@ public class TransactionTest {
|
|||||||
final Transaction transaction = PARAMS.getDefaultSerializer().makeTransaction(transactionBytes);
|
final Transaction transaction = PARAMS.getDefaultSerializer().makeTransaction(transactionBytes);
|
||||||
transaction.checkCoinBaseHeight(height);
|
transaction.checkCoinBaseHeight(height);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Test
|
||||||
|
public void optInFullRBF() {
|
||||||
|
// a standard transaction as wallets would create
|
||||||
|
Transaction tx = FakeTxBuilder.createFakeTx(PARAMS);
|
||||||
|
assertFalse(tx.isOptInFullRBF());
|
||||||
|
|
||||||
|
tx.getInputs().get(0).setSequenceNumber(TransactionInput.NO_SEQUENCE - 2);
|
||||||
|
assertTrue(tx.isOptInFullRBF());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user