Add nonce list test
This commit is contained in:
parent
5ea1b15c53
commit
fb14961c1b
@ -14,3 +14,10 @@ class TxStateChangeError(ChainQueueException):
|
|||||||
"""Raised when an invalid state change of a queued transaction occurs
|
"""Raised when an invalid state change of a queued transaction occurs
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class CacheIntegrityError(ChainQueueException):
|
||||||
|
"""Raised when cached data does not match raw transaction data
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@ -8,8 +8,12 @@ from sqlalchemy import or_
|
|||||||
from sqlalchemy import not_
|
from sqlalchemy import not_
|
||||||
from sqlalchemy import tuple_
|
from sqlalchemy import tuple_
|
||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
|
from hexathon import add_0x
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
|
from chainqueue.db.models.otx import Otx
|
||||||
|
from chainqueue.db.models.tx import TxCache
|
||||||
|
from chainqueue.db.models.base import SessionBase
|
||||||
from chainqueue.db.enum import status_str
|
from chainqueue.db.enum import status_str
|
||||||
from chainqueue.db.enum import (
|
from chainqueue.db.enum import (
|
||||||
StatusEnum,
|
StatusEnum,
|
||||||
@ -17,11 +21,14 @@ from chainqueue.db.enum import (
|
|||||||
is_alive,
|
is_alive,
|
||||||
dead,
|
dead,
|
||||||
)
|
)
|
||||||
|
from chainqueue.error import (
|
||||||
|
NotLocalTxError,
|
||||||
|
)
|
||||||
|
|
||||||
logg = logging.getLogger().getChild(__name__)
|
logg = logging.getLogger().getChild(__name__)
|
||||||
|
|
||||||
|
|
||||||
def get_tx_cache(tx_hash):
|
def get_tx_cache(chain_spec, tx_hash):
|
||||||
"""Returns an aggregate dictionary of outgoing transaction data and metadata
|
"""Returns an aggregate dictionary of outgoing transaction data and metadata
|
||||||
|
|
||||||
:param tx_hash: Transaction hash of record to modify
|
:param tx_hash: Transaction hash of record to modify
|
||||||
@ -31,10 +38,8 @@ def get_tx_cache(tx_hash):
|
|||||||
:rtype: dict
|
:rtype: dict
|
||||||
"""
|
"""
|
||||||
session = SessionBase.create_session()
|
session = SessionBase.create_session()
|
||||||
q = session.query(Otx)
|
|
||||||
q = q.filter(Otx.tx_hash==tx_hash)
|
|
||||||
otx = q.first()
|
|
||||||
|
|
||||||
|
otx = Otx.load(tx_hash, session=session)
|
||||||
if otx == None:
|
if otx == None:
|
||||||
session.close()
|
session.close()
|
||||||
raise NotLocalTxError(tx_hash)
|
raise NotLocalTxError(tx_hash)
|
||||||
@ -47,18 +52,19 @@ def get_tx_cache(tx_hash):
|
|||||||
|
|
||||||
session.close()
|
session.close()
|
||||||
|
|
||||||
|
# TODO: DRY, get_tx_cache / get_tx
|
||||||
tx = {
|
tx = {
|
||||||
'tx_hash': otx.tx_hash,
|
'tx_hash': add_0x(otx.tx_hash),
|
||||||
'signed_tx': otx.signed_tx,
|
'signed_tx': add_0x(otx.signed_tx),
|
||||||
'nonce': otx.nonce,
|
'nonce': otx.nonce,
|
||||||
'status': status_str(otx.status),
|
'status': status_str(otx.status),
|
||||||
'status_code': otx.status,
|
'status_code': otx.status,
|
||||||
'source_token': txc.source_token_address,
|
'source_token': add_0x(txc.source_token_address),
|
||||||
'destination_token': txc.destination_token_address,
|
'destination_token': add_0x(txc.destination_token_address),
|
||||||
'block_number': txc.block_number,
|
'block_number': otx.block,
|
||||||
'tx_index': txc.tx_index,
|
'tx_index': txc.tx_index,
|
||||||
'sender': txc.sender,
|
'sender': add_0x(txc.sender),
|
||||||
'recipient': txc.recipient,
|
'recipient': add_0x(txc.recipient),
|
||||||
'from_value': int(txc.from_value),
|
'from_value': int(txc.from_value),
|
||||||
'to_value': int(txc.to_value),
|
'to_value': int(txc.to_value),
|
||||||
'date_created': txc.date_created,
|
'date_created': txc.date_created,
|
||||||
@ -69,8 +75,7 @@ def get_tx_cache(tx_hash):
|
|||||||
return tx
|
return tx
|
||||||
|
|
||||||
|
|
||||||
@celery_app.task(base=CriticalSQLAlchemyTask)
|
def get_tx(chain_spec, tx_hash):
|
||||||
def get_tx(tx_hash):
|
|
||||||
"""Retrieve a transaction queue record by transaction hash
|
"""Retrieve a transaction queue record by transaction hash
|
||||||
|
|
||||||
:param tx_hash: Transaction hash of record to modify
|
:param tx_hash: Transaction hash of record to modify
|
||||||
@ -80,25 +85,23 @@ def get_tx(tx_hash):
|
|||||||
:rtype: dict
|
:rtype: dict
|
||||||
"""
|
"""
|
||||||
session = SessionBase.create_session()
|
session = SessionBase.create_session()
|
||||||
q = session.query(Otx)
|
otx = Otx.load(tx_hash, session=session)
|
||||||
q = q.filter(Otx.tx_hash==tx_hash)
|
if otx == None:
|
||||||
tx = q.first()
|
|
||||||
if tx == None:
|
|
||||||
session.close()
|
session.close()
|
||||||
raise NotLocalTxError('queue does not contain tx hash {}'.format(tx_hash))
|
raise NotLocalTxError('queue does not contain tx hash {}'.format(tx_hash))
|
||||||
|
|
||||||
o = {
|
o = {
|
||||||
'otx_id': tx.id,
|
'otx_id': otx.id,
|
||||||
'nonce': tx.nonce,
|
'nonce': otx.nonce,
|
||||||
'signed_tx': tx.signed_tx,
|
'signed_tx': otx.signed_tx,
|
||||||
'status': tx.status,
|
'status': otx.status,
|
||||||
}
|
}
|
||||||
logg.debug('get tx {}'.format(o))
|
logg.debug('get tx {}'.format(o))
|
||||||
session.close()
|
session.close()
|
||||||
return o
|
return o
|
||||||
|
|
||||||
|
|
||||||
def get_nonce_tx(nonce, sender, chain_spec):
|
def get_nonce_tx_cache(chain_spec, nonce, sender, decoder=None):
|
||||||
"""Retrieve all transactions for address with specified nonce
|
"""Retrieve all transactions for address with specified nonce
|
||||||
|
|
||||||
:param nonce: Nonce
|
:param nonce: Nonce
|
||||||
@ -108,6 +111,8 @@ def get_nonce_tx(nonce, sender, chain_spec):
|
|||||||
:returns: Transactions
|
:returns: Transactions
|
||||||
:rtype: dict, with transaction hash as key, signed raw transaction as value
|
:rtype: dict, with transaction hash as key, signed raw transaction as value
|
||||||
"""
|
"""
|
||||||
|
chain_id = chain_spec.chain_id()
|
||||||
|
|
||||||
session = SessionBase.create_session()
|
session = SessionBase.create_session()
|
||||||
q = session.query(Otx)
|
q = session.query(Otx)
|
||||||
q = q.join(TxCache)
|
q = q.join(TxCache)
|
||||||
@ -116,18 +121,19 @@ def get_nonce_tx(nonce, sender, chain_spec):
|
|||||||
|
|
||||||
txs = {}
|
txs = {}
|
||||||
for r in q.all():
|
for r in q.all():
|
||||||
tx_signed_bytes = bytes.fromhex(r.signed_tx[2:])
|
tx_signed_bytes = bytes.fromhex(r.signed_tx)
|
||||||
tx = unpack(tx_signed_bytes, chain_id)
|
if decoder != None:
|
||||||
if sender == None or tx['from'] == sender:
|
tx = unpack(tx_signed_bytes, chain_id)
|
||||||
txs[r.tx_hash] = r.signed_tx
|
if sender != None and tx['from'] != sender:
|
||||||
|
raise IntegrityError('Cache sender {} does not match sender in tx {} using decoder {}'.format(sender, r.tx_hash, str(decoder)))
|
||||||
|
txs[r.tx_hash] = r.signed_tx
|
||||||
|
|
||||||
session.close()
|
session.close()
|
||||||
|
|
||||||
return txs
|
return txs
|
||||||
|
|
||||||
|
|
||||||
|
def get_paused_tx_cache(chain_spec, status=None, sender=None, session=None, decoder=None):
|
||||||
def get_paused_txs(chain_spec, status=None, sender=None, session=None):
|
|
||||||
"""Returns not finalized transactions that have been attempted sent without success.
|
"""Returns not finalized transactions that have been attempted sent without success.
|
||||||
|
|
||||||
:param status: If set, will return transactions with this local queue status only
|
:param status: If set, will return transactions with this local queue status only
|
||||||
@ -157,13 +163,19 @@ def get_paused_txs(chain_spec, status=None, sender=None, session=None):
|
|||||||
q = q.filter(TxCache.sender==sender)
|
q = q.filter(TxCache.sender==sender)
|
||||||
|
|
||||||
txs = {}
|
txs = {}
|
||||||
|
gas = 0
|
||||||
|
|
||||||
for r in q.all():
|
for r in q.all():
|
||||||
tx_signed_bytes = bytes.fromhex(r.signed_tx[2:])
|
tx_signed_bytes = bytes.fromhex(r.signed_tx)
|
||||||
tx = unpack(tx_signed_bytes, chain_id)
|
if decoder != None:
|
||||||
if sender == None or tx['from'] == sender:
|
tx = unpack(tx_signed_bytes, chain_id)
|
||||||
#gas += tx['gas'] * tx['gasPrice']
|
if sender != None and tx['from'] != sender:
|
||||||
txs[r.tx_hash] = r.signed_tx
|
raise IntegrityError('Cache sender {} does not match sender in tx {} using decoder {}'.format(sender, r.tx_hash, str(decoder)))
|
||||||
|
gas += tx['gas'] * tx['gasPrice']
|
||||||
|
|
||||||
|
#tx = unpack(tx_signed_bytes, chain_id)
|
||||||
|
#if sender == None or tx['from'] == sender:
|
||||||
|
txs[r.tx_hash] = r.signed_tx
|
||||||
|
|
||||||
SessionBase.release_session(session)
|
SessionBase.release_session(session)
|
||||||
|
|
||||||
|
@ -101,9 +101,6 @@ def set_final(tx_hash, block=None, fail=False):
|
|||||||
q = q.filter(Otx.tx_hash==strip_0x(tx_hash))
|
q = q.filter(Otx.tx_hash==strip_0x(tx_hash))
|
||||||
o = q.first()
|
o = q.first()
|
||||||
|
|
||||||
if o != None:
|
|
||||||
|
|
||||||
|
|
||||||
session.close()
|
session.close()
|
||||||
|
|
||||||
return tx_hash
|
return tx_hash
|
||||||
|
@ -20,6 +20,7 @@ from chainqueue.tx import create
|
|||||||
|
|
||||||
script_dir = os.path.realpath(os.path.dirname(__file__))
|
script_dir = os.path.realpath(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.WARNING)
|
||||||
logg = logging.getLogger().getChild(__name__)
|
logg = logging.getLogger().getChild(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -44,7 +45,7 @@ class TestBase(unittest.TestCase):
|
|||||||
SessionBase.poolable = False
|
SessionBase.poolable = False
|
||||||
SessionBase.transactional = False
|
SessionBase.transactional = False
|
||||||
SessionBase.procedural = False
|
SessionBase.procedural = False
|
||||||
SessionBase.connect(dsn, debug=False)
|
SessionBase.connect(dsn, debug=True)
|
||||||
|
|
||||||
ac = alembic.config.Config(os.path.join(migrationsdir, 'alembic.ini'))
|
ac = alembic.config.Config(os.path.join(migrationsdir, 'alembic.ini'))
|
||||||
ac.set_main_option('sqlalchemy.url', dsn)
|
ac.set_main_option('sqlalchemy.url', dsn)
|
||||||
|
@ -5,6 +5,7 @@ import unittest
|
|||||||
from chainqueue.db.models.tx import TxCache
|
from chainqueue.db.models.tx import TxCache
|
||||||
from chainqueue.error import NotLocalTxError
|
from chainqueue.error import NotLocalTxError
|
||||||
from chainqueue.state import *
|
from chainqueue.state import *
|
||||||
|
from chainqueue.query import get_tx_cache
|
||||||
|
|
||||||
# test imports
|
# test imports
|
||||||
from tests.base import TestTxBase
|
from tests.base import TestTxBase
|
||||||
@ -31,5 +32,10 @@ class TestTxCache(TestTxBase):
|
|||||||
self.assertEqual(txc.tx_index, 13)
|
self.assertEqual(txc.tx_index, 13)
|
||||||
|
|
||||||
|
|
||||||
|
def test_get(self):
|
||||||
|
tx_extended_dict = get_tx_cache(self.chain_spec, self.tx_hash)
|
||||||
|
self.assertEqual(tx_extended_dict['tx_hash'], self.tx_hash)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Loading…
Reference in New Issue
Block a user