]>
Commit | Line | Data |
---|---|---|
4f0da23b SS |
1 | import sys |
2 | import time | |
3 | import json | |
82e6c354 SS |
4 | import logging |
5 | import binascii | |
f5cf215f | 6 | import struct |
2b2c75de | 7 | import base64 |
4f0da23b SS |
8 | from testsupport import * |
9 | ||
10 | ||
7d937f29 SS |
11 | SCRIPT_FALSE = 'Script evaluated without error but finished with a false/empty top stack element' |
12 | ||
13 | ||
82e6c354 SS |
14 | @fanout_input(0) |
15 | def test_basic_spend(inp): | |
456c9e72 SS |
16 | spend = {'inputs': [inp], "outputs": [nospend]} |
17 | spend_txid = submit(sign(spend)) | |
18 | assert rpc.getrawtransaction(spend_txid) | |
4f0da23b | 19 | |
4f0da23b | 20 | |
82e6c354 SS |
21 | @fanout_input(1) |
22 | def test_fulfillment_wrong_signature(inp): | |
456c9e72 SS |
23 | # Set other pubkey and sign |
24 | inp['script']['fulfillment']['publicKey'] = bob_pk | |
25 | spend = {'inputs': [inp], 'outputs': [nospend]} | |
26 | signed = sign(spend) | |
82e6c354 | 27 | |
f5cf215f | 28 | # Set the correct pubkey, signature is bob's |
28658719 | 29 | signed['inputs'][0]['script']['fulfillment']['publicKey'] = alice_pk |
82e6c354 SS |
30 | |
31 | try: | |
456c9e72 | 32 | assert not submit(signed), 'should raise an error' |
82e6c354 | 33 | except RPCError as e: |
7d937f29 | 34 | assert SCRIPT_FALSE in str(e), str(e) |
82e6c354 | 35 | |
4f0da23b | 36 | |
82e6c354 SS |
37 | @fanout_input(2) |
38 | def test_fulfillment_wrong_pubkey(inp): | |
456c9e72 | 39 | spend = {'inputs': [inp], 'outputs': [nospend]} |
456c9e72 | 40 | signed = sign(spend) |
f5cf215f | 41 | |
82e6c354 | 42 | # Set the wrong pubkey, signature is correct |
28658719 | 43 | signed['inputs'][0]['script']['fulfillment']['publicKey'] = bob_pk |
82e6c354 SS |
44 | |
45 | try: | |
46 | assert not submit(signed), 'should raise an error' | |
47 | except RPCError as e: | |
7d937f29 | 48 | assert SCRIPT_FALSE in str(e), str(e) |
82e6c354 SS |
49 | |
50 | ||
51 | @fanout_input(3) | |
f5cf215f | 52 | def test_invalid_fulfillment_binary(inp): |
82e6c354 | 53 | # Create a valid script with an invalid fulfillment payload |
456c9e72 SS |
54 | inp['script'] = binascii.hexlify(b"\007invalid").decode('utf-8') |
55 | spend = {'inputs': [inp], 'outputs': [nospend]} | |
4f0da23b | 56 | |
82e6c354 | 57 | try: |
28658719 | 58 | assert not submit(spend), 'should raise an error' |
82e6c354 SS |
59 | except RPCError as e: |
60 | assert 'Crypto-Condition payload is invalid' in str(e), str(e) | |
4f0da23b | 61 | |
4f0da23b | 62 | |
f5cf215f SS |
63 | @fanout_input(4) |
64 | def test_invalid_condition(inp): | |
65 | # Create a valid output script with an invalid cryptocondition binary | |
66 | outputscript = to_hex(b"\007invalid\xcc") | |
67 | spend = {'inputs': [inp], 'outputs': [{'amount': 1000, 'script': outputscript}]} | |
68 | spend_txid = submit(sign(spend)) | |
69 | ||
70 | spend1 = { | |
71 | 'inputs': [{'txid': spend_txid, 'idx': 0, 'script': {'fulfillment': cond_alice}}], | |
72 | 'outputs': [nospend], | |
73 | } | |
74 | ||
75 | try: | |
76 | assert not submit(sign(spend1)), 'should raise an error' | |
77 | except RPCError as e: | |
7d937f29 | 78 | assert SCRIPT_FALSE in str(e), str(e) |
f5cf215f SS |
79 | |
80 | ||
db2df2c3 | 81 | @fanout_input(5) |
f5cf215f SS |
82 | def test_oversize_fulfillment(inp): |
83 | # Create oversize fulfillment script where the total length is <2000 | |
84 | binscript = b'\x4d%s%s' % (struct.pack('h', 2000), b'a' * 2000) | |
85 | inp['script'] = to_hex(binscript) | |
86 | spend = {'inputs': [inp], 'outputs': [nospend]} | |
87 | ||
88 | try: | |
28658719 | 89 | assert not submit(spend), 'should raise an error' |
f5cf215f SS |
90 | except RPCError as e: |
91 | assert 'scriptsig-size' in str(e), str(e) | |
92 | ||
93 | ||
46d1bcc6 | 94 | @fanout_input(7) |
2b2c75de SS |
95 | def test_secp256k1_condition(inp): |
96 | ec_cond = { | |
97 | 'type': 'secp256k1-sha-256', | |
98 | 'publicKey': notary_pk | |
46d1bcc6 SS |
99 | } |
100 | ||
2b2c75de | 101 | # Create some secp256k1 outputs |
46d1bcc6 SS |
102 | spend0 = { |
103 | 'inputs': [inp], | |
104 | 'outputs': [ | |
2b2c75de SS |
105 | {'amount': 500, 'script': {'condition': ec_cond}}, |
106 | {'amount': 500, 'script': {'condition': ec_cond}} | |
46d1bcc6 SS |
107 | ] |
108 | } | |
109 | spend0_txid = submit(sign(spend0)) | |
110 | assert rpc.getrawtransaction(spend0_txid) | |
111 | ||
112 | # Test a good fulfillment | |
113 | spend1 = { | |
2b2c75de SS |
114 | 'inputs': [{'txid': spend0_txid, 'idx': 0, 'script': {'fulfillment': ec_cond}}], |
115 | 'outputs': [{'amount': 500, 'script': {'condition': ec_cond}}] | |
46d1bcc6 SS |
116 | } |
117 | spend1_txid = submit(sign(spend1)) | |
118 | assert rpc.getrawtransaction(spend1_txid) | |
119 | ||
120 | # Test a bad fulfillment | |
121 | spend2 = { | |
2b2c75de SS |
122 | 'inputs': [{'txid': spend0_txid, 'idx': 1, 'script': {'fulfillment': ec_cond}}], |
123 | 'outputs': [{'amount': 500, 'script': {'condition': ec_cond}}] | |
46d1bcc6 | 124 | } |
2b2c75de SS |
125 | signed = sign(spend2) |
126 | signed['inputs'][0]['script']['fulfillment']['publicKey'] = \ | |
127 | '0275cef12fc5c49be64f5aab3d1fbba08cd7b0d02908b5112fbd8504218d14bc7d' | |
46d1bcc6 | 128 | try: |
2b2c75de | 129 | assert not submit(signed), 'should raise an error' |
46d1bcc6 | 130 | except RPCError as e: |
7d937f29 SS |
131 | assert SCRIPT_FALSE in str(e), str(e) |
132 | ||
4f0da23b | 133 | if __name__ == '__main__': |
f5cf215f | 134 | logging.basicConfig(level=logging.INFO) |
82e6c354 SS |
135 | for name, f in globals().items(): |
136 | if name.startswith('test_'): | |
137 | logging.info("Running test: %s" % name) | |
138 | f() | |
f5cf215f | 139 | logging.info("Test OK: %s" % name) |