Implement error parser to rpc instantation
This commit is contained in:
parent
fc69b2762b
commit
0c0d1fac8f
113
chaind_eth/runnable/retry.py
Normal file
113
chaind_eth/runnable/retry.py
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
# standard imports
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
# external imports
|
||||||
|
from hexathon import (
|
||||||
|
add_0x,
|
||||||
|
strip_0x,
|
||||||
|
)
|
||||||
|
from chaind import Environment
|
||||||
|
import chainlib.eth.cli
|
||||||
|
from chainlib.chain import ChainSpec
|
||||||
|
from chainqueue.db import dsn_from_config
|
||||||
|
from chainqueue.sql.backend import SQLBackend
|
||||||
|
from chainqueue.enum import StatusBits
|
||||||
|
from chaind.sql.session import SessionIndex
|
||||||
|
from chainqueue.adapters.eth import EthAdapter
|
||||||
|
from chainlib.eth.gas import price
|
||||||
|
from chainlib.eth.connection import EthHTTPConnection
|
||||||
|
from crypto_dev_signer.eth.transaction import EIP155Transaction
|
||||||
|
|
||||||
|
DEFAULT_GAS_FACTOR = 1.1
|
||||||
|
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.WARNING)
|
||||||
|
logg = logging.getLogger()
|
||||||
|
|
||||||
|
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
config_dir = os.path.join(script_dir, '..', 'data', 'config')
|
||||||
|
|
||||||
|
arg_flags = chainlib.eth.cli.argflag_std_write
|
||||||
|
argparser = chainlib.eth.cli.ArgumentParser(arg_flags)
|
||||||
|
argparser.add_argument('--backend', type=str, default='sql', help='Backend to use (currently only "sql")')
|
||||||
|
argparser.add_positional('session_id', required=False, type=str, help='Ethereum address of recipient')
|
||||||
|
args = argparser.parse_args()
|
||||||
|
extra_args = {
|
||||||
|
'backend': None,
|
||||||
|
'session_id': 'SESSION_ID',
|
||||||
|
}
|
||||||
|
|
||||||
|
env = Environment(domain='eth', env=os.environ)
|
||||||
|
|
||||||
|
config = chainlib.eth.cli.Config.from_args(args, arg_flags, extra_args=extra_args, base_config_dir=config_dir)
|
||||||
|
|
||||||
|
if config.get('SESSION_DATA_DIR') == None:
|
||||||
|
config.add(env.data_dir, 'SESSION_DATA_DIR', exists_ok=True)
|
||||||
|
|
||||||
|
chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
|
||||||
|
|
||||||
|
tx_getter = None
|
||||||
|
session_method = None
|
||||||
|
if config.get('_BACKEND') == 'sql':
|
||||||
|
from chainqueue.sql.query import get_tx_cache as tx_getter
|
||||||
|
from chainqueue.runnable.sql import setup_backend
|
||||||
|
from chainqueue.db.models.base import SessionBase
|
||||||
|
setup_backend(config, debug=config.true('DATABASE_DEBUG'))
|
||||||
|
session_method = SessionBase.create_session
|
||||||
|
else:
|
||||||
|
raise NotImplementedError('backend {} not implemented'.format(config.get('_BACKEND')))
|
||||||
|
|
||||||
|
if config.get('DATABASE_ENGINE') == 'sqlite':
|
||||||
|
config.add(os.path.join(config.get('SESSION_DATA_DIR'), config.get('DATABASE_NAME') + '.sqlite'), 'DATABASE_NAME', exists_ok=True)
|
||||||
|
|
||||||
|
wallet = chainlib.eth.cli.Wallet()
|
||||||
|
wallet.from_config(config)
|
||||||
|
|
||||||
|
rpc = chainlib.eth.cli.Rpc(wallet=wallet)
|
||||||
|
conn = rpc.connect_by_config(config)
|
||||||
|
|
||||||
|
dsn = dsn_from_config(config)
|
||||||
|
backend = SQLBackend(dsn, debug=config.true('DATABASE_DEBUG'), error_parser=rpc.error_parser)
|
||||||
|
session_index_backend = SessionIndex(config.get('SESSION_ID'))
|
||||||
|
adapter = EthAdapter(backend, session_index_backend=session_index_backend)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
before = datetime.datetime.utcnow() - adapter.pending_retry_threshold
|
||||||
|
txs = session_index_backend.get(chain_spec, adapter, status=StatusBits.IN_NETWORK, not_status=StatusBits.FINAL | StatusBits.OBSOLETE, before=before)
|
||||||
|
|
||||||
|
o = price()
|
||||||
|
r = conn.do(o, error_parser=rpc.error_parser)
|
||||||
|
gas_price = strip_0x(r)
|
||||||
|
try:
|
||||||
|
gas_price = int(gas_price, 16)
|
||||||
|
except ValueError:
|
||||||
|
gas_price = int(gas_price)
|
||||||
|
logg.info('got current gas price {}'.format(gas_price))
|
||||||
|
|
||||||
|
signer = rpc.get_signer()
|
||||||
|
|
||||||
|
db_session = adapter.create_session()
|
||||||
|
for tx_hash in txs:
|
||||||
|
tx_bytes = bytes.fromhex(strip_0x(txs[tx_hash]))
|
||||||
|
tx = adapter.translate(tx_bytes, chain_spec)
|
||||||
|
tx_gas_price = int(tx['gasPrice'])
|
||||||
|
if tx_gas_price < gas_price:
|
||||||
|
tx['gasPrice'] = gas_price
|
||||||
|
else:
|
||||||
|
tx['gasPrice'] = int(tx['gasPrice'] * DEFAULT_GAS_FACTOR)
|
||||||
|
tx_obj = EIP155Transaction(tx, tx['nonce'], chain_spec.chain_id())
|
||||||
|
new_tx_bytes = signer.sign_transaction_to_wire(tx_obj)
|
||||||
|
logg.debug('add tx {} with gas price changed from {} to {}: {}'.format(tx_hash, tx_gas_price, tx['gasPrice'], new_tx_bytes.hex()))
|
||||||
|
adapter.add(new_tx_bytes, chain_spec, session=db_session)
|
||||||
|
|
||||||
|
db_session.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
@ -17,6 +17,7 @@ from chainlib.eth.connection import EthHTTPConnection
|
|||||||
from chainqueue.sql.backend import SQLBackend
|
from chainqueue.sql.backend import SQLBackend
|
||||||
from chainlib.error import JSONRPCException
|
from chainlib.error import JSONRPCException
|
||||||
from chainqueue.db import dsn_from_config
|
from chainqueue.db import dsn_from_config
|
||||||
|
from chaind.sql.session import SessionIndex
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from chaind_eth.dispatch import Dispatcher
|
from chaind_eth.dispatch import Dispatcher
|
||||||
@ -59,7 +60,7 @@ if not config.get('SESSION_SOCKET_PATH'):
|
|||||||
|
|
||||||
if config.get('DATABASE_ENGINE') == 'sqlite':
|
if config.get('DATABASE_ENGINE') == 'sqlite':
|
||||||
#config.add(os.path.join(config.get('SESSION_DATA_DIR'), config.get('DATABASE_NAME') + '.sqlite'), 'DATABASE_NAME', exists_ok=True)
|
#config.add(os.path.join(config.get('SESSION_DATA_DIR'), config.get('DATABASE_NAME') + '.sqlite'), 'DATABASE_NAME', exists_ok=True)
|
||||||
config.add(os.path.join(config.get('SESSION_DATA_DIR'), config.get('DATABASE_NAME')), 'DATABASE_NAME', exists_ok=True)
|
config.add(os.path.join(config.get('SESSION_DATA_DIR'), config.get('DATABASE_NAME') + '.sqlite'), 'DATABASE_NAME', exists_ok=True)
|
||||||
|
|
||||||
config.censor('PASSWORD', 'DATABASE')
|
config.censor('PASSWORD', 'DATABASE')
|
||||||
logg.debug('config loaded:\n{}'.format(config))
|
logg.debug('config loaded:\n{}'.format(config))
|
||||||
@ -116,10 +117,14 @@ signal.signal(signal.SIGTERM, ctrl.shutdown)
|
|||||||
|
|
||||||
chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
|
chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC'))
|
||||||
|
|
||||||
|
rpc = chainlib.eth.cli.Rpc()
|
||||||
|
conn = rpc.connect_by_config(config)
|
||||||
|
|
||||||
|
logg.debug('error {}'.format(rpc.error_parser))
|
||||||
dsn = dsn_from_config(config)
|
dsn = dsn_from_config(config)
|
||||||
backend = SQLBackend(dsn, debug=config.true('DATABASE_DEBUG'))
|
backend = SQLBackend(dsn, error_parser=rpc.error_parser, debug=config.true('DATABASE_DEBUG'))
|
||||||
adapter = EthAdapter(backend)
|
session_index_backend = SessionIndex(config.get('SESSION_ID'))
|
||||||
rpc = EthHTTPConnection(url=config.get('RPC_HTTP_PROVIDER'), chain_spec=chain_spec)
|
adapter = EthAdapter(backend, session_index_backend=session_index_backend)
|
||||||
|
|
||||||
|
|
||||||
def process_outgoing(chain_spec, adapter, rpc):
|
def process_outgoing(chain_spec, adapter, rpc):
|
||||||
@ -148,7 +153,7 @@ def main():
|
|||||||
break
|
break
|
||||||
if srvs == None:
|
if srvs == None:
|
||||||
logg.debug('timeout (remote socket is none)')
|
logg.debug('timeout (remote socket is none)')
|
||||||
r = process_outgoing(chain_spec, adapter, rpc)
|
r = process_outgoing(chain_spec, adapter, conn)
|
||||||
if r > 0:
|
if r > 0:
|
||||||
ctrl.srv.settimeout(0.1)
|
ctrl.srv.settimeout(0.1)
|
||||||
else:
|
else:
|
||||||
@ -174,15 +179,21 @@ def main():
|
|||||||
|
|
||||||
logg.debug('recv {} bytes'.format(len(data)))
|
logg.debug('recv {} bytes'.format(len(data)))
|
||||||
session = backend.create_session()
|
session = backend.create_session()
|
||||||
|
tx_hash = None
|
||||||
try:
|
try:
|
||||||
r = adapter.add(data, chain_spec, session=session)
|
tx_hash = adapter.add(data, chain_spec, session=session)
|
||||||
try:
|
|
||||||
r = srvs.send(r.to_bytes(4, byteorder='big'))
|
|
||||||
logg.debug('{} bytes sent'.format(r))
|
|
||||||
except BrokenPipeError:
|
|
||||||
logg.debug('they just hung up. how rude.')
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logg.error('invalid input: {}'.format(e))
|
logg.error('invalid input: {}'.format(e))
|
||||||
|
|
||||||
|
r = 1
|
||||||
|
if tx_hash != None:
|
||||||
|
session.commit()
|
||||||
|
r = 0
|
||||||
|
try:
|
||||||
|
r = srvs.send(r.to_bytes(4, byteorder='big'))
|
||||||
|
logg.debug('{} bytes sent'.format(r))
|
||||||
|
except BrokenPipeError:
|
||||||
|
logg.debug('they just hung up. how rude.')
|
||||||
session.close()
|
session.close()
|
||||||
srvs.close()
|
srvs.close()
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
# standard imports
|
# standard imports
|
||||||
import logging
|
import logging
|
||||||
import datetime
|
|
||||||
|
|
||||||
# external imports
|
# external imports
|
||||||
from chainlib.eth.constant import ZERO_ADDRESS
|
from chainlib.eth.constant import ZERO_ADDRESS
|
||||||
@ -12,18 +11,15 @@ from hexathon import (
|
|||||||
add_0x,
|
add_0x,
|
||||||
strip_0x,
|
strip_0x,
|
||||||
)
|
)
|
||||||
from chainqueue.enum import (
|
|
||||||
StatusBits,
|
|
||||||
errors as queue_errors,
|
|
||||||
)
|
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from chainqueue.adapters.base import Adapter
|
from chainqueue.adapters.sessionindex import SessionIndexAdapter
|
||||||
|
|
||||||
logg = logging.getLogger(__name__)
|
logg = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class EthAdapter(Adapter):
|
class EthAdapter(SessionIndexAdapter):
|
||||||
|
|
||||||
|
|
||||||
def translate(self, bytecode, chain_spec):
|
def translate(self, bytecode, chain_spec):
|
||||||
logg.debug('bytecode {}'.format(bytecode))
|
logg.debug('bytecode {}'.format(bytecode))
|
||||||
@ -41,27 +37,6 @@ class EthAdapter(Adapter):
|
|||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def upcoming(self, chain_spec, session=None):
|
|
||||||
txs = self.backend.get(chain_spec, self.translate, session=session, status=StatusBits.QUEUED, not_status=StatusBits.IN_NETWORK)
|
|
||||||
before = datetime.datetime.utcnow() - self.error_retry_threshold
|
|
||||||
errored_txs = self.backend.get(chain_spec, self.translate, session=session, status=StatusBits.LOCAL_ERROR, not_status=StatusBits.FINAL, before=before, requeue=True)
|
|
||||||
for tx_hash in errored_txs.keys():
|
|
||||||
txs[tx_hash] = errored_txs[tx_hash]
|
|
||||||
return txs
|
|
||||||
|
|
||||||
|
|
||||||
def add(self, bytecode, chain_spec, session=None):
|
|
||||||
tx = self.translate(bytecode, chain_spec)
|
|
||||||
r = self.backend.create(chain_spec, tx['nonce'], tx['from'], tx['hash'], add_0x(bytecode.hex()), session=session)
|
|
||||||
if r:
|
|
||||||
session.rollback()
|
|
||||||
session.close()
|
|
||||||
return r
|
|
||||||
r = self.backend.cache(tx, session=session)
|
|
||||||
session.commit()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
# def cache(self, chain_spec):
|
# def cache(self, chain_spec):
|
||||||
# session = self.backend.create_session()
|
# session = self.backend.create_session()
|
||||||
# r = self.backend.create(chain_spec, tx['nonce'], tx['from'], tx['hash'], add_0x(bytecode.hex()), session=session)
|
# r = self.backend.create(chain_spec, tx['nonce'], tx['from'], tx['hash'], add_0x(bytecode.hex()), session=session)
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
chaind<=0.0.2,>=0.0.2a3
|
chaind<=0.0.3,>=0.0.3a1
|
||||||
hexathon~=0.0.1a8
|
hexathon~=0.0.1a8
|
||||||
chainlib-eth<=0.1.0,>=0.0.9a4
|
chainlib-eth<=0.1.0,>=0.0.9a4
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
name = chaind-eth
|
name = chaind-eth
|
||||||
version = 0.0.2a1
|
version = 0.0.3a1
|
||||||
description = Queue server for ethereum
|
description = Queue server for ethereum
|
||||||
author = Louis Holbrook
|
author = Louis Holbrook
|
||||||
author_email = dev@holbrook.no
|
author_email = dev@holbrook.no
|
||||||
|
Loading…
Reference in New Issue
Block a user