首頁 >web前端 >js教程 >探索 Mina 協定:zk 應用程式的實際用例

探索 Mina 協定:zk 應用程式的實際用例

DDD
DDD原創
2024-12-29 07:32:10686瀏覽

Zkapps(零知識應用)是由零知識證明支持的 mina 協議智能合約,特別是 zk-Snarks [零知識簡潔非互動式知識論證]。 zkapps 取代了 snapps [智慧非互動式知識論證]應用]。 ZkApp 智能合約是使用 o1js(一個 TypeScript 函式庫)編寫的。 zkApps 在使用者的 Web 瀏覽器中執行客戶端,並僅發布一個小的有效性證明,然後由 Mina 節點進行驗證。 Zkapp 由智能合約和 UI 組成,我將在下一節中進一步描述。

應用

我創建了關於年齡驗證的 zkapp,其中使用者年齡在不干預個人資料的情況下得到驗證。

我繼續安裝 zkapp-cli npm 包,它實際上創建了用於繼續使用證明器函數和驗證器函數的模板,作為 zk 證明構建過程的一部分

執行

以下是新增驗證自訂邏輯的實作。它定義了 zk-SNARK 的電路邏輯,在證明產生過程中使用。實際的證明者函數由 o1js 函式庫管理,並在使用私有輸入在鏈外執行 zkApp 方法時呼叫。

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


以下腳本是與 AgeVerification zkApp 互動的測試套件。它在 txn.prove() 期間呼叫證明者邏輯,並透過檢查其更新狀態來驗證 zkApp 的行為。

實際的證明者功能位於底層的 zkApp 方法(verifyAge)中,txn.prove() 是在測試過程中產生證明的機制。

為了測試輸入,我編輯了測試腳本,如下所示。

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


以下是測試結果

Exploring the Mina Protocol: Practical Use Cases for zk Applications

我在interact.ts檔案中加入了證明者機制,它基本上產生一個zk-SNARK證明,並在mina區塊鏈中進行交易時提交證明。當 interact.ts 腳本產生證明時,驗證是在處理交易時由 Mina 區塊鏈執行的。這是 zk-SNARK 系統的關鍵方面,證明者產生驗證者(Mina 網路)檢查的證明。

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


我使用的年齡和閾值輸入為 25 和 18。

由於測試已透過執行 npm run test 成功完成。我繼續使用 zk config 在 devnet 上部署

我提供了以下輸入:

部署別名:test
網路類型:測試網
網址:https://api.minascan.io/node/devnet/v1/graphql
付費者:新的付費者金鑰
交易:0.1

可以從這裡檢索 URL:

Exploring the Mina Protocol: Practical Use Cases for zk Applications

然後在部署後我得到了以下回應。

Exploring the Mina Protocol: Practical Use Cases for zk Applications

Exploring the Mina Protocol: Practical Use Cases for zk Applications

合約部署在以下devnet

部署後,我繼續使用 UI,透過提供 RPC URL 和部署的合約位址,選擇簡單的 html、css 和 js,這是最終的 UI。

Exploring the Mina Protocol: Practical Use Cases for zk Applications

將智能合約與UI整合後zkapp的創建就完成了。在為 AgeVerification zkApp 建立使用者介面 (UI) 後,前端與智慧合約的整合允許使用者與零知識證明系統無縫互動。 UI 有助於向合約提交用戶年齡和閾值數據,同時透過 zk-SNARK 維護隱私。這使得用戶能夠在不透露實際值的情況下驗證自己的年齡,從而保持機密性。後端利用證明者功能產生證明,Mina 區塊鏈對其進行有效驗證。這種端對端解決方案可確保安全性、使用者友好的體驗,同時充分利用 Mina 基於 zk-SNARK 的架構提供的隱私和可擴展性功能。

以上是探索 Mina 協定:zk 應用程式的實際用例的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn