Децентрализирана архитектура на приложения: Обратни модели, модели за сигурност и дизайн

Децентрализираните приложения или ÐApps изискват специален дизайн на системата, за да се постигне висока сигурност и надеждност. В тази статия ще разгледам няколко основни принципа за правилното проектиране и прилагане на бекграунд и интелигентни договори за децентрализирани приложения, като взема Ethereum за основен пример, въпреки че голяма част от него ще се прилага за EOS, Tron и други децентрализирани платформи за данни.

Акценти на статията:

  • Как да съхранявате частни ключове на задния край без опасения за сигурността
  • Как правилно да проектирате интелигентни договори и какво да „децентрализирате“
  • Децентрализирани и полуцентрализирани примери за архитектура на приложения
  • Как да се справим с неща от ниско ниво като зареждане на мрежата и повреди

Ще бъде голямо, нека го направим!

Децентрализирани програми и блокчейн

Въпреки факта, че блокчейн днес е изправен пред много трудности при приемането и регулирането, това е един вид технология, която остава тук, независимо дали това е блокчейн, хешграф, темп или друга технология за разпространена книга, която все още предстои, независимо от алгоритъма.

Основната стойност, която блокчейнът и другите подобни технологии носят, могат да се обобщят по следния начин: те позволяват на хората да пишат и да изпълняват програми, които на практика не могат да бъдат променени след създаването, нито да бъдат подправени по време на изпълнение. С други думи, тези програми винаги се изпълняват както са проектирани и никоя партия не може да повлияе на тяхното поведение.

Това определение е валидно за много криптовалути, които съществуват днес, ако ги считаме за програми, които определят как могат да се прехвърлят монети напред и назад. Това обяснява и защо криптовалутите и многото видове токени имат реална стойност: те не могат да бъдат генерирани от въздух от техните дефинирани „основни програми“.

Платформите Ethereum / EOS / Tron /…, за разлика от Bitcoin, прилагат по-сложен програмен слой, който от своя страна реализира средата за изпълнение, позволяваща на всеки да напише свои собствени децентрализирани програми на върха на платформата. Тези програми, дефинирани от потребителя, винаги се изпълняват както са проектирани, без изключения и тяхната сигурност е гарантирана от платформата.

Децентрализирани приложения

Тези сигурни и неизменяеми програми, работещи в децентрализирана мрежа в комбинация с традиционните технологии отпред и отзад, са това, което днес наричаме децентрализирани приложения (ÐApps). Чрез някои от тях могат да бъдат полуцентрализирани, голяма част от дейностите в наистина децентрализираното приложение трябва да се осъществяват извън контрола на централната партия.

Ако някой ме помоли да нарисувам как работят DApps днес, вероятно щях да нарисувам това

За да си представим това, което днес наричаме децентрализирани приложения, вземете за пример всеки съществуващ централизиран уеб ресурс като _YouTube_ или _Instagram_ и си представете, че вместо защитен с парола централизиран акаунт, вашата „криптовалута“ е свързана с уеб / мобилния ресурс.

Това ви предоставя софтуерът на Wallet. Частният ключ от тази идентичност (тайна, притежаваща която, можете да действате от името на тази идентичност) се съхранява на вашето локално устройство и никога не излиза в интернет, като никой не може да контролира тази идентичност, освен вас. С тази идентичност можете да извършвате различни действия както в централизирани (уеб ресурс, контролиран от централен орган), така и децентрализирани (което е различна мрежа от традиционните www, чиято цел е да се премахне централната власт) мрежи, като използвате уебсайта като точка за достъп и / или като графичен потребителски интерфейс. Целият смисъл на тази „криптовалута“ е, че вашите действия са защитени криптографски и никой не е в състояние да промени това, което сте подписали, нито вашия подпис.

Днес възможностите за изчисление и съхранение на децентрализирани мрежи, устойчиви на откази като Ethereum, EOS или Tron, са ограничени. Ако те са мащабируеми, бихме могли да използваме децентрализирани мрежи, за да съхраним цялото децентрализирано приложение, включително неговия графичен потребителски интерфейс, данни и бизнес логика. В този случай бихме нарекли тези приложения наистина децентрализирани / разпределени.

Тъй като днес тези мрежи не са мащабируеми, ние комбинираме различни подходи за постигане на максимално ниво на децентрализация на нашите приложения. „Традиционният“ заден край, тъй като знаем, че не отива никъде. Например:

  • Използваме back end, за да хостваме предния край за децентрализирано приложение.
  • Използваме back end за интеграция с всякакви други съществуващи технологии и услуги. Реалните приложения от световна класа не могат да живеят в изолирана среда.
  • Използваме задния край, за да съхраняваме и обработваме всичко достатъчно голямо за децентрализирана мрежа (по-специално blockchain). На практика цялото приложение и неговата бизнес логика се съхраняват някъде по света, с изключение само на блокчейн частта. Да не говорим, IPFS и подобни слоеве за съхранение не могат да гарантират достъпността на файловете, следователно не можем да разчитаме на тях, без да хостваме и самите файлове. С други думи, винаги има нужда от специализиран работещ сървър.

Няма начин да се изгради сигурно и частично децентрализирано приложение, без да се използва солиден заден край от днес и целият смисъл на тази статия е да се обясни как да направите това правилно.

(De) централизация и маркери

Така се случва, че почти всички децентрализирани приложения днес са изградени около така наречените токени - криптовалути, изградени по поръчка (или просто просто клонирани), които задвижват определено децентрализирано приложение. Токените са просто програмируема валута или активи, това е всичко.

Докато интелигентните договори за токени определят как потребителите могат да прехвърлят маркери, смарт приложенията за приложения могат да разширят всичко, което липсва в интелигентните договори за маркери. И двата интелигентни договора работят върху децентрализирани мрежи

Обикновено маркерът е „интелигентен договор“ (персонализирана програма), написан отгоре на децентрализираната платформа като Ethereum. Притежавайки някои маркери, вие по принцип можете да получите различни услуги на уеб ресурс или мобилно приложение и да търгувате този жетон за нещо друго. Ключовият момент тук е, че маркерът живее самостоятелно и не се контролира от централен орган.

Има много примери за приложения, които са изградени около токени: от множество колекционерски игри като CryptoKitties (ERC721 токени) до по-ориентирани към услуги приложения като LOOM Network или дори браузъри като Brave и игрални платформи като DreamTeam (съвместими с ERC20 маркери).

Самите разработчици определят и решават колко контрол ще имат (или няма да имат) над своите приложения. Те могат да изграждат бизнес логиката на цялото приложение на базата на интелигентни договори (като CryptoKitties направи), или, изобщо, не могат да използват интелигентни договори, като централизират всичко на своите сървъри. Най-добрият подход обаче е някъде по средата.

Заден край за децентрализирани мрежи

От техническа гледна точка трябва да има мост, който свързва маркери и други интелигентни договори с уеб / мобилното приложение.

В днешните напълно децентрализирани приложения, където клиентите си взаимодействат директно с интелигентни договори, този мост е стеснен до възможности за JSON RPC API на публични API или пулове от възли като Infura, които от своя страна са принудени да съществуват поради факта, че не всяко устройство може стартирайте и поддържайте своя отделен мрежов възел. Този API обаче осигурява само основен и много тесен набор от функции, които едва позволяват извършване на прости заявки, нито ефективно агрегиране на данни. Поради това в крайна сметка персонализираният бек-енд стартира, което прави приложението полуцентрализирано.

Цялото взаимодействие с децентрализираната мрежа може да бъде ограничено до само една или две точки, в зависимост от нуждите на приложението:

  1. Слушане на мрежови събития (като прехвърляне на маркери) / четене на състоянието на мрежата.
  2. Публикуване на транзакции (извикване на променящи състоянието функции на смарт договори като прехвърляне на жетони).

Изпълнението на двете точки е доста сложно, особено ако искаме да изградим сигурно и надеждно бек-енд решение. Ето основните моменти, които ще разделим по-долу:

  • На първо място, в Ethereum извличането на събития не е готово за производство извън кутията. Поради множество причини: мрежовите възли могат да се провалят, докато извличат голям брой събития, събитията могат да изчезнат или да се променят поради мрежови вилици и т.н. Трябва да изградим абстракционен слой, за да синхронизираме събития от мрежата и да гарантираме надеждната им доставка.
  • Същото и за публикуването на транзакции, ние трябва да абстрахираме ниските нива на Ethereum, като броячи без значение и оценки на газ, както и препубликуване на транзакции, осигурявайки надежден и стабилен интерфейс. Нещо повече, публикуването на транзакции предполага използването на частни ключове, което изисква разширена защита в заден план.
  • Сигурност. Ще се заемем сериозно с това и ще се изправим пред факта, че е невъзможно да гарантираме, че частните ключове няма да бъдат компрометирани в заден план. За щастие има подход за създаване на децентрализирано приложение, без дори да е необходимо задните акаунти да бъдат силно защитени.

В нашата практика всичко това ни накара да създадем стабилно бек-енд решение за Ethereum, което наричаме Ethereum Gateway. Той абстрахира други микросервизи от забавлението на Ethereum и осигурява надежден API за работа с него.

Като бързоразвиващ се стартъп не можем да разкрием цялостното решение (все още) по очевидни причини, но аз ще споделя всичко, което трябва да знаете, за да може вашето децентрализирано приложение да работи безупречно. Ако обаче имате някакви конкретни въпроси или запитвания, не се колебайте да се свържете с мен. Коментарите към тази статия също са много оценени!

Мониторинг на задния край за Ethereum. Мониторът демонстрира дейности главно по отношение на повтарящата се функция за таксуване (въпреки че можете да видите върхове, които се случват на всеки час).

Децентрализирана архитектура на приложенията

Тази част от статията силно зависи от нуждите на конкретно децентрализирано приложение, но ще се опитаме да подредим някои основни модели на взаимодействие, върху които са изградени тези приложения (ÐPlatform = Децентрализирана платформа = Ethereum / EOS / Tron / каквото и да е):

Клиент ⬌ Ð Платформа: напълно децентрализирани приложения.

Клиентът (браузър или мобилно приложение) разговаря директно с децентрализираната платформа с помощта на Ethereum “wallet” софтуер като Metamask, Trust или хардуерни портфейли като Trezor или Ledger. Примери за DApps изградени по този начин са CryptoKitties, делегирано обаждане на Loom, самите крипто портфейли (Metamask, Trust, Tron Wallet и други), децентрализирани криптовалути като Etherdelta и т.н.

ÐPlatform ⬌ Клиент ⬌ Back End ⬌ ÐPlatform: централизирани или полуцентрализирани приложения.

Взаимодействието на клиента с децентрализираната платформа и сървъра има малко общо. Добрият пример за това е всяка (централизирана) криптовалута днес, като BitFinex или Poloniex: валутите, с които търгувате на борсите, просто се записват в традиционната база данни. Можете да „попълните” баланса на базата си данни, като изпратите активи на конкретен адрес (ÐPlatform ⬌ Клиент) и след това изтеглите активи след някои действия в приложението (Back End ⬌ ÐPlatform), но всичко, което правите по отношение на „ÐApp“ самия (клиент ⬌ Back End) не предполага вашето пряко взаимодействие с ÐPlatform.

Друг пример е Etherscan.io, който използва полуцентрализиран подход: можете да извършвате всички полезни децентрализирани действия там, но самото приложение просто няма смисъл без цялостния им заден край (Etherscan непрекъснато синхронизира транзакции, анализира данни и ги съхранява, в крайна сметка предоставя цялостен API / потребителски интерфейс).

Нещо между: все още, централизирани или полуцентрализирани приложения.

