class TxItemJson:
    tx_versions = TransactionVersions()
    tx_serializers = {
        "0x2":
        TransactionSerializer.new(
            "0x2", tx_versions.get_hash_generator_version("0x2")),
        "0x3":
        TransactionSerializer.new(
            "0x3", tx_versions.get_hash_generator_version("0x3"))
    }

    def __init__(self, tx_json: str, channel: str):
        self.channel = channel
        self.__tx_json = tx_json
        self.__len = sys.getsizeof(tx_json) + sys.getsizeof(channel)

    def __len__(self):
        return self.__len

    def get_tx_message(self):
        message = loopchain_pb2.TxSend(tx_json=self.__tx_json,
                                       channel=self.channel)
        return message

    @classmethod
    def create_tx_item(cls, tx: Transaction, channel: str):
        # util.logger.spam(f"tx_item_helper_icx:create_tx_item create_tx_param({create_tx_param})")
        tx_serializer = cls.tx_serializers[tx.version]

        tx_item = TxItemJson(json.dumps(tx_serializer.to_raw_data(tx)),
                             channel)
        return tx_item
Exemple #2
0
    async def get_block_v2(self, block_height, block_hash, block_data_filter,
                           tx_data_filter):
        # This is a temporary function for v2 support of exchanges.
        block, block_filter, block_hash, fail_response_code, tx_filter = await self.__get_block(
            block_data_filter, block_hash, block_height, tx_data_filter)
        if fail_response_code:
            return fail_response_code, block_hash, json.dumps({}), ""

        bs = BlockSerializer.new(block.header.version)
        block_data_dict = bs.serialize(block)

        if block.header.height == 0:
            return message_code.Response.success, block_hash, json.dumps(
                block_data_dict), []

        confirmed_tx_list = block_data_dict["confirmed_transaction_list"]
        confirmed_tx_list_without_fail = []

        tv = TransactionVersions()
        tss = {
            "genesis":
            TransactionSerializer.new(
                "genesis", tv.get_hash_generator_version("genesis")),
            "0x2":
            TransactionSerializer.new("0x2",
                                      tv.get_hash_generator_version("0x2")),
            "0x3":
            TransactionSerializer.new("0x3",
                                      tv.get_hash_generator_version("0x3"))
        }

        for tx in confirmed_tx_list:
            version = tv.get_version(tx)
            tx_hash = tss[version].get_hash(tx)

            invoke_result = self._channel_service.block_manager.get_invoke_result(
                tx_hash)

            if 'failure' in invoke_result:
                continue

            if tv.get_version(tx) == "0x3":
                step_used, step_price = int(invoke_result["stepUsed"],
                                            16), int(
                                                invoke_result["stepPrice"], 16)
                tx["fee"] = hex(step_used * step_price)

            confirmed_tx_list_without_fail.append(tx)

        # Replace the existing confirmed_tx_list with v2 ver.
        block_data_dict[
            "confirmed_transaction_list"] = confirmed_tx_list_without_fail
        block_data_json = json.dumps(block_data_dict)

        if fail_response_code:
            return fail_response_code, block_hash, json.dumps({}), []

        return message_code.Response.success, block_hash, block_data_json, []
Exemple #3
0
    def test_hash_case_v3_escape(self):
        request = r'''{
            "jsonrpc": "2.0",
            "method": "icx_sendTransaction",
            "id": 1234,
            "params": {
                "version": "0x3",
                "from": "hxbe258ceb872e08851f1f59694dac2558708ece11",
                "to": "cxb0776ee37f5b45bfaea8cff1d8232fbb6122ec32",
                "stepLimit": "0x12345",
                "timestamp": "0x563a6cf330136",
                "nonce": "0x1",
                "nid": "0x2",
                "signature": "VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA=",
                "dataType": "call",
                "data": {
                    "method": "transfer",
                    "params": {
                        "to": "hx.ab2d8215eab\\14bc6bdd8bfb2c[8151257]032ec{d8}b",
                        "value": "0x1",
                        "array0": [
                            "1",
                            "2.21"
                        ],
                        "array1": [
                            {
                                "hash": "0x12",
                                "value": "0x34"
                            },
                            {
                                "hash": "0x56",
                                "value": "0x78"
                            }
                        ]
                    }
                }
            }
        }'''

        logging.info(f"request : {request}")
        request = json.loads(request)
        logging.info(f"request loaded : {request}")
        logging.info(f"to : {request['params']['data']['params']['to']}")

        question = request['params']
        answer = r"icx_sendTransaction.data.{method.transfer.params." \
                 r"{array0.[1.2\.21].array1.[{hash.0x12.value.0x34}.{hash.0x56.value.0x78}]." \
                 r"to.hx\.ab2d8215eab\\14bc6bdd8bfb2c\[8151257\]032ec\{d8\}b.value.0x1}}." \
                 r"dataType.call.from.hxbe258ceb872e08851f1f59694dac2558708ece11.nid.0x2.nonce.0x1.stepLimit.0x12345." \
                 r"timestamp.0x563a6cf330136.to.cxb0776ee37f5b45bfaea8cff1d8232fbb6122ec32.version.0x3"

        tv = TransactionVersions()
        version = tv.get_version(question)
        ts = TransactionSerializer.new(version,
                                       tv.get_hash_generator_version(version))
        tx = ts.from_(question)
        result = self.hash_generator.generate_salted_origin(
            ts.to_origin_data(tx))
        logging.info(f"result : {result}")
        self.assertEqual(result, answer)
