Author

Topic: POS – Proof of Stake محاولة شرح خوارزمية دليل الحصة (Read 295 times)

member
Activity: 98
Merit: 117
Someday we will rise ...
شكرا جميعا.
بالحقيقة الموضوع بحاجة لمعرفة مسبقة ببعض المفاهيم و التقنيات لفهم هالنص أكتر, ومع الوقت رح انشر مواضيع مكملة متل الـHashو UTXO الخ الخ.


للمزيد من التفاصيل لتسهيل الفهم:



Long Bitcoin BTC. Short the Banks
legendary
Activity: 1610
Merit: 1131
بالفعل نحن بحاجة لترجمة المواضيع الهامة لنفهم اكثر طبيعة ونظام العملات الرقمية المشفرة التي نتعامل بها.
الحقيقية مثل هذه المواضيع لا يمكن استيعابها بالقراءة مرة واحدة يجب ان نعيد القراءة لأنها مفاهيم ومصطلحات تقنية يصعب على القارئ العادي ان يفهمها بسهولة.


صدق من قال بالقراءة تصبح عالما إحدى كتابات الراحل طه حسين، نعم صحيح لا يمكن تعلم أشياء جديدة بدون الإستعانة بالقراءة، فالقراءة توفر للمنتدي معلومات إضافية تمكنه من النشر و التفاعل بالشكل المطلوب لذالك أنصح الأغلبية من الأعضاء بقراءة مجموعة من المواضيع التقنية بخصوص التشفير حتى يستوعب أفكار كثيرة، فالموضوع الذي قام بطرحه أخونا قمت بقرائته عدة مرات و أعتبره مثالي حقا، و كما أني تأخرت في التعليق عليه في الحقيقة الموضوع يستحق الجدارة و أشكر من الصميم الأخ أسي و لدي نصيحة يجب عليك في المستقبل ذكر المصدر فالأمر ضروري لا غبار عليه.
jr. member
Activity: 51
Merit: 12
نشكر الاخ على  هذا الشرح و الخوارزمية  ال POSبدات تنتشر اكثر واضن  ايضا ان الاثيريوم سيقوم بنشرها اكثر مع التحديث المنتظر
member
Activity: 142
Merit: 70
موضوع بكل صراحة جميل , لم أستطع إكماله لذا سأعود له لاحقا. و الموضوع المشروح من الناحية التقنية تسهل الامر لفهم خوارزمية الدليل الذي شرحته
تحياتي
sr. member
Activity: 534
Merit: 295
بالفعل نحن بحاجة لترجمة المواضيع الهامة لنفهم اكثر طبيعة ونظام العملات الرقمية المشفرة التي نتعامل بها.
الحقيقية مثل هذه المواضيع لا يمكن استيعابها بالقراءة مرة واحدة يجب ان نعيد القراءة لأنها مفاهيم ومصطلحات تقنية يصعب على القارئ العادي ان يفهمها بسهولة.
hero member
Activity: 2338
Merit: 757
Top-tier crypto casino and sportsbook
رغم المجهود الجبار الذي بذله الأخ icy3 لنقل هذا الموضوع من لغته الأم، و رغم أهمية العناصر الواردة به، الا أنه من المستغرب أن الموضوع لم يلقى أي تفاعل يذكر و لا حتى نقاط جدارة للدعم !
وددت حقا قراءة المزيد من التعليقات عن 'مبدأ اثرات العمل' بما أنه يبدو من الصعب حقا استيعاب الموضوع استنادا الى نص مكتوب بالعربية خصوصا أن هذا يعتبر الأول من نوعه بالعربية الذي يشرح مفاهيم تقنية معقدة فعلا .
member
Activity: 98
Merit: 117
Someday we will rise ...
شكرا على المجهود الكبير في ترجمة الموضوع.
نحن بحاجة لمثل هذه المواضيع للتعرف على الاساسيات التي بنيت عليها العملات الرقمية.

ملاحظة: لتجنب حذف الموضوع، ارجو اضافة رابط الموضوع الاصلي: https://medium.com/@nDEXNetwork/pos-and-utxos-model-of-nexbit-coin-nbc-ndt-coin-9d3441261d49
شكرا عيون، و بقدر قدراتك التحليلية، بس يبدو أني تجاوزت عدد الكلمات المحدد فنقص من الموضوع جملتين:
Quote
-----------------------------------------------------------------------

المصدر: http://earlz.net/view/2017/07/27/1904/the-missing-explanation-of-proof-of-stake-version


Long Bitcoin BTC. Short the Banks

عكل حال قدرت ضيف المصدر للنص الأساسي.
legendary
Activity: 2744
Merit: 3096
Top Crypto Casino
شكرا على المجهود الكبير في ترجمة الموضوع.
نحن بحاجة لمثل هذه المواضيع للتعرف على الاساسيات التي بنيت عليها العملات الرقمية.

ملاحظة: لتجنب حذف الموضوع، ارجو اضافة رابط الموضوع الاصلي: https://medium.com/@nDEXNetwork/pos-and-utxos-model-of-nexbit-coin-nbc-ndt-coin-9d3441261d49
member
Activity: 98
Merit: 117
Someday we will rise ...
ضمن كل عملة الكترونية مشفرة يجب ان يوجد خوارزمية اتفاق، التي بدورها تبقي كامل الشبكة الموزعة متزامنة. عندما أتى الـ Bitcoin للوجود، قام بتعريف خوارزمية اتفاق دليل العمل Proof-Of-Work. يعمل POW بإنتاج هاش لقطعة من المعلومات (رأس الكتلة Block Header) مرارا وتكرارا حتى يتم إيجاد الهاش المناسب. بسبب طريقة عمل الـ One-way Hashing, فان أي تغيير طفيف ضمن البيانات يمكن أن ينتج هاش مختلف بشكل جذري. المشاركين في الشبكة يمكنهم ان يحددوا إذا كان دليل العمل صالح من خلال الحكم على الهاش المٌنتَج من أنه يحقق حالة معينة أو شرط معين، يسمى الصعوبة Difficulty. الصعوبة او صعوبة التعدين هو هدف متغير على الدوام، الذي على الهاش ان يساويه او يتجاوزه. كلما انتجت الشبكة بلوكات أكثر من اللازم، فان صعوبة التعدين تتغير بشكل آلي من قبل الشبكة بحيث يصبح تحقيق هدف صعوبة التعدين أعلى وأعلى. وهكذا تحتاج المزيد والمزيد من الطاقة الحسابية Computing Power لإيجاد الهاش الذي يحقق هدف صعوبة التعدين Difficulty Targetضمن الإطار الزمني المقدر بـ 10 دقائق.
تعريفات:
•   UTXO اختصار لـ Unspent Transaction Output, او خرج المعاملة الغير مصروف.
•   vin: ضمن معاملة يكون الـvin عبارة عن UTXO يتم صرفه كدخل للمعاملة input.
•   vout: ضمن معاملة يكون الـvout عبارة عن UTXO جديد يتم انشاءه كخرج للمعاملة output. الـ vouts هو فعليا جميع العملات المرسلة بعد تأكيد معاملة التحويل.
•   Hashing: هي عملية انشاء الـHash. بحيث تأخذ كمية عشوائية من البيانات كدخل، وتعطي كخرج عصارة محددة الحجم والذي بدوره من المستحيل عكسه (أي الرجوع من الخرج الى بيانات الدخل). بالإضافة، إذا قمت بتغيير أي شيء ببيانات الدخل، فان الخرج سيتغير بشكل جذري.
•   Hash: نتيجة تطبيق خوارزمية او عملية التهييش Hashing.
•   script: برنامج على البلوكتشين لتحديد كيفية صرف vout/UTXO.
•   pay-to-pubkeyhash script: النص البرمجي script الأكثر استخداما لإرسال المال ضمن الـBitcoin و عملات أُخرى. من أجل ارسال الأموال فان كل ما تحتاج معرفته هو هاش المفتاح العام للجهة المرسل اليها، ومن أجل إنفاق الأموال المستقبلة فكل ما تحتاجه هو توقيع رقمي من المفتاح العام المرسل اليه، والمفتاح العام نفسه.
•   pay-to-pubkey: نص برمجي script بسيط, الذي بدوره لديه وظيفة مشابها لوظيفة النص البرمجي السابق. ومع ذلك، عوضا عن ارسال الأموال الى هاش المفتاح العام، فان الأموال بتم ارسالها الى المفتاح العام نفسه. كل ما تحتاجه للإنفاق هو توقيع رقمي يثبت امتلاكك للمفتاح العام.
•   OP_RETURN: هي عملية تستخدم في النص البرمجي script الذي يجعل من الخرج للمعاملة بشكل فعال غير قابل للإنفاق. يستخدم عادة لحفظ كمية صغيرة من البيانات ضمن البلوكتشين دون تلويث مجموعة الـ UTXO للمعاملة.
•   Prevout: الـvout المُنفَق كـvin ضمن المعاملة, أي الخرج لمعاملة سابقة المنفق كدخل للمعاملة الحالية.

