def export_blocks(ctx, from_, to, file): """Export the blockchain to FILE. The chain will be stored in binary format, i.e. as a concatenated list of RLP encoded blocks, starting with the earliest block. If the file already exists, the additional blocks are appended. Otherwise, a new file is created. Use - to write to stdout. """ app = EthApp(ctx.obj['config']) DBService.register_with_app(app) AccountsService.register_with_app(app) ChainService.register_with_app(app) if from_ is None: from_ = 0 head_number = app.services.chain.chain.head.number if to is None: to = head_number if from_ < 0: log.fatal('block numbers must not be negative') sys.exit(1) if to < from_: log.fatal('"to" block must be newer than "from" block') sys.exit(1) if to > head_number: log.fatal( '"to" block not known (current head: {})'.format(head_number)) sys.exit(1) log.info('Starting export') for n in xrange(from_, to + 1): log.debug('Exporting block {}'.format(n)) if (n - from_) % 50000 == 0: log.info('Exporting block {} to {}'.format(n, min(n + 50000, to))) block_hash = app.services.chain.chain.index.get_block_by_number(n) # bypass slow block decoding by directly accessing db block_rlp = app.services.db.get(block_hash) file.write(block_rlp) log.info('Export complete')
def export_blocks(ctx, from_, to, file): """Export the blockchain to FILE. The chain will be stored in binary format, i.e. as a concatenated list of RLP encoded blocks, starting with the earliest block. If the file already exists, the additional blocks are appended. Otherwise, a new file is created. Use - to write to stdout. """ app = EthApp(ctx.obj['config']) DBService.register_with_app(app) AccountsService.register_with_app(app) ChainService.register_with_app(app) if from_ is None: from_ = 0 head_number = app.services.chain.chain.head.number if to is None: to = head_number if from_ < 0: log.fatal('block numbers must not be negative') sys.exit(1) if to < from_: log.fatal('"to" block must be newer than "from" block') sys.exit(1) if to > head_number: log.fatal('"to" block not known (current head: {})'.format(head_number)) sys.exit(1) log.info('Starting export') for n in xrange(from_, to + 1): log.debug('Exporting block {}'.format(n)) if (n - from_) % 50000 == 0: log.info('Exporting block {} to {}'.format(n, min(n + 50000, to))) block_hash = app.services.chain.chain.index.get_block_by_number(n) # bypass slow block decoding by directly accessing db block_rlp = app.services.db.get(block_hash) file.write(block_rlp) log.info('Export complete')
def import_blocks(ctx, file): """Import blocks from FILE. Blocks are expected to be in binary format, i.e. as a concatenated list of RLP encoded blocks. Blocks are imported sequentially. If a block can not be imported (e.g. because it is badly encoded, it is in the chain already or its parent is not in the chain) it will be ignored, but the process will continue. Sole exception: If neither the first block nor its parent is known, importing will end right away. Use - to read from stdin. """ app = EthApp(ctx.obj['config']) DBService.register_with_app(app) AccountsService.register_with_app(app) ChainService.register_with_app(app) chain = app.services.chain assert chain.block_queue.empty() data = file.read() app.start() def blocks(): """Generator for blocks encoded in `data`.""" i = 0 while i < len(data): try: block_data, next_i = rlp.codec.consume_item(data, i) except rlp.DecodingError: log.fatal('invalid RLP encoding', byte_index=i) sys.exit(1) # have to abort as we don't know where to continue try: if not isinstance(block_data, list) or len(block_data) != 3: raise rlp.DeserializationError('', block_data) yield eth_protocol.TransientBlock(block_data) except (IndexError, rlp.DeserializationError): log.warning('not a valid block', byte_index=i) # we can still continue yield None i = next_i log.info('importing blocks') # check if it makes sense to go through all blocks first_block = next(blocks()) if first_block is None: log.fatal('first block invalid') sys.exit(1) if not (chain.knows_block(first_block.header.hash) or chain.knows_block(first_block.header.prevhash)): log.fatal('unlinked chains', newest_known_block=chain.chain.head.number, first_unknown_block=first_block.header.number) sys.exit(1) # import all blocks for n, block in enumerate(blocks()): if block is None: log.warning('skipping block', number_in_file=n) continue log.debug('adding block to queue', number_in_file=n, number_in_chain=block.header.number) app.services.chain.add_block(block, None) # None for proto # let block processing finish while not app.services.chain.block_queue.empty(): gevent.sleep() app.stop() log.info('import finished', head_number=app.services.chain.chain.head.number)