Горните подходи комбинирани. Например, можем да имаме приложение, което предоставя различни услуги в замяна на криптовалута, което ви позволява да влизате и да подписвате информация с вашата криптовалута.

Надяваме се, моделът на взаимодействие на напълно децентрализираните приложения (клиент ⬌ ÐPlatform) не повдига въпроси. Като разчитате на такива невероятни услуги като Infura или Trongrid, можете просто да създадете приложение, което изобщо не изисква сървър. Почти всички клиентски библиотеки като Ethers.js за Ethereum или Tron-Web for Tron могат да се свързват с тези обществени услуги и да комуникират с мрежата. За по-сложни запитвания и задачи обаче може да се наложи да разпределите свой собствен сървър така или иначе.

Останалите модели на взаимодействие, които включват задния край, правят нещата по-интересни и сложни. За да поставим всичко това на снимка, нека си представим случай, когато задният ни край реагира на някакво събитие в мрежата. Например, потребителят публикува транзакция с надбавки, която ни дава разрешение да ги таксуваме. За да направим такса, трябва да публикуваме транзакцията за такса в отговор на събитието за излъчени надбавки:

Примерен поток на реакцията на сървъра върху действието на потребителя в децентрализираната мрежа

От гледна точка на задния край ето какво се случва:

  1. Ние слушаме определено мрежово събитие, като непрекъснато оглеждаме мрежата.
  2. След като получим събитие, ние извършваме някаква бизнес логика и след това решаваме да публикуваме транзакция в отговор.
  3. Преди да публикуваме транзакцията, искаме да гарантираме, че тя вероятно ще бъде добита (в Ethereum, успешната оценка на газ за транзакция означава, че няма грешки спрямо текущото състояние на мрежата). Не можем обаче да гарантираме, че транзакцията ще бъде добита успешно.
  4. Използвайки частен ключ, ние подписваме и публикуваме транзакцията. В Ethereum също трябва да определим цената на газа и лимита на газ на транзакцията.
  5. След като публикуваме транзакцията, ние непрекъснато изследваме мрежата за нейния статус.
  6. Ако отнема твърде много време и не можем да получим статуса на транзакцията, трябва да я публикуваме отново или да задействаме „сценарий на неуспех“. Транзакциите могат да бъдат загубени по различни причини: претоварване на мрежата, отпадане на връстници, увеличаване на натоварването на мрежата и др. В Ethereum можете също да помислите за повторно подписване на транзакция с различна (действителна) цена на газ.
  7. След като най-накрая добием транзакцията си, можем да изпълним повече бизнес логика, ако е необходимо. Например, можем да уведомяваме други резервни услуги за факта на приключване на транзакцията. Също така, помислете да изчакате няколко потвърждения, преди да вземете окончателни решения относно транзакцията: мрежата се разпространява и следователно резултатът може да се промени за секунди.

Както можете да видите, става много! Приложението ви обаче може да не изисква някои от тези стъпки, в зависимост от това, което се опитвате да постигнете. Но изграждането на здрав и стабилен заден край изисква решение за всички споменати по-горе проблеми. Нека да разбием това

Децентрализирани приложения Back End

Тук искам да подчертая някои от въпросите, които пораждат повечето въпроси, а именно:

  • Слушане на мрежови събития и четене на данни от мрежата
  • Публикуване на транзакции и как да го направите безопасно

Слушане на мрежови събития

В Ethereum, както и в други децентрализирани мрежи, концепция за интелигентни договорни събития (или дневници на събития, или просто регистрационни файлове) позволява на приложенията извън веригата да са наясно какво се случва в blockchain. Тези събития могат да бъдат създадени от разработчици на интелигентни договори във всяка точка на кода на смарт договора.

Например, в рамките на добре познатия стандарт за токени ERC20, всеки трансфер на токен трябва да регистрира събитието за прехвърляне, като по този начин уведомява външните приложения да знаят, че има прехвърляне на маркер. Чрез „слушане“ на тези събития можем да извършим всякакви (повторни) действия. Например, някои мобилни криптовалути ви изпращат известие с push / имейл, когато жетоните се прехвърлят на вашия адрес.

Всъщност няма надеждно решение за слушане на мрежови събития извън кутията. Различните библиотеки ви позволяват да проследявате / слушате събития, но има много случаи, когато нещо може да се обърка, което води до загубени или необработени събития. За да избегнем загуба на събития, трябва да изградим персонализиран заден край, който ще поддържа процеса на синхронизиране на събитията.

В зависимост от вашите нужди, изпълнението може да варира. Но за да ви покажа снимка тук е една от опциите как можете да изградите надеждна доставка на събития Ethereum от гледна точка на архитектурата на микросервизите:

Надеждна доставка на събития Ethereum до всички бек-енд услуги

Тези компоненти работят по следния начин:

  1. Услугата за синхронизиране на събития за справка постоянно оглежда мрежата, опитвайки се да извлече нови събития. След като има някои нови събития на разположение, той изпраща тези събития до шината на съобщенията. След успешно изпращане на събитие в шината на съобщенията, що се отнася до blockchain, можем да запишем блока на последното събитие, за да поискаме нови събития от този блок следващия път. Имайте предвид, че извличането на твърде много събития наведнъж може да доведе до винаги неуспешни заявки, така че трябва да ограничите броя на събитията / блоковете, които поискате от мрежата.
  2. Шината на съобщенията (например Rabbit MQ) насочва събитието към всяка опашка, която беше настроена поотделно за всяка услуга в края. Преди публикуването на събитията услугата за синхронизиране на събитията определя маршрутизиращия ключ (например, интелигентен адрес на договор + тема на събитието), докато потребителите (други услуги за задния край) създават опашки, които са абонирани само за конкретни събития.

В резултат на това всяка резервна услуга получава само онези събития, от които се нуждае. Освен това шината на съобщенията гарантира доставката на всички събития, след като бъдат публикувани в него.

Разбира се, можете да използвате нещо друго вместо шината за съобщения: HTTP обратни обаждания, сокети и т.н. В този случай ще трябва сами да разберете как да гарантирате доставката на обратни повиквания: да управлявате експоненциални / персонализирани повторни обаждания, да прилагате персонализиран мониторинг и скоро.

Издателски транзакции

Има няколко стъпки, които трябва да извършим, за да публикуваме транзакция в децентрализираната мрежа:

  1. Подготовка на транзакцията. Заедно с данните за транзакциите, тази стъпка предполага да поискате състоянието на мрежата, за да разберете дали тази транзакция е валидна и ще бъде извлечена (оценка на газ в Ethereum) и поредния номер на транзакцията (без значение в Ethereum). Някои от библиотеките се опитват да направят това под капака, но тези стъпки са важни.
  2. Подписване на транзакцията. Тази стъпка предполага използването на частния ключ. Най-вероятно тук ще искате да вградите решение за сглобяване на частен ключ (например).
  3. Публикуване и повторно публикуване на транзакцията. Един от ключовите моменти тук е, че публикуваната транзакция винаги има шанс да се изгуби или да отпадне от децентрализираната мрежа. Например в Ethereum, публикуваната транзакция може да бъде отменена, ако цената на газа в мрежата внезапно се увеличи. В този случай трябва да преиздадете транзакцията. Освен това може да искате да публикувате транзакцията с други параметри (поне с по-висока цена на газ), за да я извлечете възможно най-бързо. По този начин повторното публикуване на транзакцията може да означава повторно подписване, ако транзакцията за замяна не е била предварително подписана (с различни параметри).
Визуализирани са горните точки относно публикуването на транзакции в Ethereum

Използвайки горните подходи можете да завършите изграждането на нещо подобно на нещата, които са представени в диаграмата на последователностите по-долу. На тази конкретна диаграма на последователността демонстрирам (като цяло!) Как повтарящото се фактуриране на блокчейн (има още в свързана статия):

  1. Потребителят изпълнява функция в интелигентен договор, което в крайна сметка позволява на задния край да извърши успешна транзакция за таксуване.
  2. Служба за обратно обслужване, отговорна за конкретна задача, изслушва събирането на надбавки и публикува транзакция за таксуване.
  3. След като транзакционната транзакция бъде изчерпана, тази услуга за връщане на крайната отговорност, отговаряща за конкретна задача, получава събитие от мрежата на Ethereum и изпълнява известна логика (включително определяне на следващата дата на таксуване).
Общата диаграма на последователността за това как работи повтарящото се фактуриране в blockchain, демонстрирайки взаимодействието между бек-енд услугите и мрежата на Ethereum

Back End сигурност и интелигентни договори

Публикуването на транзакции винаги включва използване на частен ключ. Може би се чудите дали е възможно да запазите частните ключове. Е, да и не. Има множество сложни стратегии и различни видове софтуер, които позволяват да съхранявате частни ключове в задната част доста сигурно. Някои решения за съхранение на частни ключове използват георазпределени бази данни, докато други дори предлагат използването на специален хардуер. Във всеки случай обаче най-уязвимата точка на полуцентрализирано приложение е, когато частният ключ се сглобява и използва за подписване на транзакция (или, в случай на специален хардуер, точка за задействане на процедура за подписване на транзакция). Следователно теоретично няма 100% надеждно решение, което да позволи защита от куршуми от компрометиране на запазените частни ключове.

Сега помислете по този начин. В много случаи дори не е необходимо да защитете частните ключове на задния край толкова често. Вместо това можете да проектирате интелигентни договори и цялото приложение по такъв начин, че изтичането на частен ключ да не повлияе на обичайното им поведение. При този подход няма значение как оторизираните акаунти взаимодействат със смарт договора. Те просто „задействат“ интелигентен договор да върши обичайната си работа, а самият интелигентен договор изпълнява всички необходими проверки. Наричам го „моделът на оперативните сметки“.

Модел на оперативни акаунти за децентрализирани приложения, при които нямате нужда от военна сигурност за задните си акаунти

По този начин, в случай на спешност:

  • Единственото нещо, което нападателят може да открадне, е малко количество етер (от Ethereum), депозиран в оперативните сметки за публикуване на транзакции
  • Нападателят няма да може да навреди на логиката на интелигентния договор, нито на всеки, който участва в процеса
  • Компрометираните оперативни акаунти могат бързо да бъдат заменени с други, но това изисква или ръчна подмяна (генериране на нови акаунти и повторно упълномощаване на акаунти във всички интелигентни договори), или разработване на допълнително решение, което ще направи цялата магия с една транзакция от супер -защитен (хардуерен или многосигов) главен акаунт.

Например, при нашите повтарящи се таксувания за решение на Ethereum, без значение какво се случва на заден план, повтарящият се интелигентен договор за фактуриране е проектиран по такъв начин, че имаме цял месец време за подмяна на компрометираните акаунти, ако някой от тях е компрометиран. ,

Но все пак, ако искате да осигурите максимално сигурно съхранение на частния ключ в задния край, можете да опитате да използвате Vault с чудесен плъгин за Ethereum, който съхранява и управлява акаунти в Ethereum (освен това, следете нашите модули с отворен код - ние скоро ще пуснат нещо подобно). Няма да се гмурна дълбоко в детайлите тук, въпреки че можете сами да посетите свързаните проекти и да се научите от там.

Това дори не е всичко, което трябва да кажа. Тази статия обаче се оказа много по-дълга, отколкото очаквах, така че трябва да спра. Абонирайте се за My Medium / други мрежи, ако се интересувате от софтуер, криптовалута, съвети за пътуване или просто искате да следвате нещо интересно. Надявам се, че предоставих голяма ценна информация и ще я намерите полезна. Чувствайте се свободни да коментирате и разпространявате тази статия!