diff --git a/lbry/lbry/wallet/server/db/writer.py b/lbry/lbry/wallet/server/db/writer.py index 1cb5bc0d0..8de9679cd 100644 --- a/lbry/lbry/wallet/server/db/writer.py +++ b/lbry/lbry/wallet/server/db/writer.py @@ -684,6 +684,7 @@ class SQLDB: def advance_txs(self, height, all_txs, header, daemon_height, timer): insert_claims = [] update_claims = [] + update_claim_hashes = set() delete_claim_hashes = set() insert_supports = [] delete_support_txo_hashes = set() @@ -718,15 +719,25 @@ class SQLDB: update_claims.append(output) recalculate_claim_hashes.add(claim_hash) delete_claim_hashes.discard(claim_hash) - delete_others.discard(output.ref.hash) # claim insertion and update occurring in the same block + update_claim_hashes.add(claim_hash) body_timer.stop() - skip_claim_timer = timer.add_timer('skip insertion of abandoned claims') - skip_claim_timer.start() + skip_update_claim_timer = timer.add_timer('skip update of abandoned claims') + skip_update_claim_timer.start() + for updated_claim in list(update_claims): + if updated_claim.ref.hash in delete_others: + update_claims.remove(updated_claim) + delete_claim_hashes.add(updated_claim.claim_hash) + update_claim_hashes.discard(updated_claim.claim_hash) + skip_update_claim_timer.stop() + + skip_insert_claim_timer = timer.add_timer('skip insertion of abandoned claims') + skip_insert_claim_timer.start() for new_claim in list(insert_claims): if new_claim.ref.hash in delete_others: - insert_claims.remove(new_claim) - skip_claim_timer.stop() + if new_claim.claim_hash not in update_claim_hashes: + insert_claims.remove(new_claim) + skip_insert_claim_timer.stop() expire_timer = timer.add_timer('recording expired claims') expire_timer.start() diff --git a/lbry/tests/unit/wallet/server/test_sqldb.py b/lbry/tests/unit/wallet/server/test_sqldb.py index 8432b6de2..38a460c58 100644 --- a/lbry/tests/unit/wallet/server/test_sqldb.py +++ b/lbry/tests/unit/wallet/server/test_sqldb.py @@ -315,6 +315,33 @@ class TestClaimtrie(TestSQLDB): accepted=[] ) + def test_create_and_update_in_same_block(self): + advance, state = self.advance, self.state + stream = self.get_stream('Claim A', 10*COIN) + advance(10, [stream, self.get_stream_update(stream, 11*COIN)]) + self.assertTrue(reader._search()) + + def test_create_and_abandon_in_same_block(self): + advance, state = self.advance, self.state + stream = self.get_stream('Claim A', 10*COIN) + advance(10, [stream, self.get_abandon(stream)]) + self.assertFalse(reader._search()) + + def test_update_and_abandon_in_same_block(self): + advance, state = self.advance, self.state + stream = self.get_stream('Claim A', 10*COIN) + advance(10, [stream]) + update = self.get_stream_update(stream, 11*COIN) + advance(20, [update, self.get_abandon(update)]) + self.assertFalse(reader._search()) + + def test_create_update_and_delete_in_same_block(self): + advance, state = self.advance, self.state + stream = self.get_stream('Claim A', 10*COIN) + update = self.get_stream_update(stream, 11*COIN) + advance(10, [stream, update, self.get_abandon(update)]) + self.assertFalse(reader._search()) + @staticmethod def _get_x_with_claim_id_prefix(getter, prefix, cached_iteration=None, **kwargs): iterations = cached_iteration+1 if cached_iteration else 100