commit 7c27c78ba51b25c4c3568db40e12b8d8a9c700af
parent 01f55363db5a8323c289ab82b996b66ebd0e9fff
Author: lash <dev@holbrook.no>
Date: Fri, 16 Dec 2022 08:32:55 +0000
Add support for custom processing of tx, block sources
Diffstat:
6 files changed, 82 insertions(+), 19 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
@@ -1,3 +1,5 @@
+- 0.4.8
+ * Add support for dialect differences in tx and block processing
- 0.4.7
* Add support for all power of two uint sizes
- 0.4.6
diff --git a/chainlib/eth/block.py b/chainlib/eth/block.py
@@ -93,9 +93,11 @@ class Block(BaseBlock, Src):
tx_generator = Tx
- def __init__(self, src=None):
- super(Block, self).__init__(src=src)
+ def __init__(self, src=None, dialect_filter=None):
+ super(Block, self).__init__(src=src, dialect_filter=dialect_filter)
+
+ def load_src(self, dialect_filter=None):
self.set_hash(self.src['hash'])
try:
self.number = int(strip_0x(self.src['number']), 16)
@@ -117,6 +119,9 @@ class Block(BaseBlock, Src):
self.fee_cost = self.src['gas_used']
self.parent_hash = self.src['parent_hash']
+ if dialect_filter != None:
+ dialect_filter.apply_block(self)
+
def tx_index_by_hash(self, tx_hash):
i = 0
diff --git a/chainlib/eth/dialect/__init__.py b/chainlib/eth/dialect/__init__.py
@@ -1,5 +1,8 @@
+# external imports
+
# local imports
from chainlib.eth.error import EthException
+from chainlib.dialect import DialectFilter
class DefaultErrorParser:
@@ -7,3 +10,14 @@ class DefaultErrorParser:
"""
def translate(self, error):
return EthException('default parser codeĀ {}'.format(error))
+
+
+class DefaultDialectFilter(DialectFilter):
+
+ def apply_src(self, src):
+ try:
+ inpt = src['input']
+ except KeyError:
+ inpt = src['data']
+ src['input'] = src['data']
+ return src
diff --git a/chainlib/eth/tx.py b/chainlib/eth/tx.py
@@ -47,9 +47,11 @@ from .constant import (
from .contract import ABIContractEncoder
from .jsonrpc import to_blockheight_param
from .src import Src
+from .dialect import DefaultDialectFilter
logg = logging.getLogger(__name__)
+eth_dialect_filter = DefaultDialectFilter()
class TxFormat(enum.IntEnum):
@@ -581,7 +583,7 @@ class Tx(BaseTx, Src):
#:todo: divide up constructor method
"""
- def __init__(self, src, block=None, result=None, strict=False, rcpt=None):
+ def __init__(self, src, block=None, result=None, strict=False, rcpt=None, dialect_filter=eth_dialect_filter):
# backwards compat
self.gas_price = None
self.gas_limit = None
@@ -590,20 +592,16 @@ class Tx(BaseTx, Src):
self.r = None
self.s = None
- super(Tx, self).__init__(src, block=block, result=result, strict=strict)
+ super(Tx, self).__init__(src, block=block, result=result, strict=strict, dialect_filter=dialect_filter)
if result == None and rcpt != None:
self.apply_receipt(rcpt)
+ if dialect_filter != None:
+ dialect_filter.apply_result(rcpt)
- def apply_src(self, src):
- try:
- inpt = src['input']
- except KeyError:
- inpt = src['data']
- src['input'] = src['data']
-
- src = super(Tx, self).apply_src(src)
+ def apply_src(self, src, dialect_filter=None):
+ src = super(Tx, self).apply_src(src, dialect_filter=dialect_filter)
hsh = self.normal(src['hash'], SrcItem.HASH)
self.set_hash(hsh)
@@ -651,18 +649,20 @@ class Tx(BaseTx, Src):
self.s = src.get('s')
#self.status = Status.PENDING
+ if dialect_filter != None:
+ dialect_filter.apply_tx(self)
def as_dict(self):
return self.src
- def apply_receipt(self, rcpt, strict=False):
+ def apply_receipt(self, rcpt, strict=False, dialect_filter=None):
result = TxResult(src=rcpt)
self.apply_result(result)
- def apply_result(self, result, strict=False):
+ def apply_result(self, result, strict=False, dialect_filter=None):
"""Apply receipt data to transaction object.
Effect is the same as passing a receipt at construction.
@@ -680,7 +680,7 @@ class Tx(BaseTx, Src):
super(Tx, self).apply_result(result)
- def apply_block(self, block):
+ def apply_block(self, block, dialect_filter=None):
"""Apply block to transaction object.
:param block: Block object
@@ -705,18 +705,17 @@ class Tx(BaseTx, Src):
@staticmethod
- def from_src(src, block=None, rcpt=None, strict=False, chain_spec=None):
+ def from_src(src, block=None, rcpt=None, strict=False, chain_spec=None, dialect_filter=eth_dialect_filter):
"""Creates a new Tx object.
Alias of constructor.
"""
- tx = Tx(src, block=block, rcpt=rcpt, strict=strict)
+ tx = Tx(src, block=block, rcpt=rcpt, strict=strict, dialect_filter=dialect_filter)
if chain_spec != None:
tx.generate_wire(chain_spec)
return tx
-
def __str__(self):
if self.block != None:
return 'tx {} status {} block {} index {}'.format(add_0x(self.hash), self.status.name, self.block.number, self.index)
diff --git a/setup.cfg b/setup.cfg
@@ -1,6 +1,6 @@
[metadata]
name = chainlib-eth
-version = 0.4.7
+version = 0.4.8
description = Ethereum implementation of the chainlib interface
author = Louis Holbrook
author_email = dev@holbrook.no
diff --git a/tests/test_block.py b/tests/test_block.py
@@ -7,6 +7,7 @@ import logging
# local imports
from chainlib.eth.jsonrpc import to_blockheight_param
from chainlib.eth.block import Block
+from chainlib.eth.dialect import DialectFilter
logging.basicConfig(level=logging.DEBUG)
@@ -70,5 +71,47 @@ class TestBlock(unittest.TestCase):
self.assertEqual(to_blockheight_param(1), '0x0000000000000001')
+ def test_block_filter(self):
+ class TestFilter(DialectFilter):
+
+ def apply_block(self, block):
+ block.extra['foo'] = 'bar'
+ block.number = 24
+ return block
+
+ tx_one_src = {
+ 'hash': os.urandom(32).hex(),
+ 'from': os.urandom(20).hex(),
+ 'to': os.urandom(20).hex(),
+ 'value': 13,
+ 'data': '0xdeadbeef',
+ 'nonce': 666,
+ 'gasPrice': 100,
+ 'gas': 21000,
+ }
+ tx_two_src_hash = os.urandom(32).hex()
+
+ block_hash = os.urandom(32).hex()
+ parent_hash = os.urandom(32).hex()
+ block_author = os.urandom(20).hex()
+ block_time = datetime.datetime.utcnow().timestamp()
+ block_src = {
+ 'number': 42,
+ 'hash': block_hash,
+ 'author': block_author,
+ 'transactions': [
+ tx_one_src,
+ tx_two_src_hash,
+ ],
+ 'timestamp': block_time,
+ 'gas_used': '0x1234',
+ 'gas_limit': '0x2345',
+ 'parent_hash': parent_hash
+ }
+ block = Block(block_src, dialect_filter=TestFilter())
+ self.assertEqual(block.extra['foo'], 'bar')
+ self.assertEqual(block.number, 24)
+
+
if __name__ == '__main__':
unittest.main()