دليل العمل Proof of Work ونظم/خوارزميات الاتفاق للبلوكتشين:
دليل العمل او Proof of Work هو آلية اجماع او اتفاق التي جعلت من الـ Bitcoin شبكة آمنة وموثوقة لأكثر من عقد من الزمن. ومع ذلك، يوجد لديها حصتها من المشاكل. عيوب POW الرئيسية:
1-   POW يضيع الكثير من الكهرباء, مؤذياً البيئة. (الا ان رأيي الشخصي ان المشكلة هي في انتاج الكهرباء المضر للبيئة وليس الصرف. بالإضافة لا يمكن اعتبار الأمان الذي يزودنا به الـ Bitcoin لتأمين المعاملات المالية تضييعا للكهرباء انما أضواء الأعياد تعتبر تضييعا للكهرباء، ماذا عن الكهرباء المستخدمة لتسيير عمل البنوك والمؤسسات المالية، ولكن البعض لا يزال يراها كمشكلة).
2-   POW يفيد بشكل كبير اللاعبين الكبار على الأغلب, عوضا عن المشاركين الصغار في الشبكة.
3-   POW لا يقدم أي تحفيز لاستخدام العملة او الاحتفاظ بها.
4-   POW عرضة للمركزية, لأنه يشجع المعدنيين على الاشتراك بتجمعات التعدين الأكبر (عبارة عن مجموعة من المعدنين الذين يتشاركون مكافئة انتاج الكتل), بالتالي مُشَغِل أكبر تجمع معدنيين لديه الكثير من التحكم في الشبكة.

تم اختراع Proof of Stake لحل العديد من هذه المشكلات من خلال السماح للمشاركين في الشبكة بإنشاء وتعدين كتل جديدة (وبالتالي الحصول على مكافئة الكتل)، ببساطة من خلال التمسك او المحافظة على عملة الشبكة ضمن محفظتهم والسماح للمحفظة بتكديس العملات. تم اختراع الـ Proof Of Stake من قبل Sunny King وتم تطبيقها في peercoin. منذ ذلك الحين تم تحسين الخوارزمية و تم تبنيها من قبل العديد من المشاريع الأخرى.

سنقوم بشرح Proof of Stake Version 3, وهو تحسين فوق Version 2 الذي أوجد من قبل Pavel Vasin وتم تطبيقه ضمن مشروع Blackcoin, وهذا التطبيق الذي سوف نقوم بشرحه. ضمن الشرح، بعض المعرفة التقنية يفترض تواجدها بالقارئ، لكن سأحاول الشرح بحيث معظم المعرفة يمكن استنباطها من خلال السياق. بجب أن تكون على الأقل على دراية جيدة بمفهوم UTXO.
قبل البدء بالتكلم عن POS, فان فهم آلية عمل خوارزمية الاتفاق الأبسط POW سيساعد. عملية التعدين لـ POW يمكن تمثيلها بعدد قليل من السطور شبه برمجية pseudo-code:
Code:
While(blockHash > difficulty) {
block.nonce = block.nonce + 1
blochHash = sha256(sha256(block))
}

الهاش Hash عبارة عن خوارزمية تشفير تأخذ كمية غير محددة من البيانات، تقوم بمعالجتها، وتعطي كخرج عصارة Digest ثابتة الحجم للبيانات المدخلة. من المستحيل معرفة البيانات المدخلة من خلال العصارة Digest. لذا تميل خوارزمية POW لتعمل كمسألة حظ (يانصيب)، حيث يمكنك معرفة ما إذا فزت من خلال انشاء Hash والتحقق منه مقابل هدف صعوبة التعدين، ويمكنك انشاء تذكرة سحب أخرى من خلال تغيير طفيف في البيانات المدخلة (بيانات الكتلة) ثم انشاء Hash ومقارنته مع الهدف. في حالة الـ Bitcoin, الـ nonce هو المستخدم لإجراء التغيير في بيانات الادخال. بمجرد العثور على هاش أقل من هدف التعدين، فان البلوك يكون صالح، ويمكن ارساله الى باقي الشبكة. المعدنين سوف يرون البلوك الجديد، يتحققون من صحته ثم يضيفونه على البلوكتشين ويبدأن ببناء البلوك التالي بناءً عليه.

بنية وقواعد بروتوكول Proof Of Stake:
الآن سنبدأ بـ Proof of Stake. لدينا الأهداف التالية لـ POS:
1-    من المستحيل تزييف كتلة او بلوك.
2-    اللاعبون الكبار لا يحصلون على مكافآت أكبر بشكل غير متناسب.
3-    المزيد من الطاقة الحسابية لا تجدي لبناء المزيد من الكتل.
4-    لا يوجد عضو واحد في الشبكة يمكنه السيطرة على كامل البلوكتشين.

المفهوم الأساسي لـ POS مشابه جداً لـ POW, يانصيب. ومع ذلك، الفرق الكبير هو انه لا يمكن „الحصول على المزيد من التذاكر لليانصيب“ببساطة عن طريق تغيير بعض البيانات في الكتلة. فعوضا عن أن يكون هاش البلوك هو تذكرة اليانصيب لمقارنتها مع هدف صعوبة التعدين، فإن POS أوجد مفهوم هاش النواة Kernel Hash.
الـ Kernel Hash يتألف من عدة قطع من البيانات التي لا يمكن تعديلها بسهولة في البلوك الحالي. وهكذا، نظرا لأن المعدنين لا يملكون طريقة سهلة لتعديل هاش النواة، فلا يمكنهم ببساطة تكرار عملية الـ Hashing كما هو الحال في POW.
تضيف بلوكات او كتل Proof of Stake عدد من قواعد الإجماع الإضافية من أجل الوصول لهدفها. أولاً، على عكس POW, معاملة الـ coinbase (اول معاملة ضمن الكتلة) يجب ان تكون فارغة وتُكَافِئ بـ 0 عملة. عوضا عن ذلك، لمكافئة المكدسين فانه يوجد معاملة مميزة او خاصة تسمى معاملة التكديس/الحصة Stake Transaction التي يجب ان تكون المعاملة الثانية ضمن الكتلة. يتم تعريف معاملة التكديس/الحصة Stake Transaction على أنها أي عملية:
1-    لديها على الأقل vin واحد صالح.
2-    أول vout لها يجب ان تكون فارغة.
3-    ثاني vout لها لا يجب ان يكون فارغ.

علاوة على ذلك، حتى تكون لدينا معاملة تكديس/حصة Stake Transaction صالحة ضمن الكتلة Blockيجب ان تتبع هذه القواعد:
1-    vout الثانية للمعاملة يجب ان تكون اما برنامج نصي „pubkey“ (و ليس الهاش pubkeyhash), او برنامج نصي „OP_RETURN“ غير قابل للإنفاق (فقط بيانات Data) لكن يخزن بيانات لمفتاح عام.
2-    الطابع الزمني „Timestamp“ضمن المعاملة يجب ان يكون مساوي للطابع الزمني للكتلة او البلوك.
3-    القيمة الكلية لخرج معاملة الحصة يجب ان يكون مساوي لـِ او اقل من قيمة مجموع المدخلات مضافة عليها مكافئة الكتلة وإجمالي رسوم معاملات البلوك او الكتلة.
output <= (input + block reward + tx fees).
4-    أول vin مصروفة لخرج معاملة الحصة يجب ان يتم تأكيدها من قبل 500 بلوك على الأقل.
5-    على الرغم من أنه يكمن استخدام أكثر من دخل „vin“في معاملة الحصة، فانه فقط أول دخل سيستخدم لمُعَامِلات خوارزمية الاتفاق.
هذه القواعد تضمن ان معاملة الحصة يمكن معرفتها وتحديدها بسهولة، وتضمن أن تعطي معلومات كافية للشبكة لتأكيد البلوك. ان طريقة الخرج الأول الفارغ „vout“ليست الطريقة الوحيدة لتحديد معاملة الحصة، لكن هذا يعتبر التصميم الأصلي من قبل Sunny Kind وقد عملت بشكل جيد.

الآن بعد فهمنا معاملة الحصة وما هي القواعد التي تحكمها، الموضوع التالي سيكون لتغطية قواعد بلوك POS:
1-    يجب ان يملك معاملة حصة واحدة فقط لا غير.
2-    معاملة الحصة يجب ان تكون المعاملة الثانية ضمن البلوك.
3-    يجب ان تملك معاملة الحصة او معاملة coinbase قيمة خرج 0 وvout فارغ واحد فقط.
4-    يجب ان يكون الـ 4 بتات الأواخر للطابع الزمني للبلوك قيمتها 0. هذا يعني ان وقت البلوك يمكن تمثيله في فواصل زمنية من 16 ثانية، مما يقلل من تقسماتها.
5-    اصدار البلوك يجب ان يكون الإصدار 7.
6-    الـ Kernel Hash للبوك يجب ان يقابل الصعوبة المقاسة او الموزونة لخوارزمية POS.
7-    هاش البلوك يجب ان يكون مُوَقَع الكترونيا باستخدام مفتاح عام وموضوع ضمن الـ vout الثاني لمعاملة الحصة. التوقيع يوضع ضمن البلوك لكن لا يدخل ضمن هاش البلوك ذاته.
8-    التوقيع المخزن في البلوك يجب ان يكون „LowS“, والذي يعني: انه يتألف من قطعة واحدة من المعلومات ويجب ان يكون مضغوط قدر المستطاع (أي لا وجود لأصفار إضافية في النهاية أو أكواد عمليات opcodes).
9-    يتم تطبيق معظم القواعد الأخرى لبلوك POW (merkle hash صالح، عمليات صالحة، الطابع الزمني يكون ضمن إطار الانزياح الزمني المسموح به، الخ).

يوجد الكثير من التفاصيل هنا التي سيتم تغطيتها لاحقاً.
الجزء الأهم الذي يجعل خوارزمية POS فعالة تعتمد على الـ Kernel Hash. استخدام الـ Kernel Hash مشابه لمثيله في الـ POW (في حال تساوي الهاش مع صعوبة التعدين، فإن البلوك يعتبر صالح). ومع ذلك فإن الـ Kernel Hash لا يمكن تعديله بشكل مباشر في سياق البلوك الحالي. سنبدأ أولا بتغطية ما الذي يدور بهذه الهياكل (البنى) والآليات، ولاحقا سنشرح لماذا تم تصميم POSبهذه الطريقة، وما هي العواقب التي يمكن ان تأتي من تغييرات طفيفة عليها.

الـ Kernel Hash لـ Proof of Stake:
الـ Kernel Hash يتألف على وجه التحديد من المعلومات التالية، بالترتيب:
1-    الـ Stack modifier مُعَدِل° الحصة للبلوك السابق (المزيد عنه لاحقاً).
2-    الطابع الزمني لمعاملة prevout (أي خرج المعاملة التي يتم صرفها في الـ vin الأول لمعاملة الحصة).
3-    هاش معاملة الـ prevout.
4-    رقم الخرج لـ prevout (بمعنى آخر، أي خرج للمعاملة يتم صرفه بمعاملة الحصة؟).
5-    الوقت الحالي للبلوك، مع البتات ال4 الأخيرة تساوي ال0 لتقليل تقسيماته. هذه هو الشي الوحيد الذي يتغير ضمن معاملة الحصة او التكديس.
الـ Stake Modifier لبلوك POS هو هاش لـِ:
1-    هاش معاملة الـ prevout ضمن بلوكات POS, أو هاش البلوك ضمن بلوك POW.
2-    الـ Stake Modifier للبلوك السابق (معدل الحصة لبلوك الانشاء او التهيئة Genesis Block يساوي الصفر).
الطريقة الوحيدة لتغيير الـ Kernel Hash الحالي (من أجل انتاج بلوك)، هي اما بتغيير الـ prevout الخاص بك، أو بتغيير وقت البلوك الحالي.
محفظة واحدة تحتوي بالعادة على عدد من الـ UTXO. رصيد المحفظة هو في الأساس مجموع قيم جميع الـ UTXOs التي يمكن انفاقها من قبل المحفظة. هذا طبعا مطابق لمحفظة POS. هذا مهم رغم ذلك، لان أي خرج يمكن استخدامه للتكديس او التحصيص Staking. واحد من هذه المخرجات يمكن ان يصبح الـ prevout ضمن معاملة الحصة لتشكيل أو انتاج بلوك POS صالح.
أخيراً، يوجد جانب إضافي واحد يختلف في عملية تعدين بلوك POS. حيث صعوبة التعدين تقاس مقابل عدد العملات الموجودة ضمن معاملة الحصة. صعوبة التعدين في POS ينتهي بها الأمر لتكون أسهل بمقدار الضعف عند تكديس عملتين، بالمقارنة بتكديس عملة واحدة. إذا لم تكن الحالة كذلك، فذلك سوف يشجع على انشاء عدد كبير من الـ UTXOs الصغيرة للتكديس، والذي بدوره سيملئ او يزيد حجم البلوكتشين وبالتالي ستحتاج الشبكة ككل لتسخير المزيد من الموارد للمحافظة عليها، كذلك يحتمل تهديد أمن البلوكتشين ككل.
إذا أردنا كتابة كود شبه برمجي pseudo-code لإظهار كيفية إيجاد هاش النواة Kernel Hash صالح، ستكون كالتالي:
Code:
While(true) {
  Foreach(utxo in wallet) {
    blockTime = currentTime – currentTime % 16
    posDifficulty = difficulty * utxo.value
    hash = hash(previousStakeModifier + utxo.time + utxo.hash + utxo.n + blockTime)
    if (hash < posDifficulty) {
      done
    }
  }
  wait 16s
}
قد لا يكون النص شبه البرمجي السابق مفهوما مثل كود POW لذلك سأحاول شرحه كتابيا:
Code:
قم بعمل التالي مرارا وتكرارا الى الأبد:
احسب الـ BlockTime ليساوي الوقت الحالي ناقص باقي قسمة الوقت الحالي نفسه على 16.
احسب الـ posDifficulty على أنه صعوبة التعدين في الشبكة مضروب بعدد العملات الموجودة في الـ UTXO.
تنقل خلال كل UTXO في المحفظة. عند كل UTXO, قم بحساب هاش SHA256 باستخدام مُعَدِل التكديس/الحصة للبلوك السابق، بالإضافة الى بعض البيانات من الـ UTXO وأخيرا الـ BlockTime. ثم قارن هذا الهاش مع posDifficulty. إذا كان الهاش أقل من posDifficulty, عندها يكون هاش النواة Kernel Hash صالح ويمكنك من انشاء بلوك جديد.
بعد المرور على جميع الـ UTXOs, إذا لم يتم انتاج أي هاش أقل من الـ posDifficulty, عندها انتظر 16 ثانية وقم بتكرار كل شيء مرة أخرى.

الآن بعد إيجاد هاش نواة صالح باستخدام واحد من الـ UTXOs التي يمكننا إنفاقها، يمكننا انشاء معاملة الحصة.
هذه المعاملة سيكون لها vin واحدة، التي تنفق الـ UTXO التي وجدنا ان لديها هاش نواة صالح.
وسيكون لديها (على الأقل) اثنان vouts. الـ voutالأول سيكون فارغ، مُعَرِفَاً الـ Blockchain ان المعاملة هي معاملة تكديس/حصة Stake Transaction. الـ vout الثاني سيحتوي إما على معاملة بيانات OP_RETURN تحتوي على مفتاح عمومي واحد، او ستحتوي على نص برمجي pay-to-pubkey.

أخيراً، تتم إضافة أي معاملات من الـ mempool إلى البلوك. الشيء الواحد الباقي لعمله الآن هو انشاء توقيع رقمي، إثباتً أننا وافقنا على كتلة POS صالحة. التوقيع الرقمي يجب ان يستخدم المفتاح العام المضمن في الـ vout الثاني لمعاملة الحصة/التكديس Stake Transaction. بعد إضافة التوقيع، يمكن ان يتم بث البلوك الى الشبكة. العقد في الشبكة ستقوم بعد ذلك بتأكيد صحة البلوك، فاذا وجدته صالح ستقوم بقبوله واضافته الى البلوكتشين وإعادة بث البلوك الجديد الى العقد المتصلة معها.

المصدر: http://earlz.net/view/2017/07/27/1904/the-missing-explanat
Jump to: