ETH: support Geth
- Select with --daemon-id=geth
- Geth is not tested on mainnet yet
Testing:
$ test/test.py -e --coin=eth --daemon-id=geth ethdev
This commit is contained in:
parent
8965c30aff
commit
ac7bced579
6 changed files with 114 additions and 11 deletions
|
|
@ -52,7 +52,7 @@ class TokenBase(MMGenObject): # ERC20
|
|||
data = create_method_id(method_sig) + method_args
|
||||
if g.debug:
|
||||
msg('ETH_CALL {}: {}'.format(method_sig,'\n '.join(parse_abi(data))))
|
||||
ret = await self.rpc.call('eth_call',{ 'to': '0x'+self.addr, 'data': '0x'+data })
|
||||
ret = await self.rpc.call('eth_call',{ 'to': '0x'+self.addr, 'data': '0x'+data },'pending')
|
||||
if toUnit:
|
||||
return int(ret,16) * self.base_unit
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -396,7 +396,7 @@ class EthereumMMGenTX:
|
|||
return False
|
||||
if self.rpc.daemon.id in ('parity','openethereum'):
|
||||
pool = [x['hash'] for x in await self.rpc.call('parity_pendingTransactions')]
|
||||
elif self.rpc.daemon.id == 'erigon':
|
||||
elif self.rpc.daemon.id in ('geth','erigon'):
|
||||
res = await self.rpc.call('txpool_content')
|
||||
pmsg('txpool_content:',res) # DEBUG
|
||||
pool = list(res['pending']) + list(res['queued'])
|
||||
|
|
|
|||
|
|
@ -344,7 +344,7 @@ class CoinDaemon(Daemon):
|
|||
'BCH': _cd('Bitcoin Cash Node', ['bitcoin_cash_node']),
|
||||
'LTC': _cd('Litecoin', ['litecoin_core']),
|
||||
'XMR': _cd('Monero', ['monero']),
|
||||
'ETH': _cd('Ethereum', ['openethereum'] + (['erigon'] if g.enable_erigon else []) ),
|
||||
'ETH': _cd('Ethereum', ['openethereum','geth'] + (['erigon'] if g.enable_erigon else []) ),
|
||||
'ETC': _cd('Ethereum Classic', ['parity']),
|
||||
}
|
||||
|
||||
|
|
@ -658,8 +658,34 @@ class parity_daemon(openethereum_daemon):
|
|||
ports_shift = _nw(100,110,120)
|
||||
rpc_ports = _nw(*[8545 + n for n in ports_shift]) # non-standard
|
||||
|
||||
class geth_daemon(CoinDaemon):
|
||||
daemon_data = _dd('Geth', 1010007, '1.10.7')
|
||||
version_pat = r'Geth/v(\d+)\.(\d+)\.(\d+)'
|
||||
exec_fn = 'geth'
|
||||
ports_shift = _nw(300,310,320)
|
||||
rpc_ports = _nw(*[8545 + n for n in ports_shift]) # non-standard
|
||||
use_pidfile = False
|
||||
use_threads = True
|
||||
datadirs = {
|
||||
'linux': [g.home_dir,'.ethereum','geth'],
|
||||
'win': [os.getenv('LOCALAPPDATA'),'Geth'] # FIXME
|
||||
}
|
||||
|
||||
def subclass_init(self):
|
||||
self.datadir = os.path.join(self.datadir,self.id,getattr(self.proto.network_names,self.network))
|
||||
self.coind_args = list_gen(
|
||||
['--verbosity=0'],
|
||||
['--http'],
|
||||
['--http.api=eth,web3,txpool'], # ,clique,personal,net'],
|
||||
[f'--http.port={self.rpc_port}'],
|
||||
['--maxpeers=0', not 'online' in self.opts],
|
||||
[f'--datadir={self.datadir}'],
|
||||
['--chain=goerli', self.network=='testnet'],
|
||||
['--dev', self.network=='regtest'],
|
||||
)
|
||||
|
||||
# https://github.com/ledgerwatch/erigon
|
||||
class erigon_daemon(CoinDaemon):
|
||||
class erigon_daemon(geth_daemon):
|
||||
avail_opts = ('online',)
|
||||
daemon_data = _dd('Erigon', 2021007005, '2021.07.5')
|
||||
version_pat = r'erigon/(\d+)\.(\d+)\.(\d+)'
|
||||
|
|
@ -667,8 +693,6 @@ class erigon_daemon(CoinDaemon):
|
|||
private_ports = _nw(9090,9091,9092) # testnet and regtest are non-standard
|
||||
ports_shift = _nw(200,210,220)
|
||||
rpc_ports = _nw(*[8545 + n for n in ports_shift]) # non-standard
|
||||
use_pidfile = False
|
||||
use_threads = True
|
||||
datadirs = {
|
||||
'linux': [g.home_dir,'.local','share','erigon'],
|
||||
'win': [os.getenv('LOCALAPPDATA'),'Erigon'] # FIXME
|
||||
|
|
|
|||
|
|
@ -407,7 +407,7 @@ class CoinProtocol(MMGenObject):
|
|||
61: 'classic', # ethereum classic mainnet
|
||||
62: 'morden', # ethereum classic testnet
|
||||
17: 'developmentchain', # parity dev chain
|
||||
1337: 'developmentchain', # erigon dev chain
|
||||
1337: 'developmentchain', # geth dev chain
|
||||
}
|
||||
|
||||
@property
|
||||
|
|
|
|||
|
|
@ -624,8 +624,9 @@ class EthereumRPCClient(RPCClient,metaclass=aInitMeta):
|
|||
self.caps += ('full_node',)
|
||||
self.chainID = None if ci == None else Int(ci,16) # parity/oe return chainID only for dev chain
|
||||
self.chain = (await self.call('parity_chain')).replace(' ','_').replace('_testnet','')
|
||||
elif self.daemon.id == 'erigon':
|
||||
daemon_warning(self.daemon.id)
|
||||
elif self.daemon.id in ('geth','erigon'):
|
||||
if self.daemon.network == 'mainnet':
|
||||
daemon_warning(self.daemon.id)
|
||||
self.caps += ('full_node',)
|
||||
self.chainID = Int(ci,16)
|
||||
self.chain = self.proto.chain_ids[self.chainID]
|
||||
|
|
@ -718,6 +719,10 @@ class MoneroWalletRPCClient(MoneroRPCClient):
|
|||
|
||||
class daemon_warning(oneshot_warning):
|
||||
|
||||
class geth:
|
||||
color = 'yellow'
|
||||
message = 'Geth has not been tested on mainnet. You may experience problems.'
|
||||
|
||||
class erigon:
|
||||
color = 'red'
|
||||
message = 'Erigon support is EXPERIMENTAL. Use at your own risk!!!'
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
|
|||
('wallet_upgrade2', 'upgrading the tracking wallet (v2 -> v3)'),
|
||||
('addrgen', 'generating addresses'),
|
||||
('addrimport', 'importing addresses'),
|
||||
('addrimport_dev_addr', "importing OpenEthereum dev address 'Ox00a329c..'"),
|
||||
('addrimport_dev_addr', "importing dev faucet address 'Ox00a329c..'"),
|
||||
|
||||
('txcreate1', 'creating a transaction (spend from dev address to address :1)'),
|
||||
('txview1_raw', 'viewing the raw transaction'),
|
||||
|
|
@ -333,13 +333,87 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
|
|||
for d in ('mm1','mm2'):
|
||||
copytree(os.path.join(srcdir,d),os.path.join(self.tmpdir,d))
|
||||
if not opt.no_daemon_autostart:
|
||||
if not start_test_daemons(self.proto.coin+'_rt',remove_datadir=True):
|
||||
if g.daemon_id == 'geth':
|
||||
self.geth_setup()
|
||||
if not start_test_daemons(
|
||||
self.proto.coin+'_rt',
|
||||
remove_datadir = not g.daemon_id=='geth' ):
|
||||
return False
|
||||
from mmgen.rpc import rpc_init
|
||||
rpc = await rpc_init(self.proto)
|
||||
imsg('Daemon: {} v{}'.format(rpc.daemon.coind_name,rpc.daemon_version_str))
|
||||
return 'ok'
|
||||
|
||||
def geth_setup(self):
|
||||
|
||||
def make_key(keystore):
|
||||
pwfile = joinpath(self.tmpdir,'account_passwd')
|
||||
write_to_file(pwfile,'')
|
||||
run(['rm','-rf',keystore])
|
||||
cmd = f'geth account new --password={pwfile} --lightkdf --keystore {keystore}'
|
||||
cp = run(cmd.split(),stdout=PIPE,stderr=PIPE)
|
||||
if cp.returncode:
|
||||
die(1,cp.stderr.decode())
|
||||
keyfile = os.path.join(keystore,os.listdir(keystore)[0])
|
||||
return json.loads(open(keyfile).read())['address']
|
||||
|
||||
def make_genesis(signer_addr,prealloc_addr,prealloc_amt):
|
||||
return {
|
||||
'config': {
|
||||
'chainId': 1337, # TODO: replace constant with var
|
||||
'homesteadBlock': 0,
|
||||
'eip150Block': 0,
|
||||
'eip155Block': 0,
|
||||
'eip158Block': 0,
|
||||
'byzantiumBlock': 0,
|
||||
'constantinopleBlock': 0,
|
||||
'petersburgBlock': 0,
|
||||
'clique': {
|
||||
'period': 0,
|
||||
'epoch': 30000
|
||||
}
|
||||
},
|
||||
'difficulty': '1',
|
||||
'gasLimit': '8000000',
|
||||
'extradata': '0x' + 64*'0' + signer_addr + 130*'0',
|
||||
'alloc': {
|
||||
prealloc_addr: { 'balance': str(prealloc_amt.toWei()) }
|
||||
}
|
||||
}
|
||||
|
||||
def init_genesis(fn):
|
||||
cmd = f'geth init --datadir {d.datadir} {fn}'
|
||||
cp = run(cmd.split(),stdout=PIPE,stderr=PIPE)
|
||||
if cp.returncode:
|
||||
die(1,cp.stderr.decode())
|
||||
|
||||
from mmgen.daemon import CoinDaemon
|
||||
import json
|
||||
|
||||
d = CoinDaemon(proto=self.proto,test_suite=True)
|
||||
d.stop(quiet=True)
|
||||
d.remove_datadir()
|
||||
|
||||
imsg(cyan('Initializing Geth:'))
|
||||
|
||||
keystore = os.path.relpath(os.path.join(d.datadir,'keystore'))
|
||||
imsg(f' Keystore: {keystore}')
|
||||
|
||||
signer_addr = make_key(keystore)
|
||||
imsg(f' Signer address: {signer_addr}')
|
||||
|
||||
prealloc_amt = ETHAmt('1_000_000_000')
|
||||
imsg(f' Faucet: {dfl_addr} ({prealloc_amt} ETH)')
|
||||
|
||||
genesis_data = make_genesis(signer_addr,dfl_addr,prealloc_amt)
|
||||
|
||||
genesis_fn = joinpath(self.tmpdir,'genesis.json')
|
||||
imsg(f' Genesis block data: {genesis_fn}')
|
||||
|
||||
write_to_file( genesis_fn, json.dumps(genesis_data,indent=' ')+'\n' )
|
||||
|
||||
init_genesis(genesis_fn)
|
||||
|
||||
def wallet_upgrade(self,src_file):
|
||||
if self.proto.coin == 'ETC':
|
||||
msg('skipping test {!r} for ETC'.format(self.test_name))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue