Beispiel #1
0
    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
Beispiel #2
0
    def test_get_metadata(self):
        # Full entry caching for non-settled transactions, otherwise only metadata.
        bytedata_set_1 = bytes.fromhex(tx_hex_1)
        tx_hash_1 = bitcoinx.double_sha256(bytedata_set_1)
        metadata_set_1 = TxData(height=None, fee=2, position=None, date_added=1, date_updated=1)
        bytedata_set_2 = bytes.fromhex(tx_hex_2)
        tx_hash_2 = bitcoinx.double_sha256(bytedata_set_2)
        metadata_set_2 = TxData(height=1, fee=2, position=10, date_added=1, date_updated=1)
        with SynchronousWriter() as writer:
            self.store.create([ (tx_hash_1, metadata_set_1, bytedata_set_1, TxFlags.Unset, None),
                (tx_hash_2, metadata_set_2, bytedata_set_2, TxFlags.StateSettled, None), ],
                completion_callback=writer.get_callback())
            assert writer.succeeded()

        cache = TransactionCache(self.store)
        metadata_get = cache.get_metadata(tx_hash_1)
        assert metadata_set_1.height == metadata_get.height
        assert metadata_set_1.fee == metadata_get.fee
        assert metadata_set_1.position == metadata_get.position

        metadata_get = cache.get_metadata(tx_hash_2)
        assert metadata_set_2.height == metadata_get.height
        assert metadata_set_2.fee == metadata_get.fee
        assert metadata_set_2.position == metadata_get.position

        entry = cache._cache[tx_hash_1]
        assert cache.have_transaction_data_cached(tx_hash_1)

        entry = cache._cache[tx_hash_2]
        assert not cache.have_transaction_data_cached(tx_hash_2)
Beispiel #3
0
    def test_update_many(self):
        to_add = []
        for i in range(10):
            tx_bytes = os.urandom(10)
            tx_hash_bytes = bitcoinx.double_sha256(tx_bytes)
            tx_id = bitcoinx.hash_to_hex_str(tx_hash_bytes)
            tx_data = TxData(height=None, fee=2, position=None, timestamp=None)
            to_add.append((tx_id, tx_data, tx_bytes, TxFlags.Unset))
        self.store.add_many(to_add)

        to_update = []
        for tx_id, metadata, tx_bytes, flags in to_add:
            tx_metadata = TxData(height=1,
                                 fee=2,
                                 position=None,
                                 timestamp=None)
            to_update.append((tx_id, tx_metadata, tx_bytes, flags))
        self.store.update_many(to_update)

        for tx_id_get, metadata_get, bytedata_get, flags_get in self.store.get_many(
        ):
            for update_tx_id, update_metadata, update_tx_bytes, update_flags in to_update:
                if update_tx_id == tx_id_get:
                    self.assertEqual(metadata_get, update_metadata)
                    self.assertEqual(bytedata_get, update_tx_bytes)
                    continue
Beispiel #4
0
    def test_add_then_update(self):
        cache = TxCache(self.store)

        bytedata_1 = bytes.fromhex(tx_hex_1)
        tx_id_1 = bitcoinx.hash_to_hex_str(bitcoinx.double_sha256(bytedata_1))
        metadata_1 = TxData(position=11)
        cache.add([(tx_id_1, metadata_1, bytedata_1, TxFlags.StateDispatched)])
        self.assertTrue(cache.is_cached(tx_id_1))
        entry = cache.get_entry(tx_id_1)
        self.assertEqual(
            TxFlags.HasByteData | TxFlags.HasPosition
            | TxFlags.StateDispatched, entry.flags)
        self.assertIsNotNone(entry.bytedata)

        metadata_2 = TxData(fee=10, height=88)
        propagate_flags = TxFlags.HasFee | TxFlags.HasHeight
        cache.update([(tx_id_1, metadata_2, None,
                       propagate_flags | TxFlags.HasPosition)])
        entry = cache.get_entry(tx_id_1)
        expected_flags = propagate_flags | TxFlags.StateDispatched | TxFlags.HasByteData
        self.assertEqual(
            expected_flags, entry.flags,
            f"{TxFlags.to_repr(expected_flags)} !=  {TxFlags.to_repr(entry.flags)}"
        )
        self.assertIsNotNone(entry.bytedata)
Beispiel #5
0
    def test_update_or_add(self):
        cache = TxCache(self.store)

        # Add.
        bytedata_1 = bytes.fromhex(tx_hex_1)
        tx_hash_bytes_1 = bitcoinx.double_sha256(bytedata_1)
        tx_id_1 = bitcoinx.hash_to_hex_str(tx_hash_bytes_1)
        metadata_1 = TxData()
        cache.update_or_add([(tx_id_1, metadata_1, bytedata_1,
                              TxFlags.StateCleared)])
        self.assertTrue(cache.is_cached(tx_id_1))
        entry = cache.get_entry(tx_id_1)
        self.assertEqual(TxFlags.HasByteData | TxFlags.StateCleared,
                         entry.flags)
        self.assertIsNotNone(entry.bytedata)

        # Update.
        metadata_2 = TxData(position=22)
        cache.update_or_add([(tx_id_1, metadata_2, None,
                              TxFlags.HasPosition | TxFlags.StateDispatched)])
        entry = cache.get_entry(tx_id_1)
        store_flags = self.store.get_flags(tx_id_1)
        # State flags if present get set in an update otherwise they remain the same.
        expected_flags = TxFlags.HasPosition | TxFlags.HasByteData | TxFlags.StateDispatched
        self.assertEqual(
            expected_flags, store_flags,
            f"{TxFlags.to_repr(expected_flags)} !=  {TxFlags.to_repr(store_flags)}"
        )
        self.assertEqual(
            expected_flags, entry.flags,
            f"{TxFlags.to_repr(expected_flags)} !=  {TxFlags.to_repr(entry.flags)}"
        )
        self.assertEqual(bytedata_1, entry.bytedata)
        self.assertEqual(metadata_2.position, entry.metadata.position)
    def test_update(self):
        to_add = []
        for i in range(10):
            tx_bytes = os.urandom(10)
            tx_hash = bitcoinx.double_sha256(tx_bytes)
            tx_data = TxData(height=None, fee=2, position=None, date_added=1, date_updated=1)
            if i % 2:
                to_add.append((tx_hash, tx_data, tx_bytes, TxFlags.HasByteData, None))
            else:
                to_add.append((tx_hash, tx_data, None, TxFlags.Unset, None))
        with SynchronousWriter() as writer:
            self.store.create(to_add, completion_callback=writer.get_callback())
            assert writer.succeeded()

        to_update = []
        for tx_hash, metadata, tx_bytes, flags, description in to_add:
            tx_metadata = TxData(height=1, fee=2, position=None, date_added=1, date_updated=1)
            to_update.append((tx_hash, tx_metadata, tx_bytes, flags))
        with SynchronousWriter() as writer:
            self.store.update(to_update, completion_callback=writer.get_callback())
            assert writer.succeeded()

        for get_tx_hash, bytedata_get, flags_get, metadata_get in self.store.read():
            for update_tx_hash, update_metadata, update_tx_bytes, update_flags in to_update:
                if update_tx_hash == get_tx_hash:
                    assert metadata_get == update_metadata
                    assert bytedata_get == update_tx_bytes
                    continue
    def test_add_transaction_update(self):
        cache = TransactionCache(self.store)

        tx = Transaction.from_hex(tx_hex_1)
        data = [
            tx.hash(),
            TxData(height=1295924,
                   position=4,
                   fee=None,
                   date_added=1,
                   date_updated=1), None, TxFlags.Unset, None
        ]
        with SynchronousWriter() as writer:
            cache.add([data], completion_callback=writer.get_callback())
            assert writer.succeeded()

        entry = cache.get_entry(tx.hash())
        assert entry is not None
        assert TxFlags.Unset == entry.flags & TxFlags.STATE_MASK

        with SynchronousWriter() as writer:
            cache.add_transaction(tx,
                                  TxFlags.StateCleared,
                                  completion_callback=writer.get_callback())
            assert writer.succeeded()

        tx_hash = tx.hash()
        entry = cache.get_entry(tx_hash)
        assert entry is not None
        assert cache.have_transaction_data_cached(tx_hash)
        assert TxFlags.StateCleared == entry.flags & TxFlags.StateCleared
Beispiel #8
0
    def test_proof(self):
        bytedata = os.urandom(10)
        tx_hash = bitcoinx.double_sha256(bytedata)
        metadata = TxData(height=1,
                          fee=2,
                          position=None,
                          date_added=1,
                          date_updated=1)
        with SynchronousWriter() as writer:
            self.store.create([(tx_hash, metadata, bytedata, 0, None)],
                              completion_callback=writer.get_callback())
            assert writer.succeeded()

        position1 = 10
        merkle_branch1 = [os.urandom(32) for i in range(10)]
        proof = TxProof(position1, merkle_branch1)
        date_updated = 1
        with SynchronousWriter() as writer:
            self.store.update_proof([(tx_hash, proof, date_updated)],
                                    completion_callback=writer.get_callback())
            assert writer.succeeded()

        rows = self.store.read_proof([self.tx_hash])
        assert len(rows) == 0

        db_tx_hash, (tx_position2,
                     merkle_branch2) = self.store.read_proof([tx_hash])[0]
        assert db_tx_hash == tx_hash
        assert position1 == tx_position2
        assert merkle_branch1 == merkle_branch2
Beispiel #9
0
    def test_read_metadata(self) -> None:
        # We're going to add five matches and look for two of them, checking that we do not match
        # unwanted rows.
        all_tx_hashes = []
        datas = []
        for i in range(5):
            bytedata = os.urandom(10)
            tx_hash = bitcoinx.double_sha256(bytedata)
            metadata = TxData(height=i * 100,
                              fee=i * 1000,
                              position=None,
                              date_added=1,
                              date_updated=1)
            datas.append((tx_hash, metadata, bytedata, TxFlags.Unset, None))
            all_tx_hashes.append(tx_hash)
        with SynchronousWriter() as writer:
            self.store.create(datas, completion_callback=writer.get_callback())
            assert writer.succeeded()

        # We also ask for a dud tx_hash that won't get matched.
        select_tx_hashes = [all_tx_hashes[0], all_tx_hashes[3], b"12121212"]
        rowdatas = self.store.read_metadata(tx_hashes=select_tx_hashes)
        # Check that the two valid matches are there and their values match the projected values.
        assert len(rowdatas) == 2
        for rowdata in rowdatas:
            tx_hash = rowdata[0]
            tx_flags = rowdata[1]
            metadata = rowdata[2]
            rowidx = all_tx_hashes.index(tx_hash)
            assert metadata.height == rowidx * 100
            assert metadata.fee == rowidx * 1000
            assert metadata.position is None
Beispiel #10
0
    def test_delete(self) -> None:
        to_add = []
        for i in range(10):
            bytedata = os.urandom(10)
            tx_hash = bitcoinx.double_sha256(bytedata)
            metadata = TxData(height=1,
                              fee=2,
                              position=None,
                              date_added=1,
                              date_updated=1)
            to_add.append((tx_hash, metadata, bytedata, TxFlags.Unset, None))
        with SynchronousWriter() as writer:
            self.store.create(to_add,
                              completion_callback=writer.get_callback())
            assert writer.succeeded()

        add_hashes = set(t[0] for t in to_add)
        get_hashes = set(self._get_store_hashes())
        assert add_hashes == get_hashes
        with SynchronousWriter() as writer:
            self.store.delete(add_hashes,
                              completion_callback=writer.get_callback())
            assert writer.succeeded()

        get_hashes = self._get_store_hashes()
        assert 0 == len(get_hashes)
    def test_update__with_valid_magic_bytedata(self):
        tx_bytes = os.urandom(10)
        tx_hash = bitcoinx.double_sha256(tx_bytes)
        tx_data = TxData(height=None,
                         fee=2,
                         position=None,
                         date_added=1,
                         date_updated=1)
        row = (tx_hash, tx_data, tx_bytes, TxFlags.HasByteData, None)
        with SynchronousWriter() as writer:
            self.store.create([row], completion_callback=writer.get_callback())
            assert writer.succeeded()

        # Ensure that
        with SynchronousWriter() as writer:
            self.store.update([(tx_hash, tx_data, MAGIC_UNTOUCHED_BYTEDATA,
                                TxFlags.HasByteData)],
                              completion_callback=writer.get_callback())
            assert writer.succeeded()

        rows = self.store.read()
        assert 1 == len(rows)
        get_tx_hash, bytedata_get, flags_get, metadata_get = rows[0]
        assert tx_bytes == bytedata_get
        assert flags_get & TxFlags.HasByteData != 0
    def test_read(self):
        to_add = []
        for i in range(10):
            tx_bytes = os.urandom(10)
            tx_hash = bitcoinx.double_sha256(tx_bytes)
            tx_data = TxData(height=None, fee=2, position=None, date_added=1, date_updated=1)
            to_add.append((tx_hash, tx_data, tx_bytes, TxFlags.HasFee, None))
        with SynchronousWriter() as writer:
            self.store.create(to_add, completion_callback=writer.get_callback())
            assert writer.succeeded()

        # Test the first "add" hash is matched.
        matches = self.store.read(tx_hashes=[to_add[0][0]])
        assert to_add[0][0] == matches[0][0]

        # Test no id is matched.
        matches = self.store.read(tx_hashes=[b"aaaa"])
        assert 0 == len(matches)

        # Test flag and mask combinations.
        matches = self.store.read(flags=TxFlags.HasFee)
        assert 10 == len(matches)

        matches = self.store.read(flags=TxFlags.Unset, mask=TxFlags.HasHeight)
        assert 10 == len(matches)

        matches = self.store.read(flags=TxFlags.HasFee, mask=TxFlags.HasFee)
        assert 10 == len(matches)

        matches = self.store.read(flags=TxFlags.Unset, mask=TxFlags.HasFee)
        assert 0 == len(matches)
    def test_get_entry_cached_already(self) -> None:
        metadata = TxData(position=11, date_added=1, date_updated=1)
        flags = TxFlags.HasPosition

        def _read(*args,
                  **kwargs) -> Tuple[bytes, Optional[bytes], TxFlags, TxData]:
            nonlocal metadata, flags
            return [(b"tx_hash", None, flags, metadata)]

        def _read_metadata(*args, **kwargs) -> Tuple[bytes, TxFlags, TxData]:
            nonlocal metadata, flags
            return [(b"tx_hash", flags, metadata)]

        mock_store = MockTransactionStore()
        mock_store.read = _read
        mock_store.read_metadata = _read_metadata

        cache = TransactionCache(mock_store, 0)

        # Verify that we do not hit the store for our cached entry.
        our_entry = TransactionCacheEntry(metadata, TxFlags.HasPosition)
        cache._cache[b"tx_hash"] = our_entry

        their_entry = cache.get_entry(b"tx_hash")
        assert our_entry.metadata == their_entry.metadata
        assert our_entry.flags == their_entry.flags
Beispiel #14
0
    def test_get_transaction_after_metadata(self):
        # Getting an entry for a settled transaction should update from metadata-only to full.
        bytedata_set = bytes.fromhex(tx_hex_1)
        tx_hash = bitcoinx.double_sha256(bytedata_set)
        metadata_set = TxData(height=1, fee=2, position=None, date_added=1, date_updated=1)
        with SynchronousWriter() as writer:
            self.store.create([ (tx_hash, metadata_set, bytedata_set, TxFlags.StateSettled, None) ],
                completion_callback=writer.get_callback())
            assert writer.succeeded()

        cache = TransactionCache(self.store)
        metadata_get = cache.get_metadata(tx_hash)
        assert metadata_get is not None

        # Initial priming of cache will be only metadata.
        cached_entry_1 = cache._cache[tx_hash]
        assert not cache.have_transaction_data_cached(tx_hash)

        # Entry request will hit the database.
        entry = cache.get_entry(tx_hash)
        assert cache.have_transaction_data_cached(tx_hash)

        cached_entry_2 = cache._cache[tx_hash]
        assert entry.metadata == cached_entry_2.metadata
        assert entry.flags == cached_entry_2.flags
Beispiel #15
0
    def test_get_many(self):
        to_add = []
        for i in range(10):
            tx_bytes = os.urandom(10)
            tx_hash_bytes = bitcoinx.double_sha256(tx_bytes)
            tx_id = bitcoinx.hash_to_hex_str(tx_hash_bytes)
            tx_data = TxData(height=None, fee=2, position=None, timestamp=None)
            to_add.append((tx_id, tx_data, tx_bytes, TxFlags.HasFee))
        self.store.add_many(to_add)

        # Test the first "add" id is matched.
        matches = self.store.get_many(tx_ids=[to_add[0][0]])
        self.assertEqual(to_add[0][0], matches[0][0])

        # Test no id is matched.
        matches = self.store.get_many(tx_ids=["aaaa"])
        self.assertEqual(0, len(matches))

        # Test flag and mask combinations.
        matches = self.store.get_many(flags=TxFlags.HasFee)
        self.assertEqual(10, len(matches))

        matches = self.store.get_many(flags=TxFlags.Unset,
                                      mask=TxFlags.HasHeight)
        self.assertEqual(10, len(matches))

        matches = self.store.get_many(flags=TxFlags.HasFee,
                                      mask=TxFlags.HasFee)
        self.assertEqual(10, len(matches))

        matches = self.store.get_many(flags=TxFlags.Unset, mask=TxFlags.HasFee)
        self.assertEqual(0, len(matches))
Beispiel #16
0
    def test_update_flags(self):
        cache = TxCache(self.store)

        tx_bytes_1 = bytes.fromhex(tx_hex_1)
        tx_hash_bytes_1 = bitcoinx.double_sha256(tx_bytes_1)
        tx_id_1 = bitcoinx.hash_to_hex_str(tx_hash_bytes_1)
        data = TxData(position=11)
        cache.add([(tx_id_1, data, tx_bytes_1, TxFlags.StateDispatched)])
        self.assertTrue(cache.is_cached(tx_id_1))
        entry = cache.get_entry(tx_id_1)
        self.assertEqual(
            TxFlags.HasByteData | TxFlags.HasPosition
            | TxFlags.StateDispatched, entry.flags)
        self.assertIsNotNone(entry.bytedata)

        cache.update_flags(tx_id_1, TxFlags.StateCleared,
                           TxFlags.HasByteData | TxFlags.HasProofData)
        entry = cache.get_entry(tx_id_1)
        store_flags = self.store.get_flags(tx_id_1)
        expected_flags = TxFlags.HasByteData | TxFlags.HasPosition | TxFlags.StateCleared
        self.assertEqual(
            expected_flags, store_flags,
            f"{TxFlags.to_repr(expected_flags)} != {TxFlags.to_repr(store_flags)}"
        )
        self.assertEqual(
            expected_flags, entry.flags,
            f"{TxFlags.to_repr(expected_flags)} != {TxFlags.to_repr(entry.flags)}"
        )
        self.assertIsNotNone(entry.bytedata)
Beispiel #17
0
    def test_update_flags(self):
        bytedata = os.urandom(10)
        tx_hash_bytes = bitcoinx.double_sha256(bytedata)
        tx_id = bitcoinx.hash_to_hex_str(tx_hash_bytes)
        metadata = TxData(height=1, fee=2, position=None, timestamp=None)
        self.store.add(tx_id, metadata, bytedata)

        # Verify the field flags are assigned correctly on the add.
        expected_flags = TxFlags.HasFee | TxFlags.HasHeight | TxFlags.HasByteData
        flags = self.store.get_flags(tx_id)
        self.assertEqual(expected_flags, flags)

        flags = TxFlags.StateReceived
        mask = TxFlags.METADATA_FIELD_MASK | TxFlags.HasByteData | TxFlags.HasProofData
        self.store.update_flags(tx_id, flags, mask)

        # Verify the state flag is correctly added via the mask.
        flags_get = self.store.get_flags(tx_id)
        expected_flags |= TxFlags.StateReceived
        self.assertEqual(
            expected_flags, flags_get,
            f"{TxFlags.to_repr(expected_flags)} != {TxFlags.to_repr(flags_get)}"
        )

        flags = TxFlags.StateReceived
        mask = TxFlags.Unset
        self.store.update_flags(tx_id, flags, mask)

        # Verify the state flag is correctly set via the mask.
        flags = self.store.get_flags(tx_id)
        self.assertEqual(TxFlags.StateReceived, flags)
Beispiel #18
0
    def test_get_unsynced_ids(self):
        cache = TxCache(self.store)

        bytedata_1 = bytes.fromhex(tx_hex_1)
        tx_hash_bytes_1 = bitcoinx.double_sha256(bytedata_1)
        tx_id_1 = bitcoinx.hash_to_hex_str(tx_hash_bytes_1)
        metadata_1 = TxData(height=11)
        cache.add([(tx_id_1, metadata_1, None, TxFlags.StateCleared)])

        results = cache.get_unsynced_ids()
        self.assertEqual(1, len(results))

        metadata_2 = TxData()
        cache.update([(tx_id_1, metadata_2, bytedata_1, TxFlags.HasByteData)])

        results = cache.get_unsynced_ids()
        self.assertEqual(0, len(results))
Beispiel #19
0
    def test_labels(self):
        bytedata_1 = os.urandom(10)
        tx_hash_1 = bitcoinx.double_sha256(bytedata_1)
        metadata_1 = TxData(height=1,
                            fee=2,
                            position=None,
                            date_added=1,
                            date_updated=1)

        bytedata_2 = os.urandom(10)
        tx_hash_2 = bitcoinx.double_sha256(bytedata_2)
        metadata_2 = TxData(height=1,
                            fee=2,
                            position=None,
                            date_added=1,
                            date_updated=1)

        with SynchronousWriter() as writer:
            self.store.create([(tx_hash_1, metadata_1, bytedata_1, 0, None),
                               (tx_hash_2, metadata_2, bytedata_2, 0, None)],
                              completion_callback=writer.get_callback())
            assert writer.succeeded()

        with SynchronousWriter() as writer:
            self.store.update_descriptions(
                [("tx 1", tx_hash_1)],
                completion_callback=writer.get_callback())
            assert writer.succeeded()

        rows = self.store.read_descriptions()
        assert len(rows) == 1
        assert len([r[1] == "tx 1" for r in rows if r[0] == tx_hash_1]) == 1

        with SynchronousWriter() as writer:
            self.store.update_descriptions(
                [(None, tx_hash_1), ("tx 2", tx_hash_2)],
                completion_callback=writer.get_callback())
            assert writer.succeeded()

        rows = self.store.read_descriptions([tx_hash_2])
        assert len(rows) == 1
        assert rows[0][0] == tx_hash_2 and rows[0][1] == "tx 2"

        # Reading entries for a non-existent ...
        rows = self.store.read_descriptions([self.tx_hash])
        assert len(rows) == 0
Beispiel #20
0
 def test_delete(self):
     tx_bytes = os.urandom(10)
     tx_hash_bytes = bitcoinx.double_sha256(tx_bytes)
     tx_id = bitcoinx.hash_to_hex_str(tx_hash_bytes)
     data = TxData(height=1, fee=2, position=None, timestamp=None)
     self.store.add(tx_id, data, tx_bytes)
     self.assertTrue(self.store.has(tx_id))
     self.store.delete(tx_id)
     self.assertFalse(self.store.has(tx_id))
Beispiel #21
0
    def test_update(self):
        bytedata = os.urandom(10)
        tx_hash_bytes = bitcoinx.double_sha256(bytedata)
        tx_id = bitcoinx.hash_to_hex_str(tx_hash_bytes)
        metadata_a = TxData(height=None,
                            fee=None,
                            position=None,
                            timestamp=None)
        self.store.add(tx_id, metadata_a, bytedata)

        metadata_update = TxData(height=None,
                                 fee=100,
                                 position=None,
                                 timestamp=None)
        self.store.update(tx_id, metadata_update, bytedata)

        metadata_get, bytedata_get, flags = self.store.get(tx_id)
        self.assertEqual(metadata_update, metadata_get)
        self.assertEqual(bytedata, bytedata_get)
Beispiel #22
0
 def test_data_unpack_version_1(self):
     for hex, data, flags in [
         [
             "0101020000",
             TxData(height=1, fee=2), TxFlags.HasFee | TxFlags.HasHeight
         ],
         [
             "0200026efd4d04",
             TxData(height=-1, fee=2, position=110,
                    timestamp=1101), TxFlags.HasFee | TxFlags.HasHeight
             | TxFlags.HasPosition | TxFlags.HasTimestamp
         ],
     ]:
         raw = bytes.fromhex(hex)
         unpacked_data = self.store._unpack_data(raw, flags)
         self.assertEqual(data.height, unpacked_data.height)
         self.assertEqual(data.fee, unpacked_data.fee)
         self.assertEqual(data.position, unpacked_data.position)
         self.assertEqual(data.timestamp, unpacked_data.timestamp)
Beispiel #23
0
    def test_get_unverified_entries_too_high(self):
        cache = TxCache(self.store)

        tx_bytes_1 = bytes.fromhex(tx_hex_1)
        tx_hash_bytes_1 = bitcoinx.double_sha256(tx_bytes_1)
        tx_id_1 = bitcoinx.hash_to_hex_str(tx_hash_bytes_1)
        data = TxData(height=11, position=22)
        cache.add([(tx_id_1, data, tx_bytes_1, TxFlags.StateCleared)])

        results = cache.get_unverified_entries(100)
        self.assertEqual(0, len(results))
Beispiel #24
0
    def test_get_transaction(self):
        bytedata = bytes.fromhex(tx_hex_1)
        tx_hash_bytes = bitcoinx.double_sha256(bytedata)
        tx_id = bitcoinx.hash_to_hex_str(tx_hash_bytes)
        metadata = TxData(height=1, fee=2, position=None, timestamp=None)
        self.store.add(tx_id, metadata, bytedata)

        cache = TxCache(self.store)
        tx = cache.get_transaction(tx_id)
        self.assertIsNotNone(tx)
        self.assertEqual(tx_id, tx.txid())
Beispiel #25
0
 def test_get_all_pending(self):
     get_tx_ids = set([])
     for tx_hex in (tx_hex_1, tx_hex_2):
         bytedata = bytes.fromhex(tx_hex)
         tx_hash_bytes = bitcoinx.double_sha256(bytedata)
         tx_id = bitcoinx.hash_to_hex_str(tx_hash_bytes)
         metadata = TxData(height=1, fee=2, position=None, timestamp=None)
         self.store.add(tx_id, metadata, bytedata)
         get_tx_ids.add(tx_id)
     result_tx_ids = self.store.get_ids()
     self.assertEqual(get_tx_ids, result_tx_ids)
    def test_update__entry_with_magic_bytedata_and_set_flag(self):
        tx_bytes = os.urandom(10)
        tx_hash = bitcoinx.double_sha256(tx_bytes)
        tx_data = TxData(height=None, fee=2, position=None, date_added=1, date_updated=1)
        row = (tx_hash, tx_data, tx_bytes, TxFlags.HasByteData, None)
        with SynchronousWriter() as writer:
            self.store.create([ row ], completion_callback=writer.get_callback())
            assert writer.succeeded()

        # Ensure that the magic bytedata requires a set bytedata flag.
        with pytest.raises(AssertionError):
            self.store.update([(tx_hash, tx_data, MAGIC_UNTOUCHED_BYTEDATA, TxFlags.Unset)])
    def test_get(self):
        bytedata = os.urandom(10)
        tx_hash = bitcoinx.double_sha256(bytedata)
        metadata = TxData(height=1, fee=2, position=None, date_added=1, date_updated=1)
        with SynchronousWriter() as writer:
            self.store.create([ (tx_hash, metadata, bytedata, TxFlags.Unset, None) ],
                completion_callback=writer.get_callback())
            assert writer.succeeded()

        assert tx_hash in self._get_store_hashes()
        assert self.store.read(tx_hashes=[tx_hash])
        assert self.store.read(TxFlags.HasByteData, TxFlags.HasByteData, [tx_hash])
Beispiel #28
0
 def test_add_many(self):
     to_add = []
     for i in range(10):
         tx_bytes = os.urandom(10)
         tx_hash_bytes = bitcoinx.double_sha256(tx_bytes)
         tx_id = bitcoinx.hash_to_hex_str(tx_hash_bytes)
         tx_data = TxData(height=1, fee=2, position=None, timestamp=None)
         to_add.append((tx_id, tx_data, tx_bytes, TxFlags.Unset))
     self.store.add_many(to_add)
     existing_tx_ids = self.store.get_ids()
     added_tx_ids = set(t[0] for t in to_add)
     self.assertEqual(added_tx_ids, existing_tx_ids)
    def test_update__entry_with_set_bytedata_flag(self):
        tx_bytes = os.urandom(10)
        tx_hash = bitcoinx.double_sha256(tx_bytes)
        tx_data = TxData(height=None, fee=2, position=None, date_added=1, date_updated=1)
        row = (tx_hash, tx_data, tx_bytes, TxFlags.HasByteData, None)
        with SynchronousWriter() as writer:
            self.store.create([ row ], completion_callback=writer.get_callback())
            assert writer.succeeded()

        # Ensure that a set bytedata flag requires bytedata to be included.
        with pytest.raises(AssertionError):
            self.store.update([(tx_hash, tx_data, None, TxFlags.HasByteData)])
    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