التواصل برمجيا مع سلسلة الكتل باستخدام بروتوكول Electrum


التواصل مع سلسلة الكتل برمجيا باستخدام بروتوكول الكترم كاش (Electrum Cash Protocol)

مقدمة

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

في هذ المقال سأضع إن شاء الله أمثلة عن استخدام وظائف برتوكول الكترم كاش

استعلام خادم الكتروم

ساستخدم في مثالي بايثون لكن يمكنك تغييره لأي لغة، دعنا نجرب الاستعلام باستخدام طلب سوكىـت بسيط:

import socket
from time import sleep

hostname = 'chipnet.c3-soft.com'

port = 64001

data = """{"method":"server.version","params":[],"id":194}"""


with socket.create_connection((hostname, port)) as sock:
    sock.send(data.encode('utf-8')+b'\n')
    sleep(0.5)
    print(sock.recv(1024))

يفترض أن ترى شيئاً مثل هذا بعد تشغيل النص البرمجي:

b'{"id":194,"jsonrpc":"2.0","result":["Fulcrum 1.9.0","1.4"]}\r\n'

Query with SSL

دعنا نجرب الآن الاستعلام باستخدام SSL:

import socket
import ssl
from time import sleep

hostname = 'chipnet.c3-soft.com'
port = 64002

context = ssl.create_default_context()

data = """{"method":"server.version","params":[],"id":194}"""

with socket.create_connection((hostname, port)) as sock:
    with context.wrap_socket(sock, server_hostname=hostname) as ssock:
        ssock.send(data.encode('utf-8')+b'\n')
        sleep(0.5)
        response_byte = ssock.recv(1024)
        response = response_byte.decode()
        print(response)

لاحظ أننا غيرنا المنفذ من 64001 إلى 64002. يمكن لخوادم الكترم أن تعمل على منافذ متعددة بحسب الشبكة أو اختيار المشغّل. كذلك حولت المخرجات من بايت إلى جيسون باستخدام decode().

Resutls:

{"id":194,"jsonrpc":"2.0","result":["Fulcrum 1.9.0","1.4"]}

وظائف البروتوكول

يمكنك القراءة عن كل الوظائف الموجودة في البروتوكول هنا:

أمثلة استعلامات

الآن، بالنسبة للنص البرمجية بلغة بايثون الذي أستخدمه فإنه سيبقى نفسه ويكفي تغيير جزء data الذي هو لُبّ الاستعلام.

طلب رصيد BCH

data = """{"method":"blockchain.address.get_balance","params":["bchtest:zry77fz5ph8supxplr57h6lfx0jlw5kxjc39ctq8zc"],"id":194}"""

سيعطيني إن شغلته بهذه الطريقة $python3 /tmp/test.py |jq التالي:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": {
    "confirmed": 10108742,
    "unconfirmed": 0
  }
}

أعطاني هنا رصيد العنوان الذي وضعته من عملة BCH على شبكة الاختبار دون وضع الرصيد المتعلق بالتوكنات. سَتُحدّث شبكة بيتكوين كاش في 15 مايو سنة 2023 إن شاء الله لوضع دعم المصكوكات (toknes) لذا ربما يكون من المفيد أن نتعلم عنهم. يمكنك تشغيل الاستعلام الآتي:

data = """{"method":"blockchain.address.get_balance","params":["bchtest:zry77fz5ph8supxplr57h6lfx0jlw5kxjc39ctq8zc", "include_tokens"],"id":194}"""

لاحظ اضافة include_tokens كعنصر للطلب. يمكنك كذلك تعديل للحصول فقط على الرصيد المتعلق بالمصكوكات tokens_only.وسترى النتيجة مثلا:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": {
    "confirmed": 1000,
    "unconfirmed": 0
  }
}

تاريخ العنوان

data = """{"method":"blockchain.address.get_history","params":["bchtest:zry77fz5ph8supxplr57h6lfx0jlw5kxjc39ctq8zc"],"id":194}"""

سيعيد لك قائمة بالمعاملات المتعلقة بالعنوان الذي استعلمت عنه:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": [
    {
      "height": 130619,
      "tx_hash": "d3987427832a14a5a9998587cf57693fdebfeee5254a28d927448bf394228eac"
    },
    {
      "height": 130620,
      "tx_hash": "fd16466978638a0b721df9ba728f2b18e219d84a035a19548ce8056ad16d1adb"
    }
  ]
}

