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)
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)
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)
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)
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)
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)
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
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
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
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
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
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
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)))