python jsonrpc_Python通过JSON-RPC请求对以太坊智能合约进行部署和交易-程序员宅基地

技术标签: python jsonrpc  

本文探讨了如何将JSON-RPC请求发送到Geth节点以创建原生的交易。目标是在使用高级库(如web3py或web3js)时了解并查看后台发生的情况。

另外,对处理错误和异常不是本文的重点。如果出现任何问题,它将只是显示失败。这篇文章主要是学习。对于生产环境,还是考虑使用web3.py。

我们将仅使用HTTP请求在私有链上使用智能合约部署和交互(调用函数和读取公共变量)。交易是离线签名的,然后才发送到geth节点进行处理。

对于本指南,我们使用的是私有的Proof-of-Authority网络。如果想创建这样一个网络,可以阅读我们以前的帖子。本文假设使用Ganache(以前称为TestRPC)或任何以太坊网络都完全没问题。因此,不会介绍有关在网络设置的任何内容,重点是使用python将HTTP请求发送到Geth节点。

条件

1.通过IPC或RPC访问以太坊网络(可能是公有,私有或像Ganache这样的模拟器)。

2.安装了python 3。 我个人喜欢Anaconda发行版。

3.安装最新版本的web3py。

1.向Geth发送一个简单的请求

让我们通过向Geth发送一个非常简单的请求来热个身。查询下网络ID。 第一步是阅读文档。 我们需要的方法称为net_version,在此处进行描述。

我的Geth节点URL和端口是:http://localhost:8501。如果你使用的是具有默认值的Ganache,则URL可能是http://localhost:7545。

import requests

# create persistent HTTP connection

session = requests.Session()

# as defined in https://github.com/ethereum/wiki/wiki/JSON-RPC#net_version

method = 'net_version'

params = []

payload= {"jsonrpc":"2.0",

"method":method,

"params":params,

"id":1}

headers = {'Content-type': 'application/json'}

response = session.post('http://localhost:8501', json=payload, headers=headers)

print('raw json response: {}'.format(response.json()))

print('network id: {}'.format(response.json()['result']))

结果是:

raw json response: {'id': 1, 'jsonrpc': '2.0', 'result': '1515'}

network id: 1515

不错,从那里我们准备好与合约一起部署和交易,这建立了一个良好的基础。1515是我的私有区块链的网络ID,如创世文件中所定义。目前看起来都很棒。 使用Ganache,应该获得5777的网络ID。

但在能够签署和发送交易之前,我们需要一个地址,一个私钥和一些以太币。

2.创建公钥私钥对并获取一些以太币

web3py(release 4)库将帮助我们创建密钥对。

import web3

w3 = web3.Web3()

myAccount = w3.eth.account.create('put some extra entropy here')

myAddress = myAccount.address

myPrivateKey = myAccount.privateKey

print('my address is : {}'.format(myAccount.address))

print('my private key is : {}'.format(myAccount.privateKey.hex()))

在这个示例中,我得到:

my address is : 0xF464A67CA59606f0fFE159092FF2F474d69FD675

my private key is: 0x94cb9f766ef067eb229da85213439cf4cbbcd0dc97ede9479be5ee4b7a93b96f

请永远不要分享你的私钥!我这样做是因为它是一个本地私有链,我每天都要销毁并重启几次。我没有在任何公共网络上使用这个密钥对。

现在为了获得这个地址,有多种方法:

1.一种非常简单的方法是在genesis.json文件中添加此地址并启动新网络。下面是之前我的创世纪文件,其中包括我们刚刚创建的地址(删除0x)。

{

"config": {

"chainId": 1515,

"homesteadBlock": 1,

"eip150Block": 2,

"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",

"eip155Block": 3,

"eip158Block": 3,

"byzantiumBlock": 4,

"clique": {

"period": 5,

"epoch": 30000

}

},

"nonce": "0x0",

"timestamp": "0x5a722c92",

"extraData": "0x000000000000000000000000000000000000000000000000000000000000000008a58f09194e403d02a1928a7bf78646cfc260b087366ef81db496edd0ea2055ca605e8686eec1e60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",

"gasLimit": "0x8000000",

"difficulty": "0x1",

"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",

"coinbase": "0x0000000000000000000000000000000000000000",

"alloc": {

"08a58f09194e403d02a1928a7bf78646cfc260b0": {

"balance": "0x200000000000000000000000000000000000000000000000000000000000000"

},

"87366ef81db496edd0ea2055ca605e8686eec1e6": {

"balance": "0x200000000000000000000000000000000000000000000000000000000000000"

},

"F464A67CA59606f0fFE159092FF2F474d69FD675": {

"balance": "0x200000000000000000000000000000000000000000000000000000000000000"

}

},

"number": "0x0",

"gasUsed": "0x0",

"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"

}

2.如果你有可以挖矿的节点或ganache,请打开Geth Javascript控制台并手动创建交易:

$ geth attach ipc:'http://localhost:8501' // 7545 for ganache

Welcome to the Geth JavaScript console!

instance: Geth/v1.7.3-stable-4bb3c89d/linux-amd64/go1.9

coinbase: 0x87366ef81db496edd0ea2055ca605e8686eec1e6

at block: 1585 (Wed, 14 Feb 2018 11:46:04 CET)

modules: eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

> eth.sendTransaction({'from':eth.coinbase, 'to':'0xF464A67CA59606f0fFE159092FF2F474d69FD675', 'value':1000000000000000000000})

"0xdbc86acbe3644ac2cdb68132bbeecda40733c10f07ca16d87a2e5001e50eec4c"

> exit

这里我从0x87366...发送1000以太币到我的地址0xF464A...,1个以太坊是10的18次方wei(1个后跟18个零)。值的单位是wei。

3.在公共测试链上,使用faucet。

3.使用智能合约部署和交易

太好了,既然我们有一个带有一些以太网的地址(为了支付gas费用),我们可以离线创建我们的交易,签名并将其发送到具有原生JSON-RPC的HTTP请求节点。

我们将使用send_rawTransaction方法,该方法将交易的签名作为输入参数。

python代码正在查询truffle在编译智能合约时创建的包含合约abi和字节码的json文件。在测试python代码之前,创建一个truffle工作区并编译虚拟合约AdditionContract.sol。

$ truffle init

// add the smart contract in contracts/

$ truffle compile

然后更新python代码,用geth节点的URL以及truffle工作空间和genesis文件的路径(不要忘记在路径中用你的userName替换我的userName)。

其他一切都在代码中,应该是不言自明的。

pragma solidity ^0.4.18;

contract AdditionContract {

uint public state = 0;

function add(uint value1, uint value2) public {

state = value1 + value2;

}

function getState() public constant returns (uint) {

return state;

}

}

文末附完整代码。

我们让一切都变得简单易于修改和测试。 玩的开心 :)

python用web3.py库开发以太坊来说非常的方便,有兴趣的用户可以关注我们的python以太坊教程,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。

另外其他语言可以学习的以太坊教程如下:

web3j教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。

以太坊教程,主要介绍智能合约与dapp应用开发,适合入门。

以太坊开发,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。

php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和事件等内容。

C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和事件等。

汇智网原创翻译,转载请标明出处。这里是原文

raw_JSON_RPC_requests_to_smart_contract.py

# associated medium post: https://medium.com/@ethervolution/ethereum-create-raw-json-rpc-requests-with-python-for-deploying-and-transacting-with-a-smart-7ceafd6790d9

import requests

import json

import web3 # Release 4.0.0-beta.8

import pprint

import time

# create persistent HTTP connection

session = requests.Session()

w3 = web3.Web3()

pp = pprint.PrettyPrinter(indent=2)

requestId = 0 # is automatically incremented at each request

URL = 'http://localhost:8501' # url of my geth node

PATH_GENESIS = '/home/salanfe/privateNetworks/geth_PoA/genesis.json'

PATH_SC_TRUFFLE = '/home/salanfe/Projects/AdditionContract/' # smart contract path

# extracting data from the genesis file

genesisFile = json.load(open(PATH_GENESIS))

CHAINID = genesisFile['config']['chainId']

PERIOD = genesisFile['config']['clique']['period']

GASLIMIT = int(genesisFile['gasLimit'],0)

# compile your smart contract with truffle first

truffleFile = json.load(open(PATH_SC_TRUFFLE + '/build/contracts/AdditionContract.json'))

abi = truffleFile['abi']

bytecode = truffleFile['bytecode']

# Don't share your private key !

myAddress = '0xF464A67CA59606f0fFE159092FF2F474d69FD675' # address funded in genesis file

