تسلط بر بیت کوین توسط آندریاس M. آنتونوپولوس

ساخت وبلاگ

با محاکمه 10 روزه رایگان اوریلی ، به تسلط بر بیت کوین و 60K+ عناوین دیگر دسترسی پیدا کنید.

همچنین رویدادهای آنلاین زنده ، محتوای تعاملی ، مواد آماده سازی صدور گواهینامه و موارد دیگر وجود دارد.

فصل 6. شبکه بیت کوین

معماری شبکه همتا به همسالان

بیت کوین به عنوان یک معماری شبکه همتا به همتا در بالای اینترنت ساخته شده است. اصطلاح همتا به همسالان یا P2P به این معنی است که رایانه هایی که در شبکه شرکت می کنند ، همسالان یکدیگر هستند ، که همه آنها برابر هستند ، که هیچ گره "ویژه" وجود ندارد ، و همه گره ها بار ارائه را به اشتراک می گذارندخدمات شبکه. گره های شبکه در یک شبکه مش با یک توپولوژی "مسطح" به هم پیوسته اند. هیچ سرور ، سرویس متمرکز و سلسله مراتبی در شبکه وجود ندارد. گره ها در یک شبکه همتا به همسالان هم به طور همزمان با ارائه خدمات به عنوان انگیزه برای مشارکت ، خدمات ارائه می دهند و مصرف می کنند. شبکه های همسالان ذاتاً مقاوم ، غیرمتمرکز و باز هستند. نمونه بارز معماری شبکه P2P خود اینترنت اولیه بود ، جایی که گره های شبکه IP برابر بودند. معماری اینترنتی امروز سلسله مراتبی تر است ، اما پروتکل اینترنت هنوز هم جوهر شناسی مسطح خود را حفظ می کند. فراتر از بیت کوین ، بزرگترین و موفق ترین کاربرد فن آوری های P2P به اشتراک گذاری پرونده با Napster به عنوان Pioneer و Bittorrent به عنوان جدیدترین تکامل معماری است.

معماری شبکه P2P بیت کوین بسیار بیشتر از یک انتخاب توپولوژی است. بیت کوین با طراحی یک سیستم نقدی دیجیتال همتا به همتا است و معماری شبکه هم بازتاب و پایه و اساس آن ویژگی اصلی است. عدم تمرکز کنترل یک اصل طراحی اصلی است و فقط توسط یک شبکه اجماع P2P مسطح و غیرمتمرکز قابل دستیابی و نگهداری است.

اصطلاح "شبکه بیت کوین" به جمع آوری گره هایی که پروتکل بیت کوین P2P را اجرا می کنند ، اشاره دارد. علاوه بر پروتکل بیت کوین P2P ، پروتکل های دیگری مانند Stratum نیز وجود دارد که برای استخراج و کیف پول های سبک یا موبایل استفاده می شود. این پروتکل های اضافی توسط سرورهای مسیریابی Gateway ارائه می شود که با استفاده از پروتکل Bitcoin P2P به شبکه بیت کوین دسترسی پیدا می کنند و سپس آن شبکه را به گره هایی که پروتکل های دیگر را اجرا می کنند ، گسترش می دهد. به عنوان مثال ، سرورهای Stratum گره های معدن طبقه را از طریق پروتکل قشر به شبکه اصلی بیت کوین وصل می کنند و پروتکل قشر را به پروتکل بیت کوین P2P منتقل می کنند. ما از اصطلاح "شبکه بیت کوین گسترده" برای مراجعه به شبکه کلی که شامل پروتکل Bitcoin P2P ، پروتکل های معدن استخر ، پروتکل stratum و سایر پروتکل های مرتبط با اتصال اجزای سیستم بیت کوین است ، استفاده می کنیم.

گره ها و نقش ها

اگرچه گره های شبکه بیت کوین P2P برابر هستند ، بسته به عملکردی که از آنها پشتیبانی می کنند ، ممکن است نقش های مختلفی را به عهده بگیرند. یک گره بیت کوین مجموعه ای از کارکردها است: مسیریابی ، بانک اطلاعاتی blockchain ، معدن و خدمات کیف پول. یک گره کامل با هر چهار عملکرد در شکل 6-1 نشان داده شده است.

FullNodeReferenceClient_Small

شکل 6-1. گره شبکه بیت کوین با هر چهار عملکرد: کیف پول ، ماینر ، پایگاه داده کامل blockchain و مسیریابی شبکه

همه گره ها شامل عملکرد مسیریابی برای شرکت در شبکه هستند و ممکن است عملکرد دیگری را شامل شود. همه گره ها معاملات و بلوک ها را تأیید و تبلیغ می کنند و ارتباطات را با همسالان کشف و حفظ می کنند. در مثال کامل گره در شکل 6-1 ، عملکرد مسیریابی توسط یک دایره نارنجی به نام "گره مسیریابی شبکه" نشان داده شده است.

برخی از گره ها ، به نام گره های کامل ، همچنین یک کپی کامل و به روز از blockchain را حفظ می کنند. گره های کامل می توانند به صورت خودمختار و معتبر هرگونه معامله را بدون مرجع خارجی تأیید کنند. برخی از گره ها فقط زیر مجموعه ای از blockchain را حفظ کرده و معاملات را با استفاده از روشی به نام تأیید پرداخت ساده یا SPV تأیید می کنند. این گره ها به عنوان SPV یا گره های سبک شناخته می شوند. در مثال کامل گره در شکل ، عملکرد پایگاه داده blockchain با گره کامل توسط یک دایره آبی به نام "blockchain کامل" نشان داده شده است. در شکل 6-3 ، گره های SPV بدون دایره آبی کشیده می شوند و نشان می دهند که نسخه کاملی از blockchain ندارند.

گره های معدن با اجرای سخت افزار تخصصی برای حل الگوریتم اثبات کار ، برای ایجاد بلوک های جدید رقابت می کنند. برخی از گره های معدن نیز گره های کامل دارند و یک نسخه کامل از blockchain را حفظ می کنند ، در حالی که برخی دیگر گره های سبک وزن هستند که در استخراج استخر و بسته به سرور استخر برای حفظ یک گره کامل شرکت می کنند. عملکرد معدن در گره کامل به عنوان یک دایره سیاه به نام "معدن" نشان داده شده است.

کیف پول کاربر ممکن است بخشی از یک گره کامل باشد ، همانطور که معمولاً در مورد مشتری های بیت کوین دسک تاپ وجود دارد. به طور فزاینده ، بسیاری از کیف پول های کاربر ، به ویژه آنهایی که در دستگاه های محدود شده از منابع مانند تلفن های هوشمند کار می کنند ، گره های SPV هستند. عملکرد کیف پول در شکل 6-1 به عنوان یک دایره سبز به نام "کیف پول" نشان داده شده است.

علاوه بر انواع گره اصلی در پروتکل Bitcoin P2P ، سرورها و گره هایی وجود دارند که پروتکل های دیگری را اجرا می کنند ، مانند پروتکل های تخصصی استخر معدن و پروتکل های دسترسی به مشتری سبک.

شکل 6-2 رایج ترین انواع گره را در شبکه بیت کوین گسترده نشان می دهد.

شبکه بیت کوین گسترده

شبکه اصلی بیت کوین ، که پروتکل Bitcoin P2P را اجرا می کند ، بین 7000 تا 10،000 گره گوش دادن شامل نسخه های مختلفی از مشتری مرجع بیت کوین (هسته بیت کوین) و چند صد گره اجرا شده است که اجراهای مختلف پروتکل P2P بیت کوین مانند Bitcoinj را اجرا می کند ، مانند Bitcoinj. Libbitcoin ، و BTCD. درصد کمی از گره های موجود در شبکه Bitcoin P2P همچنین گره های معدن ، رقابت در فرآیند معدن ، اعتبارسنجی معاملات و ایجاد بلوک های جدید را دارند. شرکت های بزرگ مختلف با اجرای مشتری های تمام گره بر اساس مشتری اصلی بیت کوین ، با نسخه های کامل از blockchain و یک گره شبکه ، اما بدون عملکرد معدن یا کیف پول ، با شبکه بیت کوین ارتباط برقرار می کنند. این گره ها به عنوان روترهای لبه شبکه عمل می کنند و به خدمات مختلف دیگری (مبادلات ، کیف پول ، کاوشگر بلوک ، پردازش پرداخت بازرگانان) در بالای آن ساخته می شوند.

شبکه بیت کوین گسترده شامل شبکه ای است که پروتکل Bitcoin P2P را اجرا می کند ، که در ابتدا توضیح داده شد ، و همچنین گره هایی که پروتکل های تخصصی را اجرا می کنند. متصل به شبکه اصلی بیت کوین P2P تعدادی از سرورهای استخر و دروازه های پروتکل هستند که گره هایی را که پروتکل های دیگر را اجرا می کنند متصل می کنند. این گره های پروتکل دیگر بیشتر گره های معدن استخر هستند (به فصل 8 مراجعه کنید) و مشتری های کیف پول سبک وزن که یک نسخه کامل از blockchain را حمل نمی کنند.

شکل 6-3 شبکه بیت کوین گسترده را با انواع گره ها ، سرورهای دروازه ، روترهای لبه و مشتری های کیف پول و پروتکل های مختلفی که برای اتصال به یکدیگر استفاده می کنند ، نشان می دهد.

BitcoinNodeTypes

BitcoinNetwork

کشف شبکه

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

برای اتصال به یک همسالان شناخته شده ، گره ها اتصال TCP را معمولاً به بندر 8333 (درگاه ای که معمولاً به عنوان بیت کوین استفاده می شود) یا در صورت تهیه یک درگاه جایگزین ایجاد می کنند. پس از برقراری اتصال ، گره با انتقال یک پیام نسخه ، که شامل اطلاعات شناسایی اساسی است ، از جمله موارد زیر ، "دست به دست" را شروع می کند (شکل 6-4 را ببینید).

Protocol_Version ثابت است که نسخه پروتکل Bitcoin P2P را تعریف می کند مشتری "صحبت می کند" (به عنوان مثال ، 70002) NLOCALSERVICES لیستی از خدمات محلی که توسط گره پشتیبانی می شود ، در حال حاضر فقط node_network ntime زمان فعلی را اضافه می کند و آدرس IP گره از راه دور را از این رو مشاهده می کنید. گره addrme آدرس IP گره محلی ، همانطور که توسط گره محلی زیر مجموعه ای از زیر نسخه کشف شده است که نوع نرم افزاری را که روی این گره اجرا می شود نشان می دهد (به عنوان مثال ، "/satoshi:0. 9. 2. 1/ociation)blockchain گره

(برای نمونه ای از پیام شبکه نسخه به GitHub مراجعه کنید.)

گره همسالان برای تأیید و برقراری اتصال با Verack پاسخ می دهد و در صورت تمایل به اتصال و اتصال به عنوان همسالان ، به صورت اختیاری پیام نسخه خود را ارسال می کند.

چگونه یک گره جدید همسالان را پیدا می کند؟روش اول پرس و جو DNS با استفاده از تعدادی "دانه DNS" است که سرورهای DNS هستند که لیستی از آدرس های IP گره های بیت کوین را ارائه می دهند. برخی از این دانه های DNS یک لیست استاتیک از آدرس های IP گره های گوشتی پایدار بیت کوین را ارائه می دهند. برخی از بذرهای DNS پیاده سازی های سفارشی Bind (نام اینترنت برکلی Daemon) هستند که یک زیر مجموعه تصادفی را از لیستی از آدرس های گره بیت کوین جمع آوری شده توسط یک خزنده یا یک گره بیت کوین طولانی باز می گردانند. مشتری اصلی بیت کوین شامل نام پنج دانه مختلف DNS است. تنوع مالکیت و تنوع اجرای بذرهای مختلف DNS سطح یا قابلیت اطمینان بالایی را برای فرآیند اولیه بوت استراپ ارائه می دهد. در مشتری Bitcoin Core ، گزینه استفاده از دانه های DNS توسط گزینه سوئی چ-dnsseed گزینه کنترل می شود (به طور پیش فرض روی 1 تنظیم کنید تا از دانه DNS استفاده کنید).

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

NetworkHandshake

پس از برقراری یک یا چند اتصال ، گره جدید یک پیام ADDR حاوی آدرس IP خود را به همسایگان خود ارسال می کند. همسایگان به نوبه خود پیام ADDR را به همسایگان خود منتقل می کنند و اطمینان حاصل می کنند که گره تازه متصل به خوبی شناخته شده و بهتر در ارتباط است. علاوه بر این ، گره تازه متصل می تواند GetAddr را به همسایگان ارسال کند و از آنها بخواهد لیستی از آدرس های IP سایر همسالان را برگردانند. به این ترتیب ، یک گره می تواند همسالان را پیدا کند تا به آن در شبکه ارتباط برقرار کنند و تبلیغات خود را در شبکه انجام دهند تا گره های دیگر پیدا کنند. شکل 6-5 پروتکل کشف آدرس را نشان می دهد.

AddressPropagation

یک گره برای ایجاد مسیرهای متنوع در شبکه بیت کوین باید به چند همسالان مختلف متصل شود. مسیرها قابل اعتماد نیستند - بچه ها می آیند و می روند - و بنابراین گره باید به کشف گره های جدید ادامه دهد زیرا اتصالات قدیمی را از دست می دهد و همچنین در هنگام بوت شدن به گره های دیگر کمک می کند. فقط یک اتصال برای بوت استرپ مورد نیاز است ، زیرا گره اول می تواند مقدمهایی را برای گره های همسالان خود ارائه دهد و آن همسالان می توانند معرفی های بیشتری را ارائه دهند. اتصال به بیش از تعداد معدودی از گره ها همچنین غیر ضروری و هدر رفته منابع شبکه است. پس از بوت شدن ، یک گره جدیدترین اتصالات همسالان موفق خود را به یاد خواهد آورد ، به طوری که در صورت راه اندازی مجدد ، می تواند به سرعت ارتباطات خود را با شبکه همکار سابق خود برقرار کند. اگر هیچ یک از همسالان سابق به درخواست اتصال آن پاسخ دهند ، گره می تواند دوباره از گره های بذر برای بوت استرپ استفاده کند.

در گره ای که مشتری اصلی بیت کوین را اجرا می کند ، می توانید اتصالات همکار را با فرمان getPeerInfo لیست کنید:

برای غلبه بر مدیریت خودکار همسالان و مشخص کردن لیستی از آدرس های IP ، کاربران می توانند گزین ه-Connect = را ارائه دهند و یک یا چند آدرس IP را مشخص کنند. در صورت استفاده از این گزینه ، گره فقط به جای کشف و نگهداری اتصالات همسالان به طور خودکار به آدرس های IP انتخاب شده متصل می شود.

در صورت عدم وجود ترافیک در اتصال ، گره ها بطور دوره ای پیام برای حفظ اتصال ارسال می کنند. اگر یک گره بیش از 90 دقیقه در اتصال ارتباط نداشته باشد ، فرض می شود که قطع شود و یک همسالان جدید جستجو شود. بنابراین ، شبکه به صورت پویا با گره های گذرا و مشکلات شبکه تنظیم می شود ، و می تواند بدون نیاز به کنترل مرکزی ، به صورت ارگانیک رشد و کوچک شود.

گره های کامل

گره های کامل گره هایی هستند که با تمام معاملات یک blockchain کامل را حفظ می کنند. به طور دقیق تر ، آنها احتمالاً باید "گره های کامل blockchain" نامیده شوند. در سالهای اولیه بیت کوین ، همه گره ها گره های کامل بودند و در حال حاضر مشتری اصلی بیت کوین یک گره blockchain کامل است. با این حال ، در دو سال گذشته ، اشکال جدیدی از مشتریان بیت کوین معرفی شده است که یک blockchain کامل را حفظ نمی کنند اما به عنوان مشتری های سبک وزن اجرا می شوند. ما در بخش بعدی این موارد را با جزئیات بیشتری بررسی خواهیم کرد.

گره های کامل blockchain یک کپی کامل و به روز از blockchain بیت کوین را با تمام معاملات ، که آنها به طور مستقل انجام می دهند و تأیید می کنند ، حفظ می کنند ، با شروع اولین بلوک (بلوک پیدایش) و ساختن آخرین بلوک شناخته شده در شبکهبشریک گره کامل blockchain می تواند به طور مستقل و معتبر هرگونه معامله را بدون مراجعه یا اعتماد به هر گره یا منبع اطلاعات دیگر تأیید کند. گره کامل blockchain برای دریافت به روزرسانی در مورد بلوک های جدید معاملات ، که سپس آن را تأیید می کند و در کپی محلی خود از blockchain قرار می دهد ، به شبکه متکی است.

اجرای یک گره کامل blockchain ، تجربه خالص بیت کوین را به شما می دهد: تأیید مستقل از کلیه معاملات بدون نیاز به اعتماد به سیستم یا اعتماد به سیستم های دیگر. به راحتی می توان گفت که آیا شما یک گره کامل را اجرا می کنید زیرا برای ذخیره کامل blockchain به 20 گیگابایت ذخیره مداوم (فضای دیسک) نیاز دارد. اگر به دیسک زیادی احتیاج دارید و برای همگام سازی با شبکه دو تا سه روز طول می کشد ، یک گره کامل را اجرا می کنید. این قیمت استقلال کامل و آزادی از اقتدار مرکزی است.

چند پیاده سازی جایگزین از مشتریان کامل blockchain بیت کوین وجود دارد که با استفاده از زبان های مختلف برنامه نویسی و معماری های نرم افزاری ساخته شده است. با این حال ، متداول ترین اجرای مشتری مرجع Bitcoin Core است که به عنوان مشتری Satoshi نیز شناخته می شود. بیش از 90 ٪ گره های موجود در شبکه بیت کوین نسخه های مختلفی از هسته بیت کوین را اجرا می کنند. این رشته به عنوان "Satoshi" در رشته زیر نسخه ارسال شده در پیام نسخه مشخص شده و توسط فرمان GetPeerInfo همانطور که قبلاً دیدیم نشان داده شده است. به عنوان مثال ، /satoshi:0. 8. 6/.

مبادله "موجودی"

اولین کاری که یک گره کامل پس از اتصال به همسالان انجام خواهد داد ، تلاش برای ساختن یک blockchain کامل است. اگر این یک گره کاملاً جدید باشد و به هیچ وجه blockchain ندارد ، فقط یک بلوک را می شناسد ، بلوک پیدایش ، که از نظر آماری در نرم افزار مشتری تعبیه شده است. با شروع بلوک شماره 0 (بلوک پیدایش) ، گره جدید برای همگام سازی با شبکه و برقراری مجدد blockchain ، باید صدها هزار بلوک را بارگیری کند.

فرآیند همگام سازی blockchain با پیام نسخه شروع می شود ، زیرا این امر حاوی BestHeight ، ارتفاع blockchain فعلی یک گره (تعداد بلوک ها) است. یک گره پیام های نسخه را از همسالان خود مشاهده می کند ، می داند که هر کدام چند بلوک دارند و قادر به مقایسه با تعداد بلوک های موجود در blockchain خود هستند. گره های چشمگیر یک پیام GetBlocks را که حاوی هش (اثر انگشت) بلوک برتر در blockchain محلی آنها است ، مبادله می کنند. یکی از همسالان قادر به شناسایی هش دریافت شده به عنوان متعلق به بلوکی که در صدر نیست ، بلکه متعلق به یک بلوک قدیمی تر است ، بنابراین استنباط می کند که blockchain محلی خود طولانی تر از همسالان خود است.

همسایه ای که دارای blockchain طولانی تر است ، بلوک های بیشتری نسبت به گره دیگر دارد و می تواند مشخص کند که گره های دیگر نیازهای دیگر را برای "جلب" مسدود می کند. این 500 بلوک اول برای به اشتراک گذاشتن و انتقال هش خود را با استفاده از پیام Inv (موجودی) مشخص می کند. گره از دست رفته این بلوک ها با صدور یک سری از پیام های GetData که درخواست داده های بلوک کامل و شناسایی بلوک های درخواست شده با استفاده از هش از پیام Inv را بازیابی می کند ، آنها را بازیابی می کند.

به عنوان مثال ، فرض کنیم که یک گره فقط بلوک پیدایش را دارد. سپس یک پیام Inv از همسالان خود حاوی هش 500 بلوک بعدی در زنجیره دریافت می کند. این درخواست بلوک از همه همسالان متصل خود را آغاز می کند ، بار را پخش می کند و اطمینان حاصل می کند که هیچ یک از همسالان را با درخواست ها تحت الشعاع قرار نمی دهد. این گره پیگیری می کند که تعداد بلوک ها در هر اتصال همسالان "در حال حمل و نقل" هستند ، به معنای بلوک هایی که درخواست کرده است اما دریافت نشده است ، بررسی می کند که از حد مجاز نیست (max_blocks_in_transit_per_peer). به این ترتیب ، اگر به بلوک های زیادی احتیاج داشته باشد ، فقط درخواست های جدید را درخواست می کند زیرا درخواست های قبلی برآورده می شوند ، به همسالان این امکان را می دهد تا سرعت به روزرسانی ها را کنترل کنند و شبکه را تحت الشعاع قرار ندهند. با دریافت هر بلوک ، آن را به blockchain اضافه می شود ، همانطور که در فصل 7 خواهیم دید. از آنجا که blockchain محلی به تدریج ساخته می شود ، بلوک های بیشتری درخواست و دریافت می شود ، و این روند ادامه می یابد تا اینکه گره به بقیه رسید. شبکه.

این فرآیند مقایسه blockchain محلی با همسالان و بازیابی هرگونه بلوک مفقود شده در هر زمان که یک گره برای هر دوره زمانی آفلاین می شود اتفاق می افتد. این که آیا یک گره برای چند دقیقه آفلاین بوده و چند بلوک را از دست داده است یا یک ماه و چند هزار بلوک از دست رفته است ، با ارسال GetBlocks شروع می شود ، پاسخ Inv را دریافت می کند و بارگیری بلوک های گمشده را شروع می کند. شکل 6-6 پروتکل موجودی و انتشار بلوک را نشان می دهد.

گره های تأیید پرداخت ساده (SPV)

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

گره های SPV فقط هدرهای بلوک را بارگیری می کنند و معاملات موجود در هر بلوک را بارگیری نمی کنند. زنجیره ای از بلوک های حاصل ، بدون معاملات ، 1000 برابر کوچکتر از blockchain کامل است. گره های SPV نمی توانند تصویر کاملی از تمام UTXO هایی که برای هزینه در دسترس هستند ، بسازند زیرا آنها در مورد همه معاملات موجود در شبکه نمی دانند. گره های SPV معاملات را با استفاده از یک روش کمی متفاوت که به همسالان متکی است ، تأیید می کند تا نماهای جزئی از قسمت های مربوطه blockchain را در صورت تقاضا ارائه دهد.

InventorySynchronization

به عنوان یک قیاس ، یک گره کامل مانند یک توریست در یک شهر عجیب و غریب است که مجهز به نقشه دقیق هر خیابان و هر آدرس است. برای مقایسه ، یک گره SPV مانند یک توریست در یک شهر عجیب و غریب است که از غریبه های تصادفی برای جهت های نوبت به نوبه خود می خواهد در حالی که فقط یک خیابان اصلی را می شناسند. اگرچه هر دو گردشگر می توانند با بازدید از آن ، وجود خیابان را تأیید کنند ، اما توریست بدون نقشه نمی داند چه چیزی در خیابان های جانبی قرار دارد و نمی داند خیابان های دیگر چه چیزی وجود دارد. در مقابل خیابان 23 کلیسا ، گردشگر بدون نقشه نمی تواند بداند که آیا ده ها آدرس "خیابان 23 کلیسا" در شهر وجود دارد و آیا این مناسب است یا خیر. بهترین فرصت توریستی بدون نقشه این است که از افراد کافی سؤال کنید و امیدواریم که برخی از آنها در تلاش نیستند او را لگد بزنند.

تأیید پرداخت ساده با مراجعه به عمق آنها در blockchain به جای قد آنها ، معاملات را تأیید می کند. در حالی که یک گره کامل blockchain یک زنجیره کاملاً تأیید شده از هزاران بلوک و معاملات را که به پایین blockchain (به موقع) می رسد ، ایجاد می کند ، یک گره SPV زنجیره ای از همه بلوک ها را تأیید می کند (اما همه معاملات)و آن زنجیره را به معامله علاقه پیوند دهید.

به عنوان مثال ، هنگام بررسی معامله در بلوک 300،000 ، یک گره کامل 300،000 بلوک را به بلوک پیدایش پیوند می دهد و یک پایگاه داده کامل از UTXO ایجاد می کند و با تأیید اینکه UTXO ناخوشایند است ، اعتبار معامله را تعیین می کند. یک گره SPV نمی تواند اعتبار دهد که آیا UTXO مورد توجه نیست یا خیر. در عوض ، گره SPV با استفاده از یک مسیر Merkle (به درختان مرکل مراجعه کنید) بین معامله و بلوک موجود در آن ارتباط برقرار می کند. سپس ، گره SPV منتظر می ماند تا شش بلوک 300،001 تا 300006 را که در بالای بلوک حاوی معامله قرار گرفته است ، مشاهده کند و با ایجاد عمق آن در زیر بلوک های 300،006 تا 300،001 ، آن را تأیید می کند. این واقعیت که گره های دیگر در شبکه بلوک 300،000 را پذیرفتند و سپس کار لازم را برای تولید شش بلوک دیگر در بالای آن انجام دادند ، اثبات این است که این معامله دوتایی نبود.

گره SPV را نمی توان متقاعد کرد که وقتی معامله در واقع وجود ندارد ، معامله در یک بلوک وجود دارد. گره SPV با درخواست اثبات مسیر Merkle و با اعتبارسنجی اثبات کار در زنجیره بلوک ، وجود معامله را در یک بلوک ایجاد می کند. با این حال ، وجود یک معامله می تواند از یک گره SPV "پنهان" شود. یک گره SPV قطعاً می تواند ثابت کند که یک معامله وجود دارد اما نمی تواند تأیید کند که یک معامله ، مانند یک سوپاپ دوتایی از همان UTXO ، وجود ندارد زیرا سابقه ای از همه معاملات ندارد. این آسیب پذیری را می توان در یک حمله انکار سرویس یا برای حمله مضاعف علیه گره های SPV استفاده کرد. برای دفاع از این ، یک گره SPV باید به طور تصادفی به چندین گره وصل شود تا احتمال تماس با حداقل یک گره صادقانه را افزایش دهد. این نیاز به اتصال تصادفی به این معنی است که گره های SPV نیز در برابر حملات پارتیشن بندی شبکه یا حملات Sybil آسیب پذیر هستند ، جایی که آنها به گره های جعلی یا شبکه های جعلی متصل هستند و به گره های صادقانه یا شبکه واقعی بیت کوین دسترسی ندارند.

برای اکثر اهداف عملی ، گره های SPV به خوبی متصل هستند و به تعادل مناسب بین نیازهای منابع ، عملی و امنیت می پردازند. با این حال ، برای امنیت معصوم ، هیچ چیز در حال اجرای یک گره کامل blockchain نیست.

یک گره blockchain کامل با بررسی کل زنجیره هزاران بلوک زیر آن ، معامله را تأیید می کند تا تضمین کند که UTXO هزینه نشده است ، در حالی که یک گره SPV بررسی می کند که بلوک چقدر عمیق توسط تعداد انگشت شماری از بلوک های بالای آن دفن می شود.

برای دریافت سرصفحه های بلوک، گره های SPV از پیام getheaders به جای getblock استفاده می کنند. همتای پاسخ دهنده تا 2000 سرصفحه بلوک را با استفاده از یک پیام هدر ارسال می کند. در غیر این صورت، فرآیند مشابه فرآیندی است که توسط یک گره کامل برای بازیابی بلوک های کامل استفاده می شود. گره های SPV همچنین یک فیلتر برای اتصال به همتایان تنظیم می کنند تا جریان بلوک ها و تراکنش های آینده ارسال شده توسط همتایان را فیلتر کنند. هر تراکنش مورد علاقه با استفاده از یک درخواست getdata بازیابی می شود. همتا در پاسخ یک پیام tx حاوی تراکنش ها تولید می کند. شکل 6-7 همگام سازی هدرهای بلوک را نشان می دهد.

SPVSynchronization

از آنجایی که گره های SPV باید تراکنش های خاصی را بازیابی کنند تا به طور انتخابی آن ها را تأیید کنند، خطر حفظ حریم خصوصی نیز ایجاد می کنند. برخلاف گره های زنجیره بلوکی کامل، که تمام تراکنش های درون هر بلوک را جمع آوری می کنند، درخواست های گره SPV برای داده های خاص می تواند به طور ناخواسته آدرس های موجود در کیف پول خود را نشان دهد. به عنوان مثال، شخص ثالثی که یک شبکه را نظارت می کند می تواند تمام تراکنش های درخواست شده توسط یک کیف پول در یک گره SPV را پیگیری کند و از آنها برای مرتبط کردن آدرس های بیت کوین با کاربر آن کیف پول استفاده کند و حریم خصوصی کاربر را از بین ببرد.

مدت کوتاهی پس از معرفی گره های SPV/سبک، توسعه دهندگان بیت کوین قابلیتی به نام فیلترهای بلوم را برای مقابله با خطرات حریم خصوصی گره های SPV اضافه کردند. فیلترهای بلوم به گره های SPV اجازه می دهند تا زیرمجموعه ای از تراکنش ها را بدون نشان دادن دقیق آدرس هایی که به آن ها علاقه دارند، از طریق مکانیزم فیلتری که از احتمالات به جای الگوهای ثابت استفاده می کند، دریافت کنند.

فیلترهای بلوم

فیلتر شکوفه یک فیلتر جستجوی احتمالی است، راهی برای توصیف یک الگوی دلخواه بدون تعیین دقیق آن. فیلترهای بلوم روشی کارآمد برای بیان الگوی جستجو و در عین حال محافظت از حریم خصوصی ارائه می دهند. آنها توسط گره های SPV برای درخواست تراکنش هایی که با یک الگوی خاص مطابقت دارند از همتایان خود استفاده می کنند، بدون اینکه مشخص کنند دقیقاً کدام آدرس را جستجو می کنند.

در قیاس قبلی ما ، یک توریست بدون نقشه درخواست راهنمایی برای یک آدرس خاص ، "خیابان 23 کلیسا"اگر او از غریبه ها برای راهنمایی این خیابان بخواهد ، سهواً مقصد خود را فاش می کند. یک فیلتر شکوفه مانند پرسیدن است ، "آیا خیابان هایی در این محله وجود دارد که نام آنها به R-C-H ختم می شود؟"سوالی از این دست اندکی در مورد مقصد مورد نظر کمتر از درخواست "خیابان 23 کلیسا" نشان می دهدبا استفاده از این تکنیک ، یک گردشگر می تواند آدرس مورد نظر را با جزئیات بیشتر به عنوان "پایان دادن به U-R-C-H" یا جزئیات کمتر به عنوان "پایان دادن به H." مشخص کند. گردشگر با تغییر دقت جستجو ، اطلاعات کم و بیش را با هزینه دریافت نتایج کم و بیش خاص فاش می کند. اگر او از الگوی کمتری بخواهد ، آدرس های بسیار ممکن و حریم خصوصی بهتری کسب می کند ، اما بسیاری از نتایج بی ربط هستند. اگر او الگوی بسیار خاصی را بخواهد ، نتیجه کمتری کسب می کند اما حریم خصوصی را از دست می دهد.

فیلترهای Bloom با اجازه دادن به یک گره SPV برای مشخص کردن الگوی جستجو برای معاملات که می تواند به دقت یا حریم خصوصی تنظیم شود ، این عملکرد را ارائه می دهند. یک فیلتر شکوفه خاص تر نتایج دقیقی را به همراه خواهد داشت ، اما با هزینه ای که نشان می دهد چه آدرس هایی در کیف پول کاربر استفاده می شود. یک فیلتر شکوفه کمتر خاص ، داده های بیشتری را در مورد معاملات بیشتر تولید می کند ، بسیاری از آن برای گره بی ربط نیست ، اما به گره اجازه می دهد تا حریم خصوصی بهتری را حفظ کند.

یک گره SPV یک فیلتر شکوفه را به عنوان "خالی" آغاز می کند و در آن حالت فیلتر شکوفه با هیچ الگوی مطابقت نخواهد داشت. گره SPV سپس لیستی از تمام آدرس های موجود در کیف پول خود را تهیه می کند و یک الگوی جستجو را مطابق با خروجی معامله که مطابق با هر آدرس باشد ، ایجاد می کند. معمولاً ، الگوی جستجو یک اسکریپت پرداخت به عمومی-کلید-هاش است که اسکریپت قفل مورد انتظار است که در هر معامله ای که به کلیدهای عمومی-هاش (آدرس) پرداخت می شود ، وجود داشته باشد. اگر گره SPV در حال پیگیری تعادل یک آدرس P2SH باشد ، در عوض ، الگوی جستجو یک اسکریپت پرداخت به اسکریپت-هاش خواهد بود. گره SPV سپس هر یک از الگوهای جستجو را به فیلتر Bloom اضافه می کند ، به طوری که فیلتر Bloom می تواند در صورت وجود در یک معامله ، الگوی جستجو را تشخیص دهد. سرانجام ، فیلتر Bloom به همسالان ارسال می شود و همکار از آن برای مطابقت با معاملات برای انتقال به گره SPV استفاده می کند.

فیلترهای Bloom به عنوان یک آرایه با اندازه متغیر از رقم های باینری N (یک قسمت بیت) و تعداد متغیر عملکرد هش M اجرا می شوند. توابع هش به گونه ای طراحی شده اند که همیشه خروجی بین 1 تا n تولید می کنند ، مطابق با آرایه ای از رقم های باینری. توابع هش به صورت قطعی تولید می شوند ، به طوری که هر گره ای که یک فیلتر شکوفه را اجرا می کند ، همیشه از همان توابع هش استفاده می کند و برای یک ورودی خاص نتایج مشابهی کسب می کند. با انتخاب فیلترهای شکوفه طول (N) و تعداد متفاوتی از توابع هش ، فیلتر شکوفه را می توان تنظیم کرد و سطح دقت و در نتیجه حریم خصوصی را تغییر داد.

در شکل 6-8 ، ما از یک آرایه بسیار کوچک از 16 بیت و مجموعه ای از سه کارکرد هش استفاده می کنیم تا نحوه عملکرد فیلترهای شکوفه را نشان دهیم.

Bloom1

فیلتر شکوفه به گونه ای تنظیم می شود که آرایه بیت ها همه صفرها هستند. برای افزودن الگویی به فیلتر Bloom ، این الگوی توسط هر عملکرد هش به نوبه خود هشدار داده می شود. استفاده از اولین عملکرد هش در ورودی منجر به تعداد بین 1 و N. می شود. بیت مربوطه در آرایه (ایندکس شده از 1 تا n) یافت می شود و روی 1 تنظیم می شود و در نتیجه خروجی عملکرد هش را ضبط می کند. سپس از عملکرد هش بعدی برای تنظیم بیت دیگر و غیره استفاده می شود. پس از اعمال تمام توابع هش M ، الگوی جستجو در فیلتر شکوفه به عنوان بیت های M که از 0 به 1 تغییر یافته است "ضبط می شود".

شکل 6-9 نمونه ای از اضافه کردن الگوی "A" به فیلتر شکوفه ساده است که در شکل 6-8 نشان داده شده است.

اضافه کردن الگوی دوم به سادگی تکرار این فرآیند است. این الگوی توسط هر عملکرد هش به نوبه خود هشدار داده می شود و نتیجه با تنظیم بیت ها به 1 ثبت می شود. توجه داشته باشید که به عنوان یک فیلتر شکوفه پر از الگوهای بیشتر است ، نتیجه عملکرد هش ممکن است با کمی که در حال حاضر روی 1 تنظیم شده است ، همزمان باشد ، در این صورت بیت تغییر نمی کند. در اصل ، هرچه الگوهای بیشتر روی بیت های همپوشانی ضبط می شوند ، فیلتر شکوفه شروع به اشباع می شود با بیت های بیشتر که روی 1 تنظیم شده و دقت فیلتر کاهش می یابد. به همین دلیل فیلتر یک ساختار داده احتمالی است - با افزودن الگوهای بیشتر ، دقیق تر می شود. دقت به تعداد الگوهای اضافه شده در مقابل اندازه آرایه بیت (N) و تعداد توابع هش (M) بستگی دارد. یک آرایه بیت بزرگتر و عملکردهای هش بیشتر می توانند الگوهای بیشتری را با دقت بالاتر ثبت کنند. آرایه بیت کوچکتر یا عملکردهای هش کمتری الگوهای کمتری را ثبت می کند و دقت کمتری تولید می کند.

Bloom2

شکل 6-10 نمونه ای از اضافه کردن الگوی دوم "B" به فیلتر شکوفه ساده است.

Bloom3

برای آزمایش اینکه آیا یک الگوی بخشی از فیلتر شکوفه است ، این الگوی توسط هر عملکرد هش هاش می شود و الگوی بیت حاصل در برابر آرایه بیت آزمایش می شود. اگر تمام بیت های نمایه شده توسط توابع هش روی 1 تنظیم شود ، احتمالاً این الگوی در فیلتر Bloom ثبت می شود. از آنجا که ممکن است بیت ها به دلیل همپوشانی از الگوهای مختلف تنظیم شوند ، جواب مشخص نیست ، اما احتمالاً احتمالی است. به عبارت ساده ، یک بازی مثبت فیلتر شکوفه یک "شاید ، بله" است.

شکل 6-11 نمونه ای از آزمایش وجود الگوی "x" در فیلتر شکوفه ساده است. بیت های مربوطه روی 1 تنظیم شده اند ، بنابراین الگوی احتمالاً یک مسابقه است.

Bloom4

شکل 6-11. آزمایش وجود الگوی "x" در فیلتر شکوفه. نتیجه این یک مسابقه مثبت احتمالی است ، به معنی "شاید".

در مقابل ، اگر الگویی در برابر فیلتر شکوفه آزمایش شود و هر یک از بیت ها روی 0 تنظیم شود ، این ثابت می کند که این الگوی در فیلتر شکوفه ثبت نشده است. نتیجه منفی یک احتمال نیست ، بلکه یقین است. به زبان ساده ، یک مسابقه منفی در فیلتر شکوفه "قطعاً نه!"

شکل 6-12 نمونه ای از آزمایش وجود الگوی "y" در فیلتر شکوفه ساده است. یکی از بیت های مربوطه روی 0 تنظیم شده است ، بنابراین این الگوی قطعاً یک مسابقه نیست.

Testing the existence of patte “Y” in the bloom filter. The result is a definitive negative match, meaning “Definitely Not!”

شکل 6-12. آزمایش وجود الگوی "y" در فیلتر شکوفه. نتیجه یک مسابقه منفی قطعی است ، به معنای "قطعاً نه!"

اجرای بیت کوین از فیلترهای Bloom در پیشنهاد بهبود بیت کوین 37 (BIP0037) شرح داده شده است. به پیوست B مراجعه کنید یا به GitHub مراجعه کنید.

فیلترهای شکوفه و به روزرسانی موجودی

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

در پاسخ به پیام GetData از گره ، همسالان یک پیام Merkleblock را ارسال می کنند که فقط شامل هدرهای بلوک برای بلوک های مطابق با فیلتر و یک مسیر مرکل (به درختان مرکل) برای هر معامله تطبیق می یابد. همسالان سپس پیام های TX حاوی معاملات مطابق با فیلتر را نیز ارسال می کند.

گره تنظیم شده فیلتر Bloom می تواند با ارسال پیام FilterAdd به طور تعاملی الگوهای را به فیلتر اضافه کند. برای پاک کردن فیلتر Bloom ، گره می تواند یک پیام FilterClear ارسال کند. از آنجا که امکان حذف یک الگوی از یک فیلتر شکوفه امکان پذیر نیست ، اگر یک الگوی دیگر مورد نظر نباشد ، یک گره باید یک فیلتر شکوفه جدید را پاک و مجدداً ارسال کند.

استخرهای معامله

تقریباً هر گره در شبکه بیت کوین یک لیست موقت از معاملات تأیید نشده به نام استخر حافظه ، Mempool یا استخر معامله را در خود جای داده است. گره ها از این استخر برای پیگیری معاملات شناخته شده در شبکه استفاده می کنند اما هنوز در blockchain گنجانده نشده اند. به عنوان مثال ، گره ای که کیف پول کاربر را در اختیار دارد ، از استخر معامله برای ردیابی پرداخت های ورودی به کیف پول کاربر که در شبکه دریافت شده است استفاده می کند اما هنوز تأیید نشده است.

با دریافت و تأیید معاملات ، آنها به استخر معامله اضافه می شوند و برای انتشار در شبکه به گره های همسایه منتقل می شوند.

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

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

هر دو استخر معامله و استخر یتیم (که در آن اجرا شده است) در حافظه محلی ذخیره می شوند و در ذخیره مداوم ذخیره نمی شوند. در عوض ، آنها به صورت پویا از پیام های شبکه ورودی جمع می شوند. با شروع گره ، هر دو استخر خالی هستند و به تدریج با معاملات جدید دریافت شده در شبکه جمع می شوند.

برخی از پیاده سازی های مشتری بیت کوین همچنین یک پایگاه داده UTXO یا استخر UTXO را حفظ می کنند ، که مجموعه ای از تمام خروجی های ناخواسته در blockchain است. اگرچه نام "استخر UTXO" شبیه به استخر معامله است ، اما مجموعه ای از داده ها را نشان می دهد. بر خلاف معامله و استخرهای یتیم ، استخر UTXO خالی نشده است ، اما در عوض شامل میلیون ها مدخل خروجی معاملات ناشناخته ، از جمله برخی از قدمت های مربوط به سال 2009 است. استخر UTXO ممکن است در حافظه محلی یا به عنوان یک جدول پایگاه داده فهرست بندی شده در ذخیره سازی مداوم قرار گیرد. بشر

در حالی که استخرهای معامله و یتیم نمایانگر دیدگاه محلی یک گره واحد هستند و بسته به زمان شروع یا راه اندازی مجدد گره ممکن است از گره به گره متفاوت باشد ، استخر UTXO بیانگر اجماع نوظهور شبکه است و بنابراین بین گره ها کمی متفاوت خواهد بود. علاوه بر این ، استخرهای معامله و یتیم فقط حاوی معاملات تأیید نشده هستند ، در حالی که استخر UTXO فقط حاوی خروجی های تأیید شده است.

پیام های هشدار

پیام های هشدار یک عملکرد به ندرت استفاده می شوند ، اما با این وجود در اکثر گره ها اجرا می شوند. پیام های هشدار "سیستم پخش اضطراری" بیت کوین هستند ، ابزاری که توسعه دهندگان اصلی بیت کوین می توانند یک پیام متنی اضطراری را به همه گره های بیت کوین ارسال کنند. این ویژگی به منظور اجازه دادن به تیم توسعه دهنده اصلی به همه کاربران بیت کوین از یک مشکل جدی در شبکه بیت کوین ، مانند یک اشکال مهم که نیاز به اقدام کاربر دارد ، اطلاع می دهد. سیستم هشدار فقط بارها مورد استفاده قرار گرفته است ، مهمترین آنها در اوایل سال 2013 هنگامی که یک اشکال مهم در پایگاه داده باعث ایجاد یک چنگال چند بلوک در blockchain بیت کوین شد.

پیام های هشدار توسط پیام هشدار پخش می شوند. پیام هشدار شامل چندین زمینه است ، از جمله:

هشدار شناسایی شده به گونه ای که هشدارهای تکراری را می توان انقضاء کرد و پس از آن هشدار از زمان پایان می یابد که هشدار را نباید به مینور منتقل کرد ، حداکثر دامنه نسخه های پروتکل بیت کوین که این هشدار برای زیر نسخه نرم افزار مشتری اعمال می شوداین هشدار در مورد اولویت اولویت هشدار ، در حال حاضر استفاده نشده است

هشدارها به صورت رمزنگاری توسط یک کلید عمومی امضا می شوند. کلید خصوصی مربوطه توسط چند عضو منتخب تیم توسعه اصلی برگزار می شود. امضای دیجیتال تضمین می کند که هشدارهای جعلی در شبکه پخش نمی شود.

هر گره ای که این پیام هشدار را دریافت می کند ، آن را تأیید می کند ، انقضا را بررسی می کند و آن را به همه همسالان خود می دهد ، بنابراین انتشار سریع در کل شبکه را تضمین می کند. علاوه بر انتشار هشدار ، گره ها ممکن است یک عملکرد رابط کاربری را برای ارائه هشدار به کاربر پیاده سازی کنند.

در مشتری Bitcoin Core ، هشدار با گزینه Comman d-Lin e-alerTnotify پیکربندی شده است ، که یک دستور برای اجرای هنگام دریافت هشدار را مشخص می کند. پیام هشدار به عنوان یک پارامتر به دستور AlertNotify منتقل می شود. معمولاً ، دستور AlertNotify برای ایجاد یک پیام ایمیل به مدیر گره ، حاوی پیام هشدار تنظیم شده است. در صورت اجرای آن ، هشدار به عنوان یک گفتگوی پاپ آپ در رابط کاربری گرافیکی (Bitcoin-QT) نمایش داده می شود.

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

اکنون با پلت فرم یادگیری O'Reilly ، Bitcoin را تسلط کنید.

اعضای O'Reilly آموزش آنلاین آنلاین ، به علاوه کتاب ، فیلم و محتوای دیجیتالی را از نزدیک به 200 ناشر تجربه می کنند.

فارکس در ایران...
ما را در سایت فارکس در ایران دنبال می کنید

برچسب : نویسنده : محمدرضا گلزار بازدید : 58 تاريخ : شنبه 5 فروردين 1402 ساعت: 2:36