def test_add_signature_to_transaction_with_netowrk_id(self):

        for network_id in [1, 2, 66, 100]:

            sender_private_key = "0x0164f7c7399f4bb1eafeaae699ebbb12050bc6a50b2836b9ca766068a9d000c0"
            sender_address = "0xde3d2d9dd52ea80f7799ef4791063a5458d13913"
            to_address = "0x056db290f8ba3250ca64a45d16284d04bc6f5fbf"
            value = 10000000000
            nonce = 1048576
            data = b''
            gasprice = DEFAULT_GASPRICE
            startgas = DEFAULT_STARTGAS
            network_id = 1

            tx1 = Transaction(nonce, gasprice, startgas, to_address, value,
                              data, network_id, 0, 0)
            tx = encode_transaction(tx1)
            tx1.sign(data_decoder(sender_private_key), network_id=network_id)
            expected_signed_tx = encode_transaction(tx1)
            sig = data_encoder(signature_from_transaction(tx1))

            signed_tx = add_signature_to_transaction(tx, sig)

            self.assertEqual(signed_tx, expected_signed_tx)

            tx_obj = decode_transaction(tx)

            add_signature_to_transaction(tx_obj, sig)

            self.assertEqual(tx_obj.network_id, network_id)
            self.assertEqual(data_encoder(tx_obj.sender), sender_address)

            self.assertEqual(encode_transaction(tx_obj), expected_signed_tx)
    def do_POST(self):

        # TODO: figure out why read is blocking here
        data = self.rfile.read(len(self.rfile.peek()))
        data = data.decode('utf-8')
        data = json.loads(data)

        if self.path == "/v1/tx/skel":

            gas_price = parse_int(data['gas_price']) if 'gas_price' in data else DEFAULT_GASPRICE
            gas = parse_int(data['gas']) if 'gas' in data else DEFAULT_STARTGAS
            nonce = parse_int(data['nonce']) if 'nonce' in data else 0

            if 'value' not in data or 'from' not in data or 'to' not in data:
                self.write_data(400, {'errors': [{'id': 'bad_arguments', 'message': 'Bad Arguments'}]})
                return
            value = parse_int(data['value'])
            to_address = data['to']
            from_address = data['from']

            if not validate_address(to_address):
                self.write_data(400, {'errors': [{'id': 'invalid_to_address', 'message': 'Invalid To Address'}]})
                return
            if not validate_address(from_address):
                self.write_data(400, {'errors': [{'id': 'invalid_from_address', 'message': 'Invalid From Address'}]})
                return

            tx = create_transaction(nonce=nonce, gasprice=gas_price, startgas=gas,
                                    to=to_address, value=value)

            transaction = encode_transaction(tx)

            self.write_data(200, {
                "tx_data": {
                    "nonce": hex(nonce),
                    "from": from_address,
                    "to": to_address,
                    "value": hex(value),
                    "startGas": hex(gas),
                    "gasPrice": hex(gas_price)
                },
                "tx": transaction
            })

        elif self.path == "/v1/tx":

            tx = decode_transaction(data['tx'])

            if 'signature' in data:

                sig = data_decoder(data['signature'])

                add_signature_to_transaction(tx, sig)

            self.write_data(200, {"tx_hash": data_encoder(tx.hash)})

        else:

            self.write_data(404)
    def test_send_tx(self):

        tx = decode_transaction("0xe9808504a817c80082520894db089a4f9a8c5f17040b4fc51647e942b5fc601d880de0b6b3a764000080")
        sig = "0xf5a43adea07d366ae420a5c75a5cae6c60d3e4aaa0b72c2f37fc387efd43d7fd30c4327f2dbd959f654857f58912129b09763329459d08e25547d895ae90fa0f01"

        resp = self.service_client.send_tx(tx, sig)

        self.assertEqual(resp, "0x07ca664267650c87c11318710e3afa2f8f191814d25def8e0c4f2768f3ef5ccb")
    def test_sign_transaction_with_network_id(self):
        rlp = "0xec831000008504a817c80082520894056db290f8ba3250ca64a45d16284d04bc6f5fbf8502540be40080428080"
        tx = decode_transaction(rlp)
        tx = sign_transaction(tx, FAUCET_PRIVATE_KEY)

        self.assertEqual(data_encoder(tx.sender), FAUCET_ADDRESS)
        # after decoding a transaction, the rlp lib caches the rlp encoding from the given values
        # since the sign_transaction modifies that values, this makes sure the cache isn't used next
        # time the tx is encoded
        self.assertEqual(
            data_encoder(tx.hash),
            "0x102234ef30bb90955517ddf92dc7ce39fff7bb4ef760409b984983ad73585bf5",
            "Incorrect transaction hash after signing")
    def test_add_signature_to_transaction(self):

        tx = "0xe9808504a817c80082520894db089a4f9a8c5f17040b4fc51647e942b5fc601d880de0b6b3a764000080"
        sig = "0xf5a43adea07d366ae420a5c75a5cae6c60d3e4aaa0b72c2f37fc387efd43d7fd30c4327f2dbd959f654857f58912129b09763329459d08e25547d895ae90fa0f01"

        expected_signed_tx = "0xf86c808504a817c80082520894db089a4f9a8c5f17040b4fc51647e942b5fc601d880de0b6b3a7640000801ca0f5a43adea07d366ae420a5c75a5cae6c60d3e4aaa0b72c2f37fc387efd43d7fda030c4327f2dbd959f654857f58912129b09763329459d08e25547d895ae90fa0f"

        signed_tx = add_signature_to_transaction(tx, sig)

        self.assertEqual(signed_tx, expected_signed_tx)

        tx_obj = decode_transaction(tx)

        add_signature_to_transaction(tx_obj, sig)

        self.assertEqual(encode_transaction(tx_obj), expected_signed_tx)
    def generate_tx_skel(self,
                         from_address,
                         to_address,
                         value,
                         gas=None,
                         gas_price=None,
                         nonce=None,
                         data=None,
                         **kwargs):

        reqdata = {"from": from_address, "to": to_address, "value": value}
        if gas is not None:
            reqdata['gas'] = gas
        if gas_price is not None:
            reqdata['gas_price'] = gas_price
        if nonce is not None:
            reqdata['nonce'] = nonce
        if data is not None:
            reqdata['data'] = data

        resp = self._fetch("/v1/tx/skel", "POST", reqdata, **kwargs)
        return decode_transaction(resp['tx'])
        def test_vector(name, vector):
            if 'transaction' not in vector:
                return  # TODO: process rlp tests
            transaction = vector['transaction']
            tx = create_transaction(
                nonce=parse_int(transaction['nonce']),
                gasprice=parse_int(transaction['gasPrice']),
                startgas=parse_int(transaction['gasLimit']),
                to=transaction['to'],
                value=parse_int(transaction['value']),
                data=data_decoder(transaction['data']),
                v=parse_int(transaction['v']),
                r=parse_int(transaction['r']),
                s=parse_int(transaction['s']))
            self.assertEqual(data_encoder(tx.sender),
                             "0x{}".format(vector['sender']), name)
            self.assertEqual(calculate_transaction_hash(tx),
                             "0x{}".format(vector['hash']), name)
            self.assertEqual(encode_transaction(tx), vector['rlp'], name)

            # test decode transaction -> encode transaction round trip
            tx = decode_transaction(vector['rlp'])
            self.assertEqual(encode_transaction(tx), vector['rlp'], name)