mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-07 06:44:16 +00:00
Add a TransactionInput.verify() method that checks signatures and use it from the basicSpending test to ensure we generate valid signatures/scripts.
This commit is contained in:
parent
2f0d4cdbd8
commit
671a5aec18
@ -875,7 +875,8 @@ public class Script {
|
|||||||
return Utils.decodeMPI(Utils.reverseBytes(chunk), false);
|
return Utils.decodeMPI(Utils.reverseBytes(chunk), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void executeScript(Transaction txContainingThis, long index, Script script, LinkedList<byte[]> stack) throws ScriptException {
|
private static void executeScript(Transaction txContainingThis, long index,
|
||||||
|
Script script, LinkedList<byte[]> stack) throws ScriptException {
|
||||||
int opCount = 0;
|
int opCount = 0;
|
||||||
int lastCodeSepLocation = 0;
|
int lastCodeSepLocation = 0;
|
||||||
|
|
||||||
@ -1479,19 +1480,24 @@ public class Script {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies that this script (interpreted as a scriptSig) correctly spends the given scriptPubKey.
|
* Verifies that this script (interpreted as a scriptSig) correctly spends the given scriptPubKey.
|
||||||
|
* @param txContainingThis The transaction in which this input scriptSig resides.
|
||||||
|
* @param scriptSigIndex The index in txContainingThis of the scriptSig (note: NOT the index of the scriptPubKey).
|
||||||
|
* @param scriptPubKey The connected scriptPubKey containing the conditions needed to claim the value.
|
||||||
|
* @param enforceP2SH Whether "pay to script hash" rules should be enforced. If in doubt, set to true.
|
||||||
* @throws VerificationException if this script does not correctly spend the scriptPubKey
|
* @throws VerificationException if this script does not correctly spend the scriptPubKey
|
||||||
*/
|
*/
|
||||||
public void correctlySpends(Transaction txContainingThis, long index, Script scriptPubKey, boolean enforceP2SH) throws ScriptException {
|
public void correctlySpends(Transaction txContainingThis, long scriptSigIndex, Script scriptPubKey,
|
||||||
|
boolean enforceP2SH) throws ScriptException {
|
||||||
if (program.length > 10000 || scriptPubKey.program.length > 10000)
|
if (program.length > 10000 || scriptPubKey.program.length > 10000)
|
||||||
throw new ScriptException("Script larger than 10,000 bytes");
|
throw new ScriptException("Script larger than 10,000 bytes");
|
||||||
|
|
||||||
LinkedList<byte[]> stack = new LinkedList<byte[]>();
|
LinkedList<byte[]> stack = new LinkedList<byte[]>();
|
||||||
LinkedList<byte[]> p2shStack = null;
|
LinkedList<byte[]> p2shStack = null;
|
||||||
|
|
||||||
executeScript(txContainingThis, index, this, stack);
|
executeScript(txContainingThis, scriptSigIndex, this, stack);
|
||||||
if (enforceP2SH)
|
if (enforceP2SH)
|
||||||
p2shStack = new LinkedList<byte[]>(stack);
|
p2shStack = new LinkedList<byte[]>(stack);
|
||||||
executeScript(txContainingThis, index, scriptPubKey, stack);
|
executeScript(txContainingThis, scriptSigIndex, scriptPubKey, stack);
|
||||||
|
|
||||||
if (stack.size() == 0)
|
if (stack.size() == 0)
|
||||||
throw new ScriptException("Stack empty at end of script execution.");
|
throw new ScriptException("Stack empty at end of script execution.");
|
||||||
@ -1520,7 +1526,7 @@ public class Script {
|
|||||||
byte[] scriptPubKeyBytes = p2shStack.pollLast();
|
byte[] scriptPubKeyBytes = p2shStack.pollLast();
|
||||||
Script scriptPubKeyP2SH = new Script(params, scriptPubKeyBytes, 0, scriptPubKeyBytes.length);
|
Script scriptPubKeyP2SH = new Script(params, scriptPubKeyBytes, 0, scriptPubKeyBytes.length);
|
||||||
|
|
||||||
executeScript(txContainingThis, index, scriptPubKeyP2SH, p2shStack);
|
executeScript(txContainingThis, scriptSigIndex, scriptPubKeyP2SH, p2shStack);
|
||||||
|
|
||||||
if (p2shStack.size() == 0)
|
if (p2shStack.size() == 0)
|
||||||
throw new ScriptException("P2SH stack empty at end of script execution.");
|
throw new ScriptException("P2SH stack empty at end of script execution.");
|
||||||
|
@ -340,4 +340,17 @@ public class TransactionInput extends ChildMessage implements Serializable {
|
|||||||
public boolean hasSequence() {
|
public boolean hasSequence() {
|
||||||
return sequence != NO_SEQUENCE;
|
return sequence != NO_SEQUENCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For a connected transaction, runs the script against the connected pubkey and verifies they are correct.
|
||||||
|
* @throws ScriptException if the script did not verify.
|
||||||
|
*/
|
||||||
|
public void verify() throws ScriptException {
|
||||||
|
Preconditions.checkNotNull(getOutpoint().fromTx, "Not connected");
|
||||||
|
long spendingIndex = getOutpoint().getIndex();
|
||||||
|
Script pubKey = getOutpoint().fromTx.getOutputs().get((int) spendingIndex).getScriptPubKey();
|
||||||
|
Script sig = getScriptSig();
|
||||||
|
int myIndex = parentTransaction.getInputs().indexOf(this);
|
||||||
|
sig.correctlySpends(parentTransaction, myIndex, pubKey, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,8 +89,8 @@ public class WalletTest {
|
|||||||
assertEquals(destination, t2.getOutputs().get(0).getScriptPubKey().getToAddress());
|
assertEquals(destination, t2.getOutputs().get(0).getScriptPubKey().getToAddress());
|
||||||
assertEquals(wallet.getChangeAddress(), t2.getOutputs().get(1).getScriptPubKey().getToAddress());
|
assertEquals(wallet.getChangeAddress(), t2.getOutputs().get(1).getScriptPubKey().getToAddress());
|
||||||
assertEquals(toNanoCoins(0, 49), t2.getOutputs().get(1).getValue());
|
assertEquals(toNanoCoins(0, 49), t2.getOutputs().get(1).getValue());
|
||||||
|
// Check the script runs and signatures verify.
|
||||||
// We have NOT proven that the signature is correct!
|
t2.getInputs().get(0).verify();
|
||||||
|
|
||||||
final LinkedList<Transaction> txns = Lists.newLinkedList();
|
final LinkedList<Transaction> txns = Lists.newLinkedList();
|
||||||
wallet.addEventListener(new AbstractWalletEventListener() {
|
wallet.addEventListener(new AbstractWalletEventListener() {
|
||||||
|
Loading…
Reference in New Issue
Block a user