- PVSM.RU - https://www.pvsm.ru -
Эта статья представляет собой небольшое практическое руководство, которое поможет вам быстро настроить среду разработки смарт-контрактов на языке Solidity для блокчейна Ethereum. Вы опубликуете первый контракт, сохраните его в тестовом блокчейне Rinkeby и научитесь вызывать методы контракта. Это будет ваш первый шаг на пути создания децентрализованных приложений DApp (Decentralized Application).
Несмотря на обилие книг, статей и руководств, посвященной теме этой статьи, новичку довольно трудно приступить к публикации контрактов и работе с ними. При попытке что-то сделать по книгам, руководствам и статьям нередко оказывается, что примеры не работают, а команды возвращают непонятные ошибки. Я попытаюсь в некоторой степени упростить первый этап освоения, отразив в этой статье свой опыт изучения Ethereum.
При погружении в эту тему я использовал приложение (браузер) Mist в среде Microsoft Windows, а также интерфейс командной строки Geth узла Ethereum в среде Ubuntu. В этой статье мы расскажем о работе с Geth, а также немного о том, как вызывать методы контрактов из Node.js.
С благодарностью приму замечания и пожелания по дальнейшим статьям про блокчейн Ethereum, разработку контрактов на языке Solidity и приложений DApp.
Прежде чем начинать создание смарт-контрактов, я рекомендую изучить технологию блокчейна (Blockchain). Например, для начала вы можете почитать статью Объяснение блокчейна для веб-разработчиков [1], опубликованную на Хабре.
Ethereum — это децентрализованная платформа для разработки смарт-контрактов и создания так называемых децентрализованных приложений DApp. Сайт Ethereum находится по адресу https://www.ethereum.org/ [2]. Здесь вы найдете ссылки на основные ресурсы, которые будут вам полезны.
Например, по адресу http://www.ethdocs.org/en/latest/ [3] опубликована документация платформы.
Руководство по языку Solidity находится здесь [4]. Имеется перевод на русский язык [5], который, однако, может отставать от оригинальной документации.
По ходу изложения материала мы будем делать ссылки на те или иные ресурсы.
Для публикации контрактов и работы с Ethereum обычным пользователям компьютеров будет проще использовать браузер Mist с визуальным интерфейсом в среде Microsoft Windows. Однако разработчикам программного обеспечения (ПО) для понимания происходящего будет полезнее иметь дело с командной строкой.
Мы установим Go Ethereum — одну из трех оригинальных реализаций протокола Ethereum, написанную на языке Go (еще есть реализации на С++ и Python).
Go Ethereum можно установить на серверные платформы Ubuntu, Arch Linux и FreeBSD. Я выбрал Ubuntu, так как она похожа на Debian, а Debian мы применяем на нашем сервисе интернет-магазинов. Для эксперимента я установил ОС Ubuntu 17.10 на виртуальную машину под управлением VMWare Workstation.
Срзу после установки Ubuntu нужно добавить возможность подключения через SSH. Дополнительно я установил редактор Vim:
sudo apt-get install ssh
sudo apt-get install vim
Далее нужно установить стабильный релиз Go Ethereum:
sudo add-apt-repository -y ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install ethereum
Полностью этот процесс описан здесь [6].
Теперь нам нужно установить полный узел (full node) тестовой сети Rinkeby. Инструкция для узлов различного типа находится здесь: https://www.rinkeby.io/#geth [7]. Нам нужен блок этой инструкции для полного узла.
Прежде всего, копируем файл rinkeby.json в домашний каталог отсюда: https://www.rinkeby.io/rinkeby.json [8].
Далее открываем первое консольное окно, создаем в домашнем каталоге папку rinkeby и запускаем команду:
geth --datadir=/home/frolov/rinkeby init rinkeby.json
Эта команда запускается только один раз при инициализации. Здесь предполагается, что данные узла будут храниться в каталоге /home/frolov/rinkeby, а файл rinkeby.json — в каталоге /home/frolov/. Разумеется, вы можете выбрать другое расположение каталогов.
После завершения инициализации в этом же окне запускаем geth со следующими параметрами (вместо shop2you в параметре ethstats укажите какое-нибудь свое уникальное имя):
geth --networkid=4 --datadir=/home/frolov/rinkeby --rpc --rpcaddr "0.0.0.0" --rpcapi "admin,debug,miner,shh,txpool,personal,eth,net,web3" --ethstats='shop2you:Respect my authoritah!@stats.rinkeby.io' --bootnodes=enode://a24ac7c5484ef4ed0c5eb2d36620ba4e4aa13b8c84684e1b4aab0cebea2ae45cb4d375b77eab56516d34bfbd3c1a833fc51296ff084b770b94fb9028c4d25ccf@52.169.42.101:30303
Описание параметров команда geth вы можете найти по адресу https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options [9]. Также можно посмотреть справку по параметрам geth с помощью команды:
geth --help
Параметр --networkid=4 указывает, что мы используем тестовую сеть Rinkeby. С помощью параметра --datadir мы задаем расположение каталога для хранения базы данных узла и ключей.
Параметр --rpc разрешает работу сервера HTTP-RPC. Мы будем подключаться к нашему узлу из второго консольного окна через этот сервер. С помощью параметра --rpcaddr мы указываем, что сервер работает на всех сетевых интерфейсах узла (по умолчанию только на localhost). При помощи параметра --rpcapi мы указываем, какие API будут доступны через интерфейс HTTP-RPC.
Параметр --ethstats указывает URL-адрес отчета службы ethstats и задается в формате nodename:secret@host:port. И, наконец, параметр --bootnodes задает URL-адреса для загрузки P2P (Comma separated enode URLs for P2P discovery bootstrap).
Итак, мы запустили узел Go Ethereum для сети Rinkeby в первом консольном окне. Во втором консольном окне подключаемся к этому узлу с помощью такой команды:
geth --networkid=4 --datadir=/home/frolov/rinkeby attach ipc://home/frolov/rinkeby/geth.ipc
После подключения вы увидите командное приглашение утилиты geth. Введите в нем следующую команду:
> web3.version
{
api: "0.20.1",
ethereum: "0x3f",
network: "4",
node: "Geth/v1.7.3-stable-4bb3c89d/linux-amd64/go1.9.1",
whisper: undefined,
getEthereum: function(callback),
getNetwork: function(callback),
getNode: function(callback),
getWhisper: function(callback)
}
Эта команда покажет версию программного интерфейса Web3, с помощью которого мы будем работать с контрактами, версию geth, а также номер сети, который для Rinkeby равен 4.
Прежде чем продолжить работу, необходимо дождаться окончания синхронизации узла. Запустите во втором окне в приглашении geth команду eth.syncing:
> eth.syncing
{
currentBlock: 404158,
highestBlock: 1402511,
knownStates: 1974866,
pulledStates: 1962021,
startingBlock: 0
}
Так вы не запускаете процесс синхронизации (он должен запуститься автоматически), но, повторяя время от времени запуск команды, сможете отслеживать ход процесса. Когда синхронизация будет завершена, команда вернет false:
> eth.syncing
false
Процесс синхронизации можно наблюдать в первом консольном окне, в котором мы запустили узел Go Ethereum:
...
INFO [12-13|10:00:37] Imported new chain segment blocks=1 txs=1 mgas=0.123 elapsed=21.839ms mgasps=5.610 number=1408525 hash=bd6e8b…745ca3
INFO [12-13|10:00:51] Imported new chain segment blocks=1 txs=22 mgas=1.379 elapsed=188.490ms mgasps=7.317 number=1408526 hash=924b25…b292de
INFO [12-13|10:00:51] Imported new chain segment blocks=1 txs=22 mgas=1.379 elapsed=162.386ms mgasps=8.493 number=1408526 hash=c05478…70b24c
INFO [12-13|10:00:51] Imported new chain segment blocks=1 txs=22 mgas=1.379 elapsed=165.818ms mgasps=8.317 number=1408526 hash=8961b4…48d0a4
INFO [12-13|10:01:07] Imported new chain segment blocks=1 txs=2 mgas=0.063 elapsed=4.120ms mgasps=15.347 number=1408527 hash=a5e658…22d300
...
Заметим, что синхронизация начинается не мгновенно после запуска узел geth, и на ее завершение в сети Rinkeby может уйти достаточно продолжительное время, порядка нескольких десятков минут.
Сразу после установки нового узла вам нужно добавить в него аккаунты (если у вас уже есть аккаунты на других узлах, их можно перенести на новый узел).
Для добавления аккаунта введите в приглашении geth команду personal.newAccount():
> personal.newAccount()
Passphrase:
Repeat passphrase:
"0x7d9006e7f24bd6d90dd8cc63764ab0b92b77d9b3"
Здесь вам нужно будет ввести пароль. При работе с настоящей, не тестовой сетью Ethereum, нужно особенно позаботиться о сохранении пароля. Лучше всего не записывать пароль на компьютер, даже на зашифрованный диск. Дело в том, что вирусы или троянские программы смогут похитить пароль с зашифрованного диска, т.к. когда вы работаете с диском, его содержимое становится доступным. Также существуют кей-логгеры, которые могут перехватить пароль при его вводе с клавиатуры.
Пароль защищает ваш приватный ключ. Если злоумышленник сможет похитить пароль и приватный ключ с компьютера, он завладеет всеми средствами, которые есть у данного аккаунта. Кстати, не существует никакого способа восстановить пароль, так что терять его нельзя.
После ввода пароля на консоли появится адрес аккаунта, в нашем случае это «0x7d9006e7f24bd6d90dd8cc63764ab0b92b77d9b3» (у вас будет другой адрес). Заметим, что адреса созданных аккаунтов записывать не обязательно, т.к. их можно посмотреть при помощи команды eth.accounts:
> eth.accounts
["0x7d9006e7f24bd6d90dd8cc63764ab0b92b77d9b3"]
Вы можете добавить подобным образом несколько аккаунтов. В этом случае команда выведет массив идентификаторов для всех аккаунтов:
> eth.accounts
["0xa15862b34abfc4b423fe52f153c95d83f606cc97", "0x7d9006e7f24bd6d90dd8cc63764ab0b92b77d9b3", "0x957f5272eadf4e284aade9b2cb2a41f475936d07"]
Для каждого аккаунта создается приватный ключ. В нашем случае все ключи находятся в каталоге /home/frolov/rinkeby/keystore. Рекомендую сохранить эти ключи в безопасном месте, особенно если они относятся к аккаунтам основной, а не тестовой сети.
Для того чтобы можно было публиковать контракты и вызывать их методы, необходимо пополнить кошелек эфиром (Ether). Текущий баланс можно проверить следующей командой:
> web3.fromWei( eth.getBalance(eth.coinbase) )
0
Этой команде также можно предавать идентификатор аккаунта:
> web3.fromWei( eth.getBalance("0x7d9006e7f24bd6d90dd8cc63764ab0b92b77d9b3") )
10.428648202959703389
Чтобы пополнить кошелек в тестовой сети Rinkeby вам не потребуются реальные бумажные деньги или криптовалюта. Воспользуйтесь сайтом https://faucet.rinkeby.io/ [10]. Вам также потребуется аккаунт в Google+, Facebook или Twitter.
Сделайте публикацию в одной из перечисленных социальных сетей, содержащую адрес вашего аккаунта, такой как 0x7d9006e7f24bd6d90dd8cc63764ab0b92b77d9b3 (у вас будет другой адрес).
Далее скопируйте адрес публикации в поле Social network URL containing your Ethereum address и выберите из списка Give me Ether одно из значений.
Здесь вы можете получать 3 Ethers каждые 8 часов, 7.5 Ethers каждый день или 18.75 Ethers каждые три дня. Для начала работы вам вполне хватит 3 Ethers, так что можете выбирать первый вариант.
Если вы все сделали правильно, через некоторое время «эфирчики» поступят на ваш аккаунт. Разумеется, эти средства вы сможете потратить только в тестовой сети Rinkeby.
Теперь, когда вы все установили и проверили, пополнили свой аккаунт, можно приступать к публикации контракта. Мы будем работать с очень простым контрактом HelloSol. Вот его исходный текст на языке Solidity:
pragma solidity ^0.4.10;
contract HelloSol {
string savedString;
uint savedValue;
function setString( string newString ) public {
savedString = newString;
}
function getString() public constant returns( string ) {
return savedString;
}
function setValue( uint newValue ) public {
savedValue = newValue;
}
function getValue() public constant returns( uint ) {
return savedValue;
}
}
Этот контракт позволяет хранить текстовую строку и числовое значение. С помощью методов setString и getString можно, соответственно, записывать и читать строки. Аналогичные методы setValue и getValue предусмотрены для числовых значений.
Я создал три тестовых аккаунта:
> eth.accounts
["0xa15862b34abfc4b423fe52f153c95d83f606cc97", "0x7d9006e7f24bd6d90dd8cc63764ab0b92b77d9b3", "0x957f5272eadf4e284aade9b2cb2a41f475936d07"]
Для публикации контракта я буду использовать последний из них с адресом 0x957f5272eadf4e284aade9b2cb2a41f475936d07. На этот адрес можно ссылаться следующим образом:
> web3.eth.accounts[2]
"0x957f5272eadf4e284aade9b2cb2a41f475936d07"
Убедимся, что на аккаунте accounts[2] имеются средства:
> web3.fromWei( eth.getBalance(web3.eth.accounts[2]));
1.49157544347657552
Перед публикацией контракта (а также перед вызовом методов контракта, изменяющих данные), необходимо разблокировать аккаунт. Это можно сделать при помощи метода personal.unlockAccount:
> personal.unlockAccount(eth.accounts[2])
Unlock account 0x957f5272eadf4e284aade9b2cb2a41f475936d07
Passphrase:
true
У вас будет запрошен пароль, который вы задавали при создании аккаунта.
Далее нам нужно создать для контракта так называемый Application Binary Interface (ABI), а также выполнить компиляцию исходного текста контракта, написанного на языке Solidity.
Интерфейс ABI представляет собой спецификацию взаимодействия контракта с системой Ethereum, или, проще говоря, спецификацию параметров и возвращаемых значений методов контракта. Подробнее об этом можно почитать здесь [11].
В результате компиляции исходного текста контракта, написанного на Solidity, должен получиться бинарный код программы, который будет выполнять виртуальные машины на всех узлах сети Ethereum. В нашем случае это будет только тестовая сеть Rinkeby.
Интерфейс ABI и бинарный код программы проще всего получить при помощи браузерного инструмента IDE Remix, доступного по адресу https://remix.ethereum.org [12]. Руководство по использованию Remix можно найти здесь [13].
Откройте в браузере IDE Remix, и скопируйте код нашего контракта HelloSol в окно исходного текста, как это показано на рисунке ниже:
По умолчанию код будет сразу же откомпилирован, т.к. установлен флажок Auto compile. Чтобы получить ABI и двоичный код, щелкните кнопку Details. Найдите в появившемся окне блок web3Deploy:
Скопируйте отсюда блок кода при помощи кнопки Copy value to clipboard и вставьте этот текст в какой-нибудь текстовый редактор, например, в редактор Vim.
Для того чтобы опубликовать контракт, достаточно вставить из буфера обмена блок кода, скопированный из Remix, и нажать клавишу Enter.
Перед тем как это сделать, я отредактировал строку from: web3.eth.accounts[0], заменив ее на from: web3.eth.accounts[2]. Это было сделано, чтобы выполнить публикацию от аккаунта web3.eth.accounts[2], на котором имеются средства. Если вы создали только один аккаунт и пополнили его эфиром, то ничего редактировать не нужно, просто вставьте в окно консоли в приглашении программы geth текст, скопированный из Remix:
> var browser_ballot_sol_hellosolContract = web3.eth.contract([{"constant":true,"inputs":[],"name":"getValue","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newValue","type":"uint256"}],"name":"setValue","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newString","type":"string"}],"name":"setString","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getString","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]);
undefined
> var browser_ballot_sol_hellosol = browser_ballot_sol_hellosolContract.new(
... {
...... from: web3.eth.accounts[2],
...... data: '0x6060604052341561000f57600080fd5b6103598061001e6000396000f300606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063209652551461006757806355241077146100905780637fcaf666146100b357806389ea642f14610110575b600080fd5b341561007257600080fd5b61007a61019e565b6040518082815260200191505060405180910390f35b341561009b57600080fd5b6100b160048080359060200190919050506101a8565b005b34156100be57600080fd5b61010e600480803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919050506101b2565b005b341561011b57600080fd5b6101236101cc565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610163578082015181840152602081019050610148565b50505050905090810190601f1680156101905780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6000600154905090565b8060018190555050565b80600090805190602001906101c8929190610274565b5050565b6101d46102f4565b60008054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561026a5780601f1061023f5761010080835404028352916020019161026a565b820191906000526020600020905b81548152906001019060200180831161024d57829003601f168201915b5050505050905090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106102b557805160ff19168380011785556102e3565b828001600101855582156102e3579182015b828111156102e25782518255916020019190600101906102c7565b5b5090506102f09190610308565b5090565b602060405190810160405280600081525090565b61032a91905b8082111561032657600081600090555060010161030e565b5090565b905600a165627a7a7230582072dd1e3c0f509e8064320e887b19eb36fb41842f0897f41ce216a146c342d6140029',
...... gas: '4700000'
...... }, function (e, contract){
...... console.log(e, contract);
...... if (typeof contract.address !== 'undefined') {
......... console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
......... }
...... })
Как только вы скопируете текст, то увидите в консоли следующее:
null [object Object]
undefined
> null [object Object]
Это нормально. Теперь нужно подождать, когда контракт опубликуется. Если все сделано правильно, через несколько минут вы увидите в консоли сообщение:
Contract mined! address: 0x11c63c5ebc2c6851111d881cb58c213c609c92d4 transactionHash: 0xe79342277d7e95cedf0409e0887c2cddb3ebc5f0d952b9f7c1c1c5cef845cb97
Теперь ваш контракт опубликован в сети Rinkeby, и ему присвоен адрес 0x11c63c5ebc2c6851111d881cb58c213c609c92d4. Пользуясь этим адресом, любой пользователь сети Rinkeby сможет обращаться к контракту, вызывая его методы.
Теперь займемся самым интересным — взаимодействием с контрактом. Мы будем вызывать его методы из консоли geth, используя API JavaScript Web3, описанный здесь [14]. Заметим, что это документация на стабильную версию Web3 0.2x.x. Есть еще не реализованная версия 1.0, описанная по адресу http://web3js.readthedocs.io/en/1.0/index.html [15].
Прежде всего, в консольном приглашении Geth введите следующую строку:
var HelloSolContract = web3.eth.contract([{"constant":true,"inputs":[],"name":"getValue","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newValue","type":"uint256"}],"name":"setValue","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newString","type":"string"}],"name":"setString","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getString","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]);
Здесь на основе ABI будет создан объект нашего контракта. Вызовем для него метод at, передав этому методу в качестве параметра адрес контракта 0x11c63c5ebc2c6851111d881cb58c213c609c92d4, полученный нами на шаге публикации контракта:
var HelloSol = HelloSolContract.at("0x11c63c5ebc2c6851111d881cb58c213c609c92d4");
Теперь можно вызывать методы контракта. Как и ожидается, метод getValue возвращает нулевое значение, т.к. мы еще не сохраняли в базе контракта никаких значений:
> HelloSol.getValue()
0
Перед тем как вызывать метод setValue, нам необходимо разблокировать аккаунт при помощи метода unlockAccount:
> personal.unlockAccount(eth.accounts[2])
Unlock account 0x957f5272eadf4e284aade9b2cb2a41f475936d07
Passphrase:
true
Если вы помните, ранее мы разблокировали аккаунт перед публикацией контракта.
После того как аккаунт разблокирован, вызываем метод setValue:
> HelloSol.setValue(777, {from: "0x957f5272eadf4e284aade9b2cb2a41f475936d07"})
"0x019131872a3a834a1aaad7a810977eaaa1f9131344b9fb96e57d21a3f08c1363"
Обратите внимание, что в качестве первого параметра мы передаем методу значение, которое должно быть сохранено, а в качестве второго — адрес аккаунта, от имени которого будет вызван этот метод.
Теперь попытаемся получить значение методом getValue:
> HelloSol.getValue()
0
> HelloSol.getValue()
777
Вначале этот метод будет возвращать нулевое значение, и только через некоторое время мы получим наше новое значение.
Аналогичный эксперимент мы можем провести и с методами getString и setString, которые извлекают из базы контракта и изменяют в базе текстовую строку, соответственно:
> HelloSol.getString()
""
> personal.unlockAccount(eth.accounts[2])
Unlock account 0x957f5272eadf4e284aade9b2cb2a41f475936d07
Passphrase:
true
> HelloSol.setString("Моя строка", {from: "0x957f5272eadf4e284aade9b2cb2a41f475936d07"})
"0x6a50d48a39d7c8e4d49fcb821a16305059d3064ff25d757bf2877d4aa0a29f31"
> HelloSol.getString()
""
> HelloSol.getString()
""
> HelloSol.getString()
"Моя строка"
Небольшие контракты очень удобно отлаживать при помощи IDE Remix. Однако есть и альтернатива — пакетный компилятор solc, который можно запускать в командной строке. Документация по этому компилятору находится здесь [16].
Я использовал для установки solc следующую команду:
sudo snap install solc
После установки можно узнать версию компилятора:
solc --version
solc, the solidity compiler commandline interface
Version: 0.4.18+commit.9cf6e910.Linux.g++
Давайте выполним компиляцию нашего контракта HelloSol, получив для него файлы, содержащие ABI и двоичный код. Запишите исходный текст контракта в файл HelloSol.sol, а затем выполните следующую команду:
solc --bin --abi HelloSol.sol -o build --overwrite
После ее выполнения в подкаталоге build текущего каталога будут созданы два файла — HelloSol.abi и HelloSol.bin. Первый из них содержит ABI, а второй — двоичный код откомпилированного контракта.
Для деплоя контракта можно использовать приведенный код из Remix, подставив в него результат компиляции — содержимое файлов HelloSol.abi и HelloSol.bin. При этом нужно проследить за тем, чтобы не было переводов строк внутри строк содержимого этих файлов.
Для децентрализованных приложений DApp необходимо сделать пользовательский интерфейс. Можно связать обычное Web-приложение с системой контрактов, например, при помощи сервиса на базе Node.js. Давайте попробуем обратиться к методам нашего контракта через скрипт JavaScript, работающего на сервере под управлением Node.js.
Прежде всего, установим Node.js:
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs
node -v
v6.11.4
Также нам потребуется npm:
sudo apt install npm
npm -v
3.5.2
На следующем этапе нам нужно будет установить git, а также API Web3, причем стабильной версии. По умолчанию устанавливается нестабильная версия 1.x, поэтому сделаем так:
sudo apt-get install git
npm uninstall web3
npm install web3@0.20.1 --save
Чтобы проверить, что у нас все получилось, запустите в консоли Node.js при помощи команды node. Из консольного приглашения node введите следующие команды:
> var Web3 = require('web3')
undefined
> var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
undefined
> console.log(web3.eth.accounts);
[ '0xa15862b34abfc4b423fe52f153c95d83f606cc97',
'0x7d9006e7f24bd6d90dd8cc63764ab0b92b77d9b3',
'0x957f5272eadf4e284aade9b2cb2a41f475936d07' ]
Здесь мы подключились у узлу node и посмотрели список аккаунтов, созданных на этом узле.
Вы также можете попробовать разблокировать аккаунт следующим образом:
web3.personal.unlockAccount("0x957f5272eadf4e284aade9b2cb2a41f475936d07", "*********", 1000);
true
Вместо звездочек укажите свой пароль к аккаунту.
Далее вы можете попробовать в приглашении Node.js подключиться к опубликованному ранее контракту и вызвать его методы:
> var HelloSolContract = web3.eth.contract([{"constant":true,"inputs":[],"name":"getValue","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newValue","type":"uint256"}],"name":"setValue","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newString","type":"string"}],"name":"setString","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getString","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]);
undefined
> var HelloSol = HelloSolContract.at("0x11c63c5ebc2c6851111d881cb58c213c609c92d4");
undefined
> HelloSol.getValue()
{ [String: '777'] s: 1, e: 2, c: [ 777 ] }
> HelloSol.getString()
'Моя строка'
Мы подготовили скрипт nodejs_web3_test.js, который можно запускать командой «node nodejs_web3_test.js» из консоли Ubuntu:
var Web3 = require('web3')
var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
console.log(web3.eth.accounts);
var HelloSolContract = web3.eth.contract([{"constant":true,"inputs":[],"name":"getValue","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newValue","type":"uint256"}],"name":"setValue","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newString","type":"string"}],"name":"setString","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getString","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]);
var HelloSol = HelloSolContract.at("0x11c63c5ebc2c6851111d881cb58c213c609c92d4");
console.log(HelloSol.getValue().toString(10));
console.log(HelloSol.getString());
web3.personal.unlockAccount("0xa15862b34abfc4b423fe52f153c95d83f606cc97", "*******", 1000);
HelloSol.setString("Моя строка 999", {from: "0xa15862b34abfc4b423fe52f153c95d83f606cc97"});
Этот скрипт подключается к узлу, затем выводит список аккаунтов. Далее он подключается к контракту 0x11c63c5ebc2c6851111d881cb58c213c609c92d4 и вызывает его методы.
Вот что примерно вы увидите на консоли:
node nodejs_web3_test.js
[ '0xa15862b34abfc4b423fe52f153c95d83f606cc97',
'0x7d9006e7f24bd6d90dd8cc63764ab0b92b77d9b3',
'0x957f5272eadf4e284aade9b2cb2a41f475936d07' ]
777
Моя строка 123
Затронутая мною тема смарт-контрактов слишком масштабна и охватить ее в одной статье невозможно. Тут потребуется очень толстая книга! Я не рассмотрел некоторые очень важные темы, например, экономику Ethereum, единицы работы Gas, фильтры и многое другое. Но у меня есть планы создания новых статей, а возможно, и книги. Мне хотелось бы знать, о чем нужно рассказать в первую очередь, так что я очень жду ваших откликов!
Автор: AlexandreFrolov
Источник [17]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/kriptovalyuta/270743
Ссылки в тексте:
[1] Объяснение блокчейна для веб-разработчиков: https://habrahabr.ru/post/323128/
[2] https://www.ethereum.org/: https://www.ethereum.org/
[3] http://www.ethdocs.org/en/latest/: http://www.ethdocs.org/en/latest/
[4] здесь: https://solidity.readthedocs.io/en/develop/
[5] перевод на русский язык: https://github.com/ethereum/wiki/wiki/%5BRussian%5D-%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE-%D0%BF%D0%BE-Solidity
[6] здесь: https://ethereum.github.io/go-ethereum/install/
[7] https://www.rinkeby.io/#geth: https://www.rinkeby.io/#geth
[8] https://www.rinkeby.io/rinkeby.json: https://www.rinkeby.io/rinkeby.json
[9] https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options: https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options
[10] https://faucet.rinkeby.io/: https://faucet.rinkeby.io/
[11] здесь: https://solidity.readthedocs.io/en/develop/abi-spec.html
[12] https://remix.ethereum.org: https://remix.ethereum.org
[13] здесь: https://theethereum.wiki/w/index.php/Remix
[14] здесь: https://github.com/ethereum/wiki/wiki/JavaScript-API#web3ethcontract
[15] http://web3js.readthedocs.io/en/1.0/index.html: http://web3js.readthedocs.io/en/1.0/index.html
[16] здесь: http://solidity.readthedocs.io/en/develop/using-the-compiler.html
[17] Источник: https://habrahabr.ru/post/344578/?utm_campaign=344578
Нажмите здесь для печати.