예제 #1
0
    def do_test_bound_needle_dirs(self, hashtype):
        """test directories four deep with one data file at the lowest level"""
        (dir_name1, dir_path1, dir_name2, dir_path2) =\
            self.make_two_test_directories(FOUR, ONE)
        tree1 = MerkleTree.create_from_file_system(dir_path1, hashtype)

        self.assertEqual(dir_name1, tree1.name)
        nodes1 = tree1.nodes
        self.assertTrue(nodes1 is not None)
        self.assertEqual(ONE, len(nodes1))
        self.verify_tree_sha(tree1, dir_path1, hashtype)

        tree2 = MerkleTree.create_from_file_system(dir_path2, hashtype)
        self.assertEqual(dir_name2, tree2.name)
        nodes2 = tree2.nodes
        self.assertTrue(nodes2 is not None)
        self.assertEqual(ONE, len(nodes2))
        self.verify_tree_sha(tree2, dir_path2, hashtype)

        self.assertTrue(tree1 == tree1)
        self.assertFalse(tree1 == tree2)

        tree1_str = tree1.to_string(0)
        tree1_rebuilt = MerkleTree.create_from_serialization(
            tree1_str, hashtype)
#       # DEBUG
#       print "NEEDLEDIR TREE1:\n" + tree1Str
#       print "REBUILT TREE1:\n" + tree1Rebuilt.toString("")
#       # END
        self.assertTrue(tree1 == tree1_rebuilt)
예제 #2
0
    def do_test_bound_flat_dirs(self, hashtype):
        """test directory is single level, with four data files"""

        check_hashtype(hashtype)
        (dir_name1, dir_path1, dir_name2, dir_path2) =\
            self.make_two_test_directories(ONE, FOUR)
        tree1 = MerkleTree.create_from_file_system(dir_path1, hashtype)
        self.assertEqual(dir_name1, tree1.name)
        nodes1 = tree1.nodes
        self.assertTrue(nodes1 is not None)
        self.assertEqual(FOUR, len(nodes1))
        self.verify_tree_sha(tree1, dir_path1, hashtype)

        tree2 = MerkleTree.create_from_file_system(dir_path2, hashtype)
        self.assertEqual(dir_name2, tree2.name)
        nodes2 = tree2.nodes
        self.assertTrue(nodes2 is not None)
        self.assertEqual(FOUR, len(nodes2))
        self.verify_tree_sha(tree2, dir_path2, hashtype)

        self.assertFalse(tree1 is None)
        self.assertTrue(tree1 == tree1)
        self.assertFalse(tree1 == tree2)

        tree1_str = tree1.to_string(0)
        tree1_rebuilt = MerkleTree.create_from_serialization(
            tree1_str, hashtype)
        self.assertTrue(tree1 == tree1_rebuilt)
예제 #3
0
    def test_xlattice_bug1(self):
        """
        this test relies on dat.xlattice.org being locally present
        and an internally consistent merkleization
        """
        with open('tests/test_data/dat.xlattice.org', 'rb') as file:
            serialization = str(file.read(), 'utf-8')

        # create from serialization ---------------------------------
        tree1 = MerkleTree.create_from_serialization(
            serialization, HashTypes.SHA1)

#       # DEBUG
#       print "tree1 has %d nodes" % len(tree1.nodes)
#       with open('junk.tree1', 'w') as t:
#           t.write( tree1.toString(0) )
#       # END

        ser1 = tree1.to_string(0)
        self.assertEqual(serialization, ser1)

        # create from string array ----------------------------------
        string = serialization.split('\n')
        string = string[:-1]
        self.assertEqual(2511, len(string))

        tree2 = MerkleTree.create_from_string_array(string, HashTypes.SHA1)

        ser2 = tree2.to_string(0)
        self.assertEqual(serialization, ser2)

        self.assertTrue(tree1 == tree2)
