cic-internal-integration/apps/cic-eth/cic_eth/db/models/nonce.py
2021-03-01 20:35:05 +01:00

97 lines
2.8 KiB
Python
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# standard imports
import logging
# third-party imports
from sqlalchemy import Column, String, Integer
# local imports
from .base import SessionBase
logg = logging.getLogger()
class Nonce(SessionBase):
"""Provides thread-safe nonce increments.
"""
__tablename__ = 'nonce'
nonce = Column(Integer)
address_hex = Column(String(42))
@staticmethod
def get(address, session=None):
session = SessionBase.bind_session(session)
q = session.query(Nonce)
q = q.filter(Nonce.address_hex==address)
nonce = q.first()
nonce_value = None
if nonce != None:
nonce_value = nonce.nonce;
SessionBase.release_session(session)
return nonce_value
@staticmethod
def __get(session, address):
r = session.execute("SELECT nonce FROM nonce WHERE address_hex = '{}'".format(address))
nonce = r.fetchone()
session.flush()
if nonce == None:
return None
return nonce[0]
@staticmethod
def __set(session, address, nonce):
session.execute("UPDATE nonce set nonce = {} WHERE address_hex = '{}'".format(nonce, address))
session.flush()
@staticmethod
def next(address, initial_if_not_exists=0, session=None):
"""Generate next nonce for the given address.
If there is no previous nonce record for the address, the nonce may be initialized to a specified value, or 0 if no value has been given.
:param address: Associate Ethereum address
:type address: str, 0x-hex
:param initial_if_not_exists: Initial nonce value to set if no record exists
:type initial_if_not_exists: number
:returns: Nonce
:rtype: number
"""
session = SessionBase.bind_session(session)
SessionBase.release_session(session)
session.begin_nested()
#conn = Nonce.engine.connect()
if Nonce.transactional:
#session.execute('BEGIN')
session.execute('LOCK TABLE nonce IN SHARE ROW EXCLUSIVE MODE')
session.flush()
nonce = Nonce.__get(session, address)
logg.debug('get nonce {} for address {}'.format(nonce, address))
if nonce == None:
nonce = initial_if_not_exists
session.execute("INSERT INTO nonce (nonce, address_hex) VALUES ({}, '{}')".format(nonce, address))
session.flush()
logg.debug('setting default nonce to {} for address {}'.format(nonce, address))
Nonce.__set(session, address, nonce+1)
#if Nonce.transactional:
#session.execute('COMMIT')
#session.execute('UNLOCK TABLE nonce')
#conn.close()
session.commit()
session.commit()
SessionBase.release_session(session)
return nonce