تخطي إلى المحتوى الرئيسي

⁦مقدمة مطور ⁦Python⁩ إلى إيثيريوم، الجزء الأول⁩

python
web3.py
مبتدئ
مارك غارو
8 سبتمبر 2020
11 دقيقة للقراءة

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

المتطلبات الأساسية (المرنة)

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

الافتراضات:

  • يمكنك التعامل مع الوحدة الطرفية (terminal)،
  • لقد كتبت بضعة أسطر من كود Python،
  • تم تثبيت Python الإصدار 3.6 أو أحدث على جهازك (يُنصح بشدة باستخدام بيئة افتراضية (opens in a new tab))، و
  • لقد استخدمت pip، وهو مثبت حزم Python. مرة أخرى، إذا كان أي من هذه الافتراضات غير صحيح، أو كنت لا تخطط لإعادة إنتاج الكود في هذه المقالة، فمن المحتمل أنك لا تزال قادرًا على المتابعة بشكل جيد.

سلاسل الكتل، باختصار

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

{
   "number": 1234567,
   "hash": "0xabc123...",
   "parentHash": "0xdef456...",
   ...,
   "transactions": [...]
}

تحتوي كل كتلة على إشارة إلى الكتلة التي سبقتها؛ parentHash هو ببساطة تجزئة الكتلة السابقة.

ملاحظة: يستخدم إيثيريوم بانتظام دوال التجزئة لإنتاج قيم ذات حجم ثابت ("تجزئات"). تلعب التجزئات دورًا مهمًا في إيثيريوم، ولكن يمكنك التفكير فيها بأمان كمعرفات فريدة في الوقت الحالي.

A diagram depicting a blockchain including the data inside  each block

سلسلة الكتل هي في الأساس قائمة مرتبطة؛ كل كتلة لها إشارة إلى الكتلة السابقة.

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

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

نموذج جديد

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

من المرجح أن يلجأ مطورو Python الذين يرغبون في التفاعل مع إيثيريوم إلى Web3.py (opens in a new tab). Web3.py هي مكتبة تبسط بشكل كبير طريقة اتصالك بعقدة إيثيريوم، ثم إرسال واستقبال البيانات منها.

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

يمكن تكوين عملاء إيثيريوم ليكونوا قابلين للوصول عن طريق IPC (opens in a new tab) أو HTTP أو Websockets، لذلك ستحتاج Web3.py إلى عكس هذا التكوين. تشير Web3.py إلى خيارات الاتصال هذه باسم المزودين (providers). ستحتاج إلى اختيار أحد المزودين الثلاثة لربط مثيل Web3.py بعقدتك.

A diagram showing how web3.py uses IPC to connect your application to an Ethereum node

قم بتكوين عقدة إيثيريوم وWeb3.py للتواصل عبر نفس البروتوكول، على سبيل المثال، IPC في هذا المخطط.

بمجرد تكوين Web3.py بشكل صحيح، يمكنك البدء في التفاعل مع سلسلة الكتل. إليك بعض الأمثلة على استخدام Web3.py كمعاينة لما سيأتي:

# قراءة بيانات الكتلة:
w3.eth.get_block('latest')

# إرسال معاملة:
w3.eth.send_transaction({'from': ..., 'to': ..., 'value': ...})

التثبيت

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

ملاحظة: في الأمثلة أدناه، الأوامر التي تبدأ بـ $ مخصصة للتشغيل في الوحدة الطرفية. (لا تكتب $، فهو يشير فقط إلى بداية السطر.)

أولاً، قم بتثبيت IPython (opens in a new tab) للحصول على بيئة سهلة الاستخدام للاستكشاف فيها. يوفر IPython إكمال علامة التبويب (tab completion)، من بين ميزات أخرى، مما يسهل كثيرًا رؤية ما هو ممكن داخل Web3.py.

pip install ipython

يتم نشر Web3.py تحت اسم web3. قم بتثبيته كالتالي:

pip install web3

شيء آخر – سنقوم بمحاكاة سلسلة الكتل لاحقًا، مما يتطلب بعض التبعيات الإضافية. يمكنك تثبيتها عبر:

pip install 'web3[tester]'

أنت جاهز تمامًا للبدء!

ملاحظة: تعمل حزمة web3[tester] حتى إصدار Python 3.10.xx

تشغيل بيئة اختبار (sandbox)

افتح بيئة Python جديدة عن طريق تشغيل ipython في الوحدة الطرفية الخاصة بك. هذا مشابه لتشغيل python، ولكنه يأتي مع المزيد من الميزات والإضافات.

ipython

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

In [1]:

