Exemplo n.º 1
0
    def test_block_message(self):
        message = messages.msg_block()
        cblock = CBlock()
        message.block = cblock

        block = Block(None, BlockOrigin.private)
        block.cached_hash = message.block.GetHash()

        self.chain.blocks = {block.hash(): block}

        self.networking.block_message(self.private_connection, message)

        self.assertEqual(self.chain.blocks[block.hash()].cblock, cblock)
Exemplo n.º 2
0
    def test_block_message_two_times(self):
        message = messages.msg_block()
        cblock1 = CBlock(nNonce=1)
        cblock2 = CBlock(nNonce=2)
        message.block = cblock1

        block = Block(None, BlockOrigin.private)
        block.cached_hash = message.block.GetHash()

        self.chain.blocks = {block.hash(): block}

        self.networking.block_message(self.private_connection, message)
        message.block = cblock2
        self.networking.block_message(self.private_connection, message)
Exemplo n.º 3
0
    def test_block_message_remove_from_blocks_in_flight(self):
        message = messages.msg_block()
        cblock = CBlock()
        message.block = cblock

        block = Block(None, BlockOrigin.private)
        block.cached_hash = message.block.GetHash()

        self.chain.blocks = {block.hash(): block}
        self.networking.blocks_in_flight = {block.hash(): 'in_flight'}

        self.networking.block_message(self.private_connection, message)

        self.assertEqual(len(self.networking.blocks_in_flight), 0)
Exemplo n.º 4
0
    def test_block_message_deferred_requests(self):
        message = messages.msg_block()
        cblock = CBlock()
        hash_ = cblock.GetHash()
        message.block = cblock

        block = Block(None, BlockOrigin.private)
        block.cached_hash = hash_

        self.networking.deferred_block_requests = \
            {hash_: [self.private_connection.host[0], self.public_connection2.host[0]]}
        self.networking.send_block = MagicMock()

        self.networking.block_message(self.public_connection1, message)

        self.assertEqual(len(self.networking.deferred_block_requests), 0)
        self.assertEqual(self.networking.send_block.call_count, 2)
        self.assertEqual(self.networking.send_block.call_args[0][1], cblock)
Exemplo n.º 5
0
    def getdata_block(self, blkhash):
        block = self.chaindb.getblock(blkhash)
        if block is None:
            return

        msg = messages.msg_block()
        msg.block = block

        self.send_message(msg)

        if blkhash == self.hash_continue:
            self.hash_continue = None

            inv = net.CInv()
            inv.type = messages.MSG_BLOCK
            inv.hash = self.chaindb.gettophash()

            msg = messages.msg_inv()
            msg.inv.append(inv)

            self.send_message(msg)
Exemplo n.º 6
0
    def getdata_block(self, blkhash):
        block = self.chaindb.getblock(blkhash)
        if block is None:
            return

        msg = messages.msg_block()
        msg.block = block

        self.send_message(msg)

        if blkhash == self.hash_continue:
            self.hash_continue = None

            inv = net.CInv()
            inv.type = messages.MSG_BLOCK
            inv.hash = self.chaindb.gettophash()

            msg = messages.msg_inv()
            msg.inv.append(inv)

            self.send_message(msg)
Exemplo n.º 7
0
    def putoneblock(self, block):
        block.calc_sha256()

        if not block.is_valid():
            self.log.write("Invalid block %064x" % (block.sha256, ))
            return False

        if not self.have_prevblock(block):
            self.orphans[block.sha256] = True
            self.orphan_deps[block.hashPrevBlock] = block
            self.log.write("Orphan block %064x (%d orphans)" %
                           (block.sha256, len(self.orphan_deps)))
            return False

        top_height = self.getheight()
        top_work = long(self.db.Get('misc:total_work'), 16)

        # read metadata for previous block
        prevmeta = BlkMeta()
        if top_height >= 0:
            ser_prevhash = ser_uint256(block.hashPrevBlock)
            prevmeta.deserialize(self.db.Get('blkmeta:' + ser_prevhash))
        else:
            ser_prevhash = ''

        batch = leveldb.WriteBatch()

        # build network "block" msg, as canonical disk storage form
        msg = msg_block()
        msg.block = block
        msg_data = message_to_str(self.netmagic, msg)

        # write "block" msg to storage
        fpos = self.blk_write.tell()

        if self.compress_on_write:
            msg_data = zlib.compress(msg_data, 1)
            msg_data = struct.pack('>4si%ds' % len(msg_data), 'ZLIB',
                                   len(msg_data), msg_data)

        self.blk_write.write(msg_data)
        self.blk_write.flush()

        # add index entry
        ser_hash = ser_uint256(block.sha256)
        batch.Put('blocks:' + ser_hash, str(fpos))

        # store metadata related to this block
        blkmeta = BlkMeta()
        blkmeta.height = prevmeta.height + 1
        blkmeta.work = (prevmeta.work + uint256_from_compact(block.nBits))
        batch.Put('blkmeta:' + ser_hash, blkmeta.serialize())

        # store list of blocks at this height
        heightidx = HeightIdx()
        heightstr = str(blkmeta.height)
        try:
            heightidx.deserialize(self.db.Get('height:' + heightstr))
        except KeyError:
            pass
        heightidx.blocks.append(block.sha256)

        batch.Put('height:' + heightstr, heightidx.serialize())
        self.db.Write(batch)

        # if chain is not best chain, proceed no further
        if (blkmeta.work <= top_work):
            self.log.write("ChainDb: height %d (weak), block %064x" %
                           (blkmeta.height, block.sha256))
            return True

        # update global chain pointers
        if not self.set_best_chain(ser_prevhash, ser_hash, block, blkmeta):
            return False

        return True
Exemplo n.º 8
0
	def putoneblock(self, block):
		block.calc_sha256()

		if not block.is_valid():
			self.log.write("Invalid block %064x" % (block.sha256, ))
			return False

		if not self.have_prevblock(block):
			self.orphans[block.sha256] = True
			self.orphan_deps[block.hashPrevBlock] = block
			self.log.write("Orphan block %064x (%d orphans)" % (block.sha256, len(self.orphan_deps)))
			return False

		top_height = self.getheight()
		top_work = long(self.db.Get('misc:total_work'), 16)

		# read metadata for previous block
		prevmeta = BlkMeta()
		if top_height >= 0:
			ser_prevhash = ser_uint256(block.hashPrevBlock)
			prevmeta.deserialize(self.db.Get('blkmeta:'+ser_prevhash))
		else:
			ser_prevhash = ''

		batch = leveldb.WriteBatch()

		# build network "block" msg, as canonical disk storage form
		msg = msg_block()
		msg.block = block
		msg_data = message_to_str(self.netmagic, msg)

		# write "block" msg to storage
		fpos = self.blk_write.tell()
		self.blk_write.write(msg_data)
		self.blk_write.flush()

		# add index entry
		ser_hash = ser_uint256(block.sha256)
		batch.Put('blocks:'+ser_hash, str(fpos))

		# store metadata related to this block
		blkmeta = BlkMeta()
		blkmeta.height = prevmeta.height + 1
		blkmeta.work = (prevmeta.work +
				uint256_from_compact(block.nBits))
		batch.Put('blkmeta:'+ser_hash, blkmeta.serialize())

		# store list of blocks at this height
		heightidx = HeightIdx()
		heightstr = str(blkmeta.height)
		try:
			heightidx.deserialize(self.db.Get('height:'+heightstr))
		except KeyError:
			pass
		heightidx.blocks.append(block.sha256)

		batch.Put('height:'+heightstr, heightidx.serialize())
		self.db.Write(batch)

		# if chain is not best chain, proceed no further
		if (blkmeta.work <= top_work):
			self.log.write("ChainDb: height %d (weak), block %064x" % (blkmeta.height, block.sha256))
			return True

		# update global chain pointers
		if not self.set_best_chain(ser_prevhash, ser_hash,
					   block, blkmeta):
			return False

		return True
Exemplo n.º 9
0
    def putoneblock(self, block, initsync=True):

        
        if not self.have_prevblock(block):
            self.orphans[block.GetHash()] = True
            self.orphan_deps[block.hashPrevBlock] = block
            self.log.warn("Orphan block %s (%d orphans)" % (b2lx(block.GetHash()), len(self.orphan_deps)))
            return False


        # if block.hashPrevBlock != self.gettophash():
        #     print("Cannot connect block to chain %s %s" % (b2lx(block.GetHash()), b2lx(self.gettophash())))
        #     return

        top_height = self.getheight()
        top_work = bytes_to_int(self.db.get(b'misc:total_work'))

        prevmeta = BlkMeta()
        if top_height >= 0:
            ser_prevhash = b2lx(block.hashPrevBlock)
            data = self.db.get(('blkmeta:'+ser_prevhash).encode())
            prevmeta.deserialize(data)
        else:
            ser_prevhash = ''

        # build network "block" msg, as canonical disk storage form
        msg = msg_block()
        msg.block = block
        msg_data = msg.to_bytes()

        # write "block" msg to storage
        fpos = self.blk_write.tell()
        self.blk_write.write(msg_data)
        self.blk_write.flush()
        
        with self.db.write_batch(transaction=True) as batch:

            # add index entry
            ser_hash = b2lx(block.GetHash())
            key = ('blocks:'+ser_hash).encode()
            value = struct.pack('i', fpos)
            batch.put(key, value)

            # store metadata related to this block
            blkmeta = BlkMeta()
            blkmeta.height = prevmeta.height + 1
            blkmeta.work = (prevmeta.work +
                    uint256_from_compact(block.nBits))
            batch.put(('blkmeta:'+ser_hash).encode(), blkmeta.serialize())

            # store list of blocks at this height
            heightidx = HeightIdx()
            heightstr = str(blkmeta.height)
            d = self.db.get(('height:'+heightstr).encode())
            if d:
                heightidx.deserialize(d)
            heightidx.blocks.append(block.GetHash())

            batch.put(('height:'+heightstr).encode(), heightidx.serialize())

        # print('height: %s' % blkmeta.height)
        # print('blk: %s' % blkmeta.work)
        # print('top: %s' % top_work)

        # if chain is not best chain, proceed no further
        if (blkmeta.work <= top_work):
            self.log.info("ChainDb: height %d (weak), block %s" % (blkmeta.height, b2lx(block.GetHash())))
            return True

        # update global chain pointers
        if not self.set_best_chain(ser_prevhash, ser_hash, block, blkmeta):
            return False

        return True
Exemplo n.º 10
0
    def putoneblock(self, block):
        block.calc_sha256()

        if not block.is_valid():
            self.logger.error("Invalid block %064x" % (block.sha256, ))
            return False

        if not self.have_prevblock(block):
            self.orphans[block.sha256] = True
            self.orphan_deps[block.hashPrevBlock] = block
            self.logger.warning("Orphan block %064x (%d orphans)" % \
                (block.sha256, len(self.orphan_deps)))
            return False

        top_height = self.getheight()
        top_work = long(self.db.Get('misc:total_work'), 16)

        # read metadata for previous block
        prevmeta = BlkMeta()
        if top_height >= 0:
            ser_prevhash = ser_uint256(block.hashPrevBlock)
            prevmeta.deserialize(self.db.Get('blkmeta:' + ser_prevhash))
        else:
            ser_prevhash = ''

        batch = leveldb.WriteBatch()

        # build network "block" msg, as canonical disk storage form
        msg = msg_block()
        msg.block = block
        msg_data = message_to_str(self.netmagic, msg)

        # write "block" msg to storage
        fpos = self.blk_write.tell()
        self.blk_write.write(msg_data)
        self.blk_write.flush()

        # add index entry
        ser_hash = ser_uint256(block.sha256)
        batch.Put('blocks:' + ser_hash, str(fpos))

        # store metadata related to this block
        blkmeta = BlkMeta()
        blkmeta.height = prevmeta.height + 1
        blkmeta.work = (prevmeta.work + uint256_from_compact(block.nBits))
        batch.Put('blkmeta:' + ser_hash, blkmeta.serialize())

        # store list of blocks at this height
        heightidx = HeightIdx()
        heightstr = str(blkmeta.height)
        try:
            heightidx.deserialize(self.db.Get('height:' + heightstr))
        except KeyError:
            pass
        heightidx.blocks.append(block.sha256)

        batch.Put('height:' + heightstr, heightidx.serialize())
        self.db.Write(batch)

        # if chain is not best chain, proceed no further
        if (blkmeta.work <= top_work):
            self.logger.warning("ChainDb: height %d (weak), block %064x" %
                                (blkmeta.height, block.sha256))
            return True

        # update global chain pointers
        if not self.set_best_chain(ser_prevhash, ser_hash, block, blkmeta):
            return False

        # If just inserted block is multiple of 2016, compute new difficulty
        if blkmeta.height % 2016 == 0 and blkmeta.height != 0:
            last_stamp = block.nTime
            old_block_hash = heightidx.blocks[len(heightidx.blocks) - 2016]
            old_block = self.getblock(old_block_hash)
            old_stamp = old_block.nTime
            self.logger.debug("Changing difficulty from %02x" %
                              self.difficulty)
            self.difficulty = self.compute_difficulty(self.difficulty,
                                                      last_stamp - old_stamp)
            self.logger.debug("New difficulty %02x" % self.difficulty)

        return True
Exemplo n.º 11
0
    def putoneblock(self, block):
        try:
            core.CheckBlock(block)
        except core.CheckBlockError:
            self.log.info(
                "Invalid block {}".format(block.GetHash().encode('hex')))
            return False

        if not self.have_prevblock(block):
            self.orphans[block.GetHash()] = True
            self.orphan_deps[block.hashPrevBlock] = block
            self.log.info("Orphan block {} ({} orphans)"
                          .format(block.GetHash().encode('hex'),
                                  len(self.orphan_deps)))
            return False

        top_height = self.getheight()
        top_work = long(self.db.Get(b'misc:total_work'), 16)

        # read metadata for previous block
        prevmeta = BlkMeta()
        if top_height >= 0:
            prevmeta.deserialize(self.db.Get(b'blkmeta:' + block.hashPrevBlock))

        batch = leveldb.WriteBatch()

        # build network "block" msg, as canonical disk storage form
        msg = msg_block()
        msg.block = block
        f = io.BytesIO()
        msg.msg_ser(f)
        msg_data = f.getvalue()

        # write "block" msg to storage
        fpos = self.blk_write.tell()
        self.blk_write.write(msg_data)
        self.blk_write.flush()

        # add index entry
        batch.Put(b'blocks:' + block.GetHash(), str(fpos))

        # store metadata related to this block
        blkmeta = BlkMeta()
        blkmeta.height = prevmeta.height + 1
        blkmeta.work = (prevmeta.work +
                        serialize.uint256_from_compact(block.nBits))
        batch.Put(b'blkmeta:' + block.GetHash(), blkmeta.serialize())

        # store list of blocks at this height
        heightidx = HeightIdx()
        heightstr = str(blkmeta.height)
        try:
            heightidx.deserialize(self.db.Get(b'height:' + heightstr))
        except KeyError:
            pass
        heightidx.blocks.append(block.GetHash())

        batch.Put(b'height:' + heightstr, heightidx.serialize())
        self.db.Write(batch)

        # if chain is not best chain, proceed no further
        if blkmeta.work <= top_work:
            self.log.info(
                "height {} (weak), block {}"
                .format(blkmeta.height, block.GetHash().encode('hex')))
            return True

        # update global chain pointers
        if not self.set_best_chain(block.hashPrevBlock, block.GetHash(),
                                   block, blkmeta):
            return False

        return True
Exemplo n.º 12
0
    def putoneblock(self, block):
        try:
            core.CheckBlock(block)
        except core.CheckBlockError:
            self.log.info("Invalid block {}".format(
                block.GetHash().encode('hex')))
            return False

        if not self.have_prevblock(block):
            self.orphans[block.GetHash()] = True
            self.orphan_deps[block.hashPrevBlock] = block
            self.log.info("Orphan block {} ({} orphans)".format(
                block.GetHash().encode('hex'), len(self.orphan_deps)))
            return False

        top_height = self.getheight()
        top_work = long(self.db.Get(b'misc:total_work'), 16)

        # read metadata for previous block
        prevmeta = BlkMeta()
        if top_height >= 0:
            prevmeta.deserialize(self.db.Get(b'blkmeta:' +
                                             block.hashPrevBlock))

        batch = leveldb.WriteBatch()

        # build network "block" msg, as canonical disk storage form
        msg = msg_block()
        msg.block = block
        f = io.BytesIO()
        msg.msg_ser(f)
        msg_data = f.getvalue()

        # write "block" msg to storage
        fpos = self.blk_write.tell()
        self.blk_write.write(msg_data)
        self.blk_write.flush()

        # add index entry
        batch.Put(b'blocks:' + block.GetHash(), str(fpos))

        # store metadata related to this block
        blkmeta = BlkMeta()
        blkmeta.height = prevmeta.height + 1
        blkmeta.work = (prevmeta.work +
                        serialize.uint256_from_compact(block.nBits))
        batch.Put(b'blkmeta:' + block.GetHash(), blkmeta.serialize())

        # store list of blocks at this height
        heightidx = HeightIdx()
        heightstr = str(blkmeta.height)
        try:
            heightidx.deserialize(self.db.Get(b'height:' + heightstr))
        except KeyError:
            pass
        heightidx.blocks.append(block.GetHash())

        batch.Put(b'height:' + heightstr, heightidx.serialize())
        self.db.Write(batch)

        # if chain is not best chain, proceed no further
        if blkmeta.work <= top_work:
            self.log.info("height {} (weak), block {}".format(
                blkmeta.height,
                block.GetHash().encode('hex')))
            return True

        # update global chain pointers
        if not self.set_best_chain(block.hashPrevBlock, block.GetHash(), block,
                                   blkmeta):
            return False

        return True
Exemplo n.º 13
0
 def send_block(self, connection, block):
     msg = messages.msg_block()
     msg.block = block
     connection.send('block', msg)
     logging.info('send CBlock(hash={}) to {}'.format(core.b2lx(block.GetHash()), self.repr_connection(connection)))