Skip to content

Commit

Permalink
refactor(signers): use signer for single credentials and wallet f…
Browse files Browse the repository at this point in the history
…or credential stores (alloy-rs#883)

* NetworkSigner -> NetworkWallet

* LocalWallet -> LocalSigner, TrezorSigner -> TrezorWallet, LedgerSigner -> LedgerWallet, GcpSigner -> GcpWallet, AwsSigner stays because it is a single credential mapping to a single public key - not a keyring like Gcp

* EthereumSigner -> EthereumWallet, SignerFiller -> WalletFiller

* start major refactor

* signer -> credential

* minor fixes, still issue with on_http method cannot be called due to unsatisfied trait bounds

* fix tests

* signer-(aws|gcp|ledger|trezor) -> wallet-(aws|gcp|ledger|trezor)

* update docs

* more doc fixes

* move wallet implementations into its own block

* wallet -> signer, come up with better name than FilledLocalSigner

* default MnemonicBuilder to English

* fix docs

* fix doctests

* revert signer -> wallet crate renaming

* pull in main fix for rust-tls, fix flag

* FilledLocalSigner -> PrivateKeySigner

* minor fixes

* minor fixes

* fix clippy

* Update README.md

Co-authored-by: DaniPopes <[email protected]>

* add private key signer to list

* Update crates/signer-local/src/lib.rs

Co-authored-by: DaniPopes <[email protected]>

* Update crates/signer-local/src/lib.rs

Co-authored-by: DaniPopes <[email protected]>

* Update crates/signer/README.md

Co-authored-by: DaniPopes <[email protected]>

* add deprecation notice on LocalWallet and YubiWallet

* fix my broken english

* TrezorWallet -> TrezorSigner, GcpWallet -> GcpSigner, AwsWallet -> AwsSigner, LedgerWallet -> LedgerSigner

* populate wallet with all known default anvil keys

* revert, due to the way BTreeMap backing the signer_addresses it does not retain the insertion order

* add back multi-key insertion

* fix build issues

---------

Co-authored-by: DaniPopes <[email protected]>
  • Loading branch information
2 people authored and ben186 committed Jul 27, 2024
1 parent 5cac865 commit 92b824f
Show file tree
Hide file tree
Showing 40 changed files with 410 additions and 362 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ jobs:
--exclude alloy-signer-aws \
--exclude alloy-signer-gcp \
--exclude alloy-signer-ledger \
--exclude alloy-signer-local \
--exclude alloy-signer-trezor \
--exclude alloy-signer-wallet \
--exclude alloy-transport-ipc
wasm-wasi:
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ alloy-signer = { version = "0.1.0", default-features = false, path = "crates/sig
alloy-signer-aws = { version = "0.1.0", default-features = false, path = "crates/signer-aws" }
alloy-signer-gcp = { version = "0.1.0", default-features = false, path = "crates/signer-gcp" }
alloy-signer-ledger = { version = "0.1.0", default-features = false, path = "crates/signer-ledger" }
alloy-signer-local = { version = "0.1.0", default-features = false, path = "crates/signer-local" }
alloy-signer-trezor = { version = "0.1.0", default-features = false, path = "crates/signer-trezor" }
alloy-signer-wallet = { version = "0.1.0", default-features = false, path = "crates/signer-wallet" }
alloy-transport = { version = "0.1.0", default-features = false, path = "crates/transport" }
alloy-transport-http = { version = "0.1.0", default-features = false, path = "crates/transport-http" }
alloy-transport-ipc = { version = "0.1.0", default-features = false, path = "crates/transport-ipc" }
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ This repository contains the following crates:
- [`alloy-signer-aws`] - [AWS KMS] signer implementation
- [`alloy-signer-gcp`] - [GCP KMS] signer implementation
- [`alloy-signer-ledger`] - [Ledger] signer implementation
- [`alloy-signer-local`] - Local (private key, keystore, mnemonic, YubiHSM) signer implementations
- [`alloy-signer-trezor`] - [Trezor] signer implementation
- [`alloy-signer-wallet`] - Local wallet (Keystore/Mnemonic/Yubihsm) signer implementation
- [`alloy-transport`] - Low-level Ethereum JSON-RPC transport abstraction
- [`alloy-transport-http`] - HTTP transport implementation
- [`alloy-transport-ipc`] - IPC transport implementation
Expand Down Expand Up @@ -82,12 +82,13 @@ This repository contains the following crates:
[`alloy-signer-aws`]: https://github.com/alloy-rs/alloy/tree/main/crates/signer-aws
[`alloy-signer-gcp`]: https://github.com/alloy-rs/alloy/tree/main/crates/signer-gcp
[`alloy-signer-ledger`]: https://github.com/alloy-rs/alloy/tree/main/crates/signer-ledger
[`alloy-signer-local`]: https://github.com/alloy-rs/alloy/tree/main/crates/signer-local
[`alloy-signer-trezor`]: https://github.com/alloy-rs/alloy/tree/main/crates/signer-trezor
[`alloy-signer-wallet`]: https://github.com/alloy-rs/alloy/tree/main/crates/signer-wallet
[`alloy-transport`]: https://github.com/alloy-rs/alloy/tree/main/crates/transport
[`alloy-transport-http`]: https://github.com/alloy-rs/alloy/tree/main/crates/transport-http
[`alloy-transport-ipc`]: https://github.com/alloy-rs/alloy/tree/main/crates/transport-ipc
[`alloy-transport-ws`]: https://github.com/alloy-rs/alloy/tree/main/crates/transport-ws

[publish-subscribe]: https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern
[AWS KMS]: https://aws.amazon.com/kms
[GCP KMS]: https://cloud.google.com/kms
Expand Down
14 changes: 7 additions & 7 deletions crates/alloy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ alloy-signer = { workspace = true, optional = true }
alloy-signer-aws = { workspace = true, optional = true }
alloy-signer-gcp = { workspace = true, optional = true }
alloy-signer-ledger = { workspace = true, optional = true }
alloy-signer-local = { workspace = true, optional = true }
alloy-signer-trezor = { workspace = true, optional = true }
alloy-signer-wallet = { workspace = true, optional = true }

# transport
alloy-transport = { workspace = true, optional = true }
Expand Down Expand Up @@ -84,7 +84,7 @@ full = [
"provider-ws", # includes `providers`
"provider-ipc", # includes `providers`
"rpc-types", # includes `rpc-types-eth`
"signer-wallet", # includes `signers`
"signer-local", # includes `signers`
]

# configuration
Expand Down Expand Up @@ -148,15 +148,15 @@ signer-gcp = ["signers", "dep:alloy-signer-gcp"]
signer-ledger = ["signers", "dep:alloy-signer-ledger"]
signer-ledger-browser = ["signer-ledger", "alloy-signer-ledger?/browser"]
signer-ledger-node = ["signer-ledger", "alloy-signer-ledger?/node"]
signer-local = ["signers", "dep:alloy-signer-local"]
signer-trezor = ["signers", "dep:alloy-signer-trezor"]
signer-wallet = ["signers", "dep:alloy-signer-wallet"]
signer-keystore = ["signer-wallet", "alloy-signer-wallet?/keystore"]
signer-mnemonic = ["signer-wallet", "alloy-signer-wallet?/mnemonic"]
signer-keystore = ["signer-local", "alloy-signer-local?/keystore"]
signer-mnemonic = ["signer-local", "alloy-signer-local?/mnemonic"]
signer-mnemonic-all-languages = [
"signer-mnemonic",
"alloy-signer-wallet?/mnemonic-all-languages",
"alloy-signer-local?/mnemonic-all-languages",
]
signer-yubihsm = ["signer-wallet", "alloy-signer-wallet?/yubihsm"]
signer-yubihsm = ["signer-local", "alloy-signer-local?/yubihsm"]

# transports
transports = ["dep:alloy-transport"]
Expand Down
8 changes: 4 additions & 4 deletions crates/alloy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,13 @@ pub mod signers {
#[doc(inline)]
pub use alloy_signer_ledger as ledger;

#[cfg(feature = "signer-trezor")]
#[cfg(feature = "signer-local")]
#[doc(inline)]
pub use alloy_signer_trezor as trezor;
pub use alloy_signer_local as local;

#[cfg(feature = "signer-wallet")]
#[cfg(feature = "signer-trezor")]
#[doc(inline)]
pub use alloy_signer_wallet as wallet;
pub use alloy_signer_trezor as trezor;
}

/// Low-level Ethereum JSON-RPC transport abstraction and implementations.
Expand Down
2 changes: 1 addition & 1 deletion crates/contract/src/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ mod tests {

#[tokio::test(flavor = "multi_thread")]
async fn deploy_and_call() {
let provider = ProviderBuilder::new().with_recommended_fillers().on_anvil_with_signer();
let provider = ProviderBuilder::new().with_recommended_fillers().on_anvil_with_wallet();

let expected_address = provider.default_signer_address().create(0);
let my_contract = MyContract::deploy(provider, true).await.unwrap();
Expand Down
2 changes: 1 addition & 1 deletion crates/network/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ futures-utils-wasm.workspace = true
thiserror.workspace = true

[dev-dependencies]
alloy-signer-wallet.workspace = true
alloy-signer-local.workspace = true
tokio.workspace = true

[features]
Expand Down
11 changes: 7 additions & 4 deletions crates/network/src/any/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use alloy_consensus::BlobTransactionSidecar;
use alloy_primitives::{Address, Bytes, ChainId, TxKind, U256};
use alloy_rpc_types_eth::{AccessList, TransactionRequest, WithOtherFields};

use crate::{any::AnyNetwork, BuildResult, Network, TransactionBuilder, TransactionBuilderError};
use crate::{
any::AnyNetwork, BuildResult, Network, NetworkWallet, TransactionBuilder,
TransactionBuilderError,
};

impl TransactionBuilder<AnyNetwork> for WithOtherFields<TransactionRequest> {
fn chain_id(&self) -> Option<ChainId> {
Expand Down Expand Up @@ -154,10 +157,10 @@ impl TransactionBuilder<AnyNetwork> for WithOtherFields<TransactionRequest> {
Ok(self.inner.build_typed_tx().expect("checked by missing_keys"))
}

async fn build<S: crate::NetworkSigner<AnyNetwork>>(
async fn build<W: NetworkWallet<AnyNetwork>>(
self,
signer: &S,
wallet: &W,
) -> Result<<AnyNetwork as Network>::TxEnvelope, TransactionBuilderError<AnyNetwork>> {
Ok(signer.sign_request(self).await?)
Ok(wallet.sign_request(self).await?)
}
}
8 changes: 4 additions & 4 deletions crates/network/src/ethereum/builder.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
BuildResult, Ethereum, Network, NetworkSigner, TransactionBuilder, TransactionBuilderError,
BuildResult, Ethereum, Network, NetworkWallet, TransactionBuilder, TransactionBuilderError,
};
use alloy_consensus::{BlobTransactionSidecar, TxType, TypedTransaction};
use alloy_primitives::{Address, Bytes, ChainId, TxKind, U256};
Expand Down Expand Up @@ -171,11 +171,11 @@ impl TransactionBuilder<Ethereum> for TransactionRequest {
Ok(self.build_typed_tx().expect("checked by missing_keys"))
}

async fn build<S: NetworkSigner<Ethereum>>(
async fn build<W: NetworkWallet<Ethereum>>(
self,
signer: &S,
wallet: &W,
) -> Result<<Ethereum as Network>::TxEnvelope, TransactionBuilderError<Ethereum>> {
Ok(signer.sign_request(self).await?)
Ok(wallet.sign_request(self).await?)
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/network/src/ethereum/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::{Network, ReceiptResponse, TransactionResponse};

mod builder;

mod signer;
pub use signer::EthereumSigner;
mod wallet;
pub use wallet::EthereumWallet;

/// Types for a mainnet-like Ethereum network.
#[derive(Clone, Copy, Debug)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
use crate::{Network, NetworkSigner, TxSigner};
use crate::{Network, NetworkWallet, TxSigner};
use alloy_consensus::{SignableTransaction, TxEnvelope, TypedTransaction};
use alloy_primitives::Address;
use alloy_signer::Signature;
use async_trait::async_trait;
use std::{collections::BTreeMap, sync::Arc};

/// A signer capable of signing any transaction for the Ethereum network.
/// A wallet capable of signing any transaction for the Ethereum network.
#[derive(Clone, Default)]
pub struct EthereumSigner {
pub struct EthereumWallet {
default: Address,
secp_signers: BTreeMap<Address, Arc<dyn TxSigner<Signature> + Send + Sync>>,
signers: BTreeMap<Address, Arc<dyn TxSigner<Signature> + Send + Sync>>,
}

impl std::fmt::Debug for EthereumSigner {
impl std::fmt::Debug for EthereumWallet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EthereumSigner")
f.debug_struct("EthereumWallet")
.field("default_signer", &self.default)
.field("credentials", &self.secp_signers.len())
.field("credentials", &self.signers.len())
.finish()
}
}

impl<S> From<S> for EthereumSigner
impl<S> From<S> for EthereumWallet
where
S: TxSigner<Signature> + Send + Sync + 'static,
{
Expand All @@ -30,7 +30,7 @@ where
}
}

impl EthereumSigner {
impl EthereumWallet {
/// Create a new signer with the given signer as the default signer.
pub fn new<S>(signer: S) -> Self
where
Expand All @@ -50,7 +50,7 @@ impl EthereumSigner {
where
S: TxSigner<Signature> + Send + Sync + 'static,
{
self.secp_signers.insert(signer.address(), Arc::new(signer));
self.signers.insert(signer.address(), Arc::new(signer));
}

/// Register a new signer on this object, and set it as the default signer.
Expand All @@ -69,15 +69,15 @@ impl EthereumSigner {

/// Get the default signer.
pub fn default_signer(&self) -> Arc<dyn TxSigner<Signature> + Send + Sync + 'static> {
self.secp_signers.get(&self.default).cloned().expect("invalid signer")
self.signers.get(&self.default).cloned().expect("invalid signer")
}

/// Get the signer for the given address.
pub fn signer_by_address(
&self,
address: Address,
) -> Option<Arc<dyn TxSigner<Signature> + Send + Sync + 'static>> {
self.secp_signers.get(&address).cloned()
self.signers.get(&address).cloned()
}

#[doc(alias = "sign_tx_inner")]
Expand All @@ -97,7 +97,7 @@ impl EthereumSigner {

#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl<N> NetworkSigner<N> for EthereumSigner
impl<N> NetworkWallet<N> for EthereumWallet
where
N: Network<UnsignedTx = TypedTransaction, TxEnvelope = TxEnvelope>,
{
Expand All @@ -106,11 +106,11 @@ where
}

fn has_signer_for(&self, address: &Address) -> bool {
self.secp_signers.contains_key(address)
self.signers.contains_key(address)
}

fn signer_addresses(&self) -> impl Iterator<Item = Address> {
self.secp_signers.keys().copied()
self.signers.keys().copied()
}

#[doc(alias = "sign_tx_from")]
Expand Down
4 changes: 2 additions & 2 deletions crates/network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ use core::fmt::{Debug, Display};

mod transaction;
pub use transaction::{
BuildResult, NetworkSigner, TransactionBuilder, TransactionBuilderError, TxSigner,
BuildResult, NetworkWallet, TransactionBuilder, TransactionBuilderError, TxSigner,
TxSignerSync, UnbuiltTransactionError,
};

mod ethereum;
pub use ethereum::{Ethereum, EthereumSigner};
pub use ethereum::{Ethereum, EthereumWallet};

mod any;
pub use any::AnyNetwork;
Expand Down
6 changes: 3 additions & 3 deletions crates/network/src/transaction/builder.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::signer::NetworkSigner;
use super::signer::NetworkWallet;
use crate::Network;
use alloy_consensus::BlobTransactionSidecar;
use alloy_primitives::{Address, Bytes, ChainId, TxKind, U256};
Expand Down Expand Up @@ -365,8 +365,8 @@ pub trait TransactionBuilder<N: Network>: Default + Sized + Send + Sync + 'stati
fn build_unsigned(self) -> BuildResult<N::UnsignedTx, N>;

/// Build a signed transaction.
fn build<S: NetworkSigner<N>>(
fn build<W: NetworkWallet<N>>(
self,
signer: &S,
wallet: &W,
) -> impl_future!(<Output = Result<N::TxEnvelope, TransactionBuilderError<N>>>);
}
2 changes: 1 addition & 1 deletion crates/network/src/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ pub use builder::{
};

mod signer;
pub use signer::{NetworkSigner, TxSigner, TxSignerSync};
pub use signer::{NetworkWallet, TxSigner, TxSignerSync};
8 changes: 4 additions & 4 deletions crates/network/src/transaction/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@ use async_trait::async_trait;
use auto_impl::auto_impl;
use futures_utils_wasm::impl_future;

/// A signer capable of signing any transaction for the given network.
/// A wallet capable of signing any transaction for the given network.
///
/// Network crate authors should implement this trait on a type capable of
/// signing any transaction (regardless of signature type) on a given network.
/// Signer crate authors should instead implement [`TxSigner`] to signify
/// signing capability for specific signature types.
///
/// Network signers are expected to contain one or more signing credentials,
/// Network wallets are expected to contain one or more signing credentials,
/// keyed by signing address. The default signer address should be used when
/// no specific signer address is specified.
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[auto_impl(&, &mut, Box, Rc, Arc)]
pub trait NetworkSigner<N: Network>: std::fmt::Debug + Send + Sync {
pub trait NetworkWallet<N: Network>: std::fmt::Debug + Send + Sync {
/// Get the default signer address. This address should be used
/// in [`NetworkSigner::sign_transaction_from`] when no specific signer is
/// in [`NetworkWallet::sign_transaction_from`] when no specific signer is
/// specified.
fn default_signer_address(&self) -> Address;

Expand Down
7 changes: 4 additions & 3 deletions crates/provider/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ alloy-consensus.workspace = true
alloy-json-rpc.workspace = true
alloy-network.workspace = true
alloy-node-bindings = { workspace = true, optional = true }
alloy-signer-wallet = { workspace = true, optional = true }
alloy-signer-local = { workspace = true, optional = true }
alloy-rpc-client.workspace = true
alloy-rpc-types-anvil = { workspace = true, optional = true }
alloy-rpc-types-eth.workspace = true
Expand Down Expand Up @@ -55,9 +55,10 @@ alloy-rpc-client = { workspace = true, features = ["reqwest"] }
alloy-rlp.workspace = true
alloy-sol-types.workspace = true
alloy-signer.workspace = true
alloy-signer-wallet.workspace = true
alloy-signer-local.workspace = true
alloy-transport-http = { workspace = true, features = ["reqwest"] }

itertools.workspace = true
reqwest.workspace = true
tokio = { workspace = true, features = ["macros"] }
tracing-subscriber = { workspace = true, features = ["fmt"] }
Expand All @@ -83,6 +84,6 @@ anvil-node = [
"anvil-api",
"reqwest",
"dep:alloy-node-bindings",
"dep:alloy-signer-wallet",
"dep:alloy-signer-local",
]
engine-api = ["dep:alloy-rpc-types-engine"]
Loading

0 comments on commit 92b824f

Please sign in to comment.