myPrivateKey = '0x94cb9f766ef067eb229da85213439cf4cbbcd0dc97ede9479be5ee4b7a93b96f'

''' =========================== SOME FUNCTIONS ============================ '''

# see http://www.jsonrpc.org/specification

# and https://github.com/ethereum/wiki/wiki/JSON-RPC

def createJSONRPCRequestObject(_method, _params, _requestId):

return {"jsonrpc":"2.0",

"method":_method,

"params":_params, # must be an array [value1, value2, ..., valueN]

"id":_requestId}, _requestId+1

def postJSONRPCRequestObject(_HTTPEnpoint, _jsonRPCRequestObject):

response = session.post(_HTTPEnpoint,

json=_jsonRPCRequestObject,

headers={'Content-type': 'application/json'})

return response.json()

''' ======================= DEPLOY A SMART CONTRACT ======================= '''

### get your nonce

requestObject, requestId = createJSONRPCRequestObject('eth_getTransactionCount', [myAddress, 'latest'], requestId)

responseObject = postJSONRPCRequestObject(URL, requestObject)

myNonce = w3.toInt(hexstr=responseObject['result'])

print('nonce of address {} is {}'.format(myAddress, myNonce))

### create your transaction

transaction_dict = {'from':myAddress,

'to':'', # empty address for deploying a new contract

'chainId':CHAINID,

'gasPrice':1, # careful with gas price, gas price below the --gasprice option of Geth CLI will cause problems. I am running my node with --gasprice '1'

'gas':2000000, # rule of thumb / guess work

'nonce':myNonce,

'data':bytecode} # no constrctor in my smart contract so bytecode is enough

### sign the transaction

signed_transaction_dict = w3.eth.account.signTransaction(transaction_dict, myPrivateKey)

params = [signed_transaction_dict.rawTransaction.hex()]

### send the transacton to your node

requestObject, requestId = createJSONRPCRequestObject('eth_sendRawTransaction', params, requestId)

responseObject = postJSONRPCRequestObject(URL, requestObject)

transactionHash = responseObject['result']

print('contract submission hash {}'.format(transactionHash))

### wait for the transaction to be mined and get the address of the new contract

while(True):

requestObject, requestId = createJSONRPCRequestObject('eth_getTransactionReceipt', [transactionHash], requestId)

responseObject = postJSONRPCRequestObject(URL, requestObject)

receipt = responseObject['result']

if(receipt is not None):

if(receipt['status'] == '0x1'):

contractAddress = receipt['contractAddress']

print('newly deployed contract at address {}'.format(contractAddress))

else:

pp.pprint(responseObject)

raise ValueError('transacation status is "0x0", failed to deploy contract. Check gas, gasPrice first')

break

time.sleep(PERIOD/10)

''' ================= SEND A TRANSACTION TO SMART CONTRACT ================'''

### get your nonce

requestObject, requestId = createJSONRPCRequestObject('eth_getTransactionCount', [myAddress, 'latest'], requestId)

responseObject = postJSONRPCRequestObject(URL, requestObject)

myNonce = w3.toInt(hexstr=responseObject['result'])

print('nonce of address {} is {}'.format(myAddress, myNonce))

### prepare the data field of the transaction

# function selector and argument encoding

# https://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector-and-argument-encoding

value1, value2 = 10, 32 # random numbers here

function = 'add(uint256,uint256)' # from smart contract

methodId = w3.sha3(text=function)[0:4].hex()

param1 = (value1).to_bytes(32, byteorder='big').hex()

param2 = (value2).to_bytes(32, byteorder='big').hex()

data = '0x' + methodId + param1 + param2

transaction_dict = {'from':myAddress,

'to':contractAddress,

'chainId':CHAINID,

'gasPrice':1, # careful with gas price, gas price below the threshold defined in the node config will cause all sorts of issues (tx not bieng broadcasted for example)

'gas':2000000, # rule of thumb / guess work

'nonce':myNonce,

'data':data}

### sign the transaction

signed_transaction_dict = w3.eth.account.signTransaction(transaction_dict, myPrivateKey)

params = [signed_transaction_dict.rawTransaction.hex()]

### send the transacton to your node

print('executing {} with value {},{}'.format(function, value1, value2))

requestObject, requestId = createJSONRPCRequestObject('eth_sendRawTransaction', params, requestId)

responseObject = postJSONRPCRequestObject(URL, requestObject)

transactionHash = responseObject['result']

print('transaction hash {}'.format(transactionHash))

### wait for the transaction to be mined

while(True):

requestObject, requestId = createJSONRPCRequestObject('eth_getTransactionReceipt', [transactionHash], requestId)

responseObject = postJSONRPCRequestObject(URL, requestObject)

receipt = responseObject['result']

if(receipt is not None):

if(receipt['status'] == '0x1'):

print('transaction successfully mined')

else:

pp.pprint(responseObject)

raise ValueError('transacation status is "0x0", failed to deploy contract. Check gas, gasPrice first')

break

time.sleep(PERIOD/10)

''' ============= READ YOUR SMART CONTRACT STATE USING GETTER =============='''

# we don't need a nonce since this does not create a transaction but only ask

# our node to read it's local database

### prepare the data field of the transaction

# function selector and argument encoding

# https://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector-and-argument-encoding

# state is declared as public in the smart contract. This creates a getter function

methodId = w3.sha3(text='state()')[0:4].hex()

data = '0x' + methodId

transaction_dict = {'from':myAddress,

'to':contractAddress,

'chainId':CHAINID,

'data':data}

params = [transaction_dict, 'latest']

requestObject, requestId = createJSONRPCRequestObject('eth_call', params, requestId)

responseObject = postJSONRPCRequestObject(URL, requestObject)

state = w3.toInt(hexstr=responseObject['result'])

print('using getter for public variables: result is {}'.format(state))

''' ============= READ YOUR SMART CONTRACT STATE GET FUNCTIONS =============='''

# we don't need a nonce since this does not create a transaction but only ask

# our node to read it's local database

### prepare the data field of the transaction

# function selector and argument encoding

# https://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector-and-argument-encoding

# state is declared as public in the smart contract. This creates a getter function

methodId = w3.sha3(text='getState()')[0:4].hex()

data = '0x' + methodId

transaction_dict = {'from':myAddress,

'to':contractAddress,

'chainId':CHAINID,

'data':data}

params = [transaction_dict, 'latest']

requestObject, requestId = createJSONRPCRequestObject('eth_call', params, requestId)

responseObject = postJSONRPCRequestObject(URL, requestObject)

state = w3.toInt(hexstr=responseObject['result'])

print('using getState() function: result is {}'.format(state))

''' prints

nonce of address 0xF464A67CA59606f0fFE159092FF2F474d69FD675 is 4

contract submission hash 0x64fc8ce5cbb5cf822674b88b52563e89f9e98132691a4d838ebe091604215b25

newly deployed contract at address 0x7e99eaa36bedba49a7f0ea4096ab2717b40d3787

nonce of address 0xF464A67CA59606f0fFE159092FF2F474d69FD675 is 5

executing add(uint256,uint256) with value 10,32

transaction hash 0xcbe3883db957cf3b643567c078081343c0cbd1fdd669320d9de9d05125168926

transaction successfully mined

using getter for public variables: result is 42

using getState() function: result is 42

'''

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_39700548/article/details/110703173

智能推荐

攻防世界_难度8_happy_puzzle_攻防世界困难模式攻略图文-程序员宅基地

文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文

达梦数据库的导出(备份)、导入_达梦数据库导入导出-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作  导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释:   cwy_init/init_123..._达梦数据库导入导出

js引入kindeditor富文本编辑器的使用_kindeditor.js-程序员宅基地

文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js

STM32学习过程记录11——基于STM32G431CBU6硬件SPI+DMA的高效WS2812B控制方法-程序员宅基地

文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6

计算机网络-数据链路层_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输

软件测试工程师移民加拿大_无证移民,未受过软件工程师的教育(第1部分)-程序员宅基地

文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...

随便推点

Thinkpad X250 secure boot failed 启动失败问题解决_安装完系统提示secureboot failure-程序员宅基地

文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure

C++如何做字符串分割(5种方法)_c++ 字符串分割-程序员宅基地

文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割

2013第四届蓝桥杯 C/C++本科A组 真题答案解析_2013年第四届c a组蓝桥杯省赛真题解答-程序员宅基地

文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答

基于供需算法优化的核极限学习机(KELM)分类算法-程序员宅基地

文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。

metasploitable2渗透测试_metasploitable2怎么进入-程序员宅基地

文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入

Python学习之路:从入门到精通的指南_python人工智能开发从入门到精通pdf-程序员宅基地

文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf