forked from petertodd/python-bitcoinlib
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_scripteval.py
More file actions
115 lines (89 loc) · 4.04 KB
/
test_scripteval.py
File metadata and controls
115 lines (89 loc) · 4.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# Copyright (C) 2013-2017 The python-bitcoinlib developers
#
# This file is part of python-bitcoinlib.
#
# It is subject to the license terms in the LICENSE file found in the top-level
# directory of this distribution.
#
# No part of python-bitcoinlib, including this file, may be copied, modified,
# propagated, or distributed except according to the terms contained in the
# LICENSE file.
from __future__ import absolute_import, division, print_function, unicode_literals
import json
import os
import unittest
import sys
if sys.version > '3':
long = int
from binascii import unhexlify
from bitcoin.core import *
from bitcoin.core.script import *
from bitcoin.core.scripteval import *
def parse_script(s):
def ishex(s):
return set(s).issubset(set('0123456789abcdefABCDEF'))
r = []
# Create an opcodes_by_name table with both OP_ prefixed names and
# shortened ones with the OP_ dropped.
opcodes_by_name = {}
for name, code in OPCODES_BY_NAME.items():
opcodes_by_name[name] = code
opcodes_by_name[name[3:]] = code
for word in s.split():
if word.isdigit() or (word[0] == '-' and word[1:].isdigit()):
r.append(CScript([long(word)]))
elif word.startswith('0x') and ishex(word[2:]):
# Raw ex data, inserted NOT pushed onto stack:
r.append(unhexlify(word[2:].encode('utf8')))
elif len(word) >= 2 and word[0] == "'" and word[-1] == "'":
r.append(CScript([bytes(word[1:-1].encode('utf8'))]))
elif word in opcodes_by_name:
r.append(CScript([opcodes_by_name[word]]))
else:
raise ValueError("Error parsing script: %r" % s)
return CScript(b''.join(r))
def load_test_vectors(name):
with open(os.path.dirname(__file__) + '/data/' + name, 'r') as fd:
for test_case in json.load(fd):
if len(test_case) == 1:
continue # comment
if len(test_case) == 3:
test_case.append('') # add missing comment
scriptSig, scriptPubKey, flags, comment = test_case
scriptSig = parse_script(scriptSig)
scriptPubKey = parse_script(scriptPubKey)
flag_set = set()
for flag in flags.split(','):
if flag == '' or flag == 'NONE':
pass
else:
try:
flag = SCRIPT_VERIFY_FLAGS_BY_NAME[flag]
except IndexError:
raise Exception('Unknown script verify flag %r' % flag)
flag_set.add(flag)
yield (scriptSig, scriptPubKey, flag_set, comment, test_case)
class Test_EvalScript(unittest.TestCase):
def create_test_txs(self, scriptSig, scriptPubKey):
txCredit = CTransaction([CTxIn(COutPoint(), CScript([OP_0, OP_0]), nSequence=0xFFFFFFFF)],
[CTxOut(0, scriptPubKey)],
nLockTime=0)
txSpend = CTransaction([CTxIn(COutPoint(txCredit.GetTxid(), 0), scriptSig, nSequence=0xFFFFFFFF)],
[CTxOut(0, CScript())],
nLockTime=0)
return (txCredit, txSpend)
def test_script_valid(self):
for scriptSig, scriptPubKey, flags, comment, test_case in load_test_vectors('script_valid.json'):
(txCredit, txSpend) = self.create_test_txs(scriptSig, scriptPubKey)
try:
VerifyScript(scriptSig, scriptPubKey, txSpend, 0, flags)
except ValidationError as err:
self.fail('Script FAILED: %r %r %r with exception %r' % (scriptSig, scriptPubKey, comment, err))
def test_script_invalid(self):
for scriptSig, scriptPubKey, flags, comment, test_case in load_test_vectors('script_invalid.json'):
(txCredit, txSpend) = self.create_test_txs(scriptSig, scriptPubKey)
try:
VerifyScript(scriptSig, scriptPubKey, txSpend, 0, flags)
except ValidationError:
continue
self.fail('Expected %r to fail' % test_case)