unit test fixes, balance/utxos filters out claims, abandoning claims

This commit is contained in:
Lex Berezhny 2018-07-09 17:04:59 -04:00 committed by Jack Robison
parent 8c35d355e5
commit d81502e191
No known key found for this signature in database
GPG key ID: DF25C68FE0239BB2
6 changed files with 114 additions and 112 deletions

View file

@ -29,3 +29,11 @@ class Account(BaseAccount):
return super(Account, self).get_balance( return super(Account, self).get_balance(
is_claim=0, is_update=0, is_support=0 is_claim=0, is_update=0, is_support=0
) )
def get_unspent_outputs(self, include_claims=False):
if include_claims:
return super(Account, self).get_unspent_outputs()
else:
return super(Account, self).get_unspent_outputs(
is_claim=0, is_update=0, is_support=0
)

View file

@ -47,3 +47,8 @@ class Transaction(BaseTransaction):
amount, name, hexlify(meta.serialized), ledger.address_to_hash160(holding_address) amount, name, hexlify(meta.serialized), ledger.address_to_hash160(holding_address)
) )
return cls.pay([claim_output], funding_accounts, change_account) return cls.pay([claim_output], funding_accounts, change_account)
@classmethod
def abandon(cls, utxo, funding_accounts, change_account):
# type: (Output, List[BaseAccount], BaseAccount) -> defer.Deferred
return cls.liquidate([utxo], funding_accounts, change_account)

View file

@ -38,7 +38,7 @@ example_claim_dict = {
} }
class BasicTransactionTests(IntegrationTestCase): class BasicTransactionTest(IntegrationTestCase):
VERBOSE = True VERBOSE = True
@ -61,49 +61,33 @@ class BasicTransactionTests(IntegrationTestCase):
cert_tx = await d2f(Transaction.claim(b'@bar', cert, 1*COIN, address1, [self.account], self.account)) cert_tx = await d2f(Transaction.claim(b'@bar', cert, 1*COIN, address1, [self.account], self.account))
claim = ClaimDict.load_dict(example_claim_dict) claim = ClaimDict.load_dict(example_claim_dict)
claim = claim.sign(key, address1, hexlify(cert_tx.get_claim_id(0))) claim = claim.sign(key, address1, hexlify(cert_tx.get_claim_id(0)))
tx = await d2f(Transaction.claim(b'foo', claim, 1*COIN, address1, [self.account], self.account)) claim_tx = await d2f(Transaction.claim(b'foo', claim, 1*COIN, address1, [self.account], self.account))
await self.broadcast(cert_tx) await self.broadcast(cert_tx)
await self.broadcast(tx) await self.broadcast(claim_tx)
await asyncio.wait([ # mempool await asyncio.wait([ # mempool
self.on_transaction(tx), self.on_transaction(claim_tx),
self.on_transaction(cert_tx), self.on_transaction(cert_tx),
]) ])
await self.blockchain.generate(1) await self.blockchain.generate(1)
await asyncio.wait([ # confirmed await asyncio.wait([ # confirmed
self.on_transaction(tx), self.on_transaction(claim_tx),
self.on_transaction(cert_tx), self.on_transaction(cert_tx),
]) ])
self.assertEqual(round(await self.get_balance(self.account)/COIN, 1), 10.0) self.assertEqual(round(await d2f(self.account.get_balance())/COIN, 1), 8.0)
self.assertEqual(round(await d2f(self.account.get_balance(True))/COIN, 1), 10.0)
header = self.ledger.headers[len(self.ledger.headers)-1] response = await d2f(self.ledger.resolve('lbry://@bar/foo'))
response = await d2f(self.ledger.resolve(self.ledger.headers._hash_header(header), 'lbry://@bar/foo'))
self.assertIn('lbry://@bar/foo', response) self.assertIn('lbry://@bar/foo', response)
claim_txo = claim_tx.outputs[0]
claim_txo.txoid = await d2f(self.ledger.db.get_txoid_for_txo(claim_txo))
abandon_tx = await d2f(Transaction.abandon(claim_txo, [self.account], self.account))
await self.broadcast(abandon_tx)
await self.on_transaction(abandon_tx)
await self.blockchain.generate(1)
await self.on_transaction(abandon_tx)
#class AbandonClaimLookup(IntegrationTestCase): response = await d2f(self.ledger.resolve('lbry://@bar/foo'))
# self.assertIn('lbry://@bar/foo', response)
# async def skip_test_abandon_claim(self):
# address = yield self.lbry.wallet.get_least_used_address()
# yield self.lbrycrd.sendtoaddress(address, 0.0003 - 0.0000355)
# yield self.lbrycrd.generate(1)
# yield self.lbry.wallet.update_balance()
# yield threads.deferToThread(time.sleep, 5)
# print(self.lbry.wallet.get_balance())
# claim = yield self.lbry.wallet.claim_new_channel('@test', 0.000096)
# yield self.lbrycrd.generate(1)
# print('='*10 + 'CLAIM' + '='*10)
# print(claim)
# yield self.lbrycrd.decoderawtransaction(claim['tx'])
# abandon = yield self.lbry.wallet.abandon_claim(claim['claim_id'], claim['txid'], claim['nout'])
# print('='*10 + 'ABANDON' + '='*10)
# print(abandon)
# yield self.lbrycrd.decoderawtransaction(abandon['tx'])
# yield self.lbrycrd.generate(1)
# yield self.lbrycrd.getrawtransaction(abandon['txid'])
#
# yield self.lbry.wallet.update_balance()
# yield threads.deferToThread(time.sleep, 5)
# print('='*10 + 'FINAL BALANCE' + '='*10)
# print(self.lbry.wallet.get_balance())

View file

@ -1,62 +1,68 @@
from twisted.trial import unittest from twisted.trial import unittest
from twisted.internet import defer
from lbrynet.wallet import LBC from lbrynet.wallet.ledger import MainNetLedger
from lbrynet.wallet.manager import LbryWalletManager from lbrynet.wallet.account import Account
from torba.wallet import Account
class TestAccount(unittest.TestCase): class TestAccount(unittest.TestCase):
def setUp(self): def setUp(self):
ledger = LbryWalletManager().get_or_create_ledger(LBC.get_id()) self.ledger = MainNetLedger(db=MainNetLedger.database_class(':memory:'))
self.coin = LBC(ledger) return self.ledger.db.start()
@defer.inlineCallbacks
def test_generate_account(self): def test_generate_account(self):
account = Account.generate(self.coin, u'lbryum') account = Account.generate(self.ledger, u'lbryum')
self.assertEqual(account.coin, self.coin) self.assertEqual(account.ledger, self.ledger)
self.assertIsNotNone(account.seed) self.assertIsNotNone(account.seed)
self.assertEqual(account.public_key.coin, self.coin) self.assertEqual(account.public_key.ledger, self.ledger)
self.assertEqual(account.private_key.public_key, account.public_key) self.assertEqual(account.private_key.public_key, account.public_key)
self.assertEqual(len(account.receiving_keys.child_keys), 0) self.assertEqual(account.public_key.ledger, self.ledger)
self.assertEqual(len(account.receiving_keys.addresses), 0) self.assertEqual(account.private_key.public_key, account.public_key)
self.assertEqual(len(account.change_keys.child_keys), 0)
self.assertEqual(len(account.change_keys.addresses), 0)
account.ensure_enough_addresses() addresses = yield account.receiving.get_addresses()
self.assertEqual(len(account.receiving_keys.child_keys), 20) self.assertEqual(len(addresses), 0)
self.assertEqual(len(account.receiving_keys.addresses), 20) addresses = yield account.change.get_addresses()
self.assertEqual(len(account.change_keys.child_keys), 6) self.assertEqual(len(addresses), 0)
self.assertEqual(len(account.change_keys.addresses), 6)
yield account.ensure_address_gap()
addresses = yield account.receiving.get_addresses()
self.assertEqual(len(addresses), 20)
addresses = yield account.change.get_addresses()
self.assertEqual(len(addresses), 6)
@defer.inlineCallbacks
def test_generate_account_from_seed(self): def test_generate_account_from_seed(self):
account = Account.from_seed( account = Account.from_seed(
self.coin, self.ledger,
u"carbon smart garage balance margin twelve chest sword toast envelope bottom stomach ab" u"carbon smart garage balance margin twelve chest sword toast envelope bottom stomach ab"
u"sent", u"sent",
u"lbryum" u"lbryum"
) )
self.assertEqual( self.assertEqual(
account.private_key.extended_key_string(), account.private_key.extended_key_string(),
b'LprvXPsFZUGgrX1X9HiyxABZSf6hWJK7kHv4zGZRyyiHbBq5Wu94cE1DMvttnpLYReTPNW4eYwX9dWMvTz3PrB' b'xprv9s21ZrQH143K42ovpZygnjfHdAqSd9jo7zceDfPRogM7bkkoNVv7DRNLEoB8'
b'wwbRafEeA1ZXL69U2egM4QJdq' b'HoirMgH969NrgL8jNzLEegqFzPRWM37GXd4uE8uuRkx4LAe'
) )
self.assertEqual( self.assertEqual(
account.public_key.extended_key_string(), account.public_key.extended_key_string(),
b'Lpub2hkYkGHXktBhLpwUhKKogyuJ1M7Gt9EkjFTVKyDqZiZpWdhLuCoT1eKDfXfysMFfG4SzfXXcA2SsHzrjHK' b'xpub661MyMwAqRbcGWtPvbWh9sc2BCfw2cTeVDYF23o3N1t6UZ5wv3EMmDgp66FxH'
b'Ea5aoCNRBAhjT5NPLV6hXtvEi' b'uDtWdft3B5eL5xQtyzAtkdmhhC95gjRjLzSTdkho95asu9'
) )
self.assertEqual( address = yield account.receiving.ensure_address_gap()
account.receiving_keys.generate_next_address(), self.assertEqual(address[0], b'bCqJrLHdoiRqEZ1whFZ3WHNb33bP34SuGx')
b'bCqJrLHdoiRqEZ1whFZ3WHNb33bP34SuGx'
) private_key = yield self.ledger.get_private_key_for_address(b'bCqJrLHdoiRqEZ1whFZ3WHNb33bP34SuGx')
private_key = account.get_private_key_for_address(b'bCqJrLHdoiRqEZ1whFZ3WHNb33bP34SuGx')
self.assertEqual( self.assertEqual(
private_key.extended_key_string(), private_key.extended_key_string(),
b'LprvXTnmVLXGKvRGo2ihBE6LJ771G3VVpAx2zhTJvjnx5P3h6iZ4VJX8PvwTcgzJZ1hqXX61Wpn4pQoP6n2wgp' b'xprv9vwXVierUTT4hmoe3dtTeBfbNv1ph2mm8RWXARU6HsZjBaAoFaS2FRQu4fptR'
b'S8xjzCM6H2uGzCXuAMy5H9vtA' b'AyJWhJW42dmsEaC1nKnVKKTMhq3TVEHsNj1ca3ciZMKktT'
) )
self.assertIsNone(account.get_private_key_for_address(b'BcQjRlhDOIrQez1WHfz3whnB33Bp34sUgX')) private_key = yield self.ledger.get_private_key_for_address(b'BcQjRlhDOIrQez1WHfz3whnB33Bp34sUgX')
self.assertIsNone(private_key)
def test_load_and_save_account(self): def test_load_and_save_account(self):
account_data = { account_data = {
@ -65,34 +71,17 @@ class TestAccount(unittest.TestCase):
"h absent", "h absent",
'encrypted': False, 'encrypted': False,
'private_key': 'private_key':
'LprvXPsFZUGgrX1X9HiyxABZSf6hWJK7kHv4zGZRyyiHbBq5Wu94cE1DMvttnpLYReTPNW4eYwX9dWMvTz3PrB' 'xprv9s21ZrQH143K42ovpZygnjfHdAqSd9jo7zceDfPRogM7bkkoNVv7DRNLEoB8'
'wwbRafEeA1ZXL69U2egM4QJdq', 'HoirMgH969NrgL8jNzLEegqFzPRWM37GXd4uE8uuRkx4LAe',
'public_key': 'public_key':
'Lpub2hkYkGHXktBhLpwUhKKogyuJ1M7Gt9EkjFTVKyDqZiZpWdhLuCoT1eKDfXfysMFfG4SzfXXcA2SsHzrjHK' 'xpub661MyMwAqRbcGWtPvbWh9sc2BCfw2cTeVDYF23o3N1t6UZ5wv3EMmDgp66FxH'
'Ea5aoCNRBAhjT5NPLV6hXtvEi', 'uDtWdft3B5eL5xQtyzAtkdmhhC95gjRjLzSTdkho95asu9',
'receiving_gap': 10, 'receiving_gap': 10,
'receiving_keys': [ 'receiving_maximum_use_per_address': 2,
'02c68e2d1cf85404c86244ffa279f4c5cd00331e996d30a86d6e46480e3a9220f4',
'03c5a997d0549875d23b8e4bbc7b4d316d962587483f3a2e62ddd90a21043c4941'
],
'change_gap': 10, 'change_gap': 10,
'change_keys': [ 'change_maximum_use_per_address': 2,
'021460e8d728eee325d0d43128572b2e2bacdc027e420451df100cf9f2154ea5ab'
]
} }
account = Account.from_dict(self.coin, account_data) account = Account.from_dict(self.ledger, account_data)
account_data['ledger'] = 'lbc_mainnet'
self.assertEqual(len(account.receiving_keys.addresses), 2)
self.assertEqual(
account.receiving_keys.addresses[0],
b'bCqJrLHdoiRqEZ1whFZ3WHNb33bP34SuGx'
)
self.assertEqual(len(account.change_keys.addresses), 1)
self.assertEqual(
account.change_keys.addresses[0],
b'bFpHENtqugKKHDshKFq2Mnb59Y2bx4vKgL'
)
account_data['coin'] = 'lbc_mainnet'
self.assertDictEqual(account_data, account.to_dict()) self.assertDictEqual(account_data, account.to_dict())

View file

@ -1,38 +1,39 @@
import shutil
import tempfile
from twisted.internet import defer from twisted.internet import defer
from twisted.trial import unittest from twisted.trial import unittest
from lbrynet import conf from lbrynet import conf
from lbrynet.database.storage import SQLiteStorage from lbrynet.wallet.account import Account
from lbrynet.wallet.transaction import Transaction, Output, Input from lbrynet.wallet.transaction import Transaction, Output, Input
from lbrynet.wallet.coin import LBC from lbrynet.wallet.ledger import MainNetLedger
from lbrynet.wallet.manager import LbryWalletManager
from torba.baseaccount import Account
from torba.wallet import Wallet from torba.wallet import Wallet
class MockHeaders:
def __init__(self, ledger):
self.ledger = ledger
self.height = 1
def __len__(self):
return self.height
def __getitem__(self, height):
return {'merkle_root': 'abcd04'}
class LedgerTestCase(unittest.TestCase): class LedgerTestCase(unittest.TestCase):
@defer.inlineCallbacks
def setUp(self): def setUp(self):
conf.initialize_settings(False) conf.initialize_settings(False)
self.db_dir = tempfile.mkdtemp() self.ledger = MainNetLedger(db=MainNetLedger.database_class(':memory:'), headers_class=MockHeaders)
self.storage = SQLiteStorage(self.db_dir) self.wallet = Wallet('Main', [Account.from_seed(
yield self.storage.setup() self.ledger, u'carbon smart garage balance margin twelve chest sword toast envelope botto'
self.manager = LbryWalletManager(self.storage) u'm stomach absent', u'lbryum'
self.ledger = self.manager.get_or_create_ledger(LBC.get_id())
self.coin = LBC(self.ledger)
self.wallet = Wallet('Main', [self.coin], [Account.from_seed(
self.coin, u'carbon smart garage balance margin twelve chest sword toast envelope botto'
u'm stomach absent', u'lbryum'
)]) )])
self.account = self.wallet.default_account self.account = self.wallet.default_account
yield self.storage.add_account(self.account) return self.ledger.db.start()
@defer.inlineCallbacks @defer.inlineCallbacks
def tearDown(self): def tearDown(self):
yield self.storage.stop() yield self.ledger.db.stop()
shutil.rmtree(self.db_dir)
class BasicAccountingTests(LedgerTestCase): class BasicAccountingTests(LedgerTestCase):
@ -44,11 +45,25 @@ class BasicAccountingTests(LedgerTestCase):
@defer.inlineCallbacks @defer.inlineCallbacks
def test_balance(self): def test_balance(self):
tx = Transaction().add_outputs([Output.pay_pubkey_hash(100, b'abc1')]) address = yield self.account.receiving.get_or_create_usable_address()
yield self.storage.add_tx_output(self.account, tx.outputs[0]) hash160 = self.ledger.address_to_hash160(address)
balance = yield self.storage.get_balance_for_account(self.account)
tx = Transaction().add_outputs([Output.pay_pubkey_hash(100, hash160)])
yield self.ledger.db.save_transaction_io(
'insert', tx, 1, True, address, hash160, '{}:{}:'.format(tx.hex_id, 1)
)
balance = yield self.account.get_balance()
self.assertEqual(balance, 100) self.assertEqual(balance, 100)
tx = Transaction().add_outputs([Output.pay_claim_name_pubkey_hash(100, b'foo', b'', hash160)])
yield self.ledger.db.save_transaction_io(
'insert', tx, 1, True, address, hash160, '{}:{}:'.format(tx.hex_id, 1)
)
balance = yield self.account.get_balance()
self.assertEqual(balance, 100) # claim names don't count towards balance
balance = yield self.account.get_balance(include_claims=True)
self.assertEqual(balance, 200)
@defer.inlineCallbacks @defer.inlineCallbacks
def test_get_utxo(self): def test_get_utxo(self):
tx1 = Transaction().add_outputs([Output.pay_pubkey_hash(100, b'abc1')]) tx1 = Transaction().add_outputs([Output.pay_pubkey_hash(100, b'abc1')])

View file

@ -14,9 +14,10 @@ extras = test
changedir = {toxinidir}/tests changedir = {toxinidir}/tests
setenv = setenv =
HOME=/tmp HOME=/tmp
PYTHONHASHSEED=0
integration: LEDGER=lbrynet.wallet integration: LEDGER=lbrynet.wallet
commands = commands =
unit: pylint lbrynet unit: pylint lbrynet
unit: coverage run -p --source={envsitepackagesdir}/lbrynet -m twisted.trial functional unit unit: coverage run -p --source={envsitepackagesdir}/lbrynet -m twisted.trial unit functional
integration: orchstr8 download integration: orchstr8 download
integration: coverage run -p --source={envsitepackagesdir}/lbrynet -m twisted.trial --reactor=asyncio integration.wallet.test_transactions integration: coverage run -p --source={envsitepackagesdir}/lbrynet -m twisted.trial --reactor=asyncio integration.wallet.test_transactions.BasicTransactionTest