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

Расскажите немного о себе. Чем вас заинтересовал этот курс?
Я занимаюсь веб-разработкой около 15 лет, в основном, как фрилансер.
Разрабатывая веб-приложение долгосрочного регистра для развивающихся стран по заказу одной банковской группы, я столкнулся с задачей интеграции в него блокчейн-сертификации. В то время я не очень много знал о блокчейн-сертификации, хоть уже и интересовался крипто-технологиями – в основном, как инвестор.
В итоге эта функция не была реализована, но, задумавшись о том, что организации и банки заинтересованы в таком решении для своих приложений, я занялся изучением вопроса и скоро запустил проект .
Я разработал его бета-версию, которая уже доступна в основной сети. В то время [языка программирования 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": "Do you want 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)
})Për procesimin e këtyre të dhënave me funksionin addItem dhe zhvillimin e funksioneve të blerjes dhe opsioneve të tjera, ne përdorëm një funksion të thirrur, i cili mund të thirret nga përdoruesi jashtë bllokut. Si rezultat, ai mund të kryejë detyra të ndryshme, për shembull, të niste transferimin e fondeve, të regjistronte ose të përditësonte të dhëna në depozitën e të dhënave dApp, etj.
Ja një shembull i funksionit të thirrur, i përdorur në funksionin addItem:
@Callable(i)
funcaddItem(title: String, price: Int, data: String) = {
letsupplierAddress = toBase58String(i.caller.bytes)
letitem = getKeyItem(supplierAddress, title)
if( price <= 0) thenthrow("shuma e blerjes nuk mund të jetë më e vogël se çmimi i artikullit")
elseif( getValueItemSupplier(item) !=NONE ) thenthrow("një artikull tashmë ekziston")
else{
WriteSet([
DataEntry(getKeyItemSupplier(item), supplierAddress),
DataEntry(getKeyItemPrice(item), price),
DataEntry(getKeyItemData(item), data)
])
}
}Më vonë, ne zhvilluam një sistem votimi që lejon jepjen e votave për promovimin ose heqjen e disa produkteve. Për të parandaluar ndihmën e jashtme në procesin e votimit, ai përdor një skemë 'Commit-Reveal'.
Faza "commit" përdoret për të mbledhur vota të enkriptuara me funksionin hash dhe "kripë".
Faza "reveal" përdoret për të mbledhur vota të enkriptuara dhe për të krahasuar hash-at e tyre.
Ja një shembull i funksionit të thirrur, i përdorur këtu:
@Callable(i)
funcvoteCommit(item: String, hash: String) = {
letuser = toBase58String(i.caller.bytes)
letcommits = getValueCommitsCount(item)
letstatus = getValueItemStatus(item)
if( commits >=VOTERS) thenthrow("arritur numri maksimal i votuesve")
elseif(getValueCommit(item, user) !=NONE) thenthrow("përdoruesi ka marrë pjesë tashmë")
elseif(getKeyItemSupplier(item) ==NONE) thenthrow("artikulli nuk ekziston")
elseif(status !=NONE && status !=VOTING) thenthrow("votimi nuk është i mundur")
else{
WriteSet([
DataEntry(getKeyCommit(item, user), hash),
DataEntry(getKeyCommitsCount(item), commits +1),
DataEntry(getKeyItemStatus(item), if(commits ==VOTERS) thenREVEAL elseVOTING)
])
}
}
>Çfarë tjetër keni mësuar nga kursi?
Kursi gjithashtu përfshinte tokenizimin dhe non-fungible tokens (NFT) – tokene që përfaqësojnë diçka unik dhe prandaj nuk janë të ndërrueshme.
Mësimi i fundit ishte për orakuj. Pasi blloku nuk mund të marrë të dhëna nga bota e jashtme, na duhen orakuj për të dërguar këto të dhëna atje.
Për tregun tonë, orakujt ishin të nevojshëm për të verifikuar dhe, në rastin e nevojës, për të vendosur në listën e zezë furnizuesin që, për shembull, nuk pranoi kuponin e shitur.
Ja një shembull:
funcgetExtValueItemWhiteListStatus(item:String) = {
item +"_verifier_status"
}
letverifier = "3Mx9qgMyMhHt7WUZr6PsaXNfmydxMG7YMxv"
letVERIFIED = "verifikuar"
letBLACKLISTED = "në listë të zezë"
@Callable(i)
funcsetstatus(supplier: String, status: String) = {
letaccount = toBase58String(i.caller.bytes)
if( account !=verifier ) thenthrow("vetëm verifikuesi i orakullit është në gjendje të menaxhojë listën e zezë")
elseif( status !=VERIFIED && status !=BLACKLISTED) thenthrow("status i gabuar")
else{
WriteSet([
DataEntry(getExtValueItemWhiteListStatus(supplier), status)
])
}
}
Çfarë ishte më e dobishme për ju?
Pjesa më e dobishme ishte detyrat. Falë tyre, materiali i ligjëratave bëhej më i qartë, dhe njohuritë e sapo fituara të konsolidoheshin nëpërmjet provave dhe gabimeve. Po ashtu, puna praktike me , dhe .
Si planifikoni ta përdorni atë që keni mësuar në praktikë?
Që në fillim prisja që kursi do të ndihmonte në avancimin e projektit tim në një nivel të ri. Ideja ishte që tani të shkruaja kodin në RIDE. Versioni ekzistues tashmë ka funksione të certifikimit të dokumenteve, por, falë RIDE, do të përmirësohet ndjeshëm. Versioni i ri do të jetë më fleksibël dhe i qartë, me më shumë funksione, duke përfshirë certifikimin e email-eve, marrëveshjeve mes disa palëve, etj.
Kursi gjithashtu ofroi ushqim për mendimin, dhe kam pasur shumë ide të reja. Jam i sigurt se rezultatet do të dalin edhe në të ardhmen.
Burimi: habr.com
