feat(providers): support personal account apis (#2009)

* feat(providers): add personal key mgmt rpcs

 * add personal_importRawKey and personal_unlockAccount

* expose geth personal api

* do not prefix with 0x

* serialize privkey as string

* add allow-insecure-unlock option to Geth
This commit is contained in:
Dan Cline 2023-01-04 16:35:44 -05:00 committed by GitHub
parent 9147ee8e63
commit c0e607da1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 73 additions and 1 deletions

View File

@ -16,7 +16,7 @@ const GETH_STARTUP_TIMEOUT_MILLIS: u64 = 10_000;
const GETH_DIAL_LOOP_TIMEOUT: Duration = Duration::new(20, 0);
/// The exposed APIs
const API: &str = "eth,net,web3,txpool,admin,miner";
const API: &str = "eth,net,web3,txpool,admin,personal,miner";
/// The geth command
const GETH: &str = "geth";
@ -180,6 +180,7 @@ pub struct Geth {
ipc_path: Option<PathBuf>,
data_dir: Option<PathBuf>,
chain_id: Option<u64>,
insecure_unlock: bool,
genesis: Option<Genesis>,
mode: GethMode,
}
@ -259,6 +260,13 @@ impl Geth {
self
}
/// Allow geth to unlock accounts when rpc apis are open.
#[must_use]
pub fn insecure_unlock(mut self) -> Self {
self.insecure_unlock = true;
self
}
/// Disable discovery for the geth instance.
///
/// This will put the geth instance into non-dev mode, discarding any previously set dev-mode
@ -328,6 +336,11 @@ impl Geth {
cmd.arg("--ws.port").arg(port.to_string());
cmd.arg("--ws.api").arg(API);
// pass insecure unlock flag if set
if self.insecure_unlock {
cmd.arg("--allow-insecure-unlock");
}
// Set the port for authenticated APIs
cmd.arg("--authrpc.port").arg(authrpc_port.to_string());

View File

@ -507,6 +507,25 @@ pub trait Middleware: Sync + Send + Debug {
self.inner().mining().await.map_err(FromErr::from)
}
// Personal namespace
async fn import_raw_key(
&self,
private_key: Bytes,
passphrase: String,
) -> Result<Address, ProviderError> {
self.inner().import_raw_key(private_key, passphrase).await.map_err(FromErr::from)
}
async fn unlock_account<T: Into<Address> + Send + Sync>(
&self,
account: T,
passphrase: String,
duration: Option<u64>,
) -> Result<bool, ProviderError> {
self.inner().unlock_account(account, passphrase, duration).await.map_err(FromErr::from)
}
// Admin namespace
async fn add_peer(&self, enode_url: String) -> Result<bool, Self::Error> {

View File

@ -818,6 +818,46 @@ impl<P: JsonRpcClient> Middleware for Provider<P> {
self.request("eth_mining", ()).await
}
// Personal namespace
// NOTE: This will eventually need to be enabled by users explicitly because the personal
// namespace is being deprecated:
// Issue: https://github.com/ethereum/go-ethereum/issues/25948
// PR: https://github.com/ethereum/go-ethereum/pull/26390
/// Sends the given key to the node to be encrypted with the provided passphrase and stored.
///
/// The key represents a secp256k1 private key and should be 32 bytes.
async fn import_raw_key(
&self,
private_key: Bytes,
passphrase: String,
) -> Result<Address, ProviderError> {
// private key should not be prefixed with 0x - it is also up to the user to pass in a key
// of the correct length
// the private key argument is supposed to be a string
let private_key_hex = hex::encode(private_key);
let private_key = utils::serialize(&private_key_hex);
let passphrase = utils::serialize(&passphrase);
self.request("personal_importRawKey", [private_key, passphrase]).await
}
/// Prompts the node to decrypt the given account from its keystore.
///
/// If the duration provided is `None`, then the account will be unlocked indefinitely.
/// Otherwise, the account will be unlocked for the provided number of seconds.
async fn unlock_account<T: Into<Address> + Send + Sync>(
&self,
account: T,
passphrase: String,
duration: Option<u64>,
) -> Result<bool, ProviderError> {
let account = utils::serialize(&account.into());
let duration = utils::serialize(&duration.unwrap_or(0));
let passphrase = utils::serialize(&passphrase);
self.request("personal_unlockAccount", [account, passphrase, duration]).await
}
// Admin namespace
/// Requests adding the given peer, returning a boolean representing whether or not the peer