eth-cache

Ethereum chain data caching tools
Log | Files | Refs | LICENSE

commit a29785488fe8919b4fbf1b229a65a7d25750659a
parent 182e7e2bb244a98b8bb92f8057b1070e46d82189
Author: lash <dev@holbrook.no>
Date:   Tue, 18 Jun 2024 03:23:50 +0100

Implement address to tx index in lmdb

Diffstat:
Meth_cache/store/lmdb.py | 55++++++++++++++++++++++++++++++++++++++-----------------
Mtests/test_lmdb.py | 44+++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 81 insertions(+), 18 deletions(-)

diff --git a/eth_cache/store/lmdb.py b/eth_cache/store/lmdb.py @@ -38,8 +38,8 @@ class LmdbStoreAdder: def add(self, k, v): print("adding {} {} {}\n".format(self.action, k, v)) dbk = to_path_key(self.action.value, k) - with self.db.begin(write=True) as tx: - tx.put(dbk, v) + with self.db.begin(write=True) as dbtx: + dbtx.put(dbk, v) class LmdbStore(FsStore): @@ -53,46 +53,67 @@ class LmdbStore(FsStore): def put_tx(self, tx, include_data=False): super(LmdbStore, self).put_tx(tx, include_data=include_data) -# raw = pack(tx.src, self.chain_spec) -# tx_hash_dirnormal = strip_0x(tx.hash).upper() -# tx_hash_bytes = bytes.fromhex(tx_hash_dirnormal) -# k = self.__to_path_key('tx_raw', tx_hash_bytes) -# with self.db.begin(write=True) as tx: -# tx.put(k, raw) def get_tx(self, tx_hash): k = bytes.fromhex(tx_hash) k = to_path_key(StoreAction.TX.value, k) - with self.db.begin() as tx: - return tx.get(k) + with self.db.begin() as dbtx: + return dbtx.get(k) def get_rcpt(self, tx_hash): k = bytes.fromhex(tx_hash) k = to_path_key(StoreAction.RCPT.value, k) - with self.db.begin() as tx: - return tx.get(k) + with self.db.begin() as dbtx: + return dbtx.get(k) def get_block(self, block_hash): k = bytes.fromhex(block_hash) k = to_path_key(StoreAction.BLOCK.value, k) - with self.db.begin() as tx: - return tx.get(k) + with self.db.begin() as dbtx: + return dbtx.get(k) def get_block_number(self, block_number): r = None k = block_number.to_bytes(8, byteorder='big') k = to_path_key(StoreAction.BLOCK_NUM.value, k) - with self.db.begin() as tx: - r = tx.get(k) + with self.db.begin() as dbtx: + r = dbtx.get(k) return self.get_block(r.hex()) + def get_address_tx(self, address): + k = bytes.fromhex(address) + ok = to_path_key(StoreAction.ADDRESS.value, k) + tx_hashes = [] + with self.db.begin() as dbtx: + dbcr = dbtx.cursor() + v = dbcr.set_range(ok) + if v == None: + return tx_hashes + l = len(ok) + for k, v in dbcr: + if k[:l] != ok: + return tx_hashes + tx_hashes.append(v) + + def put_address(self, tx, address): - pass + address_bytes = bytes.fromhex(strip_0x(address)) + tx_hash_bytes = bytes.fromhex(strip_0x(tx.hash)) + k = address_bytes + tx_hash_bytes + b'.start' + + with self.db.begin() as dbtx: + r = dbtx.get(k) + if r != None: + return + + num = tx.block.number + v = num.to_bytes(8, byteorder='big') + self.add(StoreAction.ADDRESS, k, v) def __str__(self): diff --git a/tests/test_lmdb.py b/tests/test_lmdb.py @@ -5,12 +5,19 @@ import json # external imports from chainlib.eth.address import is_same_address from hexathon import strip_0x +from chainlib.eth.gas import ( + Gas, + OverrideGasOracle, + ) +from chainlib.eth.nonce import RPCNonceOracle from chainlib.eth.block import ( block_by_hash, block_by_number, + Block, ) from chainlib.eth.tx import ( transaction, + Tx, ) @@ -46,7 +53,6 @@ class TestCacheBasic(TestCache): block_hash = strip_0x(self.block.hash) block_number = int(self.block.number) j = self.store.get_block_number(block_number) - print("foo {}".format(j)) block = json.loads(j) retrieved_block_hash = strip_0x(block['hash']) self.assertEqual(retrieved_block_hash, block_hash) @@ -77,5 +83,41 @@ class TestCacheBasic(TestCache): self.assertTrue(is_same_address(tx_src['hash'], self.tx.hash)) + def test_address(self): + nonce_oracle = RPCNonceOracle(self.accounts[2], self.rpc) + gas_oracle = OverrideGasOracle(price=100000000000, limit=30000) + c = Gas(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle) + (tx_hash, o) = c.create(self.accounts[2], self.accounts[1], 1024) + r = self.rpc.do(o) + o = transaction(tx_hash) + tx_src = self.rpc.do(o) + + o = block_by_hash(tx_src['block_hash']) + block_src = self.rpc.do(o) + block = Block(block_src) + + tx = Tx(tx_src, block=block) + self.store.put_tx(tx, include_data=True) + + nonce_oracle = RPCNonceOracle(self.accounts[1], self.rpc) + c = Gas(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle, gas_oracle=gas_oracle) + (tx_hash, o) = c.create(self.accounts[1], self.accounts[0], 1024) + r = self.rpc.do(o) + o = transaction(tx_hash) + tx_src = self.rpc.do(o) + + o = block_by_hash(tx_src['block_hash']) + block_src = self.rpc.do(o) + block = Block(block_src) + + tx = Tx(tx_src, block=block) + self.store.put_tx(tx, include_data=True) + + address = strip_0x(self.accounts[1]) + # TODO: add test to limit iteration to within given address + txs = self.store.get_address_tx(address) + self.assertEqual(len(txs), 2) + + if __name__ == '__main__': unittest.main()