unit test fixes, balance/utxos filters out claims, abandoning claims
This commit is contained in:
parent
8c35d355e5
commit
d81502e191
6 changed files with 114 additions and 112 deletions
|
@ -29,3 +29,11 @@ class Account(BaseAccount):
|
|||
return super(Account, self).get_balance(
|
||||
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
|
||||
)
|
||||
|
|
|
@ -47,3 +47,8 @@ class Transaction(BaseTransaction):
|
|||
amount, name, hexlify(meta.serialized), ledger.address_to_hash160(holding_address)
|
||||
)
|
||||
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)
|
||||
|
|
|
@ -38,7 +38,7 @@ example_claim_dict = {
|
|||
}
|
||||
|
||||
|
||||
class BasicTransactionTests(IntegrationTestCase):
|
||||
class BasicTransactionTest(IntegrationTestCase):
|
||||
|
||||
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))
|
||||
claim = ClaimDict.load_dict(example_claim_dict)
|
||||
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(tx)
|
||||
await self.broadcast(claim_tx)
|
||||
await asyncio.wait([ # mempool
|
||||
self.on_transaction(tx),
|
||||
self.on_transaction(claim_tx),
|
||||
self.on_transaction(cert_tx),
|
||||
])
|
||||
await self.blockchain.generate(1)
|
||||
await asyncio.wait([ # confirmed
|
||||
self.on_transaction(tx),
|
||||
self.on_transaction(claim_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(self.ledger.headers._hash_header(header), 'lbry://@bar/foo'))
|
||||
response = await d2f(self.ledger.resolve('lbry://@bar/foo'))
|
||||
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):
|
||||
#
|
||||
# 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())
|
||||
response = await d2f(self.ledger.resolve('lbry://@bar/foo'))
|
||||
self.assertIn('lbry://@bar/foo', response)
|
||||
|
|
|
@ -1,62 +1,68 @@
|
|||
from twisted.trial import unittest
|
||||
from twisted.internet import defer
|
||||
|
||||
from lbrynet.wallet import LBC
|
||||
from lbrynet.wallet.manager import LbryWalletManager
|
||||
from torba.wallet import Account
|
||||
from lbrynet.wallet.ledger import MainNetLedger
|
||||
from lbrynet.wallet.account import Account
|
||||
|
||||
|
||||
class TestAccount(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
ledger = LbryWalletManager().get_or_create_ledger(LBC.get_id())
|
||||
self.coin = LBC(ledger)
|
||||
self.ledger = MainNetLedger(db=MainNetLedger.database_class(':memory:'))
|
||||
return self.ledger.db.start()
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_generate_account(self):
|
||||
account = Account.generate(self.coin, u'lbryum')
|
||||
self.assertEqual(account.coin, self.coin)
|
||||
account = Account.generate(self.ledger, u'lbryum')
|
||||
self.assertEqual(account.ledger, self.ledger)
|
||||
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(len(account.receiving_keys.child_keys), 0)
|
||||
self.assertEqual(len(account.receiving_keys.addresses), 0)
|
||||
self.assertEqual(len(account.change_keys.child_keys), 0)
|
||||
self.assertEqual(len(account.change_keys.addresses), 0)
|
||||
self.assertEqual(account.public_key.ledger, self.ledger)
|
||||
self.assertEqual(account.private_key.public_key, account.public_key)
|
||||
|
||||
account.ensure_enough_addresses()
|
||||
self.assertEqual(len(account.receiving_keys.child_keys), 20)
|
||||
self.assertEqual(len(account.receiving_keys.addresses), 20)
|
||||
self.assertEqual(len(account.change_keys.child_keys), 6)
|
||||
self.assertEqual(len(account.change_keys.addresses), 6)
|
||||
addresses = yield account.receiving.get_addresses()
|
||||
self.assertEqual(len(addresses), 0)
|
||||
addresses = yield account.change.get_addresses()
|
||||
self.assertEqual(len(addresses), 0)
|
||||
|
||||
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):
|
||||
account = Account.from_seed(
|
||||
self.coin,
|
||||
self.ledger,
|
||||
u"carbon smart garage balance margin twelve chest sword toast envelope bottom stomach ab"
|
||||
u"sent",
|
||||
u"lbryum"
|
||||
)
|
||||
self.assertEqual(
|
||||
account.private_key.extended_key_string(),
|
||||
b'LprvXPsFZUGgrX1X9HiyxABZSf6hWJK7kHv4zGZRyyiHbBq5Wu94cE1DMvttnpLYReTPNW4eYwX9dWMvTz3PrB'
|
||||
b'wwbRafEeA1ZXL69U2egM4QJdq'
|
||||
b'xprv9s21ZrQH143K42ovpZygnjfHdAqSd9jo7zceDfPRogM7bkkoNVv7DRNLEoB8'
|
||||
b'HoirMgH969NrgL8jNzLEegqFzPRWM37GXd4uE8uuRkx4LAe'
|
||||
)
|
||||
self.assertEqual(
|
||||
account.public_key.extended_key_string(),
|
||||
b'Lpub2hkYkGHXktBhLpwUhKKogyuJ1M7Gt9EkjFTVKyDqZiZpWdhLuCoT1eKDfXfysMFfG4SzfXXcA2SsHzrjHK'
|
||||
b'Ea5aoCNRBAhjT5NPLV6hXtvEi'
|
||||
b'xpub661MyMwAqRbcGWtPvbWh9sc2BCfw2cTeVDYF23o3N1t6UZ5wv3EMmDgp66FxH'
|
||||
b'uDtWdft3B5eL5xQtyzAtkdmhhC95gjRjLzSTdkho95asu9'
|
||||
)
|
||||
self.assertEqual(
|
||||
account.receiving_keys.generate_next_address(),
|
||||
b'bCqJrLHdoiRqEZ1whFZ3WHNb33bP34SuGx'
|
||||
)
|
||||
private_key = account.get_private_key_for_address(b'bCqJrLHdoiRqEZ1whFZ3WHNb33bP34SuGx')
|
||||
address = yield account.receiving.ensure_address_gap()
|
||||
self.assertEqual(address[0], b'bCqJrLHdoiRqEZ1whFZ3WHNb33bP34SuGx')
|
||||
|
||||
private_key = yield self.ledger.get_private_key_for_address(b'bCqJrLHdoiRqEZ1whFZ3WHNb33bP34SuGx')
|
||||
self.assertEqual(
|
||||
private_key.extended_key_string(),
|
||||
b'LprvXTnmVLXGKvRGo2ihBE6LJ771G3VVpAx2zhTJvjnx5P3h6iZ4VJX8PvwTcgzJZ1hqXX61Wpn4pQoP6n2wgp'
|
||||
b'S8xjzCM6H2uGzCXuAMy5H9vtA'
|
||||
b'xprv9vwXVierUTT4hmoe3dtTeBfbNv1ph2mm8RWXARU6HsZjBaAoFaS2FRQu4fptR'
|
||||
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):
|
||||
account_data = {
|
||||
|
@ -65,34 +71,17 @@ class TestAccount(unittest.TestCase):
|
|||
"h absent",
|
||||
'encrypted': False,
|
||||
'private_key':
|
||||
'LprvXPsFZUGgrX1X9HiyxABZSf6hWJK7kHv4zGZRyyiHbBq5Wu94cE1DMvttnpLYReTPNW4eYwX9dWMvTz3PrB'
|
||||
'wwbRafEeA1ZXL69U2egM4QJdq',
|
||||
'xprv9s21ZrQH143K42ovpZygnjfHdAqSd9jo7zceDfPRogM7bkkoNVv7DRNLEoB8'
|
||||
'HoirMgH969NrgL8jNzLEegqFzPRWM37GXd4uE8uuRkx4LAe',
|
||||
'public_key':
|
||||
'Lpub2hkYkGHXktBhLpwUhKKogyuJ1M7Gt9EkjFTVKyDqZiZpWdhLuCoT1eKDfXfysMFfG4SzfXXcA2SsHzrjHK'
|
||||
'Ea5aoCNRBAhjT5NPLV6hXtvEi',
|
||||
'xpub661MyMwAqRbcGWtPvbWh9sc2BCfw2cTeVDYF23o3N1t6UZ5wv3EMmDgp66FxH'
|
||||
'uDtWdft3B5eL5xQtyzAtkdmhhC95gjRjLzSTdkho95asu9',
|
||||
'receiving_gap': 10,
|
||||
'receiving_keys': [
|
||||
'02c68e2d1cf85404c86244ffa279f4c5cd00331e996d30a86d6e46480e3a9220f4',
|
||||
'03c5a997d0549875d23b8e4bbc7b4d316d962587483f3a2e62ddd90a21043c4941'
|
||||
],
|
||||
'receiving_maximum_use_per_address': 2,
|
||||
'change_gap': 10,
|
||||
'change_keys': [
|
||||
'021460e8d728eee325d0d43128572b2e2bacdc027e420451df100cf9f2154ea5ab'
|
||||
]
|
||||
'change_maximum_use_per_address': 2,
|
||||
}
|
||||
|
||||
account = Account.from_dict(self.coin, account_data)
|
||||
|
||||
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'
|
||||
account = Account.from_dict(self.ledger, account_data)
|
||||
account_data['ledger'] = 'lbc_mainnet'
|
||||
self.assertDictEqual(account_data, account.to_dict())
|
||||
|
|
|
@ -1,38 +1,39 @@
|
|||
import shutil
|
||||
import tempfile
|
||||
from twisted.internet import defer
|
||||
from twisted.trial import unittest
|
||||
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.coin import LBC
|
||||
from lbrynet.wallet.manager import LbryWalletManager
|
||||
from torba.baseaccount import Account
|
||||
from lbrynet.wallet.ledger import MainNetLedger
|
||||
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):
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def setUp(self):
|
||||
conf.initialize_settings(False)
|
||||
self.db_dir = tempfile.mkdtemp()
|
||||
self.storage = SQLiteStorage(self.db_dir)
|
||||
yield self.storage.setup()
|
||||
self.manager = LbryWalletManager(self.storage)
|
||||
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.ledger = MainNetLedger(db=MainNetLedger.database_class(':memory:'), headers_class=MockHeaders)
|
||||
self.wallet = Wallet('Main', [Account.from_seed(
|
||||
self.ledger, u'carbon smart garage balance margin twelve chest sword toast envelope botto'
|
||||
u'm stomach absent', u'lbryum'
|
||||
)])
|
||||
self.account = self.wallet.default_account
|
||||
yield self.storage.add_account(self.account)
|
||||
return self.ledger.db.start()
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def tearDown(self):
|
||||
yield self.storage.stop()
|
||||
shutil.rmtree(self.db_dir)
|
||||
yield self.ledger.db.stop()
|
||||
|
||||
|
||||
class BasicAccountingTests(LedgerTestCase):
|
||||
|
@ -44,11 +45,25 @@ class BasicAccountingTests(LedgerTestCase):
|
|||
|
||||
@defer.inlineCallbacks
|
||||
def test_balance(self):
|
||||
tx = Transaction().add_outputs([Output.pay_pubkey_hash(100, b'abc1')])
|
||||
yield self.storage.add_tx_output(self.account, tx.outputs[0])
|
||||
balance = yield self.storage.get_balance_for_account(self.account)
|
||||
address = yield self.account.receiving.get_or_create_usable_address()
|
||||
hash160 = self.ledger.address_to_hash160(address)
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
def test_get_utxo(self):
|
||||
tx1 = Transaction().add_outputs([Output.pay_pubkey_hash(100, b'abc1')])
|
||||
|
|
5
tox.ini
5
tox.ini
|
@ -14,9 +14,10 @@ extras = test
|
|||
changedir = {toxinidir}/tests
|
||||
setenv =
|
||||
HOME=/tmp
|
||||
PYTHONHASHSEED=0
|
||||
integration: LEDGER=lbrynet.wallet
|
||||
commands =
|
||||
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: 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
|
||||
|
|
Loading…
Reference in a new issue