Rand Protocol
Dokumentasi
Program contoh

Keputusan kredit persendirian

Program sulit yang menjalankan model penskoran yang diterbitkan ke atas data pemohon yang bersifat peribadi dan hanya menerbitkan lulus atau tolak, dengan komitmen SHA-256 yang mengikat data tersebut kepada seorang pengesah - antara muka, aritmetik titik tetap, guest Rust, skrip hos, dan program yang beroperasi secara langsung pada chain 18.

Pemberi pinjaman menerbitkan model pemarkahannya. Pemohon menjalankannya ke atas data miliknya sendiri dan menyerahkan kepada pemberi pinjaman satu resit yang tertera “diluluskan” atau “ditolak”. Pemberi pinjaman tidak pernah melihat data tersebut, dan pemohon tidak dapat mengubah model itu atau memasukkan data rekaan ke dalamnya.

Ini ialah kes berguna yang paling ringkas bagi pembuktian sesuatu pengiraan dengan program awam dan parameter awam ke atas input persendirian. Modelnya ialah rangkaian neural dua lapisan dalam aritmetik integer. Bentuk yang sama sesuai untuk mana-mana peraturan yang ingin dapat dibaca oleh pengawal selia atau pihak lawan: formula harga, ujian kelayakan, had risiko.

Example programs menyediakan persediaan yang dikongsi oleh keempat-empat halaman contoh.

1. Apa yang dibuktikan

Tiga pihak:

  • Pemberi pinjaman menggunakan program dengan model sebagai segmen awamnya. ID program menamakan model itu. Sesiapa sahaja boleh membaca semula pemberat daripada rantaian.
  • Pengaku (biro kredit, bank, majikan) mengetahui data pemohon. Pengaku memberi pemohon nilai ciri, satu salt rawak 16 bait, dan tandatangannya ke atas komitmen SHA-256(salt ‖ features).
  • Pemohon memanggil program dengan salt dan ciri sebagai input persendirian.

Panggilan itu membuktikan bahawa:

  1. setiap ciri berada dalam julat yang diisytiharkan model untuknya;
  2. skor model ke atas ciri-ciri tersebut berada pada atau melebihi ambang (status 1) atau di bawahnya (status 2);
  3. komitmen yang diterbitkan ialah SHA-256 bagi salt dan ciri-ciri yang sama itu.

Pemberi pinjaman menyemak ID program resit, statusnya, dan bahawa komitmen itu ialah komitmen yang telah ditandatangani oleh pengaku. Pemberi pinjaman hanya mengetahui satu bit tentang pemohon.

Input persendirian tidak membuktikan apa-apa tentang dunia dengan sendirinya. Tanpa perkara 3, pemohon boleh menaip sebarang nombor. Komitmen itulah yang menghubungkan nombor dalam bukti dengan nombor yang telah diakui oleh seseorang. Tandatangan itu sendiri disemak di luar rantaian oleh pemberi pinjaman: pengesahan Dilithium atau ECDSA tidak muat dalam bajet sesuatu panggilan, dan ia tidak perlu berada di dalam bukti, kerana komitmen itu awam.

2. Antara muka

Setiap perkataan awam ialah i32, disimpan sebagai u32 pelengkap duanya.

perkataan awammaksud
0bilangan ciri n, 1 hingga 16
1bilangan unit tersembunyi h, 1 hingga 16
2ambang
3bilangan bit pecahan, anjakan s, 0 hingga 31
kemudian 2n perkataanmin dan max yang dibenarkan bagi setiap ciri
kemudian h × n perkataanpemberat lapisan pertama, baris demi baris
kemudian h perkataanpincang lapisan pertama
kemudian h perkataanpemberat lapisan kedua
kemudian 1 perkataanpincang lapisan kedua
perkataan persendirianmaksud
0 hingga 3salt, 16 bait sebagai empat perkataan big-endian
4 dan seterusnyan ciri, setiap satu ialah i32
slot outputmaksud
0status: 1 diluluskan, 2 ditolak, 3 satu ciri di luar julat, 4 model rosak (saiz di luar had, atau aritmetik melimpah)
1tidak digunakan
2 hingga 620 bait pertama komitmen, sebagai lima perkataan big-endian
7tidak digunakan; panik Rust menulis 0xdeadbeef di sini

Komitmen hanya diterbitkan dengan status 1 atau 2. Input di luar julat menghentikan pelaksanaan sebelum apa-apa di-hash.

