இந்தப் பக்கம் உங்கள் சொந்த நிரலை Rand-இல் இயக்கத் தேவையான அனைத்தையும் விளக்குகிறது: ஒரு நிரல் எதுவாக இருக்கலாம், அது எதைப் படிக்கிறது, எதை வெளியிடுகிறது என்பதை எவ்வாறு வடிவமைப்பது, மேலும் இருமுறை எழுதப்பட்ட ஒரு முழுமையான எடுத்துக்காட்டு: ஒருமுறை Rust-இலும் ஒருமுறை C-யிலும். பின்னர் சோதனை, நிரூபண வரம்பு, நிறுவுதல், அழைத்தல், முடிவை யார் வேண்டுமானாலும் எவ்வாறு சரிபார்க்கலாம் என்பவற்றை விளக்குகிறது. கீழே உள்ள ஒவ்வொரு rand-guest வெளியீடும் ஓர் உண்மையான இயக்கத்திலிருந்து பெறப்பட்டு, அச்சிடப்பட்டவாறே ஒட்டப்பட்டுள்ளது. இந்த இயக்கங்கள் 2026-09-25 அன்று circuits கமிட் 7ef3220-இல் செய்யப்பட்டன. testnet இப்போது சங்கிலி 20; அதன் கருவித்தொகுப்பு, சங்கிலிகள் 18, 19 போலவே, aeacf31-இல் கட்டமைக்கப்பட்டது (கிளை feat/v067-circuits; fullnode v0.6.8 அதே கமிட்டை நிலைநிறுத்துகிறது), வெளியீடுகள் அங்கு மீண்டும் இயக்கப்படவில்லை. SDK அல்லது சங்கிலி எங்கு வேறுபடுகிறது என்பதைப் பக்கம் குறிப்பிடுகிறது.
இரண்டு சிறு பயிற்சிகள் விரைவான வழி: Rust நிரலை நிறுவுதல், RISC-V நிரலை நிறுவுதல். நீங்கள் Rust பயிற்சியின் படி 1-ஐ முடித்திருப்பதாக இந்தப் பக்கம் கருதுகிறது: aeacf31-இல் ஒரு randprotocol/zkp-circuits செக்அவுட், riscv32im-unknown-none-elf இலக்குடன் Rust 1.98.1, rand-guest இருமக் கோப்பு, C-க்கு clang 23.1.1 மற்றும் llvm-tools. RISC-V ISA இயந்திரத்துக்கான மேற்கோள் ஆவணம். எடுத்துக்காட்டு நிரல்கள் இங்கிருந்து தொடர்ந்து, பெரிய நிரல்களையும் சங்கிலி 18-இன் கேஸ் அளவீடு எதை மாற்றியது என்பதையும் விளக்குகிறது. இந்தப் பக்கம் RPL-1 நிரல்களை விளக்குகிறது; அவற்றை ஒரு Call நிலையற்ற முறையில் இயக்குகிறது. சங்கிலி 20-இல் RPL-2 நிரல் நிலையும் உள்ளது: ஒரு Invoke மாற்றும் செல்களும் ஒரு பெட்டகமும் (நிரல்கள்); முழுமையான எடுத்துக்காட்டுகள் randprotocol/example-programs-இல் உள்ளன.
1. ஒரு நிரல் எதுவாக இருக்கலாம்
ஒரு நிரல் என்பது இந்த வடிவத்துக்குப் பொருந்தும் எந்தக் கணக்கீடும் ஆகும்:
- அது உள்ளீடாக 32-பிட் சொற்களைப் படிக்கிறது.
- அது வெளியீடாக அதிகபட்சம் எட்டு 32-பிட் சொற்களை வெளியிடுகிறது.
- அது தீர்மானிக்கப்பட்ட நடத்தை கொண்டது: ஒரே உள்ளீடுகள் எப்போதும் ஒரே வெளியீடுகளைத் தருகின்றன.
- அது தனது படிநிலையின் வரம்புக்குள் நின்றுவிடுகிறது (பிரிவு 7).
அந்த வரம்புகளுக்குள் நீங்கள் எதையும் எழுதலாம். சுழற்சிகள், தன்னழைப்பு, கட்டமைப்புகள், அணிகள், 64-பிட் கணிதம், கிரேட்டுகள் ஆகியவை கிடைக்கும்; நீங்கள் ஒரு நினைவக ஒதுக்கியைக் கொண்டுவந்தால் குவியலும் கிடைக்கும். ஆனால் இயந்திரம் வெறும் RV32IM; அதன் கீழ் எந்த இயக்க முறைமையும் இல்லை:
| உங்களிடம் உள்ளவை | உங்களிடம் இல்லாதவை |
|---|---|
RV32IM முழுஎண் அறிவுறுத்தல்கள், MUL/DIV/REM உட்பட | மிதப்புப் புள்ளி வன்பொருள் (Rust-இன் மென்பொருள் மிதப்புப் புள்ளி எண்கள் வேலை செய்யும், மெதுவாக) |
இயல்புநிலை லிங்கர் ஸ்கிரிப்டில் 0x1000-இலிருந்து 1 MiB வரை RAM, 64 KiB அடுக்குடன் | குவியல், நீங்கள் ஒரு நினைவக ஒதுக்கியை வழங்காவிட்டால் (பிரிவு 6) |
| Poseidon2, Keccak-f, SHA-256 ஆகியவை அமைப்பு அழைப்புகளாக | கோப்புகள், வலையமைப்பு, கடிகாரங்கள், சீரற்ற தன்மை, இழைகள், std, libc |
no_std Rust கிரேட்டுகளும் தன்னிறைவான C-யும் | ஓர் அழைப்பிலிருந்து அடுத்த அழைப்புக்கு நீடிக்கும் நிலை |
| எட்டு பொது வெளியீட்டுச் சொற்கள் | நிரலுக்குள்ளிருந்து RAND அல்லது டோக்கன்களை நகர்த்தும் வழி |
நிரலை வடிவமைக்கும்போது கடைசி வரிசையே மிக முக்கியமானது. வெளியீடுகள் தரவு, விளைவுகள் அல்ல. குறிப்பிட்ட டைஜஸ்ட் கொண்ட ஒரு நிரல் சில தனிப்பட்ட உள்ளீடுகளின் மீது இயங்கி எட்டு சொற்களை வெளியிட்டது என்பதை ஓர் அழைப்பு நிரூபிக்கிறது. சங்கிலி அந்தச் சான்றைச் சரிபார்த்து, எட்டு சொற்களையும் ஒரு ரசீதில் சேமிக்கிறது. அது எந்த இருப்பையும் மாற்றுவதில்லை, எதையும் தூண்டுவதில்லை. அந்தச் சொற்களின் பொருள், நிரல், அதன் அழைப்பாளர், ரசீதைப் படிப்பவர் ஆகியோருக்கிடையே ஒப்புக்கொள்ளப்படுவது. சங்கிலி இன்னும் ஆதரிக்காதவற்றை நிரல்கள் பட்டியலிடுகிறது.
2. முதலில் இடைமுகத்தை வடிவமையுங்கள்
ஒரு நிரலுக்கு மூன்று வழித்தடங்கள் உள்ளன. எந்தக் குறியீட்டையும் எழுதுவதற்கு முன், ஒவ்வொன்றிலும் எது செல்லும் என்பதைத் தேர்ந்தெடுங்கள்.
| வழித்தடம் | எப்போது அமைக்கப்படுகிறது | படிக்கும் முறை | யார் பார்க்கிறார்கள் | சங்கிலி 20-இல் வரம்பு |
|---|---|---|---|---|
| தனிப்பட்ட உள்ளீடு | ஒவ்வோர் அழைப்பிலும் | read_input(i) / rand_read_input(i) | அழைப்பாளர் மட்டும், மற்றும் அழைப்பின் சாவியை அவர்கள் யாரிடம் ஒப்படைக்கிறார்களோ அவர்கள் | 16,071 சொற்கள் (முத்திரையிடப்பட்ட உள்ளீட்டு உறையின் வரம்பு) |
| பொதுப் பகுதி | ஒருமுறை, நிறுவும்போது | read_public(i) / rand_read_public(i) | அனைவரும்; நிரல் அடையாளம் அதைப் பிணைக்கிறது | 32,768 சொற்கள் |
| வெளியீடுகள் | இயக்கத்தின்போது | write_output(slot, w) / rand_write_output | அனைவரும், ரசீதில் | 8 சொற்கள் |
தனிப்பட்ட உள்ளீடுகள் தாமாக உலகைப் பற்றி எதையும் நிரூபிப்பதில்லை
ஒரு தனிப்பட்ட உள்ளீடு, சால்ட் சேர்க்கப்பட்ட உறுதிப்பாடு H_IN மூலம் சான்றுடன் பிணைக்கப்படுகிறது; எனவே நிரூபித்த பிறகு அதை மாற்ற முடியாது. ஆனால் உள்ளீடு உண்மையானது என்பதை அறிய நிரலுக்கு எந்த வழியும் இல்லை. அழைப்பாளர் எந்த எண்ணையும் தட்டச்சு செய்யலாம். ஒரு தனிப்பட்ட உள்ளீட்டுக்குப் பொருள் தர, நிரலுக்குள் அதை ஏதேனும் பொதுத் தரவுடன் இணையுங்கள்:
- முன்பே வெளியிடப்பட்ட ஓர் உறுதிப்பாடு (பொதுப் பகுதியில், அல்லது சரிபார்ப்பவருக்குத் தனி வழியில் வழங்கப்பட்டது), தனிப்பட்ட உள்ளீடு அதைத் திறக்க வேண்டும், கீழே உள்ள ஏலத்தில் உள்ளதுபோல;
- ஒரு Merkle வேர், அதன் கீழ் ஒரு தனிப்பட்ட இலை நிரூபிக்கப்பட வேண்டும் (இதற்கான அமைப்பு அழைப்பு Poseidon2);
- சரிபார்ப்பவரிடம் ஏற்கெனவே உள்ள ஒரு டைஜஸ்ட்; நிரல் அதை மீண்டும் கணக்கிட்டு வெளியீடாக வெளியிடுகிறது.
ரகசிய நிரல்களுக்கான மைய வடிவமைப்புத் திறன் இதுதான். சான்று சரிபார்ப்பவருக்கு என்ன கணக்கிடப்பட்டது என்பதைச் சொல்கிறது. பொதுத் தரவுடனான பிணைப்பு எதன் மீது என்பதைச் சொல்கிறது.
தரவைச் சொற்களாகக் குறியாக்குதல்
அனைத்தும் u32 ஆகவே பயணிக்கின்றன:
| தரவு | குறியாக்கம் |
|---|---|
| ஒரு பைட் சரம் | ஒரு நீளச் சொல், பின்னர் ஒரு சொல்லுக்கு நான்கு பைட்டுகளாக, சிறுமுனை வரிசையில், கடைசிச் சொல் பூஜ்ஜியங்களால் நிரப்பப்பட்டது (ELF பொது உள்ளீட்டுக்குப் பணப்பை பயன்படுத்தும் வடிவம்) |
ஒரு u64 அல்லது தொகை | இரண்டு சொற்கள், முதலில் கீழ்ப்பகுதி, பின்னர் மேல்பகுதி |
| குறியிட்ட முழுஎண் | ஒரு சொல்லில் இரண்டின் நிரப்பு வடிவம் |
| ஒரு பெரிய முடிவு | அதன் Poseidon2 டைஜஸ்ட்: 8 சொற்கள், இது அனைத்து வெளியீடுகளையும் நிரப்புகிறது; அல்லது சில சுருக்கச் சொற்களையும் ஒரு குறுகிய உறுதிப்பாட்டையும் வெளியிடுங்கள் |
கட்டளை வரிக் கருவிகள் உள்ளீட்டுச் சொற்களை தசம வடிவில் ஏற்கின்றன: rand-guest run --input, rand call --input இரண்டும் 0x…-ஐ ஏற்பதில்லை. rand program deploy --public-க்கான பொதுப் பகுதிக் கோப்பு தசமம், 0x பதினறும இரண்டையும் ஏற்கிறது.
வெளியீடுகளை வடிவமைத்தல்
- ஸ்லாட் 0 ஒரு நிலைச் சொல். தோல்விகள் உட்பட ஒவ்வொரு முடிவுக்கும் ஓர் எண்ணைக் கொடுங்கள்: பொருந்தாத திறப்பு, அதிகப்படியான உருப்படிகள், வரம்புக்கு வெளியே உள்ள உள்ளீடு. ஒரு சரிபார்ப்பு தோல்வியுற்றாலும், நிரல் ஒரு நிலைச் சொல்லுடன் சீராக நின்றுவிட வேண்டும்; அப்போதுதான் என்ன தவறு நடந்தது என்பதைச் சொல்லும் சான்று அழைப்பாளருக்குக் கிடைக்கும்.
- ஒவ்வொரு ஸ்லாட்டிலும் அதிகபட்சம் ஒருமுறைதான் எழுதலாம். ஒரே ஸ்லாட்டில் இரண்டாவது முறை எழுதுவது ஒரு பொறியாகும் (போன்மியில்
DoubleWrite(0)), பொறியில் சிக்கும் இயக்கத்தை நிரூபிக்க முடியாது. நீங்கள் ஒருபோதும் எழுதாத ஸ்லாட்டுகள் பூஜ்ஜியமாகப் படிக்கப்படும். - Rust-இல், ஸ்லாட் 7-ஐக் காலியாக வையுங்கள். முறிவடையும் Rust விருந்தினர் நிரல் ஸ்லாட் 7-இல்
0xdeadbeef(3,735,928,559) என்பதை எழுதி நின்றுவிடுகிறது. முறிவுக்கு முன் அது எழுதிய வெளியீடுகள் அப்படியே இருக்கும்; எனவே மற்றவற்றை நம்புவதற்கு முன் வாசிப்பவர் ஸ்லாட் 7-ஐச் சரிபார்க்க வேண்டும் (பிரிவு 6). - உங்களுக்குக் கொடுக்கப்பட்ட உள்ளீடுகளுக்கு அப்பால் படிப்பது ஒரு பொறி (போன்மியில்
InputIndex(5)). முதலில் எண்ணிக்கையைப் படித்து அதைச் சரிபாருங்கள்.
3. செய்துகாட்டிய எடுத்துக்காட்டு: முத்திரையிடப்பட்ட ஏலம்
தோல்வியுற்ற ஏலத்தொகைகளை வெளியிடாமல் இரண்டாம்-விலை ஏலம் நடத்த ஒரு விற்பனையாளர் விரும்புகிறார்:
- ஒவ்வோர் ஏலதாரரும் ஓர் ஏலத்தொகையையும் சீரற்ற 128-பிட் சால்ட்டையும் தேர்ந்தெடுத்து, விற்பனையாளருக்கு ஓர் உறுதிப்பாட்டை வழங்குகிறார்:
("BID1", bidder index, bid, salt)மீதான Poseidon2. - விற்பனையாளர் அடிப்படை விலையையும் ஒவ்வோர் உறுதிப்பாட்டையும் அதன் பொதுப் பகுதியாகக் கொண்டு ஏல நிரலை நிறுவுகிறார். இப்போது நிரல் அடையாளம் இந்த ஏலத்தை மட்டுமே குறிக்கிறது, வேறெதையும் அல்ல.
- ஒவ்வோர் ஏலதாரரும் தமது ஏலத்தொகையையும் சால்ட்டையும் விற்பனையாளருக்குத் தனிப்பட்ட முறையில் அனுப்புகிறார்.
- விற்பனையாளர் ஒவ்வோர் ஏலத்தொகையையும் சால்ட்டையும் தனிப்பட்ட உள்ளீடாகக் கொண்டு நிரலை அழைக்கிறார். நிரல் ஒவ்வொரு திறப்பையும் அதன் உறுதிப்பாட்டுடன் சரிபார்த்து, வெற்றியாளரைத் தேர்ந்தெடுத்து,
[status, winner, price, bidder count]-ஐ வெளியிடுகிறது.
யார் வென்றார், எந்த விலையில் என்பதைச் சங்கிலி அறிகிறது. தோல்வியுற்ற ஏலத்தொகைகளை அது ஒருபோதும் பார்ப்பதில்லை. எந்த ஏலத்தொகையையாவது மாற்றும் விற்பனையாளருக்கு முடிவுக்குப் பதிலாக BAD_OPENING கிடைக்கும், ஏனெனில் உறுதிப்பாடுகள் நிரல் அடையாளத்தில் நிலைநிறுத்தப்பட்டுள்ளன.
அனைத்தும் circuits செக்அவுட்டுக்குள்ளேயே இருக்கும், ஏனெனில் rand-guest build விருந்தினர் நிரலின் கோப்பகத்திலிருந்து மேல்நோக்கித் தேடி guest-sdk-ஐக் கண்டறிகிறது:
circuits/
guest-sdk/
rand-guest/
my-guests/
commit/ a Rust guest that computes one commitment
auction-core/ the auction rule as a plain no_std library, tested on the host
auction/ the Rust guest
auction-c/ the same guest in C
auction-c-test/ a host test for the C rule, outside the guest's directory
ஹாஷ் கணிப்பானாகப் போன்மி
ஏலதாரர்களுக்கு Goldilocks புலத்தின் மீதான Poseidon2, இயந்திரம் கணக்கிடுவதைப் போலவே துல்லியமாகத் தேவை. அதைக் கணக்கிடும் ஒரு சிறிய விருந்தினர் நிரலைப் போன்மியில் இயக்குவதே எளிமையான, சரியான கருவி. ஒரு டைஜஸ்ட் எட்டு சொற்கள்; வெளியீட்டு ஸ்லாட்டுகளின் எண்ணிக்கையும் சரியாக அதுவே.
my-guests/commit/Cargo.toml:
[package]
name = "commit"
version = "0.1.0"
edition = "2021"
[dependencies]
guest-sdk = { path = "../../guest-sdk" }
[profile.release]
opt-level = 3
lto = true
panic = "abort"
codegen-units = 1
[workspace]
my-guests/commit/src/main.rs:
#![no_std]
#![no_main]
use guest_sdk::{halt, poseidon2, read_input, write_output};
/// Inputs: a bidder's index, bid and four salt words.
/// Outputs: the 8-word commitment Poseidon2("BID1", index, bid, salt[0..4]).
#[no_mangle]
pub extern "C" fn main() -> ! {
let mut buf = [0u32; 8];
buf[0] = 0x4249_4431; // "BID1"
for i in 0..6 {
buf[1 + i] = read_input(i as u32);
}
unsafe { poseidon2(buf.as_mut_ptr(), 7) };
for (slot, word) in buf.iter().enumerate() {
write_output(slot as u32, *word);
}
halt();
}
poseidon2(ptr, n) n சொற்களை அதே இடத்தில் ஹாஷ் செய்து, 8-சொல் டைஜஸ்ட்டை ptr..ptr+8 மீது எழுதுகிறது; எனவே ஏழு சொற்கள் மட்டுமே ஹாஷ் செய்யப்பட்டாலும் இடையகம் குறைந்தது எட்டு சொற்களைக் கொள்ள வேண்டும். "BID1" குறிச்சொல் இந்த டைஜஸ்ட்டுகளை வேறு எந்த Poseidon2 பயன்பாட்டிலிருந்தும் தனித்து வைக்கிறது.
aeacf31-இல் poseidon2 ஒரு unsafe fn, ஏனெனில் அது ஒரு மூலச் சுட்டியை ஏற்கிறது; எனவே அழைப்பு ஒரு unsafe தொகுதிக்குள் உள்ளது. கீழே உள்ள வெளியீடுகள் உருவாக்கப்பட்ட 7ef3220-இல் அது ஒரு பாதுகாப்பான செயற்கூறாக இருந்தது; அதே வரி தொகுதி இல்லாமல் எழுதப்பட்டது. ஸ்பாஞ்ச் நிரப்புதல் செய்வதில்லை: [a], [a, 0] இரண்டும் ஒரே ஹாஷைத் தருகின்றன. ஒவ்வொரு செய்தியும் ஏழு சொற்களாகவும் ஒரு குறிச்சொல்லுடன் தொடங்குவதாகவும் இருக்கும் இந்த இடத்தில் அது தீங்கற்றது. நீளம் மாறக்கூடிய செய்திக்கு, aeacf31-இல் உள்ள SDK-யில் நீளத்தைப் பிணைக்கும் poseidon2_len(buf, n) உள்ளது (அமைப்பு அழைப்பு 7), ஆனால் அந்தக் கமிட்டில் உள்ள rand-guest check அமைப்பு அழைப்பு 7-ஐ மறுக்கிறது; எனவே அத்தகைய விருந்தினர் நிரல் இன்னும் கட்டமைக்கப்படுவதில்லை (zkp-circuits சிக்கல் #1). அதற்குப் பதிலாக நீளத்தைச் செய்தியிலேயே சேருங்கள்.
$ rand-guest build my-guests/commit --out commit.bin
76 words against a cap of 4096 (fits); 0 ecall(s) with a non-static a7
OK
wrote commit.bin and its .sha256 (76 words, hc 41007891b5c393296fdd76539c93d0b06678bc8a0bd52cfc3b6886dcf0381343, program id 11dabdf740989d43599b296c43342bf3ce890e980f5cc558d15ba8ca9e8e9438)
$ rand-guest run commit.bin --input 0 --input 400 --input 2654435769 --input 2135587861 --input 4087136352 --input 1559071514
out[0] = 3502385358
out[1] = 1187922325
out[2] = 2500412136
out[3] = 2452821097
out[4] = 2045657999
out[5] = 1866863173
out[6] = 678782893
out[7] = 3524569252
cycles 77
tier 10
இங்கும் கீழேயும் உள்ள கட்டமைப்பு வெளியீடுகளில் cargo வரிகள் விடுபட்டுள்ளன. cargo அச்சிடும் unaligned-scalar-mem எச்சரிக்கை எதிர்பார்க்கப்பட்டதே (Rust நிரலை நிறுவுதல்).
நான்கு ஏலதாரர்கள், இந்த ஏலத்தொகைகள் மற்றும் சால்ட்டுகளுடன்:
| ஏலதாரர் | ஏலத்தொகை | சால்ட் (நான்கு சொற்கள்) |
|---|---|---|
| 0 | 400 | 2654435769 2135587861 4087136352 1559071514 |
| 1 | 250 | 461845907 3432918353 3864292196 2246822507 |
| 2 | 900 | 3266489909 668265263 374761393 3550635116 |
| 3 | 300 | 4252018373 3042594569 1759714724 625341585 |
ஒவ்வோர் ஏலதாரருக்கும் ஒருமுறை commit.bin-ஐ இயக்கி, குறைந்தபட்ச விலையையும் (100), எண்ணிக்கையையும் (4), நான்கு டைஜெஸ்ட்களையும் வரிசைப்படி எழுதினால், 34 சொற்கள் கொண்ட பொதுப் பகுதி auction-public.txt கிடைக்கிறது:
100 4 3502385358 1187922325 2500412136 2452821097 2045657999 1866863173 678782893 3524569252 3413403069 1515911705 3633767467 1218237979 474331206 896634170 2889783686 541804293 3111308722 99534202 1917186958 1017842926 3082732585 4215265588 467906960 2929273893 588931287 1295911076 647129560 1384102451 625140897 4060943258 2970944086 698558155
உண்மையான ஏலத்தில் ஒவ்வோர் ஏலதாரரும் commit.bin-ஐத் தம் சொந்தக் கணினியில் இயக்குவார், சால்ட் உண்மையான சீரற்ற மூலத்திலிருந்து பெறப்படும்.
4. Rust-இல் நிரல்
விதி, சோதிக்கக்கூடிய ஒரு நூலகமாக
சிஸ்டம் அழைப்புகள் தேவைப்படாத தர்க்கத்தைத் தனியான no_std கிரேட்டில் வையுங்கள். guest-sdk riscv32 தவிர வேறு எந்த இலக்குக்கும் உருவாக மறுக்கிறது; எனவே விருந்தினர் கிரேட்டில் உங்கள் மடிக்கணினியில் cargo test இயங்காது. guest-sdk சார்பு இல்லாத நூலகக் கிரேட்டில் இயங்கும்.
my-guests/auction-core/Cargo.toml:
[package]
name = "auction-core"
version = "0.1.0"
edition = "2021"
[workspace]
my-guests/auction-core/src/lib.rs:
//! The auction's rule, with no syscalls, so it builds and tests on the host.
#![no_std]
#[derive(Debug, PartialEq, Eq)]
pub enum Outcome {
/// The highest bidder wins and pays the second-highest bid, or the reserve if higher.
Sold { winner: u32, price: u32 },
/// No bid reached the reserve.
NoSale,
}
/// A second-price (Vickrey) auction. Ties go to the lower index.
pub fn settle(reserve: u32, bids: &[u32]) -> Outcome {
let mut best: Option<(u32, u32)> = None; // (index, bid)
let mut second = 0u32;
for (i, &bid) in bids.iter().enumerate() {
match best {
Some((_, top)) if bid <= top => second = second.max(bid),
Some((_, top)) => {
second = top;
best = Some((i as u32, bid));
}
None => best = Some((i as u32, bid)),
}
}
match best {
Some((winner, top)) if top >= reserve => Outcome::Sold { winner, price: second.max(reserve) },
_ => Outcome::NoSale,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn highest_bid_pays_the_second() {
assert_eq!(settle(100, &[400, 250, 900, 300]), Outcome::Sold { winner: 2, price: 400 });
}
#[test]
fn the_reserve_sets_a_floor() {
assert_eq!(settle(500, &[400, 250, 900, 300]), Outcome::Sold { winner: 2, price: 500 });
assert_eq!(settle(1000, &[400, 250, 900, 300]), Outcome::NoSale);
}
#[test]
fn a_tie_goes_to_the_lower_index() {
assert_eq!(settle(0, &[700, 700]), Outcome::Sold { winner: 0, price: 700 });
}
#[test]
fn no_bids_is_no_sale() {
assert_eq!(settle(0, &[]), Outcome::NoSale);
}
}
$ cd my-guests/auction-core && cargo +1.98.1 test
running 4 tests
test tests::a_tie_goes_to_the_lower_index ... ok
test tests::highest_bid_pays_the_second ... ok
test tests::no_bids_is_no_sale ... ok
test tests::the_reserve_sets_a_floor ... ok
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
விருந்தினர் நிரல்
my-guests/auction/Cargo.toml இரண்டு கிரேட்களையும் பாதை வழியாகச் சார்ந்துள்ளது:
[package]
name = "auction"
version = "0.1.0"
edition = "2021"
[dependencies]
guest-sdk = { path = "../../guest-sdk" }
auction-core = { path = "../auction-core" }
[profile.release]
opt-level = 3
lto = true
panic = "abort"
codegen-units = 1
[workspace]
my-guests/auction/src/main.rs:
#![no_std]
#![no_main]
use auction_core::{settle, Outcome};
use guest_sdk::{halt, poseidon2, read_input, read_public, write_output};
const MAX_BIDDERS: usize = 64;
const TAG: u32 = 0x4249_4431; // "BID1", the same tag the commit guest uses
// Output slot 0: what happened.
const SOLD: u32 = 1;
const NO_SALE: u32 = 2;
const BAD_OPENING: u32 = 3;
const TOO_MANY: u32 = 4;
/// Public (fixed at deploy): reserve, n, then n 8-word commitments.
/// Private (per call): for each bidder, the bid and four salt words.
/// Outputs: [status, winner, price, n, 0, 0, 0, 0]; a panic sets slot 7 to 0xdeadbeef.
#[no_mangle]
pub extern "C" fn main() -> ! {
let reserve = read_public(0);
let n = read_public(1) as usize;
if n > MAX_BIDDERS {
finish(TOO_MANY, 0, 0, n as u32);
}
let mut bids = [0u32; MAX_BIDDERS];
for i in 0..n {
let base = (5 * i) as u32;
let bid = read_input(base);
let mut buf = [TAG, i as u32, bid, read_input(base + 1), read_input(base + 2),
read_input(base + 3), read_input(base + 4), 0];
unsafe { poseidon2(buf.as_mut_ptr(), 7) };
let committed = 2 + 8 * i as u32;
for w in 0..8 {
if buf[w] != read_public(committed + w as u32) {
finish(BAD_OPENING, i as u32, 0, n as u32);
}
}
bids[i] = bid;
}
match settle(reserve, &bids[..n]) {
Outcome::Sold { winner, price } => finish(SOLD, winner, price, n as u32),
Outcome::NoSale => finish(NO_SALE, 0, 0, n as u32),
}
}
fn finish(status: u32, winner: u32, price: u32, n: u32) -> ! {
write_output(0, status);
write_output(1, winner);
write_output(2, price);
write_output(3, n);
halt();
}
ஒவ்வொரு வெளியேறும் பாதையும் finish வழியாகச் செல்கிறது; அது ஒவ்வொரு ஸ்லாட்டையும் ஒருமுறை எழுதி நிறுத்துகிறது. சுழற்சியின் வரம்பு பொதுப் பகுதியிலிருந்து வருகிறது, அது deploy செய்யும்போதே நிலைநிறுத்தப்படுகிறது. எனவே உறுதிசெய்யப்பட்ட ஏலத்தொகைகளைவிடக் குறைவானவற்றை நிரல் படிக்கும்படி அழைப்பாளரால் செய்ய முடியாது.
உருவாக்கி இயக்குதல்
$ rand-guest build my-guests/auction --out auction.bin
258 words against a cap of 4096 (fits); 0 ecall(s) with a non-static a7
OK
wrote auction.bin and its .sha256 (258 words, hc aa04e4c451e986f086e9fcff53b213eb52e593317c32a979d5e24991164f050d, program id 148ab0c4b9ad5115caab4a2ab433e3e13b5e8fbecbd9d8a9d6ba20c64f942c73)
rand-guest run பொதுப் பகுதியை மீண்டும் மீண்டும் வரும் --public கொடிகளாக ஏற்கிறது. ஷெல்லில்:
PUB=$(for w in $(cat auction-public.txt); do printf -- "--public %s " "$w"; done)
BIDS="--input 400 --input 2654435769 --input 2135587861 --input 4087136352 --input 1559071514
--input 250 --input 461845907 --input 3432918353 --input 3864292196 --input 2246822507
--input 900 --input 3266489909 --input 668265263 --input 374761393 --input 3550635116
--input 300 --input 4252018373 --input 3042594569 --input 1759714724 --input 625341585"
rand-guest run auction.bin $PUB $BIDS --tier 10
out[0] = 1
out[1] = 2
out[2] = 400
out[3] = 4
out[4] = 0
out[5] = 0
out[6] = 0
out[7] = 0
cycles 641
tier 10
tier 10: fits (cycles 721 of 1023, Poseidon2 permutations 88 of 128)
விற்கப்பட்டது (1): ஏலதாரர் 2-க்கு, இரண்டாவது அதிக ஏலத்தொகையான 400-க்கு; நான்கு ஏலதாரர்கள் கணக்கிடப்பட்டனர். தோல்வியடைய வேண்டிய இரண்டு ஓட்டங்கள்:
| மாற்றம் | வெளியீடுகள் 0–3 | பொருள் |
|---|---|---|
| ஏலதாரர் 1-இன் ஏலத்தொகை 250-க்குப் பதில் 260 | 3 1 0 0 | ஏலதாரர் 1-இல் BAD_OPENING; வேறு எதுவும் வெளியிடப்படவில்லை |
| குறைந்தபட்ச விலை 100-க்குப் பதில் 1,000 (வேறு பொதுப் பகுதி, எனவே வேறு program id) | 2 0 0 4 | NO_SALE: எந்த ஏலத்தொகையும் குறைந்தபட்ச விலையை எட்டவில்லை |
5. அதே நிரல் C-இல்
C விருந்தினர் கோப்பகத்தில் .c கோப்புகளும் உங்கள் சொந்தத் தலைப்புக் கோப்புகளும் இருக்கும். rand-guest build --lang c guest.h, _start மற்றும் ஒரு சிறிய இயக்க நேர அமைப்பை வழங்குகிறது (RISC-V நிரலை deploy செய்தல்). அது கோப்பகத்திலுள்ள ஒவ்வொரு .c கோப்பையும் தொகுக்கிறது; எனவே ஹோஸ்ட் சோதனைக் கோப்புகள் வேறிடத்தில் இருக்க வேண்டும்.
my-guests/auction-c/auction.h:
#ifndef AUCTION_H
#define AUCTION_H
#include <stdint.h>
/* Outcome of a second-price auction. sold is 0 when no bid reached the reserve. */
struct outcome {
uint32_t sold;
uint32_t winner;
uint32_t price;
};
struct outcome settle(uint32_t reserve, const uint32_t *bids, uint32_t n);
#endif
my-guests/auction-c/settle.c:
#include "auction.h"
/* A second-price (Vickrey) auction. Ties go to the lower index. */
struct outcome settle(uint32_t reserve, const uint32_t *bids, uint32_t n) {
struct outcome o = {0, 0, 0};
if (n == 0) {
return o;
}
uint32_t winner = 0, top = bids[0], second = 0;
for (uint32_t i = 1; i < n; i++) {
if (bids[i] > top) {
second = top;
top = bids[i];
winner = i;
} else if (bids[i] > second) {
second = bids[i];
}
}
if (top >= reserve) {
o.sold = 1;
o.winner = winner;
o.price = second > reserve ? second : reserve;
}
return o;
}
my-guests/auction-c/main.c:
#include "guest.h"
#include "auction.h"
#define MAX_BIDDERS 64
#define TAG 0x42494431u /* "BID1", the same tag the commit guest uses */
enum { SOLD = 1, NO_SALE = 2, BAD_OPENING = 3, TOO_MANY = 4 };
static uint32_t bids[MAX_BIDDERS];
static void finish(uint32_t status, uint32_t winner, uint32_t price, uint32_t n) {
rand_write_output(0, status);
rand_write_output(1, winner);
rand_write_output(2, price);
rand_write_output(3, n);
rand_halt();
}
/* Public (fixed at deploy): reserve, n, then n 8-word commitments.
* Private (per call): for each bidder, the bid and four salt words.
* Outputs: [status, winner, price, n, 0, 0, 0, 0]. */
void main(void) {
uint32_t reserve = rand_read_public(0);
uint32_t n = rand_read_public(1);
if (n > MAX_BIDDERS) {
finish(TOO_MANY, 0, 0, n);
}
for (uint32_t i = 0; i < n; i++) {
uint32_t base = 5 * i;
uint32_t buf[8] = {TAG, i, rand_read_input(base), rand_read_input(base + 1),
rand_read_input(base + 2), rand_read_input(base + 3),
rand_read_input(base + 4), 0};
bids[i] = buf[2];
rand_poseidon2(buf, 7);
for (uint32_t w = 0; w < 8; w++) {
if (buf[w] != rand_read_public(2 + 8 * i + w)) {
finish(BAD_OPENING, i, 0, n);
}
}
}
struct outcome o = settle(reserve, bids, n);
if (o.sold) {
finish(SOLD, o.winner, o.price, n);
}
finish(NO_SALE, 0, 0, n);
}
bids பூஜ்ஜியத்தால் தொடக்கமளிக்கப்பட்ட ஒரு static; எனவே அது .bss-இல் இடம்பெறுகிறது. RAM ஏற்கனவே பூஜ்ஜியமாகப் படிக்கப்படுவதால், அதற்கு இமேஜ் சொற்கள் எதுவும் செலவாவதில்லை.
விதியை ஹோஸ்டில் சோதித்தல்
settle.c எந்தச் சிஸ்டம் அழைப்பையும் பயன்படுத்துவதில்லை, எனவே உங்கள் வழக்கமான தொகுப்பியே அதை உருவாக்க முடியும். my-guests/auction-c-test/test_settle.c:
#include <assert.h>
#include <stdio.h>
#include "../auction-c/auction.h"
int main(void) {
uint32_t bids[] = {400, 250, 900, 300};
struct outcome o = settle(100, bids, 4);
assert(o.sold && o.winner == 2 && o.price == 400);
o = settle(500, bids, 4);
assert(o.sold && o.price == 500);
o = settle(1000, bids, 4);
assert(!o.sold);
uint32_t tie[] = {700, 700};
o = settle(0, tie, 2);
assert(o.winner == 0 && o.price == 700);
puts("settle: 4 checks passed");
return 0;
}
$ cc -Wall -o test_settle my-guests/auction-c-test/test_settle.c my-guests/auction-c/settle.c && ./test_settle
settle: 4 checks passed
உருவாக்கி இயக்குதல்
$ rand-guest build --lang c my-guests/auction-c --out auction-c.bin
200 words against a cap of 4096 (fits); 0 ecall(s) with a non-static a7
OK
wrote auction-c.bin and its .sha256 (200 words, hc 68605aa8d28a863a4a52a25de07ba159327a0fd0145a9dcd5e5aa6e79ab6bea0, program id 5667c343b8848805a908c9009d426164f39d2f927b2c780529a054f0d66aafc1)
$ rand-guest run auction-c.bin $PUB $BIDS --tier 10
out[0] = 1
out[1] = 2
out[2] = 400
out[3] = 4
out[4] = 0
out[5] = 0
out[6] = 0
out[7] = 0
cycles 576
tier 10
tier 10: fits (cycles 641 of 1023, Poseidon2 permutations 73 of 128)
வெளியீடுகள் Rust விருந்தினர் நிரலின் வெளியீடுகளுடன் பொருந்துகின்றன. நான்கு ஏலதாரர்களுடன், C இமேஜ் 58 சொற்கள் சிறியது, 65 சுழற்சிகள் வேகமானது; 64 ஏலதாரர்களில் இந்தச் சமநிலை மாறுவதைப் பிரிவு 7 காட்டுகிறது. இரண்டும் வெவ்வேறு hc-களும் program id-களும் கொண்ட வெவ்வேறு நிரல்கள். எதன் மூலக் குறியீட்டை வெளியிடுகிறீர்களோ அதையே deploy செய்யுங்கள்.
6. மொழிக் குறிப்புகள்
Rust
கிரேட். #![no_std], #![no_main], மேலும் halt()-இல் முடியும் ஒரு #[no_mangle] pub extern "C" fn main() -> !. release சுயவிவரம் panic = "abort" என அமைக்கிறது. வெற்று [workspace] அட்டவணை கிரேட்டை எந்தப் பெற்றோர் workspace-இலிருந்தும் விலக்கி வைக்கிறது. .cargo/config.toml-ஐயும் உங்கள் சொந்தத் தொகுப்பிக் கொடிகளையும் தவிர்த்துவிடுங்கள்: rand-guest build முதலாவதை மறுக்கிறது, இரண்டாவதை முழுவதும் தானே அமைக்கிறது (Rust நிரலை deploy செய்தல்).
பேனிக்குகள். guest-sdk-இன் பேனிக் கையாளி ஸ்லாட் 7-இல் 0xdeadbeef எழுதி நிறுத்துகிறது. அந்த ஓட்டம் அப்போதும் செல்லுபடியான, நிரூபிக்கக்கூடிய ஓட்டமே. இந்த நிரல் ஸ்லாட்கள் 0, 1-ஐ எழுதிய பின் ஆறு உறுப்புகள் கொண்ட Vec-இன் 999-ஆம் சுட்டெண்ணைப் படிக்கிறது:
$ rand-guest run heap.bin --input 6 --input 1 --input 2 --input 3 --input 4 --input 5 --input 6
out[0] = 4
out[1] = 1080033280
out[2] = 0
out[3] = 0
out[4] = 0
out[5] = 0
out[6] = 0
out[7] = 3735928559
cycles 1326
tier 12
ஸ்லாட்கள் 0, 1 உண்மையான மதிப்புகளைக் கொண்டுள்ளன; ஓட்டம் பேனிக் ஆனதை ஸ்லாட் 7 காட்டுகிறது. அத்தகைய ஓட்டத்தைச் சமர்ப்பிக்கும் அழைப்பாளர் சங்கிலியில் ஒரு ரசீதைப் பெறுகிறார். ரசீதுகளைப் படிப்பவர் ஸ்லாட் 7 = 3,735,928,559 உள்ளவற்றை நிராகரிக்க வேண்டும், அல்லது நிரல் ஒருபோதும் பேனிக் ஆகக்கூடாது. ஒவ்வொரு பாதையிலும் get(), சரிபார்க்கப்பட்ட கணிதச் செயல்கள், வெளிப்படையான நிலைக் குறியீடுகள் ஆகியவற்றை விரும்புங்கள்.
ஹீப். இயல்பாக ஒதுக்கீட்டி எதுவும் இல்லை. நீங்கள் ஒன்றை வழங்கியதும் alloc வேலை செய்யும். ஒருமுறை இயங்கி வெளியேறும் நிரலுக்கு, நிலையான அரங்கின் மீதான bump ஒதுக்கீட்டி பொருத்தமானது:
extern crate alloc;
use alloc::vec::Vec;
use core::alloc::{GlobalAlloc, Layout};
use core::cell::UnsafeCell;
/// A bump allocator over a fixed arena: allocation moves a pointer forward, free does nothing.
/// One run is one short-lived process, so nothing needs to be reclaimed.
struct Bump {
arena: UnsafeCell<[u8; ARENA]>,
next: UnsafeCell<usize>,
}
const ARENA: usize = 256 * 1024;
unsafe impl Sync for Bump {}
unsafe impl GlobalAlloc for Bump {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let next = &mut *self.next.get();
let start = (*next + layout.align() - 1) & !(layout.align() - 1);
let end = start + layout.size();
if end > ARENA {
return core::ptr::null_mut();
}
*next = end;
(self.arena.get() as *mut u8).add(start)
}
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
}
#[global_allocator]
static HEAP: Bump = Bump { arena: UnsafeCell::new([0; ARENA]), next: UnsafeCell::new(0) };
அரங்கு பூஜ்ஜியமாக்கப்பட்டுள்ளதால், அது .bss-இல் இருக்கிறது, இமேஜ் சொற்களைச் சேர்ப்பதில்லை. இயல்புநிலை இணைப்பி ஸ்கிரிப்ட் 1 MiB RAM தருகிறது; அரங்கு, உங்கள் static மாறிகள், 64 KiB அடுக்குநினைவகம் ஆகிய அனைத்தும் அதற்குள் அடங்க வேண்டும். இந்த ஒதுக்கீட்டியுடன், Vec, collect(), iter().sum() அனைத்தும் உருவாகி check-ஐக் கடக்கின்றன. ஆனால் alloc-உம் அதன் சார்புகளும் குறியீட்டைச் சேர்க்கின்றன: இந்தச் சோதனை நிரல் 1,341 சொற்கள், ஏல நிரல் 258 சொற்கள் மட்டுமே. நிரலின் அளவு ஏன் நிரூபண வரவுசெலவைச் செலவழிக்கிறது என்பதைப் பிரிவு 7 விளக்குகிறது.
மிதவைப் புள்ளி. இலக்கில் மிதவைப் புள்ளி அறிவுறுத்தல்கள் இல்லை; Rust f32/f64-ஐ மென்பொருள் நிரல்கூறுகளாக மாற்றுகிறது. அவை வேலை செய்கின்றன: 9, 2, 7, 4, 5 ஆகியவற்றின் சராசரி f64-இல் கணக்கிடப்பட்டபோது 5.4f32-இன் பிட்களாகத் திரும்பி வந்தது. ஒவ்வொன்றும் பல சுழற்சிகளைச் செலவழிக்கிறது. இயலும் இடங்களில் முழு எண்களையோ நிலைப் புள்ளியையோ பயன்படுத்துங்கள்.
கிரேட்கள். crates.io-இலுள்ள no_std கிரேட்கள் வேறெந்தச் சார்பையும் போலவே உருவாகின்றன. hello, rand-க்கு crc கிரேட் கணக்கிட்ட CRC-32, எமுலேட்டரில் இயக்கியபோது, 2124296908 என அச்சிட்டது; Python-இன் zlib.crc32 தரும் அதே மதிப்பு. std தேவைப்படும் கிரேட்கள் இந்த இலக்குக்கு உருவாவதில்லை. rand-guest build --locked-ஐ அனுப்புவதில்லை; எனவே உங்கள் Cargo.lock-ஐ commit செய்யுங்கள்: அது இல்லாவிட்டால், மாதங்கள் கழித்து மீண்டும் உருவாக்கும்போது புதிய கிரேட் பதிப்பு தேர்ந்தெடுக்கப்பட்டு வேறு hc உருவாகலாம்.
unimp பொறி: நூலகக் குறியீட்டிலிருந்து ஒரு Csr கண்டறிதல். சில core குறியீடுகள், LLVM அடைய முடியாதது எனக் கருதும் பாதையில், ஒரு unimp சொல்லாக (0xc0001073, csrrw x0, cycle, x0) தொகுக்கப்படுகின்றன. இயந்திரத்தில் CSR-கள் இல்லை, எனவே check இமேஜை மறுக்கிறது:
0x00002250 0xc0001073 Csr: CSR instruction: the machine has no CSRs
2613 words against a cap of 4096 (fits); 0 ecall(s) with a non-static a7
REJECTED
wrote heap.bin (the loader refuses it: no hc)
இங்கே குற்றவாளி, இயக்க நேரத்தில் மட்டுமே நீளம் தெரியும் ஒரு Vec-இன் மீதான slice::sort_unstable. நிலையான sort()-உம் அதையே செய்தது; ஆனால் 16 உறுப்புகள் கொண்ட நிலையான அணியின் மீதான sort_unstable கடந்தது. அத்தகைய கண்டறிதலின் மூலத்தைக் கண்டுபிடிக்க, விருந்தினர் நிரலின் ELF-ஐப் பிரித்தமைத்து, check அச்சிட்ட முகவரியைச் சுற்றியுள்ள செயல்பாட்டைப் பாருங்கள்:
llvm-objdump -d -C my-guests/heap/target/riscv32im-unknown-none-elf/release/heap | grep -B12 unimp
பின்னர் அந்த அழைப்பை உங்கள் சொந்தக் குறியீட்டால் மாற்றுங்கள் (இந்த நிரலுக்கு, ஒரு சிறிய செருகல் வரிசைப்படுத்தல்). இதே காரணத்தால்தான் guest-sdk-இன் சொந்த halt() ஒரு noreturn உறுதிமொழிக்குப் பதிலாக loop {}-இல் முடிகிறது.
C
- நுழைவுப் புள்ளி
void main(void), அதுrand_halt()-இல் முடிகிறது. இணைக்கப்பட்ட_startஅடுக்குநினைவகத்தை அமைத்து அதை அழைக்கிறது. - libc இல்லை.
printf,malloc,<string.h>எதுவும் இல்லை. இயக்க நேர அமைப்புmemcpy,memmove,memset,memcmpஆகியவற்றையும் (struct நகல்களுக்கும் பெரிய தொடக்க மதிப்புகளுக்கும் clang அவற்றுக்கான அழைப்புகளை உருவாக்குகிறது) நான்கு 64-பிட் வகுத்தல் உதவிச் செயல்பாடுகளையும் வழங்குகிறது. அவை அனைத்தும் பைட் சுழற்சிகள்; எனவே அடிக்கடி இயங்கும் குறியீட்டில் சொற்களாக நகலெடுத்து வகுங்கள். ஹீப்புக்கு, Rust-இல் போலவே, ஒருstaticஅணியின் மீது bump ஒதுக்கீட்டியை எழுதுங்கள். - வரையறுக்கப்படாத நடத்தை பிடிக்கப்படுவதில்லை. பேனிக் கையாளி இல்லை. எல்லைக்கு வெளியே எழுதுதல் நினைவகத்தை அமைதியாகச் சிதைக்கிறது; சீரமைக்கப்படாத ஏற்றுதல் அல்லது சேமித்தல் பொறியில் சிக்குகிறது, அதாவது அந்த ஓட்டத்தை நிரூபிக்க முடியாது.
main.cn-ஐMAX_BIDDERS-உடன் சரிபார்ப்பதுபோல, சுட்டெண்களை உங்கள் சொந்த வரம்புகளுடன் சரிபாருங்கள். - கோப்பக விதிகள். உங்கள் சொந்த
guest.hஅல்லதுstart.S-ஐச் சேர்க்காதீர்கள்;build --lang cஇரண்டையும் மறுக்கிறது. கோப்பகத்திலுள்ள ஒவ்வொரு.cகோப்பும் இமேஜில் தொகுக்கப்படுவதால், சோதனைக் கோப்புகளை விருந்தினர் கோப்பகத்துக்கு வெளியே வையுங்கள். - நிலைநிறுத்தப்பட்ட clang.
rand-guest23.1.1 தவிர வேறெந்த clang-ஐயும் மறுக்கிறது.RAND_GUEST_CLANG_UNPINNED=1அதை மீறுகிறது; அப்போது உங்கள்hcவேறு எவருடைய உருவாக்கத்துடனும் பொருந்தாது என்ற எச்சரிக்கை வரும்.
7. இது நிரூபிக்கப்படுமா? வரவுசெலவு
நிரூபிப்பான் ஒவ்வொரு ஓட்டத்தையும் ஓர் அடுக்கு t-க்கு நிரப்புகிறது. ஓர் அடுக்குக்கு இரண்டு சுயாதீன வரவுசெலவுகள் உண்டு; rand-guest run --tier t இரண்டையும் அறிவிக்கிறது:
- வரிசைகள்: அதிகபட்சம்
2ᵗ − 1, இயக்கப்பட்ட சுழற்சிகளும் டைஜெஸ்ட் வரிசைகளும் சேர்த்து; - Poseidon2 வரிசைமாற்றங்கள்: அதிகபட்சம்
2ᵗ⁻³.
| அடுக்கு | வரிசைகள் | Poseidon2 வரிசைமாற்றங்கள் | ஹாஷ் அட்டவணை இல்லாத கேஸ் உச்சவரம்பு | சங்கிலி 20-இல் ஓர் அழைப்பு |
|---|---|---|---|---|
| 10 | 1,023 | 128 | 1,279 | ஏற்கப்படும் |
| 12 | 4,095 | 512 | 5,119 | ஏற்கப்படும் |
| 14 | 16,383 | 2,048 | 20,479 | ஏற்கப்படும் |
| 16 | 65,535 | 8,192 | 81,919 | v0.5.6 முதல் மறுக்கப்படும் |
| 18, 20 | 2¹⁸ − 1, 2²⁰ − 1 | 2¹⁵, 2¹⁷ | 327,679, 1,310,719 | v0.5.6 முதல் மறுக்கப்படும் |
கட்டணம் அடுக்கைப் பின்பற்றுவதில்லை, கேஸையும் பைட்களையும் பின்பற்றுகிறது. சங்கிலி 15-இல் ஓர் அழைப்பு நிலையான 0.001 + call_fee(tier) செலுத்தியது: அடுக்கு 10-இல் 0.002 RAND, அடுக்கு 12-இல் 0.0021, அடுக்கு 14-இல் 0.0022. சங்கிலி 18 முதல் ஒவ்வொரு ஓட்டமும் அளவிடப்படுகிறது. ஒரு சாதாரண வரிசை 1 கேஸ், ஒரு Poseidon2 உள்வாங்கல் வரிசை 3, ஒரு Keccak வரிசைமாற்றம் 192, ஒரு SHA-256 சுருக்கம் 64. நிரூபணம் ஓர் அறிவிக்கப்பட்ட கேஸ் வரம்பை வெளியிடுகிறது; ஓட்டத்தின் கேஸ் அதற்குச் சமமாகவோ குறைவாகவோ இருப்பதைச் சுற்று கட்டாயப்படுத்துகிறது; துல்லியமான கேஸ் தனிப்பட்டதாகவே இருக்கிறது. ஹாஷ் அட்டவணை இல்லாமல் ஓர் அடுக்கு அறிவிக்கக்கூடிய உச்சவரம்பு (2ᵗ − 1) + 2ᵗ⁻², மேலே உள்ள நெடுவரிசை. கட்டணத்தின் அடிமட்டம்
floor = BUNDLE_BASE + gas_price × declared gas limit + byte_price × ⌈bytes / 1024⌉
இங்கே BUNDLE_BASE 0.001 RAND; பைட்கள் என்பவை அழைப்பு நிரூபணமும் உள்ளீட்டு உறையும்; விலைகள் ஒரு கேஸுக்கு 100 அலகுகள், ஒரு KiB-க்கு 800 அலகுகள் எனத் தொடங்கின (ஓர் அலகு 10⁻⁹ RAND), ஒவ்வொரு தொகுதியிலும் சிறிது மாறுகின்றன. சங்கிலி 20-இல் அவை 10,000, 80,000 அலகுகளைத் தாண்டி உயர முடியாது; அழைப்புகளின் நிரூபண, உறை பைட்கள் மட்டுமே பைட் விலையை நகர்த்துகின்றன; சங்கிலிகள் 18, 19-இல் உச்சவரம்பு இல்லை. வாலட் இயல்பாக எவ்வளவு செலுத்துகிறது என்பதைப் பிரிவு 9 காட்டுகிறது; எடுத்துக்காட்டு நிரல்கள் பக்கத்தில் சங்கிலி 18-இல் அளவிடப்பட்ட நான்கு அழைப்புகள் உள்ளன, ஒவ்வொன்றும் 0.0057 முதல் 0.0075 RAND வரை.
அடுக்கு 14 என்பது ஒரு அழைப்பு பயன்படுத்தக்கூடிய மிக உயர்ந்த அடுக்கு. fullnode v0.5.6 (2026-09-25) முதல், அடுக்கு 14-க்கு மேற்பட்ட எந்த அழைப்பு நிரூபணத்தையும் ஒரு முனை சரிபார்ப்பு விசையை உருவாக்கும் முன்பே CallTierTooHigh உடன் நிராகரிக்கிறது. அத்தகைய அழைப்பைக் கொண்ட தொகுதியையும் இதே விதி செல்லாததாக்குகிறது. 2–4 GB நினைவகம் கொண்ட சரிபார்ப்பாளர்களை இந்த வரம்பு பாதுகாக்கிறது: அடுக்கு-20 சரிபார்ப்பு விசையை உருவாக்க பல நிமிடங்களும் பல ஜிகாபைட்டுகளும் தேவைப்படும். rand call அத்தகைய அழைப்பை நிரூபிக்கும் முன் நிராகரிப்பதில்லை; எனினும் chain 20-இல் அது முதலில் அடுக்கை அச்சிடுகிறது. அழைப்பதற்கு முன் rand-guest run … --tier 14 ஐ இயக்குங்கள்; ஓட்டம் பொருந்தவில்லை எனில், நிரலை மறுகட்டமைப்பு செய்யுங்கள். நிறுவுவதற்கு முன், rand program deploy --input <word> … (அல்லது உள்ளீடுகள் இல்லாத அழைப்புக்கு --check-call) நீங்கள் கருதும் அழைப்பை எமுலேட்டர் வழியாக இயக்குகிறது; அது அடுக்கு 14 அல்லது அதற்குக் கீழ் அமையாவிட்டால் நிறுவ மறுக்கிறது.
வரவுசெலவை எது செலவழிக்கிறது
எதிர்பாராத செலவு டைஜெஸ்ட் வரிசைகளும் வரிசைமாற்றங்களும்தான். உங்கள் குறியீடு இயங்குவதற்கு முன், இயந்திரம் நிரலையும், தனிப்பட்ட உள்ளீடுகளையும், பொதுப் பகுதியையும் hc, H_IN, H_PUB ஆக ஹாஷ் செய்கிறது. ஒவ்வொன்றுக்கும் நான்கு சொற்களுக்கு ஏறத்தாழ ஒரு வரிசைமாற்றமும் ஒரு வரிசையும் செலவாகிறது. அதற்கு மேல், நீங்கள் செய்யும் ஒவ்வொரு POSEIDON2 அழைப்புக்கும் ஹாஷ் செய்யப்படும் நான்கு சொற்களுக்கு ஏறத்தாழ ஒரு வரிசைமாற்றம் செலவாகிறது. அடுக்கு 10-இல் உள்ள ஏலத்திற்கு:
| உருப்படி | சொற்கள் | வரிசைமாற்றங்கள் |
|---|---|---|
நிரல் (hc) | 258 | ஏறத்தாழ 65 |
தனிப்பட்ட உள்ளீடுகள் (H_IN) | 20 | ஏறத்தாழ 5 |
பொதுப் பகுதி (H_PUB) | 34 | ஏறத்தாழ 9 |
| நான்கு கடப்பாட்டுச் சரிபார்ப்புகள், ஒவ்வொன்றும் 7 சொற்கள் | 4 × 7 | 8 |
மொத்தம், run அறிவிப்பது போல | 128-இல் 88 |
வரிசைகள்: 641 சுழற்சிகளும் டைஜெஸ்ட் வரிசைகளும் சேர்ந்து 1,023-இல் 721 ஆயின.
chain 19-இல் போலவே chain 20-இலும், பணப்பையின் சொந்தக் கணக்கு rand-guest run கணக்கை விடச் சற்று அதிகம். அங்கு ஓர் அழைப்பு நிரூபணம் அதன் பரிவர்த்தனையுடன் பிணைக்கப்பட்டுள்ளது (chain 20-இல் அதே எட்டுச் சொற்களுக்குள் பிணைப்பில் ஜெனிசிஸ் ஹாஷும் அடங்கும்), மேலும் அந்தப் பிணைப்பு பொதுப் பகுதியின் கூடுதல் எட்டுச் சொற்களாகப் பயணிக்கிறது: பொதுப் பகுதி கொண்ட நிரலுக்கு இரண்டு கூடுதல் டைஜெஸ்ட் வரிசைகளும் இரண்டு கூடுதல் வரிசைமாற்றங்களும், பொதுப் பகுதி இல்லாத நிரலுக்கு ஒவ்வொன்றிலும் ஒன்று கூடுதல்.
இதனால் நிரலின் அளவும் வரவுசெலவின் ஒரு பகுதியாகிறது. ஹீப் சோதனை நிரல் 1,183 சுழற்சிகள் மட்டுமே இயங்கியது; ஆயினும் அதன் 1,341 சொற்கள் 340 வரிசைமாற்றங்களை எடுத்து அதை அடுக்கு 12-க்குத் தள்ளின. அடுக்கு 14-இன் 2,048 வரிசைமாற்றங்களில், ஏறத்தாழ 8,000 சொற்களை விடக் கணிசமாகப் பெரிய நிரல் என்ன செய்தாலும் அதை அழைக்கவே முடியாது. chain 20-இல், பொதுப் பகுதி இல்லாத நிரலுக்கும் உள்ளீடுகள் இல்லாத அழைப்புக்கும் சரியான வரம்பு 8,180 சொற்கள்; இவற்றில் ஏதேனும் ஒன்று இருந்தால் அது குறைவு. chain 20-இல் நிரல் உச்சவரம்பு chain 15-இல் இருந்தது போலவே 65,535 சொற்கள்; ஆனால் chains 19, 20 அந்த வரம்பை மீறும் நிரலை நிறுவ மறுக்கின்றன (ProgramUncallable), அதேசமயம் chain 15 யாராலும் அழைக்க முடியாத நிரலுக்கும் நிறுவல் கட்டணத்தை வசூலித்தது. அதனால்தான் chain 13-இன் மொழிபெயர்க்கப்பட்ட ERC-20 (11,686 சொற்கள், அடுக்கு 16-இல் அழைக்கப்பட்டது) chain 20-இல் நிறுவவும் முடியாது, அழைக்கவும் முடியாது. நிரல்களைச் சிறியதாக வைத்திருங்கள்: Rust-இல் opt-level = "s", C-இல் -Os (ஏற்கெனவே அமைக்கப்பட்டுள்ளது), குறைந்த சார்புகள், தேவையில்லாவிட்டால் alloc வேண்டாம்.
ஏலம் நேர்கோட்டில் வளர்கிறது: ஒவ்வொரு கூடுதல் ஏலதாரரும் 5 உள்ளீட்டுச் சொற்கள், 8 பொதுச் சொற்கள், சரிபார்ப்புக்கு 2 வரிசைமாற்றங்கள், ஏறத்தாழ நூறு சுழற்சிகள் ஆகியவற்றைச் சேர்க்கிறார். 64 ஏலதாரர்களுடன் (சீரற்ற ஏலத்தொகைகள், 320 உள்ளீட்டுச் சொற்கள், 514 பொதுச் சொற்கள்), இரண்டு கட்டமைப்புகளும் ஒரே வெற்றியாளரையும் விலையையும் தேர்ந்தெடுக்கின்றன; இரண்டுக்கும் அடுக்கு 14 தேவைப்படுகிறது:
auction.bin tier 14: fits (cycles 6557 of 16383, Poseidon2 permutations 403 of 2048)
auction-c.bin tier 14: fits (cycles 8571 of 16383, Poseidon2 permutations 388 of 2048)
வரிசைமாற்றங்கள் அடுக்கு 12-இன் 512-க்குள் பொருந்தும், ஆனால் வரிசைகள் அதன் 4,095-க்குள் பொருந்தவில்லை. இங்கு அடுக்கைத் தீர்மானிப்பது ஹாஷிங் அல்ல, சுழற்சிகளே. 64 ஏலதாரர்களில் Rust கட்டமைப்பே வேகமானது. சுழற்சி மேலோங்கியவுடன், அதன் opt-level = 3, C கட்டமைப்பின் நிலையான -Os ஐ மிஞ்சுகிறது.
Keccak மற்றும் SHA-256
keccak, sha256_compress ஒவ்வொன்றுக்கும் ஒரு வரிசை செலவாகிறது; ஆனால் இவற்றில் ஏதேனும் ஒன்றைப் பயன்படுத்தும் நிரூபணம் ஒரு கூடுதல் அட்டவணையைச் சுமக்கிறது. aeacf31 இல் இரண்டும் ஒரு அணிக் குறிப்பை (array reference) எடுக்கின்றன: [u32; 50] மீது keccak(&mut state), [u32; 24] மீது sha256_compress(&mut buf); 7ef3220 இல் அவை ஒரு மூலச் சுட்டியை (raw pointer) எடுத்தன. v0.5.6 முதல் ஓர் அழைப்பு அதிகபட்சம் 128 Keccak-f வரிசைமாற்றங்கள் மற்றும் அதிகபட்சம் 128 SHA-256 சுருக்கங்கள் மட்டுமே பயன்படுத்தலாம். chain 20-இல் ஒரு Keccak வரிசைமாற்றத்திற்கு 192 கேஸும், ஒரு SHA-256 சுருக்கத்திற்கு 64 கேஸும் கூடுதலாகச் செலவாகின்றன.
அந்த அட்டவணை நிரூபணத்தைப் பெரிதாக்குகிறது; chain 20 ஓர் அழைப்பு நிரூபணத்தை 4,194,304 பைட்டுகளுக்கு (4 MiB, chains 17 முதல் 19 வரை இருந்தது போல; chains 13 முதல் 16 வரை உச்சவரம்பு 8 MiB) வரம்பிடுகிறது. chain 18-இல், Keccak அட்டவணையுடன் கூடிய அடுக்கு-12 அழைப்பு 3.35 MB என அளவிடப்பட்டது, இது உச்சவரம்பின் பெரும்பகுதி; SHA-256 அட்டவணையுடன் கூடிய அடுக்கு-14 அழைப்பு 1.91 MB, இரண்டும் இல்லாதபோது 1.50 MB (எடுத்துக்காட்டு நிரல்கள்). ஒவ்வொரு KiB-க்கும் பைட் விலையில் கட்டணம் விதிக்கப்படுகிறது. chain 15-இல், இலவசமான 2 MiB + 18,432-ஐத் தாண்டிய பைட்டுகளுக்கு மட்டுமே, KiB-க்கு 1,000 அலகுகள் என்ற விகிதத்தில் கட்டணம் விதிக்கப்பட்டது (கட்டணங்கள்). வெளிப்புற ஹாஷுடன் பொருந்த வேண்டிய கட்டாயம் இல்லையெனில் Poseidon2-ஐப் பயன்படுத்துங்கள்.
நிரூபிக்கத் தேவையான நினைவகமும் நேரமும்
நிரூபண நேரமும் நினைவகமும் அடுக்குடன் செங்குத்தாக உயர்கின்றன. அடுக்கு-10 அழைப்பு ஒரு மடிக்கணினியில் சில வினாடிகளில் நிரூபிக்கப்படுகிறது. chain 20-இல் ஒவ்வொரு நிறுவலும் ஒவ்வொரு அழைப்பும் தொகுப்புப் பக்க நிரூபணங்கள் இரண்டையும் சுமக்கின்றன: அடுக்கு-10 செலவு அங்கீகாரம் (சில வினாடிகள்), கட்டணத்தைச் செலுத்தும் அடுக்கு-14 தொகுப்பு (மடிக்கணினியில் ஏறத்தாழ இரண்டு நிமிடங்கள்). chain 18-இல் அளவிடப்பட்ட நான்கு அழைப்புகள் ஒவ்வொன்றும் மூன்று முதல் ஐந்தரை நிமிடங்கள் எடுத்தன; உச்ச நினைவகம் 6.1 முதல் 6.6 GB (எடுத்துக்காட்டு நிரல்கள்). chain 15-இல் தொகுப்பு ஏறத்தாழ 100 s மற்றும் ஏறத்தாழ 5.7 GB கொண்ட ஒற்றை அடுக்கு-14 நிரூபணமாக இருந்தது. அளவிடப்பட்ட எண்ணிக்கைகள் சரிபார்ப்பாளர் மற்றும் திரட்டி வன்பொருள் பக்கத்தில் உள்ளன.
8. நிறுவுதல்
testnet என்பது chain 20. நிறுவுவதற்கு fullnode v0.6.8 அல்லது அதற்குப் பிந்தைய பதிப்பின் rand பணப்பை, ஒரு விசை, சிறிது RAND ஆகியவை தேவை (அறிமுகம்; chain 19-இன் ஃபாசெட் போலவே, chain 20-இன் ஃபாசெட்டும் அதன் ஜெனிசிஸ் அனுமதிப்பட்டியலில் உள்ள 16 பணப்பைகளுக்கு மட்டுமே உருவாக்கி வழங்குகிறது). v0.6.7 பணப்பையால் chain 20-இல் அனுப்ப முடியாது: chain 20-இன் ஜெனிசிஸ் binding_domain: 1 ஐ அமைக்கிறது; எனவே ஒவ்வொரு நிரூபணப் பிணைப்பிலும் கையொப்பமிட்ட செய்தியிலும் ஜெனிசிஸ் ஹாஷ் அடங்குகிறது, அதை v0.6.7 பணப்பை சேர்ப்பதில்லை. பணப்பையை ஒத்திசைக்கவும், நிறுவவும், அழைக்கவும் பொது இறுதிப்புள்ளி https://rpc.randprotocol.org போதுமானது (அமைப்பு). ஏலம் அதன் பொதுப் பகுதியுடன் நிறுவப்படுகிறது:
rand fee deploy 258 --public-words 34 # 0.001 + 0.0001 × (258 + 34) = 0.0302 RAND
rand program deploy auction.bin --public auction-public.txt
program deploy நிரல் அடையாளம், hc, சொல் எண்ணிக்கை, பொது உள்ளீட்டின் சொல் எண்ணிக்கை மற்றும் டைஜெஸ்ட் ஆகியவற்றை அச்சிடுகிறது. எதையும் நிரூபிக்கும் முன், அது நிரலைச் சங்கிலியின் உச்சவரம்புடனும், பொது உள்ளீட்டை max_program_public_words (chain 20-இல் 32,768) உடனும் சரிபார்க்கிறது. பின்னர் கட்டணத்தைச் செலுத்தும் பூஜ்ஜிய-மதிப்புச் சுய-பரிமாற்றத் தொகுப்பை நிரூபித்து, சமர்ப்பித்து, உறுதிசெய்தலுக்காகக் காத்திருக்கிறது. chain 17 முதல் இருப்பது போலவே chain 20-இலும் அது இரண்டு நிரூபணங்கள், ஒவ்வொன்றுக்கும் தனி வெளியீட்டு வரி: அடுக்கு-10 செலவு அங்கீகாரம் (சில வினாடிகள், ஏறத்தாழ 1.37 MB), அடுக்கு-14 தொகுப்பு (ஏறத்தாழ இரண்டு நிமிடங்கள், ஏறத்தாழ 1.5 MB). chain 15-இல் அது ஏறத்தாழ 100 s மற்றும் ஏறத்தாழ 1.42 MB கொண்ட ஒற்றை அடுக்கு-14 நிரூபணம். நிறுவல் கட்டணத்தில் கேஸ் கூறு இல்லை. ஏலம் chains 18 முதல் 20 வரை நிறுவப்படவில்லை; பொதுப் பகுதியுடன் கூடிய நிறுவலைப் பணப்பை அச்சிட்டபடியே chain 18-இல் ஒரு அநாமதேய வாக்கெடுப்பு காட்டுகிறது.
--public உடன் நிரல் அடையாளம் மாறுகிறது. குறியீட்டுக்கு மட்டும் rand-guest 148ab0c4…2c73 ஐ அச்சிட்டது. பொதுப் பகுதியுடன் கூடிய நிறுவல் blake3("rand-program-2", base_pc ‖ len ‖ words ‖ len ‖ public) என்பதன் கீழ் சேமிக்கப்படுகிறது; இது இருப்பு விலையையும் நான்கு கடப்பாடுகளையும் சேர்த்துப் பிணைக்கிறது. program deploy அச்சிடும் அடையாளத்தையே பயன்படுத்துங்கள். அதே குறியீட்டையும் வேறுபட்ட கடப்பாடுகளையும் கொண்ட இரண்டாவது ஏலம் வேறொரு நிரல் அடையாளமாகும்.
rand program show <auction id> # base_pc, words_len, code_hash, deployed_at, public_words_len, public_digest
code_hash என்பது rand-guest அச்சிட்ட hc தான், வேறு வடிவில் எழுதப்பட்டது. rand-guest டைஜெஸ்டின் எட்டுச் சொற்களில் ஒவ்வொன்றையும் big-endian வடிவில் அச்சிடுகிறது; பணப்பை, rand program show, rand_getProgram ஆகியவை ஒவ்வொரு சொல்லின் பைட்டுகளையும் little-endian வடிவில் அச்சிடுகின்றன; எனவே எட்டு ஹெக்ஸ் இலக்கங்கள் கொண்ட ஒவ்வொரு குழுவும் பைட் வாரியாகத் தலைகீழாக்கப்படுகிறது. மேலே உள்ள கட்டமைப்புகளில், aa04e4c4…050d (Rust) என்பது c4e404aa…4f16 ஆகவும், 68605aa8…bea0 (C) என்பது a85a6068…b69a ஆகவும் தோன்றுகின்றன.
9. அழைத்தல்
விற்பனையாளர் 20 தனிப்பட்ட சொற்களுடனும் அழைக்கிறார்:
rand call <auction id> --expect-public auction-public.txt \
--input 400 --input 2654435769 --input 2135587861 --input 4087136352 --input 1559071514 \
--input 250 --input 461845907 --input 3432918353 --input 3864292196 --input 2246822507 \
--input 900 --input 3266489909 --input 668265263 --input 374761393 --input 3550635116 \
--input 300 --input 4252018373 --input 3042594569 --input 1759714724 --input 625341585
பணப்பை நிரலின் குறியீட்டையும் பொதுப் பகுதியையும் பெற்று, அவை அடையாளத்துக்கு ஹாஷ் ஆகின்றனவா எனச் சரிபார்க்கிறது. பொதுப் பகுதி அந்தக் கோப்பின் சொற்களாக இல்லாவிட்டால், --expect-public நிரூபிப்பதற்கு முன்பே மறுக்கிறது. பின்னர் பணப்பை அழைப்பை எமுலேட்டரில் இயக்கி, சரியான கேஸ், அது அறிவிக்கவிருக்கும் வரம்பு, அடுக்கு (ஓட்டம் பொருந்தும் மிகச் சிறிய அடுக்கு, இங்கு அடுக்கு 10), கட்டணம் ஆகியவற்றை அச்சிடுகிறது:
gas: <exact> (declaring <limit>, tier <t>)
fee <amount> RAND (incl. two price steps of headroom)
அது 20 உள்ளீட்டுச் சொற்களையும் அழைப்பவர் மட்டுமே திறக்கக்கூடிய ஓர் உறையில் முத்திரையிட்டு, ஓட்டத்தை உள்ளூரில் நிரூபித்து, ஒரு தொகுப்பின் வழியாகக் கட்டணத்தைச் செலுத்தி, சமர்ப்பித்து, காத்திருந்து, ரசீதை அச்சிடுகிறது. chain 20-இல் அது மூன்று நிரூபணங்கள்: அழைப்பு, அடுக்கு-10 செலவு அங்கீகாரம், அடுக்கு-14 தொகுப்பு.
அழைப்பின் செலவு. chain 15-இல் இந்த அழைப்பு 0.001 + call_fee(10) = 0.002 RAND செலுத்தியது. chain 20-இல் பணப்பை பிரிவு 7-இன் குறைந்தபட்சக் கட்டணத்தைச் செலுத்துகிறது; அது நிரூபணம் உருவாவதற்கு முன்பே, மூன்று இயல்புநிலை மதிப்புகளுடன் கணக்கிடப்படுகிறது:
- அறிவிக்கப்பட்ட வரம்பு என்பது துல்லியமான gas அளவை
2^(tier − 2)-இன் மடங்கிற்கு மேல்நோக்கி முழுமையாக்கிய மதிப்பு: அடுக்கு 10-இல் 256, அடுக்கு 12-இல் 1,024, அடுக்கு 14-இல் 4,096.--gas-limit maxஅந்த அடுக்கின் உச்சவரம்பை அறிவிக்கிறது;--gas-limit Nஒரு துல்லியமான எண்ணை அறிவிக்கிறது; - நிரூபணத்தின் விலை அதன் உண்மையான அளவின் அடிப்படையில் அல்லாமல், சங்கிலியின் உச்சவரம்பான 4,194,304 பைட்டுகளின் அடிப்படையில் கணக்கிடப்படுகிறது; ஏனெனில் chain 20-இல் ஓர் அழைப்பு நிரூபணம் அதன் பரிவர்த்தனையுடன் பிணைக்கப்பட்டுள்ளது, எனவே கட்டணம் முதலிலேயே நிர்ணயிக்கப்பட வேண்டும்;
- இரண்டு விலைப் படிகளுக்கான இடைவெளி, அதாவது 1.125² காரணி; ஏனெனில் விலை கணக்கிடப்பட்ட பின் இரண்டு அல்லது மூன்று தொகுதிகள் கழித்தே அழைப்பு சங்கிலியில் சேர்கிறது.
--fee இயல்புநிலை மதிப்பை மீறுகிறது; rand fee call <tier> --gas <limit> --bytes <B> குறைந்தபட்சக் கட்டணத்தை நேரடியாக node-இடம் கேட்கிறது. chain 18 முதல் 20 வரை ஏல நிரலின் அழைப்பு இதுவரை மேற்கொள்ளப்படவில்லை; எனவே அதன் gas வரியும் கட்டணமும் இங்கு காட்டப்படவில்லை. ஓர் அநாமதேய வாக்கெடுப்பு பக்கத்தில், chain 18-இல் மேற்கொள்ளப்பட்ட ஒரு முழுமையான அழைப்பு வாலட் அச்சிட்டபடியே உள்ளது; அதன் கட்டணம் 0.0062 RAND.
ரசீதில் அடுக்கு, H_IN, H_PUB மற்றும் வெளியீடுகள் [1, 2, 400, 4, 0, 0, 0, 0] இடம்பெறுகின்றன. இவை எமுலேட்டர் அச்சிட்ட அதே சொற்கள்; ஏனெனில் நிரூபணம் அதே இயக்கத்தைப் பற்றியது. நான்கு ஏலத்தொகைகளும் சால்ட்களும் சங்கிலியில் இல்லை. --auditor <rand1…> உள்ளீடுகளைப் பெயரிடப்பட்ட ஒரு தணிக்கையாளருக்கும் முத்திரையிட்டு வழங்குகிறது; --no-envelope எந்தப் பதிவேட்டையும் வெளியிடுவதில்லை, இதைப் பின்னர் மாற்ற இயலாது (நிரல்கள்).
10. முடிவைச் சரிபார்த்தல்
ஏலம் கேட்பவரோ வேறு எவருமோ விற்பனையாளரை நம்பாமலேயே ஏலத்தைச் சரிபார்க்கலாம்:
- குறியீடு. வெளியிடப்பட்ட மூலக் குறியீட்டை அதே circuits கமிட்டில், Rust 1.98.1 (அல்லது clang 23.1.1) கொண்டு
rand-guest buildமூலம் மீண்டும் உருவாக்குங்கள்.hc-ஐrand program showஅல்லதுrand_getProgramதரும்code_hash-உடன் ஒப்பிடுங்கள்; பைட் வரிசை தலைகீழான எழுத்துமுறையையும் கணக்கில் கொள்ளுங்கள் (பிரிவு 8). உருவாக்கம் மீளுருவாக்கக்கூடியது; எனவே எந்தக் கணினியிலும் இரண்டும் பொருந்தும். - பொதுப் பிரிவு. அதை
rand_getProgramPublicமூலம் பெறுங்கள், அல்லதுrand call --expect-publicஇயக்குங்கள். உங்கள் உறுதிப்பாடு உங்கள் குறியீட்டெண்ணில் உள்ளதா எனச் சரிபாருங்கள். - ரசீது.
rand receipt <tx hash>அல்லதுrand_getReceipt: நிலை1, வெற்றியாளரும் விலையும், இடம் 70xdeadbeefஅல்ல, மேலும்programஏல நிரலின் id-க்குச் சமம். - உள்ளீடுகள், அவற்றைப் பெற உங்களுக்கு உரிமை இருந்தால். விற்பனையாளரின்
rand open-call <tx hash>(அல்லது தணிக்கையாளரின்--as-auditor) முத்திரையிடப்பட்ட உள்ளீடுகளைத் திறந்து, அவற்றைH_IN-உடன் சரிபார்த்து, நிரலை மீண்டும் இயக்குகிறது; ஏதேனும் பொருத்தமின்மை இருந்தால் பூஜ்யமல்லாத நிலைக் குறியீட்டுடன் வெளியேறுகிறது. v0.6.8 வாலட்டைப் பயன்படுத்துங்கள்: v0.6.8 முதல் மறு இயக்கம் நிரலின் பொதுப் பிரிவு மற்றும் அழைப்புப் பிணைப்பின் மீது நடைபெறுவதால், அது ஏல நிரலுக்கும் செயல்படுகிறது (fullnode issue #116). v0.6.7-இல், பொதுப் பிரிவுடன் பயன்படுத்தப்பட்ட எந்த நிரலுக்கும்open-callre-running the program on these inputs failed: PublicIndex(0)என்ற பிழையுடன் நின்றது.
உறுதியளிக்கப்பட்ட ஏலத்தொகைகளின் திறப்புகளுக்கு விதி பயன்படுத்தப்பட்டது என்பதற்கு நிரூபணம் உத்தரவாதம் அளிக்கிறது. அது பணத்தை நகர்த்துவதில்லை. வெற்றியாளர் சாதாரண rand send மூலம் விற்பனையாளருக்குச் செலுத்துகிறார்; இரு தரப்பினரும் சான்றாகச் சுட்டுவது ரசீதையே.
சிக்கல் தீர்வு
| அறிகுறி | காரணமும் தீர்வும் |
|---|---|
பழைய கமிட்டுக்காக எழுதப்பட்ட poseidon2(…), keccak(…) அல்லது sha256_compress(…) அழைப்பில் உருவாக்கம் தோல்வியடைகிறது | aeacf31-இல் poseidon2 ஒரு unsafe fn; மற்ற இரண்டும் &mut [u32; 50] மற்றும் &mut [u32; 24] ஏற்கின்றன (பிரிவுகள் 3 மற்றும் 7) |
check a7 = 7 உடன் Syscall எனத் தெரிவிக்கிறது | விருந்தினர் நிரல் poseidon2_len-ஐ அழைக்கிறது; aeacf31-இல் உள்ள rand-guest check கணினி அழைப்பு 7-ஐப் பட்டியலிடுவதில்லை (zkp-circuits issue #1) |
check 0xc0001073-இல் Csr எனத் தெரிவிக்கிறது | நூலகக் குறியீடு unimp ஆகத் தொகுக்கப்பட்டுள்ளது; llvm-objdump மூலம் அந்தச் செயல்கூற்றைக் கண்டறிந்து அழைப்பை மாற்றுங்கள் (பிரிவு 6) |
இயக்கம் எந்த அடுக்கிலும் பொருந்தவில்லை, அல்லது அடுக்கு 14-ஐ விட அதிகம் தேவை என run கூறுகிறது | வரிசைகள் அல்லது Poseidon2 வரிசைமாற்றங்கள் மிக அதிகம்; நிரலைச் சுருக்குங்கள், குறைவாக hash செய்யுங்கள், அல்லது பணியைப் பல அழைப்புகளாகப் பிரித்து, அவற்றுக்கிடையே ஒரு டைஜெஸ்ட்டைக் கடத்துங்கள் |
| இடம் 7 = 3735928559 | Rust விருந்தினர் நிரல் panic ஆனது; அதற்கு முந்தைய வெளியீடுகள் நம்பகமானவை அல்ல |
trap: DoubleWrite(n) | வெளியீட்டு இடம் n இருமுறை எழுதப்பட்டது; ஒவ்வொரு வெளியேற்றத்தையும் ஒரே செயல்கூற்றின் வழியாகச் செலுத்துங்கள் |
trap: InputIndex(i) | அழைப்பாளர் வழங்காத ஒரு தனிப்பட்ட உள்ளீட்டை நிரல் படித்தது; முதலில் எண்ணிக்கையைப் படித்துச் சரிபாருங்கள் |
ஏற்றுதல் அல்லது சேமித்தலில் trap: … | சீரமைக்கப்படாத அல்லது வரம்புக்கு அப்பாற்பட்ட முகவரி; C-இல், அணியின் எல்லையைத் தாண்டிய குறியீட்டெண் |
invalid value '0x…' for '--input' | கட்டளை வரியில் உள்ளீட்டுச் சொற்கள் தசம எண்களாக இருக்க வேண்டும் |
ஓர் அழைப்பு CallTierTooHigh என மறுக்கப்படுகிறது | நிரூபணம் அடுக்கு 14-க்கு மேல் உள்ளது; அழைப்பதற்கு முன் rand-guest run --tier 14 மூலம் சரிபாருங்கள் |
மீண்டும் உருவாக்கிய hc பயன்படுத்தப்பட்டதிலிருந்து வேறுபடுகிறது | வேறுபட்ட circuits கமிட், கருவித்தொகுப்பு அல்லது சார்புப் பதிப்புகள்; மூன்றையும் நிலைப்படுத்தி Cargo.lock-ஐ கமிட் செய்யுங்கள். எழுத்துமுறை மட்டும் வேறுபட்டால், எட்டு ஹெக்ஸ் இலக்கங்கள் கொண்ட ஒவ்வொரு குழுவும் பைட் வரிசையில் தலைகீழாக இருக்கும் (பிரிவு 8) |
rand open-call PublicIndex(0) உடன் நிற்கிறது | நிரலுக்குப் பொதுப் பிரிவு உள்ளது, வாலட் v0.6.7; அதன் மறு இயக்கம் எதையும் அனுப்புவதில்லை (fullnode issue #116); v0.6.8-ஐப் பயன்படுத்துங்கள் |
… is not inside a circuits checkout | விருந்தினர் நிரல் கோப்பகத்தை checkout-க்குள் நகர்த்துங்கள் (Rust நிரலைப் பயன்படுத்துதல்) |