Skip to content
This repository has been archived by the owner on Feb 15, 2024. It is now read-only.

Commit

Permalink
script: implement OP_IF and friends, OP_RIPEMD160, OP_TUCK
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeff Garzik authored and Jeff Garzik committed Aug 6, 2012
1 parent 886d26f commit 639d8ca
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 39 deletions.
111 changes: 77 additions & 34 deletions bitcoin/scripteval.py
Expand Up @@ -7,7 +7,7 @@
#

from serialize import Hash, Hash160, ser_uint256, ser_uint160
from Crypto.Hash import SHA256
from Crypto.Hash import SHA256, RIPEMD160
from script import *
from core import CTxOut, CTransaction
from key import CKey
Expand Down Expand Up @@ -278,53 +278,62 @@ def BinOp(opcode, stack):

return True

def CheckExec(vfExec):
for b in vfExec:
if not b:
return False
return True

def EvalScript(stack, scriptIn, txTo, inIdx, hashtype):
altstack = []
vfExec = []
script = CScript(scriptIn)
while script.pc < script.pend:
if not script.getop():
return False
sop = script.sop

if sop.op <= OP_PUSHDATA4:
fExec = CheckExec(vfExec)

if fExec and sop.op <= OP_PUSHDATA4:
stack.append(sop.data)
continue

elif sop.op == OP_1NEGATE or ((sop.op >= OP_1) and (sop.op <= OP_16)):
elif fExec and sop.op == OP_1NEGATE or ((sop.op >= OP_1) and (sop.op <= OP_16)):
v = sop.op - (OP_1 - 1)
stack.append(bn2vch(v))

elif sop.op in ISA_BINOP:
elif fExec and sop.op in ISA_BINOP:
if not BinOp(sop.op, stack):
return False

elif sop.op in ISA_UNOP:
elif fExec and sop.op in ISA_UNOP:
if not UnaryOp(sop.op, stack):
return False

elif sop.op == OP_2DROP:
elif fExec and sop.op == OP_2DROP:
if len(stack) < 2:
return False
stack.pop()
stack.pop()

elif sop.op == OP_2DUP:
elif fExec and sop.op == OP_2DUP:
if len(stack) < 2:
return False
v1 = stack[-2]
v2 = stack[-1]
stack.append(v1)
stack.append(v2)

elif sop.op == OP_2OVER:
elif fExec and sop.op == OP_2OVER:
if len(stack) < 4:
return False
v1 = stack[-4]
v2 = stack[-3]
stack.append(v1)
stack.append(v2)

elif sop.op == OP_2SWAP:
elif fExec and sop.op == OP_2SWAP:
if len(stack) < 4:
return False
tmp = stack[-4]
Expand All @@ -335,7 +344,7 @@ def EvalScript(stack, scriptIn, txTo, inIdx, hashtype):
stack[-3] = stack[-1]
stack[-1] = tmp

elif sop.op == OP_3DUP:
elif fExec and sop.op == OP_3DUP:
if len(stack) < 3:
return False
v1 = stack[-3]
Expand All @@ -345,14 +354,14 @@ def EvalScript(stack, scriptIn, txTo, inIdx, hashtype):
stack.append(v2)
stack.append(v3)

elif sop.op == OP_CHECKMULTISIG or sop.op == OP_CHECKMULTISIGVERIFY:
elif fExec and sop.op == OP_CHECKMULTISIG or sop.op == OP_CHECKMULTISIGVERIFY:
tmpScript = CScript(script.vch[script.pbegincodehash:script.pend])
ok = CheckMultiSig(sop.op, tmpScript, stack, txTo,
inIdx, hashtype)
if not ok:
return False

elif sop.op == OP_CHECKSIG or sop.op == OP_CHECKSIGVERIFY:
elif fExec and sop.op == OP_CHECKSIG or sop.op == OP_CHECKSIGVERIFY:
if len(stack) < 2:
return False
vchPubKey = stack.pop()
Expand All @@ -371,25 +380,35 @@ def EvalScript(stack, scriptIn, txTo, inIdx, hashtype):
return False
stack.append("\x00")

elif sop.op == OP_CODESEPARATOR:
elif fExec and sop.op == OP_CODESEPARATOR:
script.pbegincodehash = script.pc

elif sop.op == OP_DEPTH:
elif fExec and sop.op == OP_DEPTH:
bn = len(stack)
stack.append(bn2vch(bn))

elif sop.op == OP_DROP:
elif fExec and sop.op == OP_DROP:
if len(stack) < 1:
return False
stack.pop()

elif sop.op == OP_DUP:
elif fExec and sop.op == OP_DUP:
if len(stack) < 1:
return False
v = stack[-1]
stack.append(v)

elif sop.op == OP_EQUAL or sop.op == OP_EQUALVERIFY:
elif sop.op == OP_ELSE:
if len(vfExec) == 0:
return false
vfExec[-1] = not vfExec[-1]

elif sop.op == OP_ENDIF:
if len(vfExec) == 0:
return false
vfExec.pop()

elif fExec and sop.op == OP_EQUAL or sop.op == OP_EQUALVERIFY:
if len(stack) < 2:
return False
v1 = stack.pop()
Expand All @@ -407,44 +426,57 @@ def EvalScript(stack, scriptIn, txTo, inIdx, hashtype):
else:
return False

elif sop.op == OP_FROMALTSTACK:
elif fExec and sop.op == OP_FROMALTSTACK:
if len(altstack) < 1:
return False
v = altstack.pop()
stack.append(v)

elif sop.op == OP_HASH160:
elif fExec and sop.op == OP_HASH160:
if len(stack) < 1:
return False
stack.append(ser_uint160(Hash160(stack.pop())))

elif sop.op == OP_HASH256:
elif fExec and sop.op == OP_HASH256:
if len(stack) < 1:
return False
stack.append(ser_uint256(Hash(stack.pop())))

elif sop.op == OP_IFDUP:
elif sop.op == OP_IF or sop.op == OP_NOTIF:
val = False

if fExec:
if len(stack) < 1:
return False
vch = stack.pop()
val = CastToBool(vch)
if sop.op == OP_NOTIF:
val = not val

vfExec.append(val)

elif fExec and sop.op == OP_IFDUP:
if len(stack) < 1:
return False
vch = stack[-1]
if CastToBool(vch):
stack.append(vch)

elif sop.op == OP_NIP:
elif fExec and sop.op == OP_NIP:
if len(stack) < 2:
return False
del stack[-2]

elif sop.op == OP_NOP or (sop.op >= OP_NOP1 and sop.op <= OP_NOP10):
elif fExec and sop.op == OP_NOP or (sop.op >= OP_NOP1 and sop.op <= OP_NOP10):
pass

elif sop.op == OP_OVER:
elif fExec and sop.op == OP_OVER:
if len(stack) < 2:
return False
vch = stack[-2]
stack.append(vch)

elif sop.op == OP_PICK or sop.op == OP_ROLL:
elif fExec and sop.op == OP_PICK or sop.op == OP_ROLL:
if len(stack) < 2:
return False
n = CastToBigNum(stack.pop())
Expand All @@ -455,10 +487,15 @@ def EvalScript(stack, scriptIn, txTo, inIdx, hashtype):
del stack[-n-1]
stack.append(vch)

elif sop.op == OP_RETURN:
elif fExec and sop.op == OP_RETURN:
return False

elif sop.op == OP_ROT:
elif fExec and sop.op == OP_RIPEMD160:
if len(stack) < 1:
return False
stack.append(RIPEMD160.new(stack.pop()).digest())

elif fExec and sop.op == OP_ROT:
if len(stack) < 3:
return False
tmp = stack[-3]
Expand All @@ -469,31 +506,37 @@ def EvalScript(stack, scriptIn, txTo, inIdx, hashtype):
stack[-2] = stack[-1]
stack[-1] = tmp

elif sop.op == OP_SIZE:
elif fExec and sop.op == OP_SIZE:
if len(stack) < 1:
return False
bn = len(stack[-1])
stack.append(bn2vch(bn))

elif sop.op == OP_SHA256:
elif fExec and sop.op == OP_SHA256:
if len(stack) < 1:
return False
stack.append(SHA256.new(stack.pop()).digest())

elif sop.op == OP_SWAP:
elif fExec and sop.op == OP_SWAP:
if len(stack) < 2:
return False
tmp = stack[-2]
stack[-2] = stack[-1]
stack[-1] = tmp

elif sop.op == OP_TOALTSTACK:
elif fExec and sop.op == OP_TOALTSTACK:
if len(stack) < 1:
return False
v = stack.pop()
altstack.append(v)

elif sop.op == OP_VERIFY:
elif fExec and sop.op == OP_TUCK:
if len(stack) < 2:
return False
vch = stack[-1]
stack.insert(len(stack) - 2, vch)

elif fExec and sop.op == OP_VERIFY:
if len(stack) < 1:
return False
v = CastToBool(stack[-1])
Expand All @@ -502,7 +545,7 @@ def EvalScript(stack, scriptIn, txTo, inIdx, hashtype):
else:
return False

elif sop.op == OP_WITHIN:
elif fExec and sop.op == OP_WITHIN:
if len(stack) < 3:
return False
bn3 = CastToBigNum(stack.pop())
Expand All @@ -514,7 +557,7 @@ def EvalScript(stack, scriptIn, txTo, inIdx, hashtype):
else:
stack.append("\x00")

else:
elif fExec:
print "Unsupported opcode", OPCODE_NAMES[sop.op]
return False

Expand Down
5 changes: 0 additions & 5 deletions testscript.py
Expand Up @@ -58,11 +58,6 @@
opcount = {}

SKIP_TX = {
# testnet3 transactions
0x9aa3a5a6d9b7d1ac9555be8e42596d06686cc5f76d259b06c560a207d310d5f5L : True,
0xc5d4b73af6eed28798473b05d2b227edd4f285069629843e899b52c2d1c165b7L : True,
0xe335562f7e297aadeed88e5954bc4eeb8dc00b31d829eedb232e39d672b0c009L : True,
0x74ea059a63c7ebddaee6805e1560b15c937d99a9ee9745412cbc6d2a0a5f5305L : True,
}


Expand Down

0 comments on commit 639d8ca

Please sign in to comment.