3. Aritmetik

Model ini hanya menggunakan integer. Mesin ini tidak mempunyai titik terapung, dan pengesah mesti dapat menghasilkan semula skor itu dengan tepat, sesuatu yang tidak dijamin oleh titik terapung merentas mesin.

hidden[j] = max( (b1[j] + Σ w1[j][i] · x[i]) >> s , 0 )      for each hidden unit j
score     = (b2 + Σ w2[j] · hidden[j]) >> s
approved  = score >= threshold

Pemberat ialah titik tetap dengan s bit pecahan: dengan s = 8, pemberat 256 bermaksud 1.0. Hasil tambah ialah i64, dan setiap darab serta tambah disemak, maka model dengan pemberat yang cukup besar untuk melimpah memberikan status 4 dan bukannya skor yang salah. >> pada i64 negatif membundar ke arah tolak infiniti dalam Rust, dan >> Python melakukan perkara yang sama, yang membolehkan fungsi Python sepuluh baris menjadi rujukan.

Model demo ini mempunyai lapan ciri dan empat unit tersembunyi. Pemberatnya ditulis dengan tangan untuk halaman ini. Ia bukan model terlatih dan tidak menyatakan apa-apa tentang kredit.

{
  "shift": 8,
  "threshold": 600,
  "features": [
    {"name": "age_years", "min": 18, "max": 120},
    {"name": "income_thousands", "min": 0, "max": 100000},
    {"name": "debt_to_income_pct", "min": 0, "max": 1000},
    {"name": "on_time_payments_pct", "min": 0, "max": 100},
    {"name": "utilisation_pct", "min": 0, "max": 100},
    {"name": "history_years", "min": 0, "max": 100},
    {"name": "inquiries_12m", "min": 0, "max": 100},
    {"name": "delinquencies", "min": 0, "max": 100}
  ],
  "w1": [
    [  64,   96,  -512,  1536,  -640,  1024, -2048, -8192],
    [   0,  256, -1024,     0,     0,     0,     0,     0],
    [   0,    0,     0,  2560, -1280,     0, -4096, -16384],
    [ 128,    0,     0,     0,     0,  2048,     0,     0]
  ],
  "b1": [25600, 12800, -128000, 0],
  "w2": [160, 96, 224, 128],
  "b2": 76800
}

4. Guest

my-guests/score/src/main.rs, lengkap:

#![no_std]
#![no_main]

use guest_sdk::{halt, read_input, read_public, sha256_compress, write_output};

const MAX_FEATURES: usize = 16;
const MAX_HIDDEN: usize = 16;

const APPROVED: u32 = 1;
const DECLINED: u32 = 2;
const OUT_OF_RANGE: u32 = 3;
const BAD_MODEL: u32 = 4;

/// SHA-256's initial state (FIPS 180-4 §5.3.3).
const IV: [u32; 8] = [
    0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
];

/// SHA-256 of `words`, each word taken as four big-endian bytes. The message is whole words,
/// so the padding is whole words too: `0x80000000`, zeros, then the bit length in the last
/// word of a block (the length's high word is always zero here).
fn sha256_words(words: &[u32]) -> [u32; 8] {
    let mut buf = [0u32; 24];
    buf[16..].copy_from_slice(&IV);
    let mut fill = 0;
    for &w in words {
        buf[fill] = w;
        fill += 1;
        if fill == 16 {
            sha256_compress(&mut buf);
            fill = 0;
        }
    }
    buf[fill] = 0x8000_0000;
    fill += 1;
    if fill > 14 {
        buf[fill..16].fill(0);
        sha256_compress(&mut buf);
        fill = 0;
    }
    buf[fill..15].fill(0);
    buf[15] = 32 * words.len() as u32;
    sha256_compress(&mut buf);
    let mut out = [0u32; 8];
    out.copy_from_slice(&buf[16..]);
    out
}

/// `weight · x`, added to `acc`; `None` when it does not fit an i64.
fn mul_add(acc: i64, weight: u32, x: i64) -> Option<i64> {
    acc.checked_add((weight as i32 as i64).checked_mul(x)?)
}

/// Runs the model in the public segment over the private features.
fn score(features: &[i32], hidden: usize, shift: u32) -> Option<i64> {
    let n = features.len();
    // The public segment after the header and the feature ranges:
    // hidden × n first-layer weights, hidden biases, hidden second-layer weights, one bias.
    let w1 = 4 + 2 * n;
    let b1 = w1 + hidden * n;
    let w2 = b1 + hidden;
    let b2 = w2 + hidden;

    let mut out = read_public(b2 as u32) as i32 as i64;
    for j in 0..hidden {
        let mut acc = read_public((b1 + j) as u32) as i32 as i64;
        for (i, &x) in features.iter().enumerate() {
            acc = mul_add(acc, read_public((w1 + j * n + i) as u32), x as i64)?;
        }
        // Fixed point: drop the fractional bits, then ReLU.
        let h = (acc >> shift).max(0);
        out = mul_add(out, read_public((w2 + j) as u32), h)?;
    }
    Some(out >> shift)
}

/// Public segment, fixed at deploy (every value an i32):
///   [features n, hidden units, threshold, fractional bits,
///    n × (min, max), hidden × n weights, hidden biases, hidden weights, bias]
/// Private input: [salt (4 words), n features].
/// Outputs: [status, 0, commitment (first 5 words), 0], where
/// commitment = SHA-256(salt ‖ features), every word big-endian.
#[no_mangle]
pub extern "C" fn main() -> ! {
    let n = read_public(0) as usize;
    let hidden = read_public(1) as usize;
    let threshold = read_public(2) as i32 as i64;
    let shift = read_public(3);
    if n == 0 || n > MAX_FEATURES || hidden == 0 || hidden > MAX_HIDDEN || shift > 31 {
        write_output(0, BAD_MODEL);
        halt();
    }

    // The committed message: the salt, then the features, in input order.
    let mut message = [0u32; 4 + MAX_FEATURES];
    for (i, w) in message.iter_mut().enumerate().take(4 + n) {
        *w = read_input(i as u32);
    }
    let mut features = [0i32; MAX_FEATURES];
    let mut in_range = true;
    for i in 0..n {
        let x = message[4 + i] as i32;
        let min = read_public(4 + 2 * i as u32) as i32;
        let max = read_public(5 + 2 * i as u32) as i32;
        in_range &= min <= x && x <= max;
        features[i] = x;
    }
    if !in_range {
        write_output(0, OUT_OF_RANGE);
        halt();
    }

    let status = match score(&features[..n], hidden, shift) {
        Some(s) if s >= threshold => APPROVED,
        Some(_) => DECLINED,
        None => BAD_MODEL,
    };
    let commitment = sha256_words(&message[..4 + n]);

    write_output(0, status);
    for k in 0..5 {
        write_output(2 + k as u32, commitment[k]);
    }
    halt();
}

Model ialah data, bukan kod. Pemberat dibaca dengan read_public, jadi satu imej yang digunakan boleh melayani mana-mana model sehingga 16 ciri dan 16 unit tersembunyi. Menukar model bermaksud penggunaan baharu bagi kod yang sama dengan segmen awam baharu, dan ID program baharu. Pemberi pinjaman tidak dapat menukar pemberat di bawah pemohon, dan pemohon tidak dapat memilih model yang lebih bermurah hati: resit menamakan ID program, dan ID itu mengikat pemberat.

Julat ialah sebahagian daripada model. Tanpanya, pemohon tidak dapat berbohong tentang sesuatu nilai (komitmen menghalang perkara itu) tetapi pengaku boleh menandatangani nilai yang tidak masuk akal, seperti umur −5, yang akan diberi ganjaran oleh model yang mempunyai pemberat negatif. Semakan ini juga mengikat aritmetik.

Salt melaksanakan dua tugas. Ia menjadikan komitmen tidak dapat diteka: lapan integer kecil mempunyai entropi yang rendah, dan tanpa salt sesiapa sahaja boleh me-hash calon pemohon dan membandingkannya. Dan ia menyalurkan 128 bit rawak melalui pengiraan. Sebelum set kekangan 7 menutup jumlah bas bukti, panggilan ke atas beberapa perkataan persendirian yang kecil boleh dipecahkan dengan cubaan paksa daripada bukti itu sendiri, dan nota fullnode menyuruh program sedemikian membaca perkataan rawak. Chain 18 menjalankan set kekangan 8, yang telah membaiki perkara itu, tetapi salt hanya memerlukan empat perkataan input dan menghapuskan persoalan tersebut.

5. Bahagian hos

score.py hanya menggunakan perpustakaan standard Python:

score.py setup   <model.json>                            writes public.txt
score.py witness <model.json> <salt: 32 hex> <x0> <x1> …  prints the private words;
                                                        stderr: the score, the decision, the commitment
