def test_verify_success_and_no_exc_with_fake_value_at_second(
            self, tx_version, tx_factory: 'TxFactory', raise_exception,
            expected_exc, target_attr, fake_value, monkeypatch):
        """Check that the result is successfully cached and bypasses further verifications which could raise exceptions.

        Do not apply this usecase in code!
        This test aims the reliablity of cache logic, not for the usefulness of this case.
        """
        tx = tx_factory(tx_version)
        tv = TransactionVerifier.new(tx.version,
                                     tx.type(),
                                     tx_versioner,
                                     raise_exceptions=raise_exception)
        verify_func = getattr(tv, f"verify_{target_attr}")

        # First verification
        verify_func(tx)

        # Monkeypatch with fake value
        object.__setattr__(tx, target_attr, fake_value)
        assert getattr(tx, target_attr) == fake_value

        # Verify again with fake value and ensure no exceptions raised
        if raise_exception:
            verify_func(tx)
        else:
            tv.exceptions.clear()
            assert not tv.exceptions
            verify_func(tx)
            assert not tv.exceptions
Esempio n. 2
0
    def add_tx(self, request) -> None:
        tx_json = request.tx_json

        tx_versioner = self._blockchain.tx_versioner
        tx_version, tx_type = tx_versioner.get_version(tx_json)

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

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

        if tx is not None:
            self._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()
Esempio n. 3
0
    def add_tx_list(self, request) -> tuple:
        if self.__nid is None:
            response_code = message_code.Response.fail
            message = "Node initialization is not completed."
            return response_code, message

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

            tx_version, tx_type = self.__tx_versioner.get_version(tx_json)

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

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

            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
Esempio n. 4
0
    def test_verify_hash(self, tx_version, tx_factory: 'TxFactory'):
        tx: Transaction = tx_factory(tx_version)
        tv = TransactionVerifier.new(version=tx.version,
                                     type_=tx.type(),
                                     versioner=tx_versioner)

        tv.verify_hash(tx)
Esempio n. 5
0
    def test_transaction_v3_invalid_nid(self):
        MockBlockchain = namedtuple("MockBlockchain",
                                    "find_nid find_tx_by_key")
        nids = list(range(0, 1000))
        random.shuffle(nids)

        tb = TransactionBuilder.new("0x3", None, self.tx_versioner)
        tb.step_limit = 1000000
        tb.value = 100000
        tb.signer = self.signer
        tb.to_address = ExternalAddress(os.urandom(20))
        tb.nid = nids[0]
        tb.nonce = random.randint(0, 100000)
        tb.data = "test"
        tb.data_type = "message"
        tx = tb.build()

        expected_nid = nids[1]
        mock_blockchain = MockBlockchain(find_nid=lambda: hex(expected_nid),
                                         find_tx_by_key=lambda _: False)

        tv = TransactionVerifier.new(tx.version, tx.type(), self.tx_versioner)
        self.assertRaises(TransactionInvalidNidError,
                          lambda: tv.verify(tx, mock_blockchain))
        self.assertRaises(TransactionInvalidNidError,
                          lambda: tv.pre_verify(tx, nid=expected_nid))
Esempio n. 6
0
    def test_transaction_v2_invalid_signature(self):
        # noinspection PyDictCreation
        tx_dumped = {
            'from':
            'hx48cd6eb32339d5c719dcc0af21e9bc3b67d733e6',
            'to':
            'hx22f72e44141bedd50d1e536455682863d3d8a484',
            'value':
            '0x186a0',
            'fee':
            '0xf4240',
            'timestamp':
            '1558679280067963',
            'nonce':
            '1',
            'tx_hash':
            '34477b3bc76fa73aad0258ba9fd36f28a3c4b26956c1e5eb92ddda7d98df4e32',  # valid hash
            'signature':
            'W/hW/PAo+ExeSsreD//yJVgNqmnkWKs+m0VUqE11O7Ek82yEINuczLRXtj1k515q8Ep4OLsRPPiPNjDM9vuhsgE='
        }
        tx_dumped['signature'] = Signature(os.urandom(
            Signature.size)).to_base64str()  # invalid signature

        tx_version, tx_type = self.tx_versioner.get_version(tx_dumped)
        ts = TransactionSerializer.new(tx_version, tx_type, self.tx_versioner)
        tx = ts.from_(tx_dumped)

        tv = TransactionVerifier.new(tx_version, tx_type, self.tx_versioner)
        self.assertRaises(TransactionInvalidSignatureError,
                          lambda: tv.verify(tx))
        self.assertRaises(TransactionInvalidSignatureError,
                          lambda: tv.pre_verify(tx))
    def test_exception_cached_when_raised_exception_while_verification(
            self, tx_version, tx_factory: 'TxFactory', raise_exception,
            expected_exc, target_attr, fake_value, monkeypatch):
        """Check that the exception successfully cached when raised any exception while verification step"""
        tx = tx_factory(tx_version)
        tv = TransactionVerifier.new(tx.version,
                                     tx.type(),
                                     tx_versioner,
                                     raise_exceptions=raise_exception)
        verify_func = getattr(tv, f"verify_{target_attr}")

        orig_value = getattr(tx, target_attr)
        test_values = (fake_value, orig_value)

        for test_value in test_values:
            # Monkeypatch
            object.__setattr__(tx, target_attr, test_value)
            assert getattr(tx, target_attr) == test_value

            # Verification test
            if raise_exception:
                with pytest.raises(expected_exc):
                    verify_func(tx)
            else:
                tv.exceptions.clear()
                assert not tv.exceptions
                verify_func(tx)
                assert isinstance(tv.exceptions[0], expected_exc)
Esempio n. 8
0
 def verify_transactions_loosely(self, block: 'Block', blockchain=None):
     for tx in block.body.transactions.values():
         tv = TransactionVerifier.new(tx.version, tx.type(),
                                      self._tx_versioner,
                                      self._raise_exceptions)
         tv.verify_loosely(tx, blockchain)
         if not self._raise_exceptions:
             self.exceptions.extend(tv.exceptions)
