Skip to content

feat(signer): adds signer-stronghold #2420

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ jobs:
--exclude alloy-signer-ledger \
--exclude alloy-signer-local \
--exclude alloy-signer-trezor \
--exclude alloy-transport-ipc
--exclude alloy-transport-ipc \
--exclude alloy-signer-stronghold

wasm-wasi:
runs-on: ubuntu-latest
Expand All @@ -121,6 +122,7 @@ jobs:
--exclude alloy-signer-gcp \
--exclude alloy-signer-ledger \
--exclude alloy-signer-trezor \
--exclude alloy-signer-stronghold \
--exclude alloy-transport-ipc
# Ledger signer requires one of `browser` or `node` features.
- name: build ledger
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ alloy-signer-aws = { version = "1.0", path = "crates/signer-aws", default-featur
alloy-signer-gcp = { version = "1.0", path = "crates/signer-gcp", default-features = false }
alloy-signer-ledger = { version = "1.0", path = "crates/signer-ledger", default-features = false }
alloy-signer-local = { version = "1.0", path = "crates/signer-local", default-features = false }
alloy-signer-stronghold = { version = "1.0", path = "crates/signer-stronghold", default-features = false }
alloy-signer-trezor = { version = "1.0", path = "crates/signer-trezor", default-features = false }
alloy-transport = { version = "1.0", path = "crates/transport", default-features = false }
alloy-transport-http = { version = "1.0", path = "crates/transport-http", default-features = false }
Expand Down
3 changes: 2 additions & 1 deletion crates/node-bindings/src/nodes/geth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,8 @@ impl Geth {

if let Some(genesis) = &self.genesis {
// create a temp dir to store the genesis file
let temp_genesis_dir_path = tempdir().map_err(NodeError::CreateDirError)?.keep();
let temp_genesis_dir_path =
tempdir().map_err(NodeError::CreateDirError)?.path().to_path_buf();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was getting a compilation error from this when trying to clean + test.
This fixes that compilation error.


// create a temp dir to store the genesis file
let temp_genesis_path = temp_genesis_dir_path.join("genesis.json");
Expand Down
3 changes: 3 additions & 0 deletions crates/signer-stronghold/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/target
*.stronghold
*.env
30 changes: 30 additions & 0 deletions crates/signer-stronghold/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[package]
name = "alloy-signer-stronghold"
description = "An Ethereum signer for a Stronghold"

version.workspace = true
edition.workspace = true
rust-version.workspace = true
authors.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
exclude.workspace = true

[dependencies]
alloy-consensus.workspace = true
alloy-network.workspace = true
alloy-primitives = { workspace = true, features = ["k256"] }
alloy-signer.workspace = true
async-trait.workspace = true
iota_stronghold = "2.1.0"
k256 = { version = "0.13.4", features = ["ecdsa"] }
thiserror.workspace = true

[dev-dependencies]
alloy-network.workspace = true
alloy-provider = { workspace = true, features = ["anvil-api", "debug-api", "hyper"] }
alloy-node-bindings = { workspace = true }
alloy-rpc-types = { workspace = true, features = ["eth"] }
tokio = { workspace = true, features = ["rt", "rt-multi-thread"] }
tracing.workspace = true
23 changes: 23 additions & 0 deletions crates/signer-stronghold/LICENSE-MIT
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
68 changes: 68 additions & 0 deletions crates/signer-stronghold/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# signer-stronghold

An Ethereum [signer](https://docs.rs/alloy-signer/latest/alloy_signer/trait.Signer.html) for a Stronghold.

## What is a Stronghold?

From [the documentation](https://github.com/iotaledger/stronghold.rs/blob/iota-stronghold-v2.1.0/client/src/types/stronghold.rs#L77-L82):

> The Stronghold is a secure storage for sensitive data. Secrets that are stored inside
> a Stronghold can never be read, but only be accessed via cryptographic procedures. Data inside
> a Stronghold is heavily protected by the `Runtime` by either being encrypted at rest, having
> kernel supplied memory guards, that prevent memory dumps, or a combination of both. The Stronghold
> also persists data written into a Stronghold by creating Snapshots of the current state. The
> Snapshot itself is encrypted and can be accessed by a key.

[Learn more here](https://github.com/iotaledger/stronghold.rs/tree/iota-stronghold-v2.1.0)


## Usage

```bash
## treat this environment variable with the same care as a private key

export PASSPHRASE=$(openssl rand -hex 48) # or whatever you want
```

### Basic Usage

```rust,no_run
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
use alloy_signer_stronghold::StrongholdSigner;
use alloy_signer::Signer;

let chain_id = Some(1);
let signer = StrongholdSigner::new(chain_id).unwrap();

let message = vec![0, 1, 2, 3];

let sig = signer.sign_message(&message).await.unwrap();
assert_eq!(sig.recover_address_from_msg(message).unwrap(), signer.address());
Ok(())
}
```

### With Custom Path

```rust,no_run
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
use alloy_signer_stronghold::StrongholdSigner;
use alloy_signer::Signer;
use std::path::PathBuf;

let chain_id = Some(1);
let custom_path = PathBuf::from("/path/to/my_custom.stronghold");
let signer = StrongholdSigner::new_from_path(custom_path, chain_id).unwrap();

// Use signer just like the default one
let message = vec![0, 1, 2, 3];
let sig = signer.sign_message(&message).await.unwrap();
Ok(())
}
```

## License

This project is licensed under the MIT License - see the [LICENSE-MIT](LICENSE-MIT) file for details.
10 changes: 10 additions & 0 deletions crates/signer-stronghold/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#![doc = include_str!("../README.md")]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/alloy.jpg",
html_favicon_url = "https://raw.githubusercontent.com/alloy-rs/core/main/assets/favicon.ico"
)]
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

mod signer;
pub use signer::StrongholdSigner;
Loading