commit 186f28a020862e461459b2504b54711ffb8a492d
parent d5cc76fc269bc82221aeff42293346a71b3d6783
Author: lash <dev@holbrook.no>
Date:   Sun,  6 Aug 2023 14:03:01 +0100
Enable batch retrieval of receipts
Diffstat:
6 files changed, 61 insertions(+), 17 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
@@ -1,5 +1,7 @@
+* 0.8.0
+	- Enable batch rpc retrievals of receipts
 * 0.7.1
-	* Change license to AGPL3 and copyright waived to public domain
+	- Change license to AGPL3 and copyright waived to public domain
 * 0.7.0
 	- Upgrade dependencies
 * 0.6.0
diff --git a/chainsyncer/driver/chain_interface.py b/chainsyncer/driver/chain_interface.py
@@ -1,3 +1,6 @@
+# standard imports
+import logging
+
 # external imports
 from chainlib.error import RPCException
 
@@ -5,6 +8,8 @@ from chainlib.error import RPCException
 from chainsyncer.error import NoBlockForYou
 from chainsyncer.driver import SyncDriver
 
+logg = logging.getLogger(__name__)
+
 
 class ChainInterfaceDriver(SyncDriver):
 
@@ -35,7 +40,43 @@ class ChainInterfaceDriver(SyncDriver):
         return b
 
 
+    def merge_rcpts_single(self, conn, txs):
+        i = 0
+        c = len(txs)
+        for j in range(c):
+            hsh = txs[j].hash
+            o = self.chain_interface.tx_receipt(hsh)
+            r = conn.do(o)
+            txs[j].apply_receipt(r)
+            logg.debug('get receipt {}/{}: {}'.format(j+1, c, hsh))
+            i += 1
+        return i
+
+
+    def merge_rcpts(self, conn, txs):
+        if self.chain_interface.batch_limit == 1:
+            return self.merge_rcpts_single(conn, txs)
+
+        rcpts = []
+        c = 0
+        for tx in txs:
+            rcpts.append(self.chain_interface.tx_receipt(tx.hash))
+            c += 1
+            if c == self.chain_interface.batch_limit:
+                break
+
+        rcpts_r = conn.do(rcpts)
+        i = 0
+        for j in range(len(rcpts)):
+            rcpt = rcpts_r[j]
+            if rcpt != None:
+                txs[j].apply_receipt(self.chain_interface.src_normalize(rcpt))
+            i += 1
+        return i
+
+
     def process(self, conn, item, block):
+        txs = []
         i = item.tx_cursor
         while True:
             # handle block objects regardless of whether the tx data is embedded or not
@@ -45,11 +86,16 @@ class ChainInterfaceDriver(SyncDriver):
                 tx_hash = block.txs[i]
                 o = self.chain_interface.tx_by_hash(tx_hash, block=block)
                 r = conn.do(o)
+            except IndexError:
+                break
+            txs.append(tx)
+            i += 1
+  
+        j = len(txs)
+        i = 0
+        while i < j:
+            i += self.merge_rcpts(conn, txs[i:])
 
-            rcpt = conn.do(self.chain_interface.tx_receipt(tx.hash))
-            if rcpt != None:
-                tx.apply_receipt(self.chain_interface.src_normalize(rcpt))
-
+        for tx in txs:
             self.process_single(conn, block, tx)
-                        
-            i += 1
+        raise IndexError()
diff --git a/chainsyncer/unittest/base.py b/chainsyncer/unittest/base.py
@@ -221,6 +221,10 @@ class MockDriver(SyncDriver):
 
 class MockChainInterface:
 
+    def __init__(self, batch_limit=1):
+        self.batch_limit = batch_limit
+
+
     def block_by_number(self, number):
         return ('block_by_number', number,)
 
diff --git a/requirements.txt b/requirements.txt
@@ -1,5 +1,5 @@
 confini~=0.6.1
 semver==2.13.0
 hexathon~=0.1.7
-chainlib~=0.4.0
+chainlib~=0.5.0
 shep~=0.3.0
diff --git a/setup.cfg b/setup.cfg
@@ -1,6 +1,6 @@
 [metadata]
 name = chainsyncer
-version = 0.7.2
+version = 0.8.0
 description = Generic blockchain syncer driver
 author = Louis Holbrook
 author_email = dev@holbrook.no
diff --git a/test_requirements.txt b/test_requirements.txt
@@ -1,8 +0,0 @@
-chainlib-eth~=0.0.9a14
-psycopg2==2.8.6
-SQLAlchemy==1.3.20
-alembic==1.4.2
-eth_tester==0.5.0b3
-py-evm==0.3.0a20
-rlp==2.0.1
-pytest==6.0.1