Given a private key, I would like to sign a transaction offline, so it can be sent to a node or Infura without unlocking an account first. I can find many examples in javascript using ethereumjs-tx
but I am using Rust and rust-web3 and can't find a single example that writes data. I need to be able to call functions, not just send value, so how to construct the function parameters is of particular interest. Also, how can I wait and process the return value if the function has a return value?
3 Answers
It is a function of wallet to store and use your private key. web3
API like rust-web3 usually leave transaction signing to wallet. Therefore your option is to reuse the code in Ethereum wallets that are written in Rust.
-
1I spoke to the
rust-web3
author and he said it is not yet supported but would be great to add. For now, there is an open issue filed for the project. Thanks for the link to Emerald. There is lots of Rust code in the Parity repo we have been leveraging as well.– emkmanCommented May 15, 2018 at 19:14
There is a package for this called ethereum-tx-sign on crates.io. It provides a RawTransaction
structure with a sign
method. It doesn't have any dependency on web3 and you can sign the transactions offline.
-
Thanks, this didn't exist at the time of posting. A welcome addition to the rust eth ecosystem!– emkmanCommented Nov 27, 2018 at 9:24
There's a trick using python's web3 package with cpython:
let gil = Python::acquire_gil();
let py = gil.python();
let web3 = py.import("web3").unwrap();
let transaction = {
let transaction = PyDict::new(py);
transaction.set_item(py, "gas", gas_limit).unwrap();
transaction.set_item(py, "gasPrice", gas_price).unwrap();
transaction.set_item(py, "nonce", nonce).unwrap();
transaction.set_item(py, "data", data).unwrap();
let web3 = web3.get(py, "Web3").unwrap();
let to = web3.call_method(py, "toChecksumAddress", (to, ), None).unwrap();
transaction.set_item(py, "to", to).unwrap();
transaction.set_item(py, "value", value).unwrap();
transaction
};
let account = web3.get(py, "Account").unwrap();
let signed_transaction = account.call_method(py, "signTransaction", (transaction, private_key), None).unwrap();
let raw_transaction: String = signed_transaction.getattr(py, "rawTransaction")
.unwrap()
.call_method(py, "hex", NoArgs, None)
.unwrap()
.extract(py)
.unwrap();
Boom! Got it!
Btw, about ethereum-tx-sign. I've already try it, but it seems not work correctly. My target server doesn't recognize the signedRawTransaction
. So I compare the its result with web3
's result and I found they were different.