A comprehensive Ethereum wallet and signer implementation in Rust, built for learning blockchain protocol engineering.
- Generate random private/public key pairs using secp256k1
- Derive Ethereum addresses from public keys (with EIP-55 checksumming)
- Sign messages using EIP-191 personal_sign format
- Verify signatures and recover public keys
- Encrypted keystore support (Web3 Secret Storage Definition)
- BIP39 mnemonic generation and recovery (12, 15, 18, 21, 24 words)
- BIP32 hierarchical deterministic key derivation
- Support for custom derivation paths
- Multiple account management from a single seed
- Build and sign legacy Ethereum transactions
- Build and sign EIP-1559 transactions
- RLP encoding for transaction serialization
- Transaction hash calculation
- Support for contract calls with data payloads
Add to your Cargo.toml:
[dependencies]
signet = "0.1.0"Or use as a CLI tool:
cargo install --path .use signet::{Wallet, HdWalletManager, WordCount, Address, LegacyTransaction};
// Create a random wallet
let wallet = Wallet::new();
println!("Address: {}", wallet.address());
// Sign a message
let message = b"Hello, Ethereum!";
let signature = wallet.sign_message(message)?;
// Create HD wallet with mnemonic
let hd_manager = HdWalletManager::new(WordCount::Words12);
println!("Mnemonic: {}", hd_manager.mnemonic());
// Derive multiple accounts
let wallet = hd_manager.derive_wallet(0)?;
// Create and sign a transaction
let recipient = Address::from_hex("0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0")?;
let tx = LegacyTransaction::transfer(
recipient,
1_000_000_000_000_000_000, // 1 ETH in wei
0, // nonce
21_000_000_000, // gas price (21 gwei)
21_000, // gas limit
1, // chain ID (mainnet)
);
let signed_tx = wallet.sign_legacy_transaction(&tx)?;
println!("Transaction hash: {}", signed_tx.hash_hex());# Generate a new wallet
signet new
# Generate HD wallet with 12-word mnemonic
signet hd --words 12 --accounts 5
# Recover wallet from mnemonic
signet recover "your twelve word mnemonic phrase here..."
# Import wallet from private key
signet import 0xYOUR_PRIVATE_KEY --output wallet.json
# Sign a message
signet sign "Hello, Ethereum!" --key 0xYOUR_PRIVATE_KEY
# Verify a signature
signet verify "Hello, Ethereum!" 0xSIGNATURE 0xADDRESS
# Create and sign a transaction
signet tx 0xRECIPIENT 1000000000000000000 \
--nonce 0 \
--gas-price 21 \
--gas-limit 21000 \
--chain-id 1 \
--key 0xYOUR_PRIVATE_KEYsignet/
├── src/
│ ├── address.rs # Ethereum address derivation and formatting
│ ├── crypto.rs # Cryptographic primitives (ECDSA signing/verification)
│ ├── error.rs # Error types
│ ├── hd_wallet.rs # BIP39/BIP32 HD wallet implementation
│ ├── keystore.rs # Encrypted keystore (Web3 Secret Storage)
│ ├── transaction.rs # Transaction building and signing
│ ├── wallet.rs # Main wallet interface
│ ├── lib.rs # Library exports
│ └── main.rs # CLI application
├── examples/
│ └── basic_usage.rs # Example usage
└── tests/
└── integration_tests.rs # Integration tests
Ethereum uses the secp256k1 elliptic curve for public key cryptography. Private keys are 256-bit numbers, and public keys are points on the curve.
Ethereum addresses are derived by:
- Taking the uncompressed public key (65 bytes)
- Hashing with Keccak256
- Taking the last 20 bytes
Messages are prefixed with \x19Ethereum Signed Message:\n{length} before signing to prevent transaction replay attacks.
Addresses include mixed-case checksums to prevent typos and improve security.
Human-readable phrases (12-24 words) that encode a random seed for HD wallets.
A system for deriving multiple private keys from a single seed using derivation paths like m/44'/60'/0'/0/0.
- Legacy: Traditional transactions with gas price
- EIP-1559: Modern transactions with base fee + priority fee
cargo build --releasecargo testcargo run --example basic_usagecargo run -- new
cargo run -- hd --words 12This project is designed to teach blockchain protocol engineering concepts:
- Start with crypto.rs - Learn ECDSA, signing, and verification
- Move to address.rs - Understand address derivation and checksumming
- Explore wallet.rs - See how components work together
- Study hd_wallet.rs - Learn about BIP39 and BIP32
- Dive into transaction.rs - Understand transaction structure and RLP encoding
- Check keystore.rs - Learn about secure key storage
- Always use secure random number generation
- Store private keys encrypted at rest
- Never hardcode private keys
- Use HD wallets and derive accounts from mnemonics
- Verify addresses with checksums
- Test transactions on testnets first
- Ethereum Yellow Paper
- BIP39 Specification
- BIP32 Specification
- EIP-191: Signed Data Standard
- EIP-1559: Fee Market
- Web3 Secret Storage Definition
This is a learning project, but contributions are welcome! Feel free to:
- Add more transaction types
- Implement EIP-712 typed data signing
- Add hardware wallet support
- Improve error handling
- Add more examples
MIT License - See LICENSE file for details
Built with 🦀 Rust for learning blockchain protocol engineering