WebAssembly для запуска блокчейна с использованием Go
Блокчейн — это технология с бесчисленными приложениями и огромным потенциалом, который еще не используется полностью. Это упорядоченный список блоков, которые прикованный вместе, отсюда и название блокчейн. Одной из важных особенностей, которой он обладает, является то, что блоки блокчейна добавляются на основе консенсуса узлов, создающих эту цепочку. Что касается того, что эти блоки созданы в основном для хранения информации, то их можно рассматривать как распределенную базу данных, которая управляется роем узлов, в которых предусмотрены алгоритмы консенсуса для этого роя. Чтобы разрешить добавление блоков в качестве записей в эту базу данных безопасным и неопровержимым образом, чтобы эти записи были действительными без необходимости навязывать это центральному органу. Одним из методов достижения этого консенсуса является предоставление Proof of Work (PoW), поскольку это происходит, требуя от узлов выполнения исчерпывающих вычислений, в которых только один узел не должен быть в состоянии завершить. Более подробная информация о блокчейне и его реализации представлена далее во второй части этой статьи.
Голанг
Golang (Go) представляется достойным кандидатом на язык программирования, подходящим для запуска блокчейна на узлах, реализованных в децентрализованном приложении (DApp). Его показатели производительности сравнимы с высокопроизводительными языками, такими как C, C++ и Rust, но Go, будучи простым в освоении и использовании без ущерба для производительности, дает ему преимущество над ними (по крайней мере, для этой статьи).
Веб-сборка
Чтобы запустить это DApp, написанное на Go, вам нужно скомпилировать его как консольное приложение. Но так бы и было, если бы у нас не было webassembly (к счастью, она у нас есть). Webassembly — это цель компиляции для этого кода, позволяющая нам запускать DApp в веб-браузере и чувствовать себя естественно при взаимодействии с ним.
В этой статье
В этой статье вы познакомитесь с кодом для блокчейна DApp, работающего через веб-сокет. Здесь показано, как использовать базовые операции блокчейна с javascript для представления на веб-странице. Во второй части мы рассмотрим реализацию самого блокчейна.
Структура программы
Программа построена в соответствии с рисунком ниже.
- web: компоненты пользовательского интерфейса и обратные вызовы событий, предоставляемые пользователю.
- кошелек: абстрагирование операций блокчейна до очень простых операций покупки и вознаграждения.
- blockchain: здесь реализованы операции с блокчейном, стоит отметить, что кошелек относится к блокчейну пакета Go.
- chainfabric: базовая сеть, которая связывает узлы во время майнинга.
Сценарий использования
- Есть два пользователя Алиса и Боб, каждый делает следующее:
- Предположим, Алиса открывает веб-браузер и переходит к приложению.
- Сначала она идентифицирует себя, выбрав «Алиса» из выпадающего меню.
- Она видит окно, в котором она может совершать операции с валютой, назовем эту единицу валюты
crypsys
. - Затем она щелкает
Reward
что приводит к тому, что ее баланс добавляет еще 10 крипси. - Как только у нее накопится достаточное количество крипси, она решает купить яблоки у Боба.
- Блокчейн отображается в виде последовательности блоков в веб-браузере.
- Каждая выполненная операция «вознаграждение/покупка» запускает обновление и повторную визуализацию блокчейна в веб-браузере.
- С другой стороны, Боб следует тем же шагам, что и Алиса, и он использует то же представление блокчейна, что и она.
index.html
Что касается запуска процесса в браузере, для него требуется файл index.html, из которого запускается приложение.
Заголовок индексного файла включает два первых последовательных скрипта, которые необходимы для запуска программы Go в качестве ресурса веб-сборки в браузере. Wasm_exec.js включен как есть, так как нет необходимости изменять этот файл, пока второй скрипт извлекает файл main.wasm, скомпилированный в качестве цели из программы main.go, для его запуска. Включенный исходный код jquery не является обязательным для веб-сборки, но ради облегчения жизни я включил его. Это также показывает, что мы определенно можем использовать js-фреймворки бок о бок с webassembly. Компоненты пользовательского интерфейса размещаются внутри <body>
селектор, как мы делаем с обычным html. Функции Javascript, зарегистрированные как события в элементах html, например <button>
а также <select>
реализованы в web/actions.go.
Файл action.go — это «мост», который связывает базовые операции блокчейна, написанные на Go, и их выполнение в браузере через webassembly.
Последний скрипт в конце <body>
описывает поведение ползунка, а обратный вызов javascript также реализован в web/actions.go.
действия.го
В web/actions.go реализованы все функции js, вызываемые в index.html.
Как показано, все функции в Go имеют одинаковую сигнатуру для сопоставления с соответствующими функциями javascript в index.html независимо от аргументов или возвращаемого типа последнего. В первой строке я создаю функцию для сопоставления функций javascript в index.html с соответствующими функциями Go, которые реализованы в этом файле. Во второй строке первый аргумент Set()
указывает на функцию javascript с именем reward
. В то время как второй аргумент строит функцию javascript из функции Go reward
объявлено в строке 59.
Пока changeUser()
сначала проверяет, является ли выбор из раскрывающегося списка Алисой или Бобом. Затем он включает кнопку «Купить» в строке 17, устанавливая disabled
отнести к ложным. Точно так же он переключает атрибут отключения для параметров раскрывающегося списка в значение true. Поскольку пользователь не может быть изменен снова после установки в первый раз. Следовательно User
переменной установлено значение из раскрывающегося списка в строке 22, поскольку это устанавливает владельца кошелька на этот User
. В строках 31-35 кнопка «Купить» настраивается в соответствии с выбранным пользователем. Например, если User
равно "Alice"
то действие кнопки «Купить» — купить яблоки по цене 20 крипси.
Функция buyCommodity()
вызывает кошелек для оплаты цены товара продавцу. в котором оба merchant
а также price
были установлены заранее в changeUser()
вызов функции.
networth()
вызывает кошелек, чтобы проверить количество криптоактивов, которое есть у владельца кошелька. Он возвращает значение networth как значение javascript, которое затем просматривается в index.html. reward()
дает пользователю 10 крипсис из воздуха, это не то, как все работает в реальном мире. Но это способ внедрить крипсис в этот сценарий как реализуемый.
sendSliderValToWasm()
передает значение ползунка из index.html в diff
переменная, которая содержит значение сложности майнинга. Чем больше это значение, тем сложнее становится проблема майнинга, что, в свою очередь, приводит к тому, что требуется больше времени для добавления нового блока в блокчейн.
рендерер.го
RenderPage()
делает страницу динамической, перезагружая элементы страницы в соответствии с изменениями, произошедшими в блокчейне.
Сначала я получаю кошелек пользователя, чтобы позже получить блокчейн и баланс пользователя. В строке 5 chainView
это элемент div, включающий другие элементы dom, необходимые для отрисовки блокчейна кошелька. В строке 9 chainView
добавляется в blockchain-placeholder
в index.html. Метка networth файла index.html также обновляется в строках 11.
кошелек.го
Структура кошелька представляет собой оболочку операций блокчейна, в основном она действует как абстракция над транзакциями блокчейна.
В первой строке NotifyListeners
это обратный вызов, который вызывается сразу после любой мутации в блокчейне, что, в свою очередь, требует изменения пользовательского интерфейса. Структура содержит имя пользователя и указатель на цепочку блоков, в которую она заключена. Стоит отметить, что golang не предоставляет специального синтаксиса конструктора для своих структур. Следовательно Wallet
экземпляр создается путем вызова (подобной конструктору) функции NewWallet()
поскольку программисты Go обычно прибегают к этому способу реализации «конструктора».
Networth()
проходит через блокчейн, чтобы найти имя пользователя кошелька в транзакциях, записанных в блокчейне. Он вычисляет его чистую стоимость путем вычитания транзакций, инициированных ею/него, из транзакций, направленных ей/ему.
Функции PayTo
а также Reward
являются обертками вокруг блокчейна RequestTransaction
который инициирует процесс создания нового блока с соответствующей транзакцией. Reward
инициирует транзакцию от имени пользователя «Coinbase», так как ради этой статьи пользователь отражает дополнительные крипсии, добавленные в «крипси-экономику», поэтому он может предоставить бесконечное количество крипси, если это необходимо. PayTo
передает крипсии от Алисы или Боба другому, а также проверяет наличие у плательщика достаточного количества крипси, прежде чем инициировать транзакцию.
main.go
Этот файл является точкой входа компиляции для приложения, в котором RegisterCallbacks()
вызывается, что определено в action.go, принадлежащем пакету Go web
.
В самом начале а WaitGroup
переменная объявлена так, что приложение не завершается в конце main()
. Следовательно, приложение продолжает работать, чтобы соответственно реагировать на ввод пользователя, который захватывается путем вызова RegisterCallbacks()
.
Давайте запустить его!
- Сначала перейдите в корневой каталог main.go и скомпилируйте его в webassembly.
GOARCH=wasm GOOS=js go build -o main.wasm main.go
- Бежать
node tracker.js
чтобы установить связь между экземплярами приложения. - Дублируйте папку приложения, чтобы позже запустить другой экземпляр приложения.
- Бежать
http-server
в обоих корневых каталогах main.wasm, которые будут обслуживаться черезlocalhost:port
.
miner-dapp-wasm beber$ http-server
Starting up http-server, serving ./
Available on:
miner-dapp-wasm-2 beber$ http-server
Starting up http-server, serving ./
Available on:
- Введите оба URL-адреса на двух вкладках любого веб-браузера, чтобы открыть два экземпляра приложения.
- Выберите Алису в первом экземпляре и выберите Боба во втором, теперь оба кошелька инициированы.
- В экземпляре Боба: нажмите
Reward
. - Для создания нового блока майнинг требует времени.
- Эта проблема майнинга решается майнером Боба, дающим одноразовое значение 1453337, это подробно объясняется во второй части.
- Создается новый блок, показывающий транзакцию, его чистая стоимость увеличивается на 10, в то время как у Алисы все еще нет крипсии.
- Данные, представленные каждым блоком:
crypsys from -> crypsys to: количество crypsys |
Хэш предыдущего блока |
одноразовый номер |
Хэш этого блока |
- Алиса также использует одни и те же данные блокчейна, несмотря на то, что она не участвовала в последней транзакции.
- Теперь Боб решает купить бананы у Алисы.
Его чистая ценность становится равной 0, потому что он заплатил все свои 10 крипси за бананы (неразумный ход, Боб!).
После нескольких случайных операций по покупке и вознаграждению Алиса покупает яблоки у Боба.
На этот раз Алису предупреждают, что одноразовый номер был добыт Бобом, несмотря на то, что она инициировала эту операцию. В этом случае chainfabric уведомила майнера Алисы о прекращении майнинга после того, как Боб решил одноразовый номер.
- Теперь ее чистая стоимость равна 0, так как все, что у нее было до активации этой покупки, было 20 крипси, что является ценой яблок Боба.
Надеюсь, вы взволнованы добавлением веб-сборки в свои проекты после беглого просмотра этой статьи, и вы получите представление о том, как выглядит блокчейн, пока не углубитесь в него вместе в следующей части этой статьи.
Весь код вы можете найти в моем хранилище