add tests for takeovers from amount changes in updates before/on/after activation

This commit is contained in:
Jack Robison 2021-09-25 14:59:42 -04:00 committed by Victor Shyba
parent f77f2f6e80
commit 6155cda66f
4 changed files with 346 additions and 60 deletions

View file

@ -1,20 +1,15 @@
import time
import asyncio
import typing
import struct
from bisect import bisect_right
from struct import pack, unpack
from concurrent.futures.thread import ThreadPoolExecutor
from typing import Optional, List, Tuple, Set, DefaultDict, Dict, NamedTuple
from prometheus_client import Gauge, Histogram
from collections import defaultdict
import array
import lbry
from lbry.schema.claim import Claim
from lbry.schema.mime_types import guess_stream_type
from lbry.wallet.ledger import Ledger, TestNetLedger, RegTestLedger
from lbry.wallet.constants import TXO_TYPES
from lbry.wallet.server.db.common import STREAM_TYPES, CLAIM_TYPES
from lbry.wallet.transaction import OutputScript, Output, Transaction
from lbry.wallet.server.tx import Tx, TxOutput, TxInput
@ -222,6 +217,7 @@ class BlockProcessor:
# attributes used for calculating stake activations and takeovers per block
#################################
self.taken_over_names: Set[str] = set()
# txo to pending claim
self.txo_to_claim: Dict[Tuple[int, int], StagedClaimtrieItem] = {}
# claim hash to pending claim txo
@ -234,6 +230,7 @@ class BlockProcessor:
self.removed_support_txos_by_name_by_claim: DefaultDict[str, DefaultDict[bytes, List[Tuple[int, int]]]] = \
defaultdict(lambda: defaultdict(list))
self.abandoned_claims: Dict[bytes, StagedClaimtrieItem] = {}
self.updated_claims: Set[bytes] = set()
# removed activated support amounts by claim hash
self.removed_active_support_amount_by_claim: DefaultDict[bytes, List[int]] = defaultdict(list)
# pending activated support amounts by claim hash
@ -513,6 +510,7 @@ class BlockProcessor:
).get_remove_activate_ops()
)
previous_amount = previous_claim.amount
self.updated_claims.add(claim_hash)
self.db.claim_to_txo[claim_hash] = ClaimToTXOValue(
tx_num, nout, root_tx_num, root_idx, txo.amount, channel_signature_is_valid, claim_name
@ -730,6 +728,8 @@ class BlockProcessor:
def _get_pending_claim_amount(self, name: str, claim_hash: bytes, height=None) -> int:
if (name, claim_hash) in self.activated_claim_amount_by_name_and_hash:
if claim_hash in self.claim_hash_to_txo:
return self.txo_to_claim[self.claim_hash_to_txo[claim_hash]].amount
return self.activated_claim_amount_by_name_and_hash[(name, claim_hash)]
if (name, claim_hash) in self.possible_future_claim_amount_by_name_and_hash:
return self.possible_future_claim_amount_by_name_and_hash[(name, claim_hash)]
@ -771,7 +771,7 @@ class BlockProcessor:
_controlling = controlling_claims[_name]
return _controlling
names_with_abandoned_controlling_claims: List[str] = []
names_with_abandoned_or_updated_controlling_claims: List[str] = []
# get the claims and supports previously scheduled to be activated at this block
activated_at_height = self.db.get_activated_at_height(height)
@ -784,7 +784,7 @@ class BlockProcessor:
nothing_is_controlling = not controlling
staged_is_controlling = False if not controlling else claim_hash == controlling.claim_hash
controlling_is_abandoned = False if not controlling else \
controlling.claim_hash in names_with_abandoned_controlling_claims
controlling.claim_hash in names_with_abandoned_or_updated_controlling_claims
if nothing_is_controlling or staged_is_controlling or controlling_is_abandoned:
delay = 0
@ -822,7 +822,7 @@ class BlockProcessor:
for claim_hash, staged in self.abandoned_claims.items():
controlling = get_controlling(staged.normalized_name)
if controlling and controlling.claim_hash == claim_hash:
names_with_abandoned_controlling_claims.append(staged.normalized_name)
names_with_abandoned_or_updated_controlling_claims.append(staged.normalized_name)
# print(f"\t{staged.name} needs takeover")
activation = self.db.get_activation(staged.tx_num, staged.position)
if activation > 0: # db returns -1 for non-existent txos
@ -845,13 +845,31 @@ class BlockProcessor:
continue
controlling = get_controlling(name)
if controlling and controlling.claim_hash == claim_hash and \
name not in names_with_abandoned_controlling_claims:
name not in names_with_abandoned_or_updated_controlling_claims:
abandoned_support_check_need_takeover[(name, claim_hash)].extend(amounts)
# get the controlling claims with updates to the claim to check if takeover is needed
for claim_hash in self.updated_claims:
if claim_hash in self.abandoned_claims:
continue
name = self._get_pending_claim_name(claim_hash)
if name is None:
continue
controlling = get_controlling(name)
if controlling and controlling.claim_hash == claim_hash and \
name not in names_with_abandoned_or_updated_controlling_claims:
names_with_abandoned_or_updated_controlling_claims.append(name)
# prepare to activate or delay activation of the pending claims being added this block
for (tx_num, nout), staged in self.txo_to_claim.items():
is_delayed = not staged.is_update
if staged.claim_hash in self.db.claim_to_txo:
prev_txo = self.db.claim_to_txo[staged.claim_hash]
prev_activation = self.db.get_activation(prev_txo.tx_num, prev_txo.position)
if height < prev_activation or prev_activation < 0:
is_delayed = True
self.db_op_stack.extend_ops(get_delayed_activate_ops(
staged.normalized_name, staged.claim_hash, not staged.is_update, tx_num, nout, staged.amount,
staged.normalized_name, staged.claim_hash, is_delayed, tx_num, nout, staged.amount,
is_support=False
))
@ -919,7 +937,7 @@ class BlockProcessor:
# go through claims where the controlling claim or supports to the controlling claim have been abandoned
# check if takeovers are needed or if the name node is now empty
need_reactivate_if_takes_over = {}
for need_takeover in names_with_abandoned_controlling_claims:
for need_takeover in names_with_abandoned_or_updated_controlling_claims:
existing = self.db.get_claim_txos_for_name(need_takeover)
has_candidate = False
# add existing claims to the queue for the takeover
@ -995,7 +1013,7 @@ class BlockProcessor:
amounts[controlling.claim_hash] = self._get_pending_effective_amount(name, controlling.claim_hash)
winning_claim_hash = max(amounts, key=lambda x: amounts[x])
if not controlling or (winning_claim_hash != controlling.claim_hash and
name in names_with_abandoned_controlling_claims) or \
name in names_with_abandoned_or_updated_controlling_claims) or \
((winning_claim_hash != controlling.claim_hash) and (amounts[winning_claim_hash] > amounts[controlling.claim_hash])):
amounts_with_future_activations = {claim_hash: amount for claim_hash, amount in amounts.items()}
amounts_with_future_activations.update(
@ -1056,13 +1074,13 @@ class BlockProcessor:
k.position, height, name, amount
).get_activate_ops()
)
self.taken_over_names.add(name)
self.db_op_stack.extend_ops(get_takeover_name_ops(name, winning_including_future_activations, height, controlling))
self.touched_claim_hashes.add(winning_including_future_activations)
if controlling and controlling.claim_hash not in self.abandoned_claims:
self.touched_claim_hashes.add(controlling.claim_hash)
elif not controlling or (winning_claim_hash != controlling.claim_hash and
name in names_with_abandoned_controlling_claims) or \
name in names_with_abandoned_or_updated_controlling_claims) or \
((winning_claim_hash != controlling.claim_hash) and (amounts[winning_claim_hash] > amounts[controlling.claim_hash])):
# print(f"\ttakeover by {winning_claim_hash.hex()} at {height}")
if (name, winning_claim_hash) in need_reactivate_if_takes_over:
@ -1090,6 +1108,7 @@ class BlockProcessor:
position, height, name, amount
).get_activate_ops()
)
self.taken_over_names.add(name)
self.db_op_stack.extend_ops(get_takeover_name_ops(name, winning_claim_hash, height, controlling))
if controlling and controlling.claim_hash not in self.abandoned_claims:
self.touched_claim_hashes.add(controlling.claim_hash)
@ -1114,7 +1133,9 @@ class BlockProcessor:
if controlling and controlling.claim_hash not in self.abandoned_claims:
amounts[controlling.claim_hash] = self._get_pending_effective_amount(name, controlling.claim_hash)
winning = max(amounts, key=lambda x: amounts[x])
if (controlling and winning != controlling.claim_hash) or (not controlling and winning):
self.taken_over_names.add(name)
# print(f"\ttakeover from abandoned support {controlling.claim_hash.hex()} -> {winning.hex()}")
self.db_op_stack.extend_ops(get_takeover_name_ops(name, winning, height, controlling))
if controlling:
@ -1126,6 +1147,13 @@ class BlockProcessor:
self.activation_info_to_send_es[claim_id].append(TrendingNotification(height, added, prev_amount, new_amount))
def _get_cumulative_update_ops(self, height: int):
# update the last takeover height for names with takeovers
for name in self.taken_over_names:
self.touched_claim_hashes.update(
{claim_hash for claim_hash in self.db.get_claims_for_name(name)
if claim_hash not in self.abandoned_claims}
)
# gather cumulative removed/touched sets to update the search index
self.removed_claim_hashes.update(set(self.abandoned_claims.keys()))
self.touched_claim_hashes.difference_update(self.removed_claim_hashes)
@ -1359,6 +1387,8 @@ class BlockProcessor:
self.touched_claim_hashes.clear()
self.pending_reposted.clear()
self.pending_channel_counts.clear()
self.updated_claims.clear()
self.taken_over_names.clear()
async def backup_block(self):
# self.db.assert_flushed(self.flush_data())

