Heim >Web-Frontend >js-Tutorial >Erkundung des Mina-Protokolls: Praktische Anwendungsfälle für zk-Anwendungen

Erkundung des Mina-Protokolls: Praktische Anwendungsfälle für zk-Anwendungen

DDD
DDDOriginal
2024-12-29 07:32:10674Durchsuche

Zkapps (Zero-Knowledge-Anwendungen) sind Mina-Protokoll-Smart-Contracts, die auf Zero-Knowledge-Beweisen basieren, insbesondere zk-Snarks [Zero-Knowledge Succinct Non-Interactive Argument of Knowledge]. Zkapps ersetzten Snapps [Smart Non-Interactive Argument of Knowledge]. Anwendungen]. ZkApp-Smart-Verträge werden mit o1js (einer TypeScript-Bibliothek) geschrieben. zkApps wird clientseitig im Webbrowser eines Benutzers ausgeführt und veröffentlicht nur einen kleinen Gültigkeitsnachweis, der dann von den Mina-Knoten überprüft wird. Zkapp besteht aus einem Smart Contract und einer Benutzeroberfläche, die ich im nächsten Abschnitt näher beschreiben werde.

Anwendung

Ich habe zkapp zur Altersüberprüfung erstellt, bei der das Alter des Benutzers ohne Eingriff in die persönlichen Daten validiert wird.

Ich fuhr mit der Installation des zkapp-cli npm-Pakets fort, das im Rahmen des ZK-Proof-Build-Prozesses tatsächlich Vorlagen für die Fortführung der Prüfer- und Verifiziererfunktion erstellte

Durchführung

Im Folgenden finden Sie die Implementierung des Hinzufügens einer benutzerdefinierten Verifizierungslogik. Es definiert die Schaltungslogik für zk-SNARKs, die bei der Beweiserstellung verwendet wird. Die eigentliche Beweisfunktion wird von der o1js-Bibliothek verwaltet und aufgerufen, wenn zkApp-Methoden außerhalb der Kette mit privaten Eingaben ausgeführt werden.

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


Das folgende Skript ist eine Testsuite, die mit der AgeVerification zkApp interagiert. Es ruft die Prüferlogik während txn.prove() auf und überprüft das Verhalten der zkApp, indem es ihren aktualisierten Status überprüft.

Die eigentliche Beweisfunktion liegt in der zugrunde liegenden zkApp-Methode (verifyAge), und txn.prove() ist der Mechanismus zum Generieren des Beweises während des Tests.

Um die Eingaben zu testen, habe ich das Testskript wie folgt bearbeitet.

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


Unten finden Sie das Testergebnis

Exploring the Mina Protocol: Practical Use Cases for zk Applications

Ich habe den Beweismechanismus in der Datei „interact.ts“ hinzugefügt, der im Grunde einen zk-SNARK-Beweis generiert und den Beweis übermittelt, wenn eine Transaktion in meiner Blockchain durchgeführt wird. Während das Skript „interact.ts“ den Nachweis generiert, wird die Verifizierung durch die Mina-Blockchain durchgeführt, wenn die Transaktion verarbeitet wird. Dies ist ein wichtiger Aspekt von zk-SNARK-Systemen, da der Prüfer einen Beweis generiert, den der Prüfer (Mina-Netzwerk) prüft.

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}`;
}


Ich habe Eingaben für Alter und Schwellenwert als 25 und 18 verwendet.

Da der Test durch Ausführen von npm run test erfolgreich durchgeführt wurde. Ich fuhr mit der Bereitstellung auf Devnet fort, indem ich zk config

verwendete

Wo ich folgende Eingaben gemacht habe:

Alias ​​bereitstellen: test
Netzwerkart: testnet
URL: https://api.minascan.io/node/devnet/v1/graphql
Gebührenzahler: Neue Gebührenzahler-Schlüssel
Transaktion: 0,1

Die URL kann hier abgerufen werden:

Exploring the Mina Protocol: Practical Use Cases for zk Applications

Bei der Bereitstellung erhielt ich dann die folgende Antwort.

Exploring the Mina Protocol: Practical Use Cases for zk Applications

Exploring the Mina Protocol: Practical Use Cases for zk Applications

Der Vertrag wird im folgenden Devnet bereitgestellt

Nach der Bereitstellung fuhr ich mit der Benutzeroberfläche fort, in der ich einfaches HTML, CSS und JS auswählte, indem ich meine RPC-URL und die bereitgestellte Vertragsadresse angab. Dies ist die endgültige Benutzeroberfläche.

Exploring the Mina Protocol: Practical Use Cases for zk Applications

Damit ist die Erstellung von zkapp nach der Integration des Smart Contracts in die Benutzeroberfläche abgeschlossen. Nach der Erstellung der Benutzeroberfläche (UI) für die AgeVerification zkApp ermöglicht die Integration des Frontends mit dem Smart Contract den Benutzern eine nahtlose Interaktion mit dem Zero-Knowledge-Proof-System. Die Benutzeroberfläche erleichtert die Übermittlung von Benutzeralter- und Schwellenwertdaten an den Vertrag und gewährleistet gleichzeitig die Wahrung der Privatsphäre durch zk-SNARKs. Dadurch können Benutzer ihr Alter überprüfen, ohne den tatsächlichen Wert preiszugeben, wodurch die Vertraulichkeit gewahrt bleibt. Das Backend generiert mithilfe der Prüferfunktion den Beweis und die Mina-Blockchain überprüft ihn effizient. Diese End-to-End-Lösung gewährleistet ein sicheres, benutzerfreundliches Erlebnis und nutzt gleichzeitig die Datenschutz- und Skalierbarkeitsfunktionen der zk-SNARK-basierten Architektur von Mina voll aus.

Das obige ist der detaillierte Inhalt vonErkundung des Mina-Protokolls: Praktische Anwendungsfälle für zk-Anwendungen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn