lash/backmerge #2

Merged
williamluke merged 7 commits from lash/backmerge into master 2022-02-08 13:01:34 +01:00
9 changed files with 342 additions and 216 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ build/
dist/ dist/
*.html *.html
*.egg-info/ *.egg-info/
.venv

View File

@ -1,2 +1,3 @@
# external imports # external imports
from chainlib.encode import TxHexNormalizer from chainlib.encode import TxHexNormalizer
TxNormalizer = TxHexNormalizer

View File

@ -462,6 +462,70 @@ def get_account_tx(chain_spec, address, as_sender=True, as_recipient=True, count
return txs return txs
def get_latest_txs(chain_spec, count=10, since=None, until=None, status=None, not_status=None, status_target=None, session=None):
"""Returns the lastest local queue transactions
The since parameter effect depends on its type. Results are returned inclusive of the given parameter condition.
:param chain_spec: Chain spec for transaction network
:type chain_spec: chainlib.chain.ChainSpec
:param status: Only include transactions where the given status bits are set
:type status: chainqueue.enum.StatusEnum
:param not_status: Only include transactions where the given status bits are not set
:type not_status: chainqueue.enum.StatusEnum
:param status_target: Only include transaction where the status argument is exact match
:type status_target: chainqueue.enum.StatusEnum
:param session: Backend state integrity session
:type session: varies
:raises ValueError: If address is set to be neither sender nor recipient
:returns: Transactions
:rtype: dict, with transaction hash as key, signed raw transaction as value
"""
txs = {}
session = SessionBase.bind_session(session)
try:
filter_offset = sql_range_filter(session, criteria=since)
filter_limit = sql_range_filter(session, criteria=until)
except NotLocalTxError as e:
logg.error('query build failed: {}'.format(e))
return {}
q = session.query(Otx)
q = q.join(TxCache)
if filter_offset != None:
if filter_offset[0] == 'id':
q = q.filter(Otx.id>=filter_offset[1])
elif filter_offset[0] == 'date':
q = q.filter(Otx.date_created>=filter_offset[1])
if filter_limit != None:
if filter_limit[0] == 'id':
q = q.filter(Otx.id<=filter_limit[1])
elif filter_limit[0] == 'date':
q = q.filter(Otx.date_created<=filter_limit[1])
if status != None:
if status_target == None:
status_target = status
q = q.filter(Otx.status.op('&')(status)==status_target)
if not_status != None:
q = q.filter(Otx.status.op('&')(not_status)==0)
q = q.order_by(Otx.nonce.asc(), Otx.date_created.asc()).limit(count)
results = q.all()
for r in results:
if txs.get(r.tx_hash) != None:
logg.debug('tx {} already recorded'.format(r.tx_hash))
continue
txs[r.tx_hash] = r.signed_tx
SessionBase.release_session(session)
return txs
def count_tx(chain_spec, sender=None, status=None, status_target=None, session=None): def count_tx(chain_spec, sender=None, status=None, status_target=None, session=None):
"""Count transaction records matching the given criteria. """Count transaction records matching the given criteria.

View File

@ -17,7 +17,8 @@ from chainqueue.db.enum import (
) )
from chainqueue.error import TxStateChangeError from chainqueue.error import TxStateChangeError
logg = logging.getLogger().getChild(__name__) #logg = logging.getLogger(__name__)
logg = logging.getLogger()
def create(chain_spec, nonce, holder_address, tx_hash, signed_tx, obsolete_predecessors=True, session=None): def create(chain_spec, nonce, holder_address, tx_hash, signed_tx, obsolete_predecessors=True, session=None):

View File

@ -1,8 +1,8 @@
pysha3==1.0.2 pysha3==1.0.2
hexathon~=0.0.1a8 hexathon~=0.1.0
leveldir~=0.0.2 leveldir~=0.3.0
alembic==1.4.2 alembic==1.4.2
SQLAlchemy==1.3.20 SQLAlchemy==1.3.20
confini>=0.4.1a1,<0.5.0 confini~=0.5.1
pyxdg~=0.27 pyxdg~=0.27
chainlib~=0.0.10a3 chainlib~=0.0.12

View File

@ -1,6 +1,6 @@
[metadata] [metadata]
name = chainqueue name = chainqueue
version = 0.0.6a1 version = 0.0.6a4
description = Generic blockchain transaction queue control description = Generic blockchain transaction queue control
author = Louis Holbrook author = Louis Holbrook
author_email = dev@holbrook.no author_email = dev@holbrook.no

View File

@ -1 +0,0 @@
chainlib==0.0.9a10

View File

@ -66,16 +66,17 @@ class TestTxBase(TestOtxBase):
self.to_value = 13 self.to_value = 13
backend = SQLBackend(self.db.dsn) backend = SQLBackend(self.db.dsn)
tx = { txc = TxCache(
'hash': self.tx_hash, self.tx_hash,
'from': self.alice, self.alice,
'to': self.bob, self.bob,
'source_token': self.foo_token, self.foo_token,
'destination_token': self.bar_token, self.bar_token,
'from_value': self.from_value, self.from_value,
'to_value': self.to_value, self.to_value,
} session=self.session,
backend.cache(tx, session=self.session) )
self.session.add(txc)
self.session.commit() self.session.commit()
otx = Otx.load(self.tx_hash) otx = Otx.load(self.tx_hash)

View File

@ -30,205 +30,205 @@ logg = logging.getLogger()
class TestTxQuery(TestTxBase): class TestTxQuery(TestTxBase):
# def test_get_tx(self): def test_get_tx(self):
# tx = get_tx(self.chain_spec, self.tx_hash) tx = get_tx(self.chain_spec, self.tx_hash)
# expected_keys = [ expected_keys = [
# 'otx_id', 'otx_id',
# 'status', 'status',
# 'signed_tx', 'signed_tx',
# 'nonce', 'nonce',
# ] ]
# for k in tx.keys(): for k in tx.keys():
# expected_keys.remove(k) expected_keys.remove(k)
#
# self.assertEqual(len(expected_keys), 0) self.assertEqual(len(expected_keys), 0)
#
#
# def test_nonce_tx(self): def test_nonce_tx(self):
#
# nonce_hashes = [self.tx_hash] nonce_hashes = [self.tx_hash]
# tx_hash = add_0x(os.urandom(32).hex()) tx_hash = add_0x(os.urandom(32).hex())
# signed_tx = add_0x(os.urandom(128).hex()) signed_tx = add_0x(os.urandom(128).hex())
# create( create(
# self.chain_spec, self.chain_spec,
# 42, 42,
# self.alice, self.alice,
# tx_hash, tx_hash,
# signed_tx, signed_tx,
# session=self.session, session=self.session,
# ) )
# txc = TxCache( txc = TxCache(
# tx_hash, tx_hash,
# self.alice, self.alice,
# self.bob, self.bob,
# self.foo_token, self.foo_token,
# self.bar_token, self.bar_token,
# self.from_value, self.from_value,
# self.to_value, self.to_value,
# session=self.session, session=self.session,
# ) )
# self.session.add(txc) self.session.add(txc)
# self.session.commit() self.session.commit()
#
# nonce_hashes.append(tx_hash) nonce_hashes.append(tx_hash)
#
# tx_hash = add_0x(os.urandom(32).hex()) tx_hash = add_0x(os.urandom(32).hex())
# signed_tx = add_0x(os.urandom(128).hex()) signed_tx = add_0x(os.urandom(128).hex())
# create( create(
# self.chain_spec, self.chain_spec,
# 41, 41,
# self.alice, self.alice,
# tx_hash, tx_hash,
# signed_tx, signed_tx,
# session=self.session, session=self.session,
# ) )
# txc = TxCache( txc = TxCache(
# tx_hash, tx_hash,
# self.alice, self.alice,
# self.bob, self.bob,
# self.foo_token, self.foo_token,
# self.bar_token, self.bar_token,
# self.from_value, self.from_value,
# self.to_value, self.to_value,
# session=self.session, session=self.session,
# ) )
# self.session.add(txc) self.session.add(txc)
#
# txs = get_nonce_tx_cache(self.chain_spec, 42, self.alice) txs = get_nonce_tx_cache(self.chain_spec, 42, self.alice)
# self.assertEqual(len(txs.keys()), 2) self.assertEqual(len(txs.keys()), 2)
#
# for h in nonce_hashes: for h in nonce_hashes:
# self.assertTrue(strip_0x(h) in txs) self.assertTrue(strip_0x(h) in txs)
#
#
# def test_paused_tx_cache(self): def test_paused_tx_cache(self):
# set_waitforgas(self.chain_spec, self.tx_hash) set_waitforgas(self.chain_spec, self.tx_hash)
#
# tx_hash = add_0x(os.urandom(32).hex()) tx_hash = add_0x(os.urandom(32).hex())
# signed_tx = add_0x(os.urandom(128).hex()) signed_tx = add_0x(os.urandom(128).hex())
# create( create(
# self.chain_spec, self.chain_spec,
# 43, 43,
# self.alice, self.alice,
# tx_hash, tx_hash,
# signed_tx, signed_tx,
# session=self.session, session=self.session,
# ) )
# txc = TxCache( txc = TxCache(
# tx_hash, tx_hash,
# self.alice, self.alice,
# self.bob, self.bob,
# self.foo_token, self.foo_token,
# self.bar_token, self.bar_token,
# self.from_value, self.from_value,
# self.to_value, self.to_value,
# session=self.session, session=self.session,
# ) )
# self.session.add(txc) self.session.add(txc)
# self.session.commit() self.session.commit()
#
# txs = get_paused_tx_cache(self.chain_spec, status=StatusBits.GAS_ISSUES, sender=self.alice, session=self.session) txs = get_paused_tx_cache(self.chain_spec, status=StatusBits.GAS_ISSUES, sender=self.alice, session=self.session)
# self.assertEqual(len(txs.keys()), 1) self.assertEqual(len(txs.keys()), 1)
#
# txs = get_paused_tx_cache(self.chain_spec, status=StatusBits.GAS_ISSUES, session=self.session) txs = get_paused_tx_cache(self.chain_spec, status=StatusBits.GAS_ISSUES, session=self.session)
# self.assertEqual(len(txs.keys()), 1) self.assertEqual(len(txs.keys()), 1)
#
# tx_hash = add_0x(os.urandom(32).hex()) tx_hash = add_0x(os.urandom(32).hex())
# signed_tx = add_0x(os.urandom(128).hex()) signed_tx = add_0x(os.urandom(128).hex())
# create( create(
# self.chain_spec, self.chain_spec,
# 42, 42,
# self.bob, self.bob,
# tx_hash, tx_hash,
# signed_tx, signed_tx,
# session=self.session, session=self.session,
# ) )
# txc = TxCache( txc = TxCache(
# tx_hash, tx_hash,
# self.bob, self.bob,
# self.alice, self.alice,
# self.bar_token, self.bar_token,
# self.foo_token, self.foo_token,
# self.to_value, self.to_value,
# self.from_value, self.from_value,
# session=self.session, session=self.session,
# ) )
# self.session.add(txc) self.session.add(txc)
# self.session.commit() self.session.commit()
#
# txs = get_paused_tx_cache(self.chain_spec, status=StatusBits.GAS_ISSUES, session=self.session) txs = get_paused_tx_cache(self.chain_spec, status=StatusBits.GAS_ISSUES, session=self.session)
# self.assertEqual(len(txs.keys()), 1) self.assertEqual(len(txs.keys()), 1)
#
# set_waitforgas(self.chain_spec, tx_hash) set_waitforgas(self.chain_spec, tx_hash)
# self.session.commit() self.session.commit()
#
# txs = get_paused_tx_cache(self.chain_spec, status=StatusBits.GAS_ISSUES, session=self.session) txs = get_paused_tx_cache(self.chain_spec, status=StatusBits.GAS_ISSUES, session=self.session)
# self.assertEqual(len(txs.keys()), 2) self.assertEqual(len(txs.keys()), 2)
#
# txs = get_paused_tx_cache(self.chain_spec, status=StatusBits.GAS_ISSUES, sender=self.bob, session=self.session) txs = get_paused_tx_cache(self.chain_spec, status=StatusBits.GAS_ISSUES, sender=self.bob, session=self.session)
# self.assertEqual(len(txs.keys()), 1) self.assertEqual(len(txs.keys()), 1)
#
#
# def test_count(self): def test_count(self):
# for i in range(3): for i in range(3):
# tx_hash = add_0x(os.urandom(32).hex()) tx_hash = add_0x(os.urandom(32).hex())
# signed_tx = add_0x(os.urandom(128).hex()) signed_tx = add_0x(os.urandom(128).hex())
# create( create(
# self.chain_spec, self.chain_spec,
# i, i,
# self.alice, self.alice,
# tx_hash, tx_hash,
# signed_tx, signed_tx,
# session=self.session, session=self.session,
# ) )
# txc = TxCache( txc = TxCache(
# tx_hash, tx_hash,
# self.alice, self.alice,
# self.bob, self.bob,
# self.foo_token, self.foo_token,
# self.bar_token, self.bar_token,
# self.from_value, self.from_value,
# self.to_value, self.to_value,
# session=self.session, session=self.session,
# ) )
# self.session.add(txc) self.session.add(txc)
# set_ready(self.chain_spec, tx_hash, session=self.session) set_ready(self.chain_spec, tx_hash, session=self.session)
# set_reserved(self.chain_spec, tx_hash, session=self.session) set_reserved(self.chain_spec, tx_hash, session=self.session)
# if i > 0: if i > 0:
# set_sent(self.chain_spec, tx_hash, session=self.session) set_sent(self.chain_spec, tx_hash, session=self.session)
# if i == 2: if i == 2:
# set_final(self.chain_spec, tx_hash, session=self.session) set_final(self.chain_spec, tx_hash, session=self.session)
#
# tx_hash = add_0x(os.urandom(32).hex()) tx_hash = add_0x(os.urandom(32).hex())
# signed_tx = add_0x(os.urandom(128).hex()) signed_tx = add_0x(os.urandom(128).hex())
# create( create(
# self.chain_spec, self.chain_spec,
# i, i,
# self.bob, self.bob,
# tx_hash, tx_hash,
# signed_tx, signed_tx,
# session=self.session, session=self.session,
# ) )
# txc = TxCache( txc = TxCache(
# tx_hash, tx_hash,
# self.bob, self.bob,
# self.carol, self.carol,
# self.foo_token, self.foo_token,
# self.bar_token, self.bar_token,
# self.from_value, self.from_value,
# self.to_value, self.to_value,
# session=self.session, session=self.session,
# ) )
#
# self.session.add(txc) self.session.add(txc)
# set_ready(self.chain_spec, tx_hash, session=self.session) set_ready(self.chain_spec, tx_hash, session=self.session)
# set_reserved(self.chain_spec, tx_hash, session=self.session) set_reserved(self.chain_spec, tx_hash, session=self.session)
# set_sent(self.chain_spec, tx_hash, session=self.session) set_sent(self.chain_spec, tx_hash, session=self.session)
# self.session.commit() self.session.commit()
#
# self.assertEqual(count_tx(self.chain_spec, status=StatusBits.IN_NETWORK | StatusBits.FINAL, status_target=StatusBits.IN_NETWORK), 2) self.assertEqual(count_tx(self.chain_spec, status=StatusBits.IN_NETWORK | StatusBits.FINAL, status_target=StatusBits.IN_NETWORK), 2)
# self.assertEqual(count_tx(self.chain_spec, address=self.alice, status=StatusBits.IN_NETWORK | StatusBits.FINAL, status_target=StatusBits.IN_NETWORK), 1) self.assertEqual(count_tx(self.chain_spec, sender=self.alice, status=StatusBits.IN_NETWORK | StatusBits.FINAL, status_target=StatusBits.IN_NETWORK), 1)
#
def test_account_tx(self): def test_account_tx(self):
@ -345,6 +345,65 @@ class TestTxQuery(TestTxBase):
txs = get_account_tx(self.chain_spec, self.alice, as_sender=True, as_recipient=False, not_status=StatusBits.QUEUED, status=StatusBits.IN_NETWORK, session=self.session) txs = get_account_tx(self.chain_spec, self.alice, as_sender=True, as_recipient=False, not_status=StatusBits.QUEUED, status=StatusBits.IN_NETWORK, session=self.session)
self.assertEqual(len(txs.keys()), 1) self.assertEqual(len(txs.keys()), 1)
def test_latest_txs(self):
nonce_hashes = [self.tx_hash]
tx_hash = add_0x(os.urandom(32).hex())
signed_tx = add_0x(os.urandom(128).hex())
create(
self.chain_spec,
42,
self.alice,
tx_hash,
signed_tx,
session=self.session,
)
txc = TxCache(
tx_hash,
self.alice,
self.bob,
self.foo_token,
self.bar_token,
self.from_value,
self.to_value,
session=self.session,
)
self.session.add(txc)
self.session.commit()
nonce_hashes.append(tx_hash)
time_between = datetime.datetime.utcnow()
tx_hash = add_0x(os.urandom(32).hex())
signed_tx = add_0x(os.urandom(128).hex())
create(
self.chain_spec,
41,
self.alice,
tx_hash,
signed_tx,
session=self.session,
)
txc = TxCache(
tx_hash,
self.alice,
self.bob,
self.foo_token,
self.bar_token,
self.from_value,
self.to_value,
session=self.session,
)
self.session.add(txc)
nonce_hashes.append(tx_hash)
txs = get_latest_txs(self.chain_spec, session=self.session)
self.assertEqual(len(txs.keys()), 3)
txs = get_latest_txs(self.chain_spec, count=1, session=self.session)
self.assertEqual(len(txs.keys()), 1)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()