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
Example #2
0
    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"]
Example #3
0
    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
Example #4
0
    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)
Example #5
0
    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
Example #6
0
    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)
Example #7
0
    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"]
Example #8
0
    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
Example #9
0
    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
Example #10
0
    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
Example #11
0
    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)
Example #12
0
    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)