예제 #4
0
    def test_xlattice_bug3(self):
        """
        this test relies on dat2.xlattice.org being locally present
        and an internally consistent merkleization
        """
        with open('tests/test_data/dat2.xlattice.org', 'rb') as file:
            serialization = str(file.read(), 'utf-8')

        # create from serialization ---------------------------------
        tree1 = MerkleTree.create_from_serialization(
            serialization, HashTypes.SHA2)

        ser1 = tree1.to_string(0)
        self.assertEqual(serialization, ser1)

        # create from string array ----------------------------------
        string = serialization.split('\n')
        string = string[:-1]
        self.assertEqual(2511, len(string))

        tree2 = MerkleTree.create_from_string_array(string, HashTypes.SHA2)

        ser2 = tree2.to_string(0)
        self.assertEqual(serialization, ser2)

        self.assertTrue(tree1 == tree2)
예제 #5
0
def test2():
    m = MerkleTree(data[0:2])
    merkle_hashes = m.get_hashes()

    assert merkle_hashes[0][0] == sha256(hashes[0] + hashes[1]).digest()
    assert merkle_hashes[1][0] == hashes[0]
    assert merkle_hashes[1][1] == hashes[1]
    for h in merkle_hashes[2]:
        assert h == None
예제 #6
0
	def createClearMerkleTree(self, height):
		subsidy = self.SubsidyAlgo(height)
		cbtxn = self.makeCoinbaseTxn(subsidy, False, witness_commitment=None)
		cbtxn.setCoinbase(b'\0\0')  # necessary to avoid triggering segwit marker+flags
		cbtxn.assemble()
		MT = MerkleTree([cbtxn])
		if self.currentMerkleTree:
			self.UpdateClearMerkleTree(MT, self.currentMerkleTree.MP)
		MT.witness_commitment = None
		return MT
예제 #7
0
def test3():
    m = MerkleTree(data[0:3])
    merkle_hashes = m.get_hashes()

    assert merkle_hashes[0][0] == hash_abc
    assert merkle_hashes[1][0] == hash_ab
    assert merkle_hashes[1][1] == hashes[2]
    assert merkle_hashes[2][0] == hashes[0]
    assert merkle_hashes[2][1] == hashes[1]
    assert merkle_hashes[2][2] == None
    assert merkle_hashes[2][3] == None
예제 #8
0
    def get_merklepath(self, txn):
        # Get Tree information from minernode
        proof = None
        for block in self.blockchain.blockchain:
            if txn in block[0].txnlist:
                merkletree = MerkleTree(block[0].txnlist)
                merkletree.build()
                arrayTree = merkletree.tree

                # Get merkle path
                proof = merkletree.get_proof(txn)

        return proof
예제 #9
0
def test4():
    m = MerkleTree(data[0:4])
    merkle_hashes = m.get_hashes()

    assert merkle_hashes[0][0] == hash_abcd
    assert merkle_hashes[1][0] == hash_ab
    assert merkle_hashes[1][1] == hash_cd
    assert merkle_hashes[2][0] == hashes[0]
    assert merkle_hashes[2][1] == hashes[1]
    assert merkle_hashes[2][2] == hashes[2]
    assert merkle_hashes[2][3] == hashes[3]

    for n in merkle_hashes[3]:
        assert n == None
예제 #10
0
def test5():
    m = MerkleTree(data[0:5])
    merkle_hashes = m.get_hashes()

    assert merkle_hashes[0][0] == hash_abcde
    assert merkle_hashes[1][0] == hash_abcd
    assert merkle_hashes[1][1] == hashes[4]
    assert merkle_hashes[2][0] == hash_ab
    assert merkle_hashes[2][1] == hash_cd
    assert merkle_hashes[2][2] == None
    assert merkle_hashes[2][3] == None

    assert merkle_hashes[3][0] == hashes[0]
    assert merkle_hashes[3][1] == hashes[1]
    assert merkle_hashes[3][2] == hashes[2]
    assert merkle_hashes[3][3] == hashes[3]
