> ## Content Index
> Fetch the complete content index at: https://arabroot.io/llms.txt
> Use this file to discover other available public pages before exploring further.

# هل تحتاج بلوكتشين أم قاعدة بيانات؟ اختبار من خمسة أسئلة
- URL: https://arabroot.io/articles/هل-تحتاج-بلوكتشين-ام-قاعدة-بيانات-اختبار-من-خمسة-اسئلة/
- Published: 2026-10-28T06:02:35.000Z
- Updated: 2026-10-28T07:37:34.000Z
- Description: خمسة أسئلة تحدد هل يحتاج مشروعك بلوكتشين، مع تجربة تبني البديل الأرخص في PostgreSQL وتقيس تكلفة العقد الذكي.
- Author: فريق عرب رووت
- Tags: الأدلة التقنية, البلوكتشين والعملات الرقمية, الاستضافة الذاتية

لنفرض أن لديك شركة ناشئة تبني منصة لشهادات الضمان: المصنع يسجل الجهاز برقمه التسلسلي، والموزع يسجل بيعه للمتجر، والمتجر يسجل بيعه للعميل فيبدأ الضمان، ومركز الصيانة يسجل كل إصلاح، والعميل يفتح التطبيق فيرى تاريخ جهازه كاملاً. وفي اجتماع مع أحد الموزعين الكبار يقول مدير المشتريات عندهم: «نريد أن تكون الشهادات على البلوكتشين، حتى لا يستطيع أحد أن يغيرها». ثم يرسل لك المدير التنفيذي بعد الاجتماع رسالة قصيرة: «هل نحتاجه فعلاً؟ وكم يكلف؟ أريد الجواب قبل نهاية الأسبوع». وهذا السؤال يتكرر في كل شركة تقريباً، والجواب الصحيح عنه لا يأتي من حماس الاجتماع ولا من رفض التقنية مسبقاً، وإنما من أسئلة محددة عن من يكتب، ومن يثق بمن، وماذا يحدث للبيانات بعد خمس سنوات.

