Serpent — лучший язык для «умных контрактов» на Эфириуме Классик

%d0%b7%d0%b0%d0%b3%d1%80%d1%83%d0%b6%d0%b5%d0%bd%d0%be_22-1-2017_%d0%b2_16_16_47

Serpent — язык для «умных контрактов» на основе Python. Python, вероятно, лучший язык для начинающих программистов и наиболее плодотворный язык для серьезных разработчиков. Serpent используется в сложных проектах на предприятиях. Изначально он был разработан для Эфириума. Здесь я опишу, как работать с этим языком в системе Эфириума Классик (ETC).

Установка

u5ds668a7csviqr3opccdaelciyekir

На большинстве платформ проще всего устанавливать Serpent с помощью системы управления пакетами Pip. Чтобы установить Serpent, сначала установите Python 2 и Pip. Затем запустите следующую команду:

pip install ethereum-serpent

Чтобы тестировать программы на Serpent, стоит установить дополнительный пакет с помощью такой команды:

pip install ethereum

Программирование

u5drcmlf1rcxvmrhatbqkwbo6nxp6gq

Чтобы получить «умный контракт», просто создайте функцию Serpent. Учтите, что некоторые особенности Python изменены или отсутствуют в Serpent. Например, целые числа составляют 32 байта, и строки в 32 байта или меньше рассматриваются как целые числа. Чтобы узнать об этом подробнее, смотрите документацию по Python и Serpent. Ниже представлено два примера функций:

 

def get_confirmation():
        #
        # Returns a string message confirming everything is working.
        #
        
        return "It works!"

def add_thousand(n):
        #
        # Accepts an integer and returns the result of adding 1000 to it.
        #
        
        return n + 1000

Чтобы протестировать функции с использованием блокчейна-заглушки, можно использовать следующий скрипт Python:

#!/usr/bin/env python

"""
Tests Serpent functions.

Requires a file name and a function invocation.

Serpent files     correspond to Ethereum Classic smart contracts.
Serpent functions correspond to Ethereum Classic smart contract   methods.

Testing is done on a mock blockchain.

Usage: serpent_test <file> <call data>
"""

import ethereum.tester
import ethereum.abi
import serpent
import binascii
import re
import sys

ETHER    = 0
PRIV_KEY = ethereum.tester.k0

program        = open(sys.argv[1]).read()
machine_code   = serpent.compile(program)
blockchain     = ethereum.tester.state()
smart_contract = blockchain.evm(machine_code)
method         = sys.argv[2][:sys.argv[2].find("(")]
args           = sys.argv[2][sys.argv[2].find("(") + 1:-1]
args           = [int(e) for e in args.split(",") if e]
call_data      = serpent.mk_full_signature(program)
call_data      = [e for e in call_data if e["name"].startswith(method + "(")]
call_data      = ethereum.abi.ContractTranslator(call_data).encode(method, args)
result         = blockchain.send(PRIV_KEY, smart_contract, ETHER, call_data)
print "call data : 0x" + binascii.hexlify(call_data)
print "result    : 0x" + binascii.hexlify(result)

Сохраните этот код в файл serpent_test. Затем сделайте файл исполняемым. Ниже представлена немного отредактированная текущая сессия, на компьютере с Linux, с файлом two_functions.se, который содержит функции get_confirmation и add_thousand:

% serpent_test two_functions.se "get_confirmation()"
call data : 0x7a6550fc
result    : 0x497420776f726b73210000000000000000000000000000000000000000000000

% serpent_test two_functions.se "add_thousand(234)" 
call data : 0x337170af00000000000000000000000000000000000000000000000000000000000000ea
result    : 0x00000000000000000000000000000000000000000000000000000000000004d2

Call data — это закодированная информация, необходимая для исполнения метода «умного контракта» на блокчейне ETC. Обратите внимание, что результат get_confirmation — это 32-байтовое шестнадцатеричное представление строки It works! (Работает!). А результат add_thousand — это 32-байтовое шестнадцатеричное представление целого числа 1234.

Компиляция

u5dr1tu5ur6q13bkqwe8rj36gssdadb

Чтобы скомпилировать функции Serpent в файле в код виртуальной машины ETC (байт-код), запустите следующую команду:

