5 from BCDataStream import *
6 from enumeration import Enumeration
7 from base58 import public_key_to_bc_address, hash_160_to_bc_address
10 from util import short_hex, long_hex
12 def parse_CAddress(vds):
14 d['nVersion'] = vds.read_int32()
15 d['nTime'] = vds.read_uint32()
16 d['nServices'] = vds.read_uint64()
17 d['pchReserved'] = vds.read_bytes(12)
18 d['ip'] = socket.inet_ntoa(vds.read_bytes(4))
19 d['port'] = vds.read_uint16()
22 def deserialize_CAddress(d):
23 return d['ip']+":"+str(d['port'])+" (lastseen: %s)"%(time.ctime(d['nTime']),)
25 def parse_setting(setting, vds):
26 if setting[0] == "f": # flag (boolean) settings
27 return str(vds.read_boolean())
28 elif setting == "addrIncoming":
29 return "" # bitcoin 0.4 purposely breaks addrIncoming setting in encrypted wallets.
30 elif setting[0:4] == "addr": # CAddress
31 d = parse_CAddress(vds)
32 return deserialize_CAddress(d)
33 elif setting == "nTransactionFee":
34 return vds.read_int64()
35 elif setting == "nLimitProcessors":
36 return vds.read_int32()
37 return 'unknown setting'
41 d['prevout_hash'] = vds.read_bytes(32)
42 d['prevout_n'] = vds.read_uint32()
43 d['scriptSig'] = vds.read_bytes(vds.read_compact_size())
44 d['sequence'] = vds.read_uint32()
46 def deserialize_TxIn(d, transaction_index=None, owner_keys=None):
47 if d['prevout_hash'] == "\x00"*32:
48 result = "TxIn: COIN GENERATED"
49 result += " coinbase:"+d['scriptSig'].encode('hex_codec')
50 elif transaction_index is not None and d['prevout_hash'] in transaction_index:
51 p = transaction_index[d['prevout_hash']]['txOut'][d['prevout_n']]
52 result = "TxIn: value: %f"%(p['value']/1.0e8,)
53 result += " prev("+long_hex(d['prevout_hash'][::-1])+":"+str(d['prevout_n'])+")"
55 result = "TxIn: prev("+long_hex(d['prevout_hash'][::-1])+":"+str(d['prevout_n'])+")"
56 pk = extract_public_key(d['scriptSig'])
57 result += " pubkey: "+pk
58 result += " sig: "+decode_script(d['scriptSig'])
59 if d['sequence'] < 0xffffffff: result += " sequence: "+hex(d['sequence'])
64 d['value'] = vds.read_int64()
65 d['scriptPubKey'] = vds.read_bytes(vds.read_compact_size())
68 def deserialize_TxOut(d, owner_keys=None):
69 result = "TxOut: value: %f"%(d['value']/1.0e8,)
70 pk = extract_public_key(d['scriptPubKey'])
71 result += " pubkey: "+pk
72 result += " Script: "+decode_script(d['scriptPubKey'])
73 if owner_keys is not None:
74 if pk in owner_keys: result += " Own: True"
75 else: result += " Own: False"
78 def parse_Transaction(vds):
80 d['version'] = vds.read_int32()
81 n_vin = vds.read_compact_size()
83 for i in xrange(n_vin):
84 d['txIn'].append(parse_TxIn(vds))
85 n_vout = vds.read_compact_size()
87 for i in xrange(n_vout):
88 d['txOut'].append(parse_TxOut(vds))
89 d['lockTime'] = vds.read_uint32()
91 def deserialize_Transaction(d, transaction_index=None, owner_keys=None):
92 result = "%d tx in, %d out\n"%(len(d['txIn']), len(d['txOut']))
93 for txIn in d['txIn']:
94 result += deserialize_TxIn(txIn, transaction_index) + "\n"
95 for txOut in d['txOut']:
96 result += deserialize_TxOut(txOut, owner_keys) + "\n"
99 def parse_MerkleTx(vds):
100 d = parse_Transaction(vds)
101 d['hashBlock'] = vds.read_bytes(32)
102 n_merkleBranch = vds.read_compact_size()
103 d['merkleBranch'] = vds.read_bytes(32*n_merkleBranch)
104 d['nIndex'] = vds.read_int32()
107 def deserialize_MerkleTx(d, transaction_index=None, owner_keys=None):
108 tx = deserialize_Transaction(d, transaction_index, owner_keys)
109 result = "block: "+(d['hashBlock'][::-1]).encode('hex_codec')
110 result += " %d hashes in merkle branch\n"%(len(d['merkleBranch'])/32,)
113 def parse_WalletTx(vds):
114 d = parse_MerkleTx(vds)
115 n_vtxPrev = vds.read_compact_size()
117 for i in xrange(n_vtxPrev):
118 d['vtxPrev'].append(parse_MerkleTx(vds))
121 n_mapValue = vds.read_compact_size()
122 for i in xrange(n_mapValue):
123 key = vds.read_string()
124 value = vds.read_string()
125 d['mapValue'][key] = value
126 n_orderForm = vds.read_compact_size()
128 for i in xrange(n_orderForm):
129 first = vds.read_string()
130 second = vds.read_string()
131 d['orderForm'].append( (first, second) )
132 d['fTimeReceivedIsTxTime'] = vds.read_uint32()
133 d['timeReceived'] = vds.read_uint32()
134 d['fromMe'] = vds.read_boolean()
135 d['spent'] = vds.read_boolean()
139 def deserialize_WalletTx(d, transaction_index=None, owner_keys=None):
140 result = deserialize_MerkleTx(d, transaction_index, owner_keys)
141 result += "%d vtxPrev txns\n"%(len(d['vtxPrev']),)
142 result += "mapValue:"+str(d['mapValue'])
143 if len(d['orderForm']) > 0:
144 result += "\n"+" orderForm:"+str(d['orderForm'])
145 result += "\n"+"timeReceived:"+time.ctime(d['timeReceived'])
146 result += " fromMe:"+str(d['fromMe'])+" spent:"+str(d['spent'])
149 # The CAuxPow (auxiliary proof of work) structure supports merged mining.
150 # A flag in the block version field indicates the structure's presence.
151 # As of 8/2011, the Original Bitcoin Client does not use it. CAuxPow
152 # originated in Namecoin; see
153 # https://github.com/vinced/namecoin/blob/mergedmine/doc/README_merged-mining.md.
154 def parse_AuxPow(vds):
155 d = parse_MerkleTx(vds)
156 n_chainMerkleBranch = vds.read_compact_size()
157 d['chainMerkleBranch'] = vds.read_bytes(32*n_chainMerkleBranch)
158 d['chainIndex'] = vds.read_int32()
159 d['parentBlock'] = parse_BlockHeader(vds)
162 def parse_BlockHeader(vds):
164 header_start = vds.read_cursor
165 d['version'] = vds.read_int32()
166 d['hashPrev'] = vds.read_bytes(32)
167 d['hashMerkleRoot'] = vds.read_bytes(32)
168 d['nTime'] = vds.read_uint32()
169 d['nBits'] = vds.read_uint32()
170 d['nNonce'] = vds.read_uint32()
171 header_end = vds.read_cursor
172 d['__header__'] = vds.input[header_start:header_end]
175 def parse_Block(vds):
176 d = parse_BlockHeader(vds)
177 if d['version'] & (1 << 8):
178 d['auxpow'] = parse_AuxPow(vds)
179 d['transactions'] = []
180 nTransactions = vds.read_compact_size()
181 for i in xrange(nTransactions):
182 d['transactions'].append(parse_Transaction(vds))
186 def deserialize_Block(d):
187 result = "Time: "+time.ctime(d['nTime'])+" Nonce: "+str(d['nNonce'])
188 result += "\nnBits: 0x"+hex(d['nBits'])
189 result += "\nhashMerkleRoot: 0x"+d['hashMerkleRoot'][::-1].encode('hex_codec')
190 result += "\nPrevious block: "+d['hashPrev'][::-1].encode('hex_codec')
191 result += "\n%d transactions:\n"%len(d['transactions'])
192 for t in d['transactions']:
193 result += deserialize_Transaction(t)+"\n"
194 result += "\nRaw block header: "+d['__header__'].encode('hex_codec')
197 def parse_BlockLocator(vds):
198 d = { 'hashes' : [] }
199 nHashes = vds.read_compact_size()
200 for i in xrange(nHashes):
201 d['hashes'].append(vds.read_bytes(32))
204 def deserialize_BlockLocator(d):
205 result = "Block Locator top: "+d['hashes'][0][::-1].encode('hex_codec')
208 opcodes = Enumeration("Opcodes", [
209 ("OP_0", 0), ("OP_PUSHDATA1",76), "OP_PUSHDATA2", "OP_PUSHDATA4", "OP_1NEGATE", "OP_RESERVED",
210 "OP_1", "OP_2", "OP_3", "OP_4", "OP_5", "OP_6", "OP_7",
211 "OP_8", "OP_9", "OP_10", "OP_11", "OP_12", "OP_13", "OP_14", "OP_15", "OP_16",
212 "OP_NOP", "OP_VER", "OP_IF", "OP_NOTIF", "OP_VERIF", "OP_VERNOTIF", "OP_ELSE", "OP_ENDIF", "OP_VERIFY",
213 "OP_RETURN", "OP_TOALTSTACK", "OP_FROMALTSTACK", "OP_2DROP", "OP_2DUP", "OP_3DUP", "OP_2OVER", "OP_2ROT", "OP_2SWAP",
214 "OP_IFDUP", "OP_DEPTH", "OP_DROP", "OP_DUP", "OP_NIP", "OP_OVER", "OP_PICK", "OP_ROLL", "OP_ROT",
215 "OP_SWAP", "OP_TUCK", "OP_CAT", "OP_SUBSTR", "OP_LEFT", "OP_RIGHT", "OP_SIZE", "OP_INVERT", "OP_AND",
216 "OP_OR", "OP_XOR", "OP_EQUAL", "OP_EQUALVERIFY", "OP_RESERVED1", "OP_RESERVED2", "OP_1ADD", "OP_1SUB", "OP_2MUL",
217 "OP_2DIV", "OP_NEGATE", "OP_ABS", "OP_NOT", "OP_0NOTEQUAL", "OP_ADD", "OP_SUB", "OP_MUL", "OP_DIV",
218 "OP_MOD", "OP_LSHIFT", "OP_RSHIFT", "OP_BOOLAND", "OP_BOOLOR",
219 "OP_NUMEQUAL", "OP_NUMEQUALVERIFY", "OP_NUMNOTEQUAL", "OP_LESSTHAN",
220 "OP_GREATERTHAN", "OP_LESSTHANOREQUAL", "OP_GREATERTHANOREQUAL", "OP_MIN", "OP_MAX",
221 "OP_WITHIN", "OP_RIPEMD160", "OP_SHA1", "OP_SHA256", "OP_HASH160",
222 "OP_HASH256", "OP_CODESEPARATOR", "OP_CHECKSIG", "OP_CHECKSIGVERIFY", "OP_CHECKMULTISIG",
223 "OP_CHECKMULTISIGVERIFY",
224 ("OP_SINGLEBYTE_END", 0xF0),
225 ("OP_DOUBLEBYTE_BEGIN", 0xF000),
226 "OP_PUBKEY", "OP_PUBKEYHASH",
227 ("OP_INVALIDOPCODE", 0xFFFF),
230 def script_GetOp(bytes):
232 while i < len(bytes):
234 opcode = ord(bytes[i])
236 if opcode >= opcodes.OP_SINGLEBYTE_END:
241 if opcode <= opcodes.OP_PUSHDATA4:
243 if opcode == opcodes.OP_PUSHDATA1:
244 nSize = ord(bytes[i])
246 elif opcode == opcodes.OP_PUSHDATA2:
247 nSize = unpack_from('<H', bytes, i)
249 elif opcode == opcodes.OP_PUSHDATA4:
250 nSize = unpack_from('<I', bytes, i)
252 vch = bytes[i:i+nSize]
257 def script_GetOpName(opcode):
258 return (opcodes.whatis(opcode)).replace("OP_", "")
260 def decode_script(bytes):
262 for (opcode, vch) in script_GetOp(bytes):
263 if len(result) > 0: result += " "
264 if opcode <= opcodes.OP_PUSHDATA4:
265 result += "%d:"%(opcode,)
266 result += short_hex(vch)
268 result += script_GetOpName(opcode)
271 def match_decoded(decoded, to_match):
272 if len(decoded) != len(to_match):
274 for i in range(len(decoded)):
275 if to_match[i] == opcodes.OP_PUSHDATA4 and decoded[i][0] <= opcodes.OP_PUSHDATA4:
276 continue # Opcodes below OP_PUSHDATA4 all just push data onto stack, and are equivalent.
277 if to_match[i] != decoded[i][0]:
281 def extract_public_key(bytes):
282 decoded = [ x for x in script_GetOp(bytes) ]
284 # non-generated TxIn transactions push a signature
285 # (seventy-something bytes) and then their public key
286 # (65 bytes) onto the stack:
287 match = [ opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4 ]
288 if match_decoded(decoded, match):
289 return public_key_to_bc_address(decoded[1][1])
291 # The Genesis Block, self-payments, and pay-by-IP-address payments look like:
292 # 65 BYTES:... CHECKSIG
293 match = [ opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG ]
294 if match_decoded(decoded, match):
295 return public_key_to_bc_address(decoded[0][1])
297 # Pay-by-Bitcoin-address TxOuts look like:
298 # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG
299 match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ]
300 if match_decoded(decoded, match):
301 return hash_160_to_bc_address(decoded[2][1])