Rand Protocol
الوثائق
المراجع

JSON-RPC

جميع دوال rand_* التي تخدمها العقدة: المعاملات ونماذج النتائج والأخطاء، إضافةً إلى الدفعات واشتراكات WebSocket وصيغة المعاملة على الشبكة.

The node serves JSON-RPC 2.0 over HTTP on --rpc (default 127.0.0.1:8545), and a WebSocket on the same port for subscriptions. Since v0.6.8 it can also open a second, public listener (--public-rpc, أدناه). randprotocol_client::RpcClient (Rust) wraps every method below. This page is the method list as v0.6.8 (c9c9bd3c), the build chain 20 runs, serves it; where a method exists in the code but is inert on chain 20, it says so.

curl -s http://127.0.0.1:8545 -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"rand_getHead","params":[]}'

نقطة النهاية العامة

https://rpc.randprotocol.org (the same proxy is also at https://randprotocol.org/api/rpc) يُحيل الطلبات إلى عقدة أرشيفية على chain-20 تحتفظ بكل كتلة، وذلك للمحافظ والصفحات التي لا تملك عقدة خاصة بها (rand --rpc https://rpc.randprotocol.org …). هي HTTP POST فقط، مع CORS مفتوح وبلا WebSocket، وهي أضيق من العقدة:

  • طلب واحد لكل استدعاء. تُرفض الدفعة بالرمز -32600.
  • قائمة مسموح بها من الطرق: منذ 2026-10-01 هي المجموعة نفسها التي يتيحها المستمع العام للعقدة (rpc::PUBLIC_METHODS في v0.6.8)، ومن ثمّ فإن قراءات حالة البرامج التي يحتاجها rand program invoke، وrand_getAdmitted، وقراءات التجميع (aggregation)، وقراءات الاستحقاق التدريجي (vesting) كلها ضمنها، إلى جانب rand_checkTransaction وrand_sendTransaction. أما rand_mint وrand_importViewingKey وrand_getViewingNotes وrand_removeViewingKey وrand_getPeers فليست ضمنها، وتردّ بالرمز -32601 مع الرسالة method not allowed here دون أن تصل إلى العقدة: فالصنبور (faucet) العام سطح للإساءة، ولا ينبغي أن يُرسَل مفتاح العرض (viewing key) إلا إلى عقدة تديرها بنفسك.
  • جسم طلب لا يتجاوز 12 MiB، يتسع لأي تحويل أو إجراء على الرمز أو نشر، ولاستدعاء يبلغ إثباته نحو 3.4 MB (تُرمَّز المعاملة بالنظام السداسي عشري، ويشغل إثباتا الحزمة (bundle) والتفويض (auth) نحو 2.85 MB قبل إثبات الاستدعاء). الاستدعاء الأكبر يذهب إلى عقدتك الخاصة. عند تجاوز الحد: HTTP 413 و-32600.
  • لكل عنوان 1,200 طلب في الدقيقة، و6 في الدقيقة لـ rand_sendTransaction. عند تجاوزها: HTTP 429 و-32005. وقد حُدِّدت ميزانية القراءة بما يناسب أول مزامنة للمحفظة، وهي عدة مئات من الطلبات دفعة واحدة (645 عند ارتفاع chain 18 البالغ 99,000).
  • -32000 مع upstream unavailable حين لا تردّ العقدة التي خلفها.

كل ما عدا ذلك في هذه الصفحة يصف العقدة نفسها.

مستمعا العقدة

منذ v0.6.8 (audit v6) تملك العقدة مستمعَي JSON-RPC.

  • --rpc <ADDR>، مستمع المشغّل. كل الطرق، والدفعات، وWebSocket. يتعرّف على المتصل من عنوان المقبس (socket) ويثق بحلقة الاسترجاع (loopback): فطرق مفتاح العرض لا تردّ إلا على loopback، وloopback غير مقيَّس. أبقِه على 127.0.0.1. فالوكيل العكسي أو تحويل SSH يصل عبر loopback، وعليه فخلف أيٍّ منهما يكون كل زائر هو المشغّل: لا توجّه أبدًا نقطة نهاية عامة إلى هذا المنفذ.
  • --public-rpc <ADDR>، المستمع العام، لهذه الحلقة تحديدًا. يخدم مجموعة ثابتة من الطرق، هي القراءات التي تحتاجها المحفظة أو المستكشف أو الصفحة، إضافةً إلى rand_sendTransaction (rpc::PUBLIC_METHODS). لا تُخدَّم عليه أبدًا rand_importViewingKey وrand_getViewingNotes وrand_removeViewingKey وrand_mint وrand_getPeers، ولا أي طريقة تُضاف لاحقًا إلى أن تُدرَج في القائمة؛ ويردّ استدعاؤها بالرمز -32000 مع <method> is not served on this node's public listener. الدفعة تردّ بالرمز -32600، ولا يوجد مسار WebSocket. عدّاد واحد يشمل جميع المتصلين معًا: 600 طلب في الدفعة الواحدة و150 في الثانية؛ وبعد ذلك HTTP 429 مع جسم -32000. أما الحدود لكل زائر فمن شأن الوكيل، لأنه يرى الزوار. ولا يشغل متصلوه أكثر من نصف خانات القراءة الحاجبة في العقدة، فلا يتضوّر مستمع المشغّل.

يشترك المستمعان في حدّين للقراءة. القراءة الحاجبة التي لم تعد خلال 30 s يُردّ عليها بالرمز -32000 مع this read took longer than 30 s on this node; retry with a smaller range. وتنهي rand_getBlocks صفحتها متى قرأت 64 MiB من الكتل.

يضع --rpc-viewing-token-file <PATH> رمز حامل (bearer token) على طرق مفتاح العرض في --rpc: السطر الأول من الملف، وطوله 32 حرفًا على الأقل، يُرسَل بصيغة Authorization: Bearer <token>. ومعه لا يكفي loopback وحده، ويُخدَّم أي متصل في أي مكان يقدّمه.

الاصطلاحات

  • عناوين المدقّقين (validators) سلاسل base58 (32 بايت). الهاشات 64 حرفًا سداسيًا عشريًا، مع 0x أو بدونها. القيم المحمية (shielded) — الالتزامات (commitments) والمبطِلات (nullifiers) والمراسي (anchors) وجذور الأشجار ومستويات الشاهد (witness) — هي Word8: ثماني كلمات u32 بترتيب little-endian مكتوبة 64 حرفًا سداسيًا عشريًا بالأحرف الصغيرة.
  • العناوين المحمية (shielded) هي rand1 + base58، بطول 1,667 حرفًا. يُرفض أي معامل يتجاوز طوله 2,000 حرف بسبب طوله قبل تحليله.
  • كل مبلغ من نوع u64 هو سلسلة عشرية ("1500000000" = 1.5 RAND؛ 1 RAND = 10⁹ وحدة): وحدات RAND أو وحدات رمز، سواء أكان حالة السلسلة أم حقلًا في معاملة مفكوكة. فالعدد في JSON ليس عددًا صحيحًا دقيقًا بعد 2⁵³، ومعروض رمز بتسعة خانات عشرية يتجاوز ذلك عند بضع عشرات الملايين من الوحدات. انظر الملاحظة المؤرّخة أدناه لمعرفة ما غيّره ذلك.
  • الفهارس وقيم nonce والارتفاعات وفهارس الأوراق والعروض (views) والأطوال وخانات الكسور العشرية (decimals) وعدّادات الأيام (mint_day) ليست مبالغ أبدًا، وهي أعداد صحيحة JSON في كل موضع.
  • يجب أن يحمل كل طلب عضوًا id. الكائن الذي لا يحمله إشعار (notification) ويُرفض بالرمز -32600؛ أما "id": null الصريح فهو طلب عادي.
  • لا توجد طريقة للرصيد ولا طريقة للحساب. تحسب المحفظة رصيدها بمسح rand_getCommitments وrand_getNullifiers بمفتاح العرض الخاص بها. أما rand_getBalance وrand_getAccount وrand_getAssetBalance فتردّ بالرمز -32601.

تغيير جذري، 2026-09-20 (chain 14): كل مبلغ سلسلة عشرية

قبل chain 14 كانت المبالغ داخل المعاملة المفكوكة أعدادًا صحيحة JSON. زال هذا الاستثناء. تغيّرت هذه الحقول من أعداد JSON إلى سلاسل عشرية، دون أي تغيير آخر في معناها أو موضعها:

  • bundle.fee، في tx ضمن rand_getTransaction وفي transactions[] ضمن rand_getBlockByHeight / rand_getBlockByHash؛
  • action.amount حين kind = mint أو bond أو unbond أو withdraw أو bridge_attest (في الطرق الثلاث نفسها)؛
  • action.amount وaction.relayer_fee حين kind = bridge_burn (في الطرق الثلاث نفسها)؛
  • locked في صفوف rand_getAssets وفي rand_getBridgeState.assets[].

على العميل الذي يقرأ أيًّا من هذه الحقول كعدد أن يحلّل سلسلة بدلًا من ذلك. وصار aggregation.subsidy_base في rand_status (لسلاسل التجميع فقط) سلسلة في التغيير نفسه. وكل مبلغ آخر كان سلسلة أصلًا: rand_getSupply وrand_getEmission وrand_getValidators وملاحظات العرض (viewing notes)، وكل حقل استُحدث مع chain 14 — أي burn_a وburn_r في الحزمة، وإجماليات عرض الرموز، وlocked لكل غطاء (backing)، وmint_cap_per_day وminted_today، وregistration_fee، وamount في token_mint وtoken_burn وregister_token (initial_amount وinitial.amount).

الدفعات

يجوز أن يكون جسم POST مصفوفة من 20 كائن طلب على الأكثر، يُردّ عليها بمصفوفة بالطول نفسه وبترتيب الطلبات، بما في ذلك الأخطاء. تُنفَّذ الطلبات الواحد تلو الآخر. المصفوفة الفارغة، أو المصفوفة التي تتجاوز 20، أو الجسم الذي ليس كائنًا ولا مصفوفة، يعطي رد -32600 واحدًا بمعرّف null. ويظل الجسم كله محدودًا بحد جسم الطلب في العقدة، المحدَّد لمعاملة واحدة حاملة لإثبات: فدفعة من استدعاءَي rand_sendTransaction حاملين لإثباتين تُرفض بالرمز 413. اجعل الدفعات للقراءات، لا للإرسالات المثبَتة.

السلسلة والعقدة

rand_chainId

Params []. Result: the chain id (integer); 20 on the testnet.

rand_tokenInfo

Params []. Result { "symbol": "RAND", "decimals": 9 }.

rand_getHead

Params []. Result { "height": 1998, "hash": "…", "view": 2251 }. view هو عرض الإجماع الحالي للعقدة، وهو يتقدّم على الارتفاع حين تنتهي مهلة العروض.

rand_status (alias rand_syncStatus)

Params []. Result:

{
  "height": 1998, "head_hash": "…", "view": 2251, "high_qc_view": 2250,
  "syncing": false, "sync_target": 1998,
  "sync_inflight_age_ms": null, "sync_failures": 0, "sync_late_batches": 0,
  "peer_count": 26, "connected_peers": 26, "reserved_peers": 25, "ws_clients": 0, "refused_cache": 0,
  "verify_queue": 0, "mempool_size": 0,
  "is_validator": true, "active_validator": true, "faucet": true, "confidential": true,
  "testnet": true, "fri_profile": "production", "programs": 10, "viewing_keys": 0,
  "notes": 197, "nullifiers": 160, "tree_root": "72b9…1197", "hc_bundle": "60af…3fce", "hc_auth": "1e4e…39c1",
  "binding_domain": 1,
  "address": "5TAofR…", "peer_id": "12D3KooW…",
  "gas_prices": { "gas_price": "100", "byte_price": "800" }
}

is_validator: تحمل هذه العقدة مفتاح مدقّق؛ active_validator: ذلك المفتاح ضمن المجموعة التي تشغّل الحقبة (epoch) الحالية. يعدّ reserved_peers (v0.6.8) الأقران المقبولين فوق حد الاتصالات الواردة: عُقد الإقلاع (bootstraps)، وأي --reserved-peer، وكل هوية مدقّق عُرفت من ربط موقَّع للقرين، كلٌّ مرة واحدة؛ وعلى عقدة في الأسطول ينبغي أن يبلغ عدد المدقّقين خلال دقيقة من البدء. viewing_keys هو عدد مفاتيح العرض التي تحتفظ بها العقدة في الذاكرة للمسح على جانب العقدة. verify_queue هو عدد المعاملات المنتظرة لأحد عمّال التحقق من الإثباتات الأربعة (بعمق 64 على الأكثر). hc_bundle هو برنامج الضيف (guest) للحزمة الذي تُبنى عليه إثباتات هذه السلسلة، وhc_auth هو برنامج ضيف التفويض الذي يثبّته genesis الخاص بها (تفويض مجزّأ، منذ chain 17)، أو null على سلسلة بلا واحد منهما؛ والعقدة التي يخالف بناؤها أيًّا منهما ترفض البدء. testnet وbinding_domain هما حقلا genesis بالاسمين نفسيهما، كما يخدمهما rand_getLimits. gas_prices هي أسعار الغاز الحالية في دفتر الإكراميات (tip ledger)، وتُحدَّث عند كل إتمام (commit)، بوصفها سلاسل عشرية؛ وnull على سلسلة بلا قسم gas. أسعار chain 20 ديناميكية وتتحرك مع كل كتلة بحسب امتلائها، لا تقل عن الحدين الأدنيين 100 و800 ولا تزيد على الحدين الأعلى 10,000 و80,000، فاقرأها هنا أو في rand_getLimits ولا تثبّتها في الشيفرة. ويحمل الكائن أيضًا كائن aggregation (وsubsidy_base فيه سلسلة عشرية، وبقية حقوله أعداد صحيحة)، يُقرأ أصفارًا كلها على سلسلة بلا قسم aggregation، كما هي حال chain 20.

