Construire une blockchain fonctionnelle avec preuve de travail (Proof of Work) depuis zéro.
Tu comprendras les mécanismes cryptographiques sous-jacents d'Ethereum et Bitcoin tout en pratiquant Rust avancé.
Durée estimée : 2-3 semaines à temps partiel
[dependencies]
# Cryptographie
sha2 = "0.10" # Hashing SHA-256
hex = "0.4" # Conversion bytes <-> hexadécimal
# Sérialisation
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
# Date/Temps
chrono = "0.4" # Timestamps
# CLI (optionnel mais recommandé)
clap = { version = "4.0", features = ["derive"] }cargo-watch: Recompilation automatique (cargo install cargo-watch)cargo-expand: Voir le code généré par les macros- Tests unitaires : Framework intégré de Rust (
#[test])
- Quand cloner vs emprunter (
&vs.clone()) - Lifetime annotations pour les références dans les structs
- Comprendre pourquoi certaines données doivent être
'static
- Implémenter
std::fmt::Displaypour un affichage custom - Créer un trait
Hashablepour tout ce qui doit être hashé - Utiliser
deriveintelligemment (Debug, Clone, Serialize)
- Créer des enums d'erreur personnalisées
- Utiliser
thiserrorou définir tes propres types d'erreur - Propager les erreurs avec
?et gérer les cas limites
- Manipuler
Vec<T>efficacement - Utiliser
.iter(),.map(),.filter()pour la validation - Comprendre quand utiliser
collect()vsfor_each()
- Comprendre comment SHA-256 fonctionne conceptuellement
- Manipuler des arrays de bytes (
[u8; 32]) - Convertir entre String, bytes, et hexadécimal
src/
├── main.rs # Point d'entrée CLI
├── block.rs # Définition d'un bloc
├── blockchain.rs # Chaîne complète + validation
├── transaction.rs # Modèle de transaction
├── proof_of_work.rs # Algorithme de minage
├── wallet.rs # (Optionnel) Gestion d'adresses
└── utils.rs # Fonctions helpers (hashing, etc.)
Questions de design :
-
Quelles données un bloc doit-il contenir ?
- Index du bloc dans la chaîne
- Timestamp de création
- Transactions contenues
- Hash du bloc précédent
- Nonce (pour le proof of work)
- Hash du bloc actuel
-
Comment garantir l'immutabilité des blocs après création ?
-
Faut-il stocker le hash ou le calculer à chaque fois ?
Concepts clés :
- Struct avec champs publics vs privés
- Méthodes pour créer un bloc (constructeur + builder pattern ?)
- Implémenter une méthode
calculate_hash()qui concatène tous les champs
Challenges :
- Le bloc Genesis (premier bloc) : Comment le rendre spécial ?
- Validation : Comment vérifier qu'un bloc est valide ?
Ce qu'une transaction doit représenter :
- Émetteur (adresse/identifiant)
- Destinataire
- Montant
- Timestamp
- Signature ? (optionnel pour V1)
Questions importantes :
- Comment générer des adresses uniques ?
- Faut-il vérifier les soldes ? (UTXOs comme Bitcoin ou comptes comme Ethereum ?)
- Comment empêcher les doubles dépenses ?
Concepts :
- Struct simple avec validation dans le constructeur
- Méthode
is_valid()pour vérifier la cohérence - Sérialisation en JSON pour le stockage
Le principe :
Le minage consiste à trouver un nonce tel que le hash du bloc commence par N zéros.
Questions algorithmiques :
- Quelle difficulté choisir ? (nombre de zéros requis)
- Comment incrémenter le nonce efficacement ?
- Quand arrêter la boucle de minage ?
- Comment afficher la progression (optionnel) ?
Concepts :
- Boucles infinies avec condition de sortie
- Conversion de hash en format binaire/hexadécimal
- Performance : combien de hashs par seconde ?
Challenge avancé : Ajuste la difficulté dynamiquement (comme Bitcoin) si les blocs sont minés trop vite.
Structure de données :
- Un
Vec<Block>pour stocker la chaîne - Transactions en attente (mempool) :
Vec<Transaction> - Difficulté actuelle
Fonctionnalités essentielles :
- Récupérer les transactions en attente
- Créer un nouveau bloc avec le hash du dernier bloc
- Lancer le proof of work
- Ajouter le bloc à la chaîne
- Vider le mempool
Pour chaque bloc (sauf Genesis) :
- Son hash est-il correct ?
- Le
previous_hashcorrespond-il au hash du bloc précédent ? - Le proof of work est-il valide ?
Si tu as plusieurs chaînes, laquelle est la "vraie" ?
→ La plus longue gagne (ou celle avec le plus de travail cumulé)
Concepts :
- Méthodes mutables (
&mut self) pour ajouter des blocs - Méthodes immutables (
&self) pour validation - Gestion d'erreurs si validation échoue
Fonctions helpers :
hash_string(data: &str) -> String: Calcule SHA-256 d'une stringhash_block(block: &Block) -> String: Hash toutes les données d'un blocmeets_difficulty(hash: &str, difficulty: usize) -> bool: Vérifie les zéros
Concepts :
- Utiliser le crate
sha2avecDigesttrait - Formatter les bytes en hexadécimal avec
hex - Fonctions pures (pas d'effets de bord)
Commandes à implémenter :
| Commande | Action |
|---|---|
init |
Créer une nouvelle blockchain avec bloc Genesis |
add-transaction <from> <to> <amount> |
Ajouter une transaction au mempool |
mine |
Miner un nouveau bloc avec les transactions en attente |
balance <address> |
Afficher le solde d'une adresse |
chain |
Afficher toute la blockchain |
validate |
Vérifier l'intégrité de la chaîne |
save / load |
Persister la blockchain en JSON |
Concepts :
- Parsing d'arguments avec
clapoustd::env::args() - Match sur les commandes
- Feedback utilisateur clair (succès, erreurs, temps de minage)
-
Wallets avec Clés Publiques/Privées
- Génération de paires de clés (crate
ed25519-dalek) - Signature des transactions
- Vérification cryptographique
- Génération de paires de clés (crate
-
Smart Contracts Basiques
- Un langage de script simple (if/then, transferts conditionnels)
- Machine virtuelle pour exécuter le code
-
Réseau P2P
- Plusieurs nœuds qui se synchronisent
- Protocole de gossip
- Résolution de forks
-
Merkle Trees
- Hacher les transactions dans un arbre
- Preuve d'inclusion (comme Bitcoin SPV)
-
Interface Web
- Backend API avec
actix-webouaxum - Frontend pour visualiser la chaîne
- Backend API avec
Comment créer le premier bloc sans previous_hash ?
→ Pense à une valeur par défaut (chaîne de zéros ? hash d'une phrase ?)
Comment vérifier qu'une adresse a assez de fonds ?
→ Dois-tu parcourir toute la chaîne ? Garder un état des balances ?
Si deux transactions dépensent le même argent, comment choisir ?
→ Première arrivée, première servie dans le mempool ?
Avec une difficulté de 4 zéros, combien de temps pour miner un bloc ?
→ Mesure avec std::time::Instant et optimise si nécessaire
Où sauvegarder la blockchain ?
→ Un seul gros JSON ? Plusieurs fichiers ? Base de données ?
// Exemples de tests à implémenter
#[test]
fn test_block_hashing() {
// Un bloc avec les mêmes données doit toujours avoir le même hash
}
#[test]
fn test_proof_of_work() {
// Le hash d'un bloc miné doit commencer par N zéros
}
#[test]
fn test_chain_validation() {
// Une chaîne valide doit passer la validation
// Une chaîne modifiée doit échouer
}
#[test]
fn test_transaction_validity() {
// Transactions avec montants négatifs doivent être rejetées
}
#[test]
fn test_genesis_block() {
// Le premier bloc doit avoir un previous_hash spécial
}Concepts :
#[cfg(test)]pour modules de tests- Assertions avec
assert_eq!,assert! - Tests qui doivent paniquer :
#[should_panic]
- ✅ Créer la struct
Blockavec tous ses champs - ✅ Implémenter
calculate_hash()pour un bloc - ✅ Fonction de hashing SHA-256 de base
- ✅ Tests : Vérifier que le même bloc produit le même hash
- ✅ Implémenter l'algorithme de minage (boucle + nonce)
- ✅ Fonction
meets_difficulty()pour vérifier les zéros - ✅ Tester avec différentes difficultés (2, 3, 4 zéros)
- ✅ Chronométrer le temps de minage
- ✅ Struct
BlockchainavecVec<Block> - ✅ Créer le bloc Genesis automatiquement
- ✅ Méthode
add_block()qui mine et ajoute - ✅ Méthode
is_valid()qui valide toute la chaîne
- ✅ Struct
Transactionavec validation - ✅ Mempool pour transactions en attente
- ✅ Intégrer les transactions dans les blocs
- ✅ Calculer les balances (parcourir la chaîne)
- ✅ Commandes CLI de base
- ✅ Sauvegarde JSON de la blockchain
- ✅ Chargement au démarrage
- ✅ Interface utilisateur agréable
- ✅ Tests complets
- ✅ Documentation (
///comments) - ✅ Gestion d'erreurs robuste
- ✅ Au choix : wallets, réseau, contracts...
- Bitcoin Whitepaper : Le document original de Satoshi (9 pages, très accessible)
- "Mastering Bitcoin" (Chapitre 9 sur la blockchain) : Gratuit en ligne
- Video "But how does bitcoin actually work?" (3Blue1Brown) : Excellente explication visuelle
- SHA-256 : Fonction de hashing unidirectionnelle
- Proof of Work : Trouver un hash avec propriétés spécifiques
- Merkle Trees : Structure pour prouver l'inclusion de données
| Concept Solidity | Équivalent dans ce Projet |
|---|---|
block.number |
Index du bloc |
block.timestamp |
Chrono timestamp |
msg.sender |
Champ from de Transaction |
require() |
Pattern matching + Result |
| Storage | Vec persisté en JSON |
| Events | Logs en CLI (optionnel) |
❌ Mauvais : let block = blockchain.get(0).unwrap();
✅ Bon : Pattern matching ou propagation d'erreur avec ?
❌ Mauvais : Cloner chaque bloc pour le valider
✅ Bon : Emprunter avec & quand c'est suffisant
Si tu stockes des références dans une struct, tu devras annoter les lifetimes.
💡 Alternative : Utiliser String au lieu de &str pour simplifier
Tu ne peux pas hasher une struct Rust directement.
→ Sérialise-la d'abord en JSON ou concatène ses champs en String
Commence avec 2-3 zéros max. 5 zéros = plusieurs minutes par bloc !
Tu as réussi le projet si :
- Tu peux miner des blocs avec preuve de travail
- La chaîne détecte toute modification frauduleuse
- Les transactions sont correctement stockées dans les blocs
- Les balances sont calculées avec précision
- Le programme survit à un redémarrage (persistence)
- Le code compile sans warnings
- Au moins 10 tests unitaires passent
- Tu comprends VRAIMENT comment fonctionne une blockchain
Peux-tu casser ta propre blockchain ?
- Modifie un bloc au milieu de la chaîne
- Change une transaction dans un bloc déjà miné
- Essaie de miner deux blocs avec le même
previous_hash - Crée une transaction avec montant négatif
- Dépense plus d'argent que tu n'en as
Si ton code détecte toutes ces fraudes, félicitations ! 🎉
Après ce projet, tu seras prêt pour :
- Contribuer à des projets blockchain open-source
- Comprendre le code source de Bitcoin/Ethereum
- Builder des dApps avec une compréhension profonde
- Implémenter des protocoles de consensus (PoS, PBFT...)
Bon courage ! N'hésite pas à expérimenter et à casser des choses. C'est comme ça qu'on apprend. 🦀⛓️
Remember: Une blockchain n'est qu'une liste chaînée avec des garanties cryptographiques.