diff --git a/clients/py/sapphirepy/envelope.py b/clients/py/sapphirepy/envelope.py index b78ddd3a..5ef90bf1 100644 --- a/clients/py/sapphirepy/envelope.py +++ b/clients/py/sapphirepy/envelope.py @@ -97,7 +97,7 @@ def encrypt(self, plaintext: bytes): } return cbor2.dumps(envelope, canonical=True) - def encrypt_envelope(self, plaintext: bytes): + def make_envelope(self, plaintext: bytes): ciphertext, nonce = self._encrypt_calldata(plaintext) envelope = { 'body': { diff --git a/clients/py/sapphirepy/sapphire.py b/clients/py/sapphirepy/sapphire.py index 27f4babe..b3189197 100644 --- a/clients/py/sapphirepy/sapphire.py +++ b/clients/py/sapphirepy/sapphire.py @@ -77,7 +77,7 @@ def _encrypt_tx_params(pk: CalldataPublicKey, params: tuple[TxParams], method, web3: Web3, - account: LocalAccount) -> TransactionCipher: + account: Optional[LocalAccount]) -> TransactionCipher: c = TransactionCipher(peer_pubkey=pk['key'], peer_epoch=pk['epoch']) data = params[0]['data'] if isinstance(data, bytes): @@ -91,12 +91,12 @@ def _encrypt_tx_params(pk: CalldataPublicKey, encrypted_data = c.encrypt(data_bytes) if params[0]['from'] and method == 'eth_call': - data_pack = _new_signed_call_data_pack(c.encrypt_envelope(data_bytes), + assert account is not None, 'Account must be provided for encrypted calls!' + data_pack = _new_signed_call_data_pack(c.make_envelope(data_bytes), data_bytes, params, web3, account) - data_pack['signature'] = bytes(data_pack['signature']) params[0]['data'] = cbor2.dumps(data_pack, canonical=True) else: params[0]['data'] = HexStr('0x' + hexlify(encrypted_data).decode('ascii')) @@ -111,7 +111,7 @@ def _new_signed_call_data_pack(encrypted_data: dict, account: LocalAccount) -> dict: # Update params with default values, these get used outside the scope of this function params[0]['gas'] = params[0].get('gas', DEFAULT_GAS_LIMIT) - params[0]['gasPrice'] = params[0].get('gasPrice', DEFAULT_GAS_PRICE) + params[0]['gasPrice'] = params[0].get('gasPrice', web3.to_wei(DEFAULT_GAS_PRICE, 'wei')) domain_data = { "name": "oasis-runtime-sdk/evm: signed query", @@ -142,7 +142,7 @@ def _new_signed_call_data_pack(encrypted_data: dict, {"name": "blockRange", "type": "uint64"}, ], } - nonce = web3.eth.get_transaction_count(params[0]['from']) + nonce = web3.eth.get_transaction_count(web3.to_checksum_address(params[0]['from'])) block_number = web3.eth.block_number block_hash = web3.eth.get_block(block_number-1)['hash'].hex() msg_data = { @@ -182,13 +182,13 @@ def _new_signed_call_data_pack(encrypted_data: dict, data_pack= { 'data': encrypted_data, 'leash': leash, - 'signature': signed_msg['signature'], + 'signature': bytes(signed_msg['signature']), } return data_pack def construct_sapphire_middleware( - account: LocalAccount = None + account: Optional[LocalAccount] = None ) -> Middleware: """ Construct a Sapphire middleware for Web3.py. @@ -264,7 +264,7 @@ def middleware(method: RPCEndpoint, params: Any) -> RPCResponse: return sapphire_middleware -def wrap(w3: Web3, account: LocalAccount = None): +def wrap(w3: Web3, account: Optional[LocalAccount] = None): """ Adds the Sapphire transaction encryption middleware to a Web3.py provider. diff --git a/clients/py/sapphirepy/tests/test_e2e.py b/clients/py/sapphirepy/tests/test_e2e.py index fe27b43b..a8d32faf 100644 --- a/clients/py/sapphirepy/tests/test_e2e.py +++ b/clients/py/sapphirepy/tests/test_e2e.py @@ -56,6 +56,7 @@ def setUp(self): w3 = Web3(Web3.HTTPProvider('http://localhost:8545')) # w3 = Web3(Web3.HTTPProvider('https://testnet.sapphire.oasis.io')) w3.middleware_onion.add(construct_sign_and_send_raw_middleware(account)) + self.w3_no_signer = Web3(Web3.HTTPProvider('http://localhost:8545')) self.w3 = w3 = sapphire.wrap(w3, account) w3.eth.default_account = account.address @@ -67,6 +68,7 @@ def setUp(self): tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) self.greeter = w3.eth.contract(address=tx_receipt['contractAddress'], abi=iface['abi']) + self.greeter_no_signer = self.w3_no_signer.eth.contract(address=tx_receipt['contractAddress'], abi=iface['abi']) def test_viewcall_revert_custom(self): with self.assertRaises(ContractCustomError) as cm: @@ -87,6 +89,11 @@ def test_viewcall(self): def test_viewcall_only_owner(self): self.assertEqual(self.greeter.functions.greetOnlyOwner().call(), 'Hello') + def test_viewcall_only_owner_no_signer(self): + with self.assertRaises(ContractLogicError) as cm: + self.greeter_no_signer.functions.greetOnlyOwner().call() + self.assertEqual(cm.exception.message, 'execution reverted: Only owner can call this function') + def test_transaction(self): w3 = self.w3 greeter = self.greeter diff --git a/clients/py/sapphirepy/tests/testdata/Greeter.abi b/clients/py/sapphirepy/tests/testdata/Greeter.abi new file mode 100644 index 00000000..cfbd2b24 --- /dev/null +++ b/clients/py/sapphirepy/tests/testdata/Greeter.abi @@ -0,0 +1 @@ +[{"inputs": [], "stateMutability": "nonpayable", "type": "constructor"}, {"inputs": [{"internalType": "string", "name": "blah", "type": "string"}], "name": "MyCustomError", "type": "error"}, {"anonymous": false, "inputs": [{"indexed": false, "internalType": "string", "name": "g", "type": "string"}], "name": "Greeting", "type": "event"}, {"inputs": [], "name": "blah", "outputs": [], "stateMutability": "nonpayable", "type": "function"}, {"inputs": [], "name": "greet", "outputs": [{"internalType": "string", "name": "", "type": "string"}], "stateMutability": "view", "type": "function"}, {"inputs": [], "name": "greetOnlyOwner", "outputs": [{"internalType": "string", "name": "", "type": "string"}], "stateMutability": "view", "type": "function"}, {"inputs": [], "name": "greeting", "outputs": [{"internalType": "string", "name": "", "type": "string"}], "stateMutability": "view", "type": "function"}, {"inputs": [], "name": "owner", "outputs": [{"internalType": "address", "name": "", "type": "address"}], "stateMutability": "view", "type": "function"}, {"inputs": [], "name": "revertWithCustomError", "outputs": [], "stateMutability": "pure", "type": "function"}, {"inputs": [], "name": "revertWithReason", "outputs": [], "stateMutability": "pure", "type": "function"}, {"inputs": [{"internalType": "string", "name": "_greeting", "type": "string"}], "name": "setGreeting", "outputs": [], "stateMutability": "nonpayable", "type": "function"}] \ No newline at end of file diff --git a/clients/py/sapphirepy/tests/testdata/Greeter.bin b/clients/py/sapphirepy/tests/testdata/Greeter.bin new file mode 100644 index 00000000..cf9ef436 --- /dev/null +++ b/clients/py/sapphirepy/tests/testdata/Greeter.bin @@ -0,0 +1 @@ +"608060405234801561001057600080fd5b506040518060400160405280600581526020017f48656c6c6f0000000000000000000000000000000000000000000000000000008152506000908051906020019061005c9291906100a3565b5033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101a7565b8280546100af90610175565b90600052602060002090601f0160209004810192826100d15760008555610118565b82601f106100ea57805160ff1916838001178555610118565b82800160010185558215610118579182015b828111156101175782518255916020019190600101906100fc565b5b5090506101259190610129565b5090565b5b8082111561014257600081600090555060010161012a565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061018d57607f821691505b602082108114156101a1576101a0610146565b5b50919050565b610a7d806101b66000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063a41368621161005b578063a4136862146100dd578063cfae3217146100f9578063e39dcc2114610117578063ef690cc01461012157610088565b806346fc4bb11461008d57806355f64074146100975780635b2dd100146100b55780638da5cb5b146100bf575b600080fd5b61009561013f565b005b61009f61017a565b6040516100ac91906105b5565b60405180910390f35b6100bd61029c565b005b6100c76102df565b6040516100d49190610618565b60405180910390f35b6100f760048036038101906100f2919061077c565b610305565b005b61010161031f565b60405161010e91906105b5565b60405180910390f35b61011f6103b1565b005b6101296103eb565b60405161013691906105b5565b60405180910390f35b6040517fb98c011300000000000000000000000000000000000000000000000000000000815260040161017190610811565b60405180910390fd5b6060600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461020c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610203906108a3565b60405180910390fd5b60008054610219906108f2565b80601f0160208091040260200160405190810160405280929190818152602001828054610245906108f2565b80156102925780601f1061026757610100808354040283529160200191610292565b820191906000526020600020905b81548152906001019060200180831161027557829003601f168201915b5050505050905090565b60006102dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d490610970565b60405180910390fd5b565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b806000908051906020019061031b929190610479565b5050565b60606000805461032e906108f2565b80601f016020809104026020016040519081016040528092919081815260200182805461035a906108f2565b80156103a75780601f1061037c576101008083540402835291602001916103a7565b820191906000526020600020905b81548152906001019060200180831161038a57829003601f168201915b5050505050905090565b7fa5263230ff6fc3abbbad333e24faf0f402b4e050b83a1d30ad4051f4e5d0f72760006040516103e19190610a25565b60405180910390a1565b600080546103f8906108f2565b80601f0160208091040260200160405190810160405280929190818152602001828054610424906108f2565b80156104715780601f1061044657610100808354040283529160200191610471565b820191906000526020600020905b81548152906001019060200180831161045457829003601f168201915b505050505081565b828054610485906108f2565b90600052602060002090601f0160209004810192826104a757600085556104ee565b82601f106104c057805160ff19168380011785556104ee565b828001600101855582156104ee579182015b828111156104ed5782518255916020019190600101906104d2565b5b5090506104fb91906104ff565b5090565b5b80821115610518576000816000905550600101610500565b5090565b600081519050919050565b600082825260208201905092915050565b60005b8381101561055657808201518184015260208101905061053b565b83811115610565576000848401525b50505050565b6000601f19601f8301169050919050565b60006105878261051c565b6105918185610527565b93506105a1818560208601610538565b6105aa8161056b565b840191505092915050565b600060208201905081810360008301526105cf818461057c565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610602826105d7565b9050919050565b610612816105f7565b82525050565b600060208201905061062d6000830184610609565b92915050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6106898261056b565b810181811067ffffffffffffffff821117156106a8576106a7610651565b5b80604052505050565b60006106bb610633565b90506106c78282610680565b919050565b600067ffffffffffffffff8211156106e7576106e6610651565b5b6106f08261056b565b9050602081019050919050565b82818337600083830152505050565b600061071f61071a846106cc565b6106b1565b90508281526020810184848401111561073b5761073a61064c565b5b6107468482856106fd565b509392505050565b600082601f83011261076357610762610647565b5b813561077384826020860161070c565b91505092915050565b6000602082840312156107925761079161063d565b5b600082013567ffffffffffffffff8111156107b0576107af610642565b5b6107bc8482850161074e565b91505092915050565b7f746869734973437573746f6d0000000000000000000000000000000000000000600082015250565b60006107fb600c83610527565b9150610806826107c5565b602082019050919050565b6000602082019050818103600083015261082a816107ee565b9050919050565b7f4f6e6c79206f776e65722063616e2063616c6c20746869732066756e6374696f60008201527f6e00000000000000000000000000000000000000000000000000000000000000602082015250565b600061088d602183610527565b915061089882610831565b604082019050919050565b600060208201905081810360008301526108bc81610880565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061090a57607f821691505b6020821081141561091e5761091d6108c3565b5b50919050565b7f726561736f6e476f657348657265000000000000000000000000000000000000600082015250565b600061095a600e83610527565b915061096582610924565b602082019050919050565b600060208201905081810360008301526109898161094d565b9050919050565b60008190508160005260206000209050919050565b600081546109b2816108f2565b6109bc8186610527565b945060018216600081146109d757600181146109e957610a1c565b60ff1983168652602086019350610a1c565b6109f285610990565b60005b83811015610a14578154818901526001820191506020810190506109f5565b808801955050505b50505092915050565b60006020820190508181036000830152610a3f81846109a5565b90509291505056fea26469706673582212205e5a4ce57c30ee5012ef4f55f3e7c7d1e83602f3e823586ace8decb2703f7ebd64736f6c63430008090033" \ No newline at end of file