Guest User

Untitled

a guest
May 22nd, 2018
262
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.11 KB | None | 0 0
  1. # associated medium post: https://medium.com/@ethervolution/ethereum-create-raw-json-rpc-requests-with-python-for-deploying-and-transacting-with-a-smart-7ceafd6790d9
  2. import requests
  3. import json
  4. import web3 # Release 4.0.0-beta.8
  5. import pprint
  6. import time
  7.  
  8. # create persistent HTTP connection
  9. session = requests.Session()
  10. w3 = web3.Web3()
  11. pp = pprint.PrettyPrinter(indent=2)
  12.  
  13. requestId = 0 # is automatically incremented at each request
  14.  
  15. URL = 'http://localhost:8501' # url of my geth node
  16. PATH_GENESIS = '/home/salanfe/privateNetworks/geth_PoA/genesis.json'
  17. PATH_SC_TRUFFLE = '/home/salanfe/Projects/AdditionContract/' # smart contract path
  18.  
  19. # extracting data from the genesis file
  20. genesisFile = json.load(open(PATH_GENESIS))
  21. CHAINID = genesisFile['config']['chainId']
  22. PERIOD = genesisFile['config']['clique']['period']
  23. GASLIMIT = int(genesisFile['gasLimit'],0)
  24.  
  25. # compile your smart contract with truffle first
  26. truffleFile = json.load(open(PATH_SC_TRUFFLE + '/build/contracts/AdditionContract.json'))
  27. abi = truffleFile['abi']
  28. bytecode = truffleFile['bytecode']
  29.  
  30. # Don't share your private key !
  31. myAddress = '0xF464A67CA59606f0fFE159092FF2F474d69FD675' # address funded in genesis file
  32. myPrivateKey = '0x94cb9f766ef067eb229da85213439cf4cbbcd0dc97ede9479be5ee4b7a93b96f'
  33.  
  34.  
  35. ''' =========================== SOME FUNCTIONS ============================ '''
  36. # see http://www.jsonrpc.org/specification
  37. # and https://github.com/ethereum/wiki/wiki/JSON-RPC
  38.  
  39. def createJSONRPCRequestObject(_method, _params, _requestId):
  40. return {"jsonrpc":"2.0",
  41. "method":_method,
  42. "params":_params, # must be an array [value1, value2, ..., valueN]
  43. "id":_requestId}, _requestId+1
  44.  
  45. def postJSONRPCRequestObject(_HTTPEnpoint, _jsonRPCRequestObject):
  46. response = session.post(_HTTPEnpoint,
  47. json=_jsonRPCRequestObject,
  48. headers={'Content-type': 'application/json'})
  49.  
  50. return response.json()
  51.  
  52.  
  53. ''' ======================= DEPLOY A SMART CONTRACT ======================= '''
  54. ### get your nonce
  55. requestObject, requestId = createJSONRPCRequestObject('eth_getTransactionCount', [myAddress, 'latest'], requestId)
  56. responseObject = postJSONRPCRequestObject(URL, requestObject)
  57. myNonce = w3.toInt(hexstr=responseObject['result'])
  58. print('nonce of address {} is {}'.format(myAddress, myNonce))
  59.  
  60. ### create your transaction
  61. transaction_dict = {'from':myAddress,
  62. 'to':'', # empty address for deploying a new contract
  63. 'chainId':CHAINID,
  64. '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'
  65. 'gas':2000000, # rule of thumb / guess work
  66. 'nonce':myNonce,
  67. 'data':bytecode} # no constrctor in my smart contract so bytecode is enough
  68.  
  69. ### sign the transaction
  70. signed_transaction_dict = w3.eth.account.signTransaction(transaction_dict, myPrivateKey)
  71. params = [signed_transaction_dict.rawTransaction.hex()]
  72.  
  73. ### send the transacton to your node
  74. requestObject, requestId = createJSONRPCRequestObject('eth_sendRawTransaction', params, requestId)
  75. responseObject = postJSONRPCRequestObject(URL, requestObject)
  76. transactionHash = responseObject['result']
  77. print('contract submission hash {}'.format(transactionHash))
  78.  
  79. ### wait for the transaction to be mined and get the address of the new contract
  80. while(True):
  81. requestObject, requestId = createJSONRPCRequestObject('eth_getTransactionReceipt', [transactionHash], requestId)
  82. responseObject = postJSONRPCRequestObject(URL, requestObject)
  83. receipt = responseObject['result']
  84. if(receipt is not None):
  85. if(receipt['status'] == '0x1'):
  86. contractAddress = receipt['contractAddress']
  87. print('newly deployed contract at address {}'.format(contractAddress))
  88. else:
  89. pp.pprint(responseObject)
  90. raise ValueError('transacation status is "0x0", failed to deploy contract. Check gas, gasPrice first')
  91. break
  92. time.sleep(PERIOD/10)
  93.  
  94.  
  95. ''' ================= SEND A TRANSACTION TO SMART CONTRACT ================'''
  96. ### get your nonce
  97. requestObject, requestId = createJSONRPCRequestObject('eth_getTransactionCount', [myAddress, 'latest'], requestId)
  98. responseObject = postJSONRPCRequestObject(URL, requestObject)
  99. myNonce = w3.toInt(hexstr=responseObject['result'])
  100. print('nonce of address {} is {}'.format(myAddress, myNonce))
  101.  
  102. ### prepare the data field of the transaction
  103. # function selector and argument encoding
  104. # https://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector-and-argument-encoding
  105. value1, value2 = 10, 32 # random numbers here
  106. function = 'add(uint256,uint256)' # from smart contract
  107. methodId = w3.sha3(text=function)[0:4].hex()
  108. param1 = (value1).to_bytes(32, byteorder='big').hex()
  109. param2 = (value2).to_bytes(32, byteorder='big').hex()
  110. data = '0x' + methodId + param1 + param2
  111.  
  112. transaction_dict = {'from':myAddress,
  113. 'to':contractAddress,
  114. 'chainId':CHAINID,
  115. '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)
  116. 'gas':2000000, # rule of thumb / guess work
  117. 'nonce':myNonce,
  118. 'data':data}
  119.  
  120. ### sign the transaction
  121. signed_transaction_dict = w3.eth.account.signTransaction(transaction_dict, myPrivateKey)
  122. params = [signed_transaction_dict.rawTransaction.hex()]
  123.  
  124. ### send the transacton to your node
  125. print('executing {} with value {},{}'.format(function, value1, value2))
  126. requestObject, requestId = createJSONRPCRequestObject('eth_sendRawTransaction', params, requestId)
  127. responseObject = postJSONRPCRequestObject(URL, requestObject)
  128. transactionHash = responseObject['result']
  129. print('transaction hash {}'.format(transactionHash))
  130.  
  131. ### wait for the transaction to be mined
  132. while(True):
  133. requestObject, requestId = createJSONRPCRequestObject('eth_getTransactionReceipt', [transactionHash], requestId)
  134. responseObject = postJSONRPCRequestObject(URL, requestObject)
  135. receipt = responseObject['result']
  136. if(receipt is not None):
  137. if(receipt['status'] == '0x1'):
  138. print('transaction successfully mined')
  139. else:
  140. pp.pprint(responseObject)
  141. raise ValueError('transacation status is "0x0", failed to deploy contract. Check gas, gasPrice first')
  142. break
  143. time.sleep(PERIOD/10)
  144.  
  145.  
  146.  
  147. ''' ============= READ YOUR SMART CONTRACT STATE USING GETTER =============='''
  148. # we don't need a nonce since this does not create a transaction but only ask
  149. # our node to read it's local database
  150.  
  151. ### prepare the data field of the transaction
  152. # function selector and argument encoding
  153. # https://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector-and-argument-encoding
  154. # state is declared as public in the smart contract. This creates a getter function
  155. methodId = w3.sha3(text='state()')[0:4].hex()
  156. data = '0x' + methodId
  157. transaction_dict = {'from':myAddress,
  158. 'to':contractAddress,
  159. 'chainId':CHAINID,
  160. 'data':data}
  161.  
  162. params = [transaction_dict, 'latest']
  163. requestObject, requestId = createJSONRPCRequestObject('eth_call', params, requestId)
  164. responseObject = postJSONRPCRequestObject(URL, requestObject)
  165. state = w3.toInt(hexstr=responseObject['result'])
  166. print('using getter for public variables: result is {}'.format(state))
  167.  
  168.  
  169.  
  170. ''' ============= READ YOUR SMART CONTRACT STATE GET FUNCTIONS =============='''
  171. # we don't need a nonce since this does not create a transaction but only ask
  172. # our node to read it's local database
  173.  
  174. ### prepare the data field of the transaction
  175. # function selector and argument encoding
  176. # https://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector-and-argument-encoding
  177. # state is declared as public in the smart contract. This creates a getter function
  178. methodId = w3.sha3(text='getState()')[0:4].hex()
  179. data = '0x' + methodId
  180. transaction_dict = {'from':myAddress,
  181. 'to':contractAddress,
  182. 'chainId':CHAINID,
  183. 'data':data}
  184.  
  185. params = [transaction_dict, 'latest']
  186. requestObject, requestId = createJSONRPCRequestObject('eth_call', params, requestId)
  187. responseObject = postJSONRPCRequestObject(URL, requestObject)
  188. state = w3.toInt(hexstr=responseObject['result'])
  189. print('using getState() function: result is {}'.format(state))
  190.  
  191.  
  192. ''' prints
  193. nonce of address 0xF464A67CA59606f0fFE159092FF2F474d69FD675 is 4
  194. contract submission hash 0x64fc8ce5cbb5cf822674b88b52563e89f9e98132691a4d838ebe091604215b25
  195. newly deployed contract at address 0x7e99eaa36bedba49a7f0ea4096ab2717b40d3787
  196. nonce of address 0xF464A67CA59606f0fFE159092FF2F474d69FD675 is 5
  197. executing add(uint256,uint256) with value 10,32
  198. transaction hash 0xcbe3883db957cf3b643567c078081343c0cbd1fdd669320d9de9d05125168926
  199. transaction successfully mined
  200. using getter for public variables: result is 42
  201. using getState() function: result is 42
  202.  
  203. Traceback (most recent call last):
  204. File "Transaction.py", line 84, in <module>
  205. signed_transaction_dict = w3.eth.account.signTransaction(transaction_dict, myPrivateKey)
  206. File "/home/nicer/anaconda3/lib/python3.6/site-packages/eth_utils/decorators.py", line 17, in _wrapper
  207. return self.method(obj, *args, **kwargs)
  208. File "/home/nicer/anaconda3/lib/python3.6/site-packages/eth_account/account.py", line 437, in signTransaction
  209. ) = sign_transaction_dict(account._key_obj, sanitized_transaction)
  210. File "/home/nicer/anaconda3/lib/python3.6/site-packages/eth_account/internal/signing.py", line 23, in sign_transaction_dict
  211. unsigned_transaction = serializable_unsigned_transaction_from_dict(transaction_dict)
  212. File "/home/nicer/anaconda3/lib/python3.6/site-packages/eth_account/internal/transactions.py", line 35, in serializable_unsigned_transaction_from_dict
  213. assert_valid_fields(transaction_dict)
  214. File "/home/nicer/anaconda3/lib/python3.6/site-packages/eth_account/internal/transactions.py", line 140, in assert_valid_fields
  215. raise TypeError("Transaction had invalid fields: %r" % invalid)
  216. TypeError: Transaction had invalid fields: {'to': 1040173929365648531876217761296795527146824984604}
Add Comment
Please, Sign In to add comment