یک مدل کامل ذهنی برای توسعه dApp اتریوم (بخش اول)

اگر همه ما به صورت اشتراکی یک دفتر کل عمومی حاوی موجودی‌ها و تراکنش‌ها داشته باشیم، می‌توانیم یک ارز جهانی ایجاد کنیم که کاملا از دولت‌ها و موسسات جدا است. «ساتوشی ناکاموتو» به صورتی آینده‌نگرانه نخستین بیت کوین را در بحبوحه بدترین بحران مالی از زمان رکود بزرگ استخراج کرد. کمی پس از آن، ویتالیک بوترین (Vitalik Buterin) دریافت که اگر کلاینت‌ها همچنین بتوانند «سرورها» و پایگاه‌های داده را نگهداری کنند، بلاک‌چین زیربنایی می‌تواند برنامه‌پذیر باشد. نتیجه باورنکردنی آن ایده قراردادهای هوشمند است. می‌توان به چنین قراردادهایی طوری برنامه داد تا دارایی‌های حقیقی را با سوابق غیرقابل تغییر مالکیت، توکنی‌سازی (دیجیتالی) کنند. اپلیکیشن‌هایی که از قراردادهای هوشمند استفاده می‌کنند، برنامه های نامتمرکز یا به اختصار dapp نامیده می‌شوند. برای کمک به توسعه‌دهندگان وب جهت توسعه dApp اتریوم، نگارنده امیدوار است که یک مدل ذهنی ساده برای این لایه‌های معماری ارائه دهد که پشته بلاک‌چینی اپلیکیشن را تشکیل می‌دهند.

0 116

معماری غالب اکثر برنامه‌های کاربردی وب کلاینت-سرور-دیتابیس است. ما از کلاینت‌هایی مانند لپ‌تاپ‌ها، تلفن‌های هوشمند و تبلت‌ها استفاده می‌کنیم تا از سرورهای بک‌اند درخواست کنیم، یا به آن‌ها درخواست ارسال کنیم، که در مقابل با پایگاه‌های داده برای ذخیره و بازیابی داده‌ها تماس برقرار می‌کنند. رابطه بین کلاینت و سرور/پایگاه داده یک به چند است و کنترل در سرور/پایگاه دوم متمرکز شده است. اگر تمرکز وب ۰/۱ بر صفحات وب ایستا بود، وب ۰/۲در مورد تعامل و جاوا اسکریپت است.

پشته وب: Client =>Server => Database

هدف رسیدن به Web 3.0 است، جایی که سرورها و پایگاه‌های داده به همان میزان کلاینت‌ها نامتمرکز هستند. به عبارت دیگر، کلاینت‌ها نیز می‌توانند نقش سرور یا پایگاه داده یا هر دو (همتا به همتا) را ایفا کنند. با داشتن روابط چند به چند در تمام سطوح پشته، تمرکز کنترل و نقطه واحد شکست وجود ندارد. شبکه به صورت حداکثری توزیع‌شده است.

وب ۱.۰
ایستا (HTML / CSS)

وب ۲.۰
تعاملی (جاوا اسکریپت)

Web 3.0
نامتمرکز (بلاک‌چین)

چرا تمایل داریم کلاینت‌ها نیز پایگاه‌های داده را نگهداری کنند؟ آشکارترین و قدرتمندترین مورد کاربرد، بیت کوین است. اگر همه ما به صورت اشتراکی یک دفتر کل عمومی حاوی موجودی‌ها و تراکنش‌ها داشته باشیم، می‌توانیم یک ارز جهانی ایجاد کنیم که کاملا از دولت‌ها و موسسات جدا است. «ساتوشی ناکاموتو» به صورتی آینده‌نگرانه نخستین بیت کوین را در ۳ ژانویه ۲۰۰۹ و در اثنای بحبوحه بدترین بحران مالی از زمان رکود بزرگ استخراج کرد.

بلاک‌چین => دفتر کل عمومی => ارز جهانی

