9 minutes de lecture
Aperçu
Dans le guide d'introduction, nous avons abordé l'architecture d'Aleo : exécution hors chaîne, vérification sur la chaîne et enregistrements en tant qu'état privé. Ce guide vous permettra de mettre ces concepts en pratique. Vous allez créer un jeton privé dans Leo, le tester, puis le déployer sur le Testnet d'Aleo via un point de terminaison Quicknode.
Le token que nous développons est volontairement simple : deux fonctions, aucun état public. Vous créez des tokens sous forme d'enregistrements chiffrés et les transférez de manière privée. Le réseau vérifie chaque transaction à l'aide d'une preuve à divulgation nulle de connaissance, mais ne voit jamais qui a envoyé les tokens, qui les a reçus, ni combien ont été transférés. C'est là l'argument de vente principal d'Aleo, et c'est ce vers quoi nous tendons ici.
- Nous créons un jeton privé doté de deux fonctions :
mint_privateettransfert_privé - Toutes les données d'état sont stockées dans des enregistrements chiffrés ; ainsi, rien n'est visible sur la blockchain.
- Tout le code utilise la syntaxe de Leo 4.0 :
fnpour les fonctions,enregistrementpour les types d'état privés - Déployer sur le testnet Aleo via un point de terminaison Quicknode avec
leo deploy --broadcast
Ce que vous allez apprendre
- Comment écrire un programme Leo utilisant des enregistrements pour garantir un état entièrement privé
- Comment effectuer un test avec
@testannotations ettest du Lion - Comment effectuer un déploiement sur le Testnet d'Aleo via
déploiement Leo - Comment effectuer des transactions privées et comprendre ce qui est visible sur la blockchain (rien)
Ce dont vous aurez besoin
- Connaissance des concepts présentés dans le guide « Introduction à Aleo et Leo »
- Rouille 1.94.1 ou une version plus récente (Leo nécessite cette version. Exécutez
Mise à jour de Rustup(à mettre à jour si nécessaire) - Un compte Quicknode avec un point de terminaison Aleo Testnet
- Crédits ALEO du réseau de test provenant du « faucet » Aleo
- Accès au terminal
Créer un point de terminaison Quicknode
Pour déployer des programmes et interagir avec eux sur le réseau Aleo, vous devez avoir accès à un point de terminaison RPC Aleo. Vous pourriez faire tourner votre propre nœud, mais Quicknode se charge de l'infrastructure à votre place.
Créez un compte Quicknode si ce n'est pas déjà fait. Une fois connecté, cliquez sur « Créer un point de terminaison », puis sélectionnez la chaîne Aleo et le réseau Testnet.

Une fois le point de terminaison créé, copiez l'URL du fournisseur HTTP. Vous l'ajouterez ultérieurement à la configuration de votre projet.
Ajouter /v2 à la fin de l'URL de votre point de terminaison Quicknode. Leo ajoute le chemin d'accès réseau (/testnet/...) automatiquement lors des appels API, et les points de terminaison Aleo de Quicknode nécessitent le /v2 préfixe.
Configuration de l'environnement de développement
Installez le compilateur Leo via cargo :
cargo install leo-lang
Vérifiez l'installation :
leo --version
Mettre en place un nouveau projet :
leo new private_token
cd private_token
Cela crée la structure de projet suivante :
| Fichier/Répertoire | Objectif |
|---|---|
src/main.leo | Le code source de votre programme |
tests/ | Fichiers de test avec @test fonctions annotées |
program.json | Métadonnées du projet : nom du programme, version, dépendances |
Il vous faudra également un .env fichier de configuration du déploiement. Créez-en un à la racine du projet :
Ajoutez l' .env à votre .gitignore. Ne placez jamais votre clé privée dans un système de gestion de versions.
touch .env
Ajoutez ce qui suit :
NETWORK=testnet
PRIVATE_KEY=APrivateKey1zkp... # generate one with: leo account new
ENDPOINT=https://your-quicknode-aleo-endpoint.quiknode.pro/your-auth-token/v2
Si vous ne disposez pas encore d'une clé privée, générez-en une à l'aide de Nouveau compte Leo et collez-le. Pour le point de terminaison, utilisez l'URL Quicknode que vous avez copiée précédemment avec /v2 en annexe.
Écriture du programme « Token »
Nous développons un jeton privé. Il n'y a pas de registre public des soldes, ni de mappage sur la chaîne que tout le monde peut consulter. Chaque jeton existe sous la forme d'un enregistrement crypté que seul son propriétaire peut voir. Lorsqu'une personne transfère des jetons, l'ancien enregistrement est supprimé et de nouveaux enregistrements sont créés, le tout hors chaîne. Le réseau ne voit qu'une preuve attestant que les règles ont été respectées.
Deux fonctions gèrent tout :
mint_privatecrée de nouveaux jetons sous la forme d'un enregistrement chiffrétransfert_privétransfère des jetons d'une adresse à une autre, en toute confidentialité
Remplacer le contenu de src/main.leo avec :
program private_token.aleo {
record Token {
owner: address,
amount: u64,
}
fn mint_private(receiver: address, amount: u64) -> Token {
return Token {
owner: receiver,
amount: amount,
};
}
fn transfer_private(sender: Token, receiver: address, amount: u64) -> (Token, Token) {
let difference: u64 = sender.amount - amount;
let remaining: Token = Token {
owner: sender.owner,
amount: difference,
};
let transferred: Token = Token {
owner: receiver,
amount: amount,
};
return (remaining, transferred);
}
@noupgrade
constructor() {}
}
Voyons ensemble ce qu'il y a ici :
enregistrer le jeton définit l'état privé. Chaque jeton est un enregistrement chiffré dans le registre, comportant un propriétaire et un montant. Seule la clé de consultation du propriétaire permet de le déchiffrer. Il n'existe pas de tableau public des soldes.
mint_private crée un nouveau Jeton enregistrement. Le processus se déroule entièrement hors chaîne. Le réseau vérifie la preuve, mais n'a jamais connaissance du destinataire ni du montant.
transfert_privé part d'un Jeton enregistre l'opération, la traite, puis génère deux nouveaux enregistrements : l'un pour le destinataire, indiquant le montant transféré, et l'autre pour l'expéditeur, indiquant le solde restant. Ce fonctionnement est similaire à celui du modèle UTXO de Bitcoin, à la différence près que tout est chiffré. Il n'y a pas de vérification explicite du solde, car les entiers Leo ne subissent pas de débordement vers le bas. Si montant de l'expéditeur - montant devienne négative, la transaction échoue automatiquement.
@noupgrade Le @noupgrade L'annotation verrouille le programme afin qu'il ne puisse plus être modifié après son déploiement. Pour les programmes pouvant être mis à jour, il faudrait plutôt écrire un constructeur intégrant la logique d'autorisation et utiliser Mise à jour de Leo pour publier de nouvelles versions
constructor() {} - Un constructeur est obligatoire pour tous les programmes Aleo.
Test du programme
Leo dispose d'un framework de test intégré. Les fonctions de test se trouvent dans le tests/ répertoire et utilisez la commande @test Annotation. Les fichiers de test sont eux-mêmes des programmes Leo ; ils nécessitent donc un programme bloc et un import pour le programme qu'ils testent.
Ouvrez le fichier existant tests/test_private_token.leo et remplacez son contenu par :
import private_token.aleo;
program test_private_token.aleo {
@test
fn test_mint_private() {
let receiver: address = aleo1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3ljyzc;
let result: private_token.aleo::Token = private_token.aleo::mint_private(receiver, 100u64);
assert_eq(result.owner, receiver);
assert_eq(result.amount, 100u64);
}
@test
fn test_transfer_private() {
let alice: address = self.signer;
let bob: address = aleo1qgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqanmpl0;
let minted: private_token.aleo::Token = private_token.aleo::mint_private(alice, 100u64);
let (remaining, transferred): (private_token.aleo::Token, private_token.aleo::Token) = private_token.aleo::transfer_private(minted, bob, 30u64);
assert_eq(transferred.owner, bob);
assert_eq(transferred.amount, 30u64);
assert_eq(remaining.owner, alice);
assert_eq(remaining.amount, 70u64);
}
@test
@should_fail
fn test_transfer_more_than_balance() {
let alice: address = aleo1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3ljyzc;
let bob: address = aleo1qgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqanmpl0;
let minted: private_token.aleo::Token = private_token.aleo::mint_private(alice, 50u64);
// This should fail: transferring 100 from a record with only 50
let (remaining, transferred): (private_token.aleo::Token, private_token.aleo::Token) = private_token.aleo::transfer_private(minted, bob, 100u64);
}
@noupgrade
constructor() {}
}
Exécutez les tests :
test du Lion

Quelques remarques concernant le fichier de test :
import private_token.aleo;met le programme principal dans la portée- Les types et les fonctions utilisent le chemin d'accès complet :
private_token.aleo::Token,private_token.aleo::mint_private() - Dans
test_transfert_privé, nous utilisonssignataire autonomecomme adresse de frappe, car la machine virtuelle exige que les enregistrements d'entrée appartiennent au signataire de la transaction @should_failindique à Leo que le test devrait échouer. Si la fonction s'exécute sans erreur, c'est le test lui-même qui échoue- Tout programme (y compris les programmes de test) doit disposer d'un constructeur. Nous utilisons
@noupgradeici, pour que ce soit simple
Vous pouvez filtrer les tests par nom :
leo test mint
Cela ne lance que les tests dont le nom contient « mint ».
Déploiement sur le réseau de test Aleo
Maintenant que le programme se compile et que les tests sont réussis, il est temps de le déployer.
Obtenir des crédits Testnet
Rendez-vous sur le site Aleo Faucet et demandez des crédits Testnet pour l'adresse de votre compte.
Comment trouver votre adresse Aleo
Courir Importation d'un compte Leo avec la clé privée issue de votre .env:
leo account import APrivateKey1zkp...
Cela affiche votre adresse, votre clé publique et votre clé privée. Copiez l'adresse.
Choisissez un nom de programme
Le nom de votre programme doit être unique sur l'ensemble du réseau. Si private_token.aleo est déjà pris, modifiez le nom dans les deux src/main.leo et program.json. Les noms comportant moins de 10 caractères sont soumis à des frais d'espace de noms qui augmentent à mesure que la longueur du nom diminue, à l'instar des noms de domaine courts qui coûtent plus cher. Les noms comportant 10 caractères ou plus ne sont soumis à aucun frais d'espace de noms.
Déployer
leo deploy --broadcast
Leo vous présentera le détail des frais avant de vous demander votre confirmation :
| Composante « frais » | Ce qu'il couvre |
|---|---|
| Stockage | 1 millicrédit par octet de données de programme |
| Synthèse | Proportionnelle à la complexité du circuit (nombre_de_variables + nombre_de_contraintes) |
| Espace de noms | Supplément pour les noms de programmes de moins de 10 caractères (0 pour les noms de 10 caractères ou plus) |
| Priorité | Conseil facultatif pour une inclusion plus rapide (valeur par défaut : 0) |
Une fois la confirmation obtenue, Leo diffuse la transaction de déploiement et surveille le réseau pendant un maximum de 12 blocs afin de vérifier qu'elle a bien été intégrée.

Vous pouvez vérifier le déploiement dans Aleo Explorer.
Exécution de transactions privées
Maintenant que le programme est déployé, mettons-le en pratique. Chaque étape décrite ci-dessous s'exécute hors chaîne sur votre ordinateur ; le réseau ne voit qu'une preuve.
Jetons Mint
leo execute mint_private <RECEIVER_ADDRESS> 1000u64 --broadcast
Remplacez <RECEIVER_ADDRESS> avec votre adresse Aleo. Cela crée un Jeton Enregistrement chiffré destiné au destinataire. La transaction est enregistrée sur la blockchain, mais le contenu de l'enregistrement (propriétaire, montant) est chiffré. Personne qui observe la blockchain ne peut savoir ce qui a été émis ni à qui.
Leo affiche l'enregistrement de sortie après l'exécution. Voici à quoi cela ressemble :
{
owner: aleo1abc...def.private,
amount: 1000u64.private,
_nonce: 6068899261705353026606683251009719039686976057706338283793929594435531277185group.public,
_version: 1u8.public
}
Le propriétaire et montant les champs sont marqués .privé, ce qui signifie qu'ils sont chiffrés dans le registre. Enregistrez l'enregistrement complet, car vous devrez le transmettre en tant que paramètre d'entrée à transfert_privé.
Jetons de transfert
leo execute transfer_private "{ owner: aleo1abc...def.private, amount: 1000u64.private, _nonce: 6068...185group.public, _version: 1u8.public }" <RECEIVER_ADDRESS> 300u64 --broadcast
Remplacez l'enregistrement par la sortie complète de votre étape « mint », placée entre guillemets. L'ensemble du { owner: ..., amount: ..., _nonce: ..., _version: ... } Le bloc prend un seul argument. Il utilise votre enregistrement existant et en crée deux nouveaux : 300 jetons pour le destinataire et 700 pour vous (le montant mis à jour).
Voici ce que voit le réseau : une preuve valide. C'est tout. Ni adresse d'expéditeur, ni adresse de destinataire, ni montant. Les validateurs confirment que les calculs sont corrects sans savoir en quoi consistent ces calculs.
Ce qui est visible sur la blockchain
C'est là tout l'intérêt de l'opération. Voici ce qui s'affiche localement dans votre terminal une fois le transfert terminé :

Votre terminal affiche à la fois les enregistrements de transaction (300 jetons vers le destinataire, 700 jetons en retour vers vous) et un identifiant de transaction. Vous savez exactement ce qui s'est passé.
Reprenez maintenant cet identifiant de transaction et recherchez-le dans Aleo Explorer. L'onglet « Aperçu » confirme que la transaction a bien été enregistrée sur la blockchain :

Le même identifiant de transaction, confirmé sur le réseau. Mais cliquez sur l'onglet « Transactions » :

Les entrées et les sorties sont chiffrées. Ni l'expéditeur, ni le destinataire, ni les montants ne sont identifiés. Les validateurs ont confirmé la validité de la preuve sans savoir en quoi consistait le transfert.
Comparez cela à un transfert standard de jetons EVM, où l'expéditeur, le destinataire, le montant et l'historique complet de la transaction sont accessibles à tous.
Conclusion
Nous sommes passés d'un projet à l'état brut à un jeton privé déployé sur le testnet d'Aleo. Le programme comporte deux fonctions : mint_private crée des jetons, transfert_privé les déplace. Toutes les données d'état sont stockées dans des enregistrements chiffrés. Aucune information concernant les soldes des jetons ou l'historique des transferts n'est visible sur la blockchain.
Il s'agit d'un exemple simplifié, mais il illustre le principe de base. Un jeton de production permettrait d'ajouter les soldes publics (à l'aide de mappages et final blocs), des fonctions de conversion permettant de passer du domaine public au domaine privé, ainsi que des contrôles d'accès à la création de pièces. Le guide d'introduction explique le fonctionnement des mappages et des blocs finaux si vous souhaitez aller plus loin.
Pour les appels inter-programmes, les Futures composés et d'autres modèles plus avancés, consultez la documentation pour les développeurs d'Aleo et le dépôt leo-examples.
Foire aux questions
Combien coûte le déploiement d'un programme Leo sur Aleo ?
Les frais de déploiement se composent de trois éléments : un coût de stockage de 1 millicrédit par octet de données de programme, un coût de synthèse proportionnel à la complexité du circuit (calculé en fonction du nombre de variables et de contraintes), et des frais liés à l'espace de noms pour les noms de programme de moins de 10 caractères. Les frais de priorité sont facultatifs et leur valeur par défaut est 0. L'interface en ligne de commande Leo vous présente le détail complet des coûts avant que vous ne confirmiez le déploiement.
Quelle est la différence entre « leo run » et « leo execute » ?
La commande « leo run » compile et exécute une fonction localement sans générer de preuve. Elle est utile pour effectuer des tests rapides pendant le développement. La commande « leo execute » effectue la même exécution locale, mais synthétise également le circuit et génère une preuve zk-SNARK, ce qui est nécessaire pour le déploiement et l'exécution sur la blockchain.
Puis-je mettre à jour un programme Leo déjà déployé sur Aleo ?
Oui, si le programme a été déployé en tant que programme pouvant être mis à jour, vous pouvez utiliser la commande « leo upgrade » pour déployer une nouvelle version. La mise à jour remplace le bytecode du programme sur la blockchain tout en conservant le même nom et la même adresse.
Pourquoi ne puis-je pas consulter le solde de mes jetons sur un explorateur de blocs ?
Les jetons privés utilisent des enregistrements, et non des mappages publics. Les enregistrements sont chiffrés dans le registre et seul leur propriétaire peut les déchiffrer à l'aide de sa clé de consultation. Les explorateurs de blocs ne peuvent afficher que l'état public (les mappages) ; les soldes des jetons privés leur sont donc invisibles. Vous ne pouvez consulter vos propres enregistrements qu'en local, via l'interface CLI de Leo.
Nous ❤️ les commentaires !
Faites-nous savoir si vous avez des commentaires ou des suggestions de nouveaux sujets. Nous serions ravis de vous entendre.