Exemple #4
0
    async def create_icx_tx(self, kwargs: dict):
        result_code = None
        exception = None

        try:
            tv = TransactionVersions()
            tx_version = tv.get_version(kwargs)
            tx_hash_version = self._channel_service.get_channel_option()["tx_hash_version"]

            ts = TransactionSerializer.new(tx_version, tx_hash_version)
            tx = ts.from_(kwargs)

            tv = TransactionVerifier.new(tx_version, tx_hash_version)
            tv.verify(tx)

            block_manager = self._channel_service.block_manager
            block_manager.pre_validate(tx)

            logging.debug(f"create icx input : {kwargs}")

            self._channel_service.broadcast_scheduler.schedule_job(BroadcastCommand.CREATE_TX, tx)
            return message_code.Response.success, tx.hash.hex()

        except TransactionInvalidError as e:
            result_code = e.message_code
            exception = e
        except BaseException as e:
            result_code = TransactionInvalidError.message_code
            exception = e
        finally:
            if exception:
                logging.warning(f"create_icx_tx: tx restore fail for kwargs({kwargs}), {exception}")
                return result_code, None
    def add_tx_list(self, request) -> tuple:
        tx_list = []
        for tx_item in request.tx_list:
            tx_json = json.loads(tx_item.tx_json)

            tx_version = self.__tx_versioner.get_version(tx_json)

            ts = TransactionSerializer.new(tx_version, self.__tx_versioner)
            tx = ts.from_(tx_json)

            tv = TransactionVerifier.new(tx_version, self.__tx_versioner)
            tv.verify(tx)

            tx.size(self.__tx_versioner)

            tx_list.append(tx)

        tx_len = len(tx_list)
        if tx_len == 0:
            response_code = message_code.Response.fail
            message = "fail tx validate while AddTxList"
        else:
            self.__tx_queue.put(tx_list)
            response_code = message_code.Response.success
            message = f"success ({len(tx_list)})/({len(request.tx_list)})"

        return response_code, message
    def add_tx(self, request) -> None:
        tx_json = request.tx_json

        tx_versioner = self._channel_service.block_manager.get_blockchain(
        ).tx_versioner
        tx_version = tx_versioner.get_version(tx_json)

        ts = TransactionSerializer.new(tx_version, tx_versioner)
        tx = ts.from_(tx_json)

        tv = TransactionVerifier.new(tx_version, tx_versioner)
        tv.verify(tx)

        object_has_queue = self._channel_service.get_object_has_queue_by_consensus(
        )
        if tx is not None:
            object_has_queue.add_tx_obj(tx)
            util.apm_event(
                ChannelProperty().peer_id, {
                    'event_type': 'AddTx',
                    'peer_id': ChannelProperty().peer_id,
                    'peer_name': conf.PEER_NAME,
                    'channel_name': ChannelProperty().name,
                    'data': {
                        'tx_hash': tx.tx_hash
                    }
                })
    def add_tx(self, request) -> None:
        tx_json = request.tx_json

        tx_versioner = self._channel_service.block_manager.get_blockchain(
        ).tx_versioner
        tx_version = tx_versioner.get_version(tx_json)

        ts = TransactionSerializer.new(tx_version, tx_versioner)
        tx = ts.from_(tx_json)

        tv = TransactionVerifier.new(tx_version, tx_versioner)
        tv.verify(tx)

        if tx is not None:
            self._channel_service.block_manager.add_tx_obj(tx)
            util.apm_event(
                ChannelProperty().peer_id, {
                    'event_type': 'AddTx',
                    'peer_id': ChannelProperty().peer_id,
                    'peer_name': conf.PEER_NAME,
                    'channel_name': ChannelProperty().name,
                    'data': {
                        'tx_hash': tx.tx_hash
                    }
                })

        if not conf.ALLOW_MAKE_EMPTY_BLOCK:
            self._channel_service.start_leader_complain_timer_if_tx_exists()
Exemple #8
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"]
    def get_tx_info(self, tx_hash):
        tx = self._channel_service.block_manager.get_tx_queue().get(
            tx_hash, None)
        if tx:
            blockchain = self._channel_service.block_manager.get_blockchain()
            tx_serializer = TransactionSerializer.new(tx.version,
                                                      blockchain.tx_versioner)
            tx_origin = tx_serializer.to_origin_data(tx)

            logging.info(f"get_tx_info pending : tx_hash({tx_hash})")
            tx_info = dict()
            tx_info["transaction"] = tx_origin
            tx_info["tx_index"] = None
            tx_info["block_height"] = None
            tx_info["block_hash"] = None
            return message_code.Response.success, tx_info
        else:
            try:
                return message_code.Response.success, self._channel_service.block_manager.get_tx_info(
                    tx_hash)
            except KeyError as e:
                logging.error(
                    f"get_tx_info error : tx_hash({tx_hash}) not found error({e})"
                )
                response_code = message_code.Response.fail_invalid_key_error
                return response_code, None
Exemple #10
0
    def test_hash_origin_case_v2(self):
        request = r'''{
            "jsonrpc": "2.0",
            "method": "icx_sendTransaction",
            "id": 1234,
            "params": {
                "from": "hxbe258ceb872e08851f1f59694dac2558708ece11",
                "to": "hx5bfdb090f43a808005ffc27c25b213145e80b7cd",
                "value": "0xde0b6b3a7640000",
                "fee": "0x1000000",
                "timestamp": "1000000000000",
                "nonce": "0x1",
                "tx_hash": "a247a97a23398daccb66e2d61d63788b3c2edb91e1fdbb4f34d86d485eb72915",
                "signature": "VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA="
            }
        }'''

        logging.info(f"request : {request}")
        request = json.loads(request)
        logging.info(f"request loaded : {request}")

        question = request["params"]
        answer = "icx_sendTransaction.fee.0x1000000.from.hxbe258ceb872e08851f1f59694dac2558708ece11.nonce.0x1." \
                 "timestamp.1000000000000.to.hx5bfdb090f43a808005ffc27c25b213145e80b7cd." \
                 "value.0xde0b6b3a7640000"

        tv = TransactionVersions()
        version = tv.get_version(question)
        ts = TransactionSerializer.new(version,
                                       tv.get_hash_generator_version(version))
        tx = ts.from_(question)

        result = self.hash_generator.generate_salted_origin(
            ts.to_origin_data(tx))
        self.assertEqual(result, answer)
Exemple #11
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"]
    async def create_icx_tx(self, kwargs: dict):
        if self.__qos_controller.limit():
            util.logger.debug(f"Out of TPS limit. tx={kwargs}")
            return message_code.Response.fail_out_of_tps_limit, None

        node_type = self.__properties.get('node_type', None)
        if node_type is None:
            util.logger.warning("Node type has not been set yet.")
            return NodeInitializationError.message_code, None
        elif node_type != conf.NodeType.CommunityNode.value:
            return message_code.Response.fail_no_permission, None

        result_code = None
        exception = None
        tx = None

        try:
            tx_version = self.__tx_versioner.get_version(kwargs)

            ts = TransactionSerializer.new(tx_version, self.__tx_versioner)
            tx = ts.from_(kwargs)

            nid = self.__properties.get('nid', None)
            if nid is None:
                util.logger.warning(f"NID has not been set yet.")
                raise NodeInitializationError(tx.hash.hex())

            tv = TransactionVerifier.new(tx_version, self.__tx_versioner)
            tv.pre_verify(tx, nid=nid)

            self.__pre_validate(tx)

            logging.debug(f"create icx input : {kwargs}")

            self.__broadcast_scheduler.schedule_job(BroadcastCommand.CREATE_TX,
                                                    (tx, self.__tx_versioner))
            return message_code.Response.success, tx.hash.hex()

        except MessageCodeError as e:
            result_code = e.message_code
            exception = e
            traceback.print_exc()
        except BaseException as e:
            result_code = TransactionInvalidError.message_code
            exception = e
            traceback.print_exc()
        finally:
            if exception:
                logging.warning(f"create_icx_tx: tx restore fail.\n\n"
                                f"kwargs({kwargs})\n\n"
                                f"tx({tx})\n\n"
                                f"exception({exception})")
                return result_code, None
Exemple #13
0
    def __add_tx_to_block_db(self, block, invoke_results):
        """block db 에 block_hash - block_object 를 저장할때, tx_hash - block_hash 를 저장한다.
        get tx by tx_hash 시 해당 block 을 효율적으로 찾기 위해서
        :param block:
        """
        # loop all tx in block
        logging.debug("try add all tx in block to block db, block hash: " +
                      block.header.hash.hex())
        block_manager = ObjectManager().channel_service.block_manager
        tx_queue = block_manager.get_tx_queue()
        # util.logger.spam(f"blockchain:__add_tx_to_block_db::tx_queue : {tx_queue}")
        # util.logger.spam(
        #     f"blockchain:__add_tx_to_block_db::confirmed_transaction_list : {block.confirmed_transaction_list}")

        tx_hash_version = conf.CHANNEL_OPTION[
            self.__channel_name]["tx_hash_version"]
        for index, tx in enumerate(block.body.transactions.values()):
            tx_hash = tx.hash.hex()
            invoke_result = invoke_results[tx_hash]

            tx_serializer = TransactionSerializer.new(tx.version,
                                                      tx_hash_version)
            tx_info = {
                'block_hash': block.header.hash.hex(),
                'block_height': block.header.height,
                'tx_index': hex(index),
                'transaction': tx_serializer.to_raw_data(tx),
                'result': invoke_result
            }

            self.__confirmed_block_db.Put(
                tx_hash.encode(encoding=conf.HASH_KEY_ENCODING),
                json.dumps(tx_info).encode(encoding=conf.PEER_DATA_ENCODING))

            # try:
            #     util.logger.spam(
            #         f"blockchain:__add_tx_to_block_db::{tx_hash}'s status : {tx_queue.get_item_status(tx_hash)}")
            # except KeyError as e:
            #     util.logger.spam(f"__add_tx_to_block_db :: {e}")

            tx_queue.pop(tx_hash, None)
            # util.logger.spam(f"pop tx from queue:{tx_hash}")

            if block.header.height > 0:
                self.__save_tx_by_address_strategy(tx)

        self.__save_invoke_result_block_height(block.header.height)
Exemple #14
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
Exemple #15
0
    def add_tx_list(self, request) -> tuple:
        tx_validate_count = 0

        for tx_item in request.tx_list:
            tx_json = json.loads(tx_item.tx_json)

            tv = TransactionVersions()
            tx_version = tv.get_version(tx_json)
            tx_hash_version = self._channel_service.get_channel_option(
            )["tx_hash_version"]

            ts = TransactionSerializer.new(tx_version, tx_hash_version)
            tx = ts.from_(tx_json)

            tv = TransactionVerifier.new(tx_version, tx_hash_version)
            tv.verify(tx)

            # util.logger.spam(f"channel_inner_service:add_tx tx({tx.get_data_string()})")

            object_has_queue = self._channel_service.get_object_has_queue_by_consensus(
            )
            if tx is not None:
                object_has_queue.add_tx_obj(tx)
                tx_validate_count += 1
                util.apm_event(
                    ChannelProperty().peer_id, {
                        'event_type': 'AddTx',
                        'peer_id': ChannelProperty().peer_id,
                        'peer_name': conf.PEER_NAME,
                        'channel_name': ChannelProperty().name,
                        'data': {
                            'tx_hash': tx.hash.hex()
                        }
                    })

        if tx_validate_count == 0:
            response_code = message_code.Response.fail
            message = "fail tx validate while AddTxList"
        else:
            response_code = message_code.Response.success
            message = f"success ({tx_validate_count})/({len(request.tx_list)})"

        return response_code, message
    async def create_icx_tx(self, kwargs: dict):
        result_code = None
        exception = None
        tx = None

        try:
            tx_versioner = self._channel_service.block_manager.get_blockchain(
            ).tx_versioner
            tx_version = tx_versioner.get_version(kwargs)

            ts = TransactionSerializer.new(tx_version, tx_versioner)
            tx = ts.from_(kwargs)

            tv = TransactionVerifier.new(tx_version, tx_versioner)
            tv.verify(tx)

            block_manager = self._channel_service.block_manager
            block_manager.pre_validate(tx)

            logging.debug(f"create icx input : {kwargs}")

            self._channel_service.broadcast_scheduler.schedule_job(
                BroadcastCommand.CREATE_TX, (tx, tx_versioner))
            return message_code.Response.success, tx.hash.hex()

        except TransactionInvalidError as e:
            result_code = e.message_code
            exception = e
            traceback.print_exc()
        except BaseException as e:
            result_code = TransactionInvalidError.message_code
            exception = e
            traceback.print_exc()
        finally:
            if exception:
                logging.warning(f"create_icx_tx: tx restore fail.\n\n"
                                f"kwargs({kwargs})\n\n"
                                f"tx({tx})\n\n"
                                f"exception({exception})")
                return result_code, None
Exemple #17
0
    def find_tx_by_key(self, tx_hash_key):
        """find tx by hash

        :param tx_hash_key: tx hash
        :return None: There is no tx by hash or transaction object.
        """

        try:
            tx_info_json = self.find_tx_info(tx_hash_key)
        except KeyError as e:
            # This case is not an error.
            # Client send wrong tx_hash..
            # logging.warning(f"[blockchain::find_tx_by_key] Transaction is pending. tx_hash ({tx_hash_key})")
            return None
        if tx_info_json is None:
            logging.warning(f"tx not found. tx_hash ({tx_hash_key})")
            return None

        tx_data = tx_info_json["transaction"]
        tx_version = self.tx_versioner.get_version(tx_data)
        tx_serializer = TransactionSerializer.new(tx_version, self.tx_versioner)
        return tx_serializer.from_(tx_data)
 def get_serializer(cls, tx: Transaction,
                    tx_versioner: TransactionVersioner):
     if tx.version not in cls.tx_serializers:
         cls.tx_serializers[tx.version] = TransactionSerializer.new(
             tx.version, tx_versioner)
     return cls.tx_serializers[tx.version]
Exemple #19
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)
Exemple #20
0
    def test_hash_case_v2_v3_compatibility(self):

        # These methods are obsolete.
        # But this one and new one must have same results for v2 request.
        def create_origin_for_hash(json_data: dict):
            def gen_origin_str(json_data: dict):
                ordered_keys = list(json_data)
                ordered_keys.sort()
                for key in ordered_keys:
                    yield key
                    if isinstance(json_data[key], str):
                        yield json_data[key]
                    elif isinstance(json_data[key], dict):
                        yield from gen_origin_str(json_data[key])
                    elif isinstance(json_data[key], int):
                        yield str(json_data[key])
                    else:
                        raise TypeError(
                            f"{key} must be one of them(dict, str, int).")

            origin = ".".join(gen_origin_str(json_data))
            return origin

        def generate_icx_hash(icx_origin_data, tx_hash_key):
            copy_tx = copy.deepcopy(icx_origin_data)
            if 'method' in copy_tx:
                del copy_tx['method']
            if 'signature' in copy_tx:
                del copy_tx['signature']
            if tx_hash_key in copy_tx:
                del copy_tx[tx_hash_key]
            origin = create_origin_for_hash(copy_tx)
            origin = f"icx_sendTransaction.{origin}"
            # gen hash
            return hashlib.sha3_256(origin.encode()).digest()

        request = r'''{
            "jsonrpc": "2.0",
            "method": "icx_sendTransaction",
            "id": 1234,
            "params": {
                "version": "0x3",
                "from": "hxbe258ceb872e08851f1f59694dac2558708ece11",
                "to": "hx5bfdb090f43a808005ffc27c25b213145e80b7cd",
                "value": "0xde0b6b3a7640000",
                "timestamp": "0x563a6cf330136",
                "nonce": "0x1",
                "stepLimit": "0x100000",
                "nid": "0x2",
                "signature": "VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA="
            }
        }'''

        logging.info(f"request : {request}")
        request = json.loads(request)
        logging.info(f"request loaded : {request}")

        question = request["params"]

        tv = TransactionVersions()
        version = tv.get_version(question)
        ts = TransactionSerializer.new(version,
                                       tv.get_hash_generator_version(version))
        tx = ts.from_(question)

        result_new_hash = self.hash_generator.generate_hash(
            ts.to_origin_data(tx))
        result_old_hash = generate_icx_hash(question, "tx_hash")
        self.assertEqual(result_new_hash, result_old_hash)

        v0_hash_generator = build_hash_generator(0, "icx_sendTransaction")
        result_old_hash = v0_hash_generator.generate_hash(
            ts.to_origin_data(tx))

        self.assertEquals(result_new_hash, result_old_hash)