کمی پس از آن، ویتالیک بوترین (Vitalik Buterin) دریافت که اگر کلاینت‌ها همچنین می‌توانند «سرورها» و پایگاه‌های داده را نگهداری کنند، بلاک‌چین زیربنایی می‌تواند برنامه‌پذیر باشد. نتیجه باورنکردنی آن ایده قراردادهای هوشمند است. می‌توان به چنین قراردادهایی طوری برنامه داد تا دارایی‌های حقیقی را با سوابق غیرقابل تغییر مالکیت توکنی‌سازی (دیجیتالی) کند. در نتیجه، هر کس از هر گوشه جهان می‌تواند هر چیز مانند زمین، انرژی، موسیقی و رای‌گیری را به صورت ارزان و امن و بدون نیاز به واسطه‌هایی که مستعد فساد هستند معامله کند. کاربردها بی‌پایان، متحول‌کننده و اثرگذار هستند.

قرارداد هوشمند => سوابق مالکیت => بلاک‌چین

اپلیکیشن‌هایی که از قراردادهای هوشمند استفاده می‌کنند، برنامه های نامتمرکز یا به اختصار dapp نامیده می‌شوند. Dappها اپلیکیشن‌های فرانت‌اندی هستند که با قراردادهای هوشمند (به جای سرور) ارتباط برقرار می‌کنند تا داده‌ها را (به جای پایگاه داده) در بلاک‌چین ذخیره کرده یا از آن بازیابی کند. کلاینت‌های از طریق حساب‌های خارجی با dappها ارتباط برقرار می‌کنند. برای کمک به توسعه‌دهندگان وب جهت توسعه dApp اتریوم، نگارنده امیدوار است که یک مدل ذهنی ساده برای این لایه‌های معماری ارائه دهد که پشته بلاک‌چینی اپلیکیشن را تشکیل می‌دهند.

Webapp: Client =>Server => Database

Dapp: حساب خارجی => قرارداد هوشمند => بلاک‌چین

لایه بلاک‌چین (پایگاه داده)

لایه بلاک‌چین مشابه لایه پایگاه داده است، که در آن داده‌ها ذخیره و بازیابی می‌شوند. در اینجا، بلاک‌ها هر تراکنشی که تا به حال انجام شده است را ثبت می‌کنند. چیزی که بلاکچین را متمایز می‌سازد این است که هر کسی می‌تواند چیزی را به چین اضافه کند. اجماع از طریق یک فرایند به نام استخراج به دست می‌آید، که در آن کامپیوترهایی که روی چین اتریوم فعال هستند برای به دست آوردن بلاک بعدی رقابت می‌کنند (گواه بر کار). این نودها مجموعا شبکه‌ای را تشکیل می‌دهند و هر یک، نسخه‌ای از کل بلاک‌چین را نگهداری می‌کند. این یک راه حل جدید برای مساله ژنرال بیزانسی است که همه سیستم‌های توزیع‌شده با آن درگیر هستند.

network: کلاینت‌های اتریوم => استخراج (بلاک) => اثبات

برای افزودن داده‌های جدید به بلاک‌چین، تراکنش‌ها را به نودهای شبکه ارسال می‌کنیم. سپس نودها قبل از آغاز فرآیند استخراج، تراکنش‌های موجود در صف انتظار را در یک بلاک قرار می‌دهند.

node: تراکنش => بلاک‌ها => بلاک‌چین

به عبارت دیگر، هر بلاک یک درخت مرکل (Merkle) از تراکنش‌ها، به علاوه یک درخت مرکل از رسیدها و یک درخت مرکل از وضعیت است. مزیت این درختان مرکل (به طور دقیق ترای مرکل-پاتریشیا (Merkle-Patricia trie)) یک فرآیند تایید اعتبار ساده است (اثبات مرکل)، که در آن نودها می‌توانند به جای همه تراکنش‌های همه بلاک‌ها، برای تایید یک پرداخت تنها هدر بلاک‌ها را دانلود کنند (کلاینت‌های سبک).

هدر بلاک‌ها:

۱) تراکنش‌ها => transactions trie => transactionsRoot

۲) اطلاعات و سوابق => receipts trie => receiptsRoot

۳) نشانی‌ها و و موجودی‌ها => state trie => stateRoot

transactionsRoot یک ترای از تراکنش‌ها در بلاک است، ‌receiptsRoot یک ترای از اطلاعات و سوابق تراکنش، و stateRoot ترای نشانی‌ها و موجودی حساب است (دفتر کل). اساسا، یک تراکنش تنها یک وضعیت و یک قرارداد هوشمند تنها یک تابع انتقال وضعیت است.

تراکنش‌ها: پیدایش => وضعیت ۱ => وضعیت ۲ => … => وضعیت N

و ساختار زیربنایی اساسا یک فهرست پیوند شده از درخت های باینری هش‌های رمزنگاری است.

بلاک‌چین: پیدایش <= ترای‌های ۱ <= ترای‌های ۲ <= … <= ترای‌های N

برای استخراج یک بلاک جدید، ما یک هش از این روت‌های مرکل را در یک در هدر بلاک محاسبه می‌کنیم. این هش باید به هش آخرین بلاک اشاره کرده و در عین حال یک نانس (nounce) ویژه را محاسبه کند که نتیجه آن کمتر از یک هدف است. این عملیات ریاضی «اثبات» اعتبار بلاک است.

hash (نانس، هدر بلاک، هش قبلی) < target

هدف توسط الگوریتم Ethash تعیین می‌شود که زمان مورد نیاز برای حل بلاک قبلی را طوری نظر می‌گیرد که زمان متوسط به ۱۵ ثانیه نرمال شود (زمان بلاک). این هدف به طور مداوم تنظیم می‌شود، چرا که تعداد افرادی که نودها را اجرا می‌کنند همیشه ثابت نبوده و کیفیت منابع محاسباتی همواره بهتر می‌شود. هش خروجی شانزده شانزدهی بوده (پایه ۱۶، معمولا با پیشوند 0x) و همواره ۶۴ حرف طول دارد.

ETHEREUM AVERAGE BLOCKTIME CHART

https://etherscan.io/chart/blocktime

یک زمان بلاک بیش از حد بالا (هدف کم) باعث کاهش سرعت شبکه و افزایش زمان پردازش تراکنش‌ها می‌شود. یک زمان بلاک بیش از حد پایین (هدف بالا) باعث ایجاد راه حل‌های تکراری بسیار و فورک در بلاک‌چین می‌گردد. به نظر می‌رسد که زمان بلاکی ۱۵ ثانیه مناسب باشد.

هدف پایین=> زمان بلاک بالا => طولانی شدن بیش از حد

هدف بالا => زمان بلاک پایین => فورک‌های زیاد

هنگامی که یک فورک رخ می‌دهد، اتریوم از پروتکل GHOST‌ پیروی می‌کند. این پروتکل فورکی را انتخاب می‌کند که بیشترین کار را انجام داده باشد یا به عبارت دیگر طولانی‌ترین چین (بالاترین عدد بلاک) را داشته باشد.

فورک A: پیدایش + بلاک ۱ + بلاک ۲ + … + بلاک ۱۲ // اصلی

فورک B: پیدایش + بلاک ۱ + بلاک ۲ + … + بلاک ۱۱ // عمو

فورک C: پیدایش + بلاک ۱ + بلاک ۲ + … + بلاک ۱۰ // عمو

بر خلاف بیت کوین،‌ فورک‌های اتریوم «یتیم» نبوده و رها نمی‌شوند. آن‌ها «عمو» خوانده شده برای ایجاد انگیزه‌ای که استخرهای استخراج را با هدف افزایش امنیت نامتمرکز می‌سازد پاداش می‌گیرند. به طور کلی، برای این که اجازه دهیم طولانی‌ترین چین پیروز شود عموما ۶ تراکنش صبر می‌کنیم.

پاداش بلاک: ۳ + کارمزدها + ۱/۳۲ × عموها)

پاداش عمو:۷/۸ × ۳// دو عمو به ازای هر بلاک (حداکثر)

هرچه استخراج متمرکزتر شود، خطر حمله ۵۱٪ که در آن ماینرها برای تایید خرج مضاعف تبانی می‌کنند بیشتر می‌شود. انتظار برای حداقل تایید ۶ بلاک دیگر از سوی شبکه نیز این خطر را کاهش می‌دهد. در هر صورت، چنین حملاتی عملا سودآور نیستند. اجرای آن‌ها حدود ۶ میلیارد دلار هزینه دارد و اگر هزینه فرصت صادقانه عمل نکردن و عدم دریافت پاداش را نیز در نظر بگیریم هزینه باز هم بالاتر خواهد بود.

بیایید به یک بلاک حقیقی تراکنش‌ها در شبکه اتریوم نگاهی بیندازیم:

BLOCKS

https://etherscan.io/block/5912705

