Add chain interface driver

This commit is contained in:
lash
2022-03-30 06:55:21 +00:00
parent e8decb9cb7
commit 8527901e6c
8 changed files with 184 additions and 14 deletions

View File

@@ -0,0 +1 @@
from .base import SyncDriver

View File

@@ -94,11 +94,12 @@ class SyncDriver:
def loop(self, conn, item, interval=1):
logg.debug('started loop')
tx_start = item.tx_cursor
while self.running and SyncDriver.running_global:
self.last_start = time.clock_gettime_ns(self.clock_id)
if self.pre_callback != None:
self.pre_callback()
while True and self.running:
try:
block = self.get(conn, item)
@@ -111,27 +112,26 @@ class SyncDriver:
self.block_callback(block, None)
try:
self.process(conn, item, block, tx_start)
self.process(conn, item, block)
except IndexError:
item.next(advance_block=True)
tx_start = 0
time.sleep(self.yield_delay)
if self.store.target > -1 and block.number >= self.store.target:
self.running = False
if self.post_callback != None:
self.post_callback()
logg.debug('fooo')
if self.store.target > -1 and block.number >= self.store.target:
self.running = False
self.idle(interval)
def process_single(self, conn, block, tx):
logg.debug('single')
self.session.filter(conn, block, tx)
def process(self, conn, block, tx_start):
def process(self, conn, item, block):
raise NotImplementedError()

View File

@@ -0,0 +1,57 @@
# external imports
from chainlib.error import RPCException
# local imports
from chainsyncer.error import NoBlockForYou
from chainsyncer.driver import SyncDriver
class ChainInterfaceDriver(SyncDriver):
def __init__(self, store, chain_interface, offset=0, target=-1, pre_callback=None, post_callback=None, block_callback=None, idle_callback=None):
super(ChainInterfaceDriver, self).__init__(store, offset=offset, target=target, pre_callback=pre_callback, post_callback=post_callback, block_callback=block_callback, idle_callback=idle_callback)
self.chain_interface = chain_interface
def get(self, conn, item):
"""Retrieve the block currently defined by the syncer cursor from the RPC provider.
:param conn: RPC connection
:type conn: chainlib.connectin.RPCConnection
:raises NoBlockForYou: Block at the given height does not exist
:rtype: chainlib.block.Block
:returns: Block object
"""
o = self.chain_interface.block_by_number(item.cursor)
try:
r = conn.do(o)
except RPCException:
r = None
if r == None:
raise NoBlockForYou()
b = self.chain_interface.block_from_src(r)
b.txs = b.txs[item.tx_cursor:]
return b
def process(self, conn, item, block):
tx_src = None
i = item.tx_cursor
while True:
# handle block objects regardless of whether the tx data is embedded or not
try:
tx = block.tx(i)
except AttributeError:
tx_hash = block.txs[i]
o = self.chain_interface.tx_by_hash(tx_hash, block=block)
r = conn.do(o)
#tx = self.chain_interface.tx_from_src(tx_src, block=block)
rcpt = conn.do(self.chain_interface.tx_receipt(tx.hash))
if rcpt != None:
tx.apply_receipt(self.chain_interface.src_normalize(rcpt))
self.process_single(conn, block, tx)
i += 1

View File

@@ -121,7 +121,7 @@ class MockBlock:
:param i: Transaction index
:type i: int
"""
return MockTx(i, self.txs[i])
return MockTx(i, self.txs[i].hash)
class MockStore(State):
@@ -170,7 +170,7 @@ class MockFilter:
r = True
self.brk -= 1
self.contents.append((block.number, tx.index, tx.hash,))
logg.debug('filter {} result {} block {}'.format(self.common_name(), r, block.number))
logg.debug('filter {} result {} block {} tx {} {}'.format(self.common_name(), r, block.number, tx.index, tx.hash))
return r
@@ -202,8 +202,8 @@ class MockDriver(SyncDriver):
raise NoBlockForYou()
def process(self, conn, item, block, tx_start):
i = tx_start
def process(self, conn, item, block):
i = item.tx_cursor
while self.running:
if self.interrupt != None:
if self.interrupt[0] == block.number and self.interrupt[1] == i:
@@ -216,3 +216,54 @@ class MockDriver(SyncDriver):
self.process_single(conn, block, tx)
item.next()
i += 1
class MockChainInterface:
def block_by_number(self, number):
return ('block_by_number', number,)
def tx_by_hash(self, hsh):
return ('tx_by_hash', hsh,)
def block_from_src(self, src):
return src
def src_normalize(self, src):
return src
def tx_receipt(self, hsh):
return ('receipt', hsh,)
class MockChainInterfaceConn(MockConn):
def __init__(self, interface):
self.ifc = interface
self.blocks = {}
self.txs = {}
def add_block(self, block):
logg.debug('add block {} {} with {} txs'.format(block.number, block.hash, len(block.txs)))
self.blocks[block.number] = block
for tx in block.txs:
self.txs[tx.hash] = tx
def do(self, o):
m = getattr(self, 'handle_' + o[0])
return m(o[1])
def handle_block_by_number(self, number):
return self.blocks[number]
def handle_receipt(self, hsh):
return {}