Add addrses to nonce index on new tx object

This commit is contained in:
lash 2022-03-11 14:10:16 +00:00
parent 38aae6f8c0
commit 539d3384a6
Signed by: lash
GPG Key ID: 21D2E7BB88C2A746
3 changed files with 129 additions and 16 deletions

View File

@ -39,7 +39,7 @@ class Verify:
if from_state & state_store.RESERVED:
return 'not reserved'
if from_state & state_store.mask_error:
return 'already finalized'
return 'already in error state'
def NODE_ERROR(self, state_store, from_state):
@ -50,7 +50,14 @@ class Verify:
if from_state & state_store.RESERVED:
return 'not reserved'
if from_state & state_store.mask_error:
return 'already in error state'
def NETWORK_ERROR(self, state_store, from_state):
if from_state & state_store.FINAL:
return 'already finalized'
if from_state & state_store.IN_NETWORK:
return 'already in network'
def OBSOLETE(self, state_store, from_state):
@ -75,7 +82,28 @@ class Verify:
return 'not in error state'
elif from_state & state_store.mask_error:
return 'no first send on error state'
def SENDFAIL(self, state_store, from_state):
return self.NODE_ERROR(state_store, from_state)
def FINAL(self, state_store, from_state):
if from_state & state_store.FINAL:
return 'already finalized'
def _MINEFAIL(self, state_store, from_state):
return self.NETWORK_ERROR(state_store, from_state)
def _CANCEL(self, state_store, from_state):
if from_state:
if from_state & state_store.FINAL:
return 'already finalized'
if not from_state & (state_store.OBSOLETE | state_store.IN_NETWORK):
return 'can only cancel state having OBSOLETE and/or IN_NETWORK'
class Status(shep.persist.PersistedState):
@ -103,7 +131,9 @@ class Status(shep.persist.PersistedState):
self.alias('CANCELLED', self.IN_NETWORK | self.FINAL | self.OBSOLETE)
self.alias('OVERRIDDEN', self.FINAL | self.OBSOLETE | self.MANUAL)
self.alias('REJECTED', self.NODE_ERROR | self.FINAL)
self.alias('REVERTED', self.IN_NETWORK | self.FINAL, self.NETWORK_ERROR)
self.alias('REVERTED', self.IN_NETWORK | self.FINAL | self.NETWORK_ERROR)
self.alias('SUCCESS', self.IN_NETWORK | self.FINAL)
self.alias('_MINEFAIL', self.FINAL | self.NETWORK_ERROR)
self.alias('_CANCEL', self.FINAL | self.OBSOLETE)
self.mask_error = self.LOCAL_ERROR | self.NODE_ERROR | self.NETWORK_ERROR | self.UNKNOWN_ERROR

View File

@ -6,21 +6,34 @@ logg = logging.getLogger(__name__)
class Tx:
def __init__(self, store, seq, tx_hash, signed_tx, cache=None):
self.store = store
self.seq = seq
self.tx_hash = tx_hash
self.signed_tx = signed_tx
def __init__(self, state_store, index_store, tx_hash, cache=None):
self.state_store = state_store
self.index_store = index_store
self.cache = cache
self.k = self.__to_key(str(seq), tx_hash)
self.tx_hash = tx_hash
self.signed_tx = None
self.seq = None
self.k = None
self.synced = False
def __to_key(self, k, v):
return '{:>010s}_{}'.format(k, v)
def create(self):
self.store.put(self.k, self.signed_tx)
def create(self, seq, signed_tx):
n = str(seq)
self.k = self.__to_key(n, self.tx_hash)
self.state_store.put(self.k, signed_tx)
self.index_store.put(self.tx_hash, n)
self.synced = True
def load(self):
seq = self.index_store.get(self.tx_hash)
self.k = self.__to_key(seq, self.tx_hash)
self.signed_tx = self.state_store.get(self.k)
self.synced = True
def __match_state(self, state):
@ -45,8 +58,11 @@ class Tx:
self.state.set(self.k, self.store.NODE_ERROR)
def override(self):
self.state.set(self.k, self.store.OBSOLETE)
def override(self, manual=False):
if manual:
self.state.set(self.k, self.store.OBSOLETE | self.store.MANUAL)
else:
self.state.set(self.k, self.store.OBSOLETE)
def manual(self):
@ -64,3 +80,52 @@ class Tx:
return
self.state.change(self.k, self.store.QUEUED, self.store.INSUFFICIENT_FUNDS)
def sent(self):
if self.__match_state(self.store.IN_NETWORK):
return
self.state.change(self.k, self.state.IN_NETWORK, self.state.RESERVED | self.state.DEFERRED | self.state.QUEUED | self.state.LOCAL_ERROR | self.state.NODE_ERROR)
def sendfail(self):
if self.__match_state(self.store.NODE_ERROR):
return
self.state.change(self.k, self.state.LOCAL_ERROR | self.state.DEFERRED, self.state.RESERVED | self.state.QUEUED | self.state.INSUFFICIENT_FUNDS)
def reserve(self):
if self.__match_state(self.store.RESERVED):
return
self.state.change(self.k, self.state.RESERVED, self.state.QUEUED)
def minefail(self, block):
if self.__match_state(self.store.NETWORK_ERROR):
return
self.state.set(self.k, self.state.NETWORK_ERROR)
if self.cache:
self.cache.set_block(self.tx_hash, block)
def cancel(self, confirmed=False):
if confirmed:
self.state.change(self.k, self.state.OBSOLETE | self.state.FINAL, self.state.RESERVED | self.state.QUEUED)
else:
self.state.change(self.k, self.state.OBSOLETE, self.state.RESERVED | self.state.QUEUED)
def success(self, block):
self.state.set(self.state.FINAL)
if self.cache:
self.cache.set_block(self.tx_hash, block)
def get(status=0, limit=4096, status_exact=True):
hashes = []
i = 0
for k in self.state.list(status):
if status_exact:
if self.state.status(k) != status:
continue
hashes.append(k)
return k

View File

@ -17,6 +17,20 @@ logging.basicConfig(level=logging.DEBUG)
logg = logging.getLogger()
class MockIndexStore:
def __init__(self):
self.store = {}
def put(self, k, v):
self.store[k] = v
def get(self, k):
return self.store.get(k)
class TestShepBase(unittest.TestCase):
def setUp(self):
@ -35,9 +49,13 @@ class TestShep(TestShepBase):
tx_hash = add_0x(os.urandom(20).hex())
signed_tx = add_0x(os.urandom(128).hex())
nonce = 42
tx = Tx(self.state, nonce, tx_hash, signed_tx)
tx.create()
logg.debug('file {}'.format(self.path))
mock_store = MockIndexStore()
tx = Tx(self.state, mock_store, tx_hash)
tx.create(nonce, signed_tx)
tx_retrieved = Tx(self.state, mock_store, tx_hash)
tx_retrieved.load()
self.assertEqual(tx_retrieved.signed_tx, signed_tx)
def test_shep_valid(self):