score.py commit  <salt: 32 hex> <x0> <x1> …              prints the commitment alone

Pemarkah rujukan dan komitmen, secara penuh:

def score(m, x):
    """The guest's arithmetic exactly: integers, a floor shift after each layer, ReLU between."""
    out = m["b2"]
    for row, b, w2 in zip(m["w1"], m["b1"], m["w2"]):
        h = max((b + sum(w * xi for w, xi in zip(row, x))) >> m["shift"], 0)
        out += w2 * h
    return out >> m["shift"]

def commitment(salt: bytes, x):
    return hashlib.sha256(salt + b"".join(struct.pack(">i", xi) for xi in x)).digest()
$ cd my-guests/score
$ python3 score.py setup model.json
wrote public.txt (61 words)
$ cat public.txt
8 4 600 8 18 120 0 100000 0 1000 0 100 0 100 0 100 0 100 0 100 64 96 4294966784 1536 4294966656 1024 4294965248 4294959104 0 256 4294966272 0 0 0 0 0 0 0 0 2560 4294966016 0 4294963200 4294950912 128 0 0 0 0 2048 0 0 25600 12800 4294839296 0 160 96 224 128 76800

Nombor yang besar ialah pemberat negatif: 4294966784 ialah −512.

Guest itu diuji terhadap rujukan ini ke atas 300 pemohon rawak, dengan membandingkan keputusan dan kesemua lima perkataan komitmen, dan ke atas pemohon yang skornya 599 dan 600. Semuanya sepadan.

6. Bina dan jalankan

$ rand-guest build my-guests/score --max-words 65535
462 words against a cap of 65535 (fits); 0 ecall(s) with a non-static a7
OK
wrote my-guests/score/image.bin and its .sha256 (462 words, hc c63d7b15a165a11d007ce48bc37563b71f77fcc4991ffe0182c8cf4c77b6e7b5, program id ce8d234faf737c24bdd2826933ac843973c140c53e76fbb2cccaef3073da9818)

Seorang pemohon berumur 41 tahun dengan pendapatan 85 ribu, 28% hutang kepada pendapatan, 97% bayaran tepat pada masanya, 22% penggunaan, 12 tahun sejarah, satu pertanyaan dan tiada tunggakan:

$ python3 score.py witness model.json 00112233445566778899aabbccddeeff 41 85 28 97 22 12 1 0 > witness.txt
score 1075 approved
commitment 9430c3818f5966f8dd33f78e05a7d079355191e6
$ cat witness.txt
1122867 1146447479 2291772091 3437096703 41 85 28 97 22 12 1 0
$ rand-guest run image.bin --public $(cat public.txt) --input $(cat witness.txt) --tier 14
out[0] = 1
out[1] = 0
out[2] = 2486223745
out[3] = 2405000952
out[4] = 3711170446
out[5] = 94883961
out[6] = 894538214
out[7] = 0
cycles 1810
tier 12
tier 14: fits (cycles 1946 of 16383, Poseidon2 permutations 136 of 2048)

2486223745 ialah 0x9430c381, empat bait pertama komitmen. Skor itu, 1075, tidak muncul di mana-mana dalam output.

Pemohon kedua (23, 31, 55, 82, 91, 2, 6, 2, dengan salt lain) memperoleh skor 417 dan memberikan out[0] = 2 dengan komitmennya sendiri, dalam 1,810 kitaran yang sama. Pemohon pertama dengan umur ditukar kepada 17 memberikan out[0] = 3 dan tiada komitmen.

7. Bajet

program462 perkataan
segmen awam61 perkataan
perkataan persendirian12
kitaran1,810
pemampatan SHA-2561 (48 bait mesej muat dalam satu blok)
peringkat12

Ini ialah program yang paling murah daripada keempat-empatnya. Hantaran ke hadapan ialah 36 pendaraban. Model pada had program, 16 ciri dan 16 unit tersembunyi, ialah 272 pendaraban dan segmen awam 325 perkataan. Ia diukur pada 7,900 kitaran dalam emulator, kira-kira separuh daripada peringkat 14.

Pelaksanaan tidak bergantung pada data: 200 pemohon rawak, yang diluluskan dan ditolak sama-sama, masing-masing mengambil tepat 1,810 kitaran. Had gas yang diisytiharkan oleh sesuatu panggilan adalah awam dan dibundarkan daripada gas pelaksanaan, jadi program yang bilangan kitarannya mengikut inputnya akan membocorkan sedikit daripadanya. Program ini tidak mempunyai apa-apa untuk dibocorkan dengan cara itu.

Sejak chain 18, dompet mencetak gas tepat pelaksanaan dan had yang diisytiharkannya:

gas: 2011 (declaring 2048, tier 12)

1,948 baris pada 1 gas setiap satu, ditambah 63 lagi untuk satu pemampatan itu.

8. Penggunaan

61 perkataan model dibayar seperti perkataan kod: 0.001 + 0.0001 × (462 + 61) = 0.0533 RAND.

$ rand fee deploy 462 --public-words 61
0.0533 RAND
$ rand program deploy image.bin --public public.txt
program id: 7bbec14289f4446231b3a9a5ac18cb0613a373ca8a14fe4f046f3fde7ae6c73c (462 words, hc 157b3dc61da165a18be47c00b76375c3c4fc771f01fe1f994ccfc882b5e7b677, public input 61 words, digest a08a7c691c45babeb39e953930d4d7174662b7b8adcc2d0f4e6c193d362d6668)
proving the spend authorisation on this machine (tier 10; seconds)…
authorisation proved in 7.4s: tier 10, 1364940 bytes
proving the bundle (tier 14; about a minute and a half on a laptop)…
proved in 123.5s: tier 14, 1497319 bytes
submitted deploy d47a9323ea53bfafc3faa36d004416d374bf3c2a48971d87e346be426b0caf14
  0 RAND out, 59.7229 RAND change, fee 0.0533 RAND, anchored at height 98062, proved in 123.5s (bundle) + 7.4s (auth)

9. Panggilan

$ rand call 7bbec14289f4446231b3a9a5ac18cb0613a373ca8a14fe4f046f3fde7ae6c73c \
    $(sed 's/[0-9][0-9]*/--input &/g' witness.txt)
