Оседлай вълната на Web 3.0

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

Оседлай вълната на Web 3.0

Разкажете малко за себе си. Какво ви привлече в този курс?

Занимавам се с уеб разработки повече от 15 години, основно като фрийлансър.

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

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

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

Кои аспекти на курса ви се сториха най-лесни и кои най-трудни?

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

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

Няколко пъти не разбирах напълно теоретичната част, докато не започвах да пиша код, изпълнявайки заданието. Не ни беше разрешено да правим ‘copy/paste’, целият код трябваше да се пише сами, и това също помогна за по-доброто разбиране на всичко.

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

Възможно е частта от курса, посветена на оракулите и NFT, да бъде по-подробна. Но в крайна сметка основната задача на курса е да заинтересува разработчиците. След това, за да се разберат напълно всички аспекти, ще бъде нужно, разбира се, да се отдели време за опити и практика.

Разкажете по-подробно за решението, над което работихте през целия курс – ‘Coupon Bazaar’? Може ли също да видим примери за код?

Да, работихме над ‘Coupon Bazaar’, това е маркетплейс, където хората продават и купуват купони, които дават право на покупка на стоки и услуги на по-ниска цена. Всеки купон е представен като цифров актив, който предлага специална отстъпка от доставчика.

Оседлай вълната на Web 3.0

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

Оседлай вълната на Web 3.0

По време на курса добавихме и няколко нови функции, включително система за гласуване и функция, която позволява верификация и добавяне на доставчици в черен списък.

Първо изучихме разликата между смарт активи, смарт акаунти и dApp акаунти, както и основите на работата с функции за верификация. Функциите за верификация позволяват промяна на поведението на акаунта, зададено по подразбиране. По подразбиране те проверяват подписите на транзакциите, но функцията за верификация позволява задаване на други "правила".

{-# STDLIB_VERSION 3 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}
let ownerPublicKey = base58'H8ndsHjBha6oJBQQx33zqbP5wi8sQP7hwgjzWUv3q95M'
@Verifier(tx)
func verify() = {
    match tx {
        case: SetScriptTransaction=>sigVerify(tx.bodyBytes, tx.proofs[0], ownerPublicKey)
        case: DataTransaction=>true
        case_ =>false
    }
}

След това започнахме да добавяме купони. Използвахме една от най-важните функции на dApp, която позволява записване на данни от всякакъв тип в блокчейна под формата на двойки "ключ-стойност" – транзакция с данни. Обединихме я с новата транзакция, invokeScript, която се използва за извикване на функция от dApp извън блокчейна.

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

letdatajson = {
    "title":        "тениска с , гласувайте 1",
    "coupon_price": 10000000,
    "old_price":    1000000000,
    "new_price":    100000000,
    "address":      "Вселената",
    "description":  "Искам да правите любов, а не война, знам, че сте го чували преди",
    "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("сумата за покупка не може да бъде по-малка от цената на артикула")
    elseif( getValueItemSupplier(item) !=NONE ) thenthrow("артикулът вече съществува")
    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("достигнат е максималният брой гласоподаватели")
    elseif(getValueCommit(item, user) !=NONE) thenthrow("потребителят вече е участвал")
    elseif(getKeyItemSupplier(item) ==NONE) thenthrow("артикулът не съществува")
    elseif(status !=NONE && status !=VOTING) thenthrow("гласуването не е възможно")
    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, експлорера и оракулите.

Как планирате да приложите наученото на практика?

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

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

Източник: habr.com

Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри 🔥 Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри | ProHoster