Skip to content

Commit

Permalink
ETH: add experimental support for Erigon
Browse files Browse the repository at this point in the history
https://github.com/ledgerwatch/erigon

- Support is for testing/development only
- Enable with MMGEN_ENABLE_ERIGON environmental var
- Specify with --daemon-id=erigon
  • Loading branch information
mmgen committed Aug 4, 2021
1 parent 9f24236 commit b88c4bb
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 2 deletions.
4 changes: 4 additions & 0 deletions mmgen/altcoins/eth/tx.py
Expand Up @@ -396,6 +396,10 @@ async def is_in_mempool():
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':
res = await self.rpc.call('txpool_content')
pmsg('txpool_content:',res) # DEBUG
pool = list(res['pending']) + list(res['queued'])
return '0x'+self.coin_txid in pool

async def is_in_wallet():
Expand Down
83 changes: 82 additions & 1 deletion mmgen/daemon.py
Expand Up @@ -342,7 +342,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']),
'ETH': _cd('Ethereum', ['openethereum'] + (['erigon'] if g.enable_erigon else []) ),
'ETC': _cd('Ethereum Classic', ['parity']),
}

Expand Down Expand Up @@ -656,3 +656,84 @@ class parity_daemon(openethereum_daemon):
exec_fn = 'parity'
ports_shift = _nw(100,110,120)
rpc_ports = _nw(*[8545 + n for n in ports_shift]) # non-standard

# https://github.com/ledgerwatch/erigon
class erigon_daemon(CoinDaemon):
avail_opts = ('online',)
daemon_data = _dd('Erigon', 2021007005, '2021.07.5')
version_pat = r'erigon/(\d+)\.(\d+)\.(\d+)'
exec_fn = 'erigon'
cfg_file = 'erigon.conf'
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
}
datadir_is_subdir = True
testnet_dir = 'erigon_testnet'

def subclass_init(self):
self.private_port = getattr(self.private_ports,self.network)
if self.network == 'regtest':
self.datadir = None
self.coind_args = list_gen(
['--verbosity=0'],
[f'--private.api.addr=127.0.0.1:{self.private_port}'],
[f'--datadir={self.datadir}', self.network!='regtest'],
['--chain=dev', self.network=='regtest'],
['--chain=goerli', self.network=='testnet'],
['--miner.etherbase=00a329c0648769a73afac7f9381e08fb43dbea72', self.network=='regtest'],
)
self.rpc_d = erigon_rpcdaemon(
proto = self.proto,
rpc_port = self.rpc_port,
private_port = self.private_port,
test_suite = self.test_suite,
datadir = self.datadir )

def start(self,quiet=False,silent=False):
super().start(quiet=quiet,silent=silent)
self.rpc_d.debug = self.debug
return self.rpc_d.start(quiet=quiet,silent=silent)

def stop(self,quiet=False,silent=False):
self.rpc_d.debug = self.debug
self.rpc_d.stop(quiet=quiet,silent=silent)
return super().stop(quiet=quiet,silent=silent)

@property
def start_cmds(self):
return [self.start_cmd,self.rpc_d.start_cmd]

class erigon_rpcdaemon(RPCDaemon):

master_daemon = 'erigon_daemon'
rpc_type = 'Erigon'
exec_fn = 'rpcdaemon'
use_pidfile = False
use_threads = True

def __init__(self,proto,rpc_port,private_port,test_suite,datadir):

self.proto = proto
self.test_suite = test_suite

super().__init__()

self.network = proto.network
self.rpc_port = rpc_port
self.datadir = datadir

self.daemon_args = list_gen(
['--verbosity=0'],
[f'--private.api.addr=127.0.0.1:{private_port}'],
[f'--datadir={self.datadir}', self.network != 'regtest'],
['--http.api=eth,erigon,web3,net,txpool'],
[f'--http.port={self.rpc_port}'],
)

self.lock()
2 changes: 2 additions & 0 deletions mmgen/globalvars.py
Expand Up @@ -112,6 +112,7 @@ class GlobalContext(Lockable):

# miscellaneous features:
use_internal_keccak_module = False
enable_erigon = False

# test suite:
bogus_wallet_data = ''
Expand Down Expand Up @@ -227,6 +228,7 @@ class GlobalContext(Lockable):
'MMGEN_RPC_BACKEND',
'MMGEN_IGNORE_DAEMON_VERSION',
'MMGEN_USE_STANDALONE_SCRYPT_MODULE',
'MMGEN_ENABLE_ERIGON',

'MMGEN_DISABLE_COLOR',
'MMGEN_DISABLE_MSWIN_PW_WARNING',
Expand Down
15 changes: 14 additions & 1 deletion mmgen/protocol.py
Expand Up @@ -397,6 +397,19 @@ class Ethereum(DummyWIF,Secp256k1):
avg_bdi = 15
ignore_daemon_version = False

chain_ids = {
1: 'ethereum', # ethereum mainnet
2: 'morden', # morden testnet (deprecated)
3: 'ropsten', # ropsten testnet
4: 'rinkeby', # rinkeby testnet
5: 'goerli', # goerli testnet
42: 'kovan', # kovan testnet
61: 'classic', # ethereum classic mainnet
62: 'morden', # ethereum classic testnet
17: 'developmentchain', # parity dev chain
1337: 'developmentchain', # erigon dev chain
}

@property
def dcoin(self):
return self.tokensym or self.coin
Expand All @@ -415,7 +428,7 @@ def pubhash2addr(self,pubkey_hash,p2sh):
return pubkey_hash

class EthereumTestnet(Ethereum):
chain_names = ['kovan']
chain_names = ['kovan','goerli','rinkeby']

class EthereumRegtest(EthereumTestnet):
chain_names = ['developmentchain']
Expand Down
12 changes: 12 additions & 0 deletions mmgen/rpc.py
Expand Up @@ -624,12 +624,18 @@ async def __ainit__(self,proto,daemon,backend):
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':
do_erigon_warning()
self.caps += ('full_node',)
self.chainID = Int(ci,16)
self.chain = self.proto.chain_ids[self.chainID]

rpcmethods = (
'eth_blockNumber',
'eth_call',
# Returns the EIP155 chain ID used for transaction signing at the current best block.
# Parity: Null is returned if not available, ID not required in transactions
# Erigon: always returns ID, requires ID in transactions
'eth_chainId',
'eth_gasPrice',
'eth_getBalance',
Expand All @@ -640,6 +646,7 @@ async def __ainit__(self,proto,daemon,backend):
'parity_chain',
'parity_nodeKind',
'parity_pendingTransactions',
'txpool_content',
)

class MoneroRPCClient(RPCClient):
Expand Down Expand Up @@ -709,6 +716,11 @@ class MoneroWalletRPCClient(MoneroRPCClient):
'refresh', # start_height
)

def do_erigon_warning(erigon_warning_shown=[]):
if not erigon_warning_shown:
rmsg(f'WARNING: Erigon support is EXPERIMENTAL. Use at your own risk!!!')
erigon_warning_shown.append(1)

def handle_unsupported_daemon_version(rpc,proto,ignore_daemon_version,unsupported_daemon_warning_shown=[]):
if ignore_daemon_version or proto.ignore_daemon_version or g.ignore_daemon_version:
if not type(proto) in unsupported_daemon_warning_shown:
Expand Down

0 comments on commit b88c4bb

Please sign in to comment.