Compare commits

..

No commits in common. "master" and "lash/more-logging" have entirely different histories.

36 changed files with 55 additions and 530 deletions

View File

@ -1,22 +1,3 @@
- 0.1.1
* Add fee_limit, fee_price alias to Tx object
- 0.1.0:
* Allow nonce ommission in encode when not tx mode
* Add rcpt src to tx object
- 0.0.27:
* Add man pages with chainlib man page generator helper
* Remove redundant arg flags from runnables: get
- 0.0.26:
* Remove manual 0x handling bug in tx
- 0.0.25:
* Upgrade chainlib to get passphrase file for wallet keyfile
- 0.0.24:
* Upgrade from hexathon bug breaking compact hex function
- 0.0.23:
* Make get block args and responses compatible with picky golang marhaling in geth
- 0.0.22:
* Enable unpack of pre EIP-155 transactions
* Allow missing status property of receipts in non-strict modes
- 0.0.21: - 0.0.21:
* Remove warnings from cytoolz/rlp in funga-eth * Remove warnings from cytoolz/rlp in funga-eth
- 0.0.15: - 0.0.15:

View File

@ -1,16 +0,0 @@
PREFIX ?= /usr/local
BUILD_DIR = build/$(PREFIX)/share/man
man:
mkdir -vp $(BUILD_DIR)
chainlib-man.py -b `PYTHONPATH=. python chainlib/eth/runnable/flags.py gas` -v -n eth-gas -d $(BUILD_DIR)/ man
chainlib-man.py -b `PYTHONPATH=. python chainlib/eth/runnable/flags.py info` -v -n eth-info -d $(BUILD_DIR)/ man
chainlib-man.py -b `PYTHONPATH=. python chainlib/eth/runnable/flags.py get` -v -n eth-get -d $(BUILD_DIR)/ man
chainlib-man.py -b `PYTHONPATH=. python chainlib/eth/runnable/flags.py decode` -v -n eth-decode -d $(BUILD_DIR)/ man
chainlib-man.py -b `PYTHONPATH=. python chainlib/eth/runnable/flags.py encode` -v -n eth-encode -d $(BUILD_DIR)/ man
chainlib-man.py -b `PYTHONPATH=. python chainlib/eth/runnable/flags.py count` -v -n eth-count -d $(BUILD_DIR)/ man
chainlib-man.py -b `PYTHONPATH=. python chainlib/eth/runnable/flags.py raw` -v -n eth-raw -d $(BUILD_DIR)/ man
chainlib-man.py -b `PYTHONPATH=. python chainlib/eth/runnable/flags.py wait` -v -n eth-wait -d $(BUILD_DIR)/ man
chainlib-man.py -b `PYTHONPATH=. python chainlib/eth/runnable/flags.py balance` -v -n eth-balance -d $(BUILD_DIR)/ man
.PHONY: man

View File

@ -1,11 +1,10 @@
import sys
# external imports # external imports
from chainlib.jsonrpc import JSONRPCRequest from chainlib.jsonrpc import JSONRPCRequest
from chainlib.block import Block as BaseBlock from chainlib.block import Block as BaseBlock
from hexathon import ( from hexathon import (
add_0x, add_0x,
strip_0x, strip_0x,
compact, even,
) )
# local imports # local imports
@ -35,8 +34,7 @@ def block_by_hash(hsh, include_tx=True, id_generator=None):
def block_by_number(n, include_tx=True, id_generator=None): def block_by_number(n, include_tx=True, id_generator=None):
"""Implements chainlib.interface.ChainInterface method """Implements chainlib.interface.ChainInterface method
""" """
hx = strip_0x(hex(n)) nhx = add_0x(even(hex(n)[2:]))
nhx = add_0x(compact(hx), compact_value=True)
j = JSONRPCRequest(id_generator) j = JSONRPCRequest(id_generator)
o = j.template() o = j.template()
o['method'] = 'eth_getBlockByNumber' o['method'] = 'eth_getBlockByNumber'

View File

@ -4,7 +4,6 @@ from chainlib.cli import (
argflag_std_read, argflag_std_read,
argflag_std_write, argflag_std_write,
argflag_std_base, argflag_std_base,
argflag_std_base_read, reset as argflag_reset,
flag_reset as argflag_reset,
Flag, Flag,
) )

View File

@ -1,2 +0,0 @@
[rpc]
provider = Fully-qualified URL to EVM node's RPC endpoint.

View File

@ -25,7 +25,7 @@ logg = logging.getLogger()
script_dir = os.path.dirname(os.path.realpath(__file__)) script_dir = os.path.dirname(os.path.realpath(__file__))
config_dir = os.path.join(script_dir, '..', 'data', 'config') config_dir = os.path.join(script_dir, '..', 'data', 'config')
arg_flags = chainlib.eth.cli.argflag_std_base_read | chainlib.eth.cli.Flag.WALLET arg_flags = chainlib.eth.cli.argflag_std_read
argparser = chainlib.eth.cli.ArgumentParser(arg_flags) argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
argparser.add_positional('address', type=str, help='Ethereum address of recipient') argparser.add_positional('address', type=str, help='Ethereum address of recipient')
args = argparser.parse_args() args = argparser.parse_args()

View File

@ -11,7 +11,8 @@ import urllib
import sha3 import sha3
# external imports # external imports
from chainlib.cli import flag_reset import chainlib.eth.cli
from chainlib.eth.cli.encode import CLIEncoder
from funga.eth.signer import EIP155Signer from funga.eth.signer import EIP155Signer
from funga.eth.keystore.dict import DictKeystore from funga.eth.keystore.dict import DictKeystore
from hexathon import ( from hexathon import (
@ -20,8 +21,6 @@ from hexathon import (
) )
# local imports # local imports
import chainlib.eth.cli
from chainlib.eth.cli.encode import CLIEncoder
from chainlib.eth.constant import ZERO_ADDRESS from chainlib.eth.constant import ZERO_ADDRESS
from chainlib.eth.address import to_checksum from chainlib.eth.address import to_checksum
from chainlib.eth.connection import EthHTTPConnection from chainlib.eth.connection import EthHTTPConnection
@ -29,6 +28,14 @@ from chainlib.jsonrpc import (
JSONRPCRequest, JSONRPCRequest,
IntSequenceGenerator, IntSequenceGenerator,
) )
from chainlib.eth.nonce import (
RPCNonceOracle,
OverrideNonceOracle,
)
from chainlib.eth.gas import (
RPCGasOracle,
OverrideGasOracle,
)
from chainlib.eth.tx import ( from chainlib.eth.tx import (
TxFactory, TxFactory,
TxFormat, TxFormat,
@ -46,20 +53,18 @@ logg = logging.getLogger()
script_dir = os.path.dirname(os.path.realpath(__file__)) script_dir = os.path.dirname(os.path.realpath(__file__))
config_dir = os.path.join(script_dir, '..', 'data', 'config') config_dir = os.path.join(script_dir, '..', 'data', 'config')
arg_flags = chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.EXEC | chainlib.eth.cli.Flag.FEE
arg_flags = chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.EXEC | chainlib.eth.cli.Flag.FEE | chainlib.eth.cli.Flag.FMT_HUMAN | chainlib.eth.cli.Flag.FMT_WIRE | chainlib.eth.cli.Flag.FMT_RPC
arg_flags = flag_reset(arg_flags, chainlib.cli.Flag.NO_TARGET)
argparser = chainlib.eth.cli.ArgumentParser(arg_flags) argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
argparser.add_argument('--mode', type=str, choices=['tx', 'call', 'arg'], help='Mode of operation') argparser.add_argument('--notx', action='store_true', help='Network send is not a transaction')
argparser.add_argument('--signature', type=str, help='Method signature to encode') argparser.add_argument('--signature', type=str, help='Method signature to encode')
argparser.add_argument('contract_args', type=str, nargs='*', help='arguments to encode') argparser.add_argument('contract_args', type=str, nargs='*', help='arguments to encode')
args = argparser.parse_args() args = argparser.parse_args()
extra_args = { extra_args = {
'signature': None, 'signature': None,
'contract_args': None, 'contract_args': None,
'notx': None,
} }
config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args, default_config_dir=config_dir) config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args, default_config_dir=config_dir)
logg.debug('config loaded:\n{}'.format(config))
block_all = args.ww block_all = args.ww
block_last = args.w or block_all block_last = args.w or block_all
@ -97,64 +102,28 @@ def main():
code += cli_encoder.get() code += cli_encoder.get()
if not config.get('_SIGNATURE'):
print(strip_0x(code))
return
exec_address = config.get('_EXEC_ADDRESS') exec_address = config.get('_EXEC_ADDRESS')
if exec_address: if exec_address:
exec_address = add_0x(to_checksum_address(exec_address)) exec_address = add_0x(to_checksum_address(exec_address))
mode = args.mode if signer == None or config.true('_NOTX'):
if mode == None: if config.true('_RAW'):
if signer == None:
mode = 'call'
else:
mode = 'tx'
if not config.get('_SIGNATURE'):
if mode != 'arg':
logg.error('mode tx without contract method signature makes no sense. Use eth-get with --data instead.')
sys.exit(1)
if args.format == 'rpc':
logg.error('rpc format with arg put does not make sense')
sys.exit(1)
if mode == 'arg':
print(strip_0x(code)) print(strip_0x(code))
return return
elif not exec_address:
logg.error('exec address (-e) must be defined with mode "{}"'.format(args.mode))
sys.exit(1)
if config.get('RPC_PROVIDER'): if not exec_address:
logg.debug('provider {}'.format(config.get('RPC_PROVIDER'))) argparser.error('exec address (-e) must be defined')
if not config.get('_FEE_LIMIT') or not config.get('_FEE_PRICE'):
gas_oracle = rpc.get_gas_oracle()
(price, limit) = gas_oracle.get_gas()
if not config.get('_FEE_PRICE'):
config.add(price, '_FEE_PRICE')
if not config.get('_FEE_LIMIT'):
config.add(limit, '_FEE_LIMIT')
if mode == 'tx':
if not config.get('_NONCE'):
nonce_oracle = rpc.get_nonce_oracle()
config.add(nonce_oracle.get_nonce(), '_NONCE')
else:
for arg in [
'_FEE_PRICE',
'_FEE_LIMIT',
'_NONCE',
]:
if not config.get(arg):
logg.error('--{} must be specified when no rpc provider has been set.'.format(arg.replace('_', '-').lower()))
sys.exit(1)
if mode == 'call': #signer == None or config.true('_NOTX'):
c = TxFactory(chain_spec) c = TxFactory(chain_spec)
j = JSONRPCRequest(id_generator=rpc.id_generator) j = JSONRPCRequest(id_generator=rpc.id_generator)
o = j.template() o = j.template()
o['method'] = 'eth_call'
gas_limit = add_0x(int.to_bytes(config.get('_FEE_LIMIT'), 8, byteorder='big').hex(), compact_value=True) gas_limit = add_0x(int.to_bytes(config.get('_FEE_LIMIT'), 8, byteorder='big').hex(), compact_value=True)
gas_price = add_0x(int.to_bytes(config.get('_FEE_PRICE'), 8, byteorder='big').hex(), compact_value=True) gas_price = add_0x(int.to_bytes(config.get('_FEE_PRICE'), 8, byteorder='big').hex(), compact_value=True)
o['method'] = 'eth_call'
o['params'].append({ o['params'].append({
'to': exec_address, 'to': exec_address,
'from': signer_address, 'from': signer_address,
@ -166,8 +135,6 @@ def main():
height = to_blockheight_param(config.get('_HEIGHT')) height = to_blockheight_param(config.get('_HEIGHT'))
o['params'].append(height) o['params'].append(height)
o = j.finalize(o) o = j.finalize(o)
if config.get('_RPC_SEND'):
r = conn.do(o) r = conn.do(o)
try: try:
print(strip_0x(r)) print(strip_0x(r))
@ -175,13 +142,9 @@ def main():
except ValueError: except ValueError:
sys.stderr.write('query returned an empty value ({})\n'.format(r)) sys.stderr.write('query returned an empty value ({})\n'.format(r))
sys.exit(1) sys.exit(1)
else:
print(o)
return
if signer == None: if not exec_address:
logg.error('mode "tx" without signer does not make sense. Please specify a key file with -y.') argparser.error('exec address (-e) must be defined')
sys.exit(1)
if chain_spec == None: if chain_spec == None:
raise ValueError('chain spec must be specified') raise ValueError('chain spec must be specified')

View File

@ -1,23 +0,0 @@
# standard imports
import sys
# external imports
import chainlib.eth.cli
from hexathon import add_0x
cmds = {
'gas': chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.WALLET,
'info': chainlib.eth.cli.argflag_reset(chainlib.cli.argflag_std_base_read, chainlib.eth.cli.Flag.CHAIN_SPEC),
'get': chainlib.eth.cli.argflag_reset(chainlib.cli.argflag_std_base_read, chainlib.eth.cli.Flag.CHAIN_SPEC),
'decode': chainlib.cli.argflag_std_base | chainlib.eth.cli.Flag.CHAIN_SPEC,
'encode': chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.EXEC | chainlib.eth.cli.Flag.FEE | chainlib.eth.cli.Flag.FMT_HUMAN | chainlib.eth.cli.Flag.FMT_WIRE | chainlib.eth.cli.Flag.FMT_RPC,
'count': chainlib.eth.cli.argflag_std_base_read | chainlib.eth.cli.Flag.WALLET,
'raw': chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.EXEC,
'balance': chainlib.eth.cli.argflag_std_base | chainlib.eth.cli.Flag.WALLET,
'wait': chainlib.eth.cli.argflag_reset(chainlib.eth.cli.argflag_std_base_read | chainlib.eth.cli.Flag.NO_TARGET | chainlib.eth.cli.Flag.RPC_AUTH, chainlib.eth.cli.Flag.CHAIN_SPEC | chainlib.eth.cli.Flag.RAW),
'checksum': 0,
}
if __name__ == '__main__':
b = cmds[sys.argv[1]]
print(add_0x(hex(b)))

View File

@ -48,8 +48,7 @@ logg = logging.getLogger()
script_dir = os.path.dirname(os.path.realpath(__file__)) script_dir = os.path.dirname(os.path.realpath(__file__))
config_dir = os.path.join(script_dir, '..', 'data', 'config') config_dir = os.path.join(script_dir, '..', 'data', 'config')
arg_flags = chainlib.eth.cli.argflag_std_base_read arg_flags = chainlib.eth.cli.argflag_std_read
arg_flags = chainlib.eth.cli.argflag_reset(arg_flags, chainlib.eth.cli.Flag.CHAIN_SPEC)
argparser = chainlib.eth.cli.ArgumentParser(arg_flags) argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
argparser.add_positional('item', type=str, help='Address or transaction to retrieve data for') argparser.add_positional('item', type=str, help='Address or transaction to retrieve data for')
args = argparser.parse_args() args = argparser.parse_args()

View File

@ -105,10 +105,7 @@ def main():
o = block_latest(id_generator=rpc.id_generator) o = block_latest(id_generator=rpc.id_generator)
r = conn.do(o) r = conn.do(o)
try:
n = int(r, 16) n = int(r, 16)
except ValueError:
n = int(r)
first_block_number = n first_block_number = n
if human: if human:
n = format(n, ',') n = format(n, ',')

View File

@ -51,7 +51,6 @@ config_dir = os.path.join(script_dir, '..', 'data', 'config')
arg_flags = chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.EXEC arg_flags = chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.EXEC
argparser = chainlib.eth.cli.ArgumentParser(arg_flags) argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
argparser.add_argument('--deploy', action='store_true', help='Deploy data as contract') argparser.add_argument('--deploy', action='store_true', help='Deploy data as contract')
argparser.add_argument('--mode', choices=['tx', 'call'], type=str, help='Mode of operation')
argparser.add_positional('data', type=str, help='Transaction data') argparser.add_positional('data', type=str, help='Transaction data')
args = argparser.parse_args() args = argparser.parse_args()
config = chainlib.eth.cli.Config.from_args(args, arg_flags, default_config_dir=config_dir) config = chainlib.eth.cli.Config.from_args(args, arg_flags, default_config_dir=config_dir)

View File

@ -95,11 +95,7 @@ def pack(tx_src, chain_spec):
tx_src['r'], tx_src['r'],
tx_src['s'], tx_src['s'],
]: ]:
try: for b in bytes.fromhex(strip_0x(a)):
a = strip_0x(a)
except TypeError:
a = strip_0x(hex(a)) # believe it or not, eth_tester returns signatures as ints not hex
for b in bytes.fromhex(a):
signature[cursor] = b signature[cursor] = b
cursor += 1 cursor += 1
@ -166,7 +162,6 @@ def __unpack_raw(tx_raw_bytes, chain_id=1):
vb = chain_id vb = chain_id
if chain_id != 0: if chain_id != 0:
v = int.from_bytes(d[6], 'big') v = int.from_bytes(d[6], 'big')
if v > 29:
vb = v - (chain_id * 2) - 35 vb = v - (chain_id * 2) - 35
r = bytearray(32) r = bytearray(32)
r[32-len(d[7]):] = d[7] r[32-len(d[7]):] = d[7]
@ -401,13 +396,11 @@ class TxFactory:
""" """
txe = EIP155Transaction(tx, tx['nonce'], tx['chainId']) txe = EIP155Transaction(tx, tx['nonce'], tx['chainId'])
txes = txe.serialize() txes = txe.serialize()
gas_price = strip_0x(txes['gasPrice'])
gas = strip_0x(txes['gas'])
return { return {
'from': tx['from'], 'from': tx['from'],
'to': txes['to'], 'to': txes['to'],
'gasPrice': add_0x(compact(gas_price)), 'gasPrice': '0x' + compact(txes['gasPrice']),
'gas': add_0x(compact(gas)), 'gas': '0x' + compact(txes['gas']),
'data': txes['data'], 'data': txes['data'],
} }
@ -429,8 +422,6 @@ class TxFactory:
return self.build_raw(tx) return self.build_raw(tx)
elif tx_format == TxFormat.RAW_ARGS: elif tx_format == TxFormat.RAW_ARGS:
return strip_0x(tx['data']) return strip_0x(tx['data'])
elif tx_format == TxFormat.DICT:
return tx
raise NotImplementedError('tx formatting {} not implemented'.format(tx_format)) raise NotImplementedError('tx formatting {} not implemented'.format(tx_format))
@ -527,7 +518,7 @@ class Tx(BaseTx):
#:todo: divide up constructor method #:todo: divide up constructor method
""" """
def __init__(self, src, block=None, rcpt=None, strict=False): def __init__(self, src, block=None, rcpt=None):
self.__rcpt_block_hash = None self.__rcpt_block_hash = None
src = self.src_normalize(src) src = self.src_normalize(src)
@ -556,9 +547,6 @@ class Tx(BaseTx):
self.outputs = [to_checksum(address_from)] self.outputs = [to_checksum(address_from)]
self.contract = None self.contract = None
self.fee_limit = self.gas_limit
self.fee_price = self.gas_price
try: try:
inpt = src['input'] inpt = src['input']
except KeyError: except KeyError:
@ -580,14 +568,13 @@ class Tx(BaseTx):
try: try:
self.wire = src['raw'] self.wire = src['raw']
except KeyError: except KeyError:
logg.debug('no inline raw tx src, and no raw rendering implemented, field will be "None"') logg.warning('no inline raw tx src, and no raw rendering implemented, field will be "None"')
self.status = Status.PENDING self.status = Status.PENDING
self.logs = None self.logs = None
self.tx_rcpt_src = None
if rcpt != None: if rcpt != None:
self.apply_receipt(rcpt, strict=strict) self.apply_receipt(rcpt)
self.v = src.get('v') self.v = src.get('v')
self.r = src.get('r') self.r = src.get('r')
@ -630,11 +617,7 @@ class Tx(BaseTx):
return self.src() return self.src()
def rcpt_src(self): def apply_receipt(self, rcpt):
return self.tx_rcpt_src
def apply_receipt(self, rcpt, strict=False):
"""Apply receipt data to transaction object. """Apply receipt data to transaction object.
Effect is the same as passing a receipt at construction. Effect is the same as passing a receipt at construction.
@ -644,7 +627,6 @@ class Tx(BaseTx):
""" """
rcpt = self.src_normalize(rcpt) rcpt = self.src_normalize(rcpt)
logg.debug('rcpt {}'.format(rcpt)) logg.debug('rcpt {}'.format(rcpt))
self.tx_rcpt_src = rcpt
tx_hash = add_0x(rcpt['transaction_hash']) tx_hash = add_0x(rcpt['transaction_hash'])
if rcpt['transaction_hash'] != add_0x(self.hash): if rcpt['transaction_hash'] != add_0x(self.hash):
@ -659,12 +641,6 @@ class Tx(BaseTx):
status_number = int(rcpt['status'], 16) status_number = int(rcpt['status'], 16)
except TypeError: except TypeError:
status_number = int(rcpt['status']) status_number = int(rcpt['status'])
except KeyError as e:
if strict:
raise(e)
logg.debug('setting "success" status on missing status property for {}'.format(self.hash))
status_number = 1
if rcpt['block_number'] == None: if rcpt['block_number'] == None:
self.status = Status.PENDING self.status = Status.PENDING
else: else:
@ -719,12 +695,12 @@ class Tx(BaseTx):
@staticmethod @staticmethod
def from_src(src, block=None, rcpt=None, strict=False): def from_src(src, block=None, rcpt=None):
"""Creates a new Tx object. """Creates a new Tx object.
Alias of constructor. Alias of constructor.
""" """
return Tx(src, block=block, rcpt=rcpt, strict=strict) return Tx(src, block=block, rcpt=rcpt)
def __str__(self): def __str__(self):

View File

@ -1,16 +0,0 @@
.TH eth-balance 1
.SH NAME
eth-balance \- Get network gas token balance for an address
.SH SYNOPSIS
\fBeth-balance\fP [ -p \fIrpc_provider\fP ] \fIaddress\fP
.SH DESCRIPTION
.P
Query the network for the gas token balance of an account.
.P
The balance will be returned as an integer value denominated in the gas unit.
.SS OPTION

View File

@ -1 +0,0 @@
a Address to get balance for. -a, --address

View File

@ -1,7 +0,0 @@
.SH ABOUT THE CHECKSUM
.P
Checksum protection may be used as protection against address typos.
.P
It uses the value of the address itself as input to an algorithm, which results in altering the case of the letters in the hexadecimal address.
.P
A checksum address consisting of only numbers will always pass checksum.

View File

@ -1,11 +0,0 @@
.TH eth-checksum 1
.SH NAME
eth-checksum \- Calculate checksum address
.SH SYNOPSIS
\fBeth-checksum\fP \fIaddress\fP
.SH DESCRIPTION
.P
Converts \fIaddress\fP into a checksum-protected address.

View File

@ -1,15 +0,0 @@
.TH eth-count 1
.SH NAME
eth-count \- Get transaction count for an address
.SH SYNOPSIS
\fBeth-count\fP [ -p \fIrpc_provider\fP ] \fIaddress\fP
.SH DESCRIPTION
.P
Query the network for the number of transactions known for an account. The result can be used as the \fInonce\fP value for a consecutive transaction.
.SS OPTIONS

View File

@ -1 +0,0 @@
a Address to count transactions for. -a, --address

View File

@ -1,14 +0,0 @@
.TH eth-decode 1
.SH NAME
eth-decode \- Decode a transaction in wire-format to human readable form
.SH SYNOPSIS
\fBeth-decode\fI [ -i \fIchain_spec\fP ] encoded_tx
.SH DESCRIPTION
.P
This tool deserializes a wire-format transaction and outputs its fields in human-readable form. It does not require a node to operate, and does not apply transaction state.
.P
The transaction wire-format is an ordered concatenation of transaction values, which in turn is serialized using the Recurive Length Prefix (RLP) format. \fBeth-decode\fP accepts the RLP-encoded transaction as a hex string.
.P

View File

@ -1,31 +0,0 @@
.SH MODES
The modes parameter specifies what kind of operaion the encoding should be generated for. There are three valid modes:
.SS tx
Generates a transaction that changes state. Used with \fB--format\fP \fIrpc\fP it will generate an \fIeth_sendRawTransaction\fP jsonrpc object. Used with \fB--format\fP \fIbin\fP it outputs signed RLP only in hexdecimal.
.SS call
Generates a query that reads state. Used with \fB--format\fP \fIrpc\fP it will generate a \fIeth_call\fP jsonrpc object with applicable fields filled out from environment, arguments and/or rpc retrieval. \fB--format\fP \fIbin\fP is not valid for this mode.
.SS arg
Encodes the argument part only, optionally with a method signature. \fB--format\fP \fIrpc\fP is not valid for this mode.
.SH SPECIFYING VALUES
Dynamic value types are not yet supported.
.SS Specifying an unsigned integer:
.IP u:1024
.SS Specifying an address:
.IP a:19062190B1925b5b6689D7073fDfC8c2976EF8Cb
.SS Specifying bytes values:
.IP b:deadbeef
.IP b4:deadbeef
.IP b32:deadbeef
.SS Specifying a string value:
.IP s:foobar

View File

@ -1,22 +0,0 @@
.SS Build a signed ERC20 transfer in wire format, setting nonce and fee details manually.
.EX
$ eth-encode -f bin -y <\fIkey_file_path\fP> -e <\fItoken_address\fP> --fee-price 1000000000 --fee-limit 100000 --nonce 42 --signature transfer a:00000000000000000000000000000000DeaDBeef u:1024
.EE
.SS Build Smart contract call with method signature, retrieving fee and nonce settings from rpc
\fBeth-encode\fP --mode call -f rpc -e <\fItoken_address\fP> --signature balanceOf -p <\fIrpc_endpoint\fP> a:deadbeef
.SS Build smart contract ERC20 transfer argument with signature
.EX
\fBeth-encode\fP --mode arg --signature transfer a:00000000000000000000000000000000DeaDBeef u:1024
.TP Outupt
a9059cbb00000000000000000000000000000000000000000000000000000000deadbeef0000000000000000000000000000000000000000000000000000000000000400
.EE
.SS Build smart contract ERC20 transfer argument types without signature
.EX
\fBeth-encode\fP --mode arg a:00000000000000000000000000000000DeaDBeef u:1024
.TP Output
00000000000000000000000000000000000000000000000000000000deadbeef0000000000000000000000000000000000000000000000000000000000000400
.EE

View File

@ -1,17 +0,0 @@
.TH eth-encode 1
.SH NAME
eth-encode \- Encode arbitrary contract calls and transactions
.SH SYNOPSIS
\fBeth-encode\fP [ --mode \fImode\fP ] [ -f \fIformat\fP ] [ -p \fIrpc_provider\fP ] [ -i \fIchain_Spec\fP] [ -s ] [ -w ] [ -e \fIsmart_contract_address\fP ] --signature \fIcontract_method_name\fP [ \fIvalue_specifiers\fP ... ]
.SH DESCRIPTION
Generate wire-format or rpc query any EVM smart contract call or transaction by specifying method and arguments.
The resulting call or transaction can either be stored offline for later use, or directly sent to the network using the \fB-s\fP option.
A description of value formatting is given in the \fBSPECIFYING VALUES\fP section below. Usage is demonstrated in the \fBEXAMPLES\fP section.
.SS OPTIONS

View File

@ -1 +0,0 @@
mode Mode of operation encoding is for. Must be one of "tx," "call," or "arg." See \fBMODES\fP below. --mode mode

View File

@ -1,75 +0,0 @@
.P
In the follwing we willconsaider transactions signed by the private key for address Eb3907eCad74a0013c259D5874AE7f22DcBcC95C:
.SS Offline transaction
.EX
$ eth-gas -y <\fIkey_file_path\fP> -a 00000000000000000000000000000000DeaDBeef --fee-price 100000000000 --fee-limit 21000 --nonce 42 1024
from: Eb3907eCad74a0013c259D5874AE7f22DcBcC95C
to: 00000000000000000000000000000000DeaDBeef
nonce: 42
gasPrice: 100000000000 (100 gwei)
gas: 21000
value: 1024 (0.000000000000001024 eth)
data: 0x
v: 37
recovery_byte: 0
r: 0x0c97432d4db724e66a56f7ced04174cf6129e2555709f206dd6d3a156b4af23a
s: 0x287862548314a59c7ca6139eee8b51400eb40a67b08b8dc13d67302abecccae0
chainId: 1
hash: 0x003030af05460633e85b16fff7a17607818dc67e58f89396e5491ad6f5438971
hash_unsigned: 0xa59cf9e5438b186de381892b7879ce66476d5469478c7148880da5d553ade651
src: 0xf8662a85174876e8008252089400000000000000000000000000000000deadbeef8204008025a00c97432d4db724e66a56f7ced04174cf6129e2555709f206dd6d3a156b4af23aa0287862548314a59c7ca6139eee8b51400eb40a67b08b8dc13d67302abecccae0
.EE
.SS Offline transaction with arbitrary data
.EX
$ eth-gas -y <\fIkey_file_path\fP> -a 00000000000000000000000000000000DeaDBeef --fee-price 100000000000 --fee-limit 21000 --nonce 42 --data 0x2a 1024
from: Eb3907eCad74a0013c259D5874AE7f22DcBcC95C
to: 00000000000000000000000000000000DeaDBeef
nonce: 42
gasPrice: 100000000000 (100 gwei)
gas: 21000
value: 1024 (0.000000000000001024 eth)
data: 0x2a
v: 37
recovery_byte: 0
r: 0x800b6982d3f178201d7e7e7693b9c90b3fbcd54d04b6fff5284c81101fad54dd
s: 0x3b86d710d31ac74b58f0040b0f51fdb6bdbabea62a68cf99c05e765e7e81de87
chainId: 1
hash: 0xede30052befd80760c5ab543babdccc3d97fe90523e5710d77220155a82faa47
hash_unsigned: 0xad82d8cf1a412541c8a94ef71c50e9172c3a37853af036adee2f55c577da9770
src: 0xf8662a85174876e8008252089400000000000000000000000000000000deadbeef8204002a25a0800b6982d3f178201d7e7e7693b9c90b3fbcd54d04b6fff5284c81101fad54dda03b86d710d31ac74b58f0040b0f51fdb6bdbabea62a68cf99c05e765e7e81de87
.EE
.SS Offline transaction with wire-format output
.EX
$ eth-gas -y <\fIkey_file_path\fP> -a 00000000000000000000000000000000DeaDBeef --fee-price 100000000000 --fee-limit 21000 --nonce 42 --raw 1024
0xf8662a85174876e8008252089400000000000000000000000000000000deadbeef8204008025a00c97432d4db724e66a56f7ced04174cf6129e2555709f206dd6d3a156b4af23aa0287862548314a59c7ca6139eee8b51400eb40a67b08b8dc13d67302abecccae0
.EE
.SS Sign transaction for a different network
.EX
$ eth-gas -i evm:london:3:rinkeby -y /home/lash/src/contrib/grassrootseconomics/cic-dev/UTC--2021-01-08T17-18-44.521011372Z--eb3907ecad74a0013c259d5874ae7f22dcbcc95c -a 00000000000000000000000000000000DeaDBeef --fee-price 100000000000 --fee-limit 21000 --nonce 42 --data 0x2a 1024
from: Eb3907eCad74a0013c259D5874AE7f22DcBcC95C
to: 00000000000000000000000000000000DeaDBeef
nonce: 42
gasPrice: 100000000000 (100 gwei)
gas: 21000
value: 1024 (0.000000000000001024 eth)
data: 0x2a
v: 41
recovery_byte: 0
r: 0xe522c25784111a512cbf46f883e3bdacffc2cdbd465fa1042892c28fc10ee054
s: 0x5f84eb51a0c9871cfcedaba4e6274b300014899b3a2fec9292de6fe5919bcd07
chainId: 3
hash: 0x771200a20072294a6a843b89b98d5f868c9aa94da75dacf6a9f5834dfd241199
hash_unsigned: 0xa5f9e8a5cda6985d81f4129955b7529f48ecb54728badac16ec550384e3a2bcc
src: 0xf8662a85174876e8008252089400000000000000000000000000000000deadbeef8204002a29a0e522c25784111a512cbf46f883e3bdacffc2cdbd465fa1042892c28fc10ee054a05f84eb51a0c9871cfcedaba4e6274b300014899b3a2fec9292de6fe5919bcd07
.EE
.P
The wire-format can in turn be decoded using the \fBeth-decode\fP tool)

View File

@ -1,19 +0,0 @@
.TH eth-gas 1
.SH NAME
eth-gas - Create EVM gas token transaction
.SH SYNOPSIS
.P
\fBeth-gas\fP -a RECIPIENT -y KEYFILE [ -p \fIrpc_provider ] [ -s ] [ -u ] AMOUNT
.P
\fBeth-gas\fP -a RECIPIENT -y KEYFILE [ --fee-price PRICE ] [ --fee-limit LIMIT ] [ --nonce NONCE ] [ -s ] [ -u ] AMOUNT
.SH DESCRIPTION
\fBeth-gas\fP generates serialized gas token transactions in various output formats.
If an \fIrpc_provider\fP is available, the valuess \fIfee_price\fP and \fInonce\fP will be automatically retrieved if they are not explicitly specified. If missing values cannot be retrieved, an error will occur.
Providing all arguments enables fully offline creation of the transaction.
See \fBEXAMPLES\fP for more details on inputs and outputs.
.SS OPTIONS

View File

@ -1 +0,0 @@
a Beneficiary of the gas token transaction.

View File

@ -1,19 +0,0 @@
.TH eth-get 1
.SH NAME
eth-get \- Retrieve transaction and transaction state from network
.SH SYNOPSIS
.PP
\fBeth-get\fP [ -p \fIrpc_provider\fP] \fItx_hash\fP
.PP
\fBeth-get\fP [ -p \fIrpc_provider\fP] \fIaddress\fP
.SH DESCRIPTION
.P
Retrieve a transaction by its transaction hash, or contract code by its address.
.P
In the context of transaction, \fBeth-get\fP retrieves the state of the transaction (the "receipt") and applies it to the output. It also re-serializes the transaction wire format for reference.
.SS OPTIONS

View File

@ -1,27 +0,0 @@
.TH eth-info 1
.SH NAME
eth-info - Return key metrics from the current state of the EVM network.
.SH SYNOPSIS
\fBeth-info\fP [ -p \fIrpc_provider\fP ] [ \fIkey\fP ]
.SH DESCRIPTION
\fBeth-info\fP reports statistics from the current state of the EVM network:
.EX
$ eth-info
Block: 1024478
Gas price: 1000000000
.EE
An individual data item may be specified using the \fIkey\fP positional argument:
.EX
$ eth-info block
Block: 1024478
$ eth-info --raw gas_price
1000000000
.EE
.SS OPTIONS

View File

@ -1,8 +0,0 @@
.SH EXAMPLES
Outputs of \fBeth-gas\fP and \fBeth-encode\fP map directly to inputs for \fBeth-raw\fP.
.SS Encapsulate a gas transaction
.EX
$ eth-gas -y <\fIkey_file_path\fP> -a 00000000000000000000000000000000DeaDBeef --fee-price 100000000000 --fee-limit 21000 --nonce 42 --raw 1024 | eth-raw

View File

@ -1,26 +0,0 @@
.TH eth-raw 1
.SH NAME
eth-raw \- Create and send a jsonrpc transaction from signed rlp transaction
.SH SYNOPSIS
.P
\fBeth-raw\fP [ --deploy ] \fItransaction_data\fP
.P
\fBeth-raw\fP [ -p \fIrpc_provider\fP ] [ --deploy ] -s \fItransaction_data\fP
.SH DESCRIPTION
.P
Creates a jsonrpc object from serialized data.
.P
If \fB-y\fP is defined, and \fB--mode\fP is not set, or set to "tx", a \fIeth_sendRawTransaction\fP object will be created.
.P
Otherwise, an \fIeth_call\fP object will be created. The recipient of the call will be the contract specified with \fB-e\fP. If \fB-y\fP has been set, the sender of the query will be the address corresponding to the key file.
.P
If the \fB-s\fP option is added, the jsonrpc object will be sent to the rpc provider. \fBNote\fP If the jsonrpc object is a transaction, this may incur real costs.
.P
See the \fBEXAMPLES\fP section for details on how to use \fBeth-raw\fP with the outputs from \fBeth-gas\fP and \fBeth-encode\fP
.SS OPTIONS

View File

@ -1,4 +0,0 @@
.SH SEE ALSO
.BP
confini-dump(1), eth-keyfile(1), eth-encode(1), eth-gas(1)

View File

@ -1,17 +0,0 @@
.TH eth-wait 1
.SH NAE
eth-wait \- Wait for a transaction to be confirmed on network
.SH SYNOPSIS
\fBeth-wait\fP [ -p \fIrpc_provider\fP ] \fItransaction_hash\fP ...
.SH DESCRIPTION
.P
Blocks until network confirmation for the transactions are returned from \fIrpc_provider\fP.
.P
By default, if execution of the transaction failed on the network, the command will cause an error. This behavior can be adjusted using the \fB--ignore\fP or \fB--ignore-all\fP option.
.P
A transaction hash unknown to the \fIrpc_provider\fP will also cause an error.
.SS OPTIONS

View File

@ -1,2 +0,0 @@
ignore Ignore error from the specified transaction. May be defined more than once. --ignore tx_hash
ignoreall Ignore errors from all transactions. --ignore-all

View File

@ -1,7 +1,7 @@
funga-eth~=0.6.0 funga-eth~=0.5.3
pysha3==1.0.2 pysha3==1.0.2
hexathon~=0.1.5 hexathon~=0.1.1
websocket-client==0.57.0 websocket-client==0.57.0
potaahto~=0.1.1 potaahto~=0.1.0
chainlib~=0.1.0 chainlib~=0.0.17
confini~=0.6.0 confini~=0.5.3

View File

@ -1,6 +1,6 @@
[metadata] [metadata]
name = chainlib-eth name = chainlib-eth
version = 0.1.1 version = 0.0.21
description = Ethereum implementation of the chainlib interface description = Ethereum implementation of the chainlib interface
author = Louis Holbrook author = Louis Holbrook
author_email = dev@holbrook.no author_email = dev@holbrook.no
@ -48,3 +48,4 @@ console_scripts =
eth-info = chainlib.eth.runnable.info:main eth-info = chainlib.eth.runnable.info:main
eth-nonce = chainlib.eth.runnable.count:main eth-nonce = chainlib.eth.runnable.count:main
eth-wait = chainlib.eth.runnable.wait:main eth-wait = chainlib.eth.runnable.wait:main
eth = chainlib.eth.runnable.info:main

View File

@ -50,19 +50,6 @@ class TxTestCase(EthTesterCase):
self.assertTrue(is_same_address(tx['to'], self.accounts[1])) self.assertTrue(is_same_address(tx['to'], self.accounts[1]))
def test_tx_repack(self):
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
gas_oracle = RPCGasOracle(self.rpc)
c = Gas(signer=self.signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle, chain_spec=self.chain_spec)
(tx_hash_hex, o) = c.create(self.accounts[0], self.accounts[1], 1024)
self.rpc.do(o)
o = transaction(tx_hash_hex)
tx_src = self.rpc.do(o)
tx = Tx(tx_src)
tx_bin = pack(tx.src(), self.chain_spec)
def test_tx_pack(self): def test_tx_pack(self):
nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc) nonce_oracle = RPCNonceOracle(self.accounts[0], self.rpc)
gas_oracle = RPCGasOracle(self.rpc) gas_oracle = RPCGasOracle(self.rpc)