sequence/amount_order resolve

This commit is contained in:
Lex Berezhny 2019-05-05 19:16:17 -04:00
parent 998ee9feba
commit 091bef1ead
3 changed files with 67 additions and 34 deletions

View file

@ -300,7 +300,8 @@ class SQLDB:
def _perform_overtake(self, height):
for overtake in self.get_overtakings():
self.execute(
f"UPDATE claim SET activation_height = {height} WHERE normalized = ?",
f"UPDATE claim SET activation_height = {height} WHERE normalized = ? "
f"AND (activation_height IS NULL OR activation_height > {height})",
(overtake['normalized'],)
)
self.execute(
@ -319,8 +320,17 @@ class SQLDB:
def get_claims(self, cols, **constraints):
if 'is_controlling' in constraints:
if {'sequence', 'amount_order'}.isdisjoint(constraints):
constraints['claimtrie.claim_hash__is_not_null'] = ''
del constraints['is_controlling']
if 'sequence' in constraints:
constraints['order_by'] = 'claim.activation_height ASC'
constraints['offset'] = int(constraints.pop('sequence')) - 1
constraints['limit'] = 1
if 'amount_order' in constraints:
constraints['order_by'] = 'claim.effective_amount DESC'
constraints['offset'] = int(constraints.pop('amount_order')) - 1
constraints['limit'] = 1
if 'claim_id' in constraints:
constraints['claim.claim_hash'] = sqlite3.Binary(
@ -348,15 +358,13 @@ class SQLDB:
constraints['claim.txo_hash'] = sqlite3.Binary(
tx_hash + struct.pack('<I', nout)
)
cur = self.db.cursor()
cur.execute(*query(
return self.db.execute(*query(
f"""
SELECT {cols} FROM claim
LEFT JOIN claimtrie USING (claim_hash)
LEFT JOIN claim as channel ON (claim.channel_hash=channel.claim_hash)
""", **constraints
))
return cur.fetchall()
)).fetchall()
def get_claims_count(self, **constraints):
constraints.pop('offset', None)

View file

@ -6,9 +6,20 @@ from lbrynet.testcase import CommandTestCase
class ResolveCommand(CommandTestCase):
async def test_resolve(self):
tx = await self.channel_create('@abc', '0.01')
channel_id = tx['outputs'][0]['claim_id']
def get_claim_id(self, tx):
return tx['outputs'][0]['claim_id']
async def assertResolvesToClaimId(self, name, claim_id):
other = (await self.resolve(name))[name]
if claim_id is None:
self.assertIn('error', other)
else:
self.assertEqual(claim_id, other['claim_id'])
async def test_resolve_response(self):
channel_id = self.get_claim_id(
await self.channel_create('@abc', '0.01')
)
# resolving a channel @abc
response = await self.resolve('lbry://@abc')
@ -70,6 +81,45 @@ class ResolveCommand(CommandTestCase):
self.assertEqual(claim['name'], 'gibberish')
self.assertNotIn('value', claim)
async def test_winning_by_effective_amount(self):
# first one remains winner unless something else changes
claim_id1 = self.get_claim_id(
await self.channel_create('@foo', allow_duplicate_name=True))
await self.assertResolvesToClaimId('@foo', claim_id1)
claim_id2 = self.get_claim_id(
await self.channel_create('@foo', allow_duplicate_name=True))
await self.assertResolvesToClaimId('@foo', claim_id1)
claim_id3 = self.get_claim_id(
await self.channel_create('@foo', allow_duplicate_name=True))
await self.assertResolvesToClaimId('@foo', claim_id1)
# supports change the winner
await self.support_create(claim_id3, '0.09')
await self.assertResolvesToClaimId('@foo', claim_id3)
await self.support_create(claim_id2, '0.19')
await self.assertResolvesToClaimId('@foo', claim_id2)
await self.support_create(claim_id1, '0.19')
await self.assertResolvesToClaimId('@foo', claim_id1)
async def test_advanced_resolve(self):
claim_id1 = self.get_claim_id(
await self.stream_create('foo', '0.7', allow_duplicate_name=True))
claim_id2 = self.get_claim_id(
await self.stream_create('foo', '0.8', allow_duplicate_name=True))
claim_id3 = self.get_claim_id(
await self.stream_create('foo', '0.9', allow_duplicate_name=True))
# plain winning claim
await self.assertResolvesToClaimId('foo', claim_id3)
# sequence resolution
await self.assertResolvesToClaimId('foo:1', claim_id1)
await self.assertResolvesToClaimId('foo:2', claim_id2)
await self.assertResolvesToClaimId('foo:3', claim_id3)
await self.assertResolvesToClaimId('foo:4', None)
# amount order resolution
await self.assertResolvesToClaimId('foo$1', claim_id3)
await self.assertResolvesToClaimId('foo$2', claim_id2)
await self.assertResolvesToClaimId('foo$3', claim_id1)
await self.assertResolvesToClaimId('foo$4', None)
async def _test_resolve_abc_foo(self):
response = await self.resolve('lbry://@abc/foo')
claim = response['lbry://@abc/foo']

View file

@ -1,25 +0,0 @@
from lbrynet.testcase import CommandTestCase
class TestClaimtrie(CommandTestCase):
def get_claim_id(self, tx):
return tx['outputs'][0]['claim_id']
async def assertWinningClaim(self, name, tx):
other = (await self.resolve(name))[name]
self.assertEqual(self.get_claim_id(tx), other['claim_id'])
async def test_designed_edge_cases(self):
tx1 = await self.channel_create('@foo', allow_duplicate_name=True)
await self.assertWinningClaim('@foo', tx1)
tx2 = await self.channel_create('@foo', allow_duplicate_name=True)
await self.assertWinningClaim('@foo', tx1)
tx3 = await self.channel_create('@foo', allow_duplicate_name=True)
await self.assertWinningClaim('@foo', tx1)
await self.support_create(self.get_claim_id(tx3), '0.09')
await self.assertWinningClaim('@foo', tx3)
await self.support_create(self.get_claim_id(tx2), '0.19')
await self.assertWinningClaim('@foo', tx2)
await self.support_create(self.get_claim_id(tx1), '0.19')
await self.assertWinningClaim('@foo', tx1)