chainlib-eth

Ethereum implementation of the chainlib interface
Info | Log | Files | Refs | README | LICENSE

contract_transaction.py (2436B)


      1 # standard imports
      2 import os
      3 
      4 # external imports
      5 from crypto_dev_signer.keystore.dict import DictKeystore
      6 from crypto_dev_signer.eth.signer import ReferenceSigner as EIP155Signer
      7 from hexathon import (
      8         add_0x,
      9         strip_0x,
     10         )
     11 
     12 # local imports
     13 from chainlib.chain import ChainSpec
     14 from chainlib.eth.nonce import OverrideNonceOracle
     15 from chainlib.eth.gas import OverrideGasOracle
     16 from chainlib.eth.tx import (
     17         TxFactory,
     18         TxFormat,
     19         unpack,
     20         pack,
     21         raw,
     22         )
     23 from chainlib.eth.contract import (
     24         ABIContractEncoder,
     25         ABIContractDecoder,
     26         ABIContractType,
     27         )
     28 
     29 # eth transactions need an explicit chain parameter as part of their signature
     30 chain_spec = ChainSpec.from_chain_str('evm:ethereum:1')
     31 
     32 # create keystore and signer
     33 keystore = DictKeystore()
     34 signer = EIP155Signer(keystore)
     35 sender_address = keystore.new()
     36 recipient_address = keystore.new()
     37 
     38 # explicitly set nonce and gas parameters on this transaction
     39 nonce_oracle = OverrideNonceOracle(sender_address, 0)
     40 gas_oracle = OverrideGasOracle(price=1000000000, limit=21000)
     41 
     42 # encode the contract parameters
     43 enc = ABIContractEncoder()
     44 enc.method('fooBar')
     45 enc.typ(ABIContractType.ADDRESS)
     46 enc.typ(ABIContractType.UINT256)
     47 enc.address(recipient_address)
     48 enc.uint256(42)
     49 data = enc.get()
     50 
     51 # create a new transaction, but output in raw rlp format 
     52 tx_factory = TxFactory(chain_spec, signer=signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle)
     53 tx = tx_factory.template(sender_address, recipient_address, use_nonce=True)
     54 tx = tx_factory.set_code(tx, data)
     55 (tx_hash, tx_signed_raw) = tx_factory.finalize(tx, tx_format=TxFormat.RLP_SIGNED)
     56 
     57 print('contract transaction: {}'.format(tx))
     58 
     59 # retrieve the input data from the transaction
     60 tx_src = unpack(bytes.fromhex(strip_0x(tx_signed_raw)), chain_spec)
     61 data_recovered = strip_0x(tx_src['data'])
     62 
     63 # decode the contract parameters 
     64 dec = ABIContractDecoder()
     65 dec.typ(ABIContractType.ADDRESS)
     66 dec.typ(ABIContractType.UINT256)
     67 # (yes, this interface needs to be vastly improved, it should take the whole buffer and advance with cursor itself)
     68 cursor = 8 # the method signature is 8 characters long. input data to the solidity function starts after that
     69 dec.val(data_recovered[cursor:cursor+64])
     70 cursor += 64
     71 dec.val(data_recovered[cursor:cursor+64])
     72 r = dec.decode()
     73 
     74 print('contract param 1 {}'.format(r[0]))
     75 print('contract param 2 {}'.format(r[1]))