mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-03-10 09:20:04 +01:00
Validate P2SH in Script.correctlySpends
This commit is contained in:
parent
69f441b6c7
commit
050d70cf15
2 changed files with 25 additions and 5 deletions
|
@ -113,7 +113,7 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
|
||||||
LinkedList<StoredTransactionOutput> txOutsSpent = new LinkedList<StoredTransactionOutput>();
|
LinkedList<StoredTransactionOutput> txOutsSpent = new LinkedList<StoredTransactionOutput>();
|
||||||
LinkedList<StoredTransactionOutput> txOutsCreated = new LinkedList<StoredTransactionOutput>();
|
LinkedList<StoredTransactionOutput> txOutsCreated = new LinkedList<StoredTransactionOutput>();
|
||||||
long sigOps = 0;
|
long sigOps = 0;
|
||||||
boolean enforceBIP16 = block.getTimeSeconds() >= params.BIP16_ENFORCE_TIME;
|
final boolean enforceBIP16 = block.getTimeSeconds() >= params.BIP16_ENFORCE_TIME;
|
||||||
|
|
||||||
if (scriptVerificationExecutor.isShutdown())
|
if (scriptVerificationExecutor.isShutdown())
|
||||||
scriptVerificationExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
scriptVerificationExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
||||||
|
@ -200,7 +200,7 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
|
||||||
FutureTask<VerificationException> future = new FutureTask<VerificationException>(new Callable<VerificationException>() {
|
FutureTask<VerificationException> future = new FutureTask<VerificationException>(new Callable<VerificationException>() {
|
||||||
public VerificationException call() {
|
public VerificationException call() {
|
||||||
try{
|
try{
|
||||||
scriptSig.correctlySpends(txCache, currentIndex, scriptPubKey);
|
scriptSig.correctlySpends(txCache, currentIndex, scriptPubKey, enforceBIP16);
|
||||||
} catch (ScriptException e) {
|
} catch (ScriptException e) {
|
||||||
return new VerificationException("Error verifying script: " + e.getMessage());
|
return new VerificationException("Error verifying script: " + e.getMessage());
|
||||||
} catch (VerificationException e) {
|
} catch (VerificationException e) {
|
||||||
|
@ -292,7 +292,7 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
|
||||||
LinkedList<StoredTransactionOutput> txOutsSpent = new LinkedList<StoredTransactionOutput>();
|
LinkedList<StoredTransactionOutput> txOutsSpent = new LinkedList<StoredTransactionOutput>();
|
||||||
LinkedList<StoredTransactionOutput> txOutsCreated = new LinkedList<StoredTransactionOutput>();
|
LinkedList<StoredTransactionOutput> txOutsCreated = new LinkedList<StoredTransactionOutput>();
|
||||||
long sigOps = 0;
|
long sigOps = 0;
|
||||||
boolean enforcePayToScriptHash = newBlock.getHeader().getTimeSeconds() >= params.BIP16_ENFORCE_TIME;
|
final boolean enforcePayToScriptHash = newBlock.getHeader().getTimeSeconds() >= params.BIP16_ENFORCE_TIME;
|
||||||
if (!params.isCheckpoint(newBlock.getHeight())) {
|
if (!params.isCheckpoint(newBlock.getHeight())) {
|
||||||
for(StoredTransaction tx : transactions) {
|
for(StoredTransaction tx : transactions) {
|
||||||
Sha256Hash hash = tx.getHash();
|
Sha256Hash hash = tx.getHash();
|
||||||
|
@ -356,7 +356,7 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
|
||||||
FutureTask<VerificationException> future = new FutureTask<VerificationException>(new Callable<VerificationException>() {
|
FutureTask<VerificationException> future = new FutureTask<VerificationException>(new Callable<VerificationException>() {
|
||||||
public VerificationException call() {
|
public VerificationException call() {
|
||||||
try{
|
try{
|
||||||
scriptSig.correctlySpends(txCache, currentIndex, scriptPubKey);
|
scriptSig.correctlySpends(txCache, currentIndex, scriptPubKey, enforcePayToScriptHash);
|
||||||
} catch (ScriptException e) {
|
} catch (ScriptException e) {
|
||||||
return new VerificationException("Error verifying script: " + e.getMessage());
|
return new VerificationException("Error verifying script: " + e.getMessage());
|
||||||
} catch (VerificationException e) {
|
} catch (VerificationException e) {
|
||||||
|
|
|
@ -1479,13 +1479,16 @@ 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
|
||||||
* @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) throws VerificationException, ScriptException {
|
public void correctlySpends(Transaction txContainingThis, long index, Script scriptPubKey, boolean enforceP2SH) throws VerificationException, 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;
|
||||||
|
|
||||||
executeScript(txContainingThis, index, this, stack);
|
executeScript(txContainingThis, index, this, stack);
|
||||||
|
if (enforceP2SH)
|
||||||
|
p2shStack = new LinkedList<byte[]>(stack);
|
||||||
executeScript(txContainingThis, index, scriptPubKey, stack);
|
executeScript(txContainingThis, index, scriptPubKey, stack);
|
||||||
|
|
||||||
if (stack.size() == 0)
|
if (stack.size() == 0)
|
||||||
|
@ -1493,5 +1496,22 @@ public class Script {
|
||||||
|
|
||||||
if (!castToBool(stack.pollLast()))
|
if (!castToBool(stack.pollLast()))
|
||||||
throw new VerificationException("Script resulted in a non-true stack");
|
throw new VerificationException("Script resulted in a non-true stack");
|
||||||
|
|
||||||
|
if(enforceP2SH && scriptPubKey.isPayToScriptHash()) {
|
||||||
|
for (ScriptChunk chunk : chunks)
|
||||||
|
if (chunk.isOpCode && (chunk.data[0] & 0xff) > OP_16)
|
||||||
|
throw new VerificationException("Attempted to spend a P2SH scriptPubKey with a script that contained script ops");
|
||||||
|
|
||||||
|
byte[] scriptPubKeyBytes = p2shStack.pollLast();
|
||||||
|
Script scriptPubKeyP2SH = new Script(params, scriptPubKeyBytes, 0, scriptPubKeyBytes.length);
|
||||||
|
|
||||||
|
executeScript(txContainingThis, index, scriptPubKeyP2SH, p2shStack);
|
||||||
|
|
||||||
|
if (p2shStack.size() == 0)
|
||||||
|
throw new VerificationException("P2SH stack empty at end of script execution.");
|
||||||
|
|
||||||
|
if (!castToBool(p2shStack.pollLast()))
|
||||||
|
throw new VerificationException("P2SH script execution resulted in a non-true stack");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue