def test_add_missing_transaction(self): cache = TransactionCache(self.store) tx_bytes_1 = bytes.fromhex(tx_hex_1) tx_hash_1 = bitcoinx.double_sha256(tx_bytes_1) with SynchronousWriter() as writer: cache.add_missing_transaction( tx_hash_1, 100, 94, completion_callback=writer.get_callback()) assert writer.succeeded() assert cache.is_cached(tx_hash_1) entry = cache.get_entry(tx_hash_1) assert TxFlags.HasFee | TxFlags.HasHeight, entry.flags & TxFlags.METADATA_FIELD_MASK assert entry.bytedata is None tx_bytes_2 = bytes.fromhex(tx_hex_2) tx_hash_2 = bitcoinx.double_sha256(tx_bytes_2) with SynchronousWriter() as writer: cache.add_missing_transaction( tx_hash_2, 200, completion_callback=writer.get_callback()) assert writer.succeeded() assert cache.is_cached(tx_hash_2) entry = cache.get_entry(tx_hash_2) assert TxFlags.HasHeight == entry.flags & TxFlags.METADATA_FIELD_MASK assert entry.bytedata is None
def test_add_then_update(self): cache = TransactionCache(self.store) bytedata_1 = bytes.fromhex(tx_hex_1) tx_hash_1 = bitcoinx.double_sha256(bytedata_1) metadata_1 = TxData(position=11) with SynchronousWriter() as writer: cache.add( [(tx_hash_1, metadata_1, bytedata_1, TxFlags.StateDispatched)], completion_callback=writer.get_callback()) assert writer.succeeded() assert cache.is_cached(tx_hash_1) entry = cache.get_entry(tx_hash_1) assert TxFlags.HasByteData | TxFlags.HasPosition | TxFlags.StateDispatched == entry.flags assert entry.bytedata is not None metadata_2 = TxData(fee=10, height=88) propagate_flags = TxFlags.HasFee | TxFlags.HasHeight with SynchronousWriter() as writer: cache.update([(tx_hash_1, metadata_2, None, propagate_flags | TxFlags.HasPosition)], completion_callback=writer.get_callback()) assert writer.succeeded() entry = cache.get_entry(tx_hash_1) expected_flags = propagate_flags | TxFlags.StateDispatched | TxFlags.HasByteData assert expected_flags == entry.flags, \ f"{TxFlags.to_repr(expected_flags)} != {TxFlags.to_repr(entry.flags)}" assert entry.bytedata is not None
def test_delete(self): cache = TransactionCache(self.store) tx_1 = Transaction.from_hex(tx_hex_1) tx_hash_1 = tx_1.hash() data = TxData(position=11) with SynchronousWriter() as writer: cache.add([ (tx_hash_1, data, tx_1, TxFlags.StateDispatched, None) ], completion_callback=writer.get_callback()) assert writer.succeeded() assert len(self.store.read_metadata(tx_hashes=[ tx_hash_1 ])) assert cache.is_cached(tx_hash_1) with SynchronousWriter() as writer: cache.delete(tx_hash_1, completion_callback=writer.get_callback()) assert writer.succeeded() assert not len(self.store.read_metadata(tx_hashes=[ tx_hash_1 ])) assert not cache.is_cached(tx_hash_1)
def test_add_transaction(self): cache = TransactionCache(self.store) tx = Transaction.from_hex(tx_hex_1) tx_hash = tx.hash() with SynchronousWriter() as writer: cache.add_transaction(tx_hash, tx, completion_callback=writer.get_callback()) assert writer.succeeded() assert cache.is_cached(tx_hash) entry = cache.get_entry(tx_hash) assert TxFlags.HasByteData == entry.flags & TxFlags.HasByteData assert cache.have_transaction_data_cached(tx_hash)
def test_get_flags(self): cache = TransactionCache(self.store) assert cache.get_flags(os.urandom(10).hex()) is None tx_1 = Transaction.from_hex(tx_hex_1) tx_hash_1 = tx_1.hash() data = TxData(position=11) with SynchronousWriter() as writer: cache.add([ (tx_hash_1, data, tx_1, TxFlags.StateDispatched, None) ], completion_callback=writer.get_callback()) assert writer.succeeded() assert cache.is_cached(tx_hash_1) assert TxFlags.StateDispatched | TxFlags.HasByteData | TxFlags.HasPosition == \ cache.get_flags(tx_hash_1)
def test_add_then_update(self): cache = TransactionCache(self.store) bytedata_1 = bytes.fromhex(tx_hex_1) tx_hash_1 = bitcoinx.double_sha256(bytedata_1) metadata_1 = TxData(position=11) with SynchronousWriter() as writer: cache.add([(tx_hash_1, metadata_1, bytedata_1, TxFlags.StateDispatched, None)], completion_callback=writer.get_callback()) assert writer.succeeded() assert cache.is_cached(tx_hash_1) entry = cache.get_entry(tx_hash_1) assert TxFlags.HasByteData | TxFlags.HasPosition | TxFlags.StateDispatched == entry.flags assert cache.have_transaction_data_cached(tx_hash_1) # NOTE: We are not updating bytedata, and it should remain the same. The flags we pass # into update are treated specially to achieve this. metadata_2 = TxData(fee=10, height=88) propagate_flags = TxFlags.HasFee | TxFlags.HasHeight with SynchronousWriter() as writer: cache.update([(tx_hash_1, metadata_2, None, propagate_flags | TxFlags.HasPosition)], completion_callback=writer.get_callback()) assert writer.succeeded() # Check the cache to see that the flags are correct and that bytedata is cached. entry = cache.get_entry(tx_hash_1) expected_flags = propagate_flags | TxFlags.StateDispatched | TxFlags.HasByteData assert expected_flags == entry.flags, \ f"{TxFlags.to_repr(expected_flags)} != {TxFlags.to_repr(entry.flags)}" assert cache.have_transaction_data_cached(tx_hash_1) # Check the store to see that the flags are correct and the bytedata is retained. rows = self.store.read(tx_hashes=[tx_hash_1]) assert 1 == len(rows) get_tx_hash, bytedata_get, flags_get, metadata_get = rows[0] assert bytedata_1 == bytedata_get assert flags_get & TxFlags.HasByteData != 0
def test_update_or_add(self): cache = TransactionCache(self.store) # Add. bytedata_1 = bytes.fromhex(tx_hex_1) tx_hash_1 = bitcoinx.double_sha256(bytedata_1) metadata_1 = TxData() with SynchronousWriter() as writer: cache.update_or_add( [(tx_hash_1, metadata_1, bytedata_1, TxFlags.StateSettled)], completion_callback=writer.get_callback()) assert writer.succeeded() assert cache.is_cached(tx_hash_1) entry = cache.get_entry(tx_hash_1) assert TxFlags.HasByteData | TxFlags.StateSettled == entry.flags assert entry.bytedata is not None # Update. metadata_2 = TxData(position=22) with SynchronousWriter() as writer: updated_ids = cache.update_or_add( [(tx_hash_1, metadata_2, None, TxFlags.HasPosition | TxFlags.StateDispatched)], completion_callback=writer.get_callback()) assert writer.succeeded() entry = cache.get_entry(tx_hash_1) _tx_hash, store_flags, _metadata = self.store.read_metadata( tx_hashes=[tx_hash_1])[0] # State flags if present get set in an update otherwise they remain the same. expected_flags = TxFlags.HasPosition | TxFlags.HasByteData | TxFlags.StateDispatched assert expected_flags == store_flags, \ f"{TxFlags.to_repr(expected_flags)} != {TxFlags.to_repr(store_flags)}" assert expected_flags == entry.flags, \ f"{TxFlags.to_repr(expected_flags)} != {TxFlags.to_repr(entry.flags)}" assert bytedata_1 == entry.bytedata assert metadata_2.position == entry.metadata.position assert updated_ids == set([tx_hash_1])