ويحمل الكائن أيضًا disk_free_bytes (عدد) وdisk_low، وزوج الاحتفاظ: prune_floor، وهو أدنى ارتفاع ما زالت هذه العقدة تحتفظ به (0 على الأرشيف)، وprune_history_secs، وهي النافذة التي تحتفظ بها عقدة بدأت بـ --prune-history (null حين تحتفظ بكل شيء). على chain 20، كما على chain 19، تحتفظ 24 من المدقّقين الـ 26 بكتل 24 ساعة؛ وتحتفظ العقدتان الأرشيفيتان بها جميعًا. انظر Pruned nodes.

rand_getPeers

Params []. Result: an array of { "peer_id": "12D3KooW…", "addrs": ["/ip4/…/tcp/30303"], "connected_secs": 1241 }.

rand_getBlockByHeight / rand_getBlockByHash

Params [height] or [hash]. Result null if unknown, else:

{
  "hash": "647b…", "height": 50, "view": 92, "parent": "2d41…",
  "proposer": "3v3VBJ…", "timestamp_ms": 1788000123456,
  "tx_root": "0000…", "state_root": "a1b2…", "justify_view": 91,
  "tx_count": 0, "transactions": [ ]
}

تُقدَّم الكتل المُثبَّتة (committed) فقط. يحمل الحقل transactions الشكل نفسه الذي يحمله tx في rand_getTransaction. وتحمل الكتلة أيضًا الحقل sealed، وتحمل كل معاملة من معاملاتها الحقل sealed_by؛ وقيمتاهما false وnull على سلسلة بلا تجميع (aggregation).

rand_getBlocks

المعاملات [from_height, to_height]. النتيجة: ترويسات الكتل، الأقدم أولًا، بحد أقصى 1,024 ترويسة ابتداءً من from_height (128 على عقدة قبل 2026-09-24): حقول rand_getBlockByHeight دون transactions. النطاق الأوسع من الحد، أو الذي يتجاوز الرأس، يُقتطع ولا يُرفض، ومنذ v0.6.8 تنتهي الصفحة أيضًا متى قرأت 64 MiB من الكتل؛ تابع من آخر ارتفاع أُعيد. يُعاد -32602 إذا كان to_height أقل من from_height.

منذ v0.6.8 تحمل كل ترويسة أيضًا public_notes: معاملات الكتلة من النوع bridge_attest وtoken_mint وregister_token، وعلى سلسلة ذات رسوم جسر معاملات bridge_burn فيها، بصيغة [{ "hash", "raw" }] (الترميز الذي يقدّمه rand_getRawTransaction)؛ وهي فارغة في كل كتلة أخرى. تُقدَّم معاملة الحرق (burn) وقد أُفرغت أدلتها (proofs) مع "proofs_stripped": true؛ ويبقى hash فيها معرّف المعاملة الحقيقي. تقرأ المزامنة الأولى للمحفظة هذه الصفحات ولا تحتاج إلى شيء آخر لإعادة بناء الملاحظات العامة (public notes).

rand_getFinality

المعاملات [height] أو [hash]. النتيجة إحدى الصيغ { "status": "committed", "height", "hash" } أو { "status": "certified", "height", "hash", "qc_view" } أو { "status": "proposed", "height", "hash" } أو { "status": "unknown" }. لا يُفحص الارتفاع إلا مقابل السلسلة المُثبَّتة، فيجيب committed أو unknown؛ أما التجزئة فقد تقرأ أيضًا certified (في شجرة النسخة المتماثلة غير المُثبَّتة مع شهادة نصاب quorum certificate) أو proposed (في الشجرة دون شهادة).

rand_getProposer

المعاملات [view] أو [from_view, to_view]، بحد أقصى 64 عرضًا (view). النتيجة { "epoch": 3, "proposers": [ { "view": 2251, "proposer": "2nRdFC…" } ] }: قائد كل عرض وفق مجموعة المدقّقين (validators) الحالية، لا المجموعة التي كانت قائمة عند ذلك العرض تاريخيًا. يُعاد -32602 لنطاق معكوس أو لأكثر من 64 عرضًا.

rand_getVersion

المعاملات []. النتيجة { "version", "git_sha", "chain_id", "hc_bundle", "hc_auth", "fri_profile" }. version هو إصدار حزمة workspace؛ وgit_sha تجزئة الإيداع (commit) الملتقطة وقت البناء، مع إلحاق -dirty إذا اختلفت الملفات المتتبَّعة، أو "unknown". وhc_auth هو guest المصادقة في genesis، كما في rand_status، أو null. النقطة العامة في 2026-10-01، على السلسلة 20:

{ "version": "0.6.8", "git_sha": "c9c9bd3c1903aa4cc5833b7ab8c62fc3e6942017", "chain_id": 20,
  "hc_bundle": "60af094acfe65d85fdb18fb3d06cf9085dcf28c96e59e87f1ee527226e6e3fce",
  "hc_auth": "1e4e347f44cf86750b30a9a4bdf9ec9256efe353d4ff8017451eca7d195639c1",
  "fri_profile": "production" }

rand_getGenesisHash

المعاملات []. النتيجة: تجزئة genesis بصيغة hex؛ وهي "6210cf071a390d7ac61d8cbea5dd9d139d1a493a862b54a45a498f36af2d5135" على السلسلة 20 (وكانت تجزئة السلسلة 19 a3defc93…228a). معرّف السلسلة وحده لا يميّز بين قطعتين من السلسلة؛ أما هذه التجزئة فتميّز. وعلى السلسلة 20 هي أيضًا جزء من ربط (binding) كل معاملة ومن رسالة كل إجراء موقَّع (binding_domain: 1، انظر rand_getLimits).

rand_getHealth

المعاملات []. النتيجة إحدى الصيغ { "status": "disk_low", "free_bytes": "3221225472" } أو { "status": "ok" } أو { "status": "syncing", "behind": 412 } أو { "status": "behind", "behind": 30 }. تتقدم disk_low على كل ما سواها، حين تقل المساحة الحرة في نظام الملفات الذي يحوي دليل البيانات عن أربعة أضعاف --min-free-disk-mb للعقدة (الافتراضي 1024، أي أقل من 4 GB)؛ وfree_bytes سلسلة عشرية. وتكون ok حين لا يزيد sync_target - height على 2 ولا يوجد طلب دفعة مزامنة معلّق؛ وsyncing ما دام أحدها معلّقًا؛ وbehind حين لا تكون العقدة في مزامنة ويظل التأخر فوق 2.

rand_getMempoolInfo

المعاملات []. النتيجة { "count": 2, "bytes": 2611200, "oldest_ms": 1450, "max_count": 10000 }. يجمع bytes طول الترميز لكل معاملة في المجمّع؛ ويكون oldest_ms قيمة null حين يكون المجمّع فارغًا. ومنذ v0.6.8 يُقيَّد المجمّع أيضًا بالبايتات، بثمانية أضعاف max_block_bytes في genesis (160 MiB على السلسلة 20): فبعده تُزيح المعاملة التي تدفع فوق حدّها الأدنى لكل KiB أكثر من غيرها أرخص معاملة، وتُرفض التي تدفع أقل أو المساوي بالرسالة mempool full. وتمرّ إجراءات الحوكمة من الحدّين معًا.

الإرسال

rand_sendTransaction

المعاملات [hex]، حيث hex هو bincode(Transaction). النتيجة: تجزئة المعاملة. تتحقق العقدة وفق ترتيب القبول (المعاملات)، ثم تضعها في المجمّع وتبثّها. الأخطاء هي -32000 مع السبب: nullifier already spent وanchor is not one of the last 1024 roots وtime 12 is outside [1500, 2524] (كلتا النافذتين هي proof_window_blocks في genesis، أي 1,024 على السلسلة 20؛ و256 على السلاسل حتى 19) وfee 1000000 below minimum 2000000 وthe bundle's digest is not what its proof published وinvalid bundle proof: … وunknown program … وalready in mempool وconflicts with a pending transaction over <nullifier> وfaucet is disabled on this chain؛ وفي invoke، cell <key> is no longer what this transition read (حكم يخص الحالة: أعد قراءة الخلية وأعد توليد الدليل) أو the vault holds … of asset … and the transition pays …؛ وفي Bond مسجِّل تحت القبول بالتصويت، validator … has not been admitted by the validator set's vote (staking.admission_by_vote); ask the validators for an AdmitValidator first؛ وفي حزمة لا تلائم genesis السلسلة 20، envelope is 1348 bytes, this chain requires exactly 1860 وthis chain requires an auth proof on every bundle (genesis hc_auth) وthe auth proof publishes a different commitment than the bundle's auth_commit وauth proof: … وbundle proof declares gas limit …, this chain requires exactly 20479 وnon-canonical proof: … — re-prove with an up-to-date wallet؛ وفي إجراءات الجسر bridge: attestation already consumed وthe attestation names a different recipient وthe attestation deposits under asset 2, and the transaction names 1 وthe bundle burns 399, not the 400 the action declares؛ وفي حزمة تحمل حرقًا لا يجوز لإجرائها حمله، the bundle burns asset 2 on an action that burns no token أو a burn of 5 is not allowed on this action أو RAND burned through burn_a (5); a RAND burn goes through burn_r؛ وفي حالة الجسر، bridge minting is paused وmint cap … per backing per day وalready paused وnot paused وwrong pause nonce وwrong list nonce وchain N has no registered emitter؛ وفي سجل الرموز، wrong mint nonce وwrong token index. القبول ليس تثبيتًا: استعلم عبر rand_getTransaction أو rand_getTransactionStatus.

تُرفض المعاملة الأكبر من سقف كتلة السلسلة (max_block_bytes من rand_getLimits) بالرمز -32000 مع ذكر الحجمين، قبل أن تبلغ المجمّع. ويُحدَّد سقف جسم الطلب بالقيمة 2 × (2 × max_proof_bytes + 4 × 2048 + max_call_envelope_bytes + 16,384 + 64 KiB) + 256 KiB، تُحسب من genesis عند بدء التشغيل: 8,867,840 بايت على سلسلة افتراضية و17,350,656 عند حدود السلسلة 20، وهي نفسها للسلاسل 17 إلى 19 (34,127,872 على السلاسل 13 إلى 15، التي كان سقف الأدلة فيها 8 MiB). و4 × 2048 هي أظرف الحزمة الأربعة عند سقف الظرف. والجسم الذي يتجاوزه يُرفض بالرمز -32600 مع ذكر الحد.

الرمزان -32000 (رفضه القبول) و-32602 (تعذّر فك ترميزه) وحدهما حكم على المعاملة. أما أي إخفاق آخر، ومنه -32603، فيترك مصيرها مجهولًا: إذ تضع العقدة المعاملة في المجمّع وتبثّها قبل أن ترد، فقد تكون عقدة توقفت في تلك الفترة قد قبلت ما لم تُجب عنه. ويعدّ randprotocol_client الإرسال مرفوضًا على هذين الرمزين فقط.

rand_getTransactionStatus

المعاملات [[hash, …]]، من 1 إلى 64 تجزئة. النتيجة: مدخل لكل تجزئة، بالترتيب:

[ { "hash": "…", "status": "committed", "height": 1998, "index": 0 },
  { "hash": "…", "status": "pending" },
  { "hash": "…", "status": "rejected", "reason": "bad mint signature" },
  { "hash": "…", "status": "unknown" } ]

ترتيب البحث لكل تجزئة: committed (التخزين)، ثم pending (المجمّع)، ثم rejected (ذاكرة المرفوضات التي يحصيها refused_cache في rand_status)، وإلا unknown. ولا تشمل rejected إلا حالات الرفض المتعلقة ببايتات المعاملة نفسها، التي لا تستطيع أي كتلة لاحقة تغييرها: دليل غير صالح، أو ملخّص حزمة (digest) لا يطابق ما نشره دليلها، أو توقيع سكّ (mint) سيئ، أو معرّف سلسلة خاطئ، أو جزء يتجاوز الحجم، أو nullifier أو التزام (commitment) مكرر داخل المعاملة، أو ظرف بحجم خاطئ، أو دليل مصادقة مفقود أو غير مطابق، أو حزمة أو دليل مصادقة يعلن حد غاز (gas limit) خاطئًا. أما الرفض المرتبط بحالة العقدة في تلك اللحظة — nullifier مُنفَق، أو anchor أو time خارج النافذة، أو رسم دون الحد الأدنى (وهو على السلسلة 20 يتحرك مع أسعار الغاز)، أو برنامج مجهول، أو register nonce، أو قراءة invoke قديمة — فلا يُحفظ ويُقرأ unknown. ويُعاد -32602 لقائمة فارغة أو لأكثر من 64 تجزئة.

rand_mint (صنبور testnet)

المعاملات [address] أو [address, amount]؛ address عنوان rand1…، وamount سلسلة من الوحدات لا تزيد على 100000000000 (100 RAND، وهو الافتراضي). النتيجة: تجزئة معاملة السكّ. لا يعمل إلا على سلسلة يحمل genesis فيها "faucet": true؛ وإلا يُعاد -32000 مع faucet is disabled on this chain. وتجيب العقدة المراقِبة (observer) بـ faucet mints are signed by validators; ask a validator node.

على سلسلة يضبط genesis فيها staking.faucet_recipients، كما في السلسلة 20 (16 محفظة)، لا يُدفع إلا للمحافظ المدرجة: فيُرفض السكّ إلى أي عنوان آخر بالرسالة the faucet may not mint to this recipient (not in staking.faucet_recipients). ويضبط genesis السلسلة 20 كذلك staking.faucet_minters (18 مفتاح مدقّق): فلا يوقّع السكّ إلا مفتاح مدرج. وللصنبور أيضًا ميزانية لكل حقبة (epoch)، staking.faucet_budget_per_epoch (10,000 RAND لكل حقبة من 1,000 كتلة على السلسلة 20)؛ ويُرفض السكّ الذي يتجاوزها بالرسالة FaucetBudgetExhausted، وهو حكم يخص الحالة ويُقرأ unknown متى غادر المجمّع.

يخضع الصنبور لحدّ معدّل لكل عملية عقدة: ثماني عمليات سك متتالية، يُعاد ملؤها بمعدل واحدة في الثانية. وبعد ذلك يردّ الاستدعاء بـ faucet is rate limited on this node (8 mints back to back, refilling at 1/s); try again shortly. ولذلك لا يستطيع إغراق الصنبور ملء المجمّع قبل PauseMints الخاص بالجسر، وهو، شأنه شأن إجراءات حوكمة الجسر الثلاثة الأخرى، مستثنى أيضًا من رفض المجمّع mempool full ويُرتَّب أولًا في الكتلة.

