Advertisement
franji

Untitled

Dec 20th, 2017
449
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.58 KB | None | 0 0
  1. import hashlib
  2. import struct
  3. import random
  4.  
  5. def Log2(n):
  6.     """Log2(n) - how many times n can be be divided by2 before it is zero.
  7.    >>> Log2(0)
  8.    0
  9.    >>> Log2(5)
  10.    3
  11.    """
  12.     for i in xrange(32):
  13.         # mask is i ones in binary
  14.         # i==0  => mask==0b0
  15.         # i==1  => mask==0b1
  16.         # i==2  => mask==0b11
  17.         mask = (1L << i) - 1
  18.         if (n & mask) == n:
  19.             return i
  20.     return 99
  21.  
  22.  
  23. def NumberOfZerosForPuzzle(block_serial_number):
  24.     """Given a block serial number - how many zeros should be at the end of its signature
  25.    >>> NumberOfZerosForPuzzle(1000)
  26.    30
  27.    """
  28.     return 20 + Log2(block_serial_number)
  29.  
  30.  
  31. def WalletCode(member_names_list):
  32.     """Given list of the names of wallet owners - return a 32 bit number - wallet number.
  33.    >>> WalletCode(["Foo Bar", "Bar Vaz"])
  34.    3622990312
  35.    """
  36.     member_names_str = ",".join(sorted(member_names_list))
  37.     m = hashlib.md5()
  38.     m.update(member_names_str.lower())
  39.     data = m.digest()
  40.     # take lower 32 bit of member's name digest
  41.     # Note - unpack returns a tuple of size 1 - we use [0] to get the number
  42.     return struct.unpack(">L", data[:4])[0]
  43.  
  44. # Block is 32 byte/256bit long.
  45. # record/block format:
  46. # 32 bit serial number
  47. # 32 bit wallet number
  48. # 64 bit prev_sig[:8]highest bits  (first half ) of previous block's signature (including all the block)
  49. # 32 bit puzzle answer
  50. # 96 bit sig[:12] - md5 - the first 12 bytes of md5 of above fields. need to make last N bits zero
  51.  
  52. def CreateBlock0():
  53.     block0 = [0, 0, "BLOCKNUM", 2016330331, ""]
  54.     m = hashlib.md5()
  55.     block0_bin = struct.pack(">LL8sL", *block0[:4])
  56.     m.update(block0_bin)
  57.     block0_bin += m.digest()[:12]
  58.     return block0_bin
  59.  
  60.  
  61.  
  62. def CheckSignature(sig, n_zeros):
  63.     # check tha last n_zeros bits of signature.
  64.     # look at them byte by bye (8 bits together)
  65.     sig_index = 15  # look at last byte
  66.     while n_zeros >= 8:
  67.         b = ord(sig[sig_index])
  68.         if b != 0:
  69.             return False  # bad signature
  70.         sig_index -= 1
  71.         n_zeros -= 8 # we checked one byte
  72.     if n_zeros == 0:
  73.         return True  # this happens when n_zeros was divisible by 8
  74.     mask = (1L << n_zeros) - 1
  75.     b = ord(sig[sig_index])
  76.     return (b & mask) == 0
  77.  
  78.  
  79. def CheckBlockSignature(serial, wallet, prev_sig, puzzle, block_sig):
  80.     """Given a block fields - check that signature is valid and puzzle is solved.
  81.    return 0 if OK, reason for erro if not.
  82.    """
  83.     block_data = struct.pack(">LL8sL", serial, wallet, prev_sig, puzzle)
  84.     m = hashlib.md5()
  85.     m.update(block_data)
  86.     sig = m.digest()
  87.     # check sig has right number of zeros at the end
  88.     n_zeros = NumberOfZerosForPuzzle(serial)
  89.     if not CheckSignature(sig, n_zeros):
  90.         return 4
  91.     # check that the signature is part of the block
  92.     if block_sig != sig[:12]:
  93.         return 5
  94.     return 0
  95.  
  96.  
  97. def IsValidBlock(prev_block_bin, block_bin):
  98.     """Check if block_bin is valid given the previous block.
  99.    return 0 if Block ok, a reason number if not.
  100.    """
  101.     prev_block = struct.unpack(">LL8sL12s", prev_block_bin)
  102.     block = struct.unpack(">LL8sL12s", block_bin)
  103.     # check serial number
  104.     if block[0] != prev_block[0] + 1:
  105.         return 1
  106.     # check that not same wallet number
  107.     if block[1] == prev_block[1]:
  108.         return 2
  109.     # check that new block contins part of prev block signature
  110.     if block[2] != prev_block[4][:8]:
  111.         return 3
  112.     #calculate the signature for the block
  113.     return CheckBlockSignature(*block)
  114.  
  115.  
  116. def MineCoin(my_wallet, prev_block_bin):
  117.     prev_block = struct.unpack(">LL8sL12s", prev_block_bin)
  118.     serial, w, prev_prev_sig, prev_puzzle, prev_sig  = prev_block
  119.     new_serial = serial + 1
  120.     prev_half = prev_sig[:8]
  121.     n_zeros = NumberOfZerosForPuzzle(new_serial)
  122.     while True:
  123.         puzzle = random.randint(0, 1<<32 - 1)
  124.         #print new_serial, my_wallet, prev_half, puzzle
  125.         block_bin = struct.pack(">LL8sL", new_serial, my_wallet, prev_half, puzzle)
  126.         m = hashlib.md5()
  127.         m.update(block_bin)
  128.         sig = m.digest()
  129.         if CheckSignature(sig, n_zeros):
  130.             block_bin += sig[:12]
  131.             break
  132.     return block_bin  # new block
  133.  
  134.  
  135. prev_block = CreateBlock0()
  136. wallet1 = WalletCode(["Tal Franji"])
  137. wallet2 = WalletCode(["Foo Bar"])
  138. for _ in xrange(1000):
  139.     new_block = MineCoin(wallet1, prev_block)
  140.     if IsValidBlock(prev_block, new_block) != 0:
  141.         print "BAD"
  142.         break
  143.     print repr(prev_block)
  144.     prev_block = new_block
  145.     wallet1, wallet2 = wallet2, wallet1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement