Полная версия
Создание смарт-контрактов Solidity для блокчейна Ethereum. Практическое руководство
> web3.eth.accounts
["0x4f744742ac711fd111c7a983176db1d48d29f413", "0xf212d0180b331a88bd3cafbd77bbd0d56398ae00", "0x346cc69a63f9b84c45f17e337574c0150ab6bc03", "0xae7bb3649a5c597d44f812b4a636f3cc21ee98e1"]
Параметры команды geth account
Запуская команду geth account с параметрами в консоли ОС, вы можете полностью управлять аккаунтами. Это самый безопасный способ, так как в процессе управления пользователями вы не обращаетесь ни к каким фреймворкам, а работаете с Geth напрямую.
Команде geth account можно передавать параметры, перечисленные в табл. 4.1.
Табл. 4.1. Параметры команды geth account
Хорошее описание управления аккаунтами с примерами можно найти здесь: https://github.com/ethereum/go-ethereum/wiki/Managing-your-accounts.
Пароли аккаунтов
Обращаем ваше внимание, что пароли аккаунтов невозможно восстановить. Если вы создаете узел для реального проекта или собираетесь использовать аккаунт для хранения криптовалютных средств, обращайтесь с паролем очень осторожно.
Лучше всего запомнить пароль или записать его на обычной бумаге и хранить в безопасном месте. Доступ к вашему аккаунту обеспечивается приватным ключом и паролем.
Приватный ключ хранится на сервере узла и может быть похищен, например, с использованием какой-нибудь уязвимости в ОС или в ПО, установленном на сервере. Но чтобы использовать похищенный ключ, злоумышленнику потребуется еще и пароль. Мы не рекомендуем хранить пароль в компьютере (на сервере, ноутбуке и любом другом), так как он может быть похищен вместе с ключом.
Также учтите, что вредоносные программы могут перехватить управление клавиатурой, а также получить доступ к буферу обмена данных Clipboard. В этом случае они смогут похитить пароль в процессе его ввода с клавиатурой. Используйте антивирусные программы для защиты от вирусов и вредоносных программ различных типов.
Если злоумышленник сможет похитить приватный ключ и пароль, он получит полный доступ к вашему аккаунту и сможет, например, перевести все имеющиеся там криптовалютные средства на свой аккаунт.
Криптовалюта в Ethereum
Как мы уже говорили, для того чтобы владелец аккаунта мог проводить транзакции, публиковать и запускать смарт-контракты, на аккаунте должны быть средства. В тестовой сети, которую мы создали на втором уроке, эти средства можно получить при помощи майнинга. Если вы создаете тестовую сеть с помощью Geth, передавая ей параметр –dev, уже будет создан аккаунт, имеющий на балансе значительное количество криптовалюты.
Далее вы можете создавать новые аккаунты и переводить на них средства с тех аккаунтов тестовой сети, где уже имеются монеты.
Однако в основной сети Ethereum майнинг – дорогое и долгое занятие. Есть другая возможность, а именно: приобретение криптовалютных средств у владельцев других аккаунтов на биржах и обменниках. При этом владелец аккаунта может перевести средства на ваш аккаунт. Вы должны будете сообщить адрес вашего аккаунта, и если вы ошибетесь, то не будет никакой возможности вернуть ваши средства.
На этом уроке мы будем выполнять операцию перевода средств (разумеется, тестовых) в нашей приватной сети.
Денежные единицы Ethereum
Внутренняя валюта сети Ethereum называется Ether, или эфир. Когда владелец аккаунта выполняет транзакции, валюта, которая имеется на счету аккаунта, тратится.
Помимо Ether, существуют более крупные и более мелкие единицы криптовалюты Ethereum (аналогично тому, как в фиатных деньгах существуют рубли и копейки, доллары и центы).
Самая мелкая единица – это Wei. В одном эфире (т.е. в одном Ether) содержится целых 1 000 000 000 000 000 000 единиц Wei.
Как вы увидите далее, единица Wei удобнее, чем Ether, когда речь идет об оплате транзакций, не отнимающих много ресурсов.
В таблице 4.2. мы привели полный список денежных единиц Ethereum и их ценность в единицах Wei.
Таблица 4.2. Денежные единицы Ethereum
В интернете можно найти сайты с конвертами криптовалют Ethereum, вот один из них: https://etherconverter.online/. Здесь же показывается текущий курс Ether по отношению к доллару и евро.
Определяем текущий баланс наших аккаунтов
Выше мы добавили в нашу приватную сеть несколько аккаунтов. Полный список аккаунтов всегда можно посмотреть в консоли Geth при помощи команды web3.eth.accounts.
С помощью функции web3.eth.getBalance мы можем посмотреть баланс аккаунта в единицах Wei. Адрес аккаунта нужно передать функции в качестве параметра:
> web3.eth.getBalance("0x4f744742ac711fd111c7a983176db1d48d29f413")
2.3085e+22
Функция web3.eth.getBalance возвращает достаточно большое число. Вообще при работе с API фреймворков Ethereum мы часто будем иметь дело с очень большими числами. Когда вы будете разрабатывать свое децентрализованное приложение (DApp), это нужно будет учитывать.
Для того чтобы узнать баланс нужного вам аккаунта в Ether, используйте функцию fromWei:
> web3.fromWei(eth.getBalance("0x4f744742ac711fd111c7a983176db1d48d29f413"))
23110
При этом функции eth.getBalance нужно передать адрес проверяемого аккаунта.
Перевод средств с одного аккаунта на другой
Если подобным образом проверить баланс для аккаунтов, созданных нами дополнительно, то окажется, что сразу после создания он равен нулю, например:
> web3.fromWei( eth.getBalance("0xf212d0180b331a88bd3cafbd77bbd0d56398ae00"))
0
Это неудивительно, ведь мы еще не переводили средства на эти аккаунты. Но можно перевести деньги с основного аккаунта нашей приватной сети, которую мы создали на втором уроке. Для нее был запущен майнинг, поэтому там уже должны быть средства.
Метод eth.sendTransaction
Давайте посмотрим, какие у нас есть аккаунты и какой на них баланс:
> web3.eth.accounts
["0x4f744742ac711fd111c7a983176db1d48d29f413", "0xf212d0180b331a88bd3cafbd77bbd0d56398ae00", "0x346cc69a63f9b84c45f17e337574c0150ab6bc03", "0xae7bb3649a5c597d44f812b4a636f3cc21ee98e1"]
> web3.fromWei( eth.getBalance("0x4f744742ac711fd111c7a983176db1d48d29f413"))
23135
> web3.fromWei( eth.getBalance("0xf212d0180b331a88bd3cafbd77bbd0d56398ae00"))
0
> web3.fromWei( eth.getBalance("0x346cc69a63f9b84c45f17e337574c0150ab6bc03"))
0
> web3.fromWei( eth.getBalance("0xae7bb3649a5c597d44f812b4a636f3cc21ee98e1"))
0
Как видите, на первом из этих аккаунтов средства есть, а на остальных – ничего нет.
Давайте переведем часть средств, а именно 0.05 Ether, с первого их этих аккаунтов на другой, где средств нет. Воспользуемся для этого методом eth.sendTransaction:
> eth.sendTransaction({from:"0x4f744742ac711fd111c7a983176db1d48d29f413", to:"0xf212d0180b331a88bd3cafbd77bbd0d56398ae00", value: web3.toWei(0.05, "ether")})
При попытке выполнить эту операцию вы, однако, получите сообщение об ошибке:
Error: authentication needed: password or unlock
at web3.js:3143:20
at web3.js:6347:15
at web3.js:5081:36
at
Перед выполнением такой операции необходимо разблокировать исходный аккаунт, с которого отправляются средства. Для разблокировки введите такую команду:
> web3.personal.unlockAccount("0x4f744742ac711fd111c7a983176db1d48d29f413", "*********")
true
Вместо звездочек укажите пароль, с которым данный аккаунт создавался. Если аккаунт и пароль были указаны правильно, на консоли вы увидите true.
Теперь повторите вызов функции eth.sendTransaction:
> eth.sendTransaction({from:"0x4f744742ac711fd111c7a983176db1d48d29f413", to:"0xf212d0180b331a88bd3cafbd77bbd0d56398ae00", value: web3.toWei(0.05, "ether")})
"0xb6d13a5e915c3af1feabad7caec7b45348146695973b32285df287639717e916"
На этот раз функция выполнится успешно и вернет нам так называемый хеш транзакции (Transaction Hash) со значением:
0xb6d13a5e915c3af1feabad7caec7b45348146695973b32285df287639717e916
Чтобы перевод средств произошел успешно, эта транзакция должна быть выполнена. Кроме того, нужно дождаться, когда в вашу тестовую сеть будет добавлен новый блок. После этого средства появятся на целевом счету.
Посмотрите на консоль, где мы запустили наш узел. Видим, что там есть сообщение о запуске транзакции с указанным выше хешем, а также о том, что был добавлен новый блок:
INFO [02-17|23:20:50.917] Submitted transaction fullhash=0xb6d13a5e915c3af1feabad7caec7b45348146695973b32285df287639717e916 recipient=0xF212D0180B331a88BD3CafbD77bBd0D56398aE00
INFO [02-17|23:20:53.018] Commit new mining work number=4643 sealhash=0f860c…d73ae1 uncles=0 txs=1 gas=21000 fees=2.1e-05 elapsed=36.186ms
INFO [02-17|23:22:10.119] Successfully sealed new block number=4643 sealhash=0f860c…d73ae1 hash=3c9761…8b0eea elapsed=1m17.116s
INFO [02-17|23:22:10.119]
block reached canonical chain number=4636 hash=3b5237…0e8761INFO [02-17|23:22:10.119]
mined potential block number=4643 hash=3c9761…8b0eeaТеперь, если проверить баланс второго аккаунта, на который мы переводили средства, то окажется, что он как раз равен 0.05 Ether, как и должно быть:
> web3.fromWei( eth.getBalance("0xf212d0180b331a88bd3cafbd77bbd0d56398ae00"))
0.05
Функции eth.sendTransaction мы передали в параметрах from и to адреса исходного и целевого аккаунта соответственно. В параметре value мы задали количество переводимых средств в единицах Wei. Так как нам удобнее указывать размер средств в более крупных единицах Ether, для перевода в Wei мы воспользовались функцией web3.toWei.
Заметим, что в реальной сети вместе с транзакцией нам нужно указать средства, которые пойдут на обработку этой транзакции (так называемый газ). Для этого команде eth.sendTransaction нужно задать параметры gas (количество газа, заданное для выполнения операции) и gasPrice (стоимость газа в Wei):
eth.sendTransaction({from:"0x208970e5e3d48a6eab968e64ba3447f6181310c1", to:"0x82a4165f21d8f1867d536e81537fc0085e5470a1",value: web3.toWei(5, "ether"), gas: 120000, gasPrice: 80000000000})
Просмотр состояния транзакции
Зная хеш транзакции, вы можете получить о ней определенную информацию. Это можно сделать при помощи метода web3.eth.getTransaction, передав ему в качестве параметра строку хеша транзакции.
В ответ вы получите объект следующего вида:
> web3.eth.getTransaction("0xb6d13a5e915c3af1feabad7caec7b45348146695973b32285df287639717e916")
{
blockHash: "0x3c9761fefa52a0bc563733d87163828c5fe1316d78ca89be8af18d9c818b0eea",
blockNumber: 4643,
from: "0x4f744742ac711fd111c7a983176db1d48d29f413",
gas: 90000,
gasPrice: 1000000000,
hash: "0xb6d13a5e915c3af1feabad7caec7b45348146695973b32285df287639717e916",
input: "0x",
nonce: 0,
r: "0x1e3519fbca45cc5f6a0804232c8f0362d42c8abfeaf5225536867651f53787fd",
s: "0x69e617eceec461b727a0997fd837264e02242fa16f61491e58974faaf20c49c7",
to: "0xf212d0180b331a88bd3cafbd77bbd0d56398ae00",
transactionIndex: 0,
v: "0xfc2",
value: 50000000000000000
}
Поля объекта состояния транзакции перечислены в табл. 4.3.
Таблица 4.3. Состояние транзакции
Как видите, здесь есть адреса отправителя from и получателя to, а также объем переведенных средств в Wei.
Когда вы запускаете транзакцию на выполнение, она выполняется не сразу. Вначале транзакция находится в состоянии ожидания, пока майнеры не создадут для нее новый блок. Анализируя поля номера блока blockNumber, в котором размещается транзакция, можно определить, была ли запущена транзакция или еще нет.
Поля v, r, s содержат значения для подписи транзакции. Их содержимое можно использовать для получения публичного ключа аккаунта. Способ их использования с этой целью обсуждается здесь: https://ethereum.stackexchange.com/questions/13778/get-public-key-of-any-ethereum-account.
Содержимое полей gasPrice и gas имеет отношение к стоимости транзакции. Пока мы работаем с тестовой сетью, об этом можно не беспокоиться. Если кратко, то gasPrice содержит так называемую стоимость газа, который тратится на выполнение транзакции, а поле gas – количество газа, которое выделил отправитель для выполнения транзакции.
Вы можете думать о газе, как о бензине, который тратится на выполнение транзакций. Стоимость этого бензина может меняться, а на разные транзакции этого бензина тратится разное количество.
Квитанция транзакции
Когда транзакция выполнилась (о чем можно узнать при помощи только что рассмотренного метода web3.eth.getTransaction), вы можете получить так называемую квитанцию об ее выполнении. Для этого предназначен метод web3.eth.getTransactionReceipt.
Передайте этому методу в качестве параметра хеш завершенной транзакции, и вы получите квитанцию в виде объекта:
> web3.eth.getTransactionReceipt("0xb6d13a5e915c3af1feabad7caec7b45348146695973b32285df287639717e916")
{
blockHash: "0x3c9761fefa52a0bc563733d87163828c5fe1316d78ca89be8af18d9c818b0eea",
blockNumber: 4643,
contractAddress: null,
cumulativeGasUsed: 21000,
from: "0x4f744742ac711fd111c7a983176db1d48d29f413",
gasUsed: 21000,
logs: [],
logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
root: "0xa5cdcd909d837e937189f4cffc52840111f4430bf871f07094eaea96c47d682d",
to: "0xf212d0180b331a88bd3cafbd77bbd0d56398ae00",
transactionHash: "0xb6d13a5e915c3af1feabad7caec7b45348146695973b32285df287639717e916",
transactionIndex: 0
}
Поля объекта квитанции перечислены в табл. 4.4.
Таблица 4.4. Квитанция выполненной транзакции
Анализируя квитанцию, вы можете узнать номер блока, в котором размещена транзакция blockNumber, а также индекс позиции размещения транзакции в блоке transactionIndex.
При помощи полей cumulativeGasUsed и gasUsed вы сможете понять, сколько газа ушло на выполнение транзакции. При запуске транзакции вы можете выделить определенное количество газа, но если газа будет больше, израсходуется только часть ваших средств. В реальной сети Ethereum, если газа будет выделено слишком мало, транзакция будет очень долго находиться в состоянии ожидания или не будет выполнена вовсе.
Также обратите внимание на поле contractAddress. Когда мы займемся публикацией смарт-контрактов, нам потребуется адрес размещенного смарт-контракта из этого поля.
Итоги урока
На четвертом уроке вы научились управлять аккаунтами, а также переводить средства с одного аккаунта на другой. Попутно вы изучили криптовалютные единицы, которые применяются в сети Ethereum.
Вы узнали, что созданные транзакции сначала попадают в состояние ожидания и находятся в нем до тех пор, пока в блокчейн не будет добавлен новый блок. Проверку состояния транзакции можно выполнить методом web3.eth.getTransaction.
Когда транзакция выполнена, то с помощью метода web3.eth.getTransactionReceipt вы можете получить ее квитанцию. Из квитанции можно определить, сколько газа было потрачено на выполнение транзакции. Если транзакция была связана с публикацией контракта, то этот метод поможет вам получить адрес опубликованного контракта. Адрес контракта необходим, как вы скоро узнаете, для вызова его методов.
Урок 5. Публикация первого контракта
Цель урока: на этом уроке вы узнаете о смарт-контрактах в сети Ethereum и о том, как они выполняются виртуальной машиной Ethereum. Мы расскажем, как создать смарт-контракт на языке Solidity и как опубликовать его в приватной сети. Также вы научитесь устанавливать и запускать пакетный компилятор solc. Вам нужно узнать о так называемом бинарном интерфейсе приложения Application Binary Interface (ABI) и научится его использовать.
Практические задания: на пятом уроке вы создадите первый контракт HelloSol в среде разработки Remix Solidity IDE. Этот контракт вам предстоит опубликовать в приватной сети и проверить в работе. Также вы установите пакетный компилятор solc и откомпилируете им свой смарт-контракт HelloSol.
Как вы, конечно, знаете, обычные контракты заключаются между двумя (или несколькими сторонами) в бумажном виде. Например, в контракте может быть написано, что одна сторона берет на себя обязательство поставить какой-нибудь товар, а другая обязуется после получения товара выполнить оплату. Либо контракт может предусматривать предоплату, и тогда товар поставляется после получения денег.
В контрактах также обычно предусматривают некие штрафные санкции за невыполнение условий. Это может быть, например, штраф за задержку поставки или оплаты. Если условия контракта нарушаются, пострадавшая сторона может обратиться в суд, при этом в дело включатся юристы. Вся эта процедура может отнять немало времени и средств.
Смарт-контракты в Ethereum
В сети Ethereum имеется возможность создавать так называемые смарт-контракты (Smart Contracts). Смарт-контракт представляет собой программный код, работающий в среде виртуальной машины Ethereum. Он запускается на всех узлах сети, и результаты его работы также реплицируются на все узлы.
С помощью смарт-контрактов очень удобно отслеживать выполнение транзакций, например, имеющих отношение к поставке товаров (особенно электронных, таких как файлы книг или доступы к сервисам), автоматизируя оплату при помощи криптовалютных средств. Если смарт-контракт получил тем или иным способом подтверждение выполнения условий сделки, то он может сам, автоматически, перевести средства поставщику.
Конец ознакомительного фрагмента.
Текст предоставлен ООО «ЛитРес».
Прочитайте эту книгу целиком, купив полную легальную версию на ЛитРес.
Безопасно оплатить книгу можно банковской картой Visa, MasterCard, Maestro, со счета мобильного телефона, с платежного терминала, в салоне МТС или Связной, через PayPal, WebMoney, Яндекс.Деньги, QIWI Кошелек, бонусными картами или другим удобным Вам способом.