예제 #11
0
def merkle_test():
    m = MerkleChain()

    b1 = [
        "Hey!", "Hi!", "How are ya?", "Not bad!", "Cool!", "School good?",
        "Yes!", "Aight Imma head out"
    ]
    b2 = [
        "My life is a lie", "The void grows bigger.", "I smell pennies",
        "Hmmm yes", "Enslaved water?", "Yes indeed", "Big yums", "Lovely"
    ]
    b3 = [
        "Oof", "No", "Ah yes", "Ahhh no", "Big oofs", "No oofs here", "Stop",
        "go"
    ]
    blocks = [b1, b2, b3]
    for i in range(0, len(blocks)):
        ## cons nonce
        prev_hash = m.get_latest_block_hash()
        root = MerkleTree(blocks[i]).get_merkle_root()
        nonce = generate_hash(prev_hash, root, 3)
        ## add entry
        m.insert(blocks[i], nonce)
        assert m.latest_block_idx == i + 1
        print(m.get_latest_block_hash())

    ## run some test cases against blocks
    assert m.verify("Hey!", 1, 0)
    assert not m.verify("Ah yes", 3, 1)
    assert m.verify("Ah yes", 3, 2)
    assert m.verify("The void grows bigger.", 2, 1)
    assert m.verify("Aight Imma head out", 1, 7)
    assert not m.verify("Oofie", 3, 0)
예제 #12
0
 def createClearMerkleTree(self, height):
     subsidy = self.SubsidyAlgo(height)
     cbtxn = self.makeCoinbaseTxn(subsidy, False)
     cbtxn.assemble()
     MT = MerkleTree([cbtxn])
     if self.currentMerkleTree:
         self.UpdateClearMerkleTree(MT, self.currentMerkleTree.MP)
     return MT
예제 #13
0
	def createClearMerkleTree(self, height):
		subsidy = self.SubsidyAlgo(height)
		blockInfo = (None, None)
		if hasattr(self, 'Rootstock') and self.Rootstock is not None:
			blockInfo = self.Rootstock.getBlockInfo()
		cbtxn = self.makeCoinbaseTxn(subsidy, False, witness_commitment=None)
		cbtxn.setCoinbase(b'\0\0')  # necessary to avoid triggering segwit marker+flags
		cbtxn.assemble()
		MT = MerkleTree([cbtxn])
		self.merkleTreeLock.acquire()
		if self.currentMerkleTree:
			self.UpdateClearMerkleTree(MT, self.currentMerkleTree.MP)
		self.merkleTreeLock.release()
		MT.witness_commitment = None
		if blockInfo[0] is not None:
			MT.rootstockBlockInfo = blockInfo
		return MT
예제 #14
0
 def validate(self):
     boolean = True
     for i in range(1, len(self.transactions)):
         transaction = self.transactions[i]
         boolean = transaction.validate()
         if not boolean:
             return boolean
     return self.header['tree_root'] == MerkleTree(self.transactions).get_root()
예제 #15
0
	def _ProcessGBT(self, MP, TS = None):
		oMP = MP
		MP = deepcopy(MP)
		
		prevBlock = bytes.fromhex(MP['previousblockhash'])[::-1]
		if 'height' not in MP:
			MP['height'] = TS['access'].getinfo()['blocks'] + 1
		height = MP['height']
		bits = bytes.fromhex(MP['bits'])[::-1]
		(MP['_bits'], MP['_prevBlock']) = (bits, prevBlock)
		if (prevBlock, height, bits) != self.currentBlock and (self.currentBlock[1] is None or height > self.currentBlock[1]):
			self.updateBlock(prevBlock, height, bits, _HBH=(MP['previousblockhash'], MP['bits']))
		
		txnlist = MP['transactions']
		if len(txnlist) and isinstance(txnlist[0], dict):
			txninfo = txnlist
			txnlist = tuple(a['data'] for a in txnlist)
		elif 'transactionfees' in MP:
			# Backward compatibility with pre-BIP22 gmp_fees branch
			txninfo = [{'fee':a} for a in MP['transactionfees']]
		else:
			# Backward compatibility with pre-BIP22 hex-only (bitcoind <0.7, Eloipool <future)
			txninfo = [{}] * len(txnlist)
		# TODO: cache Txn or at least txid from previous merkle roots?
		txnlist = [a for a in map(bytes.fromhex, txnlist)]
		
		self._makeBlockSafe(MP, txnlist, txninfo)
		
		cbtxn = self.makeCoinbaseTxn(MP['coinbasevalue'], prevBlockHex = MP['previousblockhash'])
		cbtxn.setCoinbase(b'\0\0')
		cbtxn.assemble()
		txnlist.insert(0, cbtxn.data)
		txninfo.insert(0, {
		})
		
		txnlist = [a for a in map(Txn, txnlist[1:])]
		txnlist.insert(0, cbtxn)
		txnlist = list(txnlist)
		newMerkleTree = MerkleTree(txnlist)
		newMerkleTree.POTInfo = MP.get('POTInfo')
		newMerkleTree.MP = MP
		newMerkleTree.oMP = oMP
		
		return newMerkleTree
예제 #16
0
    def do_test_pathless_unbound(self, hashtype):
        """
        Test basic characteristics of very simple MerkleTrees created
        using a specific SHA hash type.
        """
        (dir_name1, dir_name2) = self.get_two_unique_directory_names()

        check_hashtype(hashtype)
        tree1 = MerkleTree(dir_name1, hashtype)
        self.assertEqual(dir_name1, tree1.name)
        if hashtype == HashTypes.SHA1:
            self.assertEqual(SHA1_HEX_NONE, tree1.hex_hash)
        elif hashtype == HashTypes.SHA2:
            self.assertEqual(SHA2_HEX_NONE, tree1.hex_hash)
        elif hashtype == HashTypes.SHA3:
            self.assertEqual(SHA3_HEX_NONE, tree1.hex_hash)
        elif hashtype == HashTypes.BLAKE2B_256:
            self.assertEqual(BLAKE2B_256_HEX_NONE, tree1.hex_hash)
        else:
            raise NotImplementedError
        tree2 = MerkleTree(dir_name2, hashtype)
        self.assertEqual(dir_name2, tree2.name)

        # these tests remain skimpy
        self.assertFalse(tree1 is None)
        self.assertTrue(tree1 == tree1)
        self.assertFalse(tree1 == tree2)

        tree1_str = tree1.to_string(0)

        # there should be no indent on the first line
        self.assertFalse(tree1_str[0] == ' ')

        # no extra lines should be added
        lines = tree1_str.split('\n')
        # this split generates an extra blank line, because the serialization
        # ends with CR-LF
        if lines[-1] == '':
            lines = lines[:-1]
        self.assertEqual(1, len(lines))

        tree1_rebuilt = MerkleTree.create_from_serialization(
            tree1_str, hashtype)
        self.assertTrue(tree1 == tree1_rebuilt)
예제 #17
0
    def do_test_deepish_trees(self, hashtype):
        """
        Build a directory of random data, then its MerkleTree, then
        round trip to a serialization and back.
        """

        tree_top = os.path.join('tmp', self.rng.next_file_name(MAX_NAME_LEN))
        while os.path.exists(tree_top):
            tree_top = os.path.join(
                'tmp', self.rng.next_file_name(MAX_NAME_LEN))

        # Generate a quasi-random data directory, 7 deep, up to 5 files/dir
        self.rng.next_data_dir(tree_top, depth=7, width=5, max_len=4096)

        # Build a MerkleTree specifying the directory.
        tree = MerkleTree.create_from_file_system(tree_top, hashtype)

        # ROUND TRIP 1 ----------------------------------------------

        # Serialize it.
        ser = tree.__str__()

        # Deserialize to make another MerkleTree.
        tree2 = MerkleTree.create_from_serialization(ser, hashtype)

        self.assertTrue(tree2.__eq__(tree))
        self.assertEqual(tree2, tree)           # identical test

        # ROUND TRIP 2 ----------------------------------------------
        strings = ser.split('\n')
        strings = strings[:-1]
        tree3 = MerkleTree.create_from_string_array(strings, hashtype)
        self.assertEqual(tree3, tree)

        # ROUND TRIP 3 ----------------------------------------------
        filename = os.path.join('tmp', self.rng.next_file_name(8))
        while os.path.exists(filename):
            filename = os.path.join('tmp', self.rng.next_file_name(8))
        with open(filename, 'w') as file:
            file.write(ser)

        tree4 = MerkleTree.create_from_file(filename, hashtype)
        self.assertEqual(tree4, tree)
예제 #18
0
 def append_chain():
     conn = sqlite3.connect("message.db")
     c = conn.cursor()
     res = c.execute("SELECT merkle_idx FROM messages " +
                     "WHERE  blk_index = -1 ORDER BY merkle_idx DESC")
     msgs = [r[i] for r in res]
     root = MerkleTree(msgs).get_merkle_root()
     prev_hash = MerkleChainClientHandler.chain.get_latest_block_hash()
     nonce = generate_hash(prev_hash, root, 3)
     return MerkleChainClientHandler.chain.insert(msgs, nonce)
예제 #19
0
    def do_test_deepish_trees(self, hashtype):
        """
        Build a directory of random data, then its MerkleTree, then
        round trip to a serialization and back.
        """

        tree_top = os.path.join('tmp', self.rng.next_file_name(MAX_NAME_LEN))
        while os.path.exists(tree_top):
            tree_top = os.path.join('tmp',
                                    self.rng.next_file_name(MAX_NAME_LEN))

        # Generate a quasi-random data directory, 7 deep, up to 5 files/dir
        self.rng.next_data_dir(tree_top, depth=7, width=5, max_len=4096)

        # Build a MerkleTree specifying the directory.
        tree = MerkleTree.create_from_file_system(tree_top, hashtype)

        # ROUND TRIP 1 ----------------------------------------------

        # Serialize it.
        ser = tree.__str__()

        # Deserialize to make another MerkleTree.
        tree2 = MerkleTree.create_from_serialization(ser, hashtype)

        self.assertTrue(tree2.__eq__(tree))
        self.assertEqual(tree2, tree)  # identical test

        # ROUND TRIP 2 ----------------------------------------------
        strings = ser.split('\n')
        strings = strings[:-1]
        tree3 = MerkleTree.create_from_string_array(strings, hashtype)
        self.assertEqual(tree3, tree)

        # ROUND TRIP 3 ----------------------------------------------
        filename = os.path.join('tmp', self.rng.next_file_name(8))
        while os.path.exists(filename):
            filename = os.path.join('tmp', self.rng.next_file_name(8))
        with open(filename, 'w') as file:
            file.write(ser)

        tree4 = MerkleTree.create_from_file(filename, hashtype)
        self.assertEqual(tree4, tree)
예제 #20
0
 def __init__(self, transactions=None, prev_header=None, header=None):
     self.transactions = transactions
     if header is None:
         self.header = {
             'prev_header': prev_header,
             'tree_root': MerkleTree(transactions).get_root(),
             'timestamp': int(time.time()),
             'nonce': uuid.uuid4().hex
         }
     else:
         self.header = header
예제 #21
0
def test6():
    m = MerkleTree(data[0:6])
    merkle_hashes = m.get_hashes()

    assert merkle_hashes[0][0] == hash_abcdef
    assert merkle_hashes[1][0] == hash_abcd
    assert merkle_hashes[1][1] == hash_ef
    assert merkle_hashes[2][0] == hash_ab
    assert merkle_hashes[2][1] == hash_cd
    assert merkle_hashes[2][2] == hashes[4]
    assert merkle_hashes[2][3] == hashes[5]

    assert merkle_hashes[3][0] == hashes[0]
    assert merkle_hashes[3][1] == hashes[1]
    assert merkle_hashes[3][2] == hashes[2]
    assert merkle_hashes[3][3] == hashes[3]
    assert merkle_hashes[3][4] == None
    assert merkle_hashes[3][5] == None
    assert merkle_hashes[3][6] == None
    assert merkle_hashes[3][7] == None
예제 #22
0
    def test_gray_boxes_bug3(self):
        """ Test solution to bug in handling grayboxes website. """

        serialization =\
            '088d0e391e1a4872329e0f7ac5d45b2025363e26c199a7' + \
            '4ea39901d109afd6ba grayboxes.com/\n' +\
            ' 24652ddc14687866e6b1251589aee7e1e3079a87f80cd' + \
            '7775214f6d837612a90 images/\n' +\
            '  1eb774eef9be1e696f69a2f95711be37915aac283bb4' + \
            'b34dcbaf7d032233e090 grayboxes.gif\n' +\
            ' 6eacebda9fd55b59c0d2e48e2ed59ce9fd683379592f8' + \
            'e662b1de88e041f53c9 index.html\n'

        # create from string array ----------------------------------
        string = serialization.split('\n')
        string = string[:-1]
        self.assertEqual(4, len(string))

        tree2 = MerkleTree.create_from_string_array(string, HashTypes.SHA2)

        ser2 = tree2.to_string(0)
        self.assertEqual(serialization, ser2)

        # create from serialization ---------------------------------
        tree1 = MerkleTree.create_from_serialization(
            serialization, HashTypes.SHA2)

        ser1 = tree1.to_string(0)
        self.assertEqual(serialization, ser1)

        self.assertTrue(tree1 == tree2)

        # 2014-06-26 tagged this on here to test firstLineRE_1()
        first_line = string[0]
        match_ = MerkleTree.first_line_re_2().match(first_line)
        self.assertTrue(match_ is not None)
        self.assertEqual(match_.group(1), '')               # indent
        tree_hash = match_.group(2)
        dir_name = match_.group(3)
        self.assertEqual(tree_hash + ' ' + dir_name, first_line)
예제 #23
0
def CalculateWitnessCommitment(txnobjs, nonce, force=False):
	gentx_withash = nonce
	withashes = (gentx_withash,) + tuple(a.get_witness_hash() for a in txnobjs[1:])
	
	if not force:
		txids = (gentx_withash,) + tuple(a.txid for a in txnobjs[1:])
		if withashes == txids:
			# Unnecessary
			return None
	
	wmr = MerkleTree(data=withashes).merkleRoot()
	commitment = util.dblsha(wmr + nonce)
	return commitment
예제 #24
0
    def test_gray_boxes_bug1(self):
        """
        Verify that bug #1 in handling serialization of grayboxes website
        has been corrected.
        """
        serialization =\
            '721a08022dd26e7be98b723f26131786fd2c0dc3 grayboxes.com/\n' +\
            ' fcd3973c66230b9078a86a5642b4c359fe72d7da images/\n' +\
            '  15e47f4eb55197e1bfffae897e9d5ce4cba49623 grayboxes.gif\n' +\
            ' 2477b9ea649f3f30c6ed0aebacfa32cb8250f3df index.html\n'

        # create from string array ----------------------------------
        string = serialization.split('\n')
        string = string[:-1]
        self.assertEqual(4, len(string))

        tree2 = MerkleTree.create_from_string_array(string, HashTypes.SHA1)

        ser2 = tree2.to_string(0)
        self.assertEqual(serialization, ser2)

        # create from serialization ---------------------------------
        tree1 = MerkleTree.create_from_serialization(
            serialization, HashTypes.SHA1)

        ser1 = tree1.to_string(0)
        self.assertEqual(serialization, ser1)

        self.assertTrue(tree1 == tree2)

        # 2014-06-26 tagged this on here to test firstLineRE_1()
        first_line = string[0]
        match_ = MerkleTree.first_line_re_1().match(first_line)
        self.assertTrue(match_ is not None)
        self.assertEqual(match_.group(1), '')               # indent
        tree_hash = match_.group(2)
        dir_name = match_.group(3)
        self.assertEqual(tree_hash + ' ' + dir_name, first_line)
    def createClearMerkleTree(self, height, bits):
        basenBits = 0x1E00FFFF
        nShift = ((basenBits >> 24) & 0xff) - ((bits >> 24) & 0xff)
        dDiff = float(basenBits & 0x007fffff) / float(bits & 0x007fffff)

        while (nShift > 0):
            dDiff *= 256.0
            nShift -= 1

        while (nShift < 0):
            dDiff /= 256.0
            nShift += 1

        nSubsidy1 = int(sqrt(dDiff * height))
        subsidy = nSubsidy1 + 2500000000

        cbtxn = self.makeCoinbaseTxn(subsidy, False)
        cbtxn.assemble()
        return MerkleTree([cbtxn])
	def updateMerkleTree(self):
		global now
		self.logger.debug('Polling bitcoind for memorypool')
		self.nextMerkleUpdate = now + self.TxnUpdateRetryWait
		
		try:
			# First, try BIP 22 standard getblocktemplate :)
			MP = self.access.getblocktemplate(self.GBTReq)
			self.OldGMP = False
		except:
			try:
				# Failing that, give BIP 22 draft (2012-02 through 2012-07) getmemorypool a chance
				MP = self.access.getmemorypool(self.GMPReq)
			except:
				try:
					# Finally, fall back to bitcoind 0.5/0.6 getmemorypool
					MP = self.access.getmemorypool()
				except:
					MP = False
			if MP is False:
				# This way, we get the error from the BIP22 call if the old one fails too
				raise
			
			# Pre-BIP22 server (bitcoind <0.7 or Eloipool <20120513)
			if not self.OldGMP:
				self.OldGMP = True
				self.logger.warning('Upstream server is not BIP 22 compatible')
		
		oMP = deepcopy(MP)
		
		prevBlock = bytes.fromhex(MP['previousblockhash'])[::-1]
		if 'height' in MP:
			height = MP['height']
		else:
			height = self.access.getinfo()['blocks'] + 1
		bits = bytes.fromhex(MP['bits'])[::-1]
		if (prevBlock, height, bits) != self.currentBlock:
			self.updateBlock(prevBlock, height, bits, _HBH=(MP['previousblockhash'], MP['bits']))
		
		txnlist = MP['transactions']
		if len(txnlist) and isinstance(txnlist[0], dict):
			txninfo = txnlist
			txnlist = tuple(a['data'] for a in txnlist)
			txninfo.insert(0, {
			})
		elif 'transactionfees' in MP:
			# Backward compatibility with pre-BIP22 gmp_fees branch
			txninfo = [{'fee':a} for a in MP['transactionfees']]
		else:
			# Backward compatibility with pre-BIP22 hex-only (bitcoind <0.7, Eloipool <future)
			txninfo = [{}] * len(txnlist)
		# TODO: cache Txn or at least txid from previous merkle roots?
		txnlist = [a for a in map(bytes.fromhex, txnlist)]
		
		self._makeBlockSafe(MP, txnlist, txninfo)
		
		cbtxn = self.makeCoinbaseTxn(MP['coinbasevalue'])
		cbtxn.setCoinbase(b'\0\0')
		cbtxn.assemble()
		txnlist.insert(0, cbtxn.data)
		
		txnlist = [a for a in map(Txn, txnlist[1:])]
		txnlist.insert(0, cbtxn)
		txnlist = list(txnlist)
		newMerkleTree = MerkleTree(txnlist)
		if newMerkleTree.merkleRoot() != self.currentMerkleTree.merkleRoot():
			newMerkleTree.POTInfo = MP.get('POTInfo')
			newMerkleTree.oMP = oMP
			
			if (not self.OldGMP) and 'proposal' in MP.get('capabilities', ()):
				(prevBlock, height, bits) = self.currentBlock
				coinbase = self.makeCoinbase(height=height)
				cbtxn.setCoinbase(coinbase)
				cbtxn.assemble()
				merkleRoot = newMerkleTree.merkleRoot()
				MRD = (merkleRoot, newMerkleTree, coinbase, prevBlock, bits)
				blkhdr = MakeBlockHeader(MRD)
				data = assembleBlock(blkhdr, txnlist)
				propose = self.access.getblocktemplate({
					"mode": "proposal",
					"data": b2a_hex(data).decode('utf8'),
				})
				if propose is None:
					self.logger.debug('Updating merkle tree (upstream accepted proposal)')
					self.currentMerkleTree = newMerkleTree
				else:
					self.RejectedProposal = (newMerkleTree, propose)
					try:
						propose = propose['reject-reason']
					except:
						pass
					self.logger.error('Upstream rejected proposed block: %s' % (propose,))
			else:
				self.logger.debug('Updating merkle tree (no proposal support)')
				self.currentMerkleTree = newMerkleTree
		
		self.lastMerkleUpdate = now
		self.nextMerkleUpdate = now + self.MinimumTxnUpdateWait
		
		if self.needMerkle == 2:
			self.needMerkle = 1
			self.needMerkleSince = now
예제 #27
0
	def _ProcessGBT(self, MP, TS = None):
		oMP = MP
		MP = deepcopy(MP)
		
		if MP['version'] & 0xe0000000 != 0x20000000:
			self.logger.error('Template from \'%s\' has non-BIP9 block version (%x)' % (TS['name'], MP['version']))
			return None
		
		ISupportAllRules = True
		for ruleflag in MP['rules']:
			(MandatoryRule, rule) = SplitRuleFlag(ruleflag)
			if rule not in SupportedRules:
				ISupportAllRules = False
				if MandatoryRule:
					self.logger.error('Template from \'%s\' strictly requires unsupported rule \'%s\'', TS['name'], rule)
					return None
				else:
					self.logger.warning('Template from \'%s\' loosely requires unsupported rule \'%s\'', TS['name'], rule)
		
		MP['_filtered_vbavailable'] = {}
		for ruleflag in MP['vbavailable']:
			rulebit = MP['vbavailable'][ruleflag]
			rulemask = (1 << rulebit)
			if MP['version'] & rulemask:
				MP['_filtered_vbavailable'][ruleflag] = rulebit
		
		prevBlock = bytes.fromhex(MP['previousblockhash'])[::-1]
		if 'height' not in MP:
			MP['height'] = TS['access'].getinfo()['blocks'] + 1
		height = MP['height']
		bits = bytes.fromhex(MP['bits'])[::-1]
		(MP['_bits'], MP['_prevBlock']) = (bits, prevBlock)
		MP['_BlockVersionBytes'] = struct.pack('<L', MP['version'])
		if (prevBlock, height, bits) != self.currentBlock and (self.currentBlock[1] is None or height > self.currentBlock[1]):
			self.updateBlock(prevBlock, height, bits, _HBH=(MP['previousblockhash'], MP['bits']))
		
		txnlist = MP['transactions']
		if len(txnlist) and isinstance(txnlist[0], dict):
			txninfo = txnlist
			txnlist = tuple(a['data'] for a in txnlist)
		elif 'transactionfees' in MP:
			# Backward compatibility with pre-BIP22 gmp_fees branch
			txninfo = [{'fee':a} for a in MP['transactionfees']]
		else:
			# Backward compatibility with pre-BIP22 hex-only (bitcoind <0.7, Eloipool <future)
			txninfo = [{}] * len(txnlist)
		# TODO: cache Txn or at least txid from previous merkle roots?
		txnlist = [a for a in map(bytes.fromhex, txnlist)]
		
		self._makeBlockSafe(MP, txnlist, txninfo)
		if len(MP['transactions']) != len(txnlist) and not ISupportAllRules:
			self.logger.error('Template from \'%s\' should be trimmed, but requires unsupported rule(s)', TS['name'])
			return None
		
		txnobjs = [None]
		for i in range(len(txnlist)):
			iinfo = txninfo[i]
			ka = {}
			if 'txid' in iinfo:
				ka['txid'] = bytes.fromhex(iinfo['txid'])[::-1]
			txnobjs.append(Txn(data=txnlist[i], **ka))
		
		witness_commitment = CalculateWitnessCommitment(txnobjs, self.WitnessNonce, force=self.ForceWitnessCommitment)
		
		cbtxn = self.makeCoinbaseTxn(MP['coinbasevalue'], prevBlockHex = MP['previousblockhash'], witness_commitment=witness_commitment)
		cbtxn.setCoinbase(b'\0\0')
		cbtxn.assemble()
		txnobjs[0] = cbtxn
		
		txnobjs = list(txnobjs)
		newMerkleTree = MerkleTree(txnobjs)
		newMerkleTree.POTInfo = MP.get('POTInfo')
		newMerkleTree.MP = MP
		newMerkleTree.oMP = oMP
		newMerkleTree.witness_commitment = witness_commitment
		
		return newMerkleTree