View file

@ -95,6 +95,7 @@ class SearchIndex:
if index_version != self.VERSION:
self.logger.error("es search index has an incompatible version: %s vs %s", index_version, self.VERSION)
raise IndexVersionMismatch(index_version, self.VERSION)
await self.sync_client.indices.refresh(self.index)
return acked
def stop(self):

View file

@ -1299,10 +1299,10 @@ class HashXHistoryPrefixRow(PrefixRow):
return a.tobytes()
@classmethod
def unpack_value(cls, data: bytes) -> HashXHistoryValue:
def unpack_value(cls, data: bytes) -> array.array:
a = array.array('I')
a.frombytes(data)
return HashXHistoryValue(a.tolist())
return a
@classmethod
def pack_item(cls, hashX: bytes, height: int, history: typing.List[int]):

View file

@ -4,6 +4,7 @@ import hashlib
from bisect import bisect_right
from binascii import hexlify, unhexlify
from collections import defaultdict
from typing import NamedTuple, List
from lbry.testcase import CommandTestCase
from lbry.wallet.transaction import Transaction, Output
from lbry.schema.compat import OldClaimMessage
@ -11,6 +12,12 @@ from lbry.crypto.hash import sha256
from lbry.crypto.base58 import Base58
class ClaimStateValue(NamedTuple):
claim_id: str
activation_height: int
active_in_lbrycrd: bool
class BaseResolveTestCase(CommandTestCase):
async def assertResolvesToClaimId(self, name, claim_id):
@ -86,8 +93,6 @@ class BaseResolveTestCase(CommandTestCase):
)
self.assertEqual(len(claim_from_es[0]), 1)
self.assertEqual(claim_from_es[0][0]['claim_hash'][::-1].hex(), claim.claim_hash.hex())
self.assertEqual(claim_from_es[0][0]['claim_id'], claim.claim_hash.hex())
self.assertEqual(claim_from_es[0][0]['activation_height'], claim.activation_height)
self.assertEqual(claim_from_es[0][0]['last_take_over_height'], claim.last_takeover_height)
@ -607,63 +612,313 @@ class ResolveClaimTakeovers(BaseResolveTestCase):
await self.assertNoClaimForName(name)
await self._test_activation_delay()
async def test_claim_and_update_delays(self):
async def create_stream_claim(self, amount: str, name='derp') -> str:
return (await self.stream_create(name, amount, allow_duplicate_name=True))['outputs'][0]['claim_id']
async def assertNameState(self, height: int, name: str, winning_claim_id: str, last_takeover_height: int,
non_winning_claims: List[ClaimStateValue]):
self.assertEqual(height, self.conductor.spv_node.server.bp.db.db_height)
await self.assertMatchClaimIsWinning(name, winning_claim_id)
for non_winning in non_winning_claims:
claim = await self.assertMatchClaim(
non_winning.claim_id, is_active_in_lbrycrd=non_winning.active_in_lbrycrd
)
self.assertEqual(non_winning.activation_height, claim.activation_height)
self.assertEqual(last_takeover_height, claim.last_takeover_height)
async def test_delay_takeover_with_update(self):
name = 'derp'
first_claim_id = (await self.stream_create(name, '0.2', allow_duplicate_name=True))['outputs'][0]['claim_id']
first_claim_id = await self.create_stream_claim('0.2', name)
await self.assertMatchClaimIsWinning(name, first_claim_id)
await self.generate(320)
second_claim_id = (await self.stream_create(name, '0.1', allow_duplicate_name=True))['outputs'][0]['claim_id']
third_claim_id = (await self.stream_create(name, '0.1', allow_duplicate_name=True))['outputs'][0]['claim_id']
second_claim_id = await self.create_stream_claim('0.1', name)
third_claim_id = await self.create_stream_claim('0.1', name)
await self.generate(8)
self.assertEqual(537, self.conductor.spv_node.server.bp.db.db_height)
await self.assertMatchClaimIsWinning(name, first_claim_id)
second_claim = await self.assertMatchClaim(second_claim_id, is_active_in_lbrycrd=False)
self.assertEqual(538, second_claim.activation_height)
self.assertEqual(207, second_claim.last_takeover_height)
third_claim = await self.assertMatchClaim(third_claim_id, is_active_in_lbrycrd=False)
self.assertEqual(539, third_claim.activation_height)
self.assertEqual(207, third_claim.last_takeover_height)
await self.assertNameState(
height=537, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=False),
ClaimStateValue(third_claim_id, activation_height=539, active_in_lbrycrd=False)
]
)
await self.generate(1)
self.assertEqual(538, self.conductor.spv_node.server.bp.db.db_height)
await self.assertMatchClaimIsWinning(name, first_claim_id)
second_claim = await self.assertMatchClaim(second_claim_id)
self.assertEqual(538, second_claim.activation_height)
self.assertEqual(207, second_claim.last_takeover_height)
third_claim = await self.assertMatchClaim(third_claim_id, is_active_in_lbrycrd=False)
self.assertEqual(539, third_claim.activation_height)
self.assertEqual(207, third_claim.last_takeover_height)
await self.assertNameState(
height=538, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=539, active_in_lbrycrd=False)
]
)
await self.generate(1)
self.assertEqual(539, self.conductor.spv_node.server.bp.db.db_height)
await self.assertMatchClaimIsWinning(name, first_claim_id)
second_claim = await self.assertMatchClaim(second_claim_id)
self.assertEqual(538, second_claim.activation_height)
self.assertEqual(207, second_claim.last_takeover_height)
third_claim = await self.assertMatchClaim(third_claim_id)
self.assertEqual(539, third_claim.activation_height)
self.assertEqual(207, third_claim.last_takeover_height)
await self.assertNameState(
height=539, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=539, active_in_lbrycrd=True)
]
)
await self.daemon.jsonrpc_stream_update(third_claim_id, '0.21')
await self.generate(1)
await self.assertNameState(
height=540, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=550, active_in_lbrycrd=False)
]
)
self.assertEqual(540, self.conductor.spv_node.server.bp.db.db_height)
await self.generate(9)
await self.assertNameState(
height=549, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=550, active_in_lbrycrd=False)
]
)
await self.generate(1)
await self.assertNameState(
height=550, name=name, winning_claim_id=third_claim_id, last_takeover_height=550,
non_winning_claims=[
ClaimStateValue(first_claim_id, activation_height=207, active_in_lbrycrd=True),
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True)
]
)
async def test_delay_takeover_with_update_then_update_to_lower_before_takeover(self):
name = 'derp'
first_claim_id = await self.create_stream_claim('0.2', name)
await self.assertMatchClaimIsWinning(name, first_claim_id)
second_claim = await self.assertMatchClaim(second_claim_id)
self.assertEqual(538, second_claim.activation_height)
self.assertEqual(207, second_claim.last_takeover_height)
third_claim = await self.assertMatchClaim(third_claim_id, is_active_in_lbrycrd=False)
self.assertEqual(550, third_claim.activation_height)
self.assertEqual(207, third_claim.last_takeover_height)
await self.generate(320)
second_claim_id = await self.create_stream_claim('0.1', name)
third_claim_id = await self.create_stream_claim('0.1', name)
await self.generate(8)
await self.assertNameState(
height=537, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=False),
ClaimStateValue(third_claim_id, activation_height=539, active_in_lbrycrd=False)
]
)
await self.generate(1)
await self.assertNameState(
height=538, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=539, active_in_lbrycrd=False)
]
)
await self.generate(1)
await self.assertNameState(
height=539, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=539, active_in_lbrycrd=True)
]
)
await self.daemon.jsonrpc_stream_update(third_claim_id, '0.21')
await self.generate(1)
await self.assertNameState(
height=540, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=550, active_in_lbrycrd=False)
]
)
await self.generate(8)
await self.assertNameState(
height=548, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=550, active_in_lbrycrd=False)
]
)
await self.daemon.jsonrpc_stream_update(third_claim_id, '0.09')
await self.generate(1)
await self.assertNameState(
height=549, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=559, active_in_lbrycrd=False)
]
)
await self.generate(10)
self.assertEqual(550, self.conductor.spv_node.server.bp.db.db_height)
await self.assertMatchClaimIsWinning(name, third_claim_id)
await self.assertNameState(
height=559, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=559, active_in_lbrycrd=True)
]
)
async def test_delay_takeover_with_update_then_update_to_lower_on_takeover(self):
name = 'derp'
first_claim_id = await self.create_stream_claim('0.2', name)
await self.assertMatchClaimIsWinning(name, first_claim_id)
await self.generate(320)
second_claim_id = await self.create_stream_claim('0.1', name)
third_claim_id = await self.create_stream_claim('0.1', name)
await self.generate(8)
await self.assertNameState(
height=537, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=False),
ClaimStateValue(third_claim_id, activation_height=539, active_in_lbrycrd=False)
]
)
await self.generate(1)
await self.assertNameState(
height=538, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=539, active_in_lbrycrd=False)
]
)
await self.generate(1)
await self.assertNameState(
height=539, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=539, active_in_lbrycrd=True)
]
)
await self.daemon.jsonrpc_stream_update(third_claim_id, '0.21')
await self.generate(1)
await self.assertNameState(
height=540, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=550, active_in_lbrycrd=False)
]
)
await self.generate(8)
await self.assertNameState(
height=548, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=550, active_in_lbrycrd=False)
]
)
await self.generate(1)
await self.assertNameState(
height=549, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=550, active_in_lbrycrd=False)
]
)
await self.daemon.jsonrpc_stream_update(third_claim_id, '0.09')
await self.generate(1)
await self.assertNameState(
height=550, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=560, active_in_lbrycrd=False)
]
)
await self.generate(10)
await self.assertNameState(
height=560, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=560, active_in_lbrycrd=True)
]
)
async def test_delay_takeover_with_update_then_update_to_lower_after_takeover(self):
name = 'derp'
first_claim_id = await self.create_stream_claim('0.2', name)
await self.assertMatchClaimIsWinning(name, first_claim_id)
await self.generate(320)
second_claim_id = await self.create_stream_claim('0.1', name)
third_claim_id = await self.create_stream_claim('0.1', name)
await self.generate(8)
await self.assertNameState(
height=537, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=False),
ClaimStateValue(third_claim_id, activation_height=539, active_in_lbrycrd=False)
]
)
await self.generate(1)
await self.assertNameState(
height=538, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=539, active_in_lbrycrd=False)
]
)
await self.generate(1)
await self.assertNameState(
height=539, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=539, active_in_lbrycrd=True)
]
)
await self.daemon.jsonrpc_stream_update(third_claim_id, '0.21')
await self.generate(1)
await self.assertNameState(
height=540, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=550, active_in_lbrycrd=False)
]
)
await self.generate(8)
await self.assertNameState(
height=548, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=550, active_in_lbrycrd=False)
]
)
await self.generate(1)
await self.assertNameState(
height=549, name=name, winning_claim_id=first_claim_id, last_takeover_height=207,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=550, active_in_lbrycrd=False)
]
)
await self.generate(1)
await self.assertNameState(
height=550, name=name, winning_claim_id=third_claim_id, last_takeover_height=550,
non_winning_claims=[
ClaimStateValue(first_claim_id, activation_height=207, active_in_lbrycrd=True),
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True)
]
)
await self.daemon.jsonrpc_stream_update(third_claim_id, '0.09')
await self.generate(1)
await self.assertNameState(
height=551, name=name, winning_claim_id=first_claim_id, last_takeover_height=551,
non_winning_claims=[
ClaimStateValue(second_claim_id, activation_height=538, active_in_lbrycrd=True),
ClaimStateValue(third_claim_id, activation_height=551, active_in_lbrycrd=True)
]
)
async def test_resolve_signed_claims_with_fees(self):
channel_name = '@abc'