evm2rv يأخذ شيفرة EVM البايتية الخاصة بوقت التشغيل، أي ناتج solc --bin-runtime، ويحوّلها إلى برنامج Rand. يكتب الأداة شيفرة C، ثم يُصرّف rand-guest build هذه الشيفرة إلى صورة RV32IM. تأخذ الصورة متجه الإدخال نفسه الذي يأخذه ضيف مفسّر EVM في Rand، أي evm.bin، وتنشر كلمات الإخراج الثماني نفسها. وهي تشغّل العقد أصلياً بدلاً من تفسيره شيفرة تشغيل بعد أخرى. تعرض هذه الصفحة المسار كاملاً على عقد ERC-20.
ما هو
| المُدخل | شيفرة EVM البايتية الخاصة بـوقت التشغيل، نصاً سداسياً عشرياً (.hex) أو بايتات خام |
| المُخرج | حزمة C وسيطة (shim crate)؛ ويحوّلها rand-guest build إلى حاوية صورة |
| مكان التشغيل | خارج السلسلة، على جهاز المطوّر؛ ولا ترى السلسلة سوى الصورة |
| ما يجب أن يطابقه | حالة evm.bin وكلمات الإخراج الثماني وgas_used |
| المستودع | evm2rv/ في مستودع الدارات |
| سلسلة الأدوات المثبّتة | Rust 1.98.1 وclang 23.1.1 وحزمة cc بالإصدار 1.4.6 |
يأخذ المترجم شيفرة وقت التشغيل لا شيفرة الإنشاء. فالبرهان يغطي استدعاءً واحداً لعقد منشور، ولذلك لا يعمل المُنشئ أبداً. وتصبح الحالة التي كان المُنشئ سيكتبها جزءاً من الحالة السابقة، في صورة شواهد تخزين.
هناك مرحلتا ترجمة. تعطي كلتاهما النتائج نفسها والغاز نفسه؛ ولكل منهما برنامجها الخاص وhc الخاص بها.
| المرحلة | الراية | ما تفعله |
|---|---|---|
| الأولى | --stage 1 | كل شيفرة تشغيل فوق مكدّس في الذاكرة |
| الثانية | --stage 2، وهي الافتراضية | كلمات المكدّس لكل كتلة في متغيرات C محلية، والثوابت تُطوى عند الترجمة |
متجه الإدخال هو متجه المفسّر: الشيفرة، وبيانات الاستدعاء، والمُستدعي وكلمات البيئة الأخرى، وحدّ الغاز، وجذر الحالة السابقة، وشاهد تخزين واحد لكل خانة يلمسها الاستدعاء. أما المخرجات فهي out[0]، أي الحالة (1 نجاح، 0 تراجع، 2 توقف استثنائي)، وout[1..8]، أي ملخّص EVM_OUT على تجزئة الشيفرة وجذري الحالة وبيانات الإرجاع والسجلات.
نموذج الثقة
يتحقق المُتحقِّق من العقد المترجَم في خطوتين.
hc == translate(bytecode). أعد تشغيلevm2rvعلى الشيفرة البايتية المنشورة بالقيمتين نفسيهما لـ--stageو--chain-id، ثم أعد البناء بسلسلة الأدوات المثبّتة وقارنhc. تثبّت الحزمة المولَّدةccبدقة وتحمل ملفCargo.lockخاصاً بها.- حارس الشيفرة يربط
hcبالشيفرة البايتية. المنطق المترجَم مُصرَّف داخل الصورة، لكنCODECOPYوCODESIZEتقرآن الشيفرة من متجه الإدخال. وبلا فحص، يمكن تشغيلhcواحد مع بايتات شيفرة يختارها المُستدعي. لذلك يحملcontract.cملخّص Poseidon2 للشيفرة البايتية المصدر (طولها وبايتاتها)، ويحسب الـshim ملخّصاً للشيفرة الموجودة في متجه الإدخال بالطريقة نفسها قبل تشغيل أي شيفرة مترجمة. وتُرفض أي شيفرة أخرى: الحالة 2، وgas_usedيساوي 0، والتوقفOutOfBounds.
كما يربط ملخّص EVM_OUT قيمة keccak256 للشيفرة، كما يفعل ملخّص المفسّر. ولا تسجّل السلسلة الشيفرة البايتية المصدر ولا تجزئتها. وليتمكن الآخرون من التحقق من hc، انشر الشيفرة البايتية، أو شيفرة Solidity المصدر مع إصدار solc الدقيق.
يكلّف الحارس 1,008 دورة في عملية التحويل. وتُرفض شيفرة تختلف عن المصدر ببايت واحد في 30,418 دورة في المرحلة الثانية (الطبقة 16).
التغطية، وما يؤدي إلى الإيقاف
شيفرات التشغيل. مجموعة Shanghai. صرّف باستخدام --evm-version shanghai: فالأهداف الأحدث تُصدر MCOPY وشيفرات Cancun الأخرى، وهذه تؤدي إلى إيقاف.
شيفرات البيئة:
| شيفرة التشغيل | الترجمة |
|---|---|
ADDRESS وCALLER وCALLVALUE وCALLDATASIZE وCODESIZE | من متجه الإدخال، كما يقرؤها المفسّر |
CHAINID | قيمة --chain-id، مدمجة عند الترجمة، ولذلك يربطها hc؛ وهي مطلوبة حين تحتوي الشيفرة على CHAINID |
ORIGIN | تساوي CALLER (استدعاء واحد، بلا مرحِّل) |
GASPRICE وCOINBASE وTIMESTAMP وNUMBER وPREVRANDAO وGASLIMIT وSELFBALANCE وBASEFEE وBLOCKHASH | تؤدي إلى إيقاف (الحالة 2)، كما في المفسّر |
تؤدي شيفرات سياق الكتلة التسع إلى إيقاف إلى أن يوجد تصميم لربطها بكتلة. فالإدخال الخاص لا يستطيع حمل واقعة عن الكتلة، لأن المُتحقِّق لا يستطيع فتح H_IN. وإلى أن يُتخذ هذا القرار، فإن العقد الذي يقرأ الوقت أو رقم الكتلة (مهلة إذن، مثلاً) يتوقف.
الاستدعاءات. تشغّل CALL وCALLCODE وDELEGATECALL وSTATICCALL عقداً مُسبقاً (precompile) حين يكون الهدف هو العنوان من 1 إلى 9. وأي هدف آخر يؤدي إلى إيقاف. وأي قيمة غير صفرية في CALL أو CALLCODE تؤدي إلى إيقاف: فلا يوجد نموذج للأرصدة.
العقود المُسبقة. تعمل التسعة كلها برمجياً. وبعضها أبطأ من أن يُبرهَن عليه اليوم، لأن البرهان يتسع لـ2²⁰ صفاً على الأكثر:
| العقد المُسبق | المتجه | الدورات | يتسع في 2²⁰ |
|---|---|---|---|
| 1 ecrecover | ValidKey | 14,510,525 | لا |
| 2 sha256 | ”abc” / 200 بايت | 2,791 / 5,289 | نعم |
| 3 ripemd160 | ”abc” | 12,195 | نعم |
| 4 identity | 100 بايت | 4,498 | نعم |
| 5 modexp | nagydani-1-square / -1-pow0x10001 | 122,332 / 874,548 | نعم |
| 5 modexp | eip_example1 (256 بت) | 11,170,118 | لا |
| 5 modexp | nagydani-5-pow0x10001 (1,024 بايت) | 55,076,950 | لا |
| 6 bn256 add | chfast1 | 978,262 | نعم، بالكاد |
| 7 bn256 mul | chfast1 | 3,060,669 | لا |
| 8 bn256 pairing | زوج واحد / زوجان | 1,853,656,212 / 2,019,000,469 | لا |
| 9 blake2f | 12 جولة | 14,493 | نعم، حتى نحو 1,800 جولة |
أساس modexp ومقياسها (modulus) محدودان بـ1,024 بايت لكل منهما.
الفروق المقبولة. يجب أن تتطابق الحالة والكلمات الثماني وgas_used. وهناك ثلاثة فروق مقبولة: قد يختلف نوع التوقف (يُحتسب الغاز الثابت عند رأس كل كتلة، ولذلك قد يتبادل OutOfGas وتوقف آخر موضعهما؛ وكلاهما الحالة 2 مع استهلاك كل الغاز)؛ وتنفّذ الترجمة CHAINID وORIGIN واستدعاءات العقود المُسبقة، وهي أمور يوقف المفسّر عندها؛ ويرفض حارس الشيفرة أي شيفرة غير مصدره.
الأرقام
استدعاءات ERC-20، مع تضمين حارس الشيفرة. الدورات من rand-guest run؛ والطبقة بين قوسين.
| الاستدعاء | المفسّر (evm.bin) | المرحلة الأولى | المرحلة الثانية (الافتراضية) |
|---|---|---|---|
transfer(BOB, 250) | 121,638 (18) | 80,211 (18) | 66,235 (18) |
approve(BOB, 5) | 85,645 (18) | 56,261 (16) | 48,119 (16) |
transferFrom(ALICE, BOB, 100) | 161,434 (18) | 110,074 (18) | 88,824 (18) |
| البرنامج | الكلمات | hc |
|---|---|---|
evm.bin، المفسّر | 18,009 | 7e1aea2b…854c08 |
| ERC-20، المرحلة الأولى | 15,804 | 9cdb79e7…2fd048c8 |
| ERC-20، المرحلة الثانية | 11,686 | a0feae92a7311c9562495717100eb7aea71270a38ed435d06dc31387e0ea8ff6 |
تشغّل المرحلة الثانية الاستدعاءات الثلاثة في 54.5% و56.2% و55.0% من دورات المفسّر. ويبقى التحويل في الطبقة 18: فدوراته البالغة 66,235 مع 3,155 صفاً للملخّص تساوي 69,390 صفاً، أي أكثر بـ3,855 من 65,535 في الطبقة 16.
نحو 60% من تحويل المرحلة الثانية (نحو 39,928 دورة) هو الأساس المشترك بين الصورتين: فك ترميز الإدخال، والتحقق من شواهد التخزين، واستدعاءات keccak256 الخاصة بواجهة ABI، وملخّص الإخراج. ولا يخفض عمل الترجمة التكلفة عن هذا الحد الأدنى.
شرح تطبيقي: عقد ERC-20، من Solidity إلى مخرجات متطابقة
يُشغَّل كل أمر من جذر نسخة من مستودع الدارات عند 7ef3220، مع سلسلة الأدوات من انشر برنامج Rust وclang 23.1.1 من انشر برنامج RISC-V. والمخرجات الطويلة مقتطعة حيث وُضعت العلامة ….
0. ابنِ الأدوات
(cd evm2rv && cargo +1.98.1 build --release)
(cd rand-guest && cargo +1.98.1 build --release)
1. صرّف Solidity إلى شيفرة بايتية لوقت التشغيل
العقد هو الملف المودَع guests-compiled/evm/contracts/ERC20.sol: عقد ERC-20 قائم بذاته بتخطيط تخزين OpenZeppelin v4، مع pragma solidity 0.8.37. استخدم solc 0.8.37 تحديداً؛ فأي إصدار آخر يحسّن بطريقة مختلفة ويعطي شيفرة بايتية مختلفة.
| الإصدار | v0.8.37 من github.com/ethereum/solidity/releases |
| ملف macOS | solc-macos، وقيمة sha256 هي a27396e7732aa52e80ff89ad7bd8a2e46fec2a6dcc4ef20cd16e5e0c502d6821 |
| ملف Linux | solc-static-linux، من الإصدار نفسه |
$ curl -sSL -o solc https://github.com/ethereum/solidity/releases/download/v0.8.37/solc-macos
$ shasum -a 256 solc
a27396e7732aa52e80ff89ad7bd8a2e46fec2a6dcc4ef20cd16e5e0c502d6821 solc
$ chmod +x solc && ./solc --version
solc, the solidity compiler commandline interface
Version: 0.8.37+commit.f401782d.Darwin.appleclang
$ (cd guests-compiled/evm && ../../solc --optimize --optimize-runs 200 --evm-version shanghai \
--bin-runtime contracts/ERC20.sol) | tee solc.out
======= contracts/ERC20.sol:ERC20 =======
Binary of the runtime part:
608060405234801561000f575f5ffd5b5060043610610060575f3560e01c8063095ea7b31461006457806318160ddd1461008c57806323b872dd1461…
$ tail -1 solc.out > evm2rv/target/mytoken.hex
السطر الأخير هو الشيفرة البايتية لوقت التشغيل، وطولها 1,296 بايت. وهي مطابقة بايتاً ببايت للملف المودَع guests-compiled/evm/contracts/erc20.runtime.hex؛ والأمر SOLC=$PWD/solc bash guests-compiled/evm/contracts/build.sh يتحقق من ذلك ويطبع contracts: erc20.runtime.hex reproduces.
الرايات مهمة:
--bin-runtime: الشيفرة المنشورة، لا شيفرة الإنشاء.--evm-version shanghai: الهدف الافتراضي في 0.8.37 يُصدرMCOPY، وهي تؤدي إلى إيقاف.--optimize --optimize-runs 200: ملف تحسين للعقود المنشورة.
2. ترجم
$ evm2rv/target/release/evm2rv evm2rv/target/mytoken.hex --out evm2rv/target/mytoken --chain-id 12
1296 code bytes: 74 blocks, 798 opcodes, 51 jumpdests (stage 2)
CHAINID is the constant 12
no trapping opcodes present
wrote evm2rv/target/mytoken (crate mytoken): contract.c, Cargo.toml, Cargo.lock, build.rs, src/main.rs, shim.ld
- يجب أن يكون
--outداخل نسخة من مستودع الدارات. وبدونه يكتفيevm2rvبتحليل الشيفرة. - أي شيفرة تشغيل تؤدي إلى إيقاف ستُدرج هنا في صورة تحذير مع قيمة pc الخاصة بها.
- التُقط هذا الجلسة باستخدام
--chain-id 12. لا يحتوي عقد ERC-20 هذا علىCHAINID، ولذلك لا يغيّر--chain-idقيمةhcله. أما العقد الذي يقرأCHAINIDفيتطلب الراية؛ اضبطها على السلسلة التي ستنشر عليها (--chain-id 19للسلسلة الحية).
ينتهي contract.c بملخّص حارس الشيفرة:
const uint32_t *evm_code_digest(void) {
static const uint32_t d[8] = {0xf679280fu, 0x86c10e83u, 0x7e8f1f39u, 0xa2377de3u, 0x8a2e282fu, 0xc54cad42u, 0xddfaf009u, 0x7d28a8afu};
return d;
}
3. ابنِ الصورة
الحد الافتراضي هو 4,096 كلمة، لذا مرّر --max-words 65535.
$ rand-guest/target/release/rand-guest build evm2rv/target/mytoken --max-words 65535
…
11686 words against a cap of 65535 (fits); 0 ecall(s) with a non-static a7
OK
wrote evm2rv/target/mytoken/image.bin and its .sha256 (11686 words, hc a0feae92a7311c9562495717100eb7aea71270a38ed435d06dc31387e0ea8ff6, program id f074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d)
$ rand-guest/target/release/rand-guest info evm2rv/target/mytoken/image.bin
form: image container
text 11147 words at 0x10000; data 408 words (205 non-zero) at 0x1ae2c; prologue 539 words; program 11686 words from base_pc 0xf794
hc a0feae92a7311c9562495717100eb7aea71270a38ed435d06dc31387e0ea8ff6
program id f074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d
11686 words against a cap of 4096: does not fit
هذه هي قيمة hc المنشورة للمرحلة الثانية. واسم الحزمة لا يؤثر فيها.
4. ابنِ متجه إدخال وشغّل عملية تحويل
يطبع المثال erc20_vector متجهات اختبار التكافؤ في صورة كلمات إدخال: transfer (ترسل ALICE إلى BOB مبلغ 250 من أصل 1,000 لديها)، وapprove (تسمح ALICE لـBOB بإنفاق 5)، وtransferFrom (ينقل BOB مبلغ 100 من 1,000 تخص ALICE مقابل مخصَّص قدره 300). ولعقدك الخاص، ابنِ EvmCall بالطريقة نفسها في Rust؛ والمثال هو القالب.
$ (cd evm2rv && cargo +1.98.1 run -q --release --example erc20_vector -- transfer > target/transfer.words)
921 input words
$ rand-guest/target/release/rand-guest run evm2rv/target/mytoken/image.bin --input $(cat evm2rv/target/transfer.words)
out[0] = 1
out[1] = 513227413
out[2] = 3087537901
out[3] = 995619457
out[4] = 4004100029
out[5] = 234390638
out[6] = 3262201797
out[7] = 3842361427
cycles 66235
tier 18
5. قارن بالمفسّر
الإدخال نفسه على ضيف المفسّر:
$ rand-guest/target/release/rand-guest run guests-compiled/bin/evm.bin --input $(cat evm2rv/target/transfer.words)
out[0] = 1
out[1] = 513227413
out[2] = 3087537901
out[3] = 995619457
out[4] = 4004100029
out[5] = 234390638
out[6] = 3262201797
out[7] = 3842361427
cycles 121638
tier 18
والمفسِّر مُشغَّلًا أصليًا على المضيف، وهو المرجع الذي تُقارَن به نتائج الاختبارات:
$ (cd evm2rv && cargo +1.98.1 run -q --release --example erc20_vector -- transfer --expected)
out[0] = 1
out[1] = 513227413
…
out[7] = 3842361427
interpreter (native): status 1, Return, gas_used 29956
الفحص في أمر واحد:
$ diff <(rand-guest/target/release/rand-guest run evm2rv/target/mytoken/image.bin --input $(cat evm2rv/target/transfer.words) | grep '^out') \
<(rand-guest/target/release/rand-guest run guests-compiled/bin/evm.bin --input $(cat evm2rv/target/transfer.words) | grep '^out') \
&& echo "the eight words are identical"
the eight words are identical
كرِّر الخطوتين 4 و5 مع approve وtransferFrom؛ فكلتاهما تعطيان الكلمات نفسها. يشغّل الأمر cd evm2rv && cargo +1.98.1 test --release هذه الحالات وخمس متجهات أخرى في كلتا المرحلتين، ويتحقق أيضًا من gas_used (70 اختبارًا، إضافة إلى إثباتين متجاهَلين).
| المُترجَم (المرحلة الثانية) | المفسِّر (evm.bin) | |
|---|---|---|
| كلمات المخرجات الثماني | متطابقة | متطابقة |
| الدورات، transfer | 66,235 | 121,638 |
| المستوى | 18 | 18 |
| كلمات البرنامج | 11,686 | 18,009 |
6. النشر
rand program deploy evm2rv/target/mytoken/image.bin
تطبع المحفظة معرّف البرنامج وعدد الكلمات وhc، ثم تتحقق من حدّ السلسلة قبل أن تُنتج أي إثبات. تبلغ الصورة 11,686 كلمة، فتحتاج إلى سلسلة يضبط genesis فيها max_program_words على 11,686 على الأقل. كانت السلسلة 12 تعمل بالقيمة الافتراضية 4,096، فرُفض النشر عليها. أما السلسلة 13، سلسلة الإصدار v0.4، فقد ضبطت max_program_words على 65,535، وتحتفظ كل سلسلة بعدها بهذه القيمة. وتحتفظ السلسلة 20، وهي السلسلة الحية (genesis 6210cf071a390d7ac61d8cbea5dd9d139d1a493a862b54a45a498f36af2d5135)، بحدود الكتلة ومغلف الاستدعاء والمدخلات العامة نفسها التي وضعتها السلسلة 13، وتخفّض حدّ حجم الإثبات إلى النصف، أي 4 MiB (4,194,304 بايت، منذ السلسلة 17؛ وكانت السلاسل من 13 إلى 16 تضبطه على 8 MiB). ولم يعد حدّ الكلمات البوابة الوحيدة. فـ genesis السلسلة 20 يضبط hardening_v6، وبموجبه يكون نشر برنامج يزيد عدد كلماته على ما يتّسع له استدعاء عند حدّ الاستدعاء للمستوى 14 نشرًا غير صالح (ProgramUncallable): أي 8,180 كلمة على الأكثر دون مدخلات عامة. وهذه الصورة 11,686 كلمة، فترفض السلسلة 20 نشرها، وترفض الاستدعاءات أيضًا: إذ يُثبَت كل استدعاء لعقد ERC-20 عند المستوى 16 أو 18، أي فوق حدّ الاستدعاء للمستوى 14 (الخطوة 7). تجميع الكتل (block aggregation) معطّل في السلسلة 20 (فلا قسم aggregation في genesis الخاص بها)؛ وعُقد الإقلاع فيها مذكورة في تشغيل validator. رسوم النشر هي 0.001 + 0.0001 × 11,686 = 1.1696 RAND، وهي الرسوم التي دفعها النشر على السلسلة 13 أدناه.
جرى هذا النشر على السلسلة 13 في 2026-09-19، حين كانت السلسلة 13 هي السلسلة الحية (ملف FRI الإنتاجي، genesis 8123ccac1883a45750e4df6964fb7cd3f0b321798cde4c0ef406a0293939ece3)، من محفظة genesis shielded-1. وكل سلسلة بعدها (من 14 إلى 19) أُطلقت سلسلةً جديدة دون برامج السلسلة 13، ولم تُنشر الصورة من جديد على أيٍّ منها؛ لذا فالمعاملة والارتفاع المذكوران أدناه يخصّان السلسلة 13 ولم يعودا يُحلَّان في المستكشف. ومعرّف البرنامج هو تجزئة لـ base_pc والكلمات وحدها، فتحصل الصورة نفسها على المعرّف نفسه في أي سلسلة تقبل نشرها. مخرجات المحفظة، مع حذف أسطر التقدّم (…):
$ rand program deploy <image.bin>
program id: f074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d (11686 words, hc 92aefea0951c31a717574962aeb70e10a37012a7d035d48e8713c36df68feae0)
…
proved in 92.2s: tier 14, 1419655 bytes
submitted deploy c7a66dc4d9cdb7f9bfc4bde01f618c356e5abad7097e6bf7dc04e2e49c53acd0
…
| معرّف البرنامج | f074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d |
| الصورة | 11,686 كلمة؛ hc a0feae92… بصيغة rand-guest، و92aefea0… بصيغة المحفظة |
| حزمة الرسوم (حزمة السلسلة 13 بمدخلين ومخرجين) | المستوى 14، 1,419,655 بايت، أُنتج إثباتها في 92.2 s |
| معاملة النشر (السلسلة 13) | c7a66dc4d9cdb7f9bfc4bde01f618c356e5abad7097e6bf7dc04e2e49c53acd0 |
| أُدرجت عند الارتفاع (السلسلة 13) | 381 |
منذ السلسلة 14 صارت الحزمة الدافعة هي حزمة الأصول المخفية الواحدة بأربعة مدخلات وأربعة مخرجات التي تحملها كل معاملة، وتُثبَت مقابل ربط (binding) المعاملة. وهي ما تزال من المستوى 14: نحو 100 s ونحو 1.42 MB بملف الإنتاج على السلسلتين 14 و15. ومنذ السلسلة 17 تحمل الحزمة أيضًا إثبات تفويض من المستوى 10 (تفويض مجزّأ)، فتبلغ حزمة الرسوم لمعاملة على السلسلتين 18 و19 نحو 1.49 MB من إثبات الحزمة ونحو 1.37 MB من إثبات التفويض.
7. الاستدعاء
يحمل استدعاء transfer متجه الكلمات الـ 921 مدخلاتٍ خاصة، وهو دون حدّ المدخلات في أي سلسلة (4,295 كلمة افتراضيًا، و16,071 في السلسلة 20)، ولا يحمل كلمات عامة. ولا يمكن إرساله إلى السلسلة 20: فالبرنامج لا يمكن نشره هناك (الخطوة 6)، ويُثبَت transfer عند المستوى 18، ومنذ fullnode v0.5.6 (2026-09-25) ترفض العقدة أي إثبات استدعاء فوق المستوى 14 بالخطأ CallTierTooHigh، قبل أن تبني مفتاح المتحقق. يُنتج الأمر أدناه الإثبات محليًا وترفض السلسلة نتيجته؛ والقياسات هي إثباتات خارج السلسلة. يأخذ rand call كل كلمة بوصفها --input مكررًا:
rand call f074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d \
$(for w in $(cat evm2rv/target/transfer.words); do printf -- '--input %s ' "$w"; done)
والآن بعد القياس. أُوقف إثبات المستوى 18 على حاسوب محمول بذاكرة 48 GB عند 24.7 GB، لكن على droplet بذاكرة 128 GB (m-16vcpu-128gb) أُثبت استدعاء transfer المُترجَم: ذروة RSS بلغت 85.0 GB، في 3,230.5 s (53.8 min)، وحجم الإثبات 811,600 بايت. وجرى التحقق منه في 101.4 s على الـ droplet، وفي 50.2 s عند RSS قدرها 3.66 GB على حاسوب محمول بمعالج Apple silicon وذاكرة 48 GB (ذاكرة الإثبات). وفق جدول المستويات الثابت في دفتر الأستاذ، وهو القاعدة في السلاسل التي لا قسم gas فيها (حتى السلسلة 17)، كانت رسوم الاستدعاء عند المستوى 18 هي 0.0024 RAND. أما السلسلتان 18 و19 فتسعّران الاستدعاء بحدّ الغاز المعلن وبحجمه بالبايت، بواقع 100 وحدة لكل وحدة غاز و800 لكل KiB بأسعار genesis، ولا تقبلان أي استدعاء فوق المستوى 14.
الاستدعاء على السلسلة 13، 2026-09-19
جرى استدعاء approve(BOB, 5) (649 كلمة خاصة، المستوى 16) على السلسلة 13 في 2026-09-19، حين كانت السلسلة الحية، بملف FRI الإنتاجي، ومن المحفظة نفسها. ولم يُجرَ أي استدعاء على أي سلسلة لاحقة، إذ البرنامج غير منشور فيها، وترفض السلسلة 20 إثبات هذا الاستدعاء من المستوى 16 (CallTierTooHigh). مخرجات المحفظة، مع حذف أسطر التقدّم (…):
$ rand call f074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d --input <w0> --input <w1> … # the 649 words of approve(BOB, 5)
…
proved in 388.7s: tier 16, 3412405 bytes, outputs [1, 942495465, 790002515, 1351749335, 1059083501, 2923046783, 2814575942, 696258848]
…
proved in 96.0s: tier 14, 1420423 bytes
submitted call 279e1f62abf3f177ca71b08c633e051c37bc4720118c79ddb00936f036c4bfa7
…
| إثبات الاستدعاء | المستوى 16، 3,412,405 بايت، أُنتج في 388.7 s |
| حزمة الرسوم (حزمة السلسلة 13 بمدخلين ومخرجين) | المستوى 14، 1,420,423 بايت، أُنتج إثباتها في 96.0 s |
| المغلف المختوم | 2,700 بايت |
| معاملة الاستدعاء (السلسلة 13) | 279e1f62abf3f177ca71b08c633e051c37bc4720118c79ddb00936f036c4bfa7 |
| مُثبَّتة عند / أُدرجت عند | الارتفاع 802 / الارتفاع 919 |
| الرسوم | 0.00357 RAND |
الإيصال h_pub | null |
| مخرجات الإيصال | مساوية لكلمات المفسِّر الثماني للمتجه نفسه |
| الزمن الكلي، ذروة RSS | 622.8 s، 22.9 GB، على حاسوب محمول 48 GB بمعالج من سلسلة M |
- يبلغ الإثبات الإنتاجي 3,412,405 بايت، أي فوق حدّ الإثبات في السلسلة 12 البالغ 2 MiB. ولم تكن السلسلة 12 قادرة على قبول هذا الاستدعاء؛ أما حدّ السلسلة 13 البالغ 8 MiB فقبله. وأبقت السلاسل من 14 إلى 16 الحدّ نفسه، وضبطت السلاسل من 17 إلى 20 الحدّ على 4 MiB (4,194,304 بايت)، وإثبات بهذا الحجم ما يزال يتّسع تحته. ومنذ v0.5.6 ترفض العقدة الاستدعاء بسبب مستواه قبل أن تنظر في حجمه.
- تتضمن الرسوم حدّ البايتات من جدول السلسلة 13: فالإثبات البالغ 3.41 MB يتجاوز المسموح المجاني وقدره 2 MiB + 18,432 بايت. ومنذ السلسلة 18 يدفع كل استدعاء عن كل KiB ابتداءً من البايت 0.
كلمات الإيصال الثماني هي الواردة في الخطوة 4. لا تحتفظ السلسلة بأي حالة EVM: فالمستدعي يوفّر جذر الحالة السابقة وشواهد التخزين، وجذر الحالة اللاحقة داخل خلاصة EVM_OUT.
الحدود
- لا سياق للكتل. تُنهي عملياتُ سياق الكتلة التسع التنفيذَ بخطأ (trap) إلى أن يوجد تصميم لربط الكتل.
- لا تحويلات للقيمة. أي
CALLبقيمة غير صفرية يُنهي التنفيذ بخطأ. وكذلك الاستدعاءات إلى عقود غير العقود المُترجَمة مسبقًا (precompiles). - لا يمكن إثبات ecrecover وعملية الضرب في bn256 والـ pairing وعمليات modexp الكبيرة اليوم. فكلٌّ منها يتجاوز سقف الشريحة البالغ 2²⁰ صفًّا، وتحتاج إلى جداول معالج مساعد (coprocessor).
- لا حالة EVM على السلسلة. الاستدعاء إثبات واحد على تشغيل واحد، والمستدعي هو من يحمل الحالة.
- لا يصلح النشر ولا أي استدعاء لـ ERC-20 للقبول على chain 20. بموجب
hardening_v6في chain 20، يكون نشر برنامج بعدد كلمات أكبر مما يتسع له استدعاء من الشريحة 14 غير صالح (ProgramUncallable؛ 8,180 كلمة كحد أقصى)، بينما تبلغ الصورة 11,686. ومنذ fullnode v0.5.6 يجب أن يكون إثبات الاستدعاء من الشريحة 14 أو أدنى (CallTierTooHigh)؛ ويُثبَتapproveفي الشريحة 16، وtransferوtransferFromفي الشريحة 18. ويضع الفحص نفسه سقفًا لجداول التجزئة التي يجوز للاستدعاء التصريح بها: 2¹² صفًّا لـ Keccak (128 تبديلًا) و2¹³ صفًّا لـ SHA-256 (128 عملية ضغط). ومع ذلك ما زالت الاستدعاءات تُثبَت خارج السلسلة، كما يلي. - فهرس التخزين بعمق 32 بتًّا. تضع
evm-coreورقة تخزين العقد بحسب أعلى 32 بتًّا منkeccak256(slot)، فيكلّف العثور على خانة تتصادم مع خانة مختارة نحو 2³² تجزئة Keccak، وما دامت الخانة المختارة تحمل قيمة غير صفرية فهي مجمَّدة (لا تزوير ولا ضياع للقيمة). وهذا الوضع خامل: فحجمevm.binيبلغ 18,009 كلمة، ويتسع الاستدعاء عند سقف الشريحة 14 لـ 8,184 كلمة على الأكثر، فلا يمكن استدعاء أي وقت تشغيل EVM على أي سلسلة. ويسجّل الملفdocs/confidential.mdفي fullnode الشرط المسبق إلى جانب سقف الاستدعاء (تدقيق v6، ZKV-6؛ علىmainمنذ 2026-09-30، بعد وسم v0.6.7): قبل أن ترفع سلسلة سقف الاستدعاء في الشريحة 14 أو تقبل وقت تشغيل EVM صغيرًا يكفي لاستدعائه، يجب تعميق فهرس التخزين وإعادة تثبيتevm.bin. - مُثبَت عمليًّا. أُنهي إثبات تحويل من المرحلة الأولى (الشريحة 18) بإشارة SIGKILL على حاسوب محمول بذاكرة 48 GB عند 24.7 GB بعد 1,016 s، لكن استدعاء
transferفي المرحلة الثانية أُثبِت على droplet بذاكرة 128 GB (m-16vcpu-128gb): ذروة RSS بلغت 85.0 GB، و3,230.5 s (53.8 دقيقة)، وإثبات حجمه 811,600 بايت، جرى التحقق منه في 101.4 s (على droplet) وفي 50.2 s عند 3.66 GB RSS (حاسوب محمول 48 GB). وطابق إثبات التحويل عبرevm.binالمفسِّر ذلك عن قرب: 85.5 GB، و3,143.3 s (52.4 دقيقة)، وإثبات حجمه 805,108 بايت — ويحمل الإثباتان كلمات مخرجات عامة متطابقة، ما يؤكد التكافؤ على المُثبِت الفعلي. أماapprove(الشريحة 16، مُترجَم) فأرخص بكثير: 21.7 GB، و786.7 s (13.1 دقيقة)، وإثبات حجمه 798,930 بايت. ولا تخفّض الترجمة كلفة الإثبات إلا حين تُسقِط الاستدعاء إلى شريحة أصغر. - لا تسجّل السلسلة الشيفرة البايتية. انشرها ليتمكن الآخرون من إعادة بناء
hc.