ارتفاع بلاک نشان‌دهنده ترتیب آن در زنجیره است. در این مورد، شماره بلوک ۵٬۹۱۲٬۷۰۵ است. بر طبق برچسب زمان (TimeStamp) این بلاک در ۵ ژوئیه ۲۰۱۸ و در حدود ساعت ۱۲ صبح توسط Ethermine استخراج شده است. این بلاک شامل ۸۹ تراکنش به حجم ۱۹٬۲۹۰ بایت داده جدید است. Ethermine اولین ماینری بود که موفق شد نانس صحیحی را پیدا کند که منجر به یک مقدار هش کمتر از سختی هدف بود. به عنوان پاداش، Ethermine مبلغ ۳٫۴۶۴۸۶۹۶۴۹۹۶ اتر دریافت کرد (پاداش بلاک).

پاداش بلاک = coinbase + کارمزدها + عموها = ۳ + ۰٫۴۶۴۸۶۹۶۴۹۹۶ + ۰

Gas نشان‌دهنده عملیات محاسباتی مورد نیاز برای اجرای کد است. بلاک Gas Limit حداکثر تعداد عملیاتی را تعیین می‌کند که تمام تراکنش‌های بلاک مجاز به «مصرف» آن هستند. همانند محدودیت اندازه بلاک بیت کوین، هدف آن پایین نگاه داشتن زمان پردازش تراکنش‌ها و زمان انتشار به نودهای دیگر است. اما بر خلاف بیت کوین، این عدد ثابت نیست. ماینرها می‌توانند این محدودیت را کمی تغییر دهند.

block gas limit = ۱.۵ x 10^6 x π ± ۱/۱۰۲۴

sum (محدودیت gas تراکنش‌ها) < block gas limit

همانند بیت کوین، اتر زمانی ایجاد می‌شود که ماینرها پازل رمزنگارانه را با موفقیت حل کنند. این کار به سادگی با افزایش موجودی حساب ماینر به وسیله مبلغ پاداش (تراکنش coinbase) انجام می‌شود. اما در بیت کوین، یک تراکنش coinbase باید توسط یک ماینر صادر شود.

اکنون بیایید نگاهی به دو مورد از آن تراکنش‌ها بیاندازیم:

TRANSACTIONS

https://etherscan.io/tx/0xc28ab33c5943d0d593d34d9af1b29971310dac009b88b83d3b2fae5dfdfed327

TRANSACTIONS

https://etherscan.io/tx/0x0875ed575d905efdbb909020da5f83867aadfa572f4164ff009a94025f4a977e

این دو تراکنش نشان‌دهنده دو حالت ممکن در اتریوم هستند. می‌توانیم اترها را به یک حساب دیگر (اولین تراکنش) یا یک حساب قرارداد (تراکنش دوم) بفرستیم.

۱) حساب خارجی => حساب خارجی
۲) حساب خارجی => حساب قرارداد

۳) حساب قرارداد => حساب قرارداد // تراکنش «داخلی»

هر دو تراکنش TimeStamp، From، To، و میزان اتری که باید ارسال شود (مقدار) را در اختیار ما می‌گذارند. آن‌ها همچنین مقدار gas در دسترس (Gas Limit)، مقدار مصرف شده (Gas مورد استفاده توسط Txn) و هزینه واحد آن (قیمت گاز) را نشان می‌دهند. در اینجا نانس فقط یک شمارنده برای دادن ترتیب به تمام تراکنش‌هایی است که توسط یک فرستنده خاص در حال ارسال شدن هستند. این موضوع از آن جهت لازم است که تراکنش‌ها باید به ترتیب پردازش شوند تا افراد نتوانند بیش از چیزی که دارند مصرف کنند. پس از ارسال، TxHash ایجاد شده است. TxHash شناسه یک تراکنش است که می‌توان از آن را برای پینگ کردن شبکه جهت کنترل وضعیت TxReceipt تراکنش خود استفاده کنیم. اگر بنا بوده که تراکنش ما برای یک حساب قرارداد باشد، می‌توانیم داده‌های ورودی را نیز برای مصرف توسط قرارداد الصاق کنیم.

Gas استفاده شده توسط txn > محدودیتGas

Gas استفاده شده توسط Txn × قیمت‌ Gas = هزینه واقعی Tx/کارمزد

هنگام ارسال معاملات، ما از نودهای شبکه می‌خواهیم که آن‌ها را برای ما پردازش کند. این کار نیازمند منابع محاسباتی است که ما هزینه آن را به صورت gas پرداخت می‌کنیم. کارمزدهای gas نه تنها از اسپم جلوگیری می‌کند بلکه کدهای بد مانند حلقه‌های بی‌نهایت را نیز متوقف می‌کند. ما می‌توانیم مقدار و قیمت را مشخص کنیم. در ابتدا، کل هزینه بالقوه کسر خواهد شد. gas باقی‌مانده مسترد خواهند شد. اگر یک مقدار ناکافی تعیین کنیم، تراکنش ما برگشت خورده و هزینه کارمزد نیز استرداد نمی‌گردد. هر چه هزینه بیشتری برای هر واحد gas پرداخت کنیم، اولویت بالاتری دریافت خواهید کرد. در حال حاضر، gwei ۵۰یعنی( ۰٫۵۰  یورو) gas در یک دقیقه پردازش می‌شود. در مقایسه با انتقال پول، این سرعت باورنکردنی است و می‌توان از هزینه آن قابل چشم‌پوشی کرد.

قیمت gas = عرضه (ماینرها) + تقاضا (حساب‌های خارجی)

به شکلی گیج‌کننده، حساب‌های قرارداد نیز نانس دارند که البته حاوی یک معنی دیگر است. در این موارد، این عدد هر زمانی که حساب قرارداد یک حساب قرارداد دیگر ایجاد کند افزایش می‌یابد.

نانس بلاک = راه حل پازل رمزنگاری

نانس حساب خارجی = تعداد تراکنش‌های صادر شده
نانس حساب قرارداد = تعداد قراردادهای ایجاد شده

پیش از آن که این بخش را به پایان ببریم، اجازه دهید اجزای حساب‌های خارجی و قرارداد را بررسی کنیم.

 اجزای حساب‌های خارجی و قرارداد

عکس: https://etherscan.io/address/0x68b42e44079d1d0a4a037e8c6ecd62c48967e69f

 اجزای حساب‌های خارجی و قرارداد

https://etherscan.io/address/0x06012c8cf97bead5deae237070f9587f8e7a266d

هر دو نوع حساب می‌توانند اتر ارسال و دریافت کنند. بنابراین، هر دو دارای یک فیلد موجودی هستند که آن‌ها را پیگیری می‌کند. اما حساب‌های قرارداد می توانند داده نیز ذخیره کنند. بنابراین، آن‌ها یک فیلد ذخیره‌سازی و یک فیلد کد دارند که شامل دستورالعمل‌های ماشین در مورد نحوه دستکاری داده‌های ذخیره شده است. به عبارت دیگر، حساب‌های قرارداد قراردادهای هوشمندی هستند که در یک بلاک‌چین زندگی می‌کنند.

حساب قرارداد = موجودی + کد + ذخیره‌سازی

حساب خارجی = موجودی + خالی + خالی

حساب‌های خارجی توسط کلیدهای خصوصی (یعنی انسان) کنترل می‌شوند، در حالیکه حساب‌های قرارداد توسط تحت کنترل کد هستند. یک تراکنش بین دو حساب خارجی تنها انتقال ارزش است. یک تراکنش از یک حساب خارجی به یک حساب قرارداد، کد حساب فراخوانده شده را فعال می‌کند. بر خلاف باور عمومی، قراردادهای هوشمند نمی‌توانند خود را اجرا کنند. اقدامات حساب‌های قرارداد همیشه توسط حساب‌های خارجی آغاز می‌شوند.

حساب خارجی => تراکنش => حساب قرارداد A => تراکنش‌ «داخلی» => حساب قرارداد B => …

در اتریوم نیز مانند بیت کوین، فقط اتر می‌فرستیم و هیچ‌گاه نمی‌توانیم اتر برداریم. بنابراین، امنیت فیلد From از بیشترین اهمیت برخوردار است. در حقیقت این فیلد تا آن حد حیاتی است که از سه فیلد اضافی برای تعیین اعتبار آن استفاده می‌شود. این فیلدها v، r و s هستند. بدیهی است، اگر ما بتوانیم یک نشانی From را بازنویسی کنیم، می‌توانیم هر حساب را دستکاری کرده و اترهای آن را به خود منتقل کنیم. برای درک v، r و s، نیاز به درک رمزنگاری نامتقارن داریم.

تراکنش = ارسال اتر/ / هیچ‌گاه نمی‌توان اتر برداشت.

ما از رمزنگاری برای رمزگذاری و رمزگشایی پیام استفاده می‌کنیم. با رمزنگاری متقارن، یک کلید را می‌توان هم برای رمزگذاری و هم برای رمزگشایی استفاده کرد. با رمزنگاری نامتقارن، تنها کلید خصوصی برای رمزگشایی قابل استفاده است، در حالی که هر کس می‌تواند از کلید عمومی ما برای رمزگذاری پیام‌هایی استفاده کند که فقط ما قادر به دیدن آن هستیم.

// رمزنگاری متقارن

encrypt(پیام رمزگذاری نشده، کلید ۱) => پیام رمزگذاری شده
decrypt(پیام رمزگذاری شده کلید ۱) => پیام رمزگذاری نشده

// رمزنگاری نامتقارن

encrypt(پیام رمزگذاری نشده، کلید عمومی) => پیام رمزگذاری شده
decrypt(پیام رمزگذاری شده، کلید خصوصی) => پیام رمزگذاری نشده

این ویژگی رمزنگاری نامتقارن را امن‌تر می‌کند زیرا ما دلیلی برای به اشتراک گذاشتن کلید خصوصی خود با شخصی نداریم. یکی دیگر از مزایای رمزنگاری نامتقارن، توانایی «امضای» پیام با کلید خصوصی است. سپس با استفاده از کلید عمومی، هر کس می‌تواند تایید کند که پیام و «امضا»ی ما تطابق دارند.

sign(پیام، کلید خصوصی) => امضا

verify(پیام، امضا، کلید عمومی) => صحیح/غلط

در اتریوم، کلیدهای خصوصی ۶۴ کاراکتر شانزده شانزدهی تصادفی هستند. در پایه ۱۰، این ارقام فوق‌العاده بزرگ و غیر قابل حدس هستند. با کلیدهای خصوصی، می‌توانیم کلیدهای عمومی را با استفاده ازالگوریتم امضای دیجیتال منحنی بیضوی (ECDSA) برای رسیدن به ۱۲۸ کاراکتر شانزده شانزدهی ایجاد کنیم. برای ایجاد نشانی حساب، کلیدهای عمومی را با استفاده از Ethash)keccak-256) هش کرده و ۲۴ کاراکتر اول را حذف می‌کنیم تا به ۴۰ کاراکتر هگزادسیمال برسیم.

random(هگزادسیمال) => کلید خصوصی // ۶۴ کاراکتر

ECDSA(کلید خصوصی) => کلید عمومی // ۱۲۸ کاراکتر

keccak(کلید عمومی) => آدرس حساب // ۴۰ کاراکتر

در اتریوم ، r و s خروجی امضای موضوع تراکنش با کلید خصوصی فرستنده با استفاده از ECDSA هستند، در حالی که v می‌تواند برای محاسبه آدرس مبدا مورد استفاده قرار گیرد.

sign(تراکنش) => r و s (امضا)

v => کلید خصوصی => نشانی حساب

این پارامترها در کنار هم وسیله‌ای هستند که نودها می‌توانند توسط آن‌ها تأیید کنند که تراکنش در حقیقت از نشانی حساب مورد نظر نشات گرفته است.

verify(تراکنش، rs_signature، v_address) => صحیح/غلط

از آنجایی که می‌توان با استفاده از v به آدرس مبدا رسید، ارسال آن به همراه تراکنش ضرورتی ندارد!

در نهایت، نشانی قرارداد را می‌توان سپس از نشانی حساب و نانس تراکنش ایجاد کرد.

keccak(آدرس حساب، نانس تراکنش) => نشانی قرارداد // ۴۰ کاراکتر

۱۲ کاراکتر اول را نادیده می‌گیریم تا مجددا به ۴۰ کاراکتر هگزادسیمال برسیم.

از آنجا که نشانی‌ خارجی و نشانی قرارداد در نهایت از کلیدهای خصوصی ما مشتق می‌شوند، تا زمانی که آن‌ها را امن نگه داریم، سرقت غیر ممکن است. برعکس، اگر کلیدهای خصوصی خود را از دست بدهیم، اترهایمان نیز برای همیشه از دست می‌رود.

شاید از این مطالب هم خوشتان بیاید.

ارسال پاسخ

آدرس ایمیل شما منتشر نخواهد شد.