Оседлай волну Web 3.0

от автора

Разработчик Кристоф Вердо рассказывает об онлайн-курсе ‘Mastering Web 3.0 with Waves’, который он недавно прошел.

Расскажите немного о себе. Чем вас заинтересовал этот курс?

Я занимаюсь веб-разработкой около 15 лет, в основном, как фрилансер.

Разрабатывая веб-приложение долгосрочного регистра для развивающихся стран по заказу одной банковской группы, я столкнулся с задачей интеграции в него блокчейн-сертификации. В то время я не очень много знал о блокчейн-сертификации, хоть уже и интересовался крипто-технологиями – в основном, как инвестор.

В итоге эта функция не была реализована, но, задумавшись о том, что организации и банки заинтересованы в таком решении для своих приложений, я занялся изучением вопроса и скоро запустил проект Signature Chain.

Я разработал его бета-версию, которая уже доступна в основной сети. В то время [языка программирования Waves] Ride еще не было, и я делал все простейшим способом, используя транзакции перевода с вложенным JSON. Но основная цель была в том, чтобы добавить более продвинутый функционал после запуска Ride. И это – главная причина, по которой я присоединился к курсу: следующая стадия развития проекта предусматривала создание децентрализованного приложения (dApp).

Какие аспекты курса показались вам наиболее простыми и какие наиболее сложными?

Самым простым было то, что у нас было достаточно времени на все задания. Смысл курса — в том, чтобы научиться чему-то, а не соревноваться между собой. Объяснения были очень доступными, а иллюстрации – простыми, но исчерпывающими. Это помогло визуализировать и понять разные темы.

При выполнении заданий нас подталкивали к тому, чтобы мыслить независимо и иногда что-то самостоятельно изучать. Это – наилучший способ научиться чему-то и разобраться в идеях, рассматриваемых на занятиях.

Несколько раз я не полностью понимал теоретическую часть до тех пор, пока не начинал писать код, выполняя задание. Нам не разрешалось делать ‘copy/paste’, весь код нужно было писать самим, и это тоже помогало лучше во всем разобраться.

Самым сложным было то, что вопросы в задании с несколькими вариантами ответа были не всегда понятны. Мой английский не идеален, и вопросы были написаны человеком, не являющимся носителем языка, поэтому порой возникало недопонимание.

Возможно, часть курса, посвященная оракулам и NFT могла бы быть более подробной. Но, в любом случае, основная задача курса – заинтересовать разработчиков. Потом, чтобы полностью понять все его аспекты, нужно будет, конечно, потратить какое-то время на то, чтобы поэкспериментировать и попрактиковаться.

Расскажите подробнее о решении, над которым вы работали в течение всего курса – ‘Coupon Bazaar’? Можно также увидеть примеры кода?

Да, мы работали над ‘Coupon Bazaar’, это – маркетплейс, где люди продают и покупают купоны, дающие право купить товары и услуги по более низкой цене. Каждый купон представлен цифровым ассетом, который предполагает специальную скидку от поставщика.

Нужно было разработать несколько компонентов приложения. Во-первых, нужно было создать систему для регистрации поставщиков и управления купонами. Затем нужна была функция верификации и возможность поиска купонов пользователями.

Во время курса мы также добавили несколько новых функций, включая систему голосования и функцию, позволяющую верифицировать и вносить в черный список поставщиков.

Сначала мы изучили разницу между смарт-ассетами, смарт-аккаунтами и dApp-аккаунтами и основы работы с функциями верификатора. Функции верификатора позволяют изменять поведение аккаунта, заданное по умолчанию. По умолчанию они проверяют подписи транзакций, но функция верификатора позволяет задавать другие «правила».

{-# STDLIB_VERSION 3 #-} {-# CONTENT_TYPE DAPP #-} {-# SCRIPT_TYPE ACCOUNT #-} letownerPublicKey = base58'H8ndsHjBha6oJBQQx33zqbP5wi8sQP7hwgjzWUv3q95M' @Verifier(tx) funcverify() = {     matchtx {         cases: SetScriptTransaction=>sigVerify(tx.bodyBytes, tx.proofs[0], ownerPublicKey)         cased: DataTransaction=>true         case_ =>false     } }

Затем мы начали добавлять купоны. Мы использовали одну из важнейших функций dApp, позволяющую записывать в блокчейн данные любого типа в виде пар «ключ-значение» – транзакцию данных. Мы объединили ее с новой транзакцией, invokeScript, использующейся для вызова вызываемой функции в dApp извне блокчейна.

Тип транзакций данных, который мы использовали во время прохождения курса, это добавление купонов на маркетплейс:

letdatajson = {     "title":        "t-shirt with , vote 1",     "coupon_price": 10000000,     "old_price":    1000000000,     "new_price":    100000000,     "address":      "Universe",     "description":  "I want you to make love, not war, i know you've heard it before",     "image":        "https://bit.ly/2EXTghg" } it('add item', asyncfunction(){     letts = invokeScript({        dApp: dappAddress,            call:{                function:"addItem",                args:[                     { type:"string", value: datajson.title },                     { type:"integer", value: datajson.coupon_price },                     { type:"string", value: JSON.stringify(datajson) }                ]},                payment: []            }, accountSupplierSeed)     lettx = awaitbroadcast(ts)     awaitwaitForTx(tx.id) })

Для обработки этих данных функцией addItem и разработки функции покупки и других опций мы использовали вызываемую функцию, которую пользователь может вызвать извне блокчейна. В результате она может выполнять различные задачи, например, инициировать передачу средств, записывать или обновлять данные в хранилище данных dApp и т.д.

Вот пример вызываемой функции, используемой в функции addItem:

@Callable(i) funcaddItem(title: String, price: Int, data: String) = {     letsupplierAddress = toBase58String(i.caller.bytes)     letitem = getKeyItem(supplierAddress, title)     if( price <= 0) thenthrow("purchase amount cannot be less than item price")     elseif( getValueItemSupplier(item) !=NONE ) thenthrow("an item is already exist")     else{         WriteSet([            DataEntry(getKeyItemSupplier(item), supplierAddress),            DataEntry(getKeyItemPrice(item), price),            DataEntry(getKeyItemData(item), data)         ])     } }

Позднее мы разработали систему голосования, позволяющую отдавать голоса за продвижение или удаление определенных продуктов. Чтобы не допустить влияния извне на процесс голосования, она использует схему ‘Commit-Reveal’.

Фаза «commit» используется для сбора зашифрованных голосов с помощью хэш-функции и «соли».

Фаза «reveal» используется для сбора зашифрованных голосов и сравнения их хэшей.

Вот пример вызываемой функции, используемой здесь:

@Callable(i) funcvoteCommit(item: String, hash: String) = {     letuser = toBase58String(i.caller.bytes)     letcommits = getValueCommitsCount(item)     letstatus = getValueItemStatus(item)     if( commits >=VOTERS) thenthrow("reached max num of voters")     elseif(getValueCommit(item, user) !=NONE) thenthrow("user has already participated")     elseif(getKeyItemSupplier(item) ==NONE) thenthrow("item does not exist")     elseif(status !=NONE && status !=VOTING) thenthrow("voting is not possible")     else{         WriteSet([            DataEntry(getKeyCommit(item, user), hash),            DataEntry(getKeyCommitsCount(item), commits +1),            DataEntry(getKeyItemStatus(item),if(commits ==VOTERS) thenREVEAL elseVOTING)         ])     } } >

Что еще вы узнали из курса?

Курс также включал в себя токенизацию и non-fungible токены (NFT) – токены, представляющие что-либо уникальное и поэтому не взаимозаменяемые.

Последнее занятие было посвящено оракулам. Поскольку блокчейн не может получать данные из внешнего мира, нам нужны оракулы для отправки в него этих данных.

Для нашего маркетплейса оракулы были нужны, чтобы верифицировать и, при необходимости, внести в черный список поставщика, который, например, не принял проданный купон.

Вот пример:

funcgetExtValueItemWhiteListStatus(item:String) = {     item +"_verifier_status" }   letverifier = "3Mx9qgMyMhHt7WUZr6PsaXNfmydxMG7YMxv" letVERIFIED = "verified" letBLACKLISTED = "blacklist" @Callable(i) funcsetstatus(supplier: String, status: String) = {     letaccount = toBase58String(i.caller.bytes)     if( account !=verifier ) thenthrow("only oracle verifier are able to manage whitelist")     elseif( status !=VERIFIED && status !=BLACKLISTED) thenthrow("wrong status")     else{         WriteSet([            DataEntry(getExtValueItemWhiteListStatus(supplier), status)         ])     } } 

Что было для вас наиболее полезным?

Самая полезная часть – это задания. Благодаря им материал лекций становился понятнее, а только что полученные знания закреплялись методом проб и ошибок. Очень полезна была и практическая работа с IDE, эксплорером и oракулами.

Как вы планируете использовать то, чему научились, на практике?

С самого начала я ожидал, что курс поможет вывести мой проект на новый уровень. Идея состояла в том, чтобы теперь написать код sign-web.app на RIDE. Существующая версия уже имеет функции сертификации документов, но, благодаря RIDE, ее можно будет значительно улучшить. Новая версия будет более гибкой и понятной, в ней будет больше функций, включая сертификацию электронных писем, соглашений между несколькими сторонами и т.д.

Курс также дал пищу для размышлений, и у меня появилось много новых идей. Я уверен, что результаты проявятся и в будущем.


ссылка на оригинал статьи https://habr.com/ru/company/waves/blog/462831/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *