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()