Skip to content

A comprehensive Ethereum wallet and signer implementation in Rust

License

Notifications You must be signed in to change notification settings

dicethedev/signet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Signet

A comprehensive Ethereum wallet and signer implementation in Rust, built for learning blockchain protocol engineering.

Features

Phase 1: Core Functionality

  • 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)

Phase 2: HD Wallets

  • 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

Phase 3: Transaction Handling

  • 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

Quick Start

Installation

Add to your Cargo.toml:

[dependencies]
signet = "0.1.0"

Or use as a CLI tool:

cargo install --path .

Library Usage

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());

CLI Usage

# 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_KEY

Project Structure

signet/
├── 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

Key Concepts

Ethereum uses the secp256k1 elliptic curve for public key cryptography. Private keys are 256-bit numbers, and public keys are points on the curve.

Address Derivation

Ethereum addresses are derived by:

  1. Taking the uncompressed public key (65 bytes)
  2. Hashing with Keccak256
  3. 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.

Transaction Types

  • Legacy: Traditional transactions with gas price
  • EIP-1559: Modern transactions with base fee + priority fee

Development

Build

cargo build --release

Run Tests

cargo test

Run Examples

cargo run --example basic_usage

Run CLI

cargo run -- new
cargo run -- hd --words 12

Learning Path

This project is designed to teach blockchain protocol engineering concepts:

  1. Start with crypto.rs - Learn ECDSA, signing, and verification
  2. Move to address.rs - Understand address derivation and checksumming
  3. Explore wallet.rs - See how components work together
  4. Study hd_wallet.rs - Learn about BIP39 and BIP32
  5. Dive into transaction.rs - Understand transaction structure and RLP encoding
  6. Check keystore.rs - Learn about secure key storage

Security Notes

⚠️ This is a learning project. Do NOT use for real funds without thorough security review.

  • 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

Resources

Contributing

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

License

MIT License - See LICENSE file for details


Built with 🦀 Rust for learning blockchain protocol engineering

About

A comprehensive Ethereum wallet and signer implementation in Rust

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages