آموزش طرز کار بلاک چین با PHP و JSON – راهنمای مقدماتی


هدف این مقاله معرفی اولیه مبانی مقدماتی بلاک چین برای توسعهدهندگان (به طور خاص وب) است که در این زمینه معلوماتی ندارند. ما در این نوشته از طریق ساخت یک بلاک چین بسیار ساده با استفاده از JSON و کمی اسکریپت PHP به بررسی ساختار آن میپردازیم.
در انتهای این راهنما، شما یک بلاک چین خواهید داشت که روی سیستمتان ذخیره شده است و یک صفحه وب برای تست نیز طراحی میکنیم که میتوانید برای ارسال بلاکهای جدید به زنجیره خودتان مورد استفاده قرار دهید.
کنترل کردن ایجاد بلوکهای جدید در حد اثبات تئوریک (proof of concept)، راهاندازی یک بلاک چین توزیع یافته و دیگر کارهای پیشرفته، خارج از حیطه این مقاله هستند.
ساختار یک بلاک چین
در ابتدا به تعریف ماهیت بلاک چین میپردازیم: بلاک چین یک کتابچه دیجیتال است که از سوی همه افراد قابل دسترس بوده و همه تراکنشها که با یک پول فرضی صورت میگیرند با ترتیب زمانی در آن ثبت میشوند.
همان گونه که امروزه شاهد هستیم، بلاک چین میتواند برای ذخیرهسازی دادههای مختلفی مورد استفاده قرار گیرد و محدود به تراکنشهای اقتصادی نیست. به علاوه جذابترین سیستمهای بلاک چین از معماری توزیع یافته بهره گرفتهاند که در آن هیچ کس مالک واقعی بلاک چین نیست.
در هر حال ما در نخستین گام خود برای ورود به دنیای بلاک چین، قصد داریم مفاهیم را به سادهترین زبان ممکن بیان کنیم. در ادامه یک بلاک چین متمرکز (یعنی غیر توزیع یافته) ایجاد میکنیم که میتواند تراکنشها را به کمک PippoCoin که پول انتخابی ما برای سیستم بلاک چین خودمان است ثبت میکند.
در یک بلاک چین، هر داده جدیدی (یک تراکنش) در یک بلوک ذخیره میشود که به انتهای زنجیره اضافه میشود. این بلوک جدید برای این که به زنجیره اضافه شود، از برخی اطلاعات بلوک قبلی بهره میگیرد تا از یکپارچگی و تغییرناپذیری زنجیره مطمئن شود.
هدف اولیه ما این است که بلاک چین خود را با تعریف ساختار بلوکها شکل بدهیم. ما در این راهنما از یک فایل JSON ساده برای ذخیرهسازی بلاک چین استفاده میکنیم. JSON یک قالب کاملاً شناخته شده است که میتواند به سهولت از سوی PHP که یک زبان اسکریپتنویسی است، خوانده و نوشته شود. ما در این راهنما از PHP برای تعامل با دادهها استفاده میکنیم.
در ابتدا شروع به ساخت یک بلاک چین ابتدایی میکنیم و نخستین بلوک خود را در آن و در یک فایل جدید به نام chain.json قرار میدهیم.
{"chain": [{ "index":0, "hashid":"first-block-doesnt-need-it", "timestamp":1541152127213, "proof-of-work":"xyz", "content": { "from":"network", "to":"simone", "amount":1 } }] }
بلاک چین ما برای مدیریت تراکنشهای PippoCoin که از سوی بلوکها تولید شده است استفاده میشود. هر تراکنش دارای خصوصیات زیر است:
- Index: اندیس یک ID به صورت عدد صحیح یکتا است که از 0 آغاز شده و هر بار 1 واحد افزایش مییابد. سادگی طراحی اندیس برای شمارش سادهتر کل بلوکها در زنجیره بهتر است.
- hashid: ما یک مقدار دلخواه برای نخستین بلوک خود انتخاب کردیم. برای بلوکهای بعدی مقدار ID هش با استفاده از تابعی اختصاصی محاسبه میشود که از برخی دادههای ذخیره شده در بلوک قبلی برای ایجاد یک مقدار یکتا و سازگار استفاده میکند.
- Timestamp: این مقدار تاریخ ایجاد بلوک را نشان میدهد. در این راهنما ما از یک مقدار ساده به صورت Unix Timestamp (به میلیثانیه) استفاده میکنیم.
- Proof-of-work: اثبات کار در یک سیستم بلاک چین کاملاً عملیاتی، برای ایجاد یک بلوک جدید در زنجیره مورد نیاز است. به طور معمول اثبات کار، راهحل یک مسئله رمزنگاری پیچیده است؛ اما در عمل میتواند هر چیزی باشد و به محیط بلاک چین طراحی شده بستگی دارد. برای نمونه میتوانیم یک محیط بلاک چین بسازیم که به افرادی که در خبرنامه ما ثبت نام میکنند، بر اساس PippoCoin پاداش بدهیم. در این صورت اثبات انجام کار ما میتواند یک id ثبت نام معتبر در خبرنامه ما باشد. در این راهنمای کاملاً مقدماتی بلاک چین، قصد نداریم چندان در زمینه اثبات انجام کار عمیق بشویم و اثبات انجام کار همه بلوکها در زنجیرهمان را برابر با «xyz» قرار میدهیم.
- Content: این مقدار شامل اطلاعات ساختارمندی در مورد خود تراکنش است و در سادهترین شکل خود حاوی یک تراکنش مالی است که به وسیله یک «فرستنده» (از) و یک «گیرنده» (به) و «کمیت مورد مبادله» (مقدار) مشخص میشود. نخستین فرستنده تراکنش، خود سیستم (شبکه) است، گیرنده کاربری است که آن را میثم مینامیم و مبلغ مورد معامله نیز 1 PippoCoin است.
ما با خواندن این بلاک چین، میتوانیم درک کنیم که یک کاربر به نام «میثم» 1 PippoCoin را از سوی سیستم دریافت کرده است. نام کاربری سیستم به صورت «network» است. این کاربر خاص تنها کسی است که مجاز به ایجاد یک PippoCoin جدید است. کاربران دیگر تنها مجاز به تغییر PippoCoin ها در میان خود هستند.
به عنوان یک قاعده اساسی در محیط PippoCoin، همه کاربران دیگر در سیستم میتوانند سکههای خود را در صورتی که سکهای داشته باشند یعنی از سوی سیستم یا فرد دیگری دریافت کرده باشند، مبادله کنند.
یک کاربر چگونه میتواند از سوی سیستم PippoCoin دریافت کند؟ به وسیله انجام کار و نمایش اثبات کار برای شبکه هر کس میتواند PippoCoin دریافت کند.
خواندن بلاک چین
زمانی که ساختار ابتدایی بلاک چین ما تعریف شد، میتوانیم شروع به کدنویسی یک «شیء دسترسی داده» (Data Access Object) ابتدایی در PHP بکنیم. این شیء ما دارای قابلیتهای زیر است:
- خواندن بلاک چین
- خواندن دادههایی در مورد آخرین بلوک در بلاک چین
- محاسبه هش بلوک که از سوی یک بلوک استفاده میشود و درج آن در بلاک چین
کد زیر در includes/dao.PHP قرار گرفته است:
<?php class DAO { function read_all() { try { $jsondata = file_get_contents(dirname(dirname(__FILE__))."/chain.json"); $arr_data = json_decode($jsondata, true); return $arr_data; } catch(Exception $e) { echo "Error: " . $e->getMessage(); exit(); } } function get_previous_hashid($chain){ $lastEl = array_values(array_slice($chain, -1))[0]; return $lastEl["hashid"]; } function get_previous_index($chain){ $lastEl = array_values(array_slice($chain, -1))[0]; return $lastEl["index"]; } function get_new_hashid($previous_hashid,$index,$timestamp,$content){ $full_string = $previous_hashid.$index.$timestamp.$content; $hash = hash('sha256',$full_string); return $hash; } function read_content($content) { $arr_content = json_decode($content); return $arr_content; } } ?>
تابع نخست یعنی ()read_all، کل بلاک چین را میخواند و آن را در آرایهای چندبُعدی قرار میدهد. این حالت به منظور طراحی یک پروتوتایپ کوچک مناسب است؛ اما بدیهی است که نمیتوان از آن در محیط production که بلاک چین ممکن است تا اندازه چندین گیگابایت رشد کند، استفاده کرد.
تابعهای ()get_previous_hashid و ()get_previous_index به ما کمک میکنند که مقادیر اندیس و ID هش آخرین بلوک درج شده در زنجیره را بازیابی کنیم. ما باید این دادهها را داشته باشیم تا بتوانیم ID هش مناسب مورد استفاده از سوی بلوک بعدی که میخواهیم ملحق کنیم را محاسبه کنیم.
هر سیستم قواعد خاص خود را برای محاسبه دادههای بلوک جدید دارد. به عنوان یک قاعده در سیستم PippoCoin، قصد داریم این الزام را برقرار سازیم که هر بلوک جدید باید یک خصوصیت به نام hashid داشته باشد که از هش (SHA256) با 4 رشته تشکیل شده باشد: hashid, index و timestamp که از بلوک قبلی به دست میآیند و content که محتوای بلوک جدید است و قصد داریم ایجاد کنیم. اکنون میتوانیم درک بهتری از نخستین بلوک داشته باشیم که چرا هیچ hashid برای آن محاسبه نشده است.
تابع آخر در فایل dao.PHP به نام ()read_content به ما کمک میکند محتوای یک بلوک (فرستنده، گیرنده و مقدار) را از یک آرایه چندبعدی بخوانیم به طوری که کار با آن در مراحل بعدی برای ایجاد یک بلوک جدید راحتتر باشد.
نوشتن یک بلوک جدید
اکنون که شیء دسترسی داده ما کامل شده است، میتوانیم شروع به نوشتن اسکریپت سادهای برای آغاز کارکرد پروتوتایپ بلاک چین خود بکنیم. ما در پوشه ریشه اپلیکیشن خود یک فایل به نام chain.php ایجاد میکنیم و شروع به نوشتن کد زیر در آن میکنیم که به ما امکان میدهد محتوای کامل بلاک چین را خوانده و به تصویر بکشیم.
<?php // including basic configuration file and Data Access Object class include_once("./includes/config.php"); include_once("./includes/dao.php"); // initializing the class $dao = new DAO(); // loading the full blockchain in an array and showing it as output on the webpage $full_chain = $dao->read_all(); echo "full blockchain loaded:<br />"; echo '<pre>',print_r($full_chain["chain"],1),'</pre>'; echo "<hr />";
کد زیر نیز به خواندن اندیس و ID هش آخرین بلوک بلاک چین کمک میکند:
<?php // reading last block's hash id $previous_hashid = $dao->get_previous_hashid($full_chain["chain"]); echo "reading last block's hash id:<br />"; echo $previous_hashid; echo "<hr />"; // reading last block's index to calculate next index $previous_index = $dao->get_previous_index($full_chain["chain"]); $next_index = $previous_index+1; echo "reading last block's index to calculate next index:<br />"; echo "Last: " .$previous_index. " | Next: ".$next_index; echo "<hr />";
اکنون ما میتوانیم مقادیر بلوک جدید را محاسبه کنیم. بازیابی اندیس بلوک جدید کاملاً سرراست است. در محیط PippoCoin یک عدد صحیح وجود دارد که از بلوک قبلی تنها 1 واحد افزایش یافته است.
hashid جدید با استفاده از متد ()get_new_hashid در کلاس DAO محاسبه میشود. این مقدار یک hash به صورت (sha256) جدید بر مبنای محتوای زیر است:
- ID هش بلوک جدید
- اندیس بلوک جدید
- مُهر زمانی بلوک جدید
- محتوای بلوک جدید
<?php echo "New hashid:<br />"; $timestamp = round(microtime(true) * 1000); // example content // $content = '{"from": "network","to": "meysam","amount": 1000}'; $content = $_POST["json_data"]; $new_hashid = $dao->get_new_hashid($previous_hashid,$next_index,$timestamp,$content); echo $new_hashid; echo "<hr />";
احتمالاً متوجه شدهاید که متغیر content$ باید شامل دادههای معناداری از تراکنش ما باشد، شامل مقدار متغیر POST به نام «JSON_data» است. برای تست و کار با این محیط کوچک بلاک چین میتوانیم یک فایل جدید به نام post.php بسازیم. و آن را درون همان پوشه قرار دهیم. این فایل حاوی یک فرم ساده است که میتواند دادههای JSON را به اسکریپت chain.php ما ارسال کند. با ارسال تراکنشها به صورت دستی به بلاک چین، میتوانیم تأیید کنیم که هر بلوک جدید به طور صحیحی الحاق یافته است. فایل post.php به صوت زیر خواهد بود:
<form action="chain.php" method="post"> <textarea name="json_data"> { "from": "network", "to": "meysam", "amount": 1 } </textarea> <input type="submit"> </form>
همان طور که شاهد هستید این فرم، دادههای JSON جدیدی را به فایل chain.php ارسال میکند. تغییر دادن مقادیر From، To و Amount منجر به ثبت تراکنش متفاوتی در بلاک چین ما میشود. بدیهی است که این یک پروتوتایپ بسیار ساده است و صرفاً جهت تست ویژگیهای ابتدایی PippoCoin و تمرکز روی ساختار و قواعد یک بلاک چین مفید است. برای مشاهده کد کامل پروژه به این ریپوی گیتهاب (+) مراجعه کنید.
اگر این مطلب برایتان مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای علوم کامپیوتر
- بلاک چین چگونه کار میکند؟ — به زبان ساده
- مجموعه آموزشهای مهندسی نرمافزار
- تفاوت های بلاک چین های عمومی و خصوصی — به زبان ساده
- بلاک چین چیست و چه کاربردهایی در زندگی آینده ما دارد؟
- دستگاه ماینر بیت کوین چیست و چگونه کار می کند؟ | گام به گام و به زبان ساده
- آموزش ساخت بلاک چین (Blockchain) با پایتون — راهنمای جامع و ساده
==
درباره شبکه بیشتر توضیح بدین که این کدها در کجا ذخیره و اجرا میشود به عنوان مثال یک شخص دیگر چگونه میتواند به عنوان یک نود به بلاکچین شما متصل شود و فعالیت کند
با تشکر
سلام من آشنایی کمی دارم ولی مطالب شما خوب و گویا بود امکان داره راهنمایی کنید من چطور میتونم برنامه رو اجرا کنم چون طری در ذهن دارم که اگه کمک کنید ممنون میشم
سلام
اگر امکان دارد فایلهای این آموزش رو ضمیمه کنید
توی اسکریپت include_once(“./includes/config.php”); اینکلود شده ولی کدش نیست
سلام دوست عزیز.
آدرس ریپازیتوری مربوطه در انتهای مطلب اضافه شد.
با تشکر از توجه شما.