Пример #1
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 = TransactionVersioner()
        version, type_ = tv.get_version(question)
        ts = TransactionSerializer.new(version, type_, tv)
        tx = ts.from_(question)

        result = self.hash_generator.generate_salted_origin(ts.to_origin_data(tx))
        self.assertEqual(result, answer)
Пример #2
0
    def test_hash_case_v3_null(self):
        request = r'''{
            "jsonrpc": "2.0",
            "method": "icx_sendTransaction",
            "id": 1234,
            "params": {
                "version": "0x3",
                "from": "hxbe258ceb872e08851f1f59694dac2558708ece11",
                "to": "cxb0776ee37f5b45bfaea8cff1d8232fbb6122ec32",
                "stepLimit": "0x12345",
                "timestamp": "0x563a6cf330136",
                "nid": "0x1",
                "nonce": "0x1",
                "signature": "VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA=",
                "dataType": "call",
                "data": {
                    "method": "transfer",
                    "params": {
                        "to": "hxab2d8215eab14bc6bdd8bfb2c8151257032ecd8b",
                        "value": "0x1",
                        "array0": [
                            null,
                            null
                        ],
                        "array1": [
                            {
                                "hash": null,
                                "value": null
                            },
                            {
                                "hash": null,
                                "value": "0x78"
                            }
                        ]
                    }
                }
            }
        }'''

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

        question = request["params"]
        answer = r"icx_sendTransaction.data.{method.transfer.params." \
                 r"{array0.[\0.\0].array1.[{hash.\0.value.\0}.{hash.\0.value.0x78}]." \
                 r"to.hxab2d8215eab14bc6bdd8bfb2c8151257032ecd8b.value.0x1}}." \
                 r"dataType.call.from.hxbe258ceb872e08851f1f59694dac2558708ece11.nid.0x1.nonce.0x1.stepLimit.0x12345." \
                 r"timestamp.0x563a6cf330136.to.cxb0776ee37f5b45bfaea8cff1d8232fbb6122ec32.version.0x3"

        tv = TransactionVersioner()
        version, type_ = tv.get_version(question)

        ts = TransactionSerializer.new(version, type_, tv)
        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)
Пример #3
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 = TransactionVersioner()
        version, type_ = tv.get_version(question)
        ts = TransactionSerializer.new(version, type_, tv)
        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)
Пример #4
0
class TestTransaction(unittest.TestCase):
    def setUp(self):
        test_util.print_testname(self._testMethodName)
        self.signer = Signer.from_prikey(os.urandom(32))
        self.tx_versioner = TransactionVersioner()
        self.tx_versioner.hash_generator_versions["0x2"] = 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)

    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)

    def test_transaction_v3(self):
        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 = 3
        tb.nonce = random.randint(0, 100000)
        tb.data = "test"
        tb.data_type = "message"
        tx = tb.build()

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

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

        self.assertEqual(ts.from_(tx_raw_data), tx)

    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)

    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)

    def test_transaction_v2_invalid_hash0(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['tx_hash'] = os.urandom(32).hex()  # invalid hash

        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(TransactionInvalidHashError, lambda: tv.verify(tx))
        self.assertRaises(TransactionInvalidHashError,
                          lambda: tv.pre_verify(tx))

    def test_transaction_v2_invalid_hash1(self):
        # noinspection PyDictCreation
        tx_dumped = {
            'from':
            'hx48cd6eb32339d5c719dcc0af21e9bc3b67d733e6',
            'to':
            'hx22f72e44141bedd50d1e536455682863d3d8a484',
            'value':
            '0x186a0',
            'fee':
            '0xf4240',
            'timestamp':
            '1558679280067963',
            'nonce':
            '1',
            'tx_hash':
            '34477b3bc76fa73aad0258ba9fd36f28a3c4b26956c1e5eb92ddda7d98df4e32',
            'signature':
            'W/hW/PAo+ExeSsreD//yJVgNqmnkWKs+m0VUqE11O7Ek82yEINuczLRXtj1k515q8Ep4OLsRPPiPNjDM9vuhsgE='
        }
        tx_dumped['value'] = hex(int(random.randrange(1,
                                                      100)))  # invalid value

        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(TransactionInvalidHashError, lambda: tv.verify(tx))
        self.assertRaises(TransactionInvalidHashError,
                          lambda: tv.pre_verify(tx))

    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_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))

    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))

    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))

    def test_transaction_v3_duplicate_hash(self):
        MockBlockchain = namedtuple("MockBlockchain",
                                    "find_nid find_tx_by_key")

        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 = 3
        tb.nonce = random.randint(0, 100000)
        tb.data = "test"
        tb.data_type = "message"
        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))