serpent compile <file>

На выходе вы получите шестнадцатеричное представление соответствующего машинного кода. Ниже показан результат компиляции вышеупомянутого файла two_functions.se с get_confirmation и add_thousand:

607980600b6000396084567c010000000000000000000000000000000000000000000000000000000060003504637a6550fc8114156056577f497420776f726b7321000000000000000000000000000000000000000000000060405260206040f35b63337170af8114156077576004356060526103e86060510160805260206080f35b505b6000f3

Развертывание

u5drmycwrffelvpbxdtrpramrqy9fvk

Для развертывания «умных контрактов» требуется счет ETC с запасом средств. Существует много способов приобрести эфир. Например, эфир можно купить на бирже Poloniex и перевести его на любой счет. Для развертывания также потребуется доступ к ноде ETC. Для настройки ноды я рекомендую реализацию Parity.

Ноды ETC Parity связываются с помощью формата JSON (JavaScript Object Notation). Чтобы выполнять все требуемые команды JSON на защищенной ноде Parity, запустите ее с помощью такой команды:

parity --chain classic --jsonrpc-apis eth,net,personal,web3

Я развертываю соответствующие задачи с помощью следующего скрипта Python:

#!/usr/bin/env python3

"""
Sends commands and receives output from Ethereum Classic Parity nodes.

Ethereum Classic Parity nodes listen for POST requests.

Usage: node_cmd <command> [<parameter>]...
"""

import urllib.request
import json
import sys

NODE_URL = "http://127.0.0.1:8545"

if   sys.argv[1] == "eth_call":
        args = [{"to" : sys.argv[2], "data" : sys.argv[3]}, "latest"]
elif sys.argv[1] == "personal_signAndSendTransaction":
        args = [{"from" : sys.argv[2], "data" : sys.argv[3]}, sys.argv[4]]
else:
        args = sys.argv[2:]
node_data = {"method"  : sys.argv[1],
             "params"  : args,
             "jsonrpc" : "2.0",
             "id"      : 1}
node_data = json.dumps(node_data).encode()
node_post = urllib.request.Request(NODE_URL)
node_post.add_header("Content-Type", "application/json")
node_post = urllib.request.urlopen(node_post, node_data).read().decode()
print(json.loads(node_post)["result"])

Сохраните этот код в файл node_cmd. Затем сделайте файл исполняемым.

Управление счетом с помощью Parity

Чтобы создать новый счет под управлением ноды, запустите следующую команду, указав желаемый пароль. В ответ вы получите адрес счета:

node_cmd personal_newAccount <password>

Чтобы составить список счетов под управлением ноды, запустите команду ниже:

node_cmd personal_listAccounts

Запустите следующую команду, чтобы получить баланс любого счета. Вы должны указать адрес счета в шестнадцатеричном виде:

node_cmd eth_getBalance <address> latest

Развертывание «умного контракта» с помощью Parity

Запустите команду ниже, чтобы развернуть «умный контракт». Вы должны указать адрес счета со средствами в шестнадцатеричном виде, пароль от него и машинный код. В ответ вы получите соответствующий хеш транзакции:

node_cmd personal_signAndSendTransaction <address> <machine code> <password>

Для команды выше будет установлен соответствующий лимит газа и стоимость на основе недавних транзакций.

Исполнение «умного контракта» с помощью Parity

Запустите следующую команду, чтобы исполнить «умный контракт» на блокчейне ETC. Вы должны указать адрес «умного контракта» и call data:

node_cmd eth_call <address> <call data>

Call data можно получить из вышеупомянутого скрипта serpent_test. Ниже приведена немного отредактированная текущая сессия на компьютере с Linux и запущенной нодой ETC Parity:

% PASSWORD="mysecretpassword"

% echo $PASSWORD
mysecretpassword

% ADDRESS=`node_cmd personal_newAccount $PASSWORD`

% echo $ADDRESS
0x853323f554263bb62af7080ef321f115ec623637

% node_cmd personal_listAccounts
['0x853323f554263bb62af7080ef321f115ec623637']

% node_cmd eth_getBalance $ADDRESS latest
0xb1a2bc2ec50000

% MACHINE_CODE="0x"`serpent compile two_functions.se`                                    

% echo $MACHINE_CODE
0x607980600b6000396084567c010000000000000000000000000000000000000000000000000000000060003504637a6550fc8114156056577f497420776f726b7321000000000000000000000000000000000000000000000060405260206040f35b63337170af8114156077576004356060526103e86060510160805260206080f35b505b6000f3

% TRANS_HASH=`node_cmd personal_signAndSendTransaction $ADDRESS $MACHINE_CODE $PASSWORD`

% echo $TRANS_HASH  
0x97e1e5c1367403dad7b80cb06d3087a0c9ab2acb475fe2a7c0b8a236224379ff

% node_cmd eth_getTransactionByHash $TRANS_HASH
{'standardV': '0x1', 'raw': '0xf8db808504a817c800830e57e08080b888607980600b6000396084567c010000000000000000000000000000000000000000000000000000000060003504637a6550fc8114156056577f497420776f726b7321000000000000000000000000000000000000000000000060405260206040f35b63337170af8114156077576004356060526103e86060510160805260206080f35b505b6000f3819ea01287a87308a565ddde438aec61ac339061ed653324305a660403f983eefa047fa07e7c6e44921b8a4aa0314ac777cba878d6a7f986bc4db8f363a15988036f56c1', 'gas': '0xe57e0', 'v': '0x9e', 'to': None, 'networkId': 61, 'value': '0x0', 'creates': '0x20ab68d0bfba229a72128af8b4965102cb5517c2', 'input': '0x607980600b6000396084567c010000000000000000000000000000000000000000000000000000000060003504637a6550fc8114156056577f497420776f726b7321000000000000000000000000000000000000000000000060405260206040f35b63337170af8114156077576004356060526103e86060510160805260206080f35b505b6000f3', 'blockHash': '0x4c6d975908a8c9d560742556b5f0bf791a97eb0731befcd266ff0c58b38ca07e', 'hash': '0x97e1e5c1367403dad7b80cb06d3087a0c9ab2acb475fe2a7c0b8a236224379ff', 'from': '0x853323f554263bb62af7080ef321f115ec623637', 'blockNumber': '0x2e8f34', 'transactionIndex': '0x0', 'r': '0x1287a87308a565ddde438aec61ac339061ed653324305a660403f983eefa047f', 'gasPrice': '0x4a817c800', 'publicKey': '0xb1be15931dd263cda0c6be5aed9e475c93a2b1a1aac1c9b6a661c1be6f628536d0e07de4f60be6736896584beb7927247e06cd9fa3d2f79faff7fe145c9726c1', 'nonce': '0x0', 's': '0x7e7c6e44921b8a4aa0314ac777cba878d6a7f986bc4db8f363a15988036f56c1'}

% serpent_test two_functions.se "get_confirmation()"
call data : 0x7a6550fc
result    : 0x497420776f726b73210000000000000000000000000000000000000000000000

% serpent_test two_functions.se "add_thousand(234)" 
call data : 0x337170af00000000000000000000000000000000000000000000000000000000000000ea
result    : 0x00000000000000000000000000000000000000000000000000000000000004d2

% RESULT=`node_cmd eth_call 0x20ab68d0bfba229a72128af8b4965102cb5517c2 0x7a6550fc`

% echo $RESULT
0x497420776f726b73210000000000000000000000000000000000000000000000

% python3 -c "import binascii ; print(binascii.unhexlify('$RESULT'[2:]))"
b'It works!\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

% RESULT=`node_cmd eth_call 0x20ab68d0bfba229a72128af8b4965102cb5517c2 0x337170af00000000000000000000000000000000000000000000000000000000000000ea`

% echo $RESULT
0x00000000000000000000000000000000000000000000000000000000000004d2 

% python3 -c "print($RESULT)"      
1234

Заключение

u5dshu9wdtwkpbu1ifqwpglq2y6k34z

Serpent отлично подходит для разработки «умных контрактов» на ETC. Используйте его и измените этот мир!

Источник: steemit.com



Рубрики:DApps, Новичкам, ETC, смарт-контракты

Метки: , , , ,

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s