استعلام عن المعاملات في حوض الذاكرة Mempool المتعلقة بعنوان

حوض الذاكرة هو مكان تجمّع المعاملات قبل تأكيدها، لنجرب الطلب الآتي:

data = """{"method":"blockchain.address.get_mempool","params":["bchtest:zry77fz5ph8supxplr57h6lfx0jlw5kxjc39ctq8zc"],"id":194}"""

النتيجة:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": [
    {
      "fee": 219,
      "height": -1,
      "tx_hash": "10c17fa8fa096855f0b63f8643e3cb6788d97e9f5f36043aa22cf8b443ed2222"
    }
  ]
}

في هذا المثال هناك معاملة واحدة غير مؤكدة تنتظر، لكنه لن يرجع شيئا إن لم يكن هناك معاملات تنتظر التأكيد في حوض الذاكرة Mempool.

Get Address Script Hash

لم يتوفر عندي الوقت للبحث أكثر في هذه لكن الطلب يعمل :slight_smile:

data = """{"method":"blockchain.address.get_scripthash","params":["bchtest:zry77fz5ph8supxplr57h6lfx0jlw5kxjc39ctq8zc"],"id":194}"""

النتيجة:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": "e135101e310f33833cd0c6982e5d678ca0ff41b110e0bc0168c2c145245af8fb"
}

الاستعلام على UTXOs التي في عنوان

إن UTXO هي الفكة في شبكة بيتكوين، رصيدك هو مجموع قيمة هذه الفكة. فإن كان لديك 0.25 و 0.10 فلكل منها كيان قائم بنفسه مخزّن على عنوانك ورصيدك هو مجموعها.

data = """{"method":"blockchain.address.listunspent","params":["bchtest:zry77fz5ph8supxplr57h6lfx0jlw5kxjc39ctq8zc"],"id":194}"""

النتيجة:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": [
    {
      "height": 130620,
      "tx_hash": "fd16466978638a0b721df9ba728f2b18e219d84a035a19548ce8056ad16d1adb",
      "tx_pos": 1,
      "value": 10098743
    },
    {
      "height": 130702,
      "tx_hash": "10c17fa8fa096855f0b63f8643e3cb6788d97e9f5f36043aa22cf8b443ed2222",
      "tx_pos": 0,
      "value": 9999
    }
  ]
}

نلاحظ هنا أن لدينا إثنين من الفكة أو إثنان UTXO على العنوان الذي استعلمنا عنه.

الاستعلام على UTXOs في عنوان مع بيانات المصكوكات

وظيفة blockchain.address.listunspent تقبل متغيرات الاستعلامات المتعلقة بالمصكوكات. نستخدم هنا include_tokens.

data = """{"method":"blockchain.address.listunspent","params":["bchtest:zry77fz5ph8supxplr57h6lfx0jlw5kxjc39ctq8zc", "include_tokens"],"id":194}"""

النتيجة بعد إضافة استعلام المصكوكات:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": [
    {
      "height": 130620,
      "token_data": {
        "amount": "1555",
        "category": "d3987427832a14a5a9998587cf57693fdebfeee5254a28d927448bf394228eac"
      },
      "tx_hash": "fd16466978638a0b721df9ba728f2b18e219d84a035a19548ce8056ad16d1adb",
      "tx_pos": 0,
      "value": 1000
    },
    {
      "height": 130620,
      "tx_hash": "fd16466978638a0b721df9ba728f2b18e219d84a035a19548ce8056ad16d1adb",
      "tx_pos": 1,
      "value": 10098743
    },
    {
      "height": 130702,
      "tx_hash": "10c17fa8fa096855f0b63f8643e3cb6788d97e9f5f36043aa22cf8b443ed2222",
      "tx_pos": 0,
      "value": 9999
    }
  ]
}

نلاحظ وجود مصكوكات عددها 1555 ك UTXO منفصل عن UTXO الباقية التي رأيناها في الاستعلام السابق.

الاشتراك بعنوان بيتكوين كاش

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

الاستعلام عن ترويسة الكتلة Block Header

