Rand Protocol
الوثائق
المفاهيم الأساسية

Mempool

ما يفعله العقدة بالمعاملة بين استلامها ووضعها في كتلة: ترتيب القبول، وتتبع التعارضات بدلًا من nonces، وعمّال التحقق الأربعة، ومقياس الأقران وذاكرة الأحكام المؤقتة، وكيف يختار المقترِح كتلة، ولماذا يختفي الإنفاق المزدوج الخاسر من تلقاء نفسه.

استخدم هذه الصفحة لفهم ما يحدث للمعاملة بعد أن تقبلها rand_sendTransaction وقبل أن تحملها كتلة: لماذا رُفضت إن رُفضت، ولماذا قد تختفي من المجمّع دون أن تفشل قط، وبأي ترتيب تُملأ الكتلة، وما الذي يستطيعه فيض من البراهين الفاسدة وما لا يستطيعه ضد مدقِّق (validator). مجمّع المعاملات هو crates/randprotocol-node/src/mempool.rs؛ أما الحواجز التي تسبقه فهي في admission.rs.

لا مُرسِلون، إذن لا أرقام تسلسلية (nonces)

في سلسلة قائمة على الحسابات يرتّب المجمّع معاملات كل مُرسِل بحسب الرقم التسلسلي (nonce). أما السلسلة المحمية فلا مُرسِلين فيها: الحزمة لا تحمل عنوانًا ولا توقيعًا، ولا ترتبط حزمتان إلا إذا مسّتا المذكّرة نفسها. فلا يبقى ترتيب لكل مُرسِل ليُجرى. وما يحلّ محل إدارة الأرقام التسلسلية هو تتبّع التعارض: يفهرس المجمّع المُبطِلات (nullifiers) والالتزامات (commitments) لكل معاملة معلّقة، ويرفض أي وافد جديد يطالب بشيء منها. وينطبق الأمر نفسه على العدّادات القليلة التي لا يقبل السجل لكل قيمة منها إلا معاملة واحدة: الرقم التسلسلي لسجل المدقِّق (Unbond أو Withdraw)، وmint_nonce للرمز (تتشاركه TokenMint وSetAuthority)، وفهرس السجل الذي تُقيَّد به RegisterToken، وpause_nonce وlist_nonce للجسر. كلٌّ منها خانة لا يجوز أن تشغلها إلا معاملة واحدة في المجمّع. فأكثر ما يمكن تضمينه من معاملتين كهاتين هو واحدة، وحمل الأخرى يكلّف المقترِح (proposer) مساحة في الكتلة، ويكلّف كل عقدة التحقق من برهان في كل جولة انتشار (gossip).

يتسع المجمّع لما لا يزيد على 10,000 معاملة (Mempool::new(10_000) في node.rs)، ومنذ v0.6.8 لما لا يزيد على حجم ثماني كتل بالبايت: MAX_POOL_BLOCKS = 8 أضعاف max_block_bytes للسلسلة، أي 160 MiB على السلسلة 20 (التدقيق v6، CH-7). وقبل ذلك كان العدد وحده مقيَّدًا، في حين تتراوح المعاملة الواحدة الحاملة لبرهان بين نحو 1.3 MB وأكثر من 12 MB. وتُتحقَّق كل معاملة من صحتها مقابل السجل عند رأس شجرة الإجماع، لا عند آخر كتلة مثبَّتة: أي الحالة التي سيبني عليها المقترِح فعلًا.

القبول: الأرخص أولًا ثم الأغلى

تمر المعاملة الواردة عبر RPC أو الانتشار بهذه الخطوات بالترتيب، وأول رفض هو الخطأ الذي تراه:

  1. التكرار. التجزئة موجودة في المجمّع أصلًا: already in mempool.
  2. التعارض. مُبطِل أو التزام أو إحدى خانات الأرقام التسلسلية والفهارس المذكورة أعلاه تطالب بها معاملة معلّقة: conflicts with a pending transaction over <hex>. وفي خانة الرمز يكون الـ hex مفتاح عرض: كلمة وسم (tokn لـ mint_nonce، وtidx لفهرس التسجيل)، ثم الفهرس ثم الرقم التسلسلي. أما إقرار الجسر (attestation) الذي تسابق عليه مرحِّلان فيُميَّز بملخّصه: conflicts with a pending transaction over bridge attestation <hash>.
  3. الامتلاء. mempool full. فحص السعة هو الأخير من الثلاثة. وعند سقف البايتات يجوز للوافد الجديد أن يحل محل مدخلات في المجمّع تقل رتبتها عنه تمامًا — بحسب الرسوم فوق الحد الأدنى الحالي لكل منها لكل KiB، ثم بحسب الرسوم — فتُطرد الأرخص أولًا حتى يتسع له المكان؛ فإن لم يكفِ ذلك، أو كان مساويًا فحسب، فهو الذي يُرفض. وتقع إجراءات الحوكمة خارج السقفين ولا تُطرد أبدًا: إجراءات حوكمة الجسر الأربعة PauseMints وUnpauseMints وRegisterBridgedToken وListBacking، ومنذ v0.6.8 أيضًا RotatePqGuardians وRotatePauseKey وصيغهما …V2 وCancelRotation وAdmitValidator وSlashEquivocation. ومع ذلك تُحتسب بايتاتها ومدخلاتها ضمن السقفين. وPauseMints هي مكبح اختراق مفتاح الحارس: بلا حزمة وبلا رسوم، وهي المعاملة الوحيدة التي يجب أن تبلغ كتلة بينما يسكّ مهاجم، فلا يجوز أن يمنعها مجمّع ممتلئ. ويحدّ خطوةُ التعارض هذا الاستثناء: فكل من pause_nonce وlist_nonce يقبل معاملة واحدة في المجمّع في كل مرة، فلا تستطيع إجراءات الجسر الأربعة أن تضيف أكثر من مدخلين فوق السقف؛ وكل من الإجراءات الأخرى يستهلك رقمًا تسلسليًا أو نصابًا خاصًا به.
  4. النصف الرخيص من Ledger::validate. كل ما قد يصبح قديمًا بين القبول والتضمين ولا يكلّف برهانًا: أن يكون المرساة (anchor) أحد آخر 1,024 جذرًا على السلسلة 20 (proof_window_blocks في التكوين الأول (genesis)؛ و256 بدونه)، وأن يقع time داخل النافذة، وأن تكون المُبطِلات غير مُنفَقة، والالتزامات غير موجودة، وملخّص الإقرار غير مطالَب به، والرقم التسلسلي لسجل إجراء التخزين (staking) هو الحالي، وmint_nonce لإجراء الرمز أو فهرس التسجيل هو الذي بلغه السجل (wrong mint nonce وwrong token index متى تجاوزته السلسلة)، والرقم التسلسلي لإيقاف أو إدراج هو الحالي للجسر. وتُحسب هنا أيضًا الالتزامات التي تنشئها المعاملة، بما فيها المذكّرة التي يشتقها السجل نفسه لـ Withdraw أو BridgeAttest أو مكافأة المُجمِّع (aggregator)، وهي ليست على السلك لكن يجب ألا تتصادم هي الأخرى. وتُفحص حدود الحجم قبل فك أي ترميز: فالبرهان الذي يتجاوز max_proof_bytes للسلسلة (2 MiB افتراضيًا، و4 MiB على السلسلة 20)، أو الإقرار الذي يتجاوز 16 KiB، أو المعاملة الأكبر من كتلة (max_block_bytes: 4 MiB افتراضيًا، و20 MiB على السلسلة 20) تُرفض فورًا، فلا تشتري كتلة ضخمة أي عمل. ويُرفض برهان الحزمة بصيغة العلامة المختومة (المقلَّمة) في الخطوة نفسها خارج مزامنة الصيغة المختومة، بوصفه PrunedFormOutsideSync. ثم، ودون التحقق من شيء بعد، يقرأ المجمّع ترويسات البراهين. وتتقدّم ثلاث سياسات: لا تُدرج في المجمّع مكالمةٌ يقل جدول مدخلاتها أو keccak أو sha256 عن 2^7 صفًّا (CallRevealsPrivateInputs)، ولا نشرٌ لا تستطيع أي مكالمة حمله (ProgramUncallable)، ولا معاملةٌ في برهان حزمتها أو مكالمتها حقل ترويسة لا يكتبه المُثبِت (prover) الأمين (NonCanonicalProof). والأخيران قاعدتان في السجل أيضًا على السلسلة 20، تحت hardening_v6. ومنذ v0.6.8 تُرفض الترويسة التي تتجاوز درجتها المعلنة سقف أعلى جدول بوصفها NonCanonicalProof قبل أن يمرّ عليها الفحص (التدقيق v6، ZKV-4)، وأي panic في هذا الفحص المسبق هو رفض لتلك المعاملة (VerifierPanicked) لا موت للعقدة. ثم حد الرسوم الأدنى: على السلسلة 20 يفك المجمّع حدَّ الغاز الذي يعلنه برهان المكالمة أو الاستدعاء، ويرفض كل رسم يقل عن BUNDLE_BASE + gas_price × limit + byte_price × ⌈bytes/1024⌉ بأسعار الرأس، مضافًا إليه رسم الخلية للاستدعاء، بوصفه FeeTooLow (الرسوم). تلك هي قاعدة الكتلة نفسها، فيطلب المجمّع بالضبط ما تطلبه الكتلة.
  5. النصف الغالي، خارج حلقة الإجماع. تُصَفّ المعاملة في طابور بعمق 64 على الأكثر لأحد أربعة عمّال تحقق. ويجري العامل بقية Ledger::validate في مهمة حاجزة: ملخّص الحزمة، وحدّ الغاز الذي يعلنه برهان الحزمة (على السلسلة 20 هو 20,479 بالضبط، وإلا BundleGasLimit)، وبرهان الحزمة، ومنذ السلسلة 17 برهان تفويضها مقابل ارتباط المعاملة، وللمكالمة برهانها الخاص وحد رسومها الأدنى. ويتحقق مقابل لقطة من الرأس تُستنسخ بتراخٍ، مرة واحدة على الأكثر لكل تغيّر في الرأس ولا تُستنسخ إلا ما دام شيء ينتظر. والمعاملة المنتشرة التي تجد الطابور ممتلئًا تُسقَط، فلا تُتحقَّق ولا تُمرَّر، بدل أن تعطّل الحلقة التي تصوّت؛ وتحملها جولة الانتشار التالية من النظير مرة أخرى.
  6. إعادة الفحص والإدراج. تعيد insert_verified الخطوة 4 مقابل الرأس الذي تُدرج عليه المعاملة فعلًا، لأن الرأس قد يكون تحرّك أثناء التحقق من البرهان، ثم تقبلها، وتمرّرها إن كانت من حركة الانتشار.

الخطوات من 1 إلى 4 هي Mempool::precheck؛ والخطوة 5 هي الوحيدة التي تتحقق من STARK. ولأن هذه الكلفة تُدفع على عامل، فإن فيض البراهين الفاسدة يشغل أربعة خيوط ولا يمس حلقة الإجماع أبدًا. وتسرد المعاملات والإجراءات ترتيب القبول في السجل نفسه، وهو ما تنفّذه الخطوتان 4 و5 معًا.

حارسان وذاكرة مؤقتة للانتشار

أمام القبول، يسري أمران على المعاملات الواردة من النظراء وحدها؛ أما ما يُقدَّم عبر RPC فيتجاوزهما، لأن ذلك المنفذ هو منفذ المشغّل نفسه وهو مقيَّد أصلًا بحد حجم الطلب. ومسار RPC الوحيد المقيَّس هو الصنبور (faucet)، أدناه.

  • عدّاد بايتات لكل نظير. منذ v0.6.8 يُحتسب كل إطار gossip على ميزانية البايتات الخاصة بالنظير الذي أعاد إرساله، وذلك قبل فك ترميزه أصلًا: دفعة أولية من ثمانية إطارات، وتجديد بمعدل إطارين بأقصى حجم إرسال في الثانية. وما يتجاوز ذلك يُسقَط الإطار دون فك ترميزه (التدقيق v6، GOSSIP-1). أما معرّف المعاملة، الذي يُحسب بتجزئة الإثبات كاملًا، فلا يُحسب إلا ضمن الحصة المسموحة للنظير المُعيد للإرسال.
  • عدّاد معاملات لكل نظير. دلو رموز (token bucket) لكل نظير يعيد الإرسال، بدفعة أولية قدرها 16 وتجديد بمعدل 4 في الثانية (PEER_TX_BURST، PEER_TX_PER_SEC). وهو يحاسب النظير الذي أعاد إرسال المعاملة، لا مؤلفها، الذي لا تستطيع سلسلة محمية (shielded) تسميته.
  • ذاكرة أحكام مؤقتة. المعاملة التي رفضتها هذه العقدة سابقًا لسبب هو دالّة في بايتاتها وحدها، كإثبات فاسد أو توقيع فاسد أو جزء يتجاوز الحجم المسموح، تُرفض مجددًا من ذاكرة FIFO بسعة 8,192 مدخلًا (REFUSED_CACHE_ENTRIES) بدل التحقق منها مرة ثانية. أما الحكم الذي يتعلق بـحالة هذه العقدة، كمرساة غير معروفة أو nullifier مُنفَق، فلا يُخزَّن أبدًا: فالعقدة المتأخرة بكتلة واحدة ستسمّم نفسها بخلاف ذلك ضد معاملات توشك أن تصبح صالحة. والقائمة قائمة سماح، فكل خطأ جديد يُعدّ حالة إلى أن يقرر أحدهم خلاف ذلك. وهذه المدخلات توضح أين يمر الحد:
    • BadPauseSignature (the pause signature does not verify) ليس دائمًا منذ v0.6.8 (التدقيق v6، BRG-18). فهو يتحقق من التوقيع بمفتاح الإيقاف الحالي للسلسلة، الذي يمكن لقواعد الجسر v2 تدويره، فهو إذن حالة: العقدة المتأخرة بكتلة واحدة عن تدوير ما سترفض PauseMints الصادر عن الحائز الجديد حتى إعادة التشغيل. وخرج كذلك فهرس توقيع PQ مشترك خارج النطاق من الذاكرة للسبب نفسه. وحتى v0.6.7، على السلسلتين 18 و19، كان كلاهما يُخزَّن بوصفه دائمًا. أما الآن فيكلّف تكرار إيقاف فاسد تحققًا واحدًا من Dilithium2 عن كل تسليم، وهو تحقق محدود بعدّاد النظير.
    • PrunedFormOutsideSync ليس دائمًا عمدًا. فصيغة العلامة لحزمة مختومة تُجزَّأ إلى معرّف المعاملة الخام نفسها، والذاكرة تفهرس بذلك المعرّف، فتخزين الرفض كان سيتيح لأي نظير gossip أن يفرض رقابة على المعاملة النزيهة في الشبكة كلها.
    • حدّ الغاز المعلن في الإثبات هو بايتاته نفسها مقابل ثابت في genesis، ولذلك فإن BundleGasLimit وAuthGasLimit دائمان. أما FeeTooLow فليس كذلك: ففي السلسلة 20 يتحرك الحد الأدنى مع الأسعار. وسياسات الترويسة الثلاث في الخطوة 4 لا تُخزَّن أيضًا أبدًا: فكل منها معرفة هذا البناء، وقد ينقلها بناء لاحق.
    • في سلسلة لها قائمة سماح للـ faucet (السلسلة 20)، يكون FaucetRecipientNotAllowed دائمًا: فهو يقارن مستلم السك نفسه بثابت في genesis. أما FaucetBudgetExhausted فليس كذلك: فهو حالة، وتُقبل عملية السك نفسها من جديد في الحقبة التالية.
    • BadSignature الخاص بإجراء رمز ليس دائمًا أيضًا، بخلاف إجراء staking: فسلطة السك للرمز حالة، ويمكن لـSetAuthority أن تسلّمها إلى مفتاح آخر، وقد تُرفض البايتات نفسها قبل أن يثبت ذلك التدوير وتُقبل بعده. أما رفوض الرموز على مستوى البايتات (اسم أو رمز فاسد، أو منازل عشرية كثيرة، أو مبلغ صفري، أو فهرس رمز 0) فتُخزَّن؛ وكذلك حقل الحرق الذي لا يجوز للإجراء ضبطه، وعملية سك لا يُفتح التزامها إلى مبلغها، وإيداع جسر ليس تعميته هي المشتقة.

حد الـ faucet

rand_mint بلا رسوم ويكلّف معاملة واحدة في المجمّع عن كل استدعاء، وفي السلسلة 20 يكون الـ faucet مفعّلًا وخلفه جسر يحتفظ بقيمة. ويقيّد genesis ما يستطيع فعله: فالسك لا يدفع إلا إلى 16 محفظة مسموحًا بها وبحد أقصى 10,000 RAND لكل حقبة من 1,000 كتلة (Staking)، ولا يجوز أن يوقّع عليه إلا مفتاح واحد من المفاتيح الـ18 في قائمة genesis staking.faucet_minters (MinterNotAllowed، لا يُخزَّن أبدًا: قاعدة دفتر منذ السلسلة 16، وسياسة عقدة في السلسلة 15 حيث كانت القائمة هي مدقّقي genesis). وفوق ذلك تحاسب كل عقدة الـ faucet الخاص بها: ثماني عمليات سك متتالية، بتجديد واحدة في الثانية (FAUCET_MINT_BURST، FAUCET_MINT_PER_SEC). وبعد ذلك يجيب الاستدعاء بـfaucet is rate limited on this node (8 mints back to back, refilling at 1/s); try again shortly. والحد لكل عملية عقدة، لا لكل مستدعٍ، لأن منفذ RPC لا يملك هوية نظير يمكن محاسبتها، والمورد المحمي هو مجمّع هذه العقدة. ومع الإعفاء من السعة المذكور أعلاه، لا يستطيع طوفان من الـ faucet أن يملأ المجمّع قبل PauseMints.

يعمل Gossipsub بتحقق على مستوى التطبيق، فلا تُعاد المعاملة إلى النظراء الآخرين إلا بعد التحقق منها هنا. والنظير الذي يغرق الشبكة بمعاملات غير صالحة يخنقه العدّاد، وتُجاب طلباته من الذاكرة المؤقتة، ولا يكلّف حلقة الإجماع شيئًا.

بناء كتلة

عندما يقود مُصادِق (validator) جولة، يطلب من المجمّع المرشحين. تُبقي candidates_within فقط المعاملات التي ما تزال سارية على الدفتر الذي تُبنى عليه الكتلة، بإعادة تشغيل النصف الرخيص من القبول: المرساة ما تزال في النافذة، وtime ما يزال فيها، والـ nullifiers لم تُنفَق بعد، والالتزامات غير موجودة بعد. كما تُسقط إجراء رمز تجاوزت السلسلةُ mint_nonce الخاص به أو فهرس تسجيله، وإيقافًا أو إدراجًا بـ nonce قديم. ومنذ v0.6.8 تعيد تسعير كل استدعاء (call) وكل invoke بالأسعار السارية عند رأس السلسلة الذي تبني عليه، انطلاقًا من حد الغاز المحفوظ عند القبول، وتستبعد ما صارت رسمه دون حده الأدنى؛ وتبقى في المجمّع، وتُعرض من جديد حين تنخفض الأسعار (التدقيق v6، CH-9). وفي السلسلة 20 ترتّب الباقي بالحوكمة أولًا، ثم بالرسم الزائد على الحد الأدنى الحالي، لكل KiB من المعاملة، ثم بالرسم، الأعلى أولًا، وتُفضّ التعادلات بالتجزئة، فيختار كل مقترِح نزيه يبني على المجمّع نفسه الكتلة نفسها، ويملأ حتى ميزانية 2,000 معاملة وسقف الكتلة في السلسلة (MAX_BLOCK_TXS؛ max_block_bytes، وهو 4 MiB افتراضيًا و20 MiB في السلسلة 20). والبايتات هي ما تعوزه الكتلة، ولهذا يؤخذ الفائض لكل KiB. أما السلسلة التي لا قسم gas فيها والعقدة التي لا سياسة غاز لها فتتجاوزان ذلك المفتاح وترتّبان بالحوكمة ثم الرسم ثم التجزئة، كما كانت السلسلة 15. والحوكمة أولًا هي النصف الآخر من ضمان الإيقاف: فـPauseMints لا يدفع رسمًا بحكم التصميم، لأنه يجب أن يعمل من محفظة لا تحمل RAND، ولذلك كان الترتيب بالرسم وحده سيضع فرامل الطوارئ خلف كل معاملة تدفع.

