diff --git a/lbrynet/daemon/Daemon.py b/lbrynet/daemon/Daemon.py index 766fd10cc..2820977ac 100644 --- a/lbrynet/daemon/Daemon.py +++ b/lbrynet/daemon/Daemon.py @@ -1849,14 +1849,15 @@ class Daemon(AuthJSONRPCServer): 'channel_name': channel_name }) - if channel_id: - certificate = self.wallet.default_account.get_certificate(by_claim_id=channel_id) - elif channel_name: - certificate = self.wallet.default_account.get_certificate(by_name=channel_name) - if not certificate: + certificate = None + if channel_name: + certificates = yield self.wallet.get_certificates(channel_name) + for cert in certificates: + if cert.claim_id == channel_id: + certificate = cert + break + if certificate is None: raise Exception("Cannot publish using channel %s" % channel_name) - else: - certificate = None result = yield self._publish_stream(name, bid, claim_dict, file_path, certificate, claim_address, change_address) diff --git a/lbrynet/wallet/account.py b/lbrynet/wallet/account.py index d4b8c01d2..d16c5d1b4 100644 --- a/lbrynet/wallet/account.py +++ b/lbrynet/wallet/account.py @@ -1,4 +1,6 @@ -from binascii import hexlify +import logging +from binascii import hexlify, unhexlify + from twisted.internet import defer from torba.baseaccount import BaseAccount @@ -8,6 +10,8 @@ from lbryschema.signer import SECP256k1, get_signer from .transaction import Transaction +log = logging.getLogger(__name__) + def generate_certificate(): secp256k1_private_key = get_signer(SECP256k1).generate().private_key.to_pem() @@ -27,8 +31,8 @@ class Account(BaseAccount): super(Account, self).__init__(*args, **kwargs) self.certificates = {} - def add_certificate(self, tx, nout, private_key): - lookup_key = '{}:{}'.format(tx.hex_id.decode(), nout) + def add_certificate_private_key(self, tx_or_hash, nout, private_key): + lookup_key = get_certificate_lookup(tx_or_hash, nout) assert lookup_key not in self.certificates, 'Trying to add a duplicate certificate.' self.certificates[lookup_key] = private_key @@ -37,15 +41,34 @@ class Account(BaseAccount): @defer.inlineCallbacks def maybe_migrate_certificates(self): + failed, succeded, total = 0, 0, 0 for maybe_claim_id in self.certificates.keys(): + total += 1 if ':' not in maybe_claim_id: claims = yield self.ledger.network.get_claims_by_ids(maybe_claim_id) - # assert claim['address'] is one of our addresses, otherwise move cert to new Account - print(claims[maybe_claim_id]) - tx_nout = '{txid}:{nout}'.format(**claims[maybe_claim_id]) - self.certificates[tx_nout] = self.certificates[maybe_claim_id] - del self.certificates[maybe_claim_id] - break + claim = claims[maybe_claim_id] + txhash = unhexlify(claim['txid'])[::-1] + tx = yield self.ledger.get_transaction(txhash) + if tx is not None: + txo = tx.outputs[claim['nout']] + assert txo.script.is_claim_involved,\ + "Certificate with claim_id {} doesn't point to a valid transaction."\ + .format(maybe_claim_id) + tx_nout = '{txid}:{nout}'.format(**claim) + self.certificates[tx_nout] = self.certificates[maybe_claim_id] + del self.certificates[maybe_claim_id] + log.info( + "Migrated certificate with claim_id '{}' ('{}') to a new look up key {}." + .format(maybe_claim_id, txo.script.values['claim_name'], tx_nout) + ) + succeded += 1 + else: + log.warning( + "Failed to migrate claim '{}', it's not associated with any of your addresses." + .format(maybe_claim_id) + ) + failed += 1 + log.info('Checked: {}, Converted: {}, Failed: {}'.format(total, succeded, failed)) def get_balance(self, include_claims=False): if include_claims: diff --git a/lbrynet/wallet/manager.py b/lbrynet/wallet/manager.py index f21dc4e93..90385af9a 100644 --- a/lbrynet/wallet/manager.py +++ b/lbrynet/wallet/manager.py @@ -11,6 +11,7 @@ from lbryschema.error import URIParseError from .ledger import MainNetLedger # pylint: disable=unused-import from .account import generate_certificate from .transaction import Transaction +from .database import WalletDatabase # pylint: disable=unused-import class BackwardsCompatibleNetwork(object): @@ -26,6 +27,14 @@ class BackwardsCompatibleNetwork(object): class LbryWalletManager(BaseWalletManager): + @property + def ledger(self): # type: () -> MainNetLedger + return self.default_account.ledger + + @property + def db(self): # type: () -> WalletDatabase + return self.ledger.db + @property def wallet(self): return self @@ -145,7 +154,7 @@ class LbryWalletManager(BaseWalletManager): claim_address = yield account.receiving.get_or_create_usable_address() if certificate: claim = claim.sign( - certificate['private_key'], claim_address, certificate['claim_id'] + certificate.private_key, claim_address, certificate.claim_id ) tx = yield Transaction.claim(name.encode(), claim, amount, claim_address, [account], account) yield account.ledger.broadcast(tx) @@ -173,6 +182,9 @@ class LbryWalletManager(BaseWalletManager): # TODO: release reserved tx outputs in case anything fails by this point defer.returnValue(tx) + def get_certificates(self, name): + return self.db.get_certificates(name, [self.default_account], exclude_without_key=True) + def update_peer_address(self, peer, address): pass # TODO: Data payments is disabled @@ -189,6 +201,7 @@ class LbryWalletManager(BaseWalletManager): def cancel_point_reservation(self, reserved_points): pass # fixme: disabled for now. + class ReservedPoints(object): def __init__(self, identifier, amount): self.identifier = identifier