2021-02-01 18:12:51 +01:00
|
|
|
|
# standard imports
|
|
|
|
|
import logging
|
|
|
|
|
|
|
|
|
|
# third-party imports
|
|
|
|
|
import celery
|
|
|
|
|
from cic_registry.chain import ChainSpec
|
|
|
|
|
|
|
|
|
|
# local imports
|
|
|
|
|
from cic_eth.eth import RpcClient
|
|
|
|
|
from cic_eth.queue.tx import create as queue_create
|
2021-03-07 14:51:59 +01:00
|
|
|
|
from cic_eth.error import SignerError
|
2021-02-01 18:12:51 +01:00
|
|
|
|
|
|
|
|
|
celery_app = celery.current_app
|
|
|
|
|
logg = celery_app.log.get_default_logger()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@celery_app.task()
|
|
|
|
|
def sign_tx(tx, chain_str):
|
|
|
|
|
"""Sign a single transaction against the given chain specification.
|
|
|
|
|
|
|
|
|
|
:param tx: Transaction in standard Ethereum format
|
|
|
|
|
:type tx: dict
|
|
|
|
|
:param chain_str: Chain spec string representation
|
|
|
|
|
:type chain_str: str
|
|
|
|
|
:returns: Transaction hash and raw signed transaction, respectively
|
|
|
|
|
:rtype: tuple
|
|
|
|
|
"""
|
|
|
|
|
chain_spec = ChainSpec.from_chain_str(chain_str)
|
|
|
|
|
c = RpcClient(chain_spec)
|
2021-03-07 14:51:59 +01:00
|
|
|
|
tx_transfer_signed = None
|
|
|
|
|
try:
|
|
|
|
|
tx_transfer_signed = c.w3.eth.sign_transaction(tx)
|
|
|
|
|
except FileNotFoundError:
|
|
|
|
|
pass
|
|
|
|
|
if tx_transfer_signed == None:
|
|
|
|
|
raise SignerError('sign tx')
|
2021-02-01 18:12:51 +01:00
|
|
|
|
logg.debug('tx_transfer_signed {}'.format(tx_transfer_signed))
|
|
|
|
|
tx_hash = c.w3.keccak(hexstr=tx_transfer_signed['raw'])
|
|
|
|
|
tx_hash_hex = tx_hash.hex()
|
|
|
|
|
return (tx_hash_hex, tx_transfer_signed['raw'],)
|
|
|
|
|
|
|
|
|
|
|
2021-03-01 21:15:17 +01:00
|
|
|
|
def sign_and_register_tx(tx, chain_str, queue, cache_task=None, session=None):
|
2021-02-01 18:12:51 +01:00
|
|
|
|
"""Signs the provided transaction, and adds it to the transaction queue cache (with status PENDING).
|
|
|
|
|
|
|
|
|
|
:param tx: Standard ethereum transaction data
|
|
|
|
|
:type tx: dict
|
|
|
|
|
:param chain_str: Chain spec, string representation
|
|
|
|
|
:type chain_str: str
|
|
|
|
|
:param queue: Task queue
|
|
|
|
|
:type queue: str
|
|
|
|
|
:param cache_task: Cache task to call with signed transaction. If None, no task will be called.
|
|
|
|
|
:type cache_task: str
|
2021-03-01 21:15:17 +01:00
|
|
|
|
:raises: sqlalchemy.exc.DatabaseError
|
2021-02-01 18:12:51 +01:00
|
|
|
|
:returns: Tuple; Transaction hash, signed raw transaction data
|
|
|
|
|
:rtype: tuple
|
|
|
|
|
"""
|
|
|
|
|
(tx_hash_hex, tx_signed_raw_hex) = sign_tx(tx, chain_str)
|
|
|
|
|
|
|
|
|
|
logg.debug('adding queue tx {}'.format(tx_hash_hex))
|
|
|
|
|
|
|
|
|
|
queue_create(
|
|
|
|
|
tx['nonce'],
|
|
|
|
|
tx['from'],
|
|
|
|
|
tx_hash_hex,
|
|
|
|
|
tx_signed_raw_hex,
|
|
|
|
|
chain_str,
|
2021-03-01 21:15:17 +01:00
|
|
|
|
session=session,
|
2021-02-01 18:12:51 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if cache_task != None:
|
|
|
|
|
logg.debug('adding cache task {} tx {}'.format(cache_task, tx_hash_hex))
|
|
|
|
|
s_cache = celery.signature(
|
|
|
|
|
cache_task,
|
|
|
|
|
[
|
|
|
|
|
tx_hash_hex,
|
|
|
|
|
tx_signed_raw_hex,
|
|
|
|
|
chain_str,
|
|
|
|
|
],
|
|
|
|
|
queue=queue,
|
|
|
|
|
)
|
|
|
|
|
s_cache.apply_async()
|
|
|
|
|
|
|
|
|
|
return (tx_hash_hex, tx_signed_raw_hex,)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# TODO: rename as we will not be sending task in the chain, this is the responsibility of the dispatcher
|
|
|
|
|
def create_check_gas_and_send_task(tx_signed_raws_hex, chain_str, holder_address, gas, tx_hashes_hex=None, queue=None):
|
|
|
|
|
"""Creates a celery task signature for a check_gas task that adds the task to the outgoing queue to be processed by the dispatcher.
|
|
|
|
|
|
|
|
|
|
If tx_hashes_hex is not spefified, a preceding task chained to check_gas must supply the transaction hashes as its return value.
|
|
|
|
|
|
|
|
|
|
:param tx_signed_raws_hex: Raw signed transaction data
|
|
|
|
|
:type tx_signed_raws_hex: list of str, 0x-hex
|
|
|
|
|
:param chain_str: Chain spec, string representation
|
|
|
|
|
:type chain_str: str
|
|
|
|
|
:param holder_address: Address sending the transactions
|
|
|
|
|
:type holder_address: str, 0x-hex
|
|
|
|
|
:param gas: Gas budget hint for transactions
|
|
|
|
|
:type gas: int
|
|
|
|
|
:param tx_hashes_hex: Transaction hashes
|
|
|
|
|
:type tx_hashes_hex: list of str, 0x-hex
|
|
|
|
|
:param queue: Task queue
|
|
|
|
|
:type queue: str
|
|
|
|
|
:returns: Signature of task chain
|
|
|
|
|
:rtype: celery.Signature
|
|
|
|
|
"""
|
|
|
|
|
s_check_gas = None
|
|
|
|
|
if tx_hashes_hex != None:
|
|
|
|
|
s_check_gas = celery.signature(
|
|
|
|
|
'cic_eth.eth.tx.check_gas',
|
|
|
|
|
[
|
|
|
|
|
tx_hashes_hex,
|
|
|
|
|
chain_str,
|
|
|
|
|
tx_signed_raws_hex,
|
|
|
|
|
holder_address,
|
|
|
|
|
gas,
|
|
|
|
|
],
|
|
|
|
|
queue=queue,
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
s_check_gas = celery.signature(
|
|
|
|
|
'cic_eth.eth.tx.check_gas',
|
|
|
|
|
[
|
|
|
|
|
chain_str,
|
|
|
|
|
tx_signed_raws_hex,
|
|
|
|
|
holder_address,
|
|
|
|
|
gas,
|
|
|
|
|
],
|
|
|
|
|
queue=queue,
|
|
|
|
|
)
|
|
|
|
|
return s_check_gas
|