وفي [مقال البلوكتشين للمبتدئين](https://arabroot.io/articles/%D8%A7%D9%84%D8%A8%D9%84%D9%88%D9%83%D8%AA%D8%B4%D9%8A%D9%86-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D9%83%D9%8A%D9%81-%D9%8A%D8%B9%D9%85%D9%84-%D9%88%D9%85%D8%AA%D9%89-%D9%84%D8%A7-%D8%AA%D8%AD%D8%AA%D8%A7%D8%AC%D9%87/#when-not) وضعنا خمسة أسئلة مختصرة في قسم «متى لا تحتاج بلوكتشين»، وهذا المقال هو النسخة العملية الكاملة منها: نأخذ كل سؤال على حدة، ونرى ما الذي يعنيه في منصة الضمان، وما البديل الأرخص الذي يحل نفس المشكلة، ثم نبني هذا البديل بأيدينا ونجربه، ونقيس ما يكلفه الخيار الآخر على شبكة Ethereum محلية. والمقال تعليمي تقني، ولا يتضمن أي نصيحة استثمارية أو ترويجاً لأي عملة أو منصة.

وسوف نناقش في هذا المقال ما يلي:

- ماذا يعطيك البلوكتشين بالضبط، وماذا يكلفك، حتى تعرف ما الذي تشتريه.
- الأسئلة الخمسة واحداً بعد الآخر: الكتاب المستقلون، والجهة الموثوقة، وهل يكفي إظهار التعديل Tamper Evidence، والبيانات الشخصية، والتحقق العلني.
- تجربة عملية: سجل يظهر التعديل في PostgreSQL بسلسلة هاش، ونقاط تحقق موقعة عند الشركاء تكشف إعادة الكتابة الكاملة.
- نفس الأحداث في عقد ذكي على شبكة Anvil المحلية: الغاز Gas والكتل، ثم تجربة «حذف» رقم جوال من السلسلة.
- حالتان موثقتان من الواقع: منصة TradeLens، ومشروع استبدال CHESS في بورصة أستراليا.
- مقارنة بإطار NIST وورقة «Do you need a Blockchain?»، والأخطاء الشائعة، وورقة قرار تستخدمها مع فريقك.

## ماذا تشتري عندما تختار البلوكتشين؟

قبل الأسئلة يجب أن نتفق على ما يعطيه البلوكتشين فعلاً، لأن كثيراً من النقاشات تفشل لأن كل طرف يقصد شيئاً مختلفاً. والبلوكتشين في جوهره سجل يكتب فيه عدة أطراف، وتحفظ كل عقدة Node نسخة كاملة منه، وتتفق العقد على ترتيب المعاملات بخوارزمية إجماع Consensus، وكل معاملة موقعة من صاحبها، وكل كتلة تحمل هاش الكتلة التي قبلها، وقد شرحنا هذه اللبنات في المقال الأول والإجماع بالتفصيل في [مقال الإجماع](https://arabroot.io/articles/%D8%A7%D9%84%D8%A7%D8%AC%D9%85%D8%A7%D8%B9-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D9%84%D9%88%D9%83%D8%AA%D8%B4%D9%8A%D9%86-%D8%A7%D8%AB%D8%A8%D8%A7%D8%AA-%D8%A7%D9%84%D8%B9%D9%85%D9%84-%D9%88%D8%A7%D8%AB%D8%A8%D8%A7%D8%AA-%D8%A7%D9%84%D8%AD%D8%B5%D8%A9/). ومن هذه اللبنات تأتي ثلاثة ضمانات لا تحصل عليها من قاعدة بيانات واحدة يشغلها طرف واحد:

- **لا يوجد مشغل يستطيع أن يغير الماضي وحده**: لأن النسخ عند أطراف مستقلة، وأي تغيير يحتاج موافقة أغلبهم.
- **لا يوجد مشغل يستطيع أن يرفض معاملة صحيحة وحده**: في الشبكة العامة أي عقدة تستطيع أن تمرر المعاملة، وفي الشبكة المصرح بها تحتاج أغلبية لترفضها.
- **التحقق المستقل**: كل طرف يشغل عقدته ويتحقق من كل معاملة بنفسه، ولا يعتمد على شاشة يعرضها عليه طرف آخر.

وفي المقابل تدفع ثمناً ثابتاً لا تستطيع أن تلغيه بالتصميم الجيد، والسبب أنه جزء من طريقة عمل التقنية نفسها: كل عقدة تنفذ كل معاملة وتحفظها، فالكتابة أبطأ وأغلى من قاعدة بيانات، وكل عضو يرى البيانات إلا إذا أضفت طبقات خصوصية تزيد التعقيد، والحذف والتصحيح صعبان أو مستحيلان، وكل طرف يحتاج إدارة مفاتيح Key Management، وكل تغيير في قواعد الشبكة يحتاج اتفاق الأعضاء أو حوكمة Governance مكتوبة. لذلك السؤال الصحيح ليس «هل البلوكتشين أفضل؟» وإنما «هل نحتاج هذه الضمانات الثلاثة تحديداً، وهل نقبل هذا الثمن من أجلها؟».

ويصف تقرير [NIST IR 8202](https://nvlpubs.nist.gov/nistpubs/ir/2018/NIST.IR.8202.pdf?ref=arabroot.io) في القسم 8 الخطأ الذي يقع فيه أغلب الناس، فيقول إن كثيراً من المؤسسات تبدأ بسؤال «نريد أن نستخدم البلوكتشين في مكان ما، فأين؟»، وإن هذا يقود إلى الإحباط لأن التقنية لا تصلح لكل شيء، وإن الأفضل أن تفهم التقنية أولاً ثم تبحث عن الأنظمة التي تناسبها. وطلب الموزع في قصتنا هو بالضبط من النوع الأول: هو لا يريد بلوكتشين، وإنما يريد ألا يستطيع أحد أن يغير الشهادات، وهذا متطلب يمكن تحقيقه بأكثر من طريقة. والصورة التالية تبين الأسئلة الخمسة التي سوف نمشي عليها والمخرج عند كل سؤال:

![مخطط من خمسة أسئلة مرتبة: هل تكتب عدة أطراف مستقلة في نفس السجل، فإذا لا فقاعدة بيانات عادية، ثم هل توجد جهة يقبل الجميع أن تشغل السجل، فإذا نعم فقاعدة بيانات تشغلها الجهة، ثم هل يكفي أن يكتشف كل طرف التعديل بنفسه، فإذا نعم فسجل بسلسلة هاش ونقاط تحقق موقعة، ثم هل في البيانات ما هو شخصي أو سري أو قد يلزم حذفه، فإذا نعم فأبقها خارج السلسلة، ثم هل يجب أن يتحقق أي شخص في العالم دون إذن، فإذا لا فشبكة مصرح بها، وإذا نعم فشبكة عامة ببيانات علنية ورسوم](https://arabroot.io/content/images/2026/10/need-blockchain-test-01-five-questions.webp)

كل سؤال يحذف خياراً أرخص قبل أن تصل إلى الخيار الأغلى، وأغلب المشاريع تقف عند الأسئلة الثلاثة الأولى

## السؤال الأول: هل تكتب عدة أطراف مستقلة في نفس السجل؟

هذا السؤال يبدو سهلاً، والإجابة الأولى التي يعطيها الفريق دائماً هي «نعم، عندنا مصنع وموزع ومتجر ومركز صيانة»، ولكن انتبه للكلمة المهمة فيه: مستقلة. فالسؤال ليس كم جهة تستخدم النظام، وإنما كم جهة تكتب في السجل بمفتاحها وعقدتها، دون أن تمر على تطبيق طرف آخر. وفي منصة الضمان كما هي اليوم، المصنع والموزع والمتجر ومركز الصيانة كلهم يكتبون عبر واجهة API التي تشغلها شركتك، وبالتالي الكاتب الحقيقي في قاعدة البيانات واحد فقط، وهو تطبيقك، والآخرون مستخدمون له مهما كان عددهم.

وقد يتساءل البعض: ما الفرق إذا كان كل واحد منهم يسجل الدخول بحسابه؟ والإجابة أن الفرق في من يملك القدرة على التعديل: تطبيقك يستطيع أن يكتب أي شيء باسم أي مستخدم، ومدير قاعدة البيانات عندك يستطيع أن يعدل أي سطر، والشركاء يرون فقط ما تعرضه عليهم الواجهة. فإذا كان هذا مقبولاً لهم فأنت في حالة الكاتب الواحد، ولا يوجد ما يتفق عليه أحد مع أحد، والحل هو قاعدة البيانات مع الصلاحيات Permissions وسجل التدقيق Audit Trail الذي شرحناه في [مقال سجل التدقيق](https://arabroot.io/articles/%D8%B3%D8%AC%D9%84-%D8%A7%D9%84%D8%AA%D8%AF%D9%82%D9%8A%D9%82-audit-trail-%D9%85%D9%86-%D9%81%D8%B9%D9%84-%D9%85%D8%A7%D8%B0%D8%A7-%D9%88%D9%85%D8%AA%D9%89/).

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

## السؤال الثاني: هل توجد جهة يقبل الجميع أن تشغل السجل؟

إذا كان هناك عدة كتاب مستقلين، فالسؤال التالي هو هل يقبلون أن تشغل جهة واحدة السجل نيابة عنهم. وهذا ليس سؤالاً تقنياً، وإنما سؤال عن العلاقات والمصالح والنظام. وأغلب الأنظمة المالية في العالم تعمل بهذا النموذج: البنوك تتنافس فيما بينها، ومع ذلك تقبل كلها أن يشغل البنك المركزي نظام التسوية، كما شرحنا في [مقال المقاصة والتسوية](https://arabroot.io/articles/%D9%83%D9%8A%D9%81-%D8%AA%D9%86%D8%AA%D9%82%D9%84-%D8%A7%D9%84%D8%A7%D9%85%D9%88%D8%A7%D9%84-%D8%A8%D9%8A%D9%86-%D8%A7%D9%84%D8%A8%D9%86%D9%88%D9%83-%D8%A7%D9%84%D9%85%D9%82%D8%A7%D8%B5%D8%A9-%D9%88%D8%A7%D9%84%D8%AA%D8%B3%D9%88%D9%8A%D8%A9/)، والسبب أن الجهة المشغلة محايدة ومنظمة وعليها رقابة.

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

💡

اسأل الشركاء مباشرة: «إذا شغلت جمعية الموزعين قاعدة البيانات، وأعطت كل عضو تقريراً موقعاً كل يوم، هل يكفيكم ذلك؟». إذا كانت الإجابة نعم فقد وفرت على الجميع شبكة كاملة، وإذا كانت لا فاسأل لماذا، فالسبب هو المتطلب الحقيقي الذي يجب أن تصممه.

## السؤال الثالث: هل يكفي أن يكتشف كل طرف التعديل بنفسه؟

هذا هو السؤال الذي يغيب عن أغلب النقاشات، وهو الأهم في قصتنا. فالموزع قال «حتى لا يستطيع أحد أن يغيرها»، ولكن هل يحتاج فعلاً أن يكون التغيير مستحيلاً، أم يكفيه أن يكون أي تغيير ظاهراً له فوراً؟ والفرق بين الاثنين كبير: منع التعديل Tamper Resistance يحتاج أن تكون النسخ عند أطراف مستقلة وأن يتفقوا على كل كتابة، أما إظهار التعديل Tamper Evidence فيكفيه سجل واحد بسلسلة هاش، ونسخة صغيرة موقعة من رأس السجل عند كل شريك. فإذا عدل أحد الماضي ظهر ذلك عند المقارنة، ثم يأتي دور العقد والنظام والمحاكم كما في أي علاقة تجارية.

وهذه الفكرة ليست نظرية: شهادات TLS التي يستخدمها كل موقع على الإنترنت تسجل في سجلات علنية تسمى شفافية الشهادات Certificate Transparency، وهي سجلات لا تقبل إلا الإضافة Append-only مبنية على شجرة Merkle كما في [RFC 9162](https://www.rfc-editor.org/rfc/rfc9162.html?ref=arabroot.io)، ويشغل كل سجل جهة واحدة، ويستطيع أي شخص أن يراقبها ويكتشف إذا حاول المشغل أن يغير ما سجله، دون أي إجماع بين المشغلين. وقد شرحنا الشهادات نفسها في [مقال الشهادات الرقمية](https://arabroot.io/articles/%D8%A7%D9%84%D8%B4%D9%87%D8%A7%D8%AF%D8%A7%D8%AA-%D8%A7%D9%84%D8%B1%D9%82%D9%85%D9%8A%D8%A9-tls-%D9%88-x509-%D9%88%D8%B5%D9%8A%D8%BA-pem-%D9%88-der/). والآن سوف نبني نسخة صغيرة من هذه الفكرة لمنصة الضمان، ونرى بأعيننا أين تكفي وأين لا تكفي.

### تجربة عملية: سجل بسلسلة هاش في PostgreSQL

نشغل PostgreSQL في Container، ونضع ملفات التجربة في مجلد يربط بداخله، وكلمة المرور هنا للتجربة المحلية فقط:

```bash
docker run -d --name lab-need-pg -e POSTGRES_PASSWORD=lab-only -v "$PWD:/lab" postgres:18.6-alpine
docker exec -i lab-need-pg psql -U postgres -t -c "select version()"
```

والمخرج سوف يكون كما يلي:

```text
 PostgreSQL 18.6 on x86_64-pc-linux-musl, compiled by gcc (Alpine 15.2.0) 15.2.0, 64-bit
```

والملف التالي ينشئ جدول أحداث الضمان، ودالة Trigger تحسب لكل صف جديد هاش SHA-256 من هاش الصف الذي قبله مع محتوى الصف نفسه، باستخدام إضافة [pgcrypto](https://www.postgresql.org/docs/18/pgcrypto.html?ref=arabroot.io). احفظه باسم `01-ledger.sql`:

```sql
-- A tamper-evident event log: every row stores the hash of the row before it.
CREATE EXTENSION IF NOT EXISTS pgcrypto;

CREATE TABLE warranty_events (
  id         bigserial PRIMARY KEY,
  party      text        NOT NULL,             -- who wrote the event (factory, distributor, service centre)
  serial_no  text        NOT NULL,             -- device serial number
  event      text        NOT NULL,             -- sold, repaired, replaced ...
  created_at timestamptz NOT NULL DEFAULT now(),
  prev_hash  bytea       NOT NULL,
  row_hash   bytea       NOT NULL
);

CREATE FUNCTION chain_event() RETURNS trigger AS $$
DECLARE last bytea;
BEGIN
  -- one writer at a time, so two inserts never take the same prev_hash
  PERFORM pg_advisory_xact_lock(42);
  SELECT row_hash INTO last FROM warranty_events ORDER BY id DESC LIMIT 1;
  NEW.prev_hash := coalesce(last, '\x00'::bytea);
  NEW.row_hash  := digest(NEW.prev_hash || convert_to(
                     NEW.party || '|' || NEW.serial_no || '|' || NEW.event || '|' || NEW.created_at::text, 'UTF8'), 'sha256');
  RETURN NEW;
END $$ LANGUAGE plpgsql;

CREATE TRIGGER chain_before_insert BEFORE INSERT ON warranty_events
  FOR EACH ROW EXECUTE FUNCTION chain_event();

-- nobody edits or deletes through the application role
REVOKE UPDATE, DELETE ON warranty_events FROM PUBLIC;
```

في الإعداد أعلاه لاحظ التالي:

- الدالة `pg_advisory_xact_lock(42)` تجعل الإدراجات تمر واحداً بعد الآخر، والسبب أن معاملتين متزامنتين قد تقرآن نفس آخر صف فتأخذان نفس `prev_hash`، فتتفرع السلسلة. والقفل يتحرر تلقائياً عند نهاية المعاملة كما في [توثيق الأقفال](https://www.postgresql.org/docs/18/explicit-locking.html?ref=arabroot.io)، وثمنه أن الكتابة في هذا الجدول تصبح متسلسلة.
- الهاش يحسب من نص ثابت الترتيب تفصل حقوله العلامة `|`، حتى يحسبه أي طرف بنفس الطريقة لاحقاً، وهي نفس فكرة `sort_keys` في المقال الأول.
- الصف الأول لا يوجد قبله صف، فيأخذ القيمة `\x00` بدلاً من هاش سابق، مثل كتلة التكوين Genesis Block.

ننفذ الملف ثم نضيف أربعة أحداث لجهاز واحد، كل حدث من جهة مختلفة:

```bash
docker exec -i lab-need-pg psql -U postgres -v ON_ERROR_STOP=1 -f /lab/01-ledger.sql
docker exec -i lab-need-pg psql -U postgres -v ON_ERROR_STOP=1 <<'EOF'
INSERT INTO warranty_events (party, serial_no, event) VALUES
 ('factory',     'SN-1001', 'manufactured'),
 ('distributor', 'SN-1001', 'sold to retailer'),
 ('retailer',    'SN-1001', 'sold to customer, warranty starts'),
 ('service',     'SN-1001', 'screen repaired under warranty');
SELECT id, party, event, encode(prev_hash,'hex')::char(12) AS prev, encode(row_hash,'hex')::char(12) AS hash FROM warranty_events ORDER BY id;
EOF
```

والمخرج سوف يكون كما يلي:

```text
CREATE EXTENSION
CREATE TABLE
CREATE FUNCTION
CREATE TRIGGER
REVOKE
INSERT 0 4
 id |    party    |               event               |     prev     |     hash
----+-------------+-----------------------------------+--------------+--------------
  1 | factory     | manufactured                      | 00           | c268317b14d6
  2 | distributor | sold to retailer                  | c268317b14d6 | 1b49b8f0f6c7
  3 | retailer    | sold to customer, warranty starts | 1b49b8f0f6c7 | 3b6c6a12a90d
  4 | service     | screen repaired under warranty    | 3b6c6a12a90d | a51bed56a0d2
(4 rows)
```

لاحظ أن عمود `prev` في كل صف هو نفس عمود `hash` في الصف الذي قبله، تماماً مثل حقل `parentHash` في كتل Ethereum. والهاشات عندك سوف تختلف لأن وقت الإدراج جزء من المحتوى. والآن نحتاج استعلاماً يعيد حساب كل الهاشات ويقارنها بالمحفوظ، احفظه باسم `02-verify.sql`:

```sql
-- Recompute every hash and compare it with what is stored.
WITH r AS (
  SELECT id, prev_hash, row_hash,
         lag(row_hash) OVER (ORDER BY id) AS real_prev,
         digest(prev_hash || convert_to(party || '|' || serial_no || '|' || event || '|' || created_at::text, 'UTF8'), 'sha256') AS recomputed
  FROM warranty_events)
SELECT count(*) AS rows,
       count(*) FILTER (WHERE recomputed <> row_hash) AS bad_content,
       count(*) FILTER (WHERE real_prev IS NOT NULL AND real_prev <> prev_hash) AS bad_links,
       min(id) FILTER (WHERE recomputed <> row_hash OR (real_prev IS NOT NULL AND real_prev <> prev_hash)) AS first_bad_id
FROM r;
```

```bash
docker exec -i lab-need-pg psql -U postgres -f /lab/02-verify.sql
```

والمخرج سوف يكون كما يلي:

```text
 rows | bad_content | bad_links | first_bad_id
------+-------------+-----------+--------------
    4 |           0 |         0 |
(1 row)
```

الدالة `lag` تعطي هاش الصف السابق فعلاً، فنقارنه بما حفظه الصف في `prev_hash`، ونعيد حساب هاش كل صف من محتواه ونقارنه بما في `row_hash`، والنتيجة صفر في الحالتين، أي أن السلسلة سليمة.

### ماذا يحدث إذا حاول التطبيق أن يعدل؟

أول خط دفاع لا علاقة له بالهاش، وإنما بالصلاحيات: ننشئ دوراً للتطبيق يستطيع أن يقرأ ويضيف فقط، ثم نجرب التعديل والحذف به:

```bash
docker exec -i lab-need-pg psql -U postgres <<'EOF'
CREATE ROLE app LOGIN PASSWORD 'lab-only';
GRANT SELECT, INSERT ON warranty_events TO app;
GRANT USAGE ON SEQUENCE warranty_events_id_seq TO app;
EOF
docker exec -i -e PGPASSWORD=lab-only lab-need-pg psql -h 127.0.0.1 -U app -d postgres -c "UPDATE warranty_events SET event = 'x' WHERE id = 2;"
docker exec -i -e PGPASSWORD=lab-only lab-need-pg psql -h 127.0.0.1 -U app -d postgres -c "DELETE FROM warranty_events WHERE id = 2;"
```

والمخرج سوف يكون كما يلي:

```text
CREATE ROLE
GRANT
GRANT
ERROR:  permission denied for table warranty_events
ERROR:  permission denied for table warranty_events
```

هذا يحمي من خطأ في الكود أو من مخترق وصل إلى التطبيق، ولكنه لا يحمي من صاحب صلاحية أعلى، وهو بالضبط ما يخشاه الموزع في قصتنا: مدير قاعدة البيانات عندك، أو موظف عندك تحت ضغط عميل كبير.

### نجرب العطل: مدير قاعدة البيانات يعدل حدثاً

لنفرض أن مركز الصيانة أصلح الشاشة تحت الضمان، ثم أراد أحدهم لاحقاً أن يقول إن الإصلاح كان على حساب العميل. نعدل الصف 4 بحساب `postgres` الذي يملك كل الصلاحيات، ثم نشغل التحقق:

```bash
docker exec -i lab-need-pg psql -U postgres -c "UPDATE warranty_events SET event = 'screen repaired, paid by customer' WHERE id = 4;"
docker exec -i lab-need-pg psql -U postgres -f /lab/02-verify.sql
```

والمخرج سوف يكون كما يلي:

```text
UPDATE 1
 rows | bad_content | bad_links | first_bad_id
------+-------------+-----------+--------------
    4 |           1 |         0 |            4
(1 row)
```

التحقق كشف التعديل وحدد الصف بالضبط، لأن المحتوى الجديد لا يطابق الهاش المحفوظ. ولكن مدير قاعدة البيانات يعرف كيف تحسب الدالة الهاش، ويستطيع أن يحسبه بنفسه. احفظ الملف التالي باسم `03-rewrite.sql`:

```sql
-- What an administrator with full access can do: recompute the hash of the edited row (and of every row after it).
UPDATE warranty_events
SET row_hash = digest(prev_hash || convert_to(party || '|' || serial_no || '|' || event || '|' || created_at::text, 'UTF8'), 'sha256')
WHERE id = 4;
```

```bash
docker exec -i lab-need-pg psql -U postgres -f /lab/03-rewrite.sql
docker exec -i lab-need-pg psql -U postgres -f /lab/02-verify.sql
```

والمخرج سوف يكون كما يلي:

```text
UPDATE 1
 rows | bad_content | bad_links | first_bad_id
------+-------------+-----------+--------------
    4 |           0 |         0 |
(1 row)
```

السلسلة تبدو سليمة تماماً، والتحقق الداخلي لم يكتشف شيئاً. وفي حالتنا عدلنا الصف الأخير فقط، ولو كان الصف في المنتصف لاحتاج أن يعيد حساب كل الصفوف بعده، وهذا استعلام واحد أيضاً على جهازه. وهذه هي نفس النتيجة التي رأيناها مع `chain.py` في المقال الأول: السلسلة وحدها تجعل التعديل ظاهراً لمن يقارن، ولا تمنع من يملك كل النسخ من إعادة كتابتها.

### نقاط التحقق الموقعة Signed Checkpoints عند الشركاء

الحل البسيط الذي لا يحتاج أي شبكة: في نهاية كل يوم يوقع المشغل رأس السجل، أي رقم آخر صف وهاشه، بمفتاحه الخاص، ويرسل التوقيع إلى كل شريك فيحفظه عنده. فإذا أعاد أحد كتابة الماضي لاحقاً، فلن يطابق الهاش الحالي الهاش الذي وقعه المشغل وحفظه الشريك، ولا يستطيع المشغل أن ينكر توقيعه. والملف التالي يحاكي الطرفين بتوقيع Ed25519، احفظه باسم `checkpoint.py`:

```python
# The operator signs the head of the log; every partner keeps a copy of the signed checkpoint.
import json, sys
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey, Ed25519PublicKey
from cryptography.hazmat.primitives import serialization as s

cmd = sys.argv[1]
if cmd == "sign":                                   # operator side: sign "row id + hash" once a day
    row_id, head = sys.argv[2], sys.argv[3]
    key = Ed25519PrivateKey.generate()
    msg = f"warranty-log head id={row_id} hash={head}".encode()
    cp = {"id": row_id, "hash": head, "sig": key.sign(msg).hex(),
          "pub": key.public_key().public_bytes(s.Encoding.Raw, s.PublicFormat.Raw).hex()}
    json.dump(cp, open("checkpoint.json", "w"), indent=1)
    print("checkpoint saved by the partner:", cp["hash"][:16], "sig", cp["sig"][:16] + "...")
elif cmd == "check":                                # partner side: compare the live log with the copy it kept
    cp = json.load(open("checkpoint.json"))
    live = sys.argv[2]
    pub = Ed25519PublicKey.from_public_bytes(bytes.fromhex(cp["pub"]))
    pub.verify(bytes.fromhex(cp["sig"]), f"warranty-log head id={cp['id']} hash={cp['hash']}".encode())
    print("signature on checkpoint: valid (the operator did sign this head)")
    print("live hash of row", cp["id"], ":", live[:16])
    print("hash in checkpoint      :", cp["hash"][:16])
    print("RESULT:", "log matches" if live == cp["hash"] else "LOG WAS REWRITTEN after the checkpoint")
```

والترتيب الصحيح للتجربة أن نوقع نقطة التحقق قبل التعديل، أي بعد إدراج الصفوف الأربعة مباشرة، فنقرأ هاش الصف 4 ونوقعه:

```bash
H=$(docker exec -i lab-need-pg psql -U postgres -At -c "select encode(row_hash,'hex') from warranty_events where id=4")
echo $H
docker run --rm --name lab-need-py -v "$PWD:/lab" -w /lab python:3.13.16-slim \
  bash -c "pip install -q --root-user-action=ignore cryptography==46.0.3 && python checkpoint.py sign 4 $H"
```

والمخرج سوف يكون كما يلي، بعد سطري تنبيه من pip:

```text
a51bed56a0d2426f6912b90bc05d004f279fc0856dd89e733ff58298008ad8f2
checkpoint saved by the partner: a51bed56a0d2426f sig 538fa9649b0235a5...
```

ثم بعد التعديل وإعادة حساب الهاش، يقرأ الشريك الهاش الحالي للصف 4 ويقارنه بما عنده:

```bash
H=$(docker exec -i lab-need-pg psql -U postgres -At -c "select encode(row_hash,'hex') from warranty_events where id=4")
docker run --rm --name lab-need-py -e PIP_DISABLE_PIP_VERSION_CHECK=1 -v "$PWD:/lab" -w /lab python:3.13.16-slim \
  bash -c "pip install -q --root-user-action=ignore cryptography==46.0.3 && python checkpoint.py check $H"
```

والمخرج سوف يكون كما يلي:

```text
signature on checkpoint: valid (the operator did sign this head)
live hash of row 4 : 76ed8ce641a2d7bf
hash in checkpoint      : a51bed56a0d2426f
RESULT: LOG WAS REWRITTEN after the checkpoint
```

في الإعداد أعلاه لاحظ التالي:

- التوقيع على نقطة التحقق صحيح، أي أن المشغل نفسه وقع على الهاش `a51bed56…` في ذلك اليوم، ولا يستطيع أن يدعي أن الشريك اخترعه.
- الهاش الحالي للصف 4 أصبح `76ed8ce6…`، والتحقق الداخلي يقول إن السلسلة سليمة، ولكن المقارنة مع النسخة الخارجية تكشف أن السجل أعيدت كتابته بعد التوقيع.
- الشريك لم يحتج نسخة من قاعدة البيانات ولا عقدة، وإنما 64 حرفاً وتوقيعاً واحداً لكل يوم. والتطبيق الحقيقي يعطي الشريك أيضاً الصفوف التي تخصه ليتحقق من أنها جزء من السلسلة.
- في هذه التجربة ولدنا مفتاح المشغل وقت التوقيع لتبقى قصيرة، وفي النظام الحقيقي يكون المفتاح ثابتاً ومحمياً، ومفتاحه العام منشوراً عند الشركاء مسبقاً، كما شرحنا في [مقال التشفير للمطورين](https://arabroot.io/articles/%D8%A7%D9%84%D8%AA%D8%B4%D9%81%D9%8A%D8%B1-%D9%84%D9%84%D9%85%D8%B7%D9%88%D8%B1%D9%8A%D9%86-%D8%A7%D9%84%D9%87%D8%A7%D8%B4-%D9%88%D9%83%D9%84%D9%85%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B1%D9%88%D8%B1-%D9%88%D8%A7%D9%84%D9%85%D9%81%D8%A7%D8%AA%D9%8A%D8%AD/).

والصورة التالية تجمع المراحل الأربع بالقيم الحقيقية:

![مخطط من أربع مراحل: في الأعلى أربعة صفوف لجهاز SN-1001 من المصنع والموزع والمتجر ومركز الصيانة، كل صف يحمل هاش الصف قبله، ونقطة تحقق عند الموزع بالهاش a51bed56a0d2 وتوقيع Ed25519، وفي الأسفل ثلاث بطاقات: مدير قاعدة البيانات يعدل الصف 4 فيكشفه التحقق الداخلي، ثم يعيد حساب الهاش فلا يكشفه التحقق الداخلي، ثم يقارن الموزع بنقطة التحقق فيجد الهاش الحالي 76ed8ce641a2 مختلفاً عن a51bed56a0d2 فيظهر LOG WAS REWRITTEN](https://arabroot.io/content/images/2026/10/need-blockchain-test-02-tamper-evident.webp)

السلسلة تكشف التعديل الجزئي، ونقطة التحقق الموقعة عند الشريك تكشف إعادة الكتابة الكاملة

إذن متى يكفي هذا الحل؟ عندما يكون هدف الشركاء أن يكتشفوا أي تلاعب ويثبتوه، ثم يحلوا الخلاف بالعقود كما يحلون أي خلاف تجاري، وهذه حالة أغلب العلاقات بين الشركات. ومتى لا يكفي؟ عندما يكون اكتشاف التلاعب بعد حدوثه غير مقبول أصلاً، كأن يكون التعديل قادراً على نقل أموال لا يمكن استرجاعها، أو عندما لا يقبل الشركاء أن يستطيع المشغل رفض كتاباتهم أو تأخيرها، وهنا تنتقل إلى السؤال الرابع ثم الخامس.

## السؤال الرابع: هل في البيانات ما هو شخصي أو سري أو قد يلزم حذفه؟

في منصة الضمان بيانات شخصية واضحة: اسم العميل ورقم جواله وعنوانه، وكلها تحتاج أن تصحح إذا أخطأ أحد في كتابتها، وأن تحذف عندما تنتهي الحاجة إليها. وفي المملكة يعطي [نظام حماية البيانات الشخصية](https://laws.boe.gov.sa/BoeLaws/Laws/LawDetails/b7cfae89-828e-4994-b167-adaa00e37188/1?ref=arabroot.io) في مادته الرابعة صاحب البيانات حقوقاً منها الحق في طلب تصحيح بياناته وتحديثها، والحق في طلب إتلاف بياناته المتوافرة لدى جهة التحكم مما انتهت الحاجة إليه، وتفاصيل التطبيق في النظام ولوائحه. وتقرير NIST نفسه يذكر أن البلوكتشين لا يعرف من عمليات CRUD إلا الإنشاء والقراءة، وأن المعاملة التي تعلم بيانات قديمة كمحذوفة تترك البيانات نفسها في السلسلة. والآن سوف نرى ذلك عملياً بدلاً من أن نصدقه.

### نفس الأحداث في عقد ذكي على Anvil

نكتب عقداً ذكياً صغيراً يسجل نفس أحداث الضمان، ونضيف إليه دالة تحفظ رقم جوال صاحب الجهاز، وهي موجودة هنا فقط لنبين لماذا لا يجب أن تكون في أي عقد حقيقي. أنشئ مجلداً باسم `chain` فيه الملف `src/WarrantyLog.sol`:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

// The same warranty events, written to a chain instead of a database table.
contract WarrantyLog {
    event Recorded(address indexed party, bytes32 indexed serial, string what);

    mapping(bytes32 => string) public lastEvent;   // contract storage: every node keeps it
    mapping(bytes32 => string) public ownerPhone;  // personal data (to show why it must stay off-chain)

    function record(bytes32 serial, string calldata what) external {
        lastEvent[serial] = what;
        emit Recorded(msg.sender, serial, what);
    }

    function setPhone(bytes32 serial, string calldata phone) external {
        ownerPhone[serial] = phone;
    }
}
```

والملف `foundry.toml` في نفس المجلد يثبت إصدار المترجم Compiler حتى يعطي نفس النتيجة كل مرة:

```ini
[profile.default]
src = "src"
out = "out"
solc = "0.8.30"
```

ثم نشغل Anvil من Image مجموعة Foundry الرسمية، وهي شبكة Ethereum محلية للتطوير شرحناها في [المقال الأول](https://arabroot.io/articles/%D8%A7%D9%84%D8%A8%D9%84%D9%88%D9%83%D8%AA%D8%B4%D9%8A%D9%86-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D9%83%D9%8A%D9%81-%D9%8A%D8%B9%D9%85%D9%84-%D9%88%D9%85%D8%AA%D9%89-%D9%84%D8%A7-%D8%AA%D8%AD%D8%AA%D8%A7%D8%AC%D9%87/#lab-anvil)، ونربط المجلد بداخلها:

```bash
docker run -d --name lab-need-anvil -v "$PWD/chain:/chain" -w /chain ghcr.io/foundry-rs/foundry:v1.8.6 "anvil --host 0.0.0.0"
docker exec lab-need-anvil forge build
```

وهنا ظهرت لنا مشكلتان حقيقيتان أثناء التجربة على Docker Desktop في Windows، وقد تظهران لك. الأولى أن الأوامر داخل ال Image تعمل بمستخدم اسمه `foundry` وليس root، فلم يستطع `forge build` أن يكتب مجلد `out` داخل المجلد المربوط، والحل أن تعطي المجلد صلاحية الكتابة بأمر `docker exec -u root lab-need-anvil sh -c "chmod -R 777 /chain"` في بيئة التجربة فقط. والثانية أن الأدوات التي تكتب ملفاً لكل معاملة، مثل `forge script` الذي سوف نستخدمه بعد قليل، تصبح بطيئة جداً عندما تكتب في مجلد مربوط من Windows، فنسخنا المشروع إلى `/tmp/chain` داخل ال Container ونفذنا منه:

```bash
docker exec lab-need-anvil sh -c "rm -rf /tmp/chain && cp -r /chain /tmp/chain"
```

ثم ننشر العقد، ونسجل نفس حدث الإصلاح الذي سجلناه في الجدول، ونستخدم أول حساب اختبار في Anvil، ومفتاحه معروف للجميع فلا يصلح لأي شبكة حقيقية:

```bash
A="docker exec -w /tmp/chain lab-need-anvil"
K=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
$A forge create src/WarrantyLog.sol:WarrantyLog --broadcast --private-key $K
C=0x5FbDB2315678afecb367f032d93F642f64180aa3
S=$($A cast format-bytes32-string SN-1001)
$A cast send $C "record(bytes32,string)" $S "screen repaired under warranty" --private-key $K | grep -E '^(blockNumber|gasUsed|status) '
```

والمخرج سوف يكون كما يلي:

```text
Compiler run successful!
Deployer: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
Deployed to: 0x5FbDB2315678afecb367f032d93F642f64180aa3
Transaction hash: 0x2d510fbc1804bc706f2162e4f3318a737dc9cc485c199c3b12439d1ee12632c0
blockNumber          2
gasUsed              48159
status               1 (success)
```

تسجيل حدث واحد استهلك 48,159 وحدة غاز، أي أكثر من ضعف التحويل البسيط الذي يكلف 21,000، والسبب أن المعاملة تكتب في تخزين العقد Storage وتصدر حدثاً Event، وكل عملية في آلة EVM لها تكلفة كما يشرح [توثيق الغاز](https://ethereum.org/en/developers/docs/gas/?ref=arabroot.io). وعلى أي شبكة حقيقية تدفع هذا الغاز بعملة الشبكة بسعر يتغير كل لحظة، لذلك نقارن بوحدات الغاز وليس بالريال.

### ألف حدث في الجدول وفي العقد

الآن نكتب ألف حدث «inspected» في العقد، كل حدث في معاملة مستقلة، بسكربت Foundry. احفظ الملف التالي باسم `chain/script/Load.s.sol`، وهو يحتاج مكتبة forge-std التي تثبتها بالأمر `forge install foundry-rs/forge-std --no-git`:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {Script} from "forge-std/Script.sol";
import {WarrantyLog} from "../src/WarrantyLog.sol";

// Sends 1000 "inspected" events, one transaction each, like the 10,000 rows we wrote to PostgreSQL.
contract Load is Script {
    function run(address log) external {
        vm.startBroadcast();
        for (uint256 i = 0; i < 1000; i++) {
            WarrantyLog(log).record(bytes32(2000 + i), "inspected");
        }
        vm.stopBroadcast();
    }
}
```

```bash
$A forge script script/Load.s.sol:Load --sig "run(address)" $C --rpc-url http://127.0.0.1:8545 --private-key $K --broadcast
```

والجزء الأخير من المخرج سوف يكون كما يلي:

```text
==========================
Chain 31337
Estimated max fee per gas: 1.758282451 gwei
Estimated base fee per gas: 0.879141225 gwei
Estimated max priority fee per gas: 0.000000001 gwei
Estimated total gas used for script: 66103480
Estimated amount required: 0.11622858883402948 ETH
==========================
==========================
ONCHAIN EXECUTION COMPLETE & SUCCESSFUL.
Transactions saved to: /tmp/chain/broadcast/Load.s.sol/31337/run-latest.json
Sensitive values saved to: /tmp/chain/cache/Load.s.sol/31337/run-latest.json
```

وملف الإيصالات الذي يحفظه forge في `broadcast/Load.s.sol/31337/run-latest.json` يبين ما حدث فعلاً: ألف إيصال كلها ناجحة، ومجموع الغاز المستهلك فعلاً 47,846,952 وحدة، أي بين 47,835 و47,847 لكل حدث، ووزعت Anvil المعاملات على 22 كتلة من الكتلة 3 إلى الكتلة 24\. ولاحظ أن رقم «Estimated total gas» تقدير أعلى من الحقيقي، فالأداة تحسب هامش أمان. والمقارنة العادلة ليست بالسرعة على جهاز واحد، فشبكة Anvil المحلية عقدة واحدة دون أي إجماع، وإنما بطبيعة التكلفة.

وفي الجهة الأخرى نكتب 10,000 حدث في جدول PostgreSQL بنفس دالة السلسلة. نولد ملف الإدراجات بسطر Python، ثم ننفذه مرتين: مرة كل إدراج في معاملة مستقلة، ومرة كلها في معاملة واحدة بالخيار `-1`:

```bash
python3 -c "
with open('bulk.sql','w') as f:
  for i in range(10000): f.write(f\"INSERT INTO warranty_events (party, serial_no, event) VALUES ('service', 'SN-{2000+i}', 'inspected');\n\")"
time (docker exec -i lab-need-pg psql -U postgres -q -f /lab/bulk.sql)
time (docker exec -i lab-need-pg psql -U postgres -q -1 -f /lab/bulk.sql)
docker exec -i lab-need-pg psql -U postgres -f /lab/02-verify.sql
docker exec -i lab-need-pg psql -U postgres -At -c "select pg_size_pretty(pg_total_relation_size('warranty_events'))"
```

والمخرج سوف يكون كما يلي، مع حذف سطري `user` و`sys` من كل قياس:

```text
real	0m24.856s
real	0m5.761s
 rows  | bad_content | bad_links | first_bad_id
-------+-------------+-----------+--------------
 20004 |           0 |         0 |
(1 row)

3408 kB
```

في الإعداد أعلاه لاحظ التالي:

- عشرة آلاف إدراج كل منها في معاملة مستقلة احتاجت قرابة 25 ثانية، أي قرابة 400 إدراج في الثانية، رغم القفل الذي يجعلها متسلسلة، وأغلب الوقت في تثبيت كل معاملة على القرص Commit.
- نفس العدد في معاملة واحدة احتاج أقل من 6 ثوان، وهذا خيار لا يوجد في الشبكة، فكل حدث هناك معاملة موقعة مستقلة لها رسومها.
- التحقق مر على 20,004 صفاً وكلها سليمة، أي أن السلسلة لم تتفرع رغم الإدراجات المتتالية، وهذه فائدة القفل.
- الجدول كله 3.4 ميجابايت على سيرفر واحد تملكه وتنسخه احتياطياً، أما بيانات العقد فتحفظها كل عقدة في الشبكة طول عمرها.

وعلى شبكة Ethereum العامة لا تحدد سرعة جهازك متى تدخل المعاملة، وإنما الشبكة نفسها: الزمن مقسم إلى خانات Slots مدة كل منها 12 ثانية كما في [توثيق إثبات الحصة](https://ethereum.org/en/developers/docs/consensus-mechanisms/pos/?ref=arabroot.io)، والنهائية Finality تأتي على حدود الحقب Epochs كما شرحنا في [قسم النهائية](https://arabroot.io/articles/%D8%A7%D9%84%D8%A7%D8%AC%D9%85%D8%A7%D8%B9-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D9%84%D9%88%D9%83%D8%AA%D8%B4%D9%8A%D9%86-%D8%A7%D8%AB%D8%A8%D8%A7%D8%AA-%D8%A7%D9%84%D8%B9%D9%85%D9%84-%D9%88%D8%A7%D8%AB%D8%A8%D8%A7%D8%AA-%D8%A7%D9%84%D8%AD%D8%B5%D8%A9/#finality). والصورة التالية تضع الأرقام جنباً إلى جنب:

![مقارنة من عمودين: على اليمين PostgreSQL مع سلسلة الهاش حيث احتاجت 10,000 إدراج في معاملات مستقلة 24.9 ثانية، وفي معاملة واحدة 5.8 ثانية، وحجم الجدول بعد 20,004 صفاً 3.4 ميجابايت، والتحقق بلا أخطاء، والبيانات على سيرفرك، وعلى اليسار عقد WarrantyLog على شبكة Anvil المحلية حيث كلف تسجيل حدث واحد 48,159 غاز مقابل 21,000 للتحويل البسيط، واستهلك ألف حدث 47,846,952 غاز في 22 كتلة، وعلى الشبكة العامة كتلة كل 12 ثانية، والبيانات عند كل عقدة للأبد](https://arabroot.io/content/images/2026/10/need-blockchain-test-03-costs.webp)

في قاعدة البيانات تدفع وقت سيرفر تملكه، وفي الشبكة تدفع غازاً لكل كتابة وتحفظ كل عقدة كل شيء

### نجرب العطل: «نحذف» رقم الجوال من العقد

نكتب رقم جوال وهمياً لصاحب الجهاز بحساب ثان، ثم «نحذفه» بكتابة نص فارغ مكانه، ثم نقرأ القيمة الحالية:

```bash
K1=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d
$A cast send $C "setPhone(bytes32,string)" $S "0555123456" --private-key $K1 | grep -E '^(blockNumber|status|transactionHash) '
$A cast send $C "setPhone(bytes32,string)" $S "" --private-key $K1 | grep -E '^(blockNumber|status) '
$A cast call $C "ownerPhone(bytes32)(string)" $S
```

والمخرج سوف يكون كما يلي:

```text
blockNumber          25
status               1 (success)
transactionHash      0x93a908ce05bc2569303698e32112c560971fba81267cbd05b2ce14f3a938b1a9
blockNumber          26
status               1 (success)
""
```

القيمة الحالية فارغة، والتطبيق الذي يقرأ الحالة الحالية سوف يقول إن الرقم حذف. ولكن ماذا يحدث إذا سأل أحد عن حالة العقد في الكتلة السابقة، أو قرأ المعاملة نفسها؟

```bash
$A cast call $C "ownerPhone(bytes32)(string)" $S --block 25
$A cast calldata-decode "setPhone(bytes32,string)" $($A cast tx 0x93a908ce05bc2569303698e32112c560971fba81267cbd05b2ce14f3a938b1a9 input)
```

والمخرج سوف يكون كما يلي:

```text
"0555123456"
0x534e2d3130303100000000000000000000000000000000000000000000000000
"0555123456"
```

الرقم ما زال موجوداً في مكانين: في حالة العقد التاريخية التي تحفظها أي عقدة أرشيفية Archive Node، وفي بيانات المعاملة Calldata التي حفظتها كل عقدة كاملة لأنها جزء من الكتلة. ولا يوجد أمر في الشبكة يحذف معاملة من كتلة قديمة، لأن حذفها يغير هاش الكتلة وكل ما بعدها، وهذه هي الخاصية التي اخترت البلوكتشين من أجلها في الأصل.

### ماذا لو نشرنا هاش الرقم بدلاً من الرقم؟

هذا هو الحل الذي يقترحه أغلب الفرق عند هذه النقطة: لا نضع الرقم، وإنما هاشه، والهاش لا يمكن الرجوع منه إلى المدخل. وهذا صحيح عندما يكون المدخل عشوائياً وطويلاً، أما أرقام الجوال فشكلها معروف وعددها محدود. والملف التالي يجرب ذلك، احفظه باسم `phonehash.py`:

```python
# "We only put the hash of the phone number on the chain" - is that enough?
import hashlib, hmac, secrets, time

phone = "0555123456"                                   # a made-up number
on_chain = hashlib.sha256(phone.encode()).hexdigest()  # what a naive design publishes
print("published hash:", on_chain[:24], "...")

start = time.perf_counter()
for n in range(1_000_000):                             # every number that starts with 0555
    guess = f"0555{n:06d}"
    if hashlib.sha256(guess.encode()).hexdigest() == on_chain:
        print(f"found {guess} after {n + 1:,} guesses in {time.perf_counter() - start:.2f}s")
        break

key = secrets.token_bytes(32)                          # kept off-chain by the operator (a pepper)
tag = hmac.new(key, phone.encode(), hashlib.sha256).hexdigest()
print("HMAC published:", tag[:24], "... (without the key, guessing numbers gives nothing)")
```

```bash
docker run --rm --name lab-need-py -v "$PWD:/lab" -w /lab python:3.13.16-slim python phonehash.py
```

والمخرج سوف يكون كما يلي:

```text
published hash: 89a50e2c8b02e95641cc8b4a ...
found 0555123456 after 123,457 guesses in 0.39s
HMAC published: 150224401bad18b36ca445c1 ... (without the key, guessing numbers gives nothing)
```

وجدنا الرقم في أقل من نصف ثانية بلغة Python على جهاز عادي، ولو كان الرقم في آخر المليون لاحتاج بضع ثوان فقط. لذلك هاش البيانات الشخصية دون سر ليس إخفاء لها، وهذه نفس المشكلة التي شرحناها مع كلمات المرور والملح Salt والفلفل Pepper في [مقال التشفير للمطورين](https://arabroot.io/articles/%D8%A7%D9%84%D8%AA%D8%B4%D9%81%D9%8A%D8%B1-%D9%84%D9%84%D9%85%D8%B7%D9%88%D8%B1%D9%8A%D9%86-%D8%A7%D9%84%D9%87%D8%A7%D8%B4-%D9%88%D9%83%D9%84%D9%85%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B1%D9%88%D8%B1-%D9%88%D8%A7%D9%84%D9%85%D9%81%D8%A7%D8%AA%D9%8A%D8%AD/). والتصميم الأنسب أن تبقى البيانات الشخصية في قاعدة بيانات تستطيع أن تصححها وتحذفها، وأن تضع في السلسلة عند الحاجة مرجعاً عشوائياً أو HMAC بمفتاح سري لا يغادر سيرفرك، فإذا طلب صاحب البيانات الإتلاف حذفت السطر، ولم يبق في السلسلة ما يدل عليه. والصورة التالية تلخص التجربتين:

![ثلاث بطاقات: الأولى حذف رقم الجوال من العقد حيث كتب في كتلة ثم كتب مكانه نص فارغ في الكتلة التالية، والقيمة الحالية فارغة ولكن القراءة في الكتلة السابقة وفك بيانات المعاملة يظهران 0555123456، والثانية نشر هاش الرقم حيث وجد الرقم بعد 123,457 محاولة في 0.39 ثانية، والثالثة التصميم الأنسب حيث تبقى البيانات الشخصية في قاعدة بيانات قابلة للحذف وفي السلسلة HMAC بمفتاح سري](https://arabroot.io/content/images/2026/10/need-blockchain-test-05-personal-data.webp)

ما يدخل السلسلة يبقى فيها، والهاش لا يخفي القيم التي يمكن تخمينها

🛑

لا تضع في أي سلسلة، عامة كانت أو خاصة، اسماً أو رقم جوال أو رقم هوية أو عنواناً، ولا هاشاً لها دون مفتاح سري، والسبب أنك لا تستطيع أن تحذفها لاحقاً من كل العقد إذا طلب صاحبها ذلك أو تغير النظام، وراجع المستشار القانوني قبل أي تصميم يقترب من البيانات الشخصية.

## السؤال الخامس: هل يجب أن يتحقق أي شخص في العالم دون إذن؟

إذا وصلت إلى هنا فعندك أطراف مستقلة لا تقبل مشغلاً واحداً، ولا يكفيها اكتشاف التعديل بعد حدوثه، وقد أبعدت البيانات الشخصية عن السلسلة. والسؤال الأخير يحدد نوع الشبكة: هل المطلوب أن يتحقق أي شخص في العالم دون أن يطلب إذناً من أحد، أم أن المشاركين مجموعة معروفة من الشركات؟

في منصة الضمان المشاركون معروفون: مصانع وموزعون ومتاجر ومراكز صيانة لها سجلات تجارية، والعميل لا يحتاج أن يشغل عقدة، وإنما يحتاج أن يثق بأن الشهادة التي يراها صحيحة. لذلك إذا وصلت المنصة إلى هذه النقطة فالمخرج هو شبكة مصرح بها Permissioned، يشغل فيها كل عضو عقدته، ويصدر لكل عضو هوية بشهادة، والإجماع فيها بالتصويت بين الأعضاء كما في Hyperledger Fabric أو Besu، وسوف نبني شبكة من هذا النوع في مقال قادم عن البلوكتشين الخاص للمؤسسات. ولاحظ أن هذه الشبكة لها معنى فقط إذا شغل الأعضاء عقدهم فعلاً، فإذا شغلت شركتك كل العقد نيابة عنهم عدت إلى قاعدة بيانات منسوخة أبطأ وأغلى، وهذه ملاحظة سوف تراها في الحالة الثانية أدناه.

أما الشبكة العامة فمكانها عندما يكون التحقق العلني هو المنتج نفسه: أصل رقمي يملكه أي شخص وينقله دون إذن، أو سجل يجب أن يبقى قابلاً للتحقق حتى لو اختفت كل الشركات المشاركة. وهنا تقبل كل الأثمان معاً: البيانات علنية للأبد، ولكل كتابة رسوم، والمفتاح الضائع لا يعيده أحد، والخصوصية تحتاج تصميماً خاصاً.

## حالتان موثقتان: حين لم تجد الأسئلة جواباً

التقنية في الحالتين التاليتين عملت، والذي أوقف المشروعين كان في الأسئلة الأولى، وهذا هو الدرس الذي يهمك وأنت تكتب رد الأسبوع للمدير التنفيذي.

الحالة الأولى منصة TradeLens لتتبع الشحن، والتي أعلنت عنها Maersk وIBM سنة 2018 كمنصة مبنية على البلوكتشين. وفي 29 نوفمبر 2022 أعلنت Maersk في [بيانها الصحفي](https://www.maersk.com/news/articles/2022/11/29/maersk-and-ibm-to-discontinue-tradelens?ref=arabroot.io) قرار إيقاف المنصة وإغلاقها بنهاية الربع الأول من 2023، ونقلت عن مسؤول منصات الأعمال فيها أنهم طوروا منصة قابلة للعمل، ولكن التعاون الكامل بين شركات القطاع على مستوى العالم لم يتحقق، فلم تصل المنصة إلى مستوى الجدوى التجارية اللازم للاستمرار. وإذا قرأت ذلك بأسئلتنا فهو السؤالان الأول والثاني معاً: المنصة تحتاج كتاباً مستقلين كثيرين من شركات شحن متنافسة، وهذه الشركات تحتاج أن تقبل منصة تقف خلفها شركة منافسة، والتقنية لم تحل هذه المشكلة.

والحالة الثانية مشروع استبدال نظام CHESS للمقاصة والتسوية في بورصة أستراليا ASX. ففي 7 ديسمبر 2017 أعلنت ASX في [بيان رسمي](https://www.asx.com.au/content/dam/asx/about/media-releases/2017/ASX-Selects-DLT-to-Replace-CHESS-Media-Release-7December2017.pdf?ref=arabroot.io) أنها ستستبدل CHESS بتقنية السجل الموزع DLT من شريكها Digital Asset، وأن النظام سوف تشغله ASX على شبكة خاصة آمنة المشاركون فيها معروفون ومصرح لهم. ثم في 17 نوفمبر 2022 أعلنت في [بيان آخر](https://www.asx.com.au/content/dam/asx/about/media-releases/2022/60-17-november-2022-CHESS-Replacement-ASX-reassessing-financial-derecognition%5F.pdf?ref=arabroot.io) أنها أوقفت العمل الحالي في المشروع بعد مراجعة مستقلة من Accenture قدرت أن التطبيق مكتمل بنسبة 63% فقط، وذكرت تعقيداً في التصميم المتكامل منه طريقة تفاعل متطلبات ASX مع التطبيق والسجل الذي تحته، وأنها سوف تشطب برمجيات مرسملة بقيمة 245 إلى 255 مليون دولار أسترالي قبل الضريبة. وكما يذكر [بيان مارس 2024](https://www.asx.com.au/content/dam/asx/about/media-releases/2024/14-mar-asx-commences-consultation-on-proposed-approach-to-deliver-chess-replacement.pdf?ref=arabroot.io) أعلنت ASX في نوفمبر 2023 أنها ستمضي في تصميم قائم على منتج جاهز تقدمه TATA Consultancy Services. وبأسئلتنا فهذه حالة السؤال الثاني: هناك جهة واحدة يقبلها السوق وتشغل النظام أصلاً، وهي ASX نفسها، فالسجل الموزع لم يحل مشكلة ثقة غير موجودة، وأضاف تعقيداً في التصميم.

![بطاقتان: الأولى TradeLens من Maersk وIBM، أعلن عنها سنة 2018، وفي 29 نوفمبر 2022 تقرر إيقافها لأن التعاون الكامل بين شركات القطاع لم يتحقق، وأغلقت في الربع الأول من 2023، والقراءة بالأسئلة أن المنافسين لم يقبلوا سجلاً تملكه شركة منافسة، والثانية CHESS في بورصة أستراليا، اختيرت تقنية السجل الموزع من Digital Asset في 7 ديسمبر 2017 على شبكة خاصة يشغلها ASX، وفي 17 نوفمبر 2022 أوقف العمل بعد مراجعة Accenture وتقدير اكتمال التطبيق 63% وشطب 245 إلى 255 مليون دولار أسترالي، وفي نوفمبر 2023 اختير حل قائم على منتج جاهز، والقراءة بالأسئلة أن جهة واحدة يقبلها السوق تشغل النظام أصلاً](https://arabroot.io/content/images/2026/10/need-blockchain-test-04-cases.webp)

في الحالتين عملت التقنية، والذي لم يجد جواباً هو من يشارك ومن يشغل

📌

لاحظ أن هذه القراءة بالأسئلة الخمسة تحليل منا للبيانات الرسمية، والبيانات نفسها لا تقول إن البلوكتشين كان سبب التعثر، فبيان Maersk يتحدث عن التعاون والجدوى التجارية، وبيان ASX يتحدث عن التصميم والحوكمة وإدارة المورد. والدرس العملي أن الأسئلة غير التقنية هي التي تحدد مصير المشروع قبل أن يكتب أي كود.

## ماذا تقول أطر القرار المعروفة؟

الأسئلة الخمسة ليست اختراعاً جديداً، وإنما ترتيب عملي لما تقوله الأطر المعروفة. فتقرير NIST IR 8202 في القسم 8 يذكر أن البلوكتشين قد يناسب الأنظمة التي فيها مشاركون كثيرون وموزعون، ولا يوجد فيها طرف ثالث موثوق أو لا يراد وجوده، والعمل فيها معاملات تنقل أصولاً أو معلومات بين الأطراف، ويحتاج الجميع تاريخاً كاملاً مشتركاً، ثم يعرض مخطط قرار من مديرية العلوم والتقنية في وزارة الأمن الداخلي الأمريكية DHS. ويشير التقرير أيضاً إلى ورقة [Do you need a Blockchain?](https://eprint.iacr.org/2017/375?ref=arabroot.io) لـ Karl Wüst وArthur Gervais من ETH Zurich، ويلاحظ أن أغلب المسارات في مخططها تنتهي بالإجابة «لا»، ويقول إن هذه النظرة النقدية هي التي يجب أن تأخذها أغلب المؤسسات.

ومخطط الورقة يسأل بالترتيب: هل تحتاج تخزين حالة State أصلاً؟ ثم هل هناك أكثر من كاتب؟ ثم هل تستطيع استخدام طرف ثالث موثوق متصل دائماً؟ ثم هل كل الكتاب معروفون؟ ثم هل يثق الكتاب ببعضهم؟ ثم هل تحتاج تحققاً علنياً؟ وتنتهي إجاباته إلى «لا تحتاج بلوكتشين» أو شبكة عامة أو شبكة مصرح بها علنية أو خاصة. والفرق بينه وبين أسئلتنا أننا أضفنا سؤالين يظهران كثيراً في المشاريع الحقيقية: سؤال إظهار التعديل بنقاط تحقق موقعة، لأنه البديل الذي يحل أغلب طلبات «لا أريد أن يغير أحد البيانات»، وسؤال البيانات الشخصية، لأنه يغير التصميم كله في أي نظام يخدم أفراداً في المملكة.

## أخطاء شائعة وكيف تلاحظها

- **«البلوكتشين يضمن صحة البيانات»**: السلسلة تضمن أن ما كتب لم يتغير، ولا تضمن أن ما كتب صحيح. فإذا سجل مركز الصيانة إصلاحاً لم يحدث فالسلسلة سوف تحفظ الكذبة للأبد بكل أمانة، ولهذا السبب يسمي الناس مشكلة إدخال الواقع إلى السلسلة مشكلة الأوراكل Oracle Problem. لاحظها عندما يقول أحد «البيانات على البلوكتشين إذن هي موثوقة».
- **اتحاد من عضو واحد**: شبكة «خاصة» تشغل كل عقدها شركة واحدة، فهي قاعدة بيانات منسوخة أبطأ، لأن الشركة تستطيع أن تعيد بناء السلسلة متى شاءت. لاحظها بسؤال واحد: «من يملك السيرفرات التي تعمل عليها العقد؟».
- **نسيان التصحيح**: الأخطاء البشرية في الإدخال تحدث كل يوم، وفي قاعدة البيانات تصلحها بتعديل وسجل تدقيق، وفي السلسلة تحتاج معاملة تصحيح جديدة يفهمها كل من يقرأ، فصمم ذلك من اليوم الأول.
- **هاش البيانات الشخصية دون سر**: كما رأينا في التجربة، رقم الجوال يعود من هاشه في أقل من ثانية.
- **حساب التكلفة بسعر اليوم**: الغاز يدفع بعملة سعرها يتغير، فالرسوم التي تبدو صغيرة اليوم قد تتضاعف في أسبوع مزدحم، لذلك ضع الميزانية بوحدات الغاز وحدودها، وليس بالريال.
- **تجاهل تكلفة المفاتيح**: كل كاتب يحتاج مفتاحاً خاصاً يحميه ويدير تدويره، ومفتاح مسرب في شبكة يعني كتابات باسمك لا تستطيع حذفها.

## ورقة القرار: من الأرخص إلى الأغلى

الصورة التالية تبين المخارج الأربعة للاختبار، مرتبة من الأرخص إلى الأغلى:

![أربعة مخارج مرتبة: قاعدة بيانات عادية يكتب فيها تطبيقك وتضمنها الصلاحيات والنسخ الاحتياطي وسجل التدقيق والحذف فيها ممكن، ثم سجل بسلسلة هاش ونقاط تحقق موقعة عند الشركاء يظهر أي تعديل والأداء قريب من قاعدة البيانات، ثم شبكة مصرح بها لأعضاء معروفين يشغل كل منهم عقدته والحذف فيها صعب، ثم شبكة عامة لأي شخص يدفع الرسوم والبيانات علنية للأبد، وتحتها شريط يتدرج من أرخص وأسرع إلى ضمانات أكثر بين أطراف لا تثق ببعضها](https://arabroot.io/content/images/2026/10/need-blockchain-test-06-options.webp)

اختر أرخص مخرج يحقق الضمان الذي يحتاجه مشروعك فعلاً

والجدول التالي هو الورقة التي تملؤها مع فريقك، وفيه إجابات منصة الضمان كمثال:

| السؤال                  | كيف تتحقق من الإجابة                          | إجابة منصة الضمان                     | النتيجة                                       |
| ----------------------- | --------------------------------------------- | ------------------------------------- | --------------------------------------------- |
| 1\. عدة كتاب مستقلين؟   | هل يكتب كل طرف بمفتاحه وعقدته، أم عبر واجهتك؟ | اليوم عبر واجهتنا                     | كاتب واحد، ولكن الموزع يريد ضماناً، فنكمل     |
| 2\. جهة يقبلها الجميع؟  | اسأل الشركاء مباشرة، واقرأ العقود             | شركتنا محايدة ولا تبيع أجهزة          | نعم بشرط ضمان إضافي للموزع                    |
| 3\. يكفي إظهار التعديل؟ | هل يمكن حل الخلاف بالعقود بعد اكتشافه؟        | نعم، الخلاف على ضمان جهاز يحل تجارياً | سجل بسلسلة هاش ونقاط تحقق يومية موقعة         |
| 4\. بيانات شخصية؟       | هل فيها اسم أو جوال أو عنوان أو هوية؟         | نعم، بيانات العميل                    | في قاعدة البيانات فقط، قابلة للتصحيح والإتلاف |
| 5\. تحقق علني دون إذن؟  | هل يحتاج غير المشاركين أن يتحققوا بأنفسهم؟    | لا                                    | لم نصل إليه                                   |

وبهذا الشكل يكون رد الأسبوع للمدير التنفيذي جملة واحدة: لا نحتاج بلوكتشين الآن، وسوف نعطي الموزع ضماناً أقوى مما طلب بسلسلة هاش ونقطة تحقق موقعة يحفظها عنده كل يوم، بتكلفة أيام عمل قليلة بدلاً من شبكة كاملة، وإذا تغيرت الإجابة عن السؤال الثاني يوماً ما، كأن ينضم منافس لا يقبل أن نشغل السجل، نعيد الاختبار.

## قائمة تحقق قبل أي قرار

- اكتب المتطلب بلغة العمل وليس بلغة التقنية: «لا يغير أحد الشهادات دون أن نعرف» وليس «نريد بلوكتشين».
- عد الكتاب المستقلين فعلاً، أي من يكتب بمفتاحه وعقدته، وليس عدد المستخدمين.
- اسأل الشركاء بالاسم عن الجهة التي يقبلون أن تشغل السجل، واكتب إجاباتهم.
- جرب سجل سلسلة الهاش مع نقاط التحقق الموقعة قبل أي شبكة، فهو أيام عمل وليس أشهراً.
- أخرج كل بيانات شخصية من أي تصميم سلسلة، ولا تعتمد على الهاش وحده لإخفائها.
- إذا وصلت إلى شبكة مصرح بها، فتأكد أن كل عضو سوف يشغل عقدته بنفسه، واكتب الحوكمة: من يضيف عضواً، ومن يقرر الترقيات، وماذا يحدث عند خلاف.
- قدر التكلفة بوحدات الغاز أو بعدد العقد والسيرفرات، وليس بسعر العملة اليوم.
- راجع المستشار القانوني في البيانات الشخصية وفي أي أصل رقمي قابل للتحويل قبل كتابة الكود.

## إزالة التجربة

```bash
docker rm -f -v lab-need-pg lab-need-anvil
docker image rm postgres:18.6-alpine ghcr.io/foundry-rs/foundry:v1.8.6
```

## تدريب عملي

1. عدل الصف 2 بدلاً من الصف 4، ثم اكتب استعلاماً يعيد حساب هاش كل الصفوف من الصف 2 حتى الآخر بالترتيب، وتأكد أن التحقق الداخلي يمر وأن نقطة التحقق تكشف التعديل.
2. أضف إلى `checkpoint.py` أمراً ثالثاً يتحقق من أن الصف الذي يخص شريكاً معيناً جزء من السلسلة، بإعطائه الصف وهاشات الصفوف بعده حتى نقطة التحقق.
3. غير `phonehash.py` ليستخدم HMAC ثم حاول التخمين بنفس الحلقة، وفسر لماذا لا تجد شيئاً.

## الخلاصة

وصلنا لنهاية الموضوع، وأهم ما فيه:

- البلوكتشين يبيعك ثلاثة ضمانات: لا مشغل يغير الماضي وحده، ولا مشغل يرفض معاملة صحيحة وحده، وتحقق مستقل عند كل طرف، وثمنها ثابت في الأداء والخصوصية والحذف والمفاتيح والحوكمة.
- السؤال الأول عن الكتاب المستقلين فعلاً، والثاني عن جهة يقبلها الجميع، وأغلب المشاريع تنتهي عندهما بقاعدة بيانات.
- السؤال الثالث هو البديل الأقوى: سلسلة هاش في PostgreSQL مع نقاط تحقق موقعة عند الشركاء كشفت في التجربة إعادة الكتابة الكاملة التي لم يكشفها التحقق الداخلي.
- ما يدخل السلسلة لا يخرج منها: الرقم «المحذوف» بقي في الحالة القديمة وفي بيانات المعاملة، وهاش رقم الجوال عاد إلى الرقم في أقل من نصف ثانية.
- تسجيل حدث واحد في العقد كلف 48,159 غاز، وكل كتابة في الشبكة معاملة مستقلة تنتظر كتلة وتحفظها كل عقدة، أما الجدول فكتب عشرة آلاف حدث في ثوان على سيرفر واحد.
- TradeLens وCHESS عملت فيهما التقنية، وتعثرا في أسئلة من يشارك ومن يشغل وكم يكلف.

[![](https://arabroot.io/content/images/2026/10/blockchain-basics-cover-cover.webp)دليلكيف يعمل البلوكتشين Blockchain ومتى لا تحتاجهما المشكلة التي يحلها البلوكتشين أصلاً وكيف يعمل من الداخل، ومتى تكون قاعدة البيانات العادية هي الحل الأصح.](https://arabroot.io/articles/%D8%A7%D9%84%D8%A8%D9%84%D9%88%D9%83%D8%AA%D8%B4%D9%8A%D9%86-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-%D9%83%D9%8A%D9%81-%D9%8A%D8%B9%D9%85%D9%84-%D9%88%D9%85%D8%AA%D9%89-%D9%84%D8%A7-%D8%AA%D8%AD%D8%AA%D8%A7%D8%AC%D9%87/)[![](https://arabroot.io/content/images/2026/10/consensus-cover-cover.webp)دليلكيف تتفق شبكة البلوكتشين؟ إثبات العمل وإثبات الحصةكيف تتفق آلاف العقد التي لا يثق بعضها ببعض على سجل واحد، ولماذا يكلف الغش كهرباء في شبكة ومالاً محجوزاً في أخرى.](https://arabroot.io/articles/%D8%A7%D9%84%D8%A7%D8%AC%D9%85%D8%A7%D8%B9-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D9%84%D9%88%D9%83%D8%AA%D8%B4%D9%8A%D9%86-%D8%A7%D8%AB%D8%A8%D8%A7%D8%AA-%D8%A7%D9%84%D8%B9%D9%85%D9%84-%D9%88%D8%A7%D8%AB%D8%A8%D8%A7%D8%AA-%D8%A7%D9%84%D8%AD%D8%B5%D8%A9/)[![](https://arabroot.io/content/images/2026/10/audit-trail-cover-cover.webp)دليلAudit Trail: كيف تبني سجل تدقيق لا يقبل العبثكيف تصمم سجلاً يجيب عن سؤال من غير هذه الصلاحية ومتى، وتحميه من الحذف والتعديل بعد كتابته.](https://arabroot.io/articles/%D8%B3%D8%AC%D9%84-%D8%A7%D9%84%D8%AA%D8%AF%D9%82%D9%8A%D9%82-audit-trail-%D9%85%D9%86-%D9%81%D8%B9%D9%84-%D9%85%D8%A7%D8%B0%D8%A7-%D9%88%D9%85%D8%AA%D9%89/)[![](https://arabroot.io/content/images/2026/10/crypto-history-cover-cover.webp)دليلتاريخ العملات الرقمية: من Cypherpunks إلى Bitcoinكيف حاول المهندسون صنع نقد رقمي أربعين سنة، ولماذا تعثرت المحاولات قبل Bitcoin، وما الذي جمعه Bitcoin منها.](https://arabroot.io/articles/%D8%AA%D8%A7%D8%B1%D9%8A%D8%AE-%D8%A7%D9%84%D8%B9%D9%85%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%B1%D9%82%D9%85%D9%8A%D8%A9-%D9%85%D9%86-cypherpunks-%D8%A7%D9%84%D9%89-bitcoin/)[![](https://arabroot.io/content/images/2026/10/blockchain-cryptography-cover-cover.webp)دليلالتشفير في البلوكتشين: الهاش والمنحنيات والتوقيعاتكيف تصنع المفاتيح والعناوين والتوقيعات في Bitcoin وEthereum، ولماذا يكشف رقم مكرر واحد في التوقيع المفتاح الخاص.](https://arabroot.io/articles/%D8%A7%D9%84%D8%AA%D8%B4%D9%81%D9%8A%D8%B1-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D9%84%D9%88%D9%83%D8%AA%D8%B4%D9%8A%D9%86-%D8%A7%D9%84%D9%87%D8%A7%D8%B4-%D9%88%D8%A7%D9%84%D9%85%D9%86%D8%AD%D9%86%D9%8A%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%AA%D9%88%D9%82%D9%8A%D8%B9%D8%A7%D8%AA/)[![](https://arabroot.io/content/images/2026/10/enterprise-blockchain-cover-cover.webp)دليلشبكة بلوكتشين خاصة للمؤسسات: Besu أم Fabric؟كيف تبني شبكة خاصة من أربع شركات بإجماع QBFT، وماذا يحدث عندما يتوقف أعضاؤها، ومتى تختار Fabric أو قاعدة بيانات.](https://arabroot.io/articles/%D8%B4%D8%A8%D9%83%D8%A9-%D8%A8%D9%84%D9%88%D9%83%D8%AA%D8%B4%D9%8A%D9%86-%D8%AE%D8%A7%D8%B5%D8%A9-%D9%84%D9%84%D9%85%D8%A4%D8%B3%D8%B3%D8%A7%D8%AA-besu-%D8%A7%D9%85-fabric/)

## سجل التحديثات

- أكتوبر 2026: كتابة المقال، واختبار التجارب على Docker Engine 29.8.0 مع PostgreSQL 18.6 وPython 3.13.16 ومكتبة cryptography 46.0.3، وFoundry v1.8.6 مع Solc 0.8.30 وforge-std v1.17.0.