منذ السلسلة 14 أصبح السك مفتوحًا: يحمل الإجراء Mint الحقول pk وtime وr الخاصة بالملاحظة إلى جانب cm وamount، ويعيد القبول حساب الالتزام ويرفض أي cm لا يُفتح على هذه القيم (the mint's commitment does not open to its published note and amount)، ويوقّع السّاك الحقول السبعة جميعها تحت النطاق rand-mint-2؛ وفي السلسلة 20 (binding_domain: 1) تحت rand-mint-3، مع وضع تجزئة التكوين أولًا. وعليه فإن مالك ملاحظة الصنبور ومبلغها علنيان، كما هو حال مدفوعات السحب. أما معاملات rand_mint فلم تتغير.

rand_estimateFee

المعاملات [spec]، وهي إحدى القيم {"kind":"bundle"} أو {"kind":"deploy","words":n,"public_words":m} أو {"kind":"call","tier":t,"bytes":b,"gas":g} حيث t أحد القيم 10 و12 و14 و16 و18 و20. النتيجة: الحد الأدنى للرسوم بالوحدات، سلسلة نصية. و{"kind":"bundle"} تساوي "1000000". تُدفع public_words (اختيارية، الافتراضي 0) عن كل كلمة كما يُدفع عن الشيفرة، فتكون الرسوم هي رسوم نشر n + m كلمة. أما bytes (اختيارية، الافتراضي 0) فهي طول إثبات الاستدعاء مضافًا إليه طول غلاف مدخلاته.

يعتمد تسعير الاستدعاء على gas_metering في rand_getLimits:

  • "circuit"، وهي سلسلة لها قسم gas خاص بها، كما هي حال السلسلة 20. gas هو حد الغاز الذي يعلنه إثبات الاستدعاء، وهو مطلوب: فبدونه يردّ الاستدعاء بالخطأ -32602 under the gas section a call estimate needs its gas. والجواب هو 1,000,000 + gas_price × gas + byte_price × ⌈bytes / 1024⌉ بأسعار رأس السلسلة الحالية، وهي التي يقدمها rand_getLimits. وبأسعار الحد الأدنى في السلسلة 20، وهي 100 و800، يكون استدعاء يعلن 20,479 من الغاز مع 1,300,000 بايت من الإثبات والغلاف "4063900". تتغير الأسعار مع كل كتلة، فقدِّر الرسوم قرب وقت الإرسال.
  • "header"، وهي سياسة غاز على مستوى العقدة في سلسلة بلا هذا القسم. تقبل مواصفة الاستدعاء keccak_log_height وsha256_log_height (اختياريان، الافتراضي 0، وكل منهما من 0 إلى 40، وإلا -32602)، وهما ارتفاعا جدولَي التجزئة اللذان يعلنهما رأس الإثبات، والجواب هو الأكبر بين حد المستوى في السجل وحد الغاز لذلك الرأس. وتحت قسم gas يُقبل الارتفاعان ولا يُستعملان.
  • null، أي لا هذا ولا ذاك. جدول المستويات في السجل وحده: عند الحصة المجانية أو دونها (2,097,152 + 18,432 بايت) يكلّف الاستدعاء رسم مستواه؛ وكل KiB فوقها، ويُحتسب الجزء من KiB كاملًا، يضيف 1,000 وحدة.

منذ الإصدار v0.6.8، يسعّر {"kind":"invoke", …, "created_cells": c} استدعاء invoke من RPL-2: كل حقل في مواصفة الاستدعاء، إضافة إلى created_cells (اختياري، الافتراضي 0، وبحد أقصى max_writes، وإلا -32602)، أي الخلايا التي سينشئها الانتقال. وتضيف كل خلية cell_fee الخاص بالسلسلة (rand_getLimits.program_state). ويحسبها المستدعي: كتابة قيمة غير صفرية في خلية يقرؤها rand_getProgramCell أصفارًا. وفي السلسلة 20 يكون الاستدعاء أعلاه مع خليتين منشأتين "24063900". وفي سلسلة بلا قسم program_state يكون هذا النوع -32602.

يتضمن الرسوم الجدول الكامل.

المجمّع

rand_getTreeInfo

المعاملات []. النتيجة { "next_index": 41, "root": "6b1d…c4", "nullifiers": 12 }: عدد الأوراق، والجذر الحالي، وعدد الملاحظات التي أُنفقت.

rand_getCommitments

المعاملات [from_index] أو [from_index, limit]. النتيجة: صفحة من الأوراق ابتداءً من from_index، الأقدم أولًا، بحد أقصى 1,000 صف مهما بلغت قيمة limit.

[ { "index": 40, "cm": "2a9f…07", "height": 37,
    "envelope": { "kem_ct": "b41c…", "to_receiver": "77e0…", "to_sender": "0c31…", "body": "9dd2…" } } ]

rand_getNullifiers

المعاملات [from_height] أو [from_height, limit]. النتيجة: كل مُبطِل (nullifier) نُشر منذ ذلك الارتفاع فصاعدًا، بالحد نفسه البالغ 1,000 صف. وقد تتوقف الصفحة داخل ارتفاع واحد؛ فارجع في الصفحات إلى أعلى ارتفاع شوهد.

[ { "height": 37, "nullifier": "8c04…d1" }, { "height": 41, "nullifier": "12be…9a" } ]

rand_getCompactBlocks

المعاملات [from_height, to_height]، وكلاهما مطلوب. النتيجة: صف واحد لكل كتلة، الأقدم أولًا، بما تحتاجه المحفظة الخفيفة ولا شيء غيره:

[ { "height": 192, "hash": "63f6…08", "timestamp_ms": 1788000123456,
    "commitments": [],
    "transactions": [
      { "hash": "4f2c…e7",
        "commitments": [ { "index": 40, "cm": "2a9f…07", "envelope": { "kem_ct": "…", "to_receiver": "…", "to_sender": "…", "body": "…" } } ],
        "nullifiers": ["8c04…d1", "5e77…20", "03aa…6f", "e19b…42"] } ] } ]

كل معاملة تحمل حزمة تملك هنا أربع ملاحظات وأربعة مُبطِلات، أي خاناتها الأربع، بما فيها الخانات الوهمية التي لا يستطيع أي قارئ تمييزها عن الحقيقية (يُعرض في المثال صف الالتزام الأول فقط). ومنذ الإصدار v0.6.8 يملك بعضها ملاحظات أكثر بعد تلك الأربع: يملك invoke ملاحظة لكل دفعة، pays ثم mints، لكل منها غلافها الخاص، فيجدها المستفيد بفك التشفير التجريبي؛ وفي سلسلة فيها رسوم جسر، كما هي حال السلسلة 20، يملك bridge_burn ملاحظة رسم الخزينة الخاصة به، ويملك bridge_attest ملاحظة رسمه بعد إيداعه. وغلاف ملاحظة الرسم فارغ، مختوم لا لأحد: تعيد محفظة الخزينة بناء الملاحظة من الحقول العلنية للمعاملة.

بحد أقصى 128 كتلة في الاستدعاء (يُقصّ المدى الأوسع) و1,000 ملاحظة بعد الكتلة الأولى، وهي تُخدَّم كاملة دائمًا؛ واستأنف من آخر height أُعيد زائدًا واحدًا. تحتوي المصفوفة commitments على مستوى الكتلة على إيداعات التكوين عند الارتفاع 0، وهي فارغة فيما عداه؛ وتظهر الملاحظات المشتقة من Withdraw وBridgeAttest تحت معاملتها. ويكون الخطأ -32602 لمدى معكوس أو حد مفقود.

rand_getAnchor

المعاملات [] للرأس، أو [height]. النتيجة { "height": 192, "root": "6b1d…c4" }، أو -32001 لارتفاع لا مرساة مسجلة له. جذور نهاية الكتل وحدها هي المراسي. قد تجيب العقدة عن ارتفاع قديم، لكن مرساة الحزمة لا تُقبل إلا إذا كانت من بين آخر proof_window_blocks من الجذور: 1,024 في السلسلة 20، و256 في السلاسل حتى 19. ابنِ على الرأس.

rand_getWitness

المعاملات [index]. النتيجة null بعد نهاية الشجرة، وإلا مسار ميركل لتلك الورقة، من الورقة صعودًا، بالضبط 32 مستوى، مع الجذر الحالي للشجرة:

{ "index": 40, "root": "6b1d…c4", "path": ["0000…00", "f2a1…3b", "…"] }

هذه أغلى قراءة تخدمها العقدة (إذ تعيد بناء الشجرة الكاملة بعمق 32)، والطلب الوحيد الذي يكشف شيئًا عن المستدعي. تشغّل العقدة بناءين للشجرة على الأكثر في وقت واحد، rand_getWitness وrand_getWitnesses معًا؛ والطلب الذي ينتظر أكثر من 10 ثوانٍ للحصول على موضع يُرفض بالخطأ -32000 witness builds are busy on this node; retry shortly.

rand_getWitnesses

المعاملات [[index, …]]، من 1 إلى 32 فهرس ورقة. النتيجة { "root": "…", "witnesses": [ { "index": 7, "path": ["…"] }, { "index": 9, "path": null } ] }: هي rand_getWitness مطبقة على أوراق كثيرة في بناء شجرة واحد، فتدفع المحفظة التي تثبت عدة ملاحظات كلفة إعادة البناء مرة واحدة. ويُقرأ فهرس يتجاوز نهاية الشجرة path: null في إدخاله. ويكون الخطأ -32602 لقائمة فارغة أو لأكثر من 32 فهرسًا.

مفاتيح العرض والإفصاح

rand_importViewingKey

المعاملات [viewing_key] أو [viewing_key, rescan_from_height]، والمفتاح 64 حرفًا سداسيًا عشريًا. النتيجة { "imported": true, "rescan_from_height": 0, "viewing_keys": 3 }. تحتفظ العقدة بالمفتاح في الذاكرة فقط: 64 مفتاحًا على الأكثر لكل عقدة، وتُمحى عند إعادة التشغيل؛ ومفتاح محتفَظ به أصلًا لا يغيّر شيئًا ("imported": false). لا يجري الاستيراد أي مسح؛ إذ تُدار عملية المسح بالطريقة التالية. ويكون الخطأ -32602 لمفتاح مشوّه؛ و-32000 عند المفتاح الخامس والستين.

تجيب طرق مفاتيح العرض الثلاث مستدعيًا من الحلقة المحلية فقط وترفض غيره بالخطأ -32000، ما لم تعمل العقدة بالخيار --rpc-viewing-open خلف ما يوثّق الهوية. وتحرّر rand_removeViewingKey ([viewing_key] ← { "removed": bool, "viewing_keys": n }) موضعًا وتصفّر المفتاح. ويُفهرس السجل بمعرّف أحادي الاتجاه للمفتاح، blake3("rand-viewing-registry-id-1" ‖ nk)، لا بالمفتاح نفسه، فيكون الاستيراد النسخة الطويلة العمر الوحيدة، والإزالة تمحوها. أما نص JSON الخاص بالطلب نفسه والنسخ المؤقتة التي يصنعها فك التشفير التجريبي فلا تُمحى.

rand_getViewingNotes

المعاملات [viewing_key] أو [viewing_key, from_index, limit] (الافتراضي والحد الأقصى لـ limit هو 1,000). يقدّم كل استدعاء مسح المفتاح بما يصل إلى 10,000 ورقة، ثم يخدّم الصفحة:

{ "scanned_index": 10041, "next_index": 10041, "complete": true,
  "notes": [
    { "index": 40, "cm": "2a9f…07", "height": 37, "role": "received",
      "note": { "pk": "…", "from": "…", "amount": "1500000000", "asset": 0, "time": 5, "memo": "coffee" },
      "nullifier": "8c04…d1", "spent": false },
    { "index": 43, "cm": "b310…88", "height": 39, "role": "sent",
      "note": { "pk": "…", "from": "…", "amount": "25000000", "asset": 0, "time": 9, "memo": null },
      "nullifier": null, "spent": null } ] }

role هو received (فُتح الغلاف بصفة المستلم وتسمّي الملاحظة pk الخاص بالمفتاح) أو sent (فُتح عبر مفتاح العرض الصادر). وmemo الخاص بالملاحظة هو المذكرة المشفرة من المرسل، نص UTF-8 بحد أقصى 510 بايت، أو null حين لا توجد أو حين فُتح حقلها مشوّهًا؛ ولا تكلّف المذكرة المشوّهة المستفيد ملاحظته أبدًا. والمذكرة نص يكتبه أي أحد: اعرضها بوصفها غير موثوقة. ويكون الخطأ -32001 لمفتاح لم تستورده هذه العقدة.

rand_checkTransaction

المعاملات [hash, key]، وkey هو TxKey خاص بكل معاملة بصيغة 64 حرفًا سداسيًا عشريًا. النتيجة null لتجزئة مجهولة، وإلا ما يفصح عنه المفتاح:

{ "tx": "4f2c…e7", "height": 192,
  "disclosed": [ { "output": "bundle:0", "cm": "2a9f…07", "index": 40,
                   "note": { "pk": "…", "from": "…", "amount": "1500000000", "asset": 0, "time": 5, "memo": "invoice 7" } } ] }

عديمة الحالة: يُسقَط المفتاح مع الاستدعاء. قيمة output هي bundle:0 … bundle:3 لخانات مخرجات الحزمة الأربع (الخانتان 0–1 لمخرجات الأصل الخاص، والخانتان 2–3 لمخرجات RAND، بما فيها المخرجات الوهمية)، وdeposit لغلاف الإيداع في إثبات الجسر، وtoken_mint لملاحظة TokenMint، وinitial_mint للسك الأولي في RegisterToken، وmint:0 للغلاف الوحيد في سك الحنفية، أو (v0.6.8) payout:0 … payout:3 للملاحظات التي دفعها invoke، مرقّمةً بحسب موضعها في الانتقال، pays ثم mints؛ أما asset_bundle:* فقد زال مع الحزمة الثانية. في سلسلة ذات رسوم جسر، يفتح deposit الإيداع الصافي، أي الإجمالي ناقص الرسم. تحمل note المكشوفة حقل asset الخاص بها: وهذا الاستدعاء، بالمفتاح الذي ختم به المرسِل، هو الموضع الوحيد الذي يكشف فيه RPC أيَّ أصل نقلته الحوالة. وتحمل كذلك memo، كما يفعل rand_getViewingNotes: المفتاح الذي يفتح الملاحظة يفتح المذكرة، من الجسم المختوم نفسه. المفتاح الخاطئ يعيد { "disclosed": [] }، ولا يمكن تمييزه عن معاملة لا تكشف شيئًا. أما أغلفة السحب وأغلفة التخصيص الأولي (genesis alloc) فلا تُجرَّب: فهي مختومة داخل العقدة بمفاتيح تُسقَط فورًا، فلا وجود لـ TxKey لها. وغلاف سك الحنفية يُجرَّب: يستعيد مستلمه المفتاح عبر نصف KEM من الغلاف (rand tx-key).

المعاملات

rand_getTransaction

المعاملات [hash]. النتيجة null إلى أن تُثبَّت المعاملة، ثم:

{
  "height": 192, "index": 0, "block_hash": "63f6…08",
  "tx": {
    "hash": "4f2c…e7", "chain_id": 20,
    "bundle": { "anchor": "6b1d…c4",
                "nullifiers": ["8c04…d1", "5e77…20", "03aa…6f", "e19b…42"],
                "commitments": ["2a9f…07", "b310…88", "77c1…0e", "5d20…b3"],
                "fee": "1000000", "burn_a": "0", "burn_r": "0", "burn_asset": 0, "time": 5,
                "proof_len": 1490435, "envelope_len": [1860, 1860, 1860, 1860],
                "auth_commit": "9217…ee9e", "auth_proof_bytes": 1361161 },
    "action": { "kind": "none" }
  }
}

قيمة bundle هي null في الإجراءات التي لا حزمة لها. تُذكر الإثباتات والأغلفة بأطوالها فقط. قيمة envelope_len هي 1,860 لكل خانة في السلسلة 20، التي يثبّت genesis فيها غلاف الملاحظة بهذا الحجم (envelope_bytes في rand_getLimits)؛ وكانت 1,348 في السلاسل 14 إلى 17. أما auth_commit وauth_proof_bytes فهما للتفويض المجزّأ (منذ السلسلة 17): الالتزام العلني c = H(AUTH, nk, salt) الذي ينشره إثبات الحزمة وإثبات التفويض معًا، وطول إثبات التفويض. وفي سلسلة بلا hc_auth تكونان أصفارًا و0.

bundle هي حزمة الأصل المخفي (منذ السلسلة 14): أربع خانات مدخلات وأربع خانات مخرجات، فثمة دائمًا أربعة nullifiers وأربعة commitments وأربعة envelope_len، بما فيها الوهمية. تحمل كل معاملة حزمة واحدة على الأكثر؛ ولا حزمة ثانية. وليس فيها حقل asset: الخانتان 0–1 تحملان أصلًا خاصًا والخانتان 2–3 تحملان RAND، ولا شيء علنيًّا يبيّن أيَّ أصل نقلته الخانتان 0–1. فحوالة RAND وحوالة أي رمز RPL كلتاهما "kind": "none" مع burn_a وburn_r وburn_asset كلها 0 — الشكل نفسه، حقلًا بحقل. ولا يوجد نوع token_transfer. وحقول الحرق الثلاثة هي البيان العلني الوحيد للحزمة عن القيمة الخارجة من المجمّع:

  • burn_a / burn_asset — مقدار الأصل الخاص المحروق، وأيّ أصل هو. غير صفري في token_burn أو bridge_burn، حيث يساويان amount وasset في الإجراء، وفي invoke تكون قيمة inflow فيه deposit أو burn.
  • burn_r — RAND المحروق. غير صفري في bond (يساوي amount فيه) وفي register_aggregator وفي invoke يودع RAND في خزنة البرنامج.
  • fee — رسم RAND، ويُدفع دائمًا من الخانتين 2–3.

عرض الإجراءات (كل amount وrelayer_fee وinitial_amount سلسلة عشرية؛ ومقادير الرمز بوحداته هو، لا بوحدات RAND):

kindfields
none—
mintcm، amount، minter (base58 للمدقّق)
deployprogram، words، public_words_len
callprogram، proof_len، input_envelope_len (تكون null حين لا يحمل الاستدعاء غلافًا)
bondvalidator، amount، registered
unbondvalidator، amount، nonce
withdrawvalidator، amount، nonce، time
bridge_attestattestation_len، recipient، asset، asset_index، amount، time، r، commitment، pq_signers (فهارس الأوصياء المشاركين في التوقيع ضمن pq_guardians؛ أما التواقيع البالغ طول كل منها 2,420 بايت فلا تُعرض). تكون asset_index وamount وcommitment قيمة null عند تدوير مجموعة الأوصياء. أما r فمشتقة، blake3("rand-deposit-r-1" ‖ mu) على الخلاصة التي وقّع عليها الأوصياء. ومنذ v0.6.8 أيضًا deposit_amount (ملاحظة المودِع: amount، أي الإجمالي الذي وقّع عليه الأوصياء، ناقص رسم الجسر) وfee_note ({ amount, asset, time, r, commitment }، ملاحظة الخزينة دون مالكها، أو null بلا رسوم جسر)؛ وcommitment هو ورقة الإيداع الصافي
bridge_burnasset، amount، relayer_fee، to_chain، token (الضمان المراد استرداده)، to. تحمل حزمة واحدة الحرق كله: فـ burn_asset وburn_a فيها هما asset وamount في الإجراء. ومنذ v0.6.8 أيضًا release_amount (ما يطلقه الجسم الموقَّع، أي amount ناقص رسم الجسر) وfee_note، كما في الإثبات
register_tokenname، symbol، decimals، authority ("none" أو "key" أو "bridge" أو "program")، index، initial_amount، initial ({ amount, recipient, time, r } أو null)
token_mintasset، amount، recipient، time، r، nonce
set_authorityasset، nonce، new_authority (base58، أو null للتنازل)
token_burnasset، amount؛ ويكرر burn_asset / burn_a في الحزمة قيمتيهما
pause_mintsnonce؛ بلا حزمة وبلا رسم، يوقّعه مفتاح الإيقاف في genesis
unpause_mintsnonce، pq_signers؛ بلا حزمة وبلا رسم
register_bridged_tokenname، symbol، salt، chain، token، decimals (منازل المصدر للضمان الأول)، nonce، asset_id، pq_signers
list_backingtoken_index، chain، token، decimals، nonce، pq_signers
rotate_pq_guardiansnew_pq_guardians، nonce (قيمة rotation_nonce المستهلكة)، pq_signers (فهارس ضمن مجموعة PQ قبل التدوير)؛ بلا حزمة وبلا رسم، في سلاسل الجسر ذات rules_v2 فقط
rotate_pause_keynew_pause_key، nonce، pq_signers؛ بالشروط نفسها
rotate_pq_guardians_v2، rotate_pause_key_v2v0.6.8: حقول الصيغة الأولى، مضافًا إليها possession_signatures (عدد) في صيغة PQ. بلا حزمة وبلا رسم؛ ومطلوبان في سلسلة يضبط فيها bridge.rotation في genesis القيمة needs_possession، كما في السلسلة 20. ويسري التدوير بعد delay_secs (86,400 ثانية في السلسلة 20)
cancel_rotationv0.6.8: rotation_kind ("pq_guardians" أو "pause_key")، nonce؛ يوقّعه مفتاح الإيقاف الحالي، ويُسقط تدويرًا معلّقًا
admit_validatorv0.6.8: candidate (عنوان)، candidate_key (hex)، voters (عناوين). بلا حزمة وبلا رسم: تصويت مجموعة المدقّقين للسماح لمفتاح جديد بالتسجيل، في سلسلة ذات staking.admission_by_vote، كالسلسلة 20
slash_equivocationv0.6.8: offender، view، first وsecond ({ hash, height })؛ في السلاسل ذات staking.slashing فقط، وليست السلسلة 20 منها
invokev0.6.8، RPL-2: حقول الاستدعاء (program، proof_len، input_envelope_len) وtransition الخاص به (أدناه). في السلاسل ذات قسم program_state فقط، كالسلسلة 20
register_aggregator، unbond_aggregator، withdraw_aggregator، slash_aggregator، aggregateحقولها العلنية؛ في سلاسل التجميع فقط
claim_vested، revoke_vesting، bond_vested، unbond_vestedentry (hex)، amount (unvested عند الإلغاء)، nonce؛ وtime عند المطالبة أو الإلغاء؛ وvalidator وregisters عند الربط؛ ومنذ v0.6.8 signers عند الإلغاء (مواضع موقّعيه في revokers الخاصة بالإدخال). بلا حزمة؛ في السلاسل ذات قسم vesting في genesis فقط، وليست السلسلة 20 منها

تسجيل الرمز وعمليات سكّه علنية، كما هو الإيداع عبر الجسر: كل كلمة في الملاحظة المسكوكة موجودة في الإجراء (وقيمة from فيها هي MINT_FROM الثابتة للسلسلة)، فيعيد المستلم بناء الملاحظة من هذه الحقول دون فكّ تشفير أي شيء. وسلاسل النوع bridge_attest وtoken_mint وregister_token وinvoke هي ما يعتمد عليه مسح المحفظة، ويثبّتها اختبار.

استدعاء invoke عند الارتفاع 3,079 في السلسلة 20، قرأ خلية واحدة وحذفها ودفع ملاحظتين من الخزنة:

{ "kind": "invoke", "program": "aaaf…4b21", "proof_len": 1433874, "input_envelope_len": null,
  "transition": {
    "reads":  [{ "key": "0100…fa98", "value": "0000000004000000…00000000" }],
    "writes": [{ "key": "0100…fa98", "value": "0000000000000000000000000000000000000000000000000000000000000000" }],
    "inflow": "none",
    "pays":  [{ "asset": 0, "amount": "1000000000", "recipient": "rand1…", "time": 3027, "r": "87e6…9a67", "cm": "2555…6487" },
              { "asset": 4, "amount": "2000000000", "recipient": "rand1…", "time": 3027, "r": "b833…f390", "cm": "2b70…f204" }],
    "mints": [] } }

كل ما فيه علني بالتصميم. reads هي الخلايا التي قرأها البرنامج مع القيم التي قرأها: صُنع الإثبات على أساسها، ويرفض السجل المعاملة ما لم تظل صحيحة. وwrites هي الخلايا التي كتبها؛ والقيمة المكتوبة المؤلفة من 64 صفرًا تحذف الخلية. مفتاح الخلية وقيمتها من النوع Word8. أما الداخل فهو ما في الحزمة: burn_r هو RAND المودَع في خزنة البرنامج، وburn_a من burn_asset هو الرمز الذي تسمّيه inflow، أي deposit في الخزنة أو burn (رمز البرنامج نفسه)، وnone حين تكون burn_a صفرًا. والخارج ملاحظة واحدة تحسبها السلسلة لكل دفعة، pays من الخزنة، ثم mints من رمز سلطة سكّه هي هذا البرنامج. وكل كلمة من كل ملاحظة موجودة هنا بأسماء حقول token_mint؛ وtime هو وقت الحزمة، وcm الورقة التي أضافتها السلسلة، وقيمة from في الملاحظة هي PROGRAM_FROM الثابتة للسلسلة. وكلمات مخرجات البرنامج الثماني على الإيصال، كما في الاستدعاء.

لا يحمل أي رد على حوالة مرسِلًا ولا مستلمًا ولا nonce ولا مقدارًا ولا أصلًا: لا يوجد مثل هذا الحقل في حوالة مخزَّنة.

rand_getRawTransaction

المعاملات [hash]. النتيجة: المعاملة المثبَّتة كاملةً بصيغة bincode hex، بما فيها بايتات الإثبات — وهو ما يحتاجه المجمِّع ولا يعرضه rand_getTransaction أبدًا.

البرامج والإيصالات

rand_getProgram

المعاملات [program_id]. النتيجة null أو { "id", "base_pc", "words_len", "code_hash", "deployed_at", "public_words_len", "public_digest" }. لا حقل deployer: فنشر البرنامج تدفع كلفته حزمة. وpublic_words_len هو طول المدخل العلني للبرنامج وقت النشر (0 إن لم يكن له مدخل)؛ وpublic_digest هو خلاصته، أي القيمة التي يُتحقَّق من إثبات كل استدعاء مقابلها، أو null إن لم يكن له مدخل.

rand_getProgramCode

المعاملات [program_id]. النتيجة null أو { "base_pc": 0, "words": [ … ] }.

rand_getProgramPublic

المعاملات [program_id]. النتيجة: الكلمات العامة للبرنامج وقت النشر في سلسلة سداسية عشرية واحدة، وكل كلمة بأربعة بايتات بترتيب little-endian (ثمانية أرقام سداسية عشرية للكلمة): [1, 2, 0xdeadbeef] تساوي "0100000002000000efbeadde". وتكون "" لبرنامج نُشر دون مُدخل عام، وnull لمعرّف لا يعود لأي برنامج. تمرّر المحفظة التي تُثبت استدعاءً هذه الكلمات إلى المُثبِت (prover)، ويتحقق السجل من التزام الإثبات مقابل public_digest الخاص بالبرنامج.

rand_getProgramCell

v0.6.8، RPL-2. المعاملات [program_id, key]، والمفتاح Word8 بصيغة 64 رقمًا سداسيًا عشريًا (مع 0x أو بدونها). النتيجة { "key": "<64 hex>", "value": "<64 hex>" }. الخلية التي لم يكتب فيها البرنامج قط، أو كتب فيها أصفارًا (وهو ما يحذفها)، تُقرأ 64 صفرًا، وهو الترميز الوحيد لحالة «غير موجودة»؛ وكذلك أي مفتاح لبرنامج لم ينشره أحد، لأن وجود البرنامج لا يُفحص. { "enabled": false } على سلسلة لا تحوي قسم program_state. الخلية عامة بالتصميم: وهذا ما تقرؤه المحفظة لبناء reads الخاصة بـinvoke.

rand_getProgramCells

v0.6.8. المعاملات [program_id, { "after": "<64 hex>" | null, "limit": n }]، والكائن اختياري. النتيجة { "cells": [{ "key", "value" }, …], "next": "<64 hex>" | null }: خلايا البرنامج بترتيب المفاتيح (مقارنة غير مُوقَّعة للكلمات الثماني)، بدءًا من بعد after، وعددها لا يزيد على limit (يُحصر بين 1 و1,000). تكون next آخر مفتاح قُدِّم عندما تتبعه خلايا أخرى؛ أعدها كقيمة لـafter. وتكون null في الصفحة الأخيرة. البرنامج الذي لا خلية له يجيب بـ{ "cells": [], "next": null }؛ و{ "enabled": false } عند غياب القسم.

rand_getProgramVault

v0.6.8. المعاملات [program_id]. النتيجة [{ "asset": 0, "amount": "123" }, …]، تصاعديًا بحسب فهرس الأصل (0 هو RAND، وكل فهرس آخر هو فهرس سجل الرموز)، والمبالغ سلاسل عشرية بوحدات الأصل نفسه. الصف الذي قيمته صفر غير موجود، فالخزنة الفارغة، وكذلك برنامج لم ينشره أحد، تكون []. { "enabled": false } عند غياب القسم. تدخل القيمة إلى الخزنة عبر حزمة invoke (burn_r، وburn_a من burn_asset عندما يكون inflow هو deposit)، وتخرج منها في صورة الملاحظات (notes) التي تسمّيها pays الخاصة بالانتقال.

rand_getLimits

المعاملات []. النتيجة: ما تحتاجه المحفظة من تكوين السلسلة (genesis) لبناء معاملة: حدود الاستدعاء الخمسة، وحجم غلاف الملاحظة، ومفتاح التبديل v0.6، وبرنامج المصادقة (auth guest)، وشروط الغاز، وحقول genesis الخاصة بـaudit-v6 وحدود حالة البرنامج منذ v0.6.8. على السلسلة 20:

{ "max_program_words": 65535, "max_proof_bytes": 4194304, "max_block_bytes": 20971520,
  "max_call_envelope_bytes": 65536, "max_program_public_words": 32768,
  "envelope_bytes": 1860, "hardening_v6": true,
  "hc_auth": "1e4e347f44cf86750b30a9a4bdf9ec9256efe353d4ff8017451eca7d195639c1",
  "gas_metering": "circuit", "gas_price": "100", "byte_price": "800",
  "bundle_gas_limit": 20479, "adjust_bps": 1250,
  "max_gas_price": "10000", "max_byte_price": "80000", "byte_load": "paying",
  "admission_by_vote": true, "testnet": true, "slashing": null, "binding_domain": 1,
  "proof_window_blocks": 1024,
  "program_state": { "cell_fee": "10000000", "max_reads": 8, "max_writes": 8, "max_payouts": 4 } }

يحصل genesis الذي لا يحوي حقول الحدود الخمسة (السلسلة 12) على 4096 و2097152 و4194304 و18432 و0. وكانت max_proof_bytes تساوي 8,388,608 على السلاسل 13 إلى 15.

fieldmeaning
envelope_bytes1860 عندما يثبّت genesis كل غلاف يُنشئ ملاحظات على هذا الطول بالضبط، أي صيغة الملاحظة الحاملة للمذكرة؛ وnull في genesis بلا هذا الحقل (السلاسل 14 إلى 17)، حيث تختم المحفظة الغلاف ذا 1,348 بايتًا دون مذكرة. لا توجد قيمة أخرى
hardening_v6true عندما يشغّل genesis قواعد الصلاحية v0.6. عندئذٍ تُثبت المحفظة الاستدعاء على المُدخل العام للبرنامج يليه ارتباط الاستدعاء (call binding) الخاص بالمعاملة، لا على المُدخل العام وحده: تُختار ملاحظات حزمة الرسوم أولًا، ويُثبت الاستدعاء ثانيًا، وتأتي الحزمة أخيرًا. السلسلة التي تحمل هذه الراية ترفض الإثبات القديم، والسلسلة التي لا تحملها ترفض الجديد
hc_authبرنامج المصادقة الذي يثبّته genesis، بصيغة سداسية عشرية، أو null. عند تعيينه يكون hc_bundle هو bundle guest v3 وتحمل كل حزمة auth_commit وإثبات مصادقة: تعطي المحفظة bundle guest القيمة nk وملحًا جديدًا، وتُثبت برنامج المصادقة على مفتاح الإنفاق
gas_metering"circuit" على سلسلة يحوي genesis فيها قسم gas (العدّاد داخل الدارة)؛ و"header" على سلسلة بلا هذا القسم عندما تشغّل العقدة سياسة الغاز الخاصة بها (--gas-price، --byte-price)؛ وnull إن لم يكن هذا ولا ذاك
gas_price, byte_priceوحدات لكل غاز، ووحدات لكل KiB من إثبات الاستدعاء وغلاف مُدخله، بصيغة سلاسل عشرية. في ظل قسم gas تكون حالة إجماع ومتطابقة على كل العقد: ومع gas.dynamic، كما في السلسلة 20، هي أسعار رأس السلسلة الحالية، وتتحرك في كل كتلة بحسب الامتلاء، ولا تهبط أبدًا دون الحدود الدنيا في genesis (100 و800) ولا ترتفع فوق الحدود العليا؛ وبدونه هي الأسعار الثابتة للقسم. وبلا قسم تكون سياسة هذه العقدة نفسها، وقد تجيب عقدتان بجوابين مختلفين
bundle_gas_limitالغاز الثابت الذي يجب أن يعلنه إثبات كل حزمة، من قسم gas في genesis؛ وnull بلا قسم
adjust_bpsأكبر حركة لسعر في كتلة واحدة يجريها المتحكم الديناميكي، بالنقاط الأساسية؛ وnull على سلسلة بلا gas.dynamic
max_gas_price, max_byte_pricev0.6.8: الحدود العليا التي لا يرفع المتحكم سعرًا فوقها، سلاسل عشرية؛ "10000" و"80000" على السلسلة 20، وnull حيث لا يحدد genesis حدًا (السلسلتان 18 و19)
byte_loadv0.6.8: "paying" عندما لا يحرّك byte_price إلا إثبات الاستدعاء وغلاف مُدخله، فلا تحرّكه كتلة من التحويلات، كما في السلسلة 20؛ وnull حيث تُحتسب بايتات كل معاملة (السلسلتان 18 و19)
admission_by_votev0.6.8: هل يحتاج السند الذي يسجّل مفتاح مدقّق جديدًا إلى تصويت مجموعة المدققين أولًا (rand_getAdmitted)؛ true على السلسلة 20
testnetv0.6.8: علامة testnet في genesis، التي تتيح وجود صنبور (faucet) بجانب قسم الجسر؛ true على السلسلة 20، وfalse على كل سلسلة سبقتها
slashingv0.6.8: { "equivocation_bps", "jail_epochs" }، أي كلفة ازدواجية القائد في التصويت (equivocation)، أو null؛ وnull على السلسلة 20
binding_domainv0.6.8: 0 حيث يربط ارتباط المعاملة وكل رسالة إجراء موقَّعة معرّف السلسلة وحده (السلاسل 14 إلى 19)، و1 حيث تحمل كذلك تجزئة genesis، فلا يصحّ إثبات أو توقيع صُنع لسلسلة على أي سلسلة أخرى (السلسلة 20). تحدد المحفظة الصيغة التي ستُثبتها بحسب معرّف السلسلة، لا بحسب هذا الجواب أبدًا: تعطي محفظة rand بالإصدار v0.6.8 المعرّفات 14 إلى 19 صيغة معرّف السلسلة وكل معرّف آخر صيغة الارتباط بـgenesis، وتقرأ هذا الحقل لترفض مبكرًا فقط. لا تستطيع محفظة أقدم من v0.6.8 الإرسال على السلسلة 20
proof_window_blocksv0.6.8: كم يبلغ عمر مرساة الحزمة الأقصى بالكتل، وكم يجوز أن يتأخر time الخاص بها عن الارتفاع، نافذة واحدة للاثنين؛ 1024 على السلسلة 20، وnull (256) على السلاسل حتى 19. تقرؤه المحفظة ذات المُثبِت البطيء أو المفوَّض لتعرف كم يجوز أن يستغرق الإثبات
program_statev0.6.8، RPL-2: قسم program_state في genesis وحدود invoke فيه، أو null، وعندئذٍ يُرفض كل invoke ولا يمكن تسجيل أي رمز برنامج. cell_fee هي وحدات RAND (سلسلة عشرية) التي يزيدها الحد الأدنى لرسم الـinvoke عن كل خلية ينشئها، أي كتابة قيمة غير صفرية في خلية تُقرأ أصفارًا؛ أما إعادة الكتابة أو الحذف أو كتابة الأصفار فلا تكلّف شيئًا. وmax_reads وmax_writes وmax_payouts (المدفوعات والسك معًا) حدود صارمة. وعمليًا تقيّد قاعدة المقطع أولًا: يجب أن تتسع كلمات سياق الانتقال (11 + 16 لكل قراءة أو كتابة + 3 لكل دفعة) بجوار المُدخل العام للبرنامج وكلمات الارتباط الثماني دون أن يكبر الجدول العام لـzkVM؛ وهذا الجدول لبرنامج بلا مُدخل عام 128 صفًا، فيبقى 119 كلمة سياق

العقدة التي سبقت حقلًا ما تجيب بدونه. لا شيء في هذا الجواب موثَّق، فلا تأخذ المحفظة envelope_bytes بقول العقدة وحده: تختم محفظة rand الغلاف القديم على معرّفات السلاسل 14 إلى 17 أيًّا كان جواب العقدة، وينبغي لسائر العملاء أن يفعلوا ذلك.

rand_getReceipt

المعاملات [tx_hash]. النتيجة null إلى أن يُثبَّت الاستدعاء، ثم { "tx", "program", "tier": 14, "outputs": [1, 0, 25, 0, 0, 0, 0, 0], "height": 17, "index": 0, "h_in": "9c0e…7f", "h_pub": null }. لا يوجد حقل effect. وh_pub هو ملخّص المُدخل العام للبرنامج وقت النشر الذي فُحص إثبات الاستدعاء مقابله، وnull لبرنامج بلا مُدخل عام. لـinvoke (v0.6.8) إيصال استدعاء، وتحمله rand_getReceipts وموضوع receipts كما هو.

rand_getReceipts

المعاملات [program_id, from_height, to_height, limit?]. النتيجة { "receipts": [ … ], "next_height": 2051 }: إيصالات program_id حيث from_height <= height <= to_height، بحسب الارتفاع ثم الفهرس، وكل إيصال هو كائن rand_getReceipt تمامًا. القيمة الافتراضية لـlimit هي 256 وهي حدّه الأقصى، ولا يقسم ارتفاعًا أبدًا: فما إن تضم الصفحة limit إيصالًا حتى تقدّم بقية ذلك الارتفاع. وnext_height هو أول ارتفاع لم يُقدَّم، أو null عندما أنهى to_height الصفحة. -32602 عندما يقلّ to_height عن from_height.

rand_getCallEnvelope

المعاملات [tx_hash]. النتيجة null، أو { "tx", "h_in", "kem_ct", "to_sender", "to_auditor", "body" } بصيغة سداسية عشرية — وهي نص مُدخل الاستدعاء المختوم، يُقدَّم كما هو؛ ولا تملك العقدة مفتاحًا يفتحه. وتكون null عندما لم ينشر الاستدعاء شيئًا (--no-envelope)، أو لا تكون المعاملة استدعاءً، أو لا يوجد إيصال.

التخزين (Staking) والمعروض

rand_getValidators

المعاملات []. النتيجة: صف لكل مدخل في السجل، بترتيب العناوين، والمبالغ سلاسل عشرية:

[{ "address": "…", "stake": "1000000000000",
   "pending": [{ "release_epoch": 41, "amount": "5000000000" }],
   "rewards": "4000000", "payout": "rand1…", "nonce": 3, "active": true, "jailed_until": null }]

jailed_until (v0.6.8) هو أول حقبة يجوز فيها أن يعود مفتاح خُفِّضت حصته إلى مجموعة، (18446744073709551615 إلى الأبد)، وnull عندما لا يكون مسجونًا. لا تحوي السلسلة 20 staking.slashing، فهي دائمًا null هناك.

rand_getAdmitted

الإصدار v0.6.8. المعاملات []. النتيجة { "admission_by_vote": true, "max": 256, "admitted": ["<address>", …] }: المفاتيح التي صوّتت مجموعة المدقّقين (validators) لإدخالها بواسطة AdmitValidator ولم تُسجَّل بعد، بترتيب العناوين. في سلسلة تضبط بدايتها (genesis) القيمة staking.admission_by_vote، كما في سلسلة 20، يجب أن يكون المفتاح الجديد الذي تسجّله عملية Bond من بين هذه المفاتيح. تمثّل max عدد ما يحتفظ به السجل في آن واحد. في سلسلة بلا هذا الخيار تكون admission_by_vote هي false، وتكون القائمة فارغة دائمًا، ولا يحتاج التسجيل إلى تصويت. أجابت سلسلة 20 بـ "admitted": [] في 2026-10-01.

rand_getEpoch

المعاملات []. النتيجة { "epoch": 41, "epoch_blocks": 1000, "next_set": ["…", "…"] }؛ وnext_set تقدير استشرافي.

rand_getSupply

المعاملات []. النتيجة:

{ "height": 1998,
  "genesis_deposited": "…", "genesis_staked": "…", "faucet_minted": "…",
  "faucet_epoch": "…", "faucet_minted_in_epoch": "…",
  "withdraw_deposited": "…", "fees_paid": "…", "burned": "…",
  "subsidised": "…", "sealed_blocks": "…", "aggregator_bonds": "…", "slashed": "…",
  "registration_fees_burned": "…",
  "vesting_issued": "…", "vesting_released": "…", "vesting_in_register": "…", "vesting_locked": "…",
  "program_rand_out": "…", "program_rand_held": "…",
  "pool_value": "…", "register_total": "…", "total_supply": "…", "invariant_holds": true }

لا تتحرك subsidised وsealed_blocks وaggregator_bonds وslashed إلا في سلسلة ذات تجميع (aggregation). أما faucet_epoch وfaucet_minted_in_epoch فهما عدّاد الصنبور (faucet) لكل حقبة مقابل staking.faucet_budget_per_epoch (حالة إجماع في سلسلة 20). والحقول الأربعة vesting_* هي عدّادات الاستحقاق التدريجي في بداية السلسلة، وقيمها كلها "0" في سلسلة بلا قسم vesting، وهذه حال سلسلة 20. أما program_rand_out وprogram_rand_held (الإصدار v0.6.8، RPL-2؛ وقيمتاهما "0" بلا قسم program_state) فهما كمية RAND التي دفعتها عمليات الاستدعاء (invokes) من خزائن البرامج على هيئة ملاحظات (notes) (جانب المجمّع، داخل pool_value)، وما لا تزال الخزائن تحتفظ به (جانب السجل، داخل total_supply)؛ وقد دخلت عبر burn_r في عملية الاستدعاء، فهي داخل burned من جانب المجمّع. وregistration_fees_burned هي Σ رسوم تسجيل الرموز المحروقة بموجب tokens.burn_registration_fee في بداية السلسلة، وهو ما تضبطه سلسلة 20؛ وتطرحه invariant_holds مع slashed مما أصدرته السلسلة. يشرح Supply هذه المعادلة.

rand_getEmission

المعاملات []. النتيجة { "inflation": "0", "subsidy": null, "faucet": true }. قيمة inflation ثابتة هي "0". وsubsidy هو جدول إعانة تجميع الكتل (current وbase وhalving_blocks وsealed_blocks وnext_halving_at) وقيمته null في سلسلة بلا قسم aggregation، وهذه حال سلسلة 20. وتعكس faucet ما تعيده rand_status.

الجسر

تجيب الأربع جميعها في أي سلسلة؛ وفي سلسلة بلا قسم bridge تكون الحالة { "enabled": false } ويكون السجل []. في بداية سلسلة 20 قسم كهذا: مجموعة الحراس 1 (guardian_set_index يساوي 1) بثمانية حراس وثمانية حراس PQ ومفتاح إيقاف مؤقت، وburn_sequence يساوي 13 عند البداية، وحد أدنى للإعادة (min_inbound_sequence يساوي 3 لسلاسل المصدر 2 و3 و4، و7 لسلسلة المصدر 5)، وقواعد الجسر rules_v2 بسقف سكّ عام قدره 4,000 zUSD لكل نافذة مدتها 24 ساعة عبر كل الضمانات، ومجموعتان جديدتان في v0.6.8: rotation (تدوير حراس PQ أو مفتاح الإيقاف المؤقت يتطلب إثبات الحيازة بالمفاتيح الجديدة ويسري بعد 86,400 ثانية من إتمامه) وfees (10 نقاط أساس من كل إيداع و10 نقاط أساس من كل حرق، تحتفظ بها Rand على هيئة ملاحظة zUSD لعنوان خزينة). كان في سلسلة 19 burn_sequence يساوي 8، وحدّان أدنيان هما 1 و4، ولم تكن فيها أي من المجموعتين. وفي قسم tokens رسم تسجيل registration_fee قدره 1 RAND (يُحرق)، وسقف mint_cap_per_day لكل ضمان قدره 10000000000000 (100,000 zUSD بثمانية منازل عشرية)، ويُدرج zUSD نفسه: منقولًا من سلسلة 14 عند البداية، بمعرّف الأصل نفسه، والفهرس 1، وسبعة ضمانات.

rand_getBridgeState

المعاملات []. النتيجة { "enabled": false }، أو:

{
  "enabled": true,
  "emitter": "01…",
  "emitters": { "2": "02…" },
  "guardian_set_index": 0,
  "guardians": ["aabb…"],
  "pq_guardians": ["…"],
  "mint_paused": false,
  "pause_nonce": 0,
  "list_nonce": 0,
  "pause_key": "…",
  "registration_fee": "1000000000",
  "burn_sequence": 1,
  "rotation_nonce": 0,
  "rules_v2": { "global_mint_cap_per_window": "…", "cap_window_secs": 86400,
                "global_minted_in_window": "…", "global_mint_headroom": "…" },
  "min_inbound_sequence": { "2": 2, "3": 2, "4": 2, "5": 2 },
  "rotation_rules": { "delay_secs": 86400, "needs_possession": true },
  "pending_rotations": [],
  "fees": { "mint_bps": 10, "burn_bps": 10, "recipient": "rand1…" },
  "assets": [ … ]
}
الحقلالمعنى
emitterعنوان المُصدِر الصادر لهذه السلسلة، 32 بايت بالست عشري
emittersمعرّف سلسلة المصدر ← عنوان المُصدِر الموثوق هناك
guardiansعناوين المجموعة الحالية، 20 بايت لكل عنوان، بالست عشري
pq_guardiansمجموعة PQ: المفاتيح العامة لـ Dilithium2 (1,312 بايت)، بالست عشري، متوافقة الفهارس مع مجموعة الحراس الحالية (المجموعة 1 في سلسلة 20). يحمل كل BridgeAttest نصابًا من التوقيعات المشتركة منها. لا يحرّكها تدوير مجموعة الحراس أبدًا؛ لا يفعل ذلك إلا rotate_pq_guardians، في سلسلة ذات rules_v2
mint_pausedما دامت true يُرفض كل إقرار تحويل برسالة bridge minting is paused؛ وتبقى عمليات الحرق والتدوير مفتوحة
pause_nonceالقيمة التي يجب أن يحملها الإيقاف المؤقت التالي أو رفعه؛ وكلاهما يزيدها
list_nonceالقيمة التي يجب أن يحملها register_bridged_token أو list_backing التالي؛ وكلاهما يزيدها
pause_keyمفتاح Dilithium2 الوحيد الذي يجوز له إيقاف السكّ مؤقتًا، بالست عشري. لا يستطيع إلا الإيقاف: أما رفع الإيقاف فيحتاج إلى نصاب حراس PQ
registration_feeما يستحقه RegisterBridgedToken فوق أساس الحزمة، بوحدات RAND، سلسلة عشرية
burn_sequenceعدد الرسائل الصادرة المُصدَرة حتى الآن
rotation_nonceالقيمة التي يجب أن يحملها rotate_pq_guardians / rotate_pause_key التالي
rules_v2السقف العام ونافذته المتحركة، أو null في سلسلة بلا قواعد الجسر v2. وفيها يصبح السقف لكل ضمان نافذة متحركة أيضًا، ويُرفض الإدراج ما دام السكّ متوقفًا مؤقتًا. ومنذ v0.6.8 تحمل أيضًا global_minted_in_window وglobal_mint_headroom، وهما سلسلتان عشريتان
min_inbound_sequenceالحد الأدنى للإعادة عند بداية السلسلة: معرّف سلسلة المصدر ← أدنى تسلسل يجوز أن يحمله تحويل من تلك السلسلة، أعداد عادية؛ وnull في سلسلة بلا حد (سلسلة 15 وما قبلها). يُرفض bridge_attest الأدنى منه برسالة BelowReplayFloor، وهو حكم دائم. يقرؤه المُرحِّل (relayer) ليُسقط قفلًا سبق أن سكّته السلسلة التي اقتُطعت منها هذه السلسلة
rotation_rulesv0.6.8: { "delay_secs", "needs_possession" } من bridge.rotation في بداية السلسلة، أو null. وبموجبها يكون التدوير هو الإجراء _v2، ويحمل توقيعات حيازة المفاتيح الجديدة، وينتظر delay_secs قبل أن يسري
pending_rotationsv0.6.8: التدويرات المُتمَّة التي لم تسرِ بعد، كلٌّ منها { "kind": "pq_guardians", "new_pq_guardians", "effective_at_secs" } أو { "kind": "pause_key", "new_pause_key", "effective_at_secs" }؛ وnull بلا rotation_rules. ويُسقط cancel_rotation الموقَّع بمفتاح الإيقاف المؤقت الحالي أحدها
feesv0.6.8: { "mint_bps", "burn_bps", "recipient" } من bridge.fees في بداية السلسلة، أو null (السلاسل من 14 إلى 19). تحتفظ السلسلة بهذه الحصة من كل إيداع وكل حرق، مقرّبةً نزولًا إلى وحدة إطلاق كاملة من الضمان، على هيئة ملاحظة zUSD إلى recipient. يُقيَّد للإيداع إجماليه ناقصًا الرسم؛ ويُطلق جسم الحرق الموقَّع مبلغه ناقصًا الرسم. تقرؤه المحفظة لتقدّر قيمة إيداعها، ولتعيد بناء ملاحظات الرسوم حين تكون هي recipient
assetsصفوف rand_getAssets

لا أرصدة: القيمة المنقولة بالجسر ملاحظات. لم يعد هناك next_index: يُدرج الرمز المنقول بالجسر، تحت فهرس ثبّته تسجيله من قبل، قبل أن يمكن إيداعه، فلا يبقى فهرس يُتوقَّع. اقرأ فهرس رمز مُدرج من assets أو من rand_getTokens.

rand_getAssets

المعاملات []. النتيجة: سجل أصول الجسر، تصاعديًا بحسب الفهرس، أو []:

[{ "index": 1, "chain": 2, "token": "aaaa…", "asset_id": "…", "decimals": 6, "locked": "600",
   "mint_cap_per_day": "10000000000000", "minted_today": "1000", "mint_day": 20350,
   "minted_in_window": "1000", "mint_window_secs": 86400, "mint_headroom": "390000000000" }]

منذ v0.6.8 يحمل كل صف ضمان، هنا وفي كل موضع تُقدَّم فيه الضمانات (rand_getBridgeState.assets، وbackings في rand_getToken وrand_getTokens وrand_getTokenSupply)، الحقلين minted_in_window (سلسلة عشرية) وmint_window_secs، وكلاهما null في سلسلة بعدّاد يومي، والحقل mint_headroom: أكبر إيداع في ذلك الضمان تسمح به السقوف عند زمن كتلة الرأس، أي السقف لكل ضمان ناقصًا ما سُكّ منه، وبموجب القواعد v2 لا يزيد على ما بقي لنافذة السجل كله. اقرأ mint_headroom لا mint_cap_per_day − minted_today، فهذا يتجاهل السقف العام. وبموجب القواعد v2، كما في سلسلة 20، تكون minted_today عدّ النافذة المتحركة، وهو الرقم الذي يُفحص السقف لكل ضمان مقابله؛ أما وصف العدّاد اليومي أدناه فهو وصف سلسلة 14.

صف واحد لكل ضمان (عملة المصدر)، فالرمز ذو سبعة ضمانات سبعة صفوف تحت index واحد. وindex هو كلمة asset التي تحملها ملاحظة ذلك الأصل؛ الفهرس 0 هو RAND ولا يكون في السجل أبدًا. وdecimals هي المنازل العشرية لعملة المصدر في الضمان. أما locked وmint_cap_per_day وminted_today فهي سلاسل عشرية بوحدات الرمز نفسه ذات الثماني منازل عشرية، لا بوحدات RAND أبدًا؛ وmint_day عدد صحيح عادي، رقم يوم UTC. وmint_cap_per_day هي tokens.mint_cap_per_day في بداية السلسلة، أي أكثر ما يجوز لضمان واحد سكّه في كل يوم UTC من زمن الكتلة. وminted_today هي ما سكّه الضمان في mint_day، يوم UTC (timestamp_ms / 86,400,000) لـكتلة الرأس، فيُقرأ عدّاد متبقٍّ من يوم سابق "0" متى تجاوز الرأس منتصف الليل. يُرفض الإيداع الذي يتجاوز السقف برسالة MintCapExceeded ويصبح مقبولًا في اليوم التالي. وchain وtoken هما الهوية السلكية التي يوقّع الحراس عليها؛ وasset_id هو blake3 لهما، وهو ما تحسبه rand_bridgeAssetId.

rand_bridgeAssetId

المعاملات [token_chain, token_address] (عدد صحيح، 32 بايت بالست عشري). النتيجة: معرّف الأصل، 64 خانة ست عشرية. حساب خالص.

rand_getBridgeBurn

المعاملات [sequence]. النتيجة null أو { "sequence": 0, "body_hex": "…", "digest": "…", "tx": "…", "height": 2, "amount": "…", "release_amount": "…", "fee": "…" }.

الحقول الثلاثة الأخيرة من v0.6.8، في كل سلسلة، سلاسل عشرية بوحدات الرمز ذات الثماني منازل عشرية. وrelease_amount هو المبلغ الذي يحمله الجسم الموقَّع، مقروءًا من body_hex نفسه: ما يطلقه عقد المصدر، ومنه يدفع رسم مُرحِّل الجسم. وfee هو رسم الجسر الذي احتفظت به السلسلة ملاحظةَ خزينة، وamount ما أحرقته الحزمة، أي release_amount + fee. بلا bridge.fees (السلاسل من 14 إلى 19) تكون fee هي "0". التسلسل 13 في سلسلة 20، حرق قدره 0.999 zUSD: "amount": "99900000" و"fee": "99900" و"release_amount": "99800100".

الرموز (RPL)

سجل رموز RPL: كل رمز، منقول بالجسر أو أصلي. يشرح Tokens المعيار.

rand_getTokens

المعاملات [from_index, limit]، وكلاهما اختياري (0 و1000؛ ويُقيَّد limit بـ 1,000). النتيجة: السجل تصاعديًا بحسب الفهرس ابتداءً من from_index، مقروءًا بالمدى من ذلك الفهرس:

{ "enabled": true, "registration_fee": "1000000000", "next_index": 3, "max_tokens": 4096,
  "burn_registration_fee": true, "bound_note_value": true,
  "tokens": [
    { "index": 2, "id": "<64 hex>", "id_text": "rpl1…", "name": "Test Coin", "symbol": "TST",
      "decimals": 6,
      "authority": { "kind": "key", "key": "<Dilithium2 key, hex>", "address": "<base58>" },
      "mint_nonce": 1, "total_supply": "5700", "registered_at": 3 }
  ] }

على سلسلة لا تتضمن قسم tokens: { "enabled": false, "tokens": [] }. index هو حقل asset الذي تحمله ملاحظة الرمز (0 هو RAND ولا يُدرج أبدًا). id هو معرّف أصل الرمز وid_text صيغته النصية ذات المجموع الاختباري: bech32m، وبادئة HRP هي rpl، على بايتات المعرّف الاثنين والثلاثين، بطول 62 حرفًا. authority واحدة مما يلي:

kindالحقول الأخرى
none— (عرض ثابت، أو جرى التنازل عنه)
keykey, address
bridgebackings: [{ "chain", "token", "decimals", "locked", "mint_cap_per_day", "minted_today", "mint_day" }]، وهي حقول rand_getAssets، بصف واحد لكل غطاء
programprogram

المعروضات وlocked وmint_cap_per_day وminted_today وregistration_fee سلاسل عشرية (بوحدات RAND للحقل registration_fee، وبوحدات الرمز لبقية الحقول)؛ أما next_index وmint_day وmax_tokens فأعداد. max_tokens هو السقف الابتدائي للسجل (4,096 على السلسلة 20؛ وnull إن لم يوجد سقف)، وما بعده يُرفض التسجيل بالخطأ RegistryFull. يبيّن burn_registration_fee ما إذا كانت رسوم التسجيل تُحرق بدلًا من أن تُدفع إلى المقترِح؛ ويبيّن bound_note_value ما إذا كان سكّ أو إيداع بقيمة 2⁶³ فأكثر قاعدة صلاحية (إذ يرفض القبول أي منهما على كل سلسلة بصرف النظر عن ذلك). الثلاثة كلها مضبوطة على السلسلة 20. الصفحة الأقصر من limit هي الأخيرة.

لا يمكن تسجيل سلطة من نوع program ({ "kind": "program", "program": "<id>" }) إلا على سلسلة فيها قسم program_state، كما هي السلسلة 20 (v0.6.8): يبدأ الرمز بعرض صفري، ولا يسكّه أو يحرقه سوى استدعاءات ذلك البرنامج.

تحلّ المحفظة معرّف الرمز عبر هذا الإدراج، لا عبر rand_getToken أبدًا: فأصل التحويل خاص على السلسلة، وقراءة السجل كاملًا تكلّف الكلفة نفسها أيًّا كان الرمز المقصود.

rand_getToken

المعاملات [token]: فهرس في السجل (عدد أو سلسلة عشرية)، أو المعرّف المكوّن من 64 خانة سداسية عشرية (مع 0x أو بدونها، بأي حالة أحرف) أو الصيغة النصية rpl1… (كلها بأحرف صغيرة أو كلها بأحرف كبيرة). النتيجة: صف ذلك الرمز من rand_getTokens، أو null. المعرّف المشوّه — مجموع اختباري خاطئ، أو HRP آخر، أو طول خاطئ، أو أحرف مختلطة الحالة، أو غير سداسي عشري — يُعاد عليه -32602، فلا يصير الخطأ المطبعي رمزًا آخر أبدًا. والبحث عن رمز بعينه يخبر العقدة بالرمز الذي يهمّ المستدعي؛ فهو مخصص للمستكشفات والقراءات المنفردة.

rand_getTokenSupply

المعاملات [token]، بالصيغ نفسها. النتيجة null، أو:

{ "total_supply": "600",
  "backings": [{ "chain": 2, "token": "<32 bytes hex>", "decimals": 6, "locked": "600",
                 "mint_cap_per_day": "10000000000000", "minted_today": "1000", "mint_day": 20350 }] }

backings فارغة للرمز الأصلي؛ وفي الرمز المُجسَّر يساوي مجموع مبالغ locked قيمة total_supply. وتنطبق ملاحظة الخصوصية نفسها الواردة في rand_getToken.

تجميع الكتل (غير مفعّل على السلسلة 20)

هذه موجودة في العقدة للسلاسل التي يحمل تكوينها الأول قسم aggregation. على السلسلة 20 يكون السجل فارغًا ولا يُفكّ ختم أي شيء.

الطريقةالمعاملاتالنتيجة
rand_getAggregate[hash]الحقول covers وaggregator وsubsidy وproving_share وn وheight للتجميع الذي ختم المعاملة؛ وnull لأي معاملة أخرى
rand_getAggregators[]سجل المجمِّعين: address وbond وpayout وnonce وunbonding لكل صف
rand_getUnsealed[from, limit]{ "bundles": [{ "hash", "height", "excess" }], "next_from" }، وهي الحزم التي ما زال بإمكان المجمِّع تغطيتها

يُرسَل Aggregate عبر rand_sendTransaction كأي معاملة أخرى.

الاستحقاق التدريجي في التكوين الأول (غير مفعّل على السلسلة 20)

هذه موجودة في العقدة للسلاسل التي يحمل تكوينها الأول قسم vesting. لا توجد سلسلة فيها قسم كهذا بعد: وعلى السلسلة 20 تجيب كل منها بـ { "enabled": false }. تمرّرها نقطة النهاية العامة منذ 2026-10-01.

الطريقةالمعاملاتالنتيجة
rand_getVesting[id] أو [id, at_ms]، وهو معرّف الإدخال من 64 خانة سداسية عشريةالإدخال: فئته، والمستفيد، والجدول الزمني (amount وstart_ms وcliff_ms وlinear_ms وstep_ms)، وما جرى المطالبة به وإلغاؤه وربطه، وvested_now وclaimable_now وunvested_now عند as_of_ms (وقت كتلة الرأس افتراضيًا)؛ وnull لمعرّف غير معروف. منذ v0.6.8 يعرض الإدخال القابل للإلغاء revokers، وthreshold الذي يحتاجه الإلغاء منهم، وtreasury الذي يدفع إليه الإلغاء (وهي تحلّ محل revoker المفرد)، ويحمل الإدخال revoke_nonce وlocked_now
rand_getVestingSummary[]{ "enabled": true, "height", "as_of_ms", "entries", "issued", "released", "locked", "classes": [ … ] }: إجماليات كل فئة، دون مفتاح أو مالك
rand_getVestingSchedule[from_ms, to_ms, step_ms]، بحد أقصى 1,000 نقطة{ "enabled": true, "issued", "points": [{ "t_ms", "locked" }] }: إجمالي المقفل في السجل عبر الزمن

المبالغ سلاسل عشرية. تُرسَل إجراءات الاستحقاق الأربعة عبر rand_sendTransaction.

الاشتراكات (WebSocket)

ws://127.0.0.1:8545/ أو /ws. لا تخدم المقبس سوى rand_subscribe وrand_unsubscribe، وتجيب بـ -32601 عن أي شيء آخر. ثلاثة مواضيع، هي تدفقات مستقلة بلا وعد بترتيب بينها:

  • newHeads — بصيغة rand_getHead، يُرسَل مرة لكل كتلة مثبَّتة، بالترتيب، بما في ذلك أثناء المزامنة. وview هنا هو العرض الخاص بالكتلة نفسها.
  • receipts أو receipts <program_id> — إشعار واحد لكل كتلة مثبَّتة تحمل إيصال استدعاء مطابقًا واحدًا على الأقل: { "height", "hash", "receipts": [ … ] }، وكل إيصال بصيغة rand_getReceipt.
  • transaction <hash> — إشعار واحد، ثم تزيل العقدة الاشتراك: { "status": "committed", "height", "index" }، أو { "status": "rejected", "reason" } لرفض يتعلق ببايتات المعاملة نفسها (وهو الحد الذي لدى rand_getTransactionStatus). أما الرفض المعتمد على الحالة فلا يُعلَن أبدًا، فاقرنه بمهلة زمنية.
{ "jsonrpc": "2.0", "id": 1, "method": "rand_subscribe",   "params": ["newHeads"] }
{ "jsonrpc": "2.0", "id": 2, "method": "rand_unsubscribe", "params": ["1"] }
{ "jsonrpc": "2.0", "id": 3, "method": "rand_subscribe",   "params": ["receipts", "<program_id>"] }
{ "jsonrpc": "2.0", "id": 4, "method": "rand_subscribe",   "params": ["transaction", "<hash>"] }

{ "jsonrpc": "2.0", "id": 1, "result": "1" }
{ "jsonrpc": "2.0", "id": 2, "result": true }
{ "jsonrpc": "2.0", "method": "rand_subscription",
  "params": { "subscription": "1", "result": { "height": 1998, "hash": "…", "view": 2251 } } }

الحدود: 64 اتصالًا لكل عقدة (يُرفض الاتصال الخامس والستون عند الترقية بالخطأ 503)، و8 اشتراكات لكل اتصال، و64 KiB لكل إطار من العميل، ونبضة ping كل 30 s يُجاب عنها خلال 5 s، و256 إدخالًا من الأعمال المتراكمة لكل تدفق — والمشترك المتأخر أكثر من ذلك في تدفق يستمع إليه يُغلَق اتصاله بالرمز 1008 ولا يُخزَّن له مؤقتًا؛ أعد الاتصال وسدّ الفجوة بـ rand_getCompactBlocks (الرؤوس) أو rand_getReceipts (الإيصالات) أو rand_getTransactionStatus (المعاملة). وطلب GET / عاديًا بلا ترويسات الترقية يُجاب عنه بـ 400.

الأخطاء

الرمزالمعنى
-32601طريقة غير معروفة (بما فيها طرق الحسابات المتقاعدة)
-32602معامل غير صالح أو مفقود
-32000مرفوض: معاملة رفضها مجمع المعاملات، أو استدعاء faucet تجاوز حد المعدل، أو بناء شاهد انتظر أكثر من 10 s، أو قراءة تجاوزت 30 s، أو طريقة لا يخدمها المستمع العام، أو اشتراك تجاوز الحد
-32001الكائن المشار إليه غير موجود
-32010مقلَّم: ارتفاع أدنى من حد الاحتفاظ في هذه العقدة؛ ويسميه data.floor (انظر أدناه)
-32603خطأ داخلي
-32600طلب غير صالح: متن يتجاوز حد الحجم، أو ليس JSON، أو دفعة مشوّهة، أو إشعار
{ "jsonrpc": "2.0", "id": 1, "error": { "code": -32000, "message": "…" } }

بالنسبة إلى rand_sendTransaction، لا يُعدّ حكمًا على المعاملة إلا -32000 و-32602؛ وبعد أي رمز آخر يكون مصيرها مجهولًا (انظر rand_sendTransaction).

العقد المقلَّمة: الخطأ -32010

العقدة التي تبدأ بالخيار --prune-history <window> تحتفظ بالدفتر كاملًا (الملاحظات، والمبطِلات، والمراسي، والسجل) لكنها تحتفظ فقط بآخر <window> من الكتل والمعاملات والإيصالات؛ وrand_status.prune_floor هو أدنى ارتفاع ما زالت تحتفظ به. على السلسلة 20، تعمل 24 من المدققين الستة والعشرين بالخيار --prune-history 24h؛ أما الأرشيفان فيعملان بلا هذا الخيار ويحتفظان بكل كتلة، وتمرّر نقطة النهاية العامة إلى أحدهما.

  • بحسب الارتفاع، دون الحد الأدنى (باستثناء التكوين الأول): تجيب rand_getBlockByHeight وrand_getFinality بحسب الارتفاع، ونطاق من rand_getBlocks أو rand_getCompactBlocks أو rand_getReceipts يصل إلى ما دونه، بالخطأ -32010 pruned: height h is below this node's retention floor f مع data: { "floor": f }. اسأل عقدة أرشيف. ولا يزال [0, 0] يخدم التكوين الأول.
  • بحسب التجزئة: تجيب rand_getBlockByHash وrand_getReceipt وrand_getRawTransaction وrand_getCallEnvelope وrand_getAggregate بـ null عن تجزئة مقلَّمة، كما عن تجزئة لم توجد قط؛ ولا يميّز بين الحالتين إلا عقدة أرشيف. وتجيب rand_getTransaction وrand_checkTransaction بـ null كذلك، وبـ -32010 فقط حين يبقى صف موقع يسمّي ارتفاعًا دون الحد الأدنى. وتضيف rand_getTransactionStatus الحقل floor إلى كل إدخال unknown على عقدة مقلَّمة.
  • مسح المحفظة غير متأثر: تقرأ rand_getCommitments وrand_getNullifiers وrand_getAnchor وطرق الشاهد عائلات بيانات لا تُقلَّم أبدًا.

المعاملة على الشبكة

Transaction { chain_id: u64, bundle: Option<Bundle>, action: Action }

Bundle {                                        // the hidden-asset bundle (since chain 14)
  anchor: Word8, nullifiers: [Word8; 4], commitments: [Word8; 4],
  fee: u64, burn_a: u64, burn_r: u64, burn_asset: u32, time: u32,
  envelopes: [Envelope; 4], proof: Vec<u8>,
  auth_commit: Word8, auth_proof: Vec<u8>,      // since chain 17 (v0.6.3): split authorisation's c and
}                                               //   its proof; zeros and empty without hc_auth
Envelope { kem_ct: Vec<u8>, to_receiver: Vec<u8>, to_sender: Vec<u8>, body: Vec<u8> }

Action::None
Action::Mint { cm: Word8, pk: Word8, time: u32, r: Word8, envelope: Envelope, amount: u64,
               minter: PublicKey, signature: Signature }
Action::Deploy { base_pc: u32, words: Vec<u32>, public: Vec<u32> }
Action::Call { program: Hash, proof: Vec<u8>, input_envelope: Option<CallEnvelope> }
Action::Bond { validator: Address, amount: u64, registration: Option<Registration> }
Action::Unbond { validator: Address, amount: u64, nonce: u64, signature: Signature }
Action::Withdraw { validator: Address, amount: u64, nonce: u64, time: u32, r: Word8,
                   envelope: Envelope, signature: Signature }
Action::BridgeAttest { attestation: Vec<u8>, recipient: ShieldedAddress, r: Word8, time: u32,
                       asset: u32, envelope: Envelope, pq_signatures: Vec<PqSignature> }
Action::BridgeBurn { asset: u32, amount: u64, relayer_fee: u64, to_chain: u16,
                     token: [u8; 32], to: [u8; 32] }
// the five aggregation variants sit here in the enum's declared order
Action::RegisterToken { name: String, symbol: String, decimals: u8, authority: MintAuthority,
                        initial: Option<InitialMint>, salt: [u8; 32], index: u32 }
Action::TokenMint { asset: u32, amount: u64, recipient: ShieldedAddress, r: Word8, time: u32,
                    envelope: Envelope, nonce: u64, signature: Signature }
Action::SetAuthority { asset: u32, new: Option<PublicKey>, nonce: u64, signature: Signature }
Action::TokenBurn { asset: u32, amount: u64 }
Action::PauseMints { nonce: u64, signature: Signature }               // bundle-less, fee-less
Action::UnpauseMints { nonce: u64, pq_signatures: Vec<PqSignature> }  // bundle-less
Action::RegisterBridgedToken { name: String, symbol: String, salt: [u8; 32], chain: u16,
                               token: [u8; 32], decimals: u8, nonce: u64,
                               pq_signatures: Vec<PqSignature> }
Action::ListBacking { token_index: u32, chain: u16, token: [u8; 32], decimals: u8, nonce: u64,
                      pq_signatures: Vec<PqSignature> }
Action::RotatePqGuardians { new_pq_guardians: Vec<PublicKey>, nonce: u64,
                            pq_signatures: Vec<PqSignature> }         // bundle-less, fee-less
Action::RotatePauseKey { new_pause_key: PublicKey, nonce: u64,
                         pq_signatures: Vec<PqSignature> }            // bundle-less, fee-less
// the four vesting variants (ClaimVested, RevokeVesting, BondVested, UnbondVested) follow, tags 24 to 27;
// since v0.6.8 RevokeVesting carries `signatures: Vec<RevokerSignature>` in place of one `signature`
Action::AdmitValidator { candidate: PublicKey, signatures: Vec<(PublicKey, Signature)> }   // tag 28, v0.6.8
Action::SlashEquivocation { first: Box<SignedHeader>, second: Box<SignedHeader> }         // tag 29
Action::RotatePqGuardiansV2 { new_pq_guardians: Vec<PublicKey>, possession: Vec<Vec<u8>>,
                              nonce: u64, pq_signatures: Vec<PqSignature> }                // tag 30
Action::RotatePauseKeyV2 { new_pause_key: PublicKey, possession: Vec<u8>, nonce: u64,
                           pq_signatures: Vec<PqSignature> }                               // tag 31
Action::CancelRotation { kind: u8, nonce: u64, signature: Signature }                      // tag 32
Action::Invoke { program: Hash, proof: Vec<u8>, input_envelope: Option<CallEnvelope>,
                 transition: Transition }                                                  // tag 33, RPL-2

MintAuthority = None | Key(PublicKey) | Bridge { backings: Vec<Backing> } | Program(Hash)
InitialMint { amount: u64, recipient: ShieldedAddress, r: Word8, time: u32, envelope: Envelope }
Transition { reads: Vec<Cell>, writes: Vec<Cell>, inflow: Inflow, pays: Vec<Payout>, mints: Vec<Payout> }
Cell { key: Word8, value: Word8 }               // keys strictly ascending in each list
Inflow = None | Deposit | Burn                  // what the bundle's burn_a of burn_asset is to the program
Payout { asset: u32, amount: u64, recipient: ShieldedAddress, r: Word8, envelope: Envelope }
Registration { public_key: PublicKey, payout: ShieldedAddress, signature: Signature }
CallEnvelope { kem_ct: Vec<u8>, to_sender: Vec<u8>, to_auditor: Vec<u8>, body: Vec<u8> }
PqSignature { index: u8, signature: Vec<u8> }   // one guardian's Dilithium2 co-signature, by set index

الإعداد الافتراضي لـ bincode: أعداد صحيحة ثابتة العرض، وبادئات طول من 8 بايتات، ووسوم تعداد u32 بترتيب التصريح. تأتي المتغيرات الخمسة للتجميع بعد BridgeBurn وقبل RegisterToken في التعداد (المعاملات)؛ ولا تقبلها السلسلة 20 أبدًا، ولا المتغيرات الأربعة للاستحقاق التدريجي ولا SlashEquivocation، لكن المرمِّز الذي يثبّت أرقام الوسوم في شيفرته عليه مع ذلك أن يعدّها.

وصل آخر حقلين في الحزمة مع v0.6.3 والسلسلة 17. وbincode موضعي، فالمرمِّز المكتوب للسلسلة 16 أو ما قبلها لا ينتج معاملة تفكّها هذه السلسلة، وتغيّر معه كل معرّف معاملة: نطاق المعرّف الآن هو rand-txid-3، الذي يربط auth_commit وملخّص إثبات المصادقة. وعلى العميل الذي يعيد حساب المعرّفات محليًا أن ينتقل معه. على السلسلة 20 تحمل كل حزمة إثبات مصادقة، سواء أُثبت ذاتيًا أم فُوِّض. لا يغيّر v0.6.8 شيئًا في تخطيط Transaction أو Bundle؛ بل يُلحق الإجراءات من 28 إلى 33.

كل معاملة تحمل حزمة واحدة على الأكثر. تحمل معاملة Bond حزمةً تساوي فيها burn_r قيمةَ amount، مع كون burn_a وburn_asset صفرًا. أما BridgeBurn وTokenBurn فتحرقان عبر الحزمة: يجب أن تكون burn_asset هي asset الخاصة بالإجراء (ولا تكون 0 أبدًا)، وburn_a هي amount الخاصة بالإجراء، وburn_r صفرًا، بينما تُدفع fee بعملة RAND من الخانتين 2–3. أي إجراء آخر لا يحرق أي رمز، ولا يُحرق RAND إلا عبر burn_r: فالحزمة التي تكون فيها burn_asset صفرًا وburn_a غير صفرية تُرفض في كل مكان. أما r في BridgeAttest فهي مشتقة وليست مختارة: إذ يتطلب القبول القيمة blake3("rand-deposit-r-1" ‖ mu) محسوبةً على الملخّص الذي وقّعه الحرّاس، ويرفض أي قيمة أخرى (WrongDepositBlinding، وهو رفض دائم). ويجب إدراج الرمز المُجسَّر — عند التكوين الأول (genesis) أو عبر RegisterBridgedToken / ListBacking — قبل أن يصبح أي إثبات له مقبولًا؛ أما إثبات عملة غير مُدرجة فيُرفض بالخطأ UnlistedToken.

يُنشأ كل إثبات للحزمة على المعاملة التي يرافقها ويُتحقَّق منه بمقابلها: أي المعاملة كاملةً بعد تفريغ إثباتاتها، مرتبطةً بمعرّف السلسلة، وفي السلسلة 20 (binding_domain: 1) بتجزئة genesis أيضًا، تحت وسوم جديدة. وفي السلاسل من 14 إلى 19 كان الربط بمعرّف السلسلة وحده، ولذلك فإن إثباتًا أُنشئ للسلسلة 19 لا يُتحقَّق منه في السلسلة 20، ولا تستطيع محفظة أقدم من v0.6.8 الإرسال إليها. وفي السلاسل من 18 إلى 20 تُرمَّز الحزمة دون إثباتيها بحجم 7,936 بايتًا، وتُرمَّز معاملة التحويل دونهما بحجم 7,949 بايتًا (5,848 و5,861 في السلاسل من 14 إلى 16، مع أغلفة بحجم 1,348 بايتًا ودون حقول المصادقة). ويبلغ حجم التحويل على الشبكة نحو 2.85 MB بحسب إعدادات الإنتاج، وجلّه إثبات: إثبات الحزمة بنحو 1.49 MB وإثبات المصادقة بنحو 1.36 MB. وكان نحو 1.43 MB قبل تقسيم التفويض.

آخر تحقق مقابل الإيداع c0878c3f في fullnode (السلسلة 21) بتاريخ 2026-10-12. إذا اختلف الكود عن هذه الصفحة فالكود هو الصحيح؛ أبلغونا بذلك.