def __get_test_block(): block_builder = BlockBuilder.new("0.1a", TransactionVersioner()) block_builder.height = 0 block_builder.prev_hash = None block = block_builder.build( ) # It does not have commit state. It will be rebuilt. return block
def genesis_invoke(self, block: Block) -> ('Block', dict): method = "icx_sendTransaction" transactions = [] for tx in block.body.transactions.values(): hash_version = conf.CHANNEL_OPTION[ ChannelProperty().name]["genesis_tx_hash_version"] tx_serializer = TransactionSerializer.new(tx.version, hash_version) transaction = { "method": method, "params": { "txHash": tx.hash.hex() }, "genesisData": tx_serializer.to_full_data(tx) } transactions.append(transaction) request = { 'block': { 'blockHeight': block.header.height, 'blockHash': block.header.hash.hex(), 'timestamp': block.header.timestamp }, 'transactions': transactions } request = convert_params(request, ParamType.invoke) stub = StubCollection().icon_score_stubs[ChannelProperty().name] response = stub.sync_task().invoke(request) response_to_json_query(response) block_builder = BlockBuilder.from_new(block) block_builder.commit_state = { ChannelProperty().name: response['stateRootHash'] } new_block = block_builder.build() return new_block, response["txResults"]
async def announce_confirmed_block(self, serialized_block, commit_state="{}"): try: bs = BlockSerializer.new("0.1a") json_block = json.loads(serialized_block) confirmed_block = bs.deserialize(json_block) util.logger.spam(f"channel_inner_service:announce_confirmed_block\n " f"hash({confirmed_block.header.hash.hex()}) " f"block height({confirmed_block.header.height}), " f"commit_state({commit_state})") header: blocks.v0_1a.BlockHeader = confirmed_block.header if not header.commit_state: bb = BlockBuilder.from_new(confirmed_block) confirmed_block = bb.build() # to generate commit_state header = confirmed_block.header try: commit_state = ast.literal_eval(commit_state) except Exception as e: logging.warning(f"channel_inner_service:announce_confirmed_block FAIL get commit_state_dict, " f"error by : {e}") if header.commit_state != commit_state: raise RuntimeError(f"Commit states does not match. " f"Generated {header.commit_state}, Received {commit_state}") if self._channel_service.block_manager.get_blockchain().block_height < confirmed_block.header.height: self._channel_service.block_manager.add_confirmed_block(confirmed_block) else: logging.debug(f"channel_inner_service:announce_confirmed_block " f"already synced block height({confirmed_block.header.height})") response_code = message_code.Response.success except Exception as e: logging.error(f"announce confirmed block error : {e}") response_code = message_code.Response.fail return response_code
def __add_genesis_block(self, tx_info: dict, reps: List[ExternalAddress]): """ :param tx_info: Transaction data for making genesis block from an initial file :return: """ logging.info("Make Genesis Block....") tx_builder = TransactionBuilder.new("genesis", self.tx_versioner) nid = tx_info.get("nid") if nid is not None: nid = int(nid, 16) tx_builder.nid = nid # Optional. It will be 0x3 except for mainnet and testnet if not defined tx_builder.accounts = tx_info["accounts"] tx_builder.message = tx_info["message"] tx = tx_builder.build() block_version = self.block_versioner.get_version(0) block_builder = BlockBuilder.new(block_version, self.tx_versioner) block_builder.height = 0 block_builder.fixed_timestamp = 0 block_builder.prev_hash = None block_builder.next_leader = ExternalAddress.fromhex(self.__peer_id) block_builder.transactions[tx.hash] = tx block_builder.reps = reps block = block_builder.build( ) # It does not have commit state. It will be rebuilt. block, invoke_results = ObjectManager().channel_service.genesis_invoke( block) self.set_invoke_results(block.header.hash.hex(), invoke_results) self.add_block(block)
def _makeup_block(self): block_builder = BlockBuilder.new("0.1a") tx_versions = TransactionVersions() while self._txQueue: if len(block_builder) >= conf.MAX_TX_SIZE_IN_BLOCK: logging.debug( f"consensus_base total size({len(block_builder)}) " f"count({len(block_builder.transactions)}) " f"_txQueue size ({len(self._txQueue)})") break tx: 'Transaction' = self._txQueue.get_item_in_status( TransactionStatusInQueue.normal, TransactionStatusInQueue.added_to_block) if tx is None: break tx_hash_version = tx_versions.get_hash_generator_version( tx.version) tv = TransactionVerifier.new(tx.version, tx_hash_version) try: tv.verify(tx, self._blockchain) except Exception as e: logging.warning(f"tx hash invalid. tx: {tx}") else: block_builder.transactions[tx.hash] = tx return block_builder
def __add_genesis_block(self, tx_info: dict = None): """ :param tx_info: Transaction data for making genesis block from an initial file :return: """ logging.info("Make Genesis Block....") genesis_hash_version = conf.CHANNEL_OPTION[ self.__channel_name]["genesis_tx_hash_version"] tx_builder = TransactionBuilder.new("genesis", genesis_hash_version) nid = tx_info.get("nid") if nid is not None: nid = int(nid, 16) tx_builder.nid = nid # Optional. It will be 0x3 except for mainnet and testnet if not defined tx_builder.accounts = tx_info["accounts"] tx_builder.message = tx_info["message"] tx = tx_builder.build() block_builder = BlockBuilder.new("0.1a") block_builder.height = 0 block_builder.fixed_timestamp = 0 block_builder.prev_hash = None block_builder.transactions[tx.hash] = tx block = block_builder.build( ) # It does not have commit state. It will be rebuilt. block, invoke_results = ObjectManager().channel_service.genesis_invoke( block) self.set_invoke_results(block.header.hash.hex(), invoke_results) self.add_block(block)
def score_invoke(self, _block: Block) -> dict or None: method = "icx_sendTransaction" transactions = [] for tx in _block.body.transactions.values(): tx_serializer = TransactionSerializer.new(tx.version, self.block_manager.get_blockchain().tx_versioner) transaction = { "method": method, "params": tx_serializer.to_full_data(tx) } transactions.append(transaction) request = { 'block': { 'blockHeight': _block.header.height, 'blockHash': _block.header.hash.hex(), 'prevBlockHash': _block.header.prev_hash.hex() if _block.header.prev_hash else '', 'timestamp': _block.header.timestamp }, 'transactions': transactions } request = convert_params(request, ParamType.invoke) stub = StubCollection().icon_score_stubs[ChannelProperty().name] response = stub.sync_task().invoke(request) response_to_json_query(response) block_builder = BlockBuilder.from_new(_block, self.__block_manager.get_blockchain().tx_versioner) block_builder.commit_state = { ChannelProperty().name: response['stateRootHash'] } new_block = block_builder.build() return new_block, response["txResults"]
def makeup_block(self, complained_result: str): # self._check_unconfirmed_block( last_block = self.__blockchain.last_unconfirmed_block or self.__blockchain.last_block block_height = last_block.header.height + 1 block_version = self.__blockchain.block_versioner.get_version(block_height) block_builder = BlockBuilder.new(block_version, self.__blockchain.tx_versioner) if not complained_result: self.__add_tx_to_block(block_builder) return block_builder
def genesis_invoke(self, block: Block) -> ('Block', dict): method = "icx_sendTransaction" transactions = [] for tx in block.body.transactions.values(): tx_serializer = TransactionSerializer.new( tx.version, self.block_manager.get_blockchain().tx_versioner) transaction = { "method": method, "params": { "txHash": tx.hash.hex() }, "genesisData": tx_serializer.to_full_data(tx) } transactions.append(transaction) request = { 'block': { 'blockHeight': block.header.height, 'blockHash': block.header.hash.hex(), 'timestamp': block.header.timestamp }, 'transactions': transactions } request = convert_params(request, ParamType.invoke) stub = StubCollection().icon_score_stubs[ChannelProperty().name] response = stub.sync_task().invoke(request) response_to_json_query(response) tx_receipts = response["txResults"] block_builder = BlockBuilder.from_new( block, self.block_manager.get_blockchain().tx_versioner) block_builder.reset_cache() block_builder.peer_id = block.header.peer_id block_builder.signature = block.header.signature block_builder.commit_state = { ChannelProperty().name: response['stateRootHash'] } block_builder.state_hash = Hash32( bytes.fromhex(response['stateRootHash'])) block_builder.receipts = tx_receipts block_builder.reps = self.get_rep_ids() new_block = block_builder.build() return new_block, tx_receipts
def _makeup_block(self): # self._check_unconfirmed_block() block_height = self._blockchain.last_block.header.height + 1 block_version = self._blockchain.block_versioner.get_version( block_height) block_builder = BlockBuilder.new(block_version, self._blockchain.tx_versioner) tx_versioner = self._blockchain.tx_versioner while self._txQueue: if block_builder.size() >= conf.MAX_TX_SIZE_IN_BLOCK: logging.debug( f"consensus_base total size({block_builder.size()}) " f"count({len(block_builder.transactions)}) " f"_txQueue size ({len(self._txQueue)})") break tx: 'Transaction' = self._txQueue.get_item_in_status( TransactionStatusInQueue.normal, TransactionStatusInQueue.added_to_block) if tx is None: break tv = TransactionVerifier.new(tx.version, tx_versioner) try: tv.verify(tx, self._blockchain) except Exception as e: logging.warning(f"tx hash invalid.\n" f"tx: {tx}\n" f"exception: {e}") traceback.print_exc() else: block_builder.transactions[tx.hash] = tx return block_builder
async def consensus(self): start_time = time.time() empty_block: Block = None try: self._loop = asyncio.get_event_loop() self._vote_queue = asyncio.Queue(loop=self._loop) block_builder = self._makeup_block() if len(block_builder.transactions ) == 0 and not conf.ALLOW_MAKE_EMPTY_BLOCK: return peer_manager = ObjectManager().channel_service.peer_manager last_block = self._blockchain.last_block block_builder.height = last_block.header.height + 1 block_builder.prev_hash = last_block.header.hash block_builder.next_leader = Address.fromhex( peer_manager.get_next_leader_peer().peer_id) block_builder.peer_private_key = ObjectManager( ).channel_service.peer_auth.peer_private_key block_builder.confirm_prev_block = (self._made_block_count > 0) candidate_block = block_builder.build() candidate_block, invoke_results = ObjectManager( ).channel_service.score_invoke(candidate_block) block_verifier = BlockVerifier.new("0.1a") block_verifier.verify(candidate_block, self._blockchain.last_block, self._blockchain) logging.info( f"candidate block height: {candidate_block.header.height}") logging.info( f"candidate block hash: {candidate_block.header.hash.hex()}") logging.info( f"candidate block next leader: {candidate_block.header.next_leader.hex()}" ) logging.info( f"candidate block confirm_prev_block: {candidate_block.body.confirm_prev_block}" ) vote = Vote(candidate_block.header.hash.hex(), ObjectManager().channel_service.peer_manager) vote.add_vote(ChannelProperty().group_id, ChannelProperty().peer_id, True) self._blockmanager.broadcast_send_unconfirmed_block( candidate_block) success = await self._wait_for_voting(candidate_block, vote) if not success: return self._blockmanager.set_invoke_results( candidate_block.header.hash.hex(), invoke_results) self._blockmanager.add_block(candidate_block) self._made_block_count += 1 pending_tx = self._txQueue.get_item_in_status( TransactionStatusInQueue.normal, TransactionStatusInQueue.normal) if not pending_tx and not conf.ALLOW_MAKE_EMPTY_BLOCK: block_builder = BlockBuilder.new("0.1a") block_builder.prev_hash = candidate_block.header.hash block_builder.height = candidate_block.header.height + 1 block_builder.next_leader = candidate_block.header.next_leader block_builder.peer_private_key = ObjectManager( ).channel_service.peer_auth.peer_private_key block_builder.confirm_prev_block = True empty_block = block_builder.build() self._blockmanager.broadcast_send_unconfirmed_block( empty_block) ObjectManager().channel_service.state_machine.turn_to_peer() finally: if not empty_block: elapsed_time = time.time() - start_time delay_time = conf.INTERVAL_BLOCKGENERATION - elapsed_time self._start_consensus_timer(delay_time)
def test_block_v0_3(self): private_auth = test_util.create_default_peer_auth() tx_versioner = TransactionVersioner() dummy_receipts = {} block_builder = BlockBuilder.new("0.3", tx_versioner) for i in range(1000): tx_builder = TransactionBuilder.new("0x3", tx_versioner) tx_builder.private_key = private_auth.private_key tx_builder.to_address = ExternalAddress.new() tx_builder.step_limit = random.randint(0, 10000) tx_builder.value = random.randint(0, 10000) tx_builder.nid = 2 tx = tx_builder.build() tx_serializer = TransactionSerializer.new(tx.version, tx_versioner) block_builder.transactions[tx.hash] = tx dummy_receipts[tx.hash.hex()] = { "dummy_receipt": "dummy", "tx_dumped": tx_serializer.to_full_data(tx) } block_builder.peer_private_key = private_auth.private_key block_builder.height = 0 block_builder.state_hash = Hash32(bytes(Hash32.size)) block_builder.receipts = dummy_receipts block_builder.reps = [ ExternalAddress.fromhex_address(private_auth.address) ] block_builder.next_leader = ExternalAddress.fromhex( "hx00112233445566778899aabbccddeeff00112233") block = block_builder.build() block_verifier = BlockVerifier.new("0.3", tx_versioner) block_verifier.invoke_func = lambda b: (block, dummy_receipts) block_verifier.verify(block, None, None, block.header.peer_id, reps=block_builder.reps) block_serializer = BlockSerializer.new("0.3", tx_versioner) block_serialized = block_serializer.serialize(block) block_deserialized = block_serializer.deserialize(block_serialized) assert block.header == block_deserialized.header # FIXME : confirm_prev_block not serialized # assert block.body == block_deserialized.body tx_hashes = list(block.body.transactions) tx_index = random.randrange(0, len(tx_hashes)) block_prover = BlockProver.new(block.header.version, tx_hashes, BlockProverType.Transaction) tx_proof = block_prover.get_proof(tx_index) assert block_prover.prove(tx_hashes[tx_index], block.header.transaction_hash, tx_proof) block_prover = BlockProver.new(block.header.version, block_builder.receipts, BlockProverType.Receipt) receipt_proof = block_prover.get_proof(tx_index) receipt_hash = block_prover.to_hash32(block_builder.receipts[tx_index]) assert block_prover.prove(receipt_hash, block.header.receipt_hash, receipt_proof)