Ruka hadi kwenye maudhui makuu

Andika Plasma mahususi kwa programu inayohifadhi faragha

sifuri-maarifa
seva
nje ya mnyororo
faragha
Ya juu
Ori Pomerantz
15 Oktoba 2025
30 dakika za kusoma

Utangulizi

Tofauti na mikusanyiko, Plasma hutumia Mtandao Mkuu wa Ethereum kwa uadilifu, lakini si kwa upatikanaji. Katika makala haya, tunaandika programu inayofanya kazi kama Plasma, huku Ethereum ikihakikisha uadilifu (hakuna mabadiliko yasiyoidhinishwa) lakini si upatikanaji (kijenzi kilichowekwa kati kinaweza kushindwa kufanya kazi na kulemaza mfumo mzima).

Programu tunayoandika hapa ni benki inayohifadhi faragha. Anwani tofauti zina akaunti zenye masalio, na zinaweza kutuma pesa (ETH) kwenye akaunti nyingine. Benki huchapisha heshi za hali (akaunti na masalio yake) na miamala, lakini huweka masalio halisi nje ya mnyororo ambapo yanaweza kubaki ya faragha.

Muundo

Huu sio mfumo ulio tayari kwa uzalishaji, bali ni zana ya kufundishia. Kwa hivyo, umeandikwa kwa mawazo kadhaa ya kurahisisha.

  • Kundi la akaunti lisilobadilika. Kuna idadi maalum ya akaunti, na kila akaunti ni ya anwani iliyoamuliwa mapema. Hii inafanya mfumo kuwa rahisi zaidi kwa sababu ni vigumu kushughulikia miundo ya data yenye ukubwa unaobadilika katika uthibitisho wa maarifa-sifuri. Kwa mfumo ulio tayari kwa uzalishaji, tunaweza kutumia mzizi wa Merkle kama heshi ya hali na kutoa uthibitisho wa Merkle kwa salio linalohitajika.

  • Hifadhi ya kumbukumbu. Kwenye mfumo wa uzalishaji, tunahitaji kuandika salio zote za akaunti kwenye diski ili kuzihifadhi endapo mfumo utawashwa upya. Hapa, ni sawa ikiwa taarifa itapotea tu.

  • Uhamisho pekee. Mfumo wa uzalishaji ungehitaji njia ya kuweka rasilimali kwenye benki na kuzitoa. Lakini dhumuni hapa ni kuelezea tu dhana, kwa hivyo benki hii ina kikomo cha uhamisho pekee.

Uthibitisho wa maarifa-sifuri

Katika kiwango cha msingi, uthibitisho wa maarifa-sifuri unaonyesha kuwa mthibitishaji anajua baadhi ya data, Dataprivate kiasi kwamba kuna uhusiano Relationship kati ya baadhi ya data za umma, Datapublic, na Dataprivate. Mhakiki anajua Relationship na Datapublic.

Ili kuhifadhi faragha, tunahitaji hali na miamala kuwa ya siri. Lakini ili kuhakikisha uadilifu, tunahitaji heshi ya kificho (opens in a new tab) ya hali kuwa ya umma. Ili kuthibitisha kwa watu wanaowasilisha miamala kwamba miamala hiyo ilifanyika kweli, tunahitaji pia kuchapisha heshi za muamala.

Katika hali nyingi, Dataprivate ni ingizo kwenye programu ya uthibitisho wa maarifa-sifuri, na Datapublic ni zao.

Sehemu hizi katika Dataprivate:

  • Staten, hali ya zamani
  • Staten+1, hali mpya
  • Transaction, muamala unaobadilika kutoka hali ya zamani kwenda mpya. Muamala huu unahitaji kujumuisha sehemu hizi:
    • Destination address (Anwani lengwa) inayopokea uhamisho
    • Amount (Kiasi) kinachohamishwa
    • Nonce (Nonsi) ili kuhakikisha kila muamala unaweza kuchakatwa mara moja tu. Anwani ya chanzo haihitaji kuwa kwenye muamala, kwa sababu inaweza kurejeshwa kutoka kwenye sahihi.
  • Signature, sahihi iliyoidhinishwa kufanya muamala. Kwa upande wetu, anwani pekee iliyoidhinishwa kufanya muamala ni anwani ya chanzo. Kwa sababu mfumo wetu wa sifuri-maarifa unafanya kazi jinsi unavyofanya, tunahitaji pia ufunguo wa umma wa akaunti, pamoja na sahihi ya Ethereum.

Hizi ni sehemu katika Datapublic:

  • Hash(Staten) heshi ya hali ya zamani
  • Hash(Staten+1) heshi ya hali mpya
  • Hash(Transaction) heshi ya muamala unaobadilisha hali kutoka Staten kwenda Staten+1.

Uhusiano unakagua masharti kadhaa:

  • Heshi za umma kwa kweli ni heshi sahihi kwa sehemu za siri.
  • Muamala, unapotumika kwenye hali ya zamani, husababisha hali mpya.
  • Sahihi inatoka kwenye anwani ya chanzo cha muamala.

Kwa sababu ya sifa za kazi za heshi za kificho, kuthibitisha masharti haya kunatosha kuhakikisha uadilifu.

Miundo ya data

Muundo mkuu wa data ni hali inayoshikiliwa na seva. Kwa kila akaunti, seva hufuatilia salio la akaunti na nonsi (opens in a new tab), inayotumika kuzuia mashambulizi ya kurudia (opens in a new tab).

Vipengele

Mfumo huu unahitaji vipengele viwili:

  • Seva inayopokea miamala, kuichakata, na kuchapisha heshi kwenye mnyororo pamoja na uthibitisho wa maarifa-sifuri.
  • Mkataba mahiri unaohifadhi heshi na kuhakiki uthibitisho wa maarifa-sifuri ili kuhakikisha mabadiliko ya hali ni halali.

Mtiririko wa data na udhibiti

Hizi ni njia ambazo vipengele mbalimbali huwasiliana ili kuhamisha kutoka akaunti moja kwenda nyingine.

  1. Kivinjari cha wavuti kinawasilisha muamala uliosainiwa ukiomba uhamisho kutoka kwenye akaunti ya msaini kwenda kwenye akaunti tofauti.

  2. Seva inahakiki kuwa muamala ni halali:

    • Msaini ana akaunti katika benki yenye salio la kutosha.
    • Mpokeaji ana akaunti katika benki.
  3. Seva inakokotoa hali mpya kwa kutoa kiasi kilichohamishwa kutoka kwenye salio la msaini na kukiongeza kwenye salio la mpokeaji.

  4. Seva inakokotoa uthibitisho wa maarifa-sifuri kwamba mabadiliko ya hali ni halali.

  5. Seva inawasilisha kwenye Ethereum muamala unaojumuisha:

    • Heshi ya hali mpya
    • Heshi ya muamala (ili mtumaji wa muamala aweze kujua kuwa umechakatwa)
    • Uthibitisho wa maarifa-sifuri unaothibitisha mabadiliko kwenda kwenye hali mpya ni halali
  6. Mkataba mahiri unahakiki uthibitisho wa maarifa-sifuri.

  7. Ikiwa uthibitisho wa maarifa-sifuri utathibitishwa, mkataba mahiri unafanya vitendo hivi:

    • Kusasisha heshi ya hali ya sasa kwenda kwenye heshi ya hali mpya
    • Kutoa ingizo la logi lenye heshi ya hali mpya na heshi ya muamala

Zana

Kwa msimbo wa upande wa mteja, tutatumia Vite (opens in a new tab), React (opens in a new tab), Viem (opens in a new tab), na Wagmi (opens in a new tab). Hizi ni zana za kiwango cha tasnia; ikiwa hauzifahamu, unaweza kutumia mafunzo haya.

Sehemu kubwa ya seva imeandikwa kwa JavaScript kwa kutumia Node (opens in a new tab). Sehemu ya sifuri-maarifa imeandikwa kwa Noir (opens in a new tab). Tunahitaji toleo la 1.0.0-beta.10, kwa hivyo baada ya kusakinisha Noir kama ilivyoelekezwa (opens in a new tab), endesha:

noirup -v 1.0.0-beta.10

Mnyororo wa vitalu tunaotumia ni anvil, mnyororo wa vitalu wa majaribio wa ndani ambao ni sehemu ya Foundry (opens in a new tab).

Utekelezaji

Kwa sababu huu ni mfumo tata, tutautekeleza kwa hatua.

Hatua ya 1 - Sifuri-maarifa ya mwongozo

Kwa hatua ya kwanza, tutasaini muamala kwenye kivinjari na kisha kutoa taarifa kwa uthibitisho wa maarifa-sifuri kwa njia ya mwongozo. Msimbo wa sifuri-maarifa unatarajia kupata taarifa hiyo katika server/noir/Prover.toml (imeandikwa hapa (opens in a new tab)).

Ili kuiona ikifanya kazi:

  1. Hakikisha umesakinisha Node (opens in a new tab) na Noir (opens in a new tab). Ikiwezekana, isakinishe kwenye mfumo wa UNIX kama vile macOS, Linux, au WSL (opens in a new tab).

  2. Pakua msimbo wa hatua ya 1 na uanzishe seva ya wavuti ili kuhudumia msimbo wa mteja.

    git clone https://github.com/qbzzt/250911-zk-bank.git -b 01-manual-zk
    cd 250911-zk-bank
    cd client
    npm install
    npm run dev
    

    Sababu ya kuhitaji seva ya wavuti hapa ni kwamba, ili kuzuia aina fulani za ulaghai, mikoba mingi (kama vile MetaMask) haikubali faili zinazohudumiwa moja kwa moja kutoka kwenye diski

  3. Fungua kivinjari chenye mkoba.

  4. Kwenye mkoba, weka nenosiri jipya. Kumbuka kwamba hii itafuta nenosiri lako lililopo, kwa hivyo hakikisha una nakala rudufu.

    Nenosiri ni test test test test test test test test test test test junk, nenosiri la msingi la majaribio la anvil.

  5. Vinjari hadi kwenye msimbo wa upande wa mteja (opens in a new tab).

  6. Unganisha kwenye mkoba na uchague akaunti yako ya mwisho na kiasi.

  7. Bofya Saini na usaini muamala.

  8. Chini ya kichwa cha Prover.toml, utapata maandishi. Badilisha server/noir/Prover.toml na maandishi hayo.

  9. Tekeleza uthibitisho wa maarifa-sifuri.

    cd ../server/noir
    nargo execute
    

    Toleo linapaswa kufanana na

ori@CryptoDocGuy:~/noir/250911-zk-bank/server/noir$ nargo execute

[zkBank] Circuit witness successfully solved [zkBank] Witness saved to target/zkBank.gz [zkBank] Circuit output: (0x199aa62af8c1d562a6ec96e66347bf3240ab2afb5d022c895e6bf6a5e617167b, 0x0cfc0a67cb7308e4e9b254026b54204e34f6c8b041be207e64c5db77d95dd82d, 0x450cf9da6e180d6159290554ae3d8787, 0x6d8bc5a15b9037e52fb59b6b98722a85)

Ujumbe upo katika muundo wa maandishi, jambo ambalo hurahisisha mtumiaji kuelewa (ambayo ni muhimu wakati wa kusaini) na kwa msimbo wa Noir kuchanganua. Kiasi kimetajwa katika finney ili kuwezesha uhamisho wa sehemu kwa upande mmoja, na kusomeka kwa urahisi kwa upande mwingine. Nambari ya mwisho ni nonsi (opens in a new tab).

Tungo ina urefu wa herufi 100. Uthibitisho wa maarifa-sifuri haushughulikii vizuri data yenye ukubwa unaobadilika, kwa hivyo mara nyingi ni muhimu kujaza data.

pubKeyX=["0x83",...,"0x75"]
pubKeyY=["0x35",...,"0xa5"]
signature=["0xb1",...,"0x0d"]

Vigezo hivi vitatu ni safu za baiti zenye ukubwa uliowekwa.

Hii ndiyo njia ya kubainisha safu ya miundo. Kwa kila ingizo, tunabainisha anwani, salio (katika milliETH a.k.a. finney (opens in a new tab)), na thamani inayofuata ya nonsi.

client/src/Transfer.tsx

Faili hili (opens in a new tab) linatekeleza uchakataji wa upande wa mteja na kuzalisha faili la server/noir/Prover.toml (lile linalojumuisha vigezo vya sifuri-maarifa).

Hapa kuna maelezo ya sehemu zinazovutia zaidi.

export default attrs =>  {

Kazi hii inaunda kipengele cha React cha Transfer, ambacho faili zingine zinaweza kuingiza.

  const accounts = [
    "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
    "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
    "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
    "0x90F79bf6EB2c4f870365E785982E1f101E93b906",
    "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65",
  ]

Hizi ni anwani za akaunti, anwani zilizoundwa na nenosiri la test ... test junk. Ikiwa unataka kutumia anwani zako mwenyewe, badilisha tu ufafanuzi huu.

  const account = useAccount()
  const wallet = createWalletClient({
    transport: custom(window.ethereum!)
  })

Ndoano hizi za Wagmi (opens in a new tab) zinaturuhusu kufikia maktaba ya Viem (opens in a new tab) na mkoba.

  const message = `send ${toAccount} ${ethAmount*1000} finney (milliEth) ${nonce}`.padEnd(100, " ")

Huu ni ujumbe, uliojazwa na nafasi. Kila wakati mojawapo ya vigezo vya useState (opens in a new tab) inapobadilika, kipengele huchorwa upya na message inasasishwa.

  const sign = async () => {

Kazi hii inaitwa wakati mtumiaji anapobofya kitufe cha Saini. Ujumbe unasasishwa kiotomatiki, lakini sahihi inahitaji idhini ya mtumiaji kwenye mkoba, na hatutaki kuiomba isipokuwa inahitajika.

    const signature = await wallet.signMessage({
        account: fromAccount,
        message,
    })

Uliza mkoba kusaini ujumbe (opens in a new tab).

    const hash = hashMessage(message)

Pata heshi ya ujumbe. Inasaidia kumpa mtumiaji kwa ajili ya utatuzi (wa msimbo wa Noir).

    const pubKey = await recoverPublicKey({
        hash,
        signature
    })

Pata ufunguo wa umma (opens in a new tab). Hii inahitajika kwa kazi ya Noir ecrecover (opens in a new tab).

    setSignature(signature)
    setHash(hash)
    setPubKey(pubKey)

Weka vigezo vya hali. Kufanya hivi huchora upya kipengele (baada ya kazi ya sign kutoka) na kumwonyesha mtumiaji thamani zilizosasishwa.

    let proverToml = `

Maandishi ya Prover.toml.

message="${message}"

pubKeyX=${hexToArray(pubKey.slice(4,4+2*32))}
pubKeyY=${hexToArray(pubKey.slice(4+2*32))}

Viem inatupa ufunguo wa umma kama tungo ya heksadesimali ya baiti 65. Baiti ya kwanza ni 0x04, alama ya toleo. Hii inafuatiwa na baiti 32 kwa ajili ya x ya ufunguo wa umma na kisha baiti 32 kwa ajili ya y ya ufunguo wa umma.

Hata hivyo, Noir inatarajia kupata taarifa hii kama safu mbili za baiti, moja kwa ajili ya x na moja kwa ajili ya y. Ni rahisi kuichanganua hapa kwa mteja badala ya kama sehemu ya uthibitisho wa maarifa-sifuri.

Kumbuka kwamba huu ni utaratibu mzuri katika sifuri-maarifa kwa ujumla. Msimbo ndani ya uthibitisho wa maarifa-sifuri ni ghali, kwa hivyo uchakataji wowote unaoweza kufanywa nje ya uthibitisho wa maarifa-sifuri unapaswa kufanywa nje ya uthibitisho wa maarifa-sifuri.

signature=${hexToArray(signature.slice(2,-2))}

Sahihi pia inatolewa kama tungo ya heksadesimali ya baiti 65. Hata hivyo, baiti ya mwisho inahitajika tu kurejesha ufunguo wa umma. Kwa kuwa ufunguo wa umma utakuwa tayari umetolewa kwa msimbo wa Noir, hatuuhitaji ili kuhakiki sahihi, na msimbo wa Noir hauuhitaji.

${accounts.map(accountInProverToml).reduce((a,b) => a+b, "")}
`

Toa akaunti.

    setProverToml(proverToml)
  }

  return (
    <>
        <h2>Transfer</h2>

Huu ni muundo wa HTML (kwa usahihi zaidi, JSX (opens in a new tab)) wa kipengele.

server/noir/src/main.nr

Faili hili (opens in a new tab) ni msimbo halisi wa sifuri-maarifa.

use std::hash::pedersen_hash;

Heshi ya Pedersen (opens in a new tab) inatolewa na maktaba ya kawaida ya Noir (opens in a new tab). Uthibitisho wa maarifa-sifuri kwa kawaida hutumia kazi hii ya heshi. Ni rahisi sana kukokotoa ndani ya saketi za kihesabu (opens in a new tab) ikilinganishwa na kazi za kawaida za heshi.

use keccak256::keccak256;
use dep::ecrecover;

Kazi hizi mbili ni maktaba za nje, zilizofafanuliwa katika Nargo.toml (opens in a new tab). Ni hasa kile zilichopewa jina, kazi inayokokotoa heshi ya keccak256 (opens in a new tab) na kazi inayohakiki sahihi za Ethereum na kurejesha anwani ya Ethereum ya msaini.

global ACCOUNT_NUMBER : u32 = 5;

Noir imehamasishwa na Rust (opens in a new tab). Vigezo, kwa chaguo-msingi, ni vya kudumu. Hivi ndivyo tunavyofafanua vigezo vya kudumu vya usanidi wa kimataifa. Hasa, ACCOUNT_NUMBER ni idadi ya akaunti tunazohifadhi.

Aina za data zilizopewa jina la u<number> ni idadi hiyo ya biti, zisizo na saini. Aina pekee zinazotumika ni u8, u16, u32, u64, na u128.

global FLAT_ACCOUNT_FIELDS : u32 = 2;

Kigezo hiki kinatumika kwa heshi ya Pedersen ya akaunti, kama ilivyoelezwa hapa chini.

global MESSAGE_LENGTH : u32 = 100;

Kama ilivyoelezwa hapo juu, urefu wa ujumbe umewekwa. Umebainishwa hapa.

global ASCII_MESSAGE_LENGTH : [u8; 3] = [0x31, 0x30, 0x30];
global HASH_BUFFER_SIZE : u32 = 26+3+MESSAGE_LENGTH;

Sahihi za EIP-191 (opens in a new tab) zinahitaji bafa yenye kiambishi awali cha baiti 26, ikifuatiwa na urefu wa ujumbe katika ASCII, na hatimaye ujumbe wenyewe.

struct Account {
    balance: u128,
    address: Field,
    nonce: u32,
}

Taarifa tunayohifadhi kuhusu akaunti. Field (opens in a new tab) ni nambari, kwa kawaida hadi biti 253, inayoweza kutumika moja kwa moja katika saketi ya kihesabu (opens in a new tab) inayotekeleza uthibitisho wa maarifa-sifuri. Hapa tunatumia Field kuhifadhi anwani ya Ethereum ya biti 160.

struct TransferTxn {
    from: Field,
    to: Field,
    amount: u128,
    nonce: u32
}

Taarifa tunayohifadhi kwa ajili ya muamala wa hamisho.

fn flatten_account(account: Account) -> [Field; FLAT_ACCOUNT_FIELDS] {

Ufafanuzi wa kazi. Kigezo ni taarifa ya Account. Matokeo ni safu ya vigezo vya Field, ambavyo urefu wake ni FLAT_ACCOUNT_FIELDS

let flat = [
        account.address,
        ((account.balance << 32) + account.nonce.into()).into(),
    ];

Thamani ya kwanza katika safu ni anwani ya akaunti. Ya pili inajumuisha salio na nonsi. Miito ya .into() inabadilisha nambari kuwa aina ya data inayohitajika kuwa. account.nonce ni thamani ya u32, lakini ili kuiongeza kwenye account.balance << 32, thamani ya u128, inahitaji kuwa u128. Hiyo ndiyo .into() ya kwanza. Ya pili inabadilisha matokeo ya u128 kuwa Field ili iingie kwenye safu.

flat
}

Katika Noir, kazi zinaweza tu kurejesha thamani mwishoni (hakuna urejeshaji wa mapema). Ili kubainisha thamani ya kurejesha, unaitathmini kabla tu ya mabano ya kufunga ya kazi.

fn flatten_accounts(accounts: [Account; ACCOUNT_NUMBER]) -> [Field; FLAT_ACCOUNT_FIELDS*ACCOUNT_NUMBER] {

Kazi hii inabadilisha safu ya akaunti kuwa safu ya Field, ambayo inaweza kutumika kama ingizo kwa Heshi ya Petersen.

let mut flat: [Field; FLAT_ACCOUNT_FIELDS*ACCOUNT_NUMBER] = [0; FLAT_ACCOUNT_FIELDS*ACCOUNT_NUMBER];

Hivi ndivyo unavyobainisha kigezo kinachoweza kubadilika, yaani, sio cha kudumu. Vigezo katika Noir lazima kila wakati viwe na thamani, kwa hivyo tunaanzisha kigezo hiki kwa sifuri zote.

for i in 0..ACCOUNT_NUMBER {

Hili ni kitanzi cha for. Kumbuka kwamba mipaka ni ya kudumu. Vitanzi vya Noir lazima viwe na mipaka yake inayojulikana wakati wa kukusanya. Sababu ni kwamba saketi za kihesabu hazitumii udhibiti wa mtiririko. Wakati wa kuchakata kitanzi cha for, kikusanyaji huweka tu msimbo ndani yake mara nyingi, moja kwa kila mzunguko.

Hatimaye, tumefika kwenye kazi inayoheshisha safu ya akaunti.

fn find_account(accounts: [Account; ACCOUNT_NUMBER], address: Field) -> u32 {
    let mut account : u32 = ACCOUNT_NUMBER;

    for i in 0..ACCOUNT_NUMBER {
        if accounts[i].address == address {
            account = i;
        }
    }

Kazi hii inatafuta akaunti yenye anwani maalum. Kazi hii ingekuwa isiyofaa sana katika msimbo wa kawaida kwa sababu inarudia akaunti zote, hata baada ya kupata anwani.

Hata hivyo, katika uthibitisho wa maarifa-sifuri, hakuna udhibiti wa mtiririko. Ikiwa tutawahi kuhitaji kuangalia sharti, lazima tuliangalie kila wakati.

Jambo kama hilo hufanyika kwa kauli za if. Kauli ya if katika kitanzi hapo juu inatafsiriwa kuwa kauli hizi za kihesabu.

conditionresult = accounts[i].address == address // moja ikiwa zinalingana, sifuri vinginevyo

accountnew = conditionresult*i + (1-conditionresult)*accountold

    assert (account < ACCOUNT_NUMBER, f"{address} does not have an account");

    account
}

Kazi ya assert (opens in a new tab) inasababisha uthibitisho wa maarifa-sifuri kuacha kufanya kazi ikiwa dai ni la uongo. Katika kesi hii, ikiwa hatuwezi kupata akaunti yenye anwani husika. Ili kuripoti anwani, tunatumia tungo ya muundo (opens in a new tab).

fn apply_transfer_txn(accounts: [Account; ACCOUNT_NUMBER], txn: TransferTxn) -> [Account; ACCOUNT_NUMBER] {

Kazi hii inatumia muamala wa hamisho na kurejesha safu mpya ya akaunti.

    let from = find_account(accounts, txn.from);
    let to = find_account(accounts, txn.to);

    let (txnFrom, txnAmount, txnNonce, accountNonce) =
        (txn.from, txn.amount, txn.nonce, accounts[from].nonce);

Hatuwezi kufikia vipengele vya muundo ndani ya tungo ya muundo katika Noir, kwa hivyo tunaunda nakala inayoweza kutumika.

    assert (accounts[from].balance >= txn.amount,
        f"{txnFrom} does not have {txnAmount} finney");

    assert (accounts[from].nonce == txn.nonce,
        f"Transaction has nonce {txnNonce}, but the account is expected to use {accountNonce}");

Haya ni masharti mawili yanayoweza kufanya muamala kuwa batili.

    let mut newAccounts = accounts;

    newAccounts[from].balance -= txn.amount;
    newAccounts[from].nonce += 1;
    newAccounts[to].balance += txn.amount;

    newAccounts
}

Unda safu mpya ya akaunti na kisha uirejeshe.

fn readAddress(messageBytes: [u8; MESSAGE_LENGTH]) -> Field

Kazi hii inasoma anwani kutoka kwenye ujumbe.

{
    let mut result : Field = 0;

    for i in 7..47 {

Anwani daima ina urefu wa baiti 20 (a.k.a. tarakimu 40 za heksadesimali), na inaanza kwenye herufi #7.

Soma kiasi na nonsi kutoka kwenye ujumbe.

{
    let mut amount : u128 = 0;
    let mut nonce: u32 = 0;
    let mut stillReadingAmount: bool = true;
    let mut lookingForNonce: bool = false;
    let mut stillReadingNonce: bool = false;

Katika ujumbe, nambari ya kwanza baada ya anwani ni kiasi cha finney (a.k.a. elfu moja ya ETH) cha kuhamisha. Nambari ya pili ni nonsi. Maandishi yoyote kati yao yanapuuzwa.

Kurejesha tupo (opens in a new tab) ni njia ya Noir ya kurejesha thamani nyingi kutoka kwenye kazi.

Kazi hii inabadilisha ujumbe kuwa baiti, kisha inabadilisha kiasi kuwa TransferTxn.

// Sawa na hashMessage ya Viem
// https://viem.sh/docs/utilities/hashMessage#hashmessage
fn hashMessage(message: str<MESSAGE_LENGTH>) -> [u8;32] {

Tuliweza kutumia Heshi ya Pedersen kwa akaunti kwa sababu zinaheshishwa tu ndani ya uthibitisho wa maarifa-sifuri. Hata hivyo, katika msimbo huu tunahitaji kuangalia sahihi ya ujumbe, ambayo inazalishwa na kivinjari. Kwa hilo, tunahitaji kufuata muundo wa kusaini wa Ethereum katika EIP-191 (opens in a new tab). Hii inamaanisha tunahitaji kuunda bafa iliyounganishwa yenye kiambishi awali cha kawaida, urefu wa ujumbe katika ASCII, na ujumbe wenyewe, na kutumia keccak256 ya kawaida ya Ethereum kuiheshisha.

Ili kuepuka matukio ambapo programu inamwomba mtumiaji kusaini ujumbe unaoweza kutumika kama muamala au kwa madhumuni mengine, EIP-191 inabainisha kwamba jumbe zote zilizosainiwa zinaanza na herufi 0x19 (sio herufi halali ya ASCII) ikifuatiwa na Ethereum Signed Message: na mstari mpya.

Shughulikia urefu wa ujumbe hadi 999 na ushindwe ikiwa ni mkubwa zaidi. Niliongeza msimbo huu, ingawa urefu wa ujumbe ni wa kudumu, kwa sababu inafanya iwe rahisi kuubadilisha. Kwenye mfumo wa uzalishaji, labda ungechukulia tu kwamba MESSAGE_LENGTH haibadiliki kwa ajili ya utendaji bora.

    keccak256::keccak256(buffer, HASH_BUFFER_SIZE)
}

Tumia kazi ya kawaida ya Ethereum ya keccak256.

fn signatureToAddressAndHash(
        message: str<MESSAGE_LENGTH>, 
        pubKeyX: [u8; 32],
        pubKeyY: [u8; 32],
        signature: [u8; 64]
    ) -> (Field, Field, Field)   // anwani, baiti 16 za kwanza za heshi, baiti 16 za mwisho za heshi        
{

Kazi hii inahakiki sahihi, ambayo inahitaji heshi ya ujumbe. Kisha inatupa anwani iliyoisaini na heshi ya ujumbe. Heshi ya ujumbe inatolewa katika thamani mbili za Field kwa sababu hizo ni rahisi kutumia katika sehemu iliyosalia ya programu kuliko safu ya baiti.

Tunahitaji kutumia thamani mbili za Field kwa sababu hesabu za uga zinafanywa modulo (opens in a new tab) nambari kubwa, lakini nambari hiyo kwa kawaida ni chini ya biti 256 (vinginevyo ingekuwa vigumu kufanya hesabu hizo katika EVM).

    let hash = hashMessage(message);

    let mut (hash1, hash2) = (0,0);

    for i in 0..16 {
        hash1 = hash1*256 + hash[31-i].into();
        hash2 = hash2*256 + hash[15-i].into();
    }

Bainisha hash1 na hash2 kama vigezo vinavyoweza kubadilika, na uandike heshi ndani yake baiti kwa baiti.

    (
        ecrecover::ecrecover(pubKeyX, pubKeyY, signature, hash), 

Hii inafanana na ecrecover ya Solidity (opens in a new tab), na tofauti mbili muhimu:

  • Ikiwa sahihi si halali, mwito unashindwa assert na programu inasitishwa.
  • Ingawa ufunguo wa umma unaweza kurejeshwa kutoka kwenye sahihi na heshi, huu ni uchakataji unaoweza kufanywa nje na, kwa hivyo, haufai kufanywa ndani ya uthibitisho wa maarifa-sifuri. Ikiwa mtu atajaribu kutudanganya hapa, uhakiki wa sahihi utashindwa.

Hatimaye, tunafika kwenye kazi ya main. Tunahitaji kuthibitisha kwamba tuna muamala unaobadilisha kihalali heshi ya akaunti kutoka thamani ya zamani hadi mpya. Pia tunahitaji kuthibitisha kwamba ina heshi hii maalum ya muamala ili mtu aliyeituma ajue muamala wake umechakatwa.

{
    let mut txn = readTransferTxn(message);

Tunahitaji txn iweze kubadilika kwa sababu hatusomi anwani ya kutoka kwenye ujumbe, tunaisoma kutoka kwenye sahihi.

Hatua ya 2 - Kuongeza seva

Katika hatua ya pili, tunaongeza seva inayopokea na kutekeleza miamala ya hamisho kutoka kwenye kivinjari.

Ili kuiona ikifanya kazi:

  1. Simamisha Vite ikiwa inafanya kazi.

  2. Pakua tawi linalojumuisha seva na uhakikishe una moduli zote muhimu.

    git checkout 02-add-server
    cd client
    npm install
    cd ../server
    npm install
    

    Hakuna haja ya kukusanya msimbo wa Noir, ni sawa na msimbo uliotumia kwa hatua ya 1.

  3. Anzisha seva.

    npm run start
    
  4. Katika dirisha tofauti la mstari wa amri, endesha Vite ili kuhudumia msimbo wa kivinjari.

    cd client
    npm run dev
    
  5. Vinjari hadi kwenye msimbo wa mteja kwenye http://localhost:5173 (opens in a new tab)

  6. Kabla ya kutoa muamala, unahitaji kujua nonsi, pamoja na kiasi unachoweza kutuma. Ili kupata taarifa hii, bofya Sasisha data ya akaunti na usaini ujumbe.

    Tuna mtanziko hapa. Kwa upande mmoja, hatutaki kusaini ujumbe unaoweza kutumika tena (shambulio la kurudia (opens in a new tab)), ndiyo maana tunataka nonsi hapo kwanza. Hata hivyo, bado hatuna nonsi. Suluhisho ni kuchagua nonsi inayoweza kutumika mara moja tu na ambayo tayari tunayo pande zote mbili, kama vile wakati wa sasa.

    Tatizo la suluhisho hili ni kwamba wakati unaweza usiwe umesawazishwa kikamilifu. Kwa hivyo badala yake, tunasaini thamani inayobadilika kila dakika. Hii inamaanisha kwamba dirisha letu la uwezekano wa kushambuliwa kwa kurudia ni dakika moja zaidi. Kwa kuzingatia kwamba katika uzalishaji ombi lililosainiwa litalindwa na TLS, na kwamba upande mwingine wa handaki---seva---tayari inaweza kufichua salio na nonsi (lazima izijue ili kufanya kazi), hii ni hatari inayokubalika.

  7. Mara tu kivinjari kinapopata salio na nonsi, kinaonyesha fomu ya hamisho. Chagua anwani ya mwisho na kiasi na ubofye Hamisha. Saini ombi hili.

  8. Ili kuona hamisho, ama Sasisha data ya akaunti au angalia kwenye dirisha ambapo unaendesha seva. Seva huweka logi ya hali kila wakati inapobadilika.

ori@CryptoDocGuy:~/x/250911-zk-bank/server$ npm run start

server@1.0.0 start node --experimental-json-modules index.mjs

Listening on port 3000 Txn send 0x90F79bf6EB2c4f870365E785982E1f101E93b906 36000 finney (milliEth) 0 processed New state: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 has 64000 (1) 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 has 100000 (0) 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC has 100000 (0) 0x90F79bf6EB2c4f870365E785982E1f101E93b906 has 136000 (0) 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 has 100000 (0) Txn send 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 7200 finney (milliEth) 1 processed New state: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 has 56800 (2) 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 has 107200 (0) 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC has 100000 (0) 0x90F79bf6EB2c4f870365E785982E1f101E93b906 has 136000 (0) 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 has 100000 (0) Txn send 0x90F79bf6EB2c4f870365E785982E1f101E93b906 3000 finney (milliEth) 2 processed New state: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 has 53800 (3) 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 has 107200 (0) 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC has 100000 (0) 0x90F79bf6EB2c4f870365E785982E1f101E93b906 has 139000 (0) 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 has 100000 (0)


#### `server/index.mjs` \{#server-index-mjs-1\}

[Faili hili](https://github.com/qbzzt/250911-zk-bank/blob/02-add-server/server/index.mjs) lina mchakato wa seva, na linaingiliana na msimbo wa Noir kwenye [`main.nr`](https://github.com/qbzzt/250911-zk-bank/blob/02-add-server/server/noir/src/main.nr). Hapa kuna maelezo ya sehemu zinazovutia.

```js
import { Noir } from '@noir-lang/noir_js'

Maktaba ya noir.js (opens in a new tab) inaunganisha kati ya msimbo wa JavaScript na msimbo wa Noir.

const circuit = JSON.parse(await fs.readFile("./noir/target/zkBank.json"))
const noir = new Noir(circuit)

Pakia saketi ya kihesabu---programu ya Noir iliyokusanywa tuliyounda katika hatua iliyopita---na uwe tayari kuitekeleza.

// Tunatoa tu taarifa za akaunti kama majibu kwa ombi lililotiwa sahihi
const accountInformation = async signature => {
    const fromAddress = await recoverAddress({
        hash: hashMessage("Get account data " + Math.floor((new Date().getTime())/60000)),
        signature
    })

Ili kutoa taarifa ya akaunti, tunahitaji tu sahihi. Sababu ni kwamba tayari tunajua ujumbe utakuwa nini, na kwa hivyo heshi ya ujumbe.

const processMessage = async (message, signature) => {

Chakata ujumbe na utekeleze muamala unaousimba.

    // Pata ufunguo wa umma
    const pubKey = await recoverPublicKey({
        hash,
        signature
    })

Sasa kwa kuwa tunaendesha JavaScript kwenye seva, tunaweza kurejesha ufunguo wa umma huko badala ya kwa mteja.

noir.execute inaendesha programu ya Noir. Vigezo ni sawa na vile vilivyotolewa katika Prover.toml (opens in a new tab). Kumbuka kwamba thamani ndefu zinatolewa kama safu ya tungo za heksadesimali (["0x60", "0xA7"]), sio kama thamani moja ya heksadesimali (0x60A7), jinsi Viem inavyofanya.

    } catch (err) {
        console.log(`Noir error: ${err}`)
        throw Error("Invalid transaction, not processed")
    }

Ikiwa kuna hitilafu, idake na kisha upeleke toleo lililorahisishwa kwa mteja.

    Accounts[fromAccountNumber].nonce++
    Accounts[fromAccountNumber].balance -= amount
    Accounts[toAccountNumber].balance += amount

Tumia muamala. Tayari tulifanya hivyo katika msimbo wa Noir, lakini ni rahisi kufanya tena hapa badala ya kutoa matokeo kutoka huko.

let Accounts = [
    {
        address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
        balance: 5000,
        nonce: 0,
    },

Muundo wa awali wa Accounts.

Hatua ya 3 - Mikataba mahiri ya Ethereum

  1. Simamisha michakato ya seva na mteja.

  2. Pakua tawi lenye mikataba mahiri na uhakikishe una moduli zote muhimu.

    git checkout 03-smart-contracts
    cd client
    npm install
    cd ../server
    npm install
    
  3. Endesha anvil katika dirisha tofauti la mstari wa amri.

  4. Zalisha ufunguo wa uhakiki na mhakiki wa Solidity, kisha nakili msimbo wa mhakiki kwenye mradi wa Solidity.

    cd noir
    bb write_vk -b ./target/zkBank.json -o ./target --oracle_hash keccak
    bb write_solidity_verifier -k ./target/vk -o ./target/Verifier.sol
    cp target/Verifier.sol ../../smart-contracts/src
    
  5. Nenda kwenye mikataba mahiri na uweke vigezo vya mazingira ili kutumia mnyororo wa vitalu wa anvil.

    cd ../../smart-contracts
    export ETH_RPC_URL=http://localhost:8545
    ETH_PRIVATE_KEY=ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
    
  6. Sambaza Verifier.sol na uhifadhi anwani katika kigezo cha mazingira.

    VERIFIER_ADDRESS=`forge create src/Verifier.sol:HonkVerifier --private-key $ETH_PRIVATE_KEY --optimize --broadcast | awk '/Deployed to:/ {print $3}'`
    echo $VERIFIER_ADDRESS
    
  7. Sambaza mkataba wa ZkBank.

    ZKBANK_ADDRESS=`forge create ZkBank --private-key $ETH_PRIVATE_KEY --broadcast --constructor-args $VERIFIER_ADDRESS 0x199aa62af8c1d562a6ec96e66347bf3240ab2afb5d022c895e6bf6a5e617167b | awk '/Deployed to:/ {print $3}'`
    echo $ZKBANK_ADDRESS
    

    Thamani ya 0x199..67b ni heshi ya Pederson ya hali ya awali ya Accounts. Ikiwa utabadilisha hali hii ya awali katika server/index.mjs, unaweza kuendesha muamala ili kuona heshi ya awali iliyoripotiwa na uthibitisho wa maarifa-sifuri.

  8. Endesha seva.

    cd ../server
    npm run start
    
  9. Endesha mteja katika dirisha tofauti la mstari wa amri.

    cd client
    npm run dev
    
  10. Endesha baadhi ya miamala.

  11. Ili kuhakiki kwamba hali imebadilika mnyororoni, anzisha upya mchakato wa seva. Angalia kwamba ZkBank haikubali tena miamala, kwa sababu thamani ya asili ya heshi katika miamala inatofautiana na thamani ya heshi iliyohifadhiwa mnyororoni.

    Hii ndiyo aina ya hitilafu inayotarajiwa.

ori@CryptoDocGuy:~/x/250911-zk-bank/server$ npm run start

server@1.0.0 start node --experimental-json-modules index.mjs

Listening on port 3000 Verification error: ContractFunctionExecutionError: The contract function "processTransaction" reverted with the following reason: Wrong old state hash

Contract Call: address: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 function: processTransaction(bytes _proof, bytes32[] _publicInputs) args: (0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf00000000000000000000000000000000000000000000000b75c020998797da7800000000000000000000000000000000000000000000000

Tunahitaji kutumia kifurushi cha Barretenberg (opens in a new tab) ili kuunda uthibitisho halisi wa kutuma mnyororoni. Tunaweza kutumia kifurushi hiki ama kwa kuendesha kiolesura cha mstari wa amri (bb) au kwa kutumia maktaba ya JavaScript, bb.js (opens in a new tab). Maktaba ya JavaScript ni polepole sana kuliko kuendesha msimbo kiasili, kwa hivyo tunatumia exec (opens in a new tab) hapa ili kutumia mstari wa amri.

Kumbuka kwamba ukiamua kutumia bb.js, unahitaji kutumia toleo linaloendana na toleo la Noir unalotumia. Wakati wa kuandika, toleo la sasa la Noir (1.0.0-beta.11) linatumia bb.js toleo la 0.87.

const zkBankAddress = process.env.ZKBANK_ADDRESS || "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512"

Anwani hapa ni ile unayopata unapoanza na anvil safi na kufuata maelekezo hapo juu.

const walletClient = createWalletClient({ 
    chain: anvil, 
    transport: http(), 
    account: privateKeyToAccount("0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6")
})

Ufunguo huu wa siri ni mojawapo ya akaunti za msingi zilizofadhiliwa mapema katika anvil.

const generateProof = async (witness, fileID) => {

Zalisha uthibitisho ukitumia faili tekelezi la bb.

    const fname = `witness-${fileID}.gz`    
    await fs.writeFile(fname, witness)

Andika Shahidi kwenye faili.

    await execPromise(`bb prove -b ./noir/target/zkBank.json -w ${fname} -o ${fileID} --oracle_hash keccak --output_format fields`)

Unda uthibitisho halisi. Hatua hii pia inaunda faili lenye vigezo vya umma, lakini hatuhitaji hilo. Tayari tulipata vigezo hivyo kutoka kwa noir.execute.

    const proof = "0x" + JSON.parse(await fs.readFile(`./${fileID}/proof_fields.json`)).reduce((a,b) => a+b, "").replace(/0x/g, "")

Uthibitisho ni safu ya JSON ya thamani za Field, kila moja ikiwakilishwa kama thamani ya heksadesimali. Hata hivyo, tunahitaji kuituma katika muamala kama thamani moja ya bytes, ambayo Viem inaiwakilisha kwa tungo kubwa ya heksadesimali. Hapa tunabadilisha muundo kwa kuunganisha thamani zote, kuondoa 0x zote, na kisha kuongeza moja mwishoni.

    await execPromise(`rm -r ${fname} ${fileID}`)

    return proof
}

Safisha na urejeshe uthibitisho.

const processMessage = async (message, signature) => {
    .
    .
    .

    const publicFields = noirResult.returnValue.map(x=>'0x' + x.slice(2).padStart(64, "0"))

Nyanja za umma zinahitaji kuwa safu ya thamani za baiti 32. Hata hivyo, kwa kuwa tulihitaji kugawanya heshi ya muamala kati ya thamani mbili za Field, inaonekana kama thamani ya baiti 16. Hapa tunaongeza sifuri ili Viem ielewe kuwa ni baiti 32 haswa.

    const proof = await generateProof(noirResult.witness, `${fromAddress}-${nonce}`)

Kila anwani inatumia kila nonsi mara moja tu ili tuweze kutumia mchanganyiko wa fromAddress na nonce kama kitambulisho cha kipekee kwa faili la Shahidi na saraka ya toleo.

Tuma muamala kwenye mnyororo.

smart-contracts/src/ZkBank.sol

Huu ni msimbo wa mnyororoni unaopokea muamala.

Msimbo wa mnyororoni unahitaji kufuatilia vigezo viwili: mhakiki (mkataba tofauti unaoundwa na nargo) na heshi ya hali ya sasa.

    event TransactionProcessed(
        bytes32 indexed transactionHash,
        bytes32 oldStateHash,
        bytes32 newStateHash
    );

Kila wakati hali inapobadilika, tunatoa tukio la TransactionProcessed.

    function processTransaction(
        bytes calldata _proof,
        bytes32[] calldata _publicFields
    ) public {

Kazi hii inachakata miamala. Inapata uthibitisho (kama bytes) na ingizo la umma (kama safu ya bytes32), katika muundo ambao mhakiki anahitaji (ili kupunguza uchakataji wa mnyororoni na kwa hivyo gharama za gesi).

        require(_publicInputs[0] == currentStateHash,
            "Wrong old state hash");

Uthibitisho wa maarifa-sifuri unahitaji kuwa kwamba muamala unabadilika kutoka kwenye heshi yetu ya sasa hadi mpya.

        myVerifier.verify(_proof, _publicFields);

Ita mkataba wa mhakiki ili kuhakiki uthibitisho wa maarifa-sifuri. Hatua hii inarejesha nyuma muamala ikiwa uthibitisho wa maarifa-sifuri si sahihi.

Ikiwa kila kitu kiko sawa, sasisha heshi ya hali kuwa thamani mpya na utoe tukio la TransactionProcessed.

Matumizi mabaya na sehemu iliyowekwa kati

Usalama wa taarifa unajumuisha sifa tatu:

  • Usiri, watumiaji hawawezi kusoma taarifa ambazo hawajaidhinishwa kuzisoma.
  • Uadilifu, taarifa haziwezi kubadilishwa isipokuwa na watumiaji walioidhinishwa kwa njia iliyoidhinishwa.
  • Upatikanaji, watumiaji walioidhinishwa wanaweza kutumia mfumo.

Kwenye mfumo huu, uadilifu hutolewa kupitia uthibitisho wa maarifa-sifuri. Upatikanaji ni mgumu zaidi kuhakikisha, na usiri hauwezekani, kwa sababu benki inapaswa kujua salio la kila akaunti na miamala yote. Hakuna njia ya kuzuia chombo kilicho na taarifa kushiriki taarifa hizo.

Inaweza kuwezekana kuunda benki yenye usiri wa kweli kwa kutumia anwani za siri (opens in a new tab), lakini hilo liko nje ya upeo wa makala haya.

Taarifa za uongo

Njia moja ambayo seva inaweza kukiuka uadilifu ni kutoa taarifa za uongo wakati data inapoombwa (opens in a new tab).

Ili kutatua hili, tunaweza kuandika programu ya pili ya Noir inayopokea akaunti kama ingizo la siri na anwani ambayo taarifa zake zinaombwa kama ingizo la umma. Toleo ni salio na nonsi ya anwani hiyo, na heshi ya akaunti hizo.

Bila shaka, uthibitisho huu hauwezi kuhakikiwa mnyororoni, kwa sababu hatutaki kuchapisha nonsi na masalio mnyororoni. Hata hivyo, inaweza kuhakikiwa na msimbo wa mteja unaoendeshwa kwenye kivinjari.

Miamala ya lazima

Utaratibu wa kawaida wa kuhakikisha upatikanaji na kuzuia udhibiti kwenye L2 ni miamala ya lazima (opens in a new tab). Lakini miamala ya lazima haiendani na uthibitisho wa maarifa-sifuri. Seva ndicho chombo pekee kinachoweza kuhakiki miamala.

Tunaweza kurekebisha smart-contracts/src/ZkBank.sol ili kukubali miamala ya lazima na kuzuia seva kubadilisha hali hadi itakapochakatwa. Hata hivyo, hii inatuweka wazi kwa shambulio rahisi la kunyimwa huduma (denial-of-service). Vipi ikiwa muamala wa lazima ni batili na hivyo hauwezekani kuchakatwa?

Suluhisho ni kuwa na uthibitisho wa maarifa-sifuri kwamba muamala wa lazima ni batili. Hii inapa seva chaguzi tatu:

  • Kuchakata muamala wa lazima, kutoa uthibitisho wa maarifa-sifuri kwamba umechakatwa na heshi mpya ya hali.
  • Kukataa muamala wa lazima, na kutoa uthibitisho wa maarifa-sifuri kwa mkataba kwamba muamala ni batili (anwani isiyojulikana, nonsi mbaya, au salio lisilotosha).
  • Kupuuza muamala wa lazima. Hakuna njia ya kulazimisha seva kuchakata muamala kikweli, lakini inamaanisha mfumo mzima haupatikani.

Dhamana za upatikanaji

Katika utekelezaji wa maisha halisi, labda kungekuwa na aina fulani ya nia ya faida ya kuweka seva ikiendelea kufanya kazi. Tunaweza kuimarisha kichocheo hiki kwa kuifanya seva iweke dhamana ya upatikanaji ambayo mtu yeyote anaweza kuiteketeza ikiwa muamala wa lazima hautachakatwa ndani ya kipindi fulani.

Msimbo mbaya wa Noir

Kawaida, ili kuwafanya watu waamini mkataba mahiri tunapakia msimbo wa chanzo kwenye kichunguzi cha bloku (opens in a new tab). Hata hivyo, katika kesi ya uthibitisho wa maarifa-sifuri, hiyo haitoshi.

Verifier.sol ina ufunguo wa uhakiki, ambao ni kazi ya programu ya Noir. Hata hivyo, ufunguo huo hautuambii programu ya Noir ilikuwa nini. Ili kuwa na suluhisho linaloaminika kikweli, unahitaji kupakia programu ya Noir (na toleo lililoiunda). Vinginevyo, uthibitisho wa maarifa-sifuri unaweza kuonyesha programu tofauti, yenye mlango wa nyuma (back door).

Hadi vichunguzi vya bloku vitakapoanza kuturuhusu kupakia na kuhakiki programu za Noir, unapaswa kufanya hivyo mwenyewe (ikiwezekana kwenye IPFS). Kisha watumiaji wenye uzoefu wataweza kupakua msimbo wa chanzo, kuukusanya wenyewe, kuunda Verifier.sol, na kuhakiki kwamba unafanana kabisa na ule ulio mnyororoni.

Hitimisho

Programu za aina ya Plasma zinahitaji kijenzi kilichowekwa kati kama hifadhi ya taarifa. Hili linafungua uwezekano wa udhaifu lakini, kwa upande mwingine, linaturuhusu kuhifadhi faragha kwa njia ambazo hazipatikani kwenye mnyororo wa vitalu wenyewe. Kwa kutumia uthibitisho wa maarifa-sifuri tunaweza kuhakikisha uadilifu na ikiwezekana kuifanya iwe na faida kiuchumi kwa yeyote anayeendesha kijenzi kilichowekwa kati kudumisha upatikanaji.

Tazama hapa kwa kazi zangu zaidi (opens in a new tab).

Shukrani

  • Josh Crites alisoma rasimu ya makala haya na kunisaidia na suala gumu la Noir.

Makosa yoyote yaliyosalia ni jukumu langu.