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