وتسري قاعدة أخرى ما دام هناك call أو invoke جاهز (التدقيق v6، POOL-2؛ سياسة عقدة في كل سلسلة، لا قاعدة صلاحية). فهذان وحدهما يدفعان سعر البايت، والتحويل الذي يدفع أكثر قليلًا من أساسه الثابت يتقدم عليهما لكل KiB، فقد يُبقي سيلٌ من التحويلات call جاهزًا خارج كل كتلة. ولذلك تأخذ المعاملات ذات الرسم الثابت في تمريرة أولى ما لا يزيد على ثلاثة أرباع بايتات الكتلة؛ وبعد وضع الـ calls يُملأ ما بقي من مساحة بالتحويلات المؤجلة، بترتيبها. فلا تضيع أي مساحة في الكتلة، ولا يتغير شيء حين لا يكون هناك call جاهز (Fees).

والمعاملة الأكبر من المساحة المتبقية تُتجاوز، ولا تنتهي بها الكتلة: فمعاملة أصغر خلفها تمر. والتحويل في السلسلة 18 نحو 2.85 MB، منها إثبات حزمة بحجم 1.49 MB وإثبات تفويض بحجم 1.36 MB، فتتسع كتلتها البالغة 20 MiB لنحو سبعة، وتتسع الكتلة الافتراضية البالغة 4 MiB لواحد. وفي السلسلة 15، بنحو 1.43 MB للتحويل، كانت الـ20 MiB نفسها تتسع لأربعة عشر. وتحت الحمل يكون الرسم هو ما يحسم أيها يمر (Fees).

التقليم

بعد كل commit، تُسقط prune من المجمّع بالضبط ما كانت candidates_within ستتجاوزه: معاملات أُنفقت ملاحظتها (note) على يد غيرها، أو صار التزامها موجودًا، أو تجاوزت السلسلةُ nonce الخاص بها أو فهرس تسجيلها، أو خرجت مرساتها أو time الخاص بها من النافذة (1,024 كتلة في السلسلة 20، و256 حتى السلسلة 19). وهكذا تختفي الحزمة التي تخسر سباق الإنفاق المزدوج من تلقاء نفسها، دون أن تُنتج خطأً لأحد. وقبول rand_sendTransaction ليس التثبيت: استعلم بـrand_getTransaction إلى أن تُرجع كتلة، وإذا مرت نافذة المرساة دون ذلك، فأعد بناء الحزمة على مرساة جديدة وأرسلها مرة أخرى.

مراقبتها

يُبلغ rand_status عن mempool_size وverify_queue (المعاملات التي تنتظر عاملًا) وrefused_cache (مدخلات ذاكرة الأحكام). وبقاء verify_queue عند 64 يعني أن الإثباتات تصل أسرع مما تتحقق منها أربعة عمال، أي نحو 16 ms لكل منها بمفتاح دافئ؛ وتزايد mempool_size مع بقاء الكتل ممتلئة يعني أن الرسم، لا ترتيب الوصول، هو ما يحسم الإدراج.

ما لم يوجد بعد

  • لا استبدال. تتحرك أسعار الغاز وأسعار البايتات في Chain 20 بحدّ أدنى جديد لكل استدعاء في كل كتلة، حتى بلوغ سقفها؛ أما الحدّ الأدنى للتحويل فثابت. ولا يوجد استبدال لمعاملة موجودة في المجمّع بمعاملة ذات رسوم أعلى على الـ notes نفسها، إذ تمنعه قاعدة التعارض. والاستدعاء الذي ارتفع سعره فوق ما دفعه ينتظر في المجمّع دون أن يُعرض، إلى أن تنخفض الأسعار أو تنقضي نافذة الـ anchor الخاصة به. أما في v0.6.7 (السلسلتان 18 و19) فكان الاستدعاء الموجود في المجمّع يحتفظ بالحدّ الأدنى الذي قُبل عنده، ويظل معروضًا بعد الارتفاع، ثم يفشل في التطبيق التجريبي لدى المقترِح بالخطأ FeeTooLow. وتدرج وثيقة مساحة الكتلة في الـ fullnode الـ mempool المرتّب بحسب الرسوم خطوةً تسبق الكتلة الأكبر، وتدرج تجميع الإثباتات على مستوى الكتلة بوصفه ما يرفع السقف لكل كتلة.
  • لا انتهاء صلاحية بحسب العمر. لا تغادر المعاملة المجمّع إلا بإدراجها في كتلة، أو بإخراجها عند بلوغ حدّ البايتات، أو بانقضاء نافذتي الـ anchor والوقت: 1,024 كتلة في Chain 20، أي نحو 23 دقيقة بمعدل 1.34 ثانية للكتلة كما أبلغ المستكشف هناك. أما حتى Chain 19 فكانت النوافذ 256 كتلة، أي نحو خمس دقائق.
  • لا RPC للـ mempool. لا توجد طريقة تعرض المعاملات المعلّقة؛ وmempool_size في rand_status والعدد والبايتات وأقدم عمر في rand_getMempoolInfo هي المعروضات الوحيدة، والمستكشف يفهرس الكتل المثبتة فقط.

آخر تحقق مقابل الإيداع c0878c3f في fullnode (السلسلة 21) بتاريخ 2026-10-12، وfullnode v0.6.8 `c9c9bd3c` (chain 20): `crates/randprotocol-node/src/mempool.rs` (`MAX_POOL_BLOCKS`, `make_room`, `is_governance`, the call reservation in `candidates_within`), the commits for CH-7, CH-9, POOL-2, BRG-18, GOSSIP-1 and ZKV-4, and `rand_getLimits` on chain 20, fullnode v0.6.7 `86941a1`: `crates/randprotocol-node/src/mempool.rs`, `admission.rs`, `crates/randprotocol-core/src/ledger/mod.rs` (the gas floor), fullnode `90e7716`: `docs/architecture.md` §8, `docs/rpc.md` (changelog, the 2026-09-28 gas entries), fullnode `ed88241`: `docs/confidential.md` (transaction binding). إذا اختلف الكود عن هذه الصفحة فالكود هو الصحيح؛ أبلغونا بذلك.