proving the call locally (12 inputs stay private, over the program's 61-word public input)…
gas: 2011 (declaring 2048, tier 12)
fee 0.005673037 RAND (incl. two price steps of headroom)
proved in 30.6s: tier 12, 1838256 bytes, outputs [1, 0, 2486223745, 2405000952, 3711170446, 94883961, 894538214, 0]
proving the spend authorisation on this machine (tier 10; seconds)…
authorisation proved in 6.8s: tier 10, 1369611 bytes
proving the bundle (tier 14; about a minute and a half on a laptop)…
proved in 124.3s: tier 14, 1499112 bytes
submitted call 454c1b9eb1e159e682d4ff26b71f77d8a950b813533d91a89293dd432fdcf6f7
  0 RAND out, 59.696058627 RAND change, fee 0.005673037 RAND, anchored at height 98832, proved in 124.3s (bundle) + 6.8s (auth)
{
  "h_in": "ef80c744a8cdea62b56e334baaf7372e4a2e6c8282d37aa8ae96b4f039ec1a22",
  "h_pub": "a08a7c691c45babeb39e953930d4d7174662b7b8adcc2d0f4e6c193d362d6668",
  "height": 98993,
  "index": 0,
  "outputs": [
    1,
    0,
    2486223745,
    2405000952,
    3711170446,
    94883961,
    894538214,
    0
  ],
  "program": "7bbec14289f4446231b3a9a5ac18cb0613a373ca8a14fe4f046f3fde7ae6c73c",
  "tier": 12,
  "tx": "454c1b9eb1e159e682d4ff26b71f77d8a950b813533d91a89293dd432fdcf6f7"
}
input transcript published; open it with `rand open-call 454c1b9eb1e159e682d4ff26b71f77d8a950b813533d91a89293dd432fdcf6f7`

Status 1 dan komitmen 9430c381 8f5966f8 dd33f78e 05a7d079 355191e6 dalam heks. h_pub ialah digest bagi 61 perkataan model. Ciri, salt dan skor tidak terdapat dalam transaksi.

Panggilan itu mengambil masa lebih sedikit daripada tiga minit pada komputer riba Apple Silicon: 31 s untuk bukti panggilan, 7 s untuk kebenaran perbelanjaan dan 124 s untuk bundle, dengan puncak 6.2 GB. Buktinya berukuran 1,838,256 bait.

10. Semak sendiri

Pihak pemberi pinjaman, dengan hanya resit dan komitmen bertandatangan pengaku:

  1. Model. rand_getProgramPublic pada ID program mengembalikan 61 perkataan. Bandingkannya dengan model.json yang diterbitkan (score.py setup membinanya semula).
  2. Kod. Bina semula my-guests/score pada commit circuits yang sama dan bandingkan hc dengan code_hash program itu.
  3. Resit. program ialah ID model, output 0 ialah 1, slot 7 bukan 3735928559.
  4. Komitmen. Output 2 hingga 6, dicetak sebagai heks, ialah 20 bait pertama komitmen yang ditandatangani oleh pengaku:
$ python3 score.py commit 00112233445566778899aabbccddeeff 41 85 28 97 22 12 1 0
9430c3818f5966f8dd33f78e05a7d079355191e6

Penolakan juga merupakan resit. Panggilan pemohon kedua, 119e7834…1b3b pada chain 18 (diulang pada chain 20 sebagai c8a60183…9f73, yang turut menolak), telah dibuktikan dan diikat dengan cara yang sama:

$ python3 score.py witness model.json 0f1e2d3c4b5a69788796a5b4c3d2e1f0 23 31 55 82 91 2 6 2 > witness.txt
score 417 declined
commitment 0313ea462178574c49a10fe7ea1d84207652e1a3
$ rand call 7bbec14289f4446231b3a9a5ac18cb0613a373ca8a14fe4f046f3fde7ae6c73c \
    $(sed 's/[0-9][0-9]*/--input &/g' witness.txt)
…
gas: 2011 (declaring 2048, tier 12)
proved in 26.1s: tier 12, 1836624 bytes, outputs [2, 0, 51636806, 561534796, 1235292135, 3927802912, 1985143203, 0]
…
submitted call 119e7834033edd19bba8e10c1a764e8bdbc0b1c8415a42f041faa392c6411b3b

Status 2, dan 51636806 ialah 0x0313ea46. Gas, had yang diisytiharkan dan tier adalah sama seperti panggilan yang diluluskan, jadi kedua-duanya hanya berbeza pada chain dalam perkataan status dan komitmen, dan tidak di tempat lain. Pemohon tiada sebab untuk menerbitkan penolakan, tetapi pemberi pinjaman boleh meminta resit itu dalam kedua-dua keadaan, dan pemohon yang ditolak tidak dapat menghasilkan resit yang diluluskan.

Perkara yang tidak diberikan oleh bukti itu

  • Data yang benar. Bukti itu menunjukkan bahawa model dijalankan ke atas nilai yang dikomit. Sama ada nilai itu benar bergantung pada kata penyaksi (attester), dan pemberi pinjaman perlu mempercayai tandatangan penyaksi untuk perkara itu.
  • Pemohon yang tidak boleh dipautkan. Komitmen ialah pengecam yang tetap: penyaksi boleh mengenalinya, dan dua resit dengan komitmen yang sama ialah pemohon yang sama dan data yang sama. Garam baharu daripada penyaksi bagi setiap permohonan menyelesaikan yang kedua, tetapi tidak yang pertama.
  • Model rahsia. Pemberat adalah awam. Itulah tujuannya bagi peraturan yang mesti dapat dibaca oleh orang ramai, dan kelemahan bagi pemberi pinjaman yang menganggap modelnya sebagai rahsia perdagangan. Pemohon juga boleh mencari input yang akan lulus, tetapi tidak dapat menggunakannya tanpa tandatangan penyaksi ke atasnya.
  • Perlindungan daripada penyelidikan oleh penyaksi yang tidak jujur. Sesiapa yang mengetahui ciri-cirinya boleh menjalankan model awam itu sendiri. Privasi di sini ialah milik pemohon terhadap pemberi pinjaman dan orang ramai, bukan terhadap pihak yang membekalkan data.
  • Model yang besar. Enam belas ciri dan enam belas unit tersembunyi ialah kad skor, bukan rangkaian dalam. Satu panggilan dihadkan pada tier 14, kira-kira enam belas ribu kitaran.

Disahkan kali terakhir terhadap commit fullnode 48dc04b (rantai 18) pada 2026-09-30, dan circuits `aeacf31` (`guest-sdk/src/lib.rs`, `rand-guest`), the commit fullnode v0.6.7 vendors; every `rand-guest`, `python3` and `rand` output on this page was produced on 2026-09-30, the deploy and the call on chain 18. Jika kod dan halaman ini tidak selari, kodlah yang betul; sila maklumkan kepada kami.