Esempio n. 9
0
    async def create_icx_tx(self, kwargs: dict):
        tx_hash = None
        relay_target = None
        if self.__qos_controller.limit():
            util.logger.debug(f"Out of TPS limit. tx={kwargs}")
            return message_code.Response.fail_out_of_tps_limit, tx_hash, relay_target

        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, tx_hash, relay_target
        elif node_type != conf.NodeType.CommunityNode.value:
            relay_target = self.__properties.get('relay_target', None)
            return message_code.Response.fail_no_permission, tx_hash, relay_target

        result_code = None
        exception = None
        tx = None

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

            ts = TransactionSerializer.new(tx_version, tx_type,
                                           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, tx_type,
                                         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(), relay_target

        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, tx_hash, relay_target
Esempio n. 10
0
    def test_verify_hash(self, tx_builder_factory: 'TxBuilderFactory'):
        tx_builder: TransactionBuilder = tx_builder_factory(self.tx_version)
        tx: Transaction = tx_builder.build(is_signing=False)

        tv = TransactionVerifier.new(version=tx.version,
                                     type_=tx.type(),
                                     versioner=tx_versioner)

        tv.verify_hash(tx)
Esempio n. 11
0
    def test_verify_signature(self, tx_version, tx_factory: 'TxFactory'):
        tx: Transaction = tx_factory(tx_version)
        tv = TransactionVerifier.new(version=tx.version,
                                     type_=tx.type(),
                                     versioner=tx_versioner)

        if tx_version != genesis.version:
            assert tx.hash
            assert tx.signature

            tv.verify_signature(tx)
Esempio n. 12
0
    def test_verify_tx_hash_unique(self, tx_version, tx_factory: 'TxFactory',
                                   mocker):
        tx: Transaction = tx_factory(tx_version)
        tv = TransactionVerifier.new(version=tx.version,
                                     type_=tx.type(),
                                     versioner=tx_versioner)

        mock_blockchain: BlockChain = mocker.MagicMock(spec=BlockChain)
        mock_blockchain.find_tx_by_key.return_value = None  # Not found in db, which means the tx is unique.

        tv.verify_tx_hash_unique(tx, mock_blockchain)
Esempio n. 13
0
    def test_verifier_version_check(self, tx_version, tx_factory: 'TxFactory'):
        tx: Transaction = tx_factory(tx_version)
        tv = TransactionVerifier.new(version=tx.version,
                                     type_=tx.type(),
                                     versioner=tx_versioner)

        if tx_version == genesis.version:
            assert isinstance(tv, genesis.TransactionVerifier)
        elif tx_version == v2.version:
            assert isinstance(tv, v2.TransactionVerifier)
        elif tx_version == v3.version:
            assert isinstance(tv, v3.TransactionVerifier)
    def test_benchmark_verify(self, benchmark, tx_version,
                              tx_factory: 'TxFactory', target_attr, tag):
        """Benchmark the elapsed time of verification func in various cases."""
        tx = tx_factory(tx_version)
        tv = TransactionVerifier.new(tx.version, tx.type(), tx_versioner)
        verify_func = getattr(tv, f"verify_{target_attr}")

        if tag == "first":
            benchmark(verify_func, tx)
        else:
            verify_func(tx)
            benchmark(verify_func, tx)
Esempio n. 15
0
    def verify_transactions(self, block: 'Block', blockchain=None):
        for tx in block.body.transactions.values():
            if not utils.is_in_time_boundary(tx.timestamp,
                                             conf.TIMESTAMP_BOUNDARY_SECOND,
                                             block.header.timestamp):
                exception = TransactionOutOfTimeBound(tx,
                                                      block.header.timestamp)
                self._handle_exception(exception)

            tv = TransactionVerifier.new(tx.version, tx.type(),
                                         self._tx_versioner,
                                         self._raise_exceptions)
            tv.verify(tx, blockchain)
            if not self._raise_exceptions:
                self.exceptions.extend(tv.exceptions)
    def test_has_cache_attr_when_verified_successfully(self, tx_version,
                                                       tx_factory: 'TxFactory',
                                                       raise_exception,
                                                       target_attr):
        """Check that the verification result has been cached successfully"""
        tx = tx_factory(tx_version)
        tv = TransactionVerifier.new(tx.version,
                                     tx.type(),
                                     tx_versioner,
                                     raise_exceptions=raise_exception)

        verify_func_name = f"verify_{target_attr}"
        verify_func = getattr(tv, verify_func_name)
        verify_func(tx)

        assert getattr(tx, f"_cache_{verify_func_name}")
Esempio n. 17
0
    def test_transaction_v2(self):
        tb = TransactionBuilder.new("0x2", None, self.tx_versioner)
        tb.fee = 1000000
        tb.value = 100000
        tb.signer = self.signer
        tb.to_address = ExternalAddress(os.urandom(20))
        tb.nonce = random.randint(0, 100000)
        tx = tb.build()

        tv = TransactionVerifier.new("0x2", tx.type(), self.tx_versioner)
        tv.verify(tx)

        ts = TransactionSerializer.new("0x2", tx.type(), self.tx_versioner)
        tx_raw_data = ts.to_raw_data(tx)

        self.assertEqual(ts.from_(tx_raw_data), tx)
Esempio n. 18
0
    def test_transaction_v2_duplicate_hash(self):
        MockBlockchain = namedtuple("MockBlockchain", "find_nid find_tx_by_key")

        tb = TransactionBuilder.new("0x2", None, self.tx_versioner)
        tb.fee = 1000000
        tb.value = 100000
        tb.signer = self.signer
        tb.to_address = ExternalAddress(os.urandom(20))
        tb.nonce = random.randint(0, 100000)
        tx = tb.build()

        mock_blockchain = MockBlockchain(find_nid=lambda: hex(3),
                                         find_tx_by_key=lambda _: True)

        tv = TransactionVerifier.new(tx.version, tx.type(), self.tx_versioner)
        self.assertRaises(TransactionDuplicatedHashError, lambda: tv.verify(tx, mock_blockchain))
Esempio n. 19
0
    def test_transaction_genesis(self):
        tb = TransactionBuilder.new("genesis", None, self.tx_versioner)
        tb.accounts = [{
            "name": "test0",
            "address": ExternalAddress(os.urandom(20)).hex_hx(),
            "balance": "0x12221231"
        }]
        tb.message = "Icon Loop"
        tx = tb.build(False)

        tv = TransactionVerifier.new("genesis", tx.type(), self.tx_versioner)
        tv.verify(tx)

        ts = TransactionSerializer.new("genesis", tx.type(), self.tx_versioner)
        tx_raw_data = ts.to_raw_data(tx)

        self.assertEqual(ts.from_(tx_raw_data), tx)
Esempio n. 20
0
    def test_transaction_v2_unsigned(self):
        signer = Signer.new()

        tb = TransactionBuilder.new("0x2", None, self.tx_versioner)
        tb.fee = 1000000
        tb.value = 100000
        tb.from_address = ExternalAddress.fromhex_address(signer.address)
        tb.to_address = ExternalAddress(os.urandom(20))
        tb.nonce = random.randint(0, 100000)
        tx = tb.build(is_signing=False)

        tv = TransactionVerifier.new("0x2", tx.type(), self.tx_versioner)
        self.assertRaises(TransactionInvalidSignatureError, lambda: tv.verify(tx))
        self.assertRaises(TransactionInvalidSignatureError, lambda: tv.pre_verify(tx))

        tb.signer = signer
        signed_tx = tb.sign_transaction(tx)
        tv.verify(signed_tx)
        tv.pre_verify(signed_tx)
Esempio n. 21
0
    def test_verify_hash_with_invalid_hash(
            self, tx_builder_factory: 'TxBuilderFactory', raise_exc):
        tx_builder: TransactionBuilder = tx_builder_factory(self.tx_version)
        tx: Transaction = tx_builder.build(is_signing=False)
        object.__setattr__(tx, "hash", Hash32(os.urandom(Hash32.size)))

        tv = TransactionVerifier.new(version=tx.version,
                                     type_=tx.type(),
                                     versioner=tx_versioner,
                                     raise_exceptions=raise_exc)

        if raise_exc:
            with pytest.raises(TransactionInvalidHashError):
                tv.verify_hash(tx)
        else:
            assert not tv.exceptions
            tv.verify_hash(tx)

            with pytest.raises(TransactionInvalidHashError):
                raise tv.exceptions[0]
Esempio n. 22
0
    def __add_tx_to_block(self, block_builder):
        tx_queue = self.__block_manager.get_tx_queue()

        block_tx_size = 0
        tx_versioner = self.__blockchain.tx_versioner
        while tx_queue:
            if block_tx_size >= conf.MAX_TX_SIZE_IN_BLOCK:
                utils.logger.warning(
                    f"consensus_base total size({block_builder.size()}) "
                    f"count({len(block_builder.transactions)}) "
                    f"_txQueue size ({len(tx_queue)})")
                break

            tx: 'Transaction' = tx_queue.get_item_in_status(
                get_status=TransactionStatusInQueue.normal,
                set_status=TransactionStatusInQueue.added_to_block
            )
            if tx is None:
                break

            block_timestamp = block_builder.fixed_timestamp
            if not utils.is_in_time_boundary(tx.timestamp, conf.TIMESTAMP_BOUNDARY_SECOND, block_timestamp):
                utils.logger.info(f"fail add tx to block by TIMESTAMP_BOUNDARY_SECOND"
                                  f"({conf.TIMESTAMP_BOUNDARY_SECOND}) "
                                  f"tx({tx.hash}), timestamp({tx.timestamp})")
                continue

            tv = TransactionVerifier.new(tx.version, tx.type(), tx_versioner)

            try:
                tv.verify(tx, self.__blockchain)
            except Exception as e:
                utils.logger.warning(
                    f"tx hash invalid.\n"
                    f"tx: {tx}\n"
                    f"exception: {e}"
                )
                traceback.print_exc()
            else:
                block_builder.transactions[tx.hash] = tx
                block_tx_size += tx.size(tx_versioner)
Esempio n. 23
0
    def test_verify_tx_hash_unique_but_duplicated_tx(self, tx_version,
                                                     tx_factory: 'TxFactory',
                                                     mocker, raise_exc):
        tx: Transaction = tx_factory(tx_version)
        tv = TransactionVerifier.new(version=tx.version,
                                     type_=tx.type(),
                                     versioner=tx_versioner,
                                     raise_exceptions=raise_exc)

        mock_blockchain: BlockChain = mocker.MagicMock(spec=BlockChain)
        mock_blockchain.find_tx_by_key.return_value = "tx_info_found!"

        if raise_exc:
            with pytest.raises(TransactionDuplicatedHashError):
                tv.verify_tx_hash_unique(tx, mock_blockchain)
        else:
            assert not tv.exceptions
            tv.verify_tx_hash_unique(tx, mock_blockchain)

            with pytest.raises(TransactionDuplicatedHashError):
                raise tv.exceptions[0]
Esempio n. 24
0
    def test_transaction_v3_unsigned(self):
        signer = Signer.new()

        tb = TransactionBuilder.new("0x3", None, self.tx_versioner)
        tb.step_limit = 1000000
        tb.value = 100000
        tb.from_address = ExternalAddress.fromhex_address(signer.address)
        tb.to_address = ExternalAddress(os.urandom(20))
        tb.nid = 3
        tb.nonce = random.randint(0, 100000)
        tb.data = "test"
        tb.data_type = "message"
        tx = tb.build(False)

        tv = TransactionVerifier.new("0x3", tx.type(), self.tx_versioner)
        self.assertRaises(TransactionInvalidSignatureError, lambda: tv.verify(tx))
        self.assertRaises(TransactionInvalidSignatureError, lambda: tv.pre_verify(tx, nid=3))

        tb.signer = signer
        signed_tx = tb.sign_transaction(tx)
        tv.verify(signed_tx)
        tv.pre_verify(signed_tx, nid=3)
Esempio n. 25
0
    def test_transaction_v3_invalid_signature(self):
        # noinspection PyDictCreation
        tx_dumped = {
            'version':
            '0x3',
            'from':
            'hx48cd6eb32339d5c719dcc0af21e9bc3b67d733e6',
            'to':
            'hxe0a231fa5c80e45f51d7df5f7d127954320df829',
            'stepLimit':
            '0xf4240',
            'timestamp':
            '0x5899c717f92f8',
            'nid':
            '0x3',
            'value':
            '0x186a0',
            'nonce':
            '0x64',
            'data':
            'test',
            'dataType':
            'message',
            'signature':
            'J84KdBtQR4w1bcBdBGF8g6aNoCXjsY/5T6vGV4RXeMwEvafj9xVRDVjzF+vN1JVYvXrAzjlYPCiiBXBQe6+tRAE='
        }
        tx_dumped['signature'] = Signature(os.urandom(
            Signature.size)).to_base64str()  # invalid signature

        tx_version, tx_type = self.tx_versioner.get_version(tx_dumped)
        ts = TransactionSerializer.new(tx_version, tx_type, self.tx_versioner)
        tx = ts.from_(tx_dumped)

        tv = TransactionVerifier.new(tx_version, tx_type, self.tx_versioner)
        self.assertRaises(TransactionInvalidSignatureError,
                          lambda: tv.verify(tx))
        self.assertRaises(TransactionInvalidSignatureError,
                          lambda: tv.pre_verify(tx, nid=3))