1__author__ = 'bobalot' 2 3import struct 4import io 5import hashlib 6from binascii import hexlify, unhexlify 7from hashlib import sha256 8import models 9 10 11# Py3 compatibility 12import sys 13bchr = chr 14if sys.version > '3': 15 bchr = lambda x: bytes([x]) 16 17 18def deser_uint32(f): 19 if type(f) is not io.BytesIO: 20 f = io.BytesIO(f) 21 22 return struct.unpack(b"<I", f.read(4))[0] 23 24 25def ser_uint32(u): 26 rs = b"" 27 rs += struct.pack(b"<I", u & 0xFFFFFFFF) 28 return rs 29 30 31def deser_string(f): 32 nit = struct.unpack(b"<B", f.read(1))[0] 33 if nit == 253: 34 nit = struct.unpack(b"<H", f.read(2))[0] 35 elif nit == 254: 36 nit = struct.unpack(b"<I", f.read(4))[0] 37 elif nit == 255: 38 nit = struct.unpack(b"<Q", f.read(8))[0] 39 return f.read(nit) 40 41 42def ser_string(s): 43 if len(s) < 253: 44 return bchr(len(s)) + s 45 elif len(s) < 0x10000: 46 return bchr(253) + struct.pack(b"<H", len(s)) + s 47 elif len(s) < 0x100000000: 48 return bchr(254) + struct.pack(b"<I", len(s)) + s 49 return bchr(255) + struct.pack(b"<Q", len(s)) + s 50 51 52def deser_hash(f): 53 return f.read(32) 54 55 56def ser_hash(h): 57 return h[::-1] 58 59 60def deser_uint256(f): 61 r = 0 62 for i in range(8): 63 t = struct.unpack(b"<I", f.read(4))[0] 64 r += t << (i * 32) 65 return r 66 67 68def ser_uint256(u): 69 rs = b"" 70 for i in range(8): 71 rs += struct.pack(b"<I", u & 0xFFFFFFFF) 72 u >>= 32 73 return rs 74 75 76def ser_uint160(u): 77 rs = b"" 78 for i in range(5): 79 rs += struct.pack(b"<I", u & 0xFFFFFFFF) 80 u >>= 32 81 return rs 82 83 84def uint160_from_str(s): 85 r = 0 86 t = struct.unpack(b"<IIIII", s[:20]) 87 for i in range(5): 88 r += t[i] << (i * 32) 89 return r 90 91 92def uint256_from_str(s): 93 r = 0 94 t = struct.unpack(b"<IIIIIIII", s[:32]) 95 for i in range(8): 96 r += t[i] << (i * 32) 97 return r 98 99 100def uint256_from_compact(c): 101 nbytes = (c >> 24) & 0xFF 102 v = (c & 0xFFFFFF) << (8 * (nbytes - 3)) 103 return v 104 105 106def uint256_to_shortstr(u): 107 s = "%064x" % (u,) 108 return s[:16] 109 110 111def deser_variable_uint(f): 112 length = struct.unpack(b"<B", f.read(1))[0] 113 if length < 0xfd: 114 return length 115 elif length == 0xfd: 116 return struct.unpack(b"<H", f.read(2))[0] 117 elif length == 0xfe: 118 return struct.unpack(b"<I", f.read(4))[0] 119 return struct.unpack(b"<Q", f.read(8))[0] 120 121 122def deser_vector(f, c, arg1=None): 123 count = deser_variable_uint(f) 124 r = [] 125 for i in range(count): 126 #if arg1 is not None: 127 # t = c(arg1) 128 #else: 129 # t = c() 130 131 if c is models.TxIn: 132 t = deser_txin(f) 133 elif c is models.TxOut: 134 t = deser_txout(f) 135 elif c is models.Transaction: 136 t = deser_tx(f) 137 else: 138 raise NotImplementedError 139 140 r.append(t) 141 return r 142 143 144def ser_vector(l): 145 r = b"" 146 if len(l) < 253: 147 r = bchr(len(l)) 148 elif len(l) < 0x10000: 149 r = bchr(253) + struct.pack(b"<H", len(l)) 150 elif len(l) < 0x100000000: 151 r = bchr(254) + struct.pack(b"<I", len(l)) 152 else: 153 r = bchr(255) + struct.pack(b"<Q", len(l)) 154 155 for i in l: 156 if type(i) is models.TxIn: 157 r += ser_txin(i) 158 elif type(i) is models.TxOut: 159 r += ser_txout(i) 160 elif type(i) is models.Transaction: 161 r += ser_tx(i) 162 else: 163 raise NotImplementedError 164 165 return r 166 167 168def deser_uint256_vector(f): 169 nit = struct.unpack(b"<B", f.read(1))[0] 170 if nit == 253: 171 nit = struct.unpack(b"<H", f.read(2))[0] 172 elif nit == 254: 173 nit = struct.unpack(b"<I", f.read(4))[0] 174 elif nit == 255: 175 nit = struct.unpack(b"<Q", f.read(8))[0] 176 r = [] 177 for i in range(nit): 178 t = deser_uint256(f) 179 r.append(t) 180 return r 181 182 183def ser_uint256_vector(l): 184 r = b"" 185 if len(l) < 253: 186 r = bchr(len(l)) 187 elif len(l) < 0x10000: 188 r = bchr(253) + struct.pack(b"<H", len(l)) 189 elif len(l) < 0x100000000: 190 r = bchr(254) + struct.pack(b"<I", len(l)) 191 else: 192 r = bchr(255) + struct.pack(b"<Q", len(l)) 193 for i in l: 194 r += ser_uint256(i) 195 return r 196 197 198def deser_string_vector(f): 199 nit = struct.unpack(b"<B", f.read(1))[0] 200 if nit == 253: 201 nit = struct.unpack(b"<H", f.read(2))[0] 202 elif nit == 254: 203 nit = struct.unpack(b"<I", f.read(4))[0] 204 elif nit == 255: 205 nit = struct.unpack(b"<Q", f.read(8))[0] 206 r = [] 207 for i in range(nit): 208 t = deser_string(f) 209 r.append(t) 210 return r 211 212 213def ser_string_vector(l): 214 r = b"" 215 if len(l) < 253: 216 r = bchr(len(l)) 217 elif len(l) < 0x10000: 218 r = bchr(253) + struct.pack(b"<H", len(l)) 219 elif len(l) < 0x100000000: 220 r = bchr(254) + struct.pack(b"<I", len(l)) 221 else: 222 r = bchr(255) + struct.pack(b"<Q", len(l)) 223 for sv in l: 224 r += ser_string(sv) 225 return r 226 227 228def deser_int_vector(f): 229 nit = struct.unpack(b"<B", f.read(1))[0] 230 if nit == 253: 231 nit = struct.unpack(b"<H", f.read(2))[0] 232 elif nit == 254: 233 nit = struct.unpack(b"<I", f.read(4))[0] 234 elif nit == 255: 235 nit = struct.unpack(b"<Q", f.read(8))[0] 236 r = [] 237 for i in range(nit): 238 t = struct.unpack(b"<i", f.read(4))[0] 239 r.append(t) 240 return r 241 242 243def ser_int_vector(l): 244 r = b"" 245 if len(l) < 253: 246 r = bchr(len(l)) 247 elif len(l) < 0x10000: 248 r = bchr(253) + struct.pack(b"<H", len(l)) 249 elif len(l) < 0x100000000: 250 r = bchr(254) + struct.pack(b"<I", len(l)) 251 else: 252 r = bchr(255) + struct.pack(b"<Q", len(l)) 253 for i in l: 254 r += struct.pack(b"<i", i) 255 return r 256 257 258def Hash(s): 259 return uint256_from_str( 260 hashlib.sha256(hashlib.sha256(s).digest()).digest() 261 ) 262 263 264def Hash160(s): 265 h = hashlib.new('ripemd160') 266 h.update(hashlib.sha256(s).digest()) 267 return uint160_from_str(h.digest()) 268 269 270def ser_destination(destination): 271 if destination is None: 272 serialized = "" 273 else: 274 try: 275 serialized = unhexlify(destination) 276 except TypeError: 277 serialized = destination 278 279 return serialized 280 281 282def deser_txout(f): 283 txout = models.TxOut() 284 txout.value = struct.unpack(b"<q", f.read(8))[0] 285 txout.script = deser_string(f) 286 return txout 287 288 289def ser_txout(txout): 290 r = b"" 291 r += struct.pack(b"<q", txout.value) 292 r += ser_string(txout.script) 293 return r 294 295 296def deser_output_point(f): 297 if type(f) is not io.BytesIO: 298 f = io.BytesIO(f) 299 300 outpoint = models.OutPoint() 301 outpoint.hash = deser_hash(f)[::-1] 302 outpoint.index = deser_uint32(f.read(4)) 303 return outpoint 304 305 306def ser_output_point(outpoint): 307 r = b"" 308 r += ser_hash(outpoint.hash) 309 r += ser_uint32(outpoint.index) 310 return r 311 312 313def deser_txin(f): 314 if type(f) is not io.BytesIO: 315 f = io.BytesIO(f) 316 317 txin = models.TxIn() 318 txin.previous_output = deser_output_point(f) 319 txin.script = deser_string(f) 320 txin.sequence = deser_uint32(f) 321 return txin 322 323 324def ser_txin(txin): 325 r = b"" 326 r += ser_output_point(txin.previous_output) 327 r += ser_string(txin.script) 328 r += ser_uint32(txin.sequence) 329 return r 330 331 332def deser_block_header(f): 333 if type(f) is not io.BytesIO: 334 f = io.BytesIO(f) 335 336 h = models.BlockHeader() 337 338 h.version = deser_uint32(f.read(4)) 339 h.previous_block_hash = f.read(32) 340 h.merkle = f.read(32) 341 h.timestamp = deser_uint32(f.read(4)) 342 h.bits = deser_uint32(f.read(4)) 343 h.nonce = deser_uint32(f.read(4)) 344 345 return h 346 347 348def ser_block_header(block_header): 349 output = b"" 350 output += ser_uint32(block_header.version) 351 output += block_header.previous_block_hash 352 output += block_header.merkle 353 output += ser_uint32(block_header.timestamp) 354 output += ser_uint32(block_header.bits) 355 output += ser_uint32(block_header.nonce) 356 357 return output 358 359 360def deser_tx(f): 361 if type(f) is not io.BytesIO: 362 f = io.BytesIO(f) 363 364 tx = models.Transaction() 365 tx.version = deser_uint32(f.read(4)) 366 tx.inputs = deser_vector(f, models.TxIn) 367 tx.outputs = deser_vector(f, models.TxOut) 368 tx.locktime = deser_uint32(f) 369 return tx 370 371 372def ser_tx(tx): 373 r = b"" 374 r += ser_uint32(tx.version) 375 r += ser_vector(tx.inputs) 376 r += ser_vector(tx.outputs) 377 r += ser_uint32(tx.locktime) 378 return r 379 380 381def deser_block(f): 382 if type(f) is not io.BytesIO: 383 f = io.BytesIO(f) 384 385 blk = models.Block() 386 387 blk.header = deser_block_header(f) 388 blk.transactions = deser_vector(f, models.Transaction) 389 return blk 390 391 392def ser_block(blk): 393 r = b"" 394 r += ser_block_header(blk.header) 395 r += ser_vector(blk.transaction_list, models.Transaction) 396 397 return r 398 399 #tx.version = struct.unpack(b"<i", f.read(4))[0] 400 #tx.vin = deser_vector(f, TxIn) 401 #tx.vout = deser_vector(f, TxOut) 402 #tx.nLockTime = struct.unpack(b"<I", f.read(4))[0] 403 404 405def deser_history_row(f): 406 if type(f) is not io.BytesIO: 407 f = io.BytesIO(f) 408 409 hr = models.history_row() 410 411 hr.output_hash = f.read(32) 412 hr.output_index = deser_uint32(f) 413 hr.output_height = deser_uint32(f) 414 415 hr.value = struct.unpack(b"<q", f.read(8))[0] 416 hr.spend_hash = f.read(32) 417 hr.spend_index = deser_uint32(f) 418 hr.spend_height = deser_uint32(f) 419 420 return hr 421 422 423def ser_history_row(hr): 424 r = b"" 425 426 r += hr.output_hash 427 r += ser_uint32(hr.output_index) 428 r += ser_uint32(hr.output_height) 429 430 r += struct.pack(b"<q", hr.value & 0xFFFFFFFFFFFFFFFF) 431 r += hr.spend_hash 432 r += ser_uint32(hr.spend_index) 433 r += ser_uint32(hr.spend_height) 434 435 return hr 436 437 438def deser_history_row_list(bytes): 439 row_bytes = 88 440 num_rows = len(bytes) / row_bytes 441 442 assert(len(bytes) % row_bytes == 0) 443 444 history_list = [] 445 446 for i in range(num_rows): 447 begin = i * row_bytes 448 end = begin + row_bytes 449 history_list.append(deser_history_row(bytes[begin, end])) 450 451 return history_list 452 453 454def dsha256(data): 455 return sha256(sha256(data).digest()).digest()[::-1] 456 457 458def checksum(data): 459 return sha256(sha256(data).digest()).digest()[:4] 460 461 462def hash_block_header(blk_head): 463 if type(blk_head) is models.Block: 464 blk_head = blk_head.header 465 466 serial = ser_block_header(blk_head) 467 468 return dsha256(serial) 469 470 471def hash_transaction(tx): 472 if type(tx) is not models.Transaction: 473 return False 474 475 serial = ser_tx(tx) 476 477 return dsha256(serial) 478 479 480def ser_data(command, data): 481 # This requires command at the moment, for no reason. 482 # Fix this. 483 #from models import commands 484 #if command not in commands: 485 # raise NotImplementedError 486 487 if type(data) is int: 488 return ser_uint32(data) 489 elif type(data) is str: 490 return data 491 492 elif type(data) is tuple: 493 r = b"" 494 495 for element in data: 496 497 r += ser_data(command, element) 498 499 return r 500 501 502def deser_address_update(f): 503 if type(f) is not io.BytesIO: 504 f = io.BytesIO(f) 505 506 update = models.address_update() 507 update.address_version_byte = f.read(1) 508 update.address_hash = f.read(20) 509 510 update.height = deser_uint32(f) 511 update.tx = deser_tx(f) 512 513 return update 514 515 516#command_data_type = \ 517# {"blockchain.fetch_transaction", 518# "blockchain.fetch_last_height", 519# "blockchain.fetch_block_header", 520# "blockchain.fetch_block_transaction_hashes", 521# "transaction_pool.validate", 522# "protocol.broadcast_transaction", 523# "address.fetch_history"] 524 525 526# deserialize and remove the ec here, 527# this leaves all the other functions able to 528# do deserialization on normal bitcoin serials. 529def deser_data(command, data_bytes): 530 if command == "blockchain.fetch_transaction": 531 return data_bytes[:4], deser_tx(data_bytes[4:]) 532 533 elif command == "blockchain.fetch_last_height": 534 return data_bytes[:4], deser_uint32(data_bytes[4:]) 535 536 elif command == "blockchain.fetch_block_header": 537 return data_bytes[:4], deser_block_header(data_bytes[4:]) 538 539 elif command == "blockchain.fetch_block_transaction_hashes": 540 hash_list = [] 541 542 print hexlify(data_bytes[4:]) 543 544 assert((len(data_bytes)-4) % 32 == 0) 545 546 f = io.BytesIO(data_bytes) 547 ec = f.read(4) 548 549 for i in range(data_bytes/32): 550 hash_list.append(f.read(32)) 551 552 return ec, hash_list 553 554 elif command == "address.fetch_history": 555 # history row is 88 bytes long. Assert there is nothing else 556 assert((len(data_bytes)-4) % 88 == 0) 557 558 history_list = [] 559 560 # use bytesio, as this will probably be a long message 561 f = io.BytesIO(data_bytes) 562 ec = f.read(4) 563 564 for i in range(len(data_bytes) / 88): 565 history_list.append(deser_history_row(f)) 566 567 return ec, history_list 568 569 elif command == "address.subscribe": 570 if len(data_bytes) == 4: 571 ec = deser_uint32(data_bytes) 572 573 return ec, None 574 575 elif command == "address.update": 576 # No error code in address.update 577 f = io.BytesIO(data_bytes) 578 579 ec = 0 580 return ec, deser_address_update(f) 581