أنت تنظر إلى صدفة Python تفاعلية الآن. في الأساس، إنها بيئة اختبار للعب فيها. إذا وصلت إلى هذا الحد، فقد حان الوقت لاستيراد Web3.py:

In [1]: from web3 import Web3

تقديم وحدة Web3

إلى جانب كونها بوابة إلى إيثيريوم، تقدم وحدة Web3 (opens in a new tab) بعض دوال المساعدة المريحة. دعنا نستكشف بعضها.

في تطبيق إيثيريوم، ستحتاج عادةً إلى تحويل فئات العملات. توفر وحدة Web3 طريقتين مساعدتين لهذا الغرض فقط: from_wei (opens in a new tab) وto_wei (opens in a new tab).

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

يتم استخدام نمط مشابه عند التعامل مع المعاملات بـ إيثر. ومع ذلك، بدلاً من نقطتين عشريتين، يحتوي إيثر على 18! تسمى أصغر فئة من إيثر Wei، لذلك هذه هي القيمة المحددة عند إرسال المعاملات.

1 ether = 1000000000000000000 wei1 wei = 0.000000000000000001 ether

حاول تحويل بعض القيم من وإلى Wei. لاحظ أن هناك أسماء للعديد من الفئات (opens in a new tab) بين إيثر وWei. من أشهرها Gwei، حيث يتم تمثيل رسوم المعاملة بها غالبًا.

In [2]: Web3.to_wei(1, 'ether')
Out[2]: 1000000000000000000

In [3]: Web3.from_wei(500000000, 'gwei')
Out[3]: Decimal('0.5')

تتضمن طرق الأدوات المساعدة الأخرى في وحدة Web3 محولات تنسيق البيانات (مثل toHex (opens in a new tab))، ومساعدات العناوين (مثل isAddress (opens in a new tab))، ودوال التجزئة (مثل keccak (opens in a new tab)). سيتم تغطية العديد من هذه لاحقًا في السلسلة. لعرض جميع الطرق والخصائص المتاحة، استخدم الإكمال التلقائي لـ IPython عن طريق كتابة Web3. والضغط على مفتاح الجدولة (tab) مرتين بعد النقطة.

التحدث إلى السلسلة

طرق المساعدة المريحة رائعة، لكن دعنا ننتقل إلى سلسلة الكتل. الخطوة التالية هي تكوين Web3.py للتواصل مع عقدة إيثيريوم. هنا لدينا خيار استخدام مزودي IPC أو HTTP أو Websocket.

لن نسلك هذا المسار، ولكن قد يبدو مثال سير العمل الكامل باستخدام مزود HTTP كالتالي:

  • قم بتنزيل عقدة إيثيريوم، على سبيل المثال، جو إيثريوم (geth) (opens in a new tab).
  • ابدأ تشغيل Geth في نافذة طرفية واحدة وانتظر حتى تتم المزامنة مع الشبكة. منفذ HTTP الافتراضي هو 8545، ولكنه قابل للتكوين.
  • أخبر Web3.py بالاتصال بالعقدة عبر HTTP، على localhost:8545. w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))
  • استخدم مثيل w3 للتفاعل مع العقدة.

في حين أن هذه إحدى الطرق "الحقيقية" للقيام بذلك، فإن عملية المزامنة تستغرق ساعات وهي غير ضرورية إذا كنت تريد فقط بيئة تطوير. تكشف Web3.py عن مزود رابع لهذا الغرض، وهو EthereumTesterProvider. يرتبط مزود الاختبار هذا بعقدة إيثيريوم محاكاة بأذونات مريحة وعملة مزيفة للعب بها.

A diagram showing the EthereumTesterProvider linking your web3.py application to a simulated Ethereum node

يتصل EthereumTesterProvider بعقدة محاكاة وهو مفيد لبيئات التطوير السريعة.

تسمى تلك العقدة المحاكاة eth-tester (opens in a new tab) وقمنا بتثبيتها كجزء من أمر pip install web3[tester]. تكوين Web3.py لاستخدام مزود الاختبار هذا بسيط كالتالي:

In [4]: w3 = Web3(Web3.EthereumTesterProvider())

الآن أنت مستعد لتصفح السلسلة! هذا ليس شيئًا يقوله الناس. لقد اختلقت ذلك للتو. لنأخذ جولة سريعة.

الجولة السريعة

أولاً وقبل كل شيء، فحص السلامة:

In [5]: w3.is_connected()
Out[5]: True

نظرًا لأننا نستخدم مزود الاختبار، فهذا ليس اختبارًا ذا قيمة كبيرة، ولكن إذا فشل، فمن المحتمل أنك كتبت شيئًا خاطئًا عند إنشاء متغير w3. تحقق مرة أخرى من أنك قمت بتضمين الأقواس الداخلية، أي Web3.EthereumTesterProvider().

محطة الجولة رقم 1: الحسابات

للراحة، قام مزود الاختبار بإنشاء بعض الحسابات وتحميلها مسبقًا بإيثر اختباري.

أولاً، لنرى قائمة بتلك الحسابات:

In [6]: w3.eth.accounts
Out[6]: ['0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
 '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
 '0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69', ...]

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

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

In [7]: w3.eth.get_balance(w3.eth.accounts[0])
Out[7]: 1000000000000000000000000

هذا الكثير من الأصفار! قبل أن تذهب ضاحكًا طوال الطريق إلى البنك المزيف، تذكر هذا الدرس حول فئات العملات من قبل. يتم تمثيل قيم إيثر بأصغر فئة، Wei. قم بتحويل ذلك إلى إيثر:

In [8]: w3.from_wei(1000000000000000000000000, 'ether')
Out[8]: Decimal('1000000')

مليون إيثر اختباري — لا يزال ليس سيئًا للغاية.

محطة الجولة رقم 2: بيانات الكتلة

لنلقِ نظرة خاطفة على حالة سلسلة الكتل المحاكاة هذه:

In [9]: w3.eth.get_block('latest')
Out[9]: AttributeDict({
   'number': 0,
   'hash': HexBytes('0x9469878...'),
   'parentHash': HexBytes('0x0000000...'),
   ...
   'transactions': []
})

يتم إرجاع الكثير من المعلومات حول الكتلة، ولكن هناك بعض الأشياء التي يجب الإشارة إليها هنا:

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

محطة الجولة رقم 3: المعاملات

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

In [10]: tx_hash = w3.eth.send_transaction({
   'from': w3.eth.accounts[0],
   'to': w3.eth.accounts[1],
   'value': w3.to_wei(3, 'ether'),
   'gas': 21000
})

هذه هي النقطة التي تنتظر فيها عادةً لعدة ثوانٍ حتى يتم تضمين معاملتك في كتلة جديدة. تسير العملية الكاملة كالتالي:

  1. أرسل معاملة واحتفظ بتجزئة المعاملة. حتى يتم إنشاء الكتلة التي تحتوي على المعاملة وبثها، تكون المعاملة "معلقة". tx_hash = w3.eth.send_transaction({ … })
  2. انتظر حتى يتم تضمين المعاملة في كتلة: w3.eth.wait_for_transaction_receipt(tx_hash)
  3. استمر في منطق التطبيق. لعرض المعاملة الناجحة: w3.eth.get_transaction(tx_hash)

ستضيف بيئتنا المحاكاة المعاملة في كتلة جديدة على الفور، حتى نتمكن من عرض المعاملة فورًا:

سترى بعض التفاصيل المألوفة هنا: يجب أن تتطابق حقول from وto وvalue مع مدخلات استدعاء send_transaction الخاص بنا. الجزء الآخر المطمئن هو أن هذه المعاملة تم تضمينها كأول معاملة ('transactionIndex': 0) داخل الكتلة رقم 1.

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

In [12]: w3.eth.get_balance(w3.eth.accounts[0])
Out[12]: 999996999979000000000000

In [13]: w3.eth.get_balance(w3.eth.accounts[1])
Out[13]: 1000003000000000000000000

الأخير يبدو جيدًا! ارتفع الرصيد من 1,000,000 إلى 1,000,003 إيثر. ولكن ماذا حدث للحساب الأول؟ يبدو أنه فقد أكثر بقليل من ثلاثة إيثر. للأسف، لا شيء في الحياة مجاني، واستخدام شبكة إيثيريوم العامة يتطلب منك تعويض أقرانك عن دورهم الداعم. تم خصم رسوم معاملة صغيرة من الحساب الذي أرسل المعاملة - هذه الرسوم هي كمية الغاز المحترق (21,000 وحدة غاز لتحويل ETH) مضروبة في الرسم الأساسي الذي يختلف وفقًا لنشاط الشبكة بالإضافة إلى إكرامية تذهب إلى المُدَقِّق الذي يضمن المعاملة في كتلة.

المزيد عن الغاز

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

وخذ نفسًا

لقد كنا نفعل هذا لفترة من الوقت، لذا يبدو هذا مكانًا جيدًا كأي مكان آخر لأخذ استراحة. تستمر التفاصيل العميقة، وسنواصل الاستكشاف في الجزء الثاني من هذه السلسلة. بعض المفاهيم القادمة: الاتصال بعقدة حقيقية، والعقود الذكية، والرموز المميزة. هل لديك أسئلة متابعة؟ أعلمني! ستؤثر ملاحظاتك على وجهتنا من هنا. نرحب بالطلبات عبر تويتر (opens in a new tab).