a63cf9c20c94593762b9ba8b8a5b235e73a9bbb3
[p2pool.git] / p2pool / bitcoin / script.py
1 from p2pool.util import math, pack
2
3 def reads_nothing(f):
4     return '', f
5 def protoPUSH(length):
6     return lambda f: pack.read(f, length)
7 def protoPUSHDATA(size_len):
8     def _(f):
9         length_str, f = pack.read(f, size_len)
10         length = math.string_to_natural(length_str[::-1].lstrip(chr(0)))
11         data, f = pack.read(f, length)
12         return data, f
13     return _
14
15 opcodes = {}
16 for i in xrange(256):
17     opcodes[i] = 'UNK_' + str(i), reads_nothing
18
19 opcodes[0] = '0', reads_nothing
20 for i in xrange(1, 76):
21     opcodes[i] = 'PUSH%i' % i, protoPUSH(i)
22 opcodes[76] = 'PUSHDATA1', protoPUSHDATA(1)
23 opcodes[77] = 'PUSHDATA2', protoPUSHDATA(2)
24 opcodes[78] = 'PUSHDATA4', protoPUSHDATA(4)
25 opcodes[79] = '-1', reads_nothing
26 for i in xrange(81, 97):
27     opcodes[i] = str(i - 80), reads_nothing
28
29 opcodes[172] = 'CHECKSIG', reads_nothing
30 opcodes[173] = 'CHECKSIGVERIFY', reads_nothing
31 opcodes[174] = 'CHECKMULTISIG', reads_nothing
32 opcodes[175] = 'CHECKMULTISIGVERIFY', reads_nothing
33
34 def parse(script):
35     f = script, 0
36     while pack.size(f):
37         opcode_str, f = pack.read(f, 1)
38         opcode = ord(opcode_str)
39         opcode_name, read_func = opcodes[opcode]
40         opcode_arg, f = read_func(f)
41         yield opcode_name, opcode_arg
42
43 def get_sigop_count(script):
44     weights = {
45         'CHECKSIG': 1,
46         'CHECKSIGVERIFY': 1,
47         'CHECKMULTISIG': 20,
48         'CHECKMULTISIGVERIFY': 20,
49     }
50     return sum(weights.get(opcode_name, 0) for opcode_name, opcode_arg in parse(script))