قد يكون هذا شيئا متقدما قليلا لكننا يمكننا تنفيذ الطلب وتعلم المزيد عنها لاحقا :slight_smile:

data = """{"method":"blockchain.block.header","params":["130713"],"id":194}"""

حيث 130713 هو رقم الكتلة

النتيجة:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": "00000020b50f525372a75dd5af367999f0967df7c8ac65770836a3b3f7febb7d0000000022fc3087af74b7b721ff5fd77b1f13c29bdc9fadf640aa1044ec4d9f90a5d20d0eb6c3637d90001d66721859"
}

الاستعلام عن مقطع من ترويسات الكتلة

سننفذه كما هو موجود في المستند الأصلي، أنصح من يريد تعلم أكثر عن تفاصيل هذه الأمور قراءة كتاب Mastering Bitcoin لكن هنا سنمر على هذه سريعا.

data = """{"method":"blockchain.block.headers","params":["130713", "3"],"id":194}"""

النتيجة:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": {
    "count": 3,
    "hex": "00000020b50f525372a75dd5af367999f0967df7c8ac65770836a3b3f7febb7d0000000022fc3087af74b7b721ff5fd77b1f13c29bdc9fadf640aa1044ec4d9f90a5d20d0eb6c3637d90001d66721859000000205ff85ddb0ea6bbf32969741740e296a1a9928e4a016183231d48942e000000004ef8322b25207002a2383049251b6eea14c4f141d1ad93b5eb57d8dbc82410b779b7c3636f88001d00c0702d00000020150af46c2931607ca5113d150480d1f5eb3c27c7f94ee8447541942000000000e7529f9e2ac9c482bdf80415a32f19de6bffb25f27814e9e66d3aee2d566b117d3b7c3635782001d05eadc83",
    "max": 2016
  }
}

تقدير العمولة

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

data = """{"method":"blockchain.estimatefee","params":["5"],"id":194}"""

النتيجة:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": 1e-05
}

الاستعلام عن رقم آخر كتلة وترويستها

لتعرف عن ماهي آخر كتلة عُدّنت وتحصل على ترويستها.

data = """{"method":"blockchain.headers.get_tip","params":[],"id":194}"""

النتيجة:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": {
    "height": 130715,
    "hex": "00000020150af46c2931607ca5113d150480d1f5eb3c27c7f94ee8447541942000000000e7529f9e2ac9c482bdf80415a32f19de6bffb25f27814e9e66d3aee2d566b117d3b7c3635782001d05eadc83"
  }
}

نشر معاملة

يستخدم هذا لنشر المعاملة إلى الشبكة. حيث تمكنك بعض المحافظ من تكوين معاملتك يدويا ثم يمكنك نشرها باستخدام هذا الاستعلام

data = """{"method":"blockchain.transaction.broadcast","params":["01000000012222ed43b4f82ca23a04365f9f7ed98867cbe343863fb6f0556809faa87fc110010000006441e034f331841fe54db54a5c5ebfcbab66ad8682fe285992130737ae7bf0a5603858511416eb6003aad3f5aa818c9400148d66f72b859eeb519718c2ecd8e2dd044121028aa60b3a3b4b590d5480fea4411e3e5ae6c959226064a336a11a7ae1a03154b5feffffff027d250000000000001976a914e9a1bdba9c8a6845b31f825c1444527006c93f9c88acdece9900000000001976a9143e8b21680884ce1d5a5c619fb69a971a676f1ffa88ac9cfe0100"],"id":194}"""

سيعيد لنا رقم المعاملة إذا نجح الإرسال:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": "882307117ca84c81b680ef944de1cdabbe4ddda147bdbf535943d771852df2b2"
}

أنشأت معاملة خامة raw transaction باستخدام محفظة Electron Cash. يمكنك فعل ذلك من لسان Send عبر اجراء الخطوات الاعتيادية وضغط معاينة Preview بدل إرسال، ثم يمكنك توقيع المعاملة Sign ونسخ بيانات المعاملة Copy لاستخدامه في هذا النص البرمجي دون الارسال مباشرة من المحفظة تلك.

كشف محاولات الدفع المزدوج

الدفع المزدوج هو محاولة لانفاق نفس المبلغ لجهتين مختلفتين ويستخدمها بعض المخادعين. وهذه الآلية تساعدك في كشفها إذا قدمت رمز المعاملة TX ID

data = """{"method":"blockchain.transaction.dsproof.get","params":["882307117ca84c81b680ef944de1cdabbe4ddda147bdbf535943d771852df2b2"],"id":194}"""

سيعيد Null إن لم يكن هناك محاولة لدفع مزودج مرتبطة بالمعاملة:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": null
}

إذا كُشفت محاولة لدفع مزدوج فسترى شيئا مثل هذا:

```json
{
  "dspid": "587d18bf8a64ede9c7450fdaeab27b9b3c46cfa8948f4c145f889601153c56b0",
  "txid": "5b59ce35093fbd13549cd6f203d4b5b01762d70e75b8e9733dfc463e0ff8cc13",
  "hex": "410c56078977120e828e4aacdd813a818d17c47d94183aa176d62c805d47697dddddf46c2ab68ee1e46a3e17aa7da548c38ec43416422d433b1782eb3298356df441",
  "outpoint": {
    "txid": "f6e2a16ba665d5402dad147fe35872961bc6961da62345a2171ee001cfcf7600",
    "vout": 0
  },
  "descendants": [
    "36fbb099e6de59d23477727e3199c65caae35ded957660f56fc681a6d81d5570",
    "5b59ce35093fbd13549cd6f203d4b5b01762d70e75b8e9733dfc463e0ff8cc13"
  ]
}

الاستعلام عن محاولات الدفع المزدوج في حوض الذاكرة

data = """{"method":"blockchain.transaction.dsproof.list","params":[],"id":194}"""

إذا وجد أي محاولات للدفع المزدوج في حوض الذاكرة Mempool سيرجع شيئا مثل هذا:

[
  "e67cc122f3c28a4243c3a1b14b38a9474c22ba928af9a194ca2b85426f0fd1bb",
  "077f0cc2439f2e48567c72eeeba5a447f8649c00c3d18ab6516eccfd4119726f",
  "ccc2f0d90b7067a83566024d4df842f0b6cb8180e18d642fcc85cae8acadbd58"
]

يمكن استخدام معرفات الدفع المزوج هذه للحصول على معلومات اكثر باستخدام وسيلة blockchain.transaction.dsproof.get.

على الحصول على المعاملة الخام من رمز المعاملة

data = """{"method":"blockchain.transaction.get","params":["882307117ca84c81b680ef944de1cdabbe4ddda147bdbf535943d771852df2b2"],"id":194}"""

النتيجة:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": "01000000012222ed43b4f82ca23a04365f9f7ed98867cbe343863fb6f0556809faa87fc110010000006441e034f331841fe54db54a5c5ebfcbab66ad8682fe285992130737ae7bf0a5603858511416eb6003aad3f5aa818c9400148d66f72b859eeb519718c2ecd8e2dd044121028aa60b3a3b4b590d5480fea4411e3e5ae6c959226064a336a11a7ae1a03154b5feffffff027d250000000000001976a914e9a1bdba9c8a6845b31f825c1444527006c93f9c88acdece9900000000001976a9143e8b21680884ce1d5a5c619fb69a971a676f1ffa88ac9cfe0100"
}

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

data = """{"method":"blockchain.transaction.get","params":["882307117ca84c81b680ef944de1cdabbe4ddda147bdbf535943d771852df2b2", true],"id":194}"""

لكن مع زيادة المخرجات قد تحتاج لرفع الحد من sock.recv(1024) إلى sock.recv(2048) في الكود البرمجي.

الاستعلام عن الكتلة التي فيها معاملة ما

data = """{"method":"blockchain.transaction.get_height","params":["882307117ca84c81b680ef944de1cdabbe4ddda147bdbf535943d771852df2b2"],"id":194}"""

النتيجة:


{
  "id": 194,
  "jsonrpc": "2.0",
  "result": 130717
}

حيث وجدت المعاملة في الكتلة رقم 130717.

الحصول على فرع Merkle Branch لمعاملة

هذا موضوع متقدم و Merkle Tree هي الشجرة التي تجعل المعاملة متسلسلة بحيث يصعب تغيير معاملة قديمة وتزويرها لأنها كلها مرتبطة. على كل لنجري الاستعلام:

data = """{"method":"blockchain.transaction.get_merkle","params":["882307117ca84c81b680ef944de1cdabbe4ddda147bdbf535943d771852df2b2"],"id":194}"""

يُرجع:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": {
    "block_height": 130717,
    "merkle": [
      "98c62086c368072827d813c98e249b2efca3ba0af9c158a158dc20660299e3f2"
    ],
    "pos": 1
  }
}

يمكنك أيضا إضافة رقم الكتلة التي تريد البحث فيها كما في هذا الاستعلام:

data = """{"method":"blockchain.transaction.get_merkle","params":["882307117ca84c81b680ef944de1cdabbe4ddda147bdbf535943d771852df2b2", "130715"],"id":194}"""

Result:

{
  "error": {
    "code": 1,
    "message": "No transaction matching the requested hash found at height 130715"
  },
  "id": 194,
  "jsonrpc": "2.0"
}

نعرف من الاستعلام السابق أن الكتلة هي 130717 لكني طلبت المعاملة في كتلة مختلفة 130715فظهر لي الخطأ.

جلب معاملة بحسب ترتيبها في الكتلة

لكل معاملة ترتيب معين في الكتلة، هذا الاستعلام يجلب المعاملة بحسب ترتيبها في الكتلة، لنطلب المعاملة صاحبة الترتيب 1 في كتلة رقم 130717:

data = """{"method":"blockchain.transaction.id_from_pos","params":["130717", "1"],"id":194}"""

النتيجة:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": "882307117ca84c81b680ef944de1cdabbe4ddda147bdbf535943d771852df2b2"
}

الحصول على UTXO باستخدام رمز المعاملة

قدّمنا رمز المعاملة وتسلسل UTXO المطلوب فيها:

data = """{"method":"blockchain.utxo.get_info","params":["882307117ca84c81b680ef944de1cdabbe4ddda147bdbf535943d771852df2b2", "1"],"id":194}"""

النتيجة:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": {
    "confirmed_height": 130717,
    "scripthash": "91595a8149d7d27b77506f4e1c6d3b8ffb9fbac1557ed71da77264486bc47caa",
    "value": 10079966
  }
}

الحصول على عنوان التبرع للخادم

مشغلوا خوادم Electrum يمكنهم اعداد هذا العنوان بحيث يتبرع المستخدمون، هنا نطلب معرفة عنوان محفظة التبرع الخاص بمشغل الخادم:

data = """{"method":"server.donation_address","params":[],"id":194}"""

يُرجع:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": "bchtest:qq9rw090p2eu9drv6ptztwx4ghpftwfa0gyqvlvx2q"
}

طلب خصائص الخادم

data = """{"method":"server.features","params":[],"id":194}"""

يُرجع:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": {
    "cashtokens": true,
    "dsproof": true,
    "genesis_hash": "000000001dd410c49a788668ce26751718cc797474d3152a5fc073dd44fd9f7b",
    "hash_function": "sha256",
    "hosts": {
      "chipnet.c3-soft.com": {
        "ssl_port": 64002,
        "tcp_port": 64001,
        "ws_port": 64003,
        "wss_port": 64004
      }
    },
    "protocol_max": "1.5",
    "protocol_min": "1.4",
    "pruning": null,
    "server_version": "Fulcrum 1.9.0"
  }
}

طرق الخادم Ping

data = """{"method":"server.ping","params":[],"id":194}"""

يُرجع:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": null
}

طلب إصدار الخادم

data = """{"method":"server.version","params":[],"id":194}"""

يُرجع:

{
  "id": 194,
  "jsonrpc": "2.0",
  "result": [
    "Fulcrum 1.9.0",
    "1.4"
  ]
}

Notes

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

هناك بعض المحافظ التي تتصل مباشر مع العقد ولا تعتمد على خادم الكترم. لكن من هذه الوسائل ميزاته وعيوبه.

مالتالي؟

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

بالنسبة للمفاهيم المتقدمة يمكن لمن يريد قراءة كتاب Mastering Bitcoin والاصدار الأول منه متوفر على الانترنت مجاناً.

إعجابَين (2)