chainlib-eth

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

raw.py (5572B)


      1 # SPDX-License-Identifier: GPL-3.0-or-later
      2 
      3 # standard imports
      4 import io
      5 import sys
      6 import os
      7 import json
      8 import argparse
      9 import logging
     10 import urllib
     11 
     12 # external imports
     13 from chainlib.settings import ChainSettings
     14 from funga.eth.signer import EIP155Signer
     15 from funga.eth.keystore.dict import DictKeystore
     16 from hexathon import (
     17         add_0x,
     18         strip_0x,
     19         )
     20 from chainlib.error import SignerMissingException
     21 from chainlib.chain import ChainSpec
     22 
     23 # local imports
     24 from chainlib.eth.address import to_checksum
     25 from chainlib.eth.connection import EthHTTPConnection
     26 from chainlib.jsonrpc import (
     27         JSONRPCRequest,
     28         IntSequenceGenerator,
     29         )
     30 from chainlib.eth.nonce import (
     31         RPCNonceOracle,
     32         OverrideNonceOracle,
     33         )
     34 from chainlib.eth.gas import (
     35         RPCGasOracle,
     36         OverrideGasOracle,
     37         )
     38 from chainlib.eth.tx import (
     39         TxFactory,
     40         raw,
     41         )
     42 from chainlib.eth.jsonrpc import to_blockheight_param
     43 import chainlib.eth.cli
     44 from chainlib.eth.cli.arg import (
     45         Arg,
     46         ArgFlag,
     47         process_args,
     48         stdin_arg,
     49         )
     50 from chainlib.eth.cli.config import (
     51         Config,
     52         process_config,
     53         )
     54 from chainlib.eth.cli.log import process_log
     55 from chainlib.eth.settings import process_settings
     56 
     57 
     58 logg = logging.getLogger()
     59 
     60 script_dir = os.path.dirname(os.path.realpath(__file__)) 
     61 config_dir = os.path.join(script_dir, '..', 'data', 'config')
     62 
     63 
     64 def process_config_local(config, arg, args, flags):
     65     config.add(args.deploy, '_DEPLOY', False)
     66     config.add(args.mode, '_MODE', False)
     67     data = config.get('_POSARG')
     68 
     69     try:
     70         data = strip_0x(data)
     71     except TypeError:
     72         data = stdin_arg()
     73         data = strip_0x(data)
     74 
     75     config.add(data, '_DATA', False)
     76 
     77     return config
     78 
     79 
     80 arg_flags = ArgFlag()
     81 arg = Arg(arg_flags)
     82 flags = arg_flags.STD_WRITE | arg_flags.EXEC
     83 
     84 argparser = chainlib.eth.cli.ArgumentParser()
     85 argparser = process_args(argparser, arg, flags)
     86 argparser.add_argument('--deploy', action='store_true', help='Deploy data as contract')
     87 argparser.add_argument('--mode', choices=['tx', 'call'], type=str, help='Mode of operation')
     88 argparser.add_argument('data', type=str, help='Transaction data')
     89 args = argparser.parse_args()
     90 
     91 logg = process_log(args, logg)
     92 
     93 config = Config()
     94 config = process_config(config, arg, args, flags, positional_name='data')
     95 config = process_config_local(config, arg, args, flags)
     96 logg.debug('config loaded:\n{}'.format(config))
     97 
     98 settings = ChainSettings()
     99 settings = process_settings(settings, config)
    100 logg.debug('settings loaded:\n{}'.format(settings))
    101 
    102 
    103 def main():
    104     if config.get('_EXEC_ADDRESS') != None or config.true('_DEPLOY'):
    105         if not args.u and exec_address != exec_address:
    106             raise ValueError('invalid checksum address')
    107 
    108         if settings.get('SENDER_ADDRESS'):
    109             j = JSONRPCRequest(id_generator=settings.get('RPC_ID_GENERATOR'))
    110             o = j.template()
    111             o['method'] = 'eth_call'
    112             o['params'].append({
    113                 'to': settings.get('EXEC'),
    114                 'from': settings.get('SENDER_ADDRESS'),
    115                 'value': '0x00',
    116                 'gas': add_0x(int.to_bytes(8000000, 8, byteorder='big').hex()), # TODO: better get of network gas limit
    117                 'gasPrice': '0x01',
    118                 'data': add_0x(config.get('_DATA')),
    119                 })
    120             height = to_blockheight_param(config.get('_HEIGHT'))
    121             o['params'].append(height)
    122             o = j.finalize(o)
    123             r = settings.get('CONN').do(o)
    124             try:
    125                 print(strip_0x(r))
    126             except ValueError:
    127                 sys.stderr.write('query returned an empty value ({})\n'.format(r))
    128                 sys.exit(1)
    129 
    130         else:
    131             if settings.get('CHAIN_SPEC') == None:
    132                 raise ValueError('chain spec must be specified')
    133             g = TxFactory(
    134                     settings.get('CHAIN_SPEC'),
    135                     signer=settings.get('SIGNER'),
    136                     gas_oracle=settings.get('GAS_ORACLE'),
    137                     nonce_oracle=settings.get('NONCE_ORACLE'),
    138                 )
    139             tx = g.template(
    140                     settings.get('SENDER_ADDRESS'),
    141                     settings.get('EXEC'),
    142                     use_nonce=True,
    143                     )
    144             if config.get('_DATA') != None:
    145                 tx = g.set_code(tx, add_0x(config.get('_DATA')))
    146 
    147             (tx_hash_hex, o) = g.finalize(tx, id_generator=rpc.id_generator)
    148        
    149             if send:
    150                 r = settings.get('CONN').do(o)
    151                 print(r)
    152             else:
    153                 if config.get('_RAW'):
    154                     o = strip_0x(o)
    155                 print(o)
    156 
    157     else:
    158         o = raw(config.get('_DATA'), id_generator=settings.get('RPC_ID_GENERATOR'))
    159         if settings.get('RPC_SEND'):
    160             tx_hash_hex = settings.get('CONN').do(o)
    161             out = tx_hash_hex
    162             if config.true('_WAIT'):
    163                 #r = settings.get('CONN').wait(tx_hash_hex)
    164                 r = settings.get('CONN').wait(tx_hash_hex)
    165                 if r['status'] == 0:
    166                     logg.critical('VM revert for {}. Wish I could tell you more'.format(tx_hash_hex))
    167                     sys.exit(1)
    168                 if config.true('_RAW'):
    169                     out = json.dumps(r)
    170             sys.stdout.write(out)
    171             if not config.true('_NULL'):
    172                 sys.stdout.write('\n')
    173 
    174         else:
    175             print(o)
    176 
    177 
    178 if __name__ == '__main__':
    179     main()