پرش به مطلب اصلی

مقدمه

قرارداد ماژول امنیتی اوراکل 1 یا OSM این اطمینان را می‌دهد که مقادیر جدید قیمت‌های منتشرشده از اوراکل توسط سیستم پذیرفته نمی‌شوند تا زمانی که یک زمان مشخص گذشته باشد. مقادیر از قرارداد DSValue یا هر قرارداد دیگری که رابط‌های read و peek را داشته باشد از طریق روش poke خوانده می‌شوند؛ روش‌های read و peek مقدار فعلی تغذیه قیمت را می‌دهند، و برای فراخوانی‌شان، قراردادهای دیگر باید در لیست معتبر قرار گرفته شوند. یک قرارداد ماژول امنیتی اوراکل می‌تواند تنها از یک تغذیه‌گر قیمت بخواند، بنابراین در عمل یک قرارداد ماژول امنیتی اوراکل برای هر نوع وثیقه باید دیپلوی شود.

عملکردهای کلیدی و اصطلاحات ماژول امنیتی اوراکل

چیدمان ذخیره‌سازی

  • stopped : یک پرچم از نوع uint256 که در صورت غیر صفر بودن، به روزرسانی‌های تغذیه قیمت را غیر فعال می‌کند.
  • src : آدرس DSValue که ماژول امنیتی اوراکل از آن خواهد خواند.
  • ONE_HOUR : معادل 3600 ثانیه از نوع داده uint16
  • hop : تاخیر زمانی بین فراخوانی‌های poke از نوع uint16 که به صورت پیش‌فرض ONE_HOUR است.
  • zzz: زمان آخرین به‌روزرسانی (گرد شده به نزدیک‌ترین مضرب و کوچکتر از hop)
  • cur : ساختار Feed که مقدار فعلی تغذیه را نگه می‌دارد
  • nxt : ساختار Feed که مقدار بعدی تغذیه را نگه می‌دارد
  • bud : یک نگاشت از آدرس به داده uint256 ؛ خوانش‌های تغذیه را در لیست معتبر قرار می‌دهد

متدهای عمومی

متدهای مدیریتی

این توابع تنها می‌توانند توسط آدرس‌های مجاز فراخوانی شوند (به عبارت دیگر آدرس‌های usr که wards[usr] == 1 است).

  • rely/deny : اضافه یا حذف کاربران مجاز (با انجام تغییرات در نگاشت wards)
  • stop /start : تغییر اینکه آیا تغذیه قیمت می‌تواند به‌روزرسانی شود یا خیر (با تغییر مقدار stopped)
  • change : تغییر داده برای قیمت‌ها (با تنظیم src)
  • step : تغییر فاصله بین به‌روزرسانی‌های قیمت (با تنظیم hop)
  • void : مشابه stop است، اما همچنین cur و nxt را به یک ساختار Feed با مقادیر صفر می‌رساند
  • kiss/diss : اضافه کردن/حذف مصرف‌کنندگان feed مجاز (با تغییرات در نگاشت buds)

متدهای خواندن تغذیه

این‌ متدها نیز تنها می‌توانند توسط آدرس‌هایی که در لیست معتبر قرار داده شده فراخوانی شوند

  • peek : مقدار تغذیه فعلی و یک باینری که نشان دهنده اعتبار است را برمی‌گرداند
  • peep : مقدار تغذیه بعدی را نشان می‌دهد (به عبارت دیگر چیزی که در فراخوانی poke بعدی به مقدار فعلی تبدیل می شود) و یک باینری را برمی‌گرداند که نشان می‌دهد معتبر است یا خیر
  • read : مقدار تغذیه فعلی را برمی‌گرداند؛ اگر توسط یک مکانیزم معتبر تنظیم نشده باشد، متدهای به‌روزرسانی تغذیه را برمی‌گرداند
  • poke : مقدار تغذیه فعلی را به‌روزرسانی می‌کند و مقدار بعدی خوانده می‌شود
  • ساختار Feed: یک ساختار با دو عضو از نوع uint128 شامل val و has که برای ذخیره داده‌ تغذیه استفاده می‌شوند.

مکانیسم‌ها و مفاهیم کلیدی

مکانیسم مرکزی به طور دوره‌ای یک قیمت به تعویق افتاده را برای نوع خاصی از وثیقه به سیستم MCD تأمین می‌کند. برای اینکه این کار به خوبی انجام شود، یک فعال خارجی باید به طور منظم متد poke را فراخوانی، قیمت فعلی را به‌روزرسانی کرده و قیمت بعدی را بخواند. این قرارداد زمان آخرین فراخوانی poke را در متغیر zzz ( به نزدیکترین مضرب از hop به پایین گرد شده است) پیگیری می‌کند و اجازه نمی‌دهد تابع poke فراخوانی شود تا وقتی که مقدار block.timestamp حداقل برابر zzz+hop باشد. این مقادیر از قرارداد DSValue (آدرس آن در src ذخیره می‌شود) خوانده می‌شوند. هدف این مکانیسم که به‌روزرسانی با تأخیر انجام می‌شود این است که زمان کافی برای شناسایی و واکنش به یک حمله اوراکل (مانند تنظیم قیمت وثیقه به صفر) فراهم شود. واکنش‌ها به این موضوع شامل فراخوانی stop یا void یا فعال‌سازی خاموشی اضطراری است.

قرارداد‌های دیگر، اگر در لیست معتبر قرار داده شوند، می‌توانند مقدار cur را از طریق متد‌های peek و read بررسی کنند. تابع peek یک مقدار باینری برمی‌گرداند که نشان می‌دهد که آیا مقدار برای آن تنظیم شده است یا خیر. اگر مقدار تنظیم نشده باشد، read وظیفه ‍revert را دارد. مقدار nxt می‌تواند از طریق peep بررسی شود. این قرارداد از یک ساختار مجوزدهی دوسطحی استفاده می‌کند. به این صورت که آدرس‌هایی که به 1 در wards نگاشت می‌شوند، می‌توانند شروع و متوقف شوند، src را تنظیم کنند، مقدار void را فراخوانی کنند، و خوانش‌های جدید را اضافه کنند؛ آدرس‌هایی که در ‍buds به 1 نگاشت می‌شوند می‌توانند peek، peep و read را فراخوانی کنند.

خطاهای احتمالی کاربر

اشتباه در فراخوانی peek به‌عنوان peep (یا برعکس) می‌تواند موجب اشتباهاتی شود. نام این متدها تنها یک حرف اختلاف دارد و در استفاده فعلی، هر دو "peek" و "peep" مفهوم مشابهی را دارند. این امر ممکن است باعث شود یک توسعه‌دهنده این دو را با هم اشتباه بگیرد و متد اشتباه را فراخوانی کند. اثرات چنین اشتباهاتی به‌طور طبیعی به متن وابسته هستند، اما ممکن است برای مثال هدف اصلی ماژول امنیتی اوراکل نادیده گرفته شود. یک روش یادآوری برای کمک به تمایز دادن آنها این است که چون 'k' در زبان انگلیسی قبل از 'p' می‌آید، مقداری که توسط peek برمی‌گرداند، قبل از مقداری است که توسط peep برمی‌گردد.

حالت‌های احتمالی شکست

هنگامی که poke به موقع فراخوانی نمی‌شود، قیمت‌های مخرب به سرعت وارد الگوریتم می‌شوند. به دلایل مختلفی، poke همواره و تا زمانی که block.timestamp/hop در حال افزایش است، قابل فراخوانی است بدون توجه به اینکه اخرین بار چه وقتی poke فراخوانی می‌شود. (زیرا zzz به نزدیک‌ترین مضرب از hop به پایین گرد می‌شود). این به این معناست که در واقع قرارداد تضمینی ندارد که یک بازه زمانی حداقلی hop ثانیه از زمان آخرین فراخوانی گذشته است. در واقع فقط این ضمانت را دارد که آخرین فراخوانی poke بلافاصله پس از افزایش قبلی block.timestamp/hop رخ داده باشد. بنابراین، مقدار قیمت مخرب ممکن است در زمانی کمتر از hop توسط سیستم تأیید شود.

مورد بعدی در واقع تصمیمی عمدی در طراحی است. دلیلی که در حمایت از آن آورده می‌شود این است که امکان اجرای کامل ماژول امنیتی اوراکل را به‌طور قابل اعتمادی در همان زمان و در یک تراکنش تضمین می‌کند. اینکه poke عمومی است و بنابراین توسط هر کسی قابل فراخوانی است، به کاهش نگرانی‌ها کمک می‌کند، اگرچه آنها را از بین نمی‌برد. به عنوان مثال، شلوغی شبکه می‌تواند جلوی هر کسی را از فراخوانی موفق poke بگیرد. اگر مشاهده شود که poke به‌موقع فراخوانی نشده است، اقداماتی که میشود انجام داد عبارتند از:

  • فراخوانی poke به‌ صورت شخصی و تصمیم‌گیری در مورد اینکه آیا مقدار بعدی مخرب است یا نه.
  • فراخوانی stop یا void (اولی اگر تنها nxt مخرب باشد؛ دومی اگر مقدار مخرب از قبل در cur باشد).
  • فعال‌سازی خاموشی اضطراری (اگر سلامتی سیستم به‌طور کلی آسیب دیده باشد یا اگر باور بر این باشد که اوراکل‌های شرور در زمان معقولی قابل اصلاح نیستند). در آینده، منطق قرارداد ممکن است برای کاهش این چالش (به‌طور مثال با تنظیم فقط اجازه فراخوانی poke در یک بازه زمانی کوتاه در هر دوره hop ) تنظیم شود.

حملات اجازه‌دهنده و اشتباهات تنظیمات

اقدامات مخرب مختلفی می‌تواند توسط افراد یا قراردادهای مجاز، به‌صورت تصادفی یا با توجه به مراقبت‌هایی که انجام نمی‌دهند، انجام شود:

  • لغو دسترسی قراردادهای اصلی به متدهایی که مقادیر را می‌خوانند، باعث عدم موفقیت در به‌روزرسانی قیمت می‌شود
  • لغو کامل دسترسی به قرارداد
  • تغییر src به یک قرارداد مخرب یا به چیزی که دارای رابط peek نباشد، باعث می‌شود تراکنش‌هایی که OSM آسیب‌دیده را به poke بازگرداند.
  • فراخوانی توابع مختلفی مانند stop و void به‌صورت نامناسب تنها راه حل برای این مسائل، مراقبت و دقت در مورد wards از ماژول امنیتی اوراکل است.

1 Oracle Security Module