Maison >interface Web >js tutoriel >Explorer le protocole Mina : cas d'utilisation pratiques pour les applications zk
Zkapps (applications sans connaissance) sont des contrats intelligents de protocole mina qui sont alimentés par des preuves de connaissance nulle, en particulier zk-Snarks [Argument de connaissance succinct non interactif sans connaissance].zkapps a remplacé les snapps [Argument de connaissance intelligent non interactif Applications]. Les contrats intelligents ZkApp sont écrits à l'aide de o1js (une bibliothèque TypeScript). zkApps s'exécute côté client dans le navigateur Web d'un utilisateur et publie uniquement une petite preuve de validité qui est ensuite vérifiée par les nœuds Mina. Zkapp se compose d'un contrat intelligent et d'une interface utilisateur que je décrirai plus en détail dans la section suivante.
J'ai créé zkapp concernant la vérification de l'âge où l'âge de l'utilisateur est validé sans intervention sur les données personnelles.
J'ai procédé en installant le package zkapp-cli npm qui a en fait créé des modèles pour procéder à la fonction de preuve et à la fonction de vérification dans le cadre du processus de construction de la preuve zk
Vous trouverez ci-dessous la mise en œuvre de l'ajout d'une logique personnalisée de vérification. Il définit la logique du circuit pour les zk-SNARK, qui est utilisée lors de la génération de la preuve. La fonction de preuve réelle est gérée par la bibliothèque o1js et invoquée lorsque les méthodes zkApp sont exécutées hors chaîne avec des entrées privées.
import { Field, SmartContract, state, State, method } from 'o1js'; /** * Private Age Verification Contract * The contract will verify if the user's age is greater than or equal to the threshold age. * The contract uses zero-knowledge proofs to keep the user's age private. */ export class AgeVerification extends SmartContract { // State variable to store the verification result (valid or invalid) @state(Field) valid = State<Field>(); // Method to initialize the state init() { super.init(); this.valid.set(Field(0)); // Default is invalid } // Method to verify the age @method async verifyAge(age: Field, threshold: Field) { // Compute age - threshold const difference = age.sub(threshold); // Use circuit-compatible logic to check if the difference is non-negative const isValid = difference.equals(Field(0)).or(difference.greaterThanOrEqual(Field(0))) ? Field(1) : Field(0); // Set the validity of the verification result this.valid.set(isValid); } }
Le script ci-dessous est une suite de tests qui interagit avec la zkApp AgeVerification. Il invoque la logique du prouveur pendant txn.prove() et vérifie le comportement de zkApp en vérifiant son état mis à jour.
La fonction de preuve réelle réside dans la méthode zkApp sous-jacente (verifyAge), et txn.prove() est le mécanisme permettant de générer la preuve pendant les tests.
Pour tester les entrées, j'ai modifié le script de test comme suit.
import { AccountUpdate, Field, Mina, PrivateKey, PublicKey } from 'o1js'; import { AgeVerification } from './AgeVerification'; // Import the correct contract let proofsEnabled = false; describe('AgeVerification', () => { let deployerAccount: Mina.TestPublicKey, deployerKey: PrivateKey, senderAccount: Mina.TestPublicKey, senderKey: PrivateKey, zkAppAddress: PublicKey, zkAppPrivateKey: PrivateKey, zkApp: AgeVerification; // Update to use AgeVerification instead of Add beforeAll(async () => { if (proofsEnabled) await AgeVerification.compile(); // Update compile for AgeVerification }); beforeEach(async () => { const Local = await Mina.LocalBlockchain({ proofsEnabled }); Mina.setActiveInstance(Local); [deployerAccount, senderAccount] = Local.testAccounts; let feePayer = Local.testAccounts[0].key; deployerKey = deployerAccount.key; senderKey = senderAccount.key; zkAppPrivateKey = PrivateKey.random(); zkAppAddress = zkAppPrivateKey.toPublicKey(); zkApp = new AgeVerification(zkAppAddress); // Instantiate AgeVerification contract }); async function localDeploy() { const txn = await Mina.transaction(deployerAccount, async () => { AccountUpdate.fundNewAccount(deployerAccount); await zkApp.deploy(); }); await txn.prove(); // this tx needs .sign(), because `deploy()` adds an account update that requires signature authorization await txn.sign([deployerKey, zkAppPrivateKey]).send(); } it('generates and deploys the `AgeVerification` smart contract', async () => { await localDeploy(); const valid = zkApp.valid.get(); // Access the 'valid' state variable expect(valid).toEqual(Field(0)); // Initially, the contract should set 'valid' to Field(0) }); it('correctly verifies the age in the `AgeVerification` smart contract', async () => { await localDeploy(); const age = Field(25); // Example age value const threshold = Field(18); // Example threshold value // Call the verifyAge method const txn = await Mina.transaction(senderAccount, async () => { await zkApp.verifyAge(age, threshold); // Use the verifyAge method }); await txn.prove(); await txn.sign([senderKey]).send(); const valid = zkApp.valid.get(); // Check the validity state after verification expect(valid).toEqual(Field(1)); // Expected to be valid if age >= threshold }); });
Ci-dessous le résultat du test
J'ai ajouté le mécanisme de preuve dans le fichier Interactive.ts qui génère essentiellement une preuve zk-SNARK et soumet la preuve lorsqu'elle est effectuée pour une transaction dans la blockchain mina. Pendant que le script Interactive.ts génère la preuve, la vérification est effectuée par la blockchain Mina lors du traitement de la transaction. Il s'agit d'un aspect clé des systèmes zk-SNARK : le prouveur génère une preuve que le vérificateur (réseau Mina) vérifie.
import fs from 'fs/promises'; import { Mina, NetworkId, PrivateKey, Field } from 'o1js'; import { AgeVerification } from './AgeVerification'; // check command line arg let deployAlias = process.argv[2]; if (!deployAlias) throw Error(`Missing <deployAlias> argument. Usage: node build/src/interact.js <deployAlias> `); Error.stackTraceLimit = 1000; const DEFAULT_NETWORK_ID = 'testnet'; // parse config and private key from file type Config = { deployAliases: Record< string, { networkId?: string; url: string; keyPath: string; fee: string; feepayerKeyPath: string; feepayerAlias: string; } >; }; let configJson: Config = JSON.parse(await fs.readFile('config.json', 'utf8')); let config = configJson.deployAliases[deployAlias]; let feepayerKeysBase58: { privateKey: string; publicKey: string } = JSON.parse( await fs.readFile(config.feepayerKeyPath, 'utf8') ); let zkAppKeysBase58: { privateKey: string; publicKey: string } = JSON.parse( await fs.readFile(config.keyPath, 'utf8') ); let feepayerKey = PrivateKey.fromBase58(feepayerKeysBase58.privateKey); let zkAppKey = PrivateKey.fromBase58(zkAppKeysBase58.privateKey); // set up Mina instance and contract we interact with const Network = Mina.Network({ // We need to default to the testnet networkId if none is specified for this deploy alias in config.json // This is to ensure the backward compatibility. networkId: (config.networkId ?? DEFAULT_NETWORK_ID) as NetworkId, mina: config.url, }); const fee = Number(config.fee) * 1e9; // in nanomina (1 billion = 1.0 mina) Mina.setActiveInstance(Network); let feepayerAddress = feepayerKey.toPublicKey(); let zkAppAddress = zkAppKey.toPublicKey(); let zkApp = new AgeVerification(zkAppAddress); let age = Field(25); // Example age let threshold = Field(18); // Example threshold age // compile the contract to create prover keys console.log('compile the contract...'); await AgeVerification.compile(); try { // call verifyAge() and send transaction console.log('build transaction and create proof...'); let tx = await Mina.transaction( { sender: feepayerAddress, fee }, async () => { await zkApp.verifyAge(age, threshold); // Replacing update() with verifyAge } ); await tx.prove(); console.log('send transaction...'); const sentTx = await tx.sign([feepayerKey]).send(); if (sentTx.status === 'pending') { console.log( '\nSuccess! Age verification transaction sent.\n' + '\nYour smart contract state will be updated' + `\nas soon as the transaction is included in a block:` + `\n${getTxnUrl(config.url, sentTx.hash)}` ); } } catch (err) { console.log(err); } function getTxnUrl(graphQlUrl: string, txnHash: string | undefined) { const hostName = new URL(graphQlUrl).hostname; const txnBroadcastServiceName = hostName .split('.') .filter((item) => item === 'minascan')?.[0]; const networkName = graphQlUrl .split('/') .filter((item) => item === 'mainnet' || item === 'devnet')?.[0]; if (txnBroadcastServiceName && networkName) { return `https://minascan.io/${networkName}/tx/${txnHash}?type=zk-tx`; } return `Transaction hash: ${txnHash}`; }
J'ai utilisé des entrées pour l'âge et le seuil comme 25 et 18.
Depuis que les tests ont été effectués avec succès en exécutant npm run test. J'ai procédé au déploiement sur devnet en utilisant zk config
Où j'ai fourni les entrées suivantes :
Déployer l'alias : tester
Type de réseau : testnet
URL : https://api.minascan.io/node/devnet/v1/graphql
Payeur : Nouvelles clés de contribuable
Transaction : 0,1
L'URL peut être récupérée ici :
Puis lors du déploiement, j'ai reçu la réponse suivante.
Le contrat est déployé sur le devnet suivant
Après le déploiement, j'ai procédé à l'interface utilisateur où j'ai choisi du HTML, CSS et js simples en donnant mon URL RPC et l'adresse du contrat déployé et c'est l'interface utilisateur finale.
Ceci conclut la création de zkapp après l'intégration du contrat intelligent avec l'interface utilisateur. Après avoir créé l'interface utilisateur (UI) pour la zkApp AgeVerification, l'intégration du frontend avec le contrat intelligent permet aux utilisateurs d'interagir de manière transparente avec le système de preuve sans connaissance. L'interface utilisateur facilite la soumission des données d'âge et de seuil de l'utilisateur au contrat, tout en préservant la confidentialité via zk-SNARK. Cela permet aux utilisateurs de vérifier leur âge sans révéler la valeur réelle, préservant ainsi la confidentialité. Le backend, utilisant la fonction de preuve, génère la preuve et la blockchain Mina la vérifie efficacement. Cette solution de bout en bout garantit une expérience sécurisée et conviviale tout en tirant pleinement parti des fonctionnalités de confidentialité et d'évolutivité offertes par l'architecture basée sur zk-SNARK de Mina.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!