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:
parent
9147ee8e63
commit
c0e607da1e
|
@ -16,7 +16,7 @@ const GETH_STARTUP_TIMEOUT_MILLIS: u64 = 10_000;
|
||||||
const GETH_DIAL_LOOP_TIMEOUT: Duration = Duration::new(20, 0);
|
const GETH_DIAL_LOOP_TIMEOUT: Duration = Duration::new(20, 0);
|
||||||
|
|
||||||
/// The exposed APIs
|
/// 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
|
/// The geth command
|
||||||
const GETH: &str = "geth";
|
const GETH: &str = "geth";
|
||||||
|
@ -180,6 +180,7 @@ pub struct Geth {
|
||||||
ipc_path: Option<PathBuf>,
|
ipc_path: Option<PathBuf>,
|
||||||
data_dir: Option<PathBuf>,
|
data_dir: Option<PathBuf>,
|
||||||
chain_id: Option<u64>,
|
chain_id: Option<u64>,
|
||||||
|
insecure_unlock: bool,
|
||||||
genesis: Option<Genesis>,
|
genesis: Option<Genesis>,
|
||||||
mode: GethMode,
|
mode: GethMode,
|
||||||
}
|
}
|
||||||
|
@ -259,6 +260,13 @@ impl Geth {
|
||||||
self
|
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.
|
/// Disable discovery for the geth instance.
|
||||||
///
|
///
|
||||||
/// This will put the geth instance into non-dev mode, discarding any previously set dev-mode
|
/// 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.port").arg(port.to_string());
|
||||||
cmd.arg("--ws.api").arg(API);
|
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
|
// Set the port for authenticated APIs
|
||||||
cmd.arg("--authrpc.port").arg(authrpc_port.to_string());
|
cmd.arg("--authrpc.port").arg(authrpc_port.to_string());
|
||||||
|
|
||||||
|
|
|
@ -507,6 +507,25 @@ pub trait Middleware: Sync + Send + Debug {
|
||||||
self.inner().mining().await.map_err(FromErr::from)
|
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
|
// Admin namespace
|
||||||
|
|
||||||
async fn add_peer(&self, enode_url: String) -> Result<bool, Self::Error> {
|
async fn add_peer(&self, enode_url: String) -> Result<bool, Self::Error> {
|
||||||
|
|
|
@ -818,6 +818,46 @@ impl<P: JsonRpcClient> Middleware for Provider<P> {
|
||||||
self.request("eth_mining", ()).await
|
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
|
// Admin namespace
|
||||||
|
|
||||||
/// Requests adding the given peer, returning a boolean representing whether or not the peer
|
/// Requests adding the given peer, returning a boolean representing whether or not the peer
|
||||||
|
|
Loading…
Reference in New Issue