commit
0910711aca
7 changed files with 305 additions and 104 deletions
|
@ -87,6 +87,10 @@ class LBRYFeeValidator(dict):
|
||||||
|
|
||||||
|
|
||||||
class Metadata(dict):
|
class Metadata(dict):
|
||||||
|
@classmethod
|
||||||
|
def load_from_hex(cls, metadata):
|
||||||
|
return cls(json.loads(metadata.decode('hex')))
|
||||||
|
|
||||||
def __init__(self, metadata):
|
def __init__(self, metadata):
|
||||||
dict.__init__(self)
|
dict.__init__(self)
|
||||||
self.meta_version = None
|
self.meta_version = None
|
||||||
|
@ -123,3 +127,9 @@ class Metadata(dict):
|
||||||
assert self.meta_version == self['ver'], "version mismatch"
|
assert self.meta_version == self['ver'], "version mismatch"
|
||||||
break
|
break
|
||||||
assert metadata == {}, "Unknown metadata keys: %s" % json.dumps(metadata.keys())
|
assert metadata == {}, "Unknown metadata keys: %s" % json.dumps(metadata.keys())
|
||||||
|
|
||||||
|
def serialize(self):
|
||||||
|
return json.dumps(self).encode("hex")
|
||||||
|
|
||||||
|
def as_json(self):
|
||||||
|
return json.dumps(self)
|
||||||
|
|
|
@ -86,6 +86,7 @@ class LBRYWallet(object):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
d = self._open_db()
|
d = self._open_db()
|
||||||
|
d.addCallback(lambda _: self._clean_bad_records())
|
||||||
d.addCallback(lambda _: self._start())
|
d.addCallback(lambda _: self._start())
|
||||||
d.addCallback(lambda _: start_manage())
|
d.addCallback(lambda _: start_manage())
|
||||||
return d
|
return d
|
||||||
|
@ -320,6 +321,10 @@ class LBRYWallet(object):
|
||||||
for k in ['value', 'txid', 'n', 'height', 'amount']:
|
for k in ['value', 'txid', 'n', 'height', 'amount']:
|
||||||
assert k in r, "getvalueforname response missing field %s" % k
|
assert k in r, "getvalueforname response missing field %s" % k
|
||||||
|
|
||||||
|
def _log_success(claim_id):
|
||||||
|
log.info("lbry://%s complies with %s, claimid: %s", name, metadata.meta_version, claim_id)
|
||||||
|
return defer.succeed(None)
|
||||||
|
|
||||||
if 'error' in result:
|
if 'error' in result:
|
||||||
log.warning("Got an error looking up a name: %s", result['error'])
|
log.warning("Got an error looking up a name: %s", result['error'])
|
||||||
return Failure(UnknownNameError(name))
|
return Failure(UnknownNameError(name))
|
||||||
|
@ -331,55 +336,116 @@ class LBRYWallet(object):
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
return Failure(InvalidStreamInfoError(name))
|
return Failure(InvalidStreamInfoError(name))
|
||||||
|
|
||||||
d = self._save_name_metadata(name, str(result['txid']), metadata['sources']['lbry_sd_hash'])
|
txid = result['txid']
|
||||||
d.addCallback(lambda _: log.info("lbry://%s complies with %s" % (name, metadata.meta_version)))
|
sd_hash = metadata['sources']['lbry_sd_hash']
|
||||||
|
d = self._save_name_metadata(name, txid, sd_hash)
|
||||||
|
d.addCallback(lambda _: self.get_claimid(name, txid))
|
||||||
|
d.addCallback(lambda cid: _log_success(cid))
|
||||||
d.addCallback(lambda _: metadata)
|
d.addCallback(lambda _: metadata)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def _get_claim_info(self, result, name):
|
def get_claim(self, name, claim_id):
|
||||||
def _check_result_fields(r):
|
d = self.get_claims_for_name(name)
|
||||||
for k in ['value', 'txid', 'n', 'height', 'amount']:
|
d.addCallback(lambda claims: next(claim for claim in claims['claims'] if claim['claimId'] == claim_id))
|
||||||
assert k in r, "getvalueforname response missing field %s" % k
|
|
||||||
|
|
||||||
def _build_response(m, result):
|
|
||||||
result['value'] = m
|
|
||||||
return result
|
|
||||||
|
|
||||||
if 'error' in result:
|
|
||||||
log.warning("Got an error looking up a name: %s", result['error'])
|
|
||||||
return Failure(UnknownNameError(name))
|
|
||||||
|
|
||||||
_check_result_fields(result)
|
|
||||||
|
|
||||||
try:
|
|
||||||
metadata = Metadata(json.loads(result['value']))
|
|
||||||
except (ValueError, TypeError):
|
|
||||||
return Failure(InvalidStreamInfoError(name))
|
|
||||||
|
|
||||||
d = self._save_name_metadata(name, str(result['txid']), metadata['sources']['lbry_sd_hash'])
|
|
||||||
d.addCallback(lambda _: log.info("lbry://%s complies with %s" % (name, metadata.meta_version)))
|
|
||||||
d.addCallback(lambda _: _build_response(metadata, result))
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def get_claim_info(self, name):
|
def get_claimid(self, name, txid):
|
||||||
d = self._get_value_for_name(name)
|
def _get_id_for_return(claim_id):
|
||||||
d.addCallback(lambda r: self._get_claim_info(r, name))
|
if claim_id:
|
||||||
|
return defer.succeed(claim_id)
|
||||||
|
else:
|
||||||
|
d = self.get_claims_from_tx(txid)
|
||||||
|
d.addCallback(lambda claims: next(c['claimId'] for c in claims if c['name'] == name))
|
||||||
|
d.addCallback(lambda cid: self._update_claimid(cid, name, txid))
|
||||||
|
return d
|
||||||
|
|
||||||
|
d = self._get_claimid_for_tx(name, txid)
|
||||||
|
d.addCallback(_get_id_for_return)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
def get_claim_info(self, name, txid=None):
|
||||||
|
if not txid:
|
||||||
|
d = self._get_value_for_name(name)
|
||||||
|
d.addCallback(lambda r: self._get_claim_info(name, r['txid']))
|
||||||
|
else:
|
||||||
|
d = self._get_claim_info(name, txid)
|
||||||
|
d.addErrback(lambda _: False)
|
||||||
|
return d
|
||||||
|
|
||||||
|
def _get_claim_info(self, name, txid):
|
||||||
|
def _build_response(claim):
|
||||||
|
result = {}
|
||||||
|
try:
|
||||||
|
metadata = Metadata(json.loads(claim['value']))
|
||||||
|
meta_ver = metadata.meta_version
|
||||||
|
sd_hash = metadata['sources']['lbry_sd_hash']
|
||||||
|
d = self._save_name_metadata(name, txid, sd_hash)
|
||||||
|
except AssertionError:
|
||||||
|
metadata = claim['value']
|
||||||
|
meta_ver = "Non-compliant"
|
||||||
|
d = defer.succeed(None)
|
||||||
|
|
||||||
|
claim_id = claim['claimId']
|
||||||
|
result['claim_id'] = claim_id
|
||||||
|
result['amount'] = claim['nEffectiveAmount']
|
||||||
|
result['height'] = claim['nHeight']
|
||||||
|
result['name'] = name
|
||||||
|
result['txid'] = txid
|
||||||
|
result['value'] = metadata
|
||||||
|
result['supports'] = [{'txid': support['txid'], 'n': support['n']} for support in claim['supports']]
|
||||||
|
result['meta_version'] = meta_ver
|
||||||
|
|
||||||
|
log.info("get claim info lbry://%s metadata: %s, claimid: %s", name, meta_ver, claim_id)
|
||||||
|
|
||||||
|
d.addCallback(lambda _: self.get_name_claims())
|
||||||
|
d.addCallback(lambda r: [c['txid'] for c in r])
|
||||||
|
d.addCallback(lambda my_claims: _add_is_mine(result, my_claims))
|
||||||
|
return d
|
||||||
|
|
||||||
|
def _add_is_mine(response, my_txs):
|
||||||
|
response['is_mine'] = response['txid'] in my_txs
|
||||||
|
return response
|
||||||
|
|
||||||
|
d = self.get_claimid(name, txid)
|
||||||
|
d.addCallback(lambda claim_id: self.get_claim(name, claim_id))
|
||||||
|
d.addCallback(_build_response)
|
||||||
|
return d
|
||||||
|
|
||||||
|
def get_claims_for_name(self, name):
|
||||||
|
d = self._get_claims_for_name(name)
|
||||||
|
return d
|
||||||
|
|
||||||
|
def update_metadata(self, new_metadata, old_metadata):
|
||||||
|
meta_for_return = old_metadata if isinstance(old_metadata, dict) else {}
|
||||||
|
for k in new_metadata:
|
||||||
|
meta_for_return[k] = new_metadata[k]
|
||||||
|
return defer.succeed(Metadata(meta_for_return))
|
||||||
|
|
||||||
def claim_name(self, name, bid, m):
|
def claim_name(self, name, bid, m):
|
||||||
|
def _save_metadata(txid, metadata):
|
||||||
metadata = Metadata(m)
|
|
||||||
|
|
||||||
d = self._send_name_claim(name, json.dumps(metadata), bid)
|
|
||||||
|
|
||||||
def _save_metadata(txid):
|
|
||||||
log.info("Saving metadata for claim %s" % txid)
|
log.info("Saving metadata for claim %s" % txid)
|
||||||
d = self._save_name_metadata(name, txid, metadata['sources']['lbry_sd_hash'])
|
d = self._save_name_metadata(name, txid, metadata['sources']['lbry_sd_hash'])
|
||||||
d.addCallback(lambda _: txid)
|
d.addCallback(lambda _: txid)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
d.addCallback(_save_metadata)
|
def _claim_or_update(claim, metadata, _bid):
|
||||||
|
if not claim:
|
||||||
|
log.info("No claim yet, making a new one")
|
||||||
|
return self._send_name_claim(name, metadata.as_json(), _bid)
|
||||||
|
if not claim['is_mine']:
|
||||||
|
log.info("Making a contesting claim")
|
||||||
|
return self._send_name_claim(name, metadata.as_json(), _bid)
|
||||||
|
else:
|
||||||
|
log.info("Updating over own claim")
|
||||||
|
d = self.update_metadata(metadata, claim['value'])
|
||||||
|
d.addCallback(lambda new_metadata: self._send_name_claim_update(name, claim['claim_id'], claim['txid'], new_metadata, _bid))
|
||||||
|
return d
|
||||||
|
|
||||||
|
meta = Metadata(m)
|
||||||
|
|
||||||
|
d = self.get_claim_info(name)
|
||||||
|
d.addCallback(lambda claim: _claim_or_update(claim, meta, bid))
|
||||||
|
d.addCallback(lambda txid: _save_metadata(txid, meta))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def abandon_name(self, txid):
|
def abandon_name(self, txid):
|
||||||
|
@ -415,19 +481,14 @@ class LBRYWallet(object):
|
||||||
dl.addCallback(abandon)
|
dl.addCallback(abandon)
|
||||||
return dl
|
return dl
|
||||||
|
|
||||||
|
def support_claim(self, name, claim_id, amount):
|
||||||
|
return self._support_claim(name, claim_id, amount)
|
||||||
|
|
||||||
def get_tx(self, txid):
|
def get_tx(self, txid):
|
||||||
d = self._get_raw_tx(txid)
|
d = self._get_raw_tx(txid)
|
||||||
d.addCallback(self._get_decoded_tx)
|
d.addCallback(self._get_decoded_tx)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def update_name(self, name, bid, value, old_txid):
|
|
||||||
d = self._get_value_for_name(name)
|
|
||||||
d.addCallback(lambda r: self.abandon_name(r['txid'] if not old_txid else old_txid))
|
|
||||||
d.addCallback(lambda r: log.info("Abandon claim tx %s" % str(r)))
|
|
||||||
d.addCallback(lambda _: self.claim_name(name, bid, value))
|
|
||||||
|
|
||||||
return d
|
|
||||||
|
|
||||||
def get_name_and_validity_for_sd_hash(self, sd_hash):
|
def get_name_and_validity_for_sd_hash(self, sd_hash):
|
||||||
d = self._get_claim_metadata_for_sd_hash(sd_hash)
|
d = self._get_claim_metadata_for_sd_hash(sd_hash)
|
||||||
d.addCallback(lambda name_txid: self._get_status_of_claim(name_txid[1], name_txid[0], sd_hash) if name_txid is not None else None)
|
d.addCallback(lambda name_txid: self._get_status_of_claim(name_txid[1], name_txid[0], sd_hash) if name_txid is not None else None)
|
||||||
|
@ -530,21 +591,45 @@ class LBRYWallet(object):
|
||||||
def _open_db(self):
|
def _open_db(self):
|
||||||
self.db = adbapi.ConnectionPool('sqlite3', os.path.join(self.db_dir, "blockchainname.db"),
|
self.db = adbapi.ConnectionPool('sqlite3', os.path.join(self.db_dir, "blockchainname.db"),
|
||||||
check_same_thread=False)
|
check_same_thread=False)
|
||||||
return self.db.runQuery("create table if not exists name_metadata (" +
|
|
||||||
|
def create_tables(transaction):
|
||||||
|
transaction.execute("create table if not exists name_metadata (" +
|
||||||
" name text, " +
|
" name text, " +
|
||||||
" txid text, " +
|
" txid text, " +
|
||||||
" sd_hash text)")
|
" sd_hash text)")
|
||||||
|
transaction.execute("create table if not exists claim_ids (" +
|
||||||
|
" claimId text, " +
|
||||||
|
" name text, " +
|
||||||
|
" txid text)")
|
||||||
|
|
||||||
|
return self.db.runInteraction(create_tables)
|
||||||
|
|
||||||
|
def _clean_bad_records(self):
|
||||||
|
d = self.db.runQuery("delete from name_metadata where length(txid) > 64 or txid is null")
|
||||||
|
return d
|
||||||
|
|
||||||
def _save_name_metadata(self, name, txid, sd_hash):
|
def _save_name_metadata(self, name, txid, sd_hash):
|
||||||
d = self.db.runQuery("select * from name_metadata where name=? and txid=? and sd_hash=?", (name, txid, sd_hash))
|
assert len(txid) == 64, "That's not a txid: %s" % str(txid)
|
||||||
d.addCallback(lambda r: self.db.runQuery("insert into name_metadata values (?, ?, ?)", (name, txid, sd_hash))
|
d = self.db.runQuery("delete from name_metadata where name=? and txid=? and sd_hash=?", (name, txid, sd_hash))
|
||||||
if not len(r) else None)
|
d.addCallback(lambda _: self.db.runQuery("insert into name_metadata values (?, ?, ?)", (name, txid, sd_hash)))
|
||||||
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def _get_claim_metadata_for_sd_hash(self, sd_hash):
|
def _get_claim_metadata_for_sd_hash(self, sd_hash):
|
||||||
d = self.db.runQuery("select name, txid from name_metadata where sd_hash=?", (sd_hash,))
|
d = self.db.runQuery("select name, txid from name_metadata where sd_hash=?", (sd_hash,))
|
||||||
d.addCallback(lambda r: r[0] if len(r) else None)
|
d.addCallback(lambda r: r[0] if r else None)
|
||||||
|
return d
|
||||||
|
|
||||||
|
def _update_claimid(self, claim_id, name, txid):
|
||||||
|
assert len(txid) == 64, "That's not a txid: %s" % str(txid)
|
||||||
|
d = self.db.runQuery("delete from claim_ids where claimId=? and name=? and txid=?", (claim_id, name, txid))
|
||||||
|
d.addCallback(lambda r: self.db.runQuery("insert into claim_ids values (?, ?, ?)", (claim_id, name, txid)))
|
||||||
|
d.addCallback(lambda _: claim_id)
|
||||||
|
return d
|
||||||
|
|
||||||
|
def _get_claimid_for_tx(self, name, txid):
|
||||||
|
assert len(txid) == 64, "That's not a txid: %s" % str(txid)
|
||||||
|
d = self.db.runQuery("select claimId from claim_ids where name=? and txid=?", (name, txid))
|
||||||
|
d.addCallback(lambda r: r[0][0] if r else None)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
######### Must be overridden #########
|
######### Must be overridden #########
|
||||||
|
@ -567,6 +652,9 @@ class LBRYWallet(object):
|
||||||
def get_name_claims(self):
|
def get_name_claims(self):
|
||||||
return defer.fail(NotImplementedError())
|
return defer.fail(NotImplementedError())
|
||||||
|
|
||||||
|
def _get_claims_for_name(self, name):
|
||||||
|
return defer.fail(NotImplementedError())
|
||||||
|
|
||||||
def _check_first_run(self):
|
def _check_first_run(self):
|
||||||
return defer.fail(NotImplementedError())
|
return defer.fail(NotImplementedError())
|
||||||
|
|
||||||
|
@ -582,7 +670,10 @@ class LBRYWallet(object):
|
||||||
def _send_abandon(self, txid, address, amount):
|
def _send_abandon(self, txid, address, amount):
|
||||||
return defer.fail(NotImplementedError())
|
return defer.fail(NotImplementedError())
|
||||||
|
|
||||||
def _update_name(self, txid, value, amount):
|
def _send_name_claim_update(self, name, claim_id, txid, value, amount):
|
||||||
|
return defer.fail(NotImplementedError())
|
||||||
|
|
||||||
|
def _support_claim(self, name, claim_id, amount):
|
||||||
return defer.fail(NotImplementedError())
|
return defer.fail(NotImplementedError())
|
||||||
|
|
||||||
def _do_send_many(self, payments_to_send):
|
def _do_send_many(self, payments_to_send):
|
||||||
|
@ -717,9 +808,15 @@ class LBRYcrdWallet(LBRYWallet):
|
||||||
def _send_abandon(self, txid, address, amount):
|
def _send_abandon(self, txid, address, amount):
|
||||||
return threads.deferToThread(self._send_abandon_rpc, txid, address, amount)
|
return threads.deferToThread(self._send_abandon_rpc, txid, address, amount)
|
||||||
|
|
||||||
def _update_name(self, txid, value, amount):
|
def _send_name_claim_update(self, name, claim_id, txid, value, amount):
|
||||||
return threads.deferToThread(self._update_name_rpc, txid, value, amount)
|
return threads.deferToThread(self._update_name_rpc, txid, value, amount)
|
||||||
|
|
||||||
|
def _support_claim(self, name, claim_id, amount):
|
||||||
|
return threads.deferToThread(self._support_claim_rpc, name, claim_id, amount)
|
||||||
|
|
||||||
|
def _get_claims_for_name(self, name):
|
||||||
|
return threads.deferToThread(self._get_claims_for_name_rpc, name)
|
||||||
|
|
||||||
def get_claims_from_tx(self, txid):
|
def get_claims_from_tx(self, txid):
|
||||||
return threads.deferToThread(self._get_claims_from_tx_rpc, txid)
|
return threads.deferToThread(self._get_claims_from_tx_rpc, txid)
|
||||||
|
|
||||||
|
@ -854,6 +951,11 @@ class LBRYcrdWallet(LBRYWallet):
|
||||||
rpc_conn = self._get_rpc_conn()
|
rpc_conn = self._get_rpc_conn()
|
||||||
return rpc_conn.getclaimsfortx(txid)
|
return rpc_conn.getclaimsfortx(txid)
|
||||||
|
|
||||||
|
@_catch_connection_error
|
||||||
|
def _get_claims_for_name_rpc(self, name):
|
||||||
|
rpc_conn = self._get_rpc_conn()
|
||||||
|
return rpc_conn.getclaimsforname(name)
|
||||||
|
|
||||||
@_catch_connection_error
|
@_catch_connection_error
|
||||||
def _get_nametrie_rpc(self):
|
def _get_nametrie_rpc(self):
|
||||||
rpc_conn = self._get_rpc_conn()
|
rpc_conn = self._get_rpc_conn()
|
||||||
|
@ -874,6 +976,7 @@ class LBRYcrdWallet(LBRYWallet):
|
||||||
rpc_conn = self._get_rpc_conn()
|
rpc_conn = self._get_rpc_conn()
|
||||||
return rpc_conn.getvalueforname(name)
|
return rpc_conn.getvalueforname(name)
|
||||||
|
|
||||||
|
@_catch_connection_error
|
||||||
def _update_name_rpc(self, txid, value, amount):
|
def _update_name_rpc(self, txid, value, amount):
|
||||||
rpc_conn = self._get_rpc_conn()
|
rpc_conn = self._get_rpc_conn()
|
||||||
return rpc_conn.updateclaim(txid, value, amount)
|
return rpc_conn.updateclaim(txid, value, amount)
|
||||||
|
@ -889,6 +992,11 @@ class LBRYcrdWallet(LBRYWallet):
|
||||||
elif 'message' in e.error:
|
elif 'message' in e.error:
|
||||||
raise ValueError(e.error['message'])
|
raise ValueError(e.error['message'])
|
||||||
|
|
||||||
|
@_catch_connection_error
|
||||||
|
def _support_claim_rpc(self, name, claim_id, amount):
|
||||||
|
rpc_conn = self._get_rpc_conn()
|
||||||
|
return rpc_conn.supportclaim(name, claim_id, amount)
|
||||||
|
|
||||||
@_catch_connection_error
|
@_catch_connection_error
|
||||||
def _get_num_addresses_rpc(self):
|
def _get_num_addresses_rpc(self):
|
||||||
rpc_conn = self._get_rpc_conn()
|
rpc_conn = self._get_rpc_conn()
|
||||||
|
@ -1102,6 +1210,25 @@ class LBRYumWallet(LBRYWallet):
|
||||||
d.addCallback(self._broadcast_transaction)
|
d.addCallback(self._broadcast_transaction)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
def _get_claims_for_name(self, name):
|
||||||
|
cmd = known_commands['getclaimsforname']
|
||||||
|
func = getattr(self.cmd_runner, cmd.name)
|
||||||
|
return threads.deferToThread(func, name)
|
||||||
|
|
||||||
|
def _send_name_claim_update(self, name, claim_id, txid, value, amount):
|
||||||
|
def send_claim_update(address):
|
||||||
|
decoded_claim_id = claim_id.decode('hex')[::-1]
|
||||||
|
metadata = Metadata(value).as_json()
|
||||||
|
log.info("updateclaim %s %s %f %s %s '%s'", txid, address, amount, name, decoded_claim_id.encode('hex'), json.dumps(metadata))
|
||||||
|
cmd = known_commands['updateclaim']
|
||||||
|
func = getattr(self.cmd_runner, cmd.name)
|
||||||
|
return threads.deferToThread(func, txid, address, amount, name, decoded_claim_id, metadata)
|
||||||
|
|
||||||
|
d = self.get_new_address()
|
||||||
|
d.addCallback(send_claim_update)
|
||||||
|
d.addCallback(self._broadcast_transaction)
|
||||||
|
return d
|
||||||
|
|
||||||
def _get_decoded_tx(self, raw_tx):
|
def _get_decoded_tx(self, raw_tx):
|
||||||
tx = Transaction(raw_tx)
|
tx = Transaction(raw_tx)
|
||||||
decoded_tx = {}
|
decoded_tx = {}
|
||||||
|
@ -1113,18 +1240,33 @@ class LBRYumWallet(LBRYWallet):
|
||||||
return decoded_tx
|
return decoded_tx
|
||||||
|
|
||||||
def _send_abandon(self, txid, address, amount):
|
def _send_abandon(self, txid, address, amount):
|
||||||
log.info("Abandon " + str(txid) + " " + str(address) + " " + str(amount))
|
log.info("Abandon %s %s %f" % (txid, address, amount))
|
||||||
cmd = known_commands['abandonclaim']
|
cmd = known_commands['abandonclaim']
|
||||||
func = getattr(self.cmd_runner, cmd.name)
|
func = getattr(self.cmd_runner, cmd.name)
|
||||||
d = threads.deferToThread(func, txid, address, amount)
|
d = threads.deferToThread(func, txid, address, amount)
|
||||||
d.addCallback(self._broadcast_transaction)
|
d.addCallback(self._broadcast_transaction)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
def _support_claim(self, name, claim_id, amount):
|
||||||
|
def _send_support(d, a, n, c):
|
||||||
|
cmd = known_commands['supportclaim']
|
||||||
|
func = getattr(self.cmd_runner, cmd.name)
|
||||||
|
d = threads.deferToThread(func, d, a, n, c)
|
||||||
|
return d
|
||||||
|
d = self.get_new_address()
|
||||||
|
d.addCallback(lambda address: _send_support(address, amount, name, claim_id))
|
||||||
|
d.addCallback(self._broadcast_transaction)
|
||||||
|
return d
|
||||||
|
|
||||||
def _broadcast_transaction(self, raw_tx):
|
def _broadcast_transaction(self, raw_tx):
|
||||||
log.info("Broadcast: " + str(raw_tx))
|
def _log_tx(r):
|
||||||
|
log.info("Broadcast tx: %s", r)
|
||||||
|
return r
|
||||||
cmd = known_commands['broadcast']
|
cmd = known_commands['broadcast']
|
||||||
func = getattr(self.cmd_runner, cmd.name)
|
func = getattr(self.cmd_runner, cmd.name)
|
||||||
d = threads.deferToThread(func, raw_tx)
|
d = threads.deferToThread(func, raw_tx)
|
||||||
|
d.addCallback(_log_tx)
|
||||||
|
d.addCallback(lambda r: r if len(r) == 64 else defer.fail(Exception("Transaction rejected")))
|
||||||
d.addCallback(self._save_wallet)
|
d.addCallback(self._save_wallet)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ class DBLBRYFileMetadataManager(object):
|
||||||
return self._add_blobs_to_stream(stream_hash, blobs, ignore_duplicate_error=True)
|
return self._add_blobs_to_stream(stream_hash, blobs, ignore_duplicate_error=True)
|
||||||
|
|
||||||
def get_blobs_for_stream(self, stream_hash, start_blob=None, end_blob=None, count=None, reverse=False):
|
def get_blobs_for_stream(self, stream_hash, start_blob=None, end_blob=None, count=None, reverse=False):
|
||||||
log.info("Getting blobs for a stream. Count is %s", str(count))
|
log.debug("Getting blobs for a stream. Count is %s", str(count))
|
||||||
|
|
||||||
def get_positions_of_start_and_end():
|
def get_positions_of_start_and_end():
|
||||||
if start_blob is not None:
|
if start_blob is not None:
|
||||||
|
|
|
@ -27,6 +27,7 @@ class ManagedLBRYFileDownloader(LBRYFileSaver):
|
||||||
self.sd_hash = None
|
self.sd_hash = None
|
||||||
self.txid = None
|
self.txid = None
|
||||||
self.uri = None
|
self.uri = None
|
||||||
|
self.claim_id = None
|
||||||
self.rowid = rowid
|
self.rowid = rowid
|
||||||
self.lbry_file_manager = lbry_file_manager
|
self.lbry_file_manager = lbry_file_manager
|
||||||
self.saving_status = False
|
self.saving_status = False
|
||||||
|
@ -43,10 +44,16 @@ class ManagedLBRYFileDownloader(LBRYFileSaver):
|
||||||
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
def _save_claim_id(claim_id):
|
||||||
|
self.claim_id = claim_id
|
||||||
|
return defer.succeed(None)
|
||||||
|
|
||||||
def _save_claim(name, txid):
|
def _save_claim(name, txid):
|
||||||
self.uri = name
|
self.uri = name
|
||||||
self.txid = txid
|
self.txid = txid
|
||||||
return defer.succeed(None)
|
d = self.wallet.get_claimid(name, txid)
|
||||||
|
d.addCallback(_save_claim_id)
|
||||||
|
return d
|
||||||
|
|
||||||
d.addCallback(_save_sd_hash)
|
d.addCallback(_save_sd_hash)
|
||||||
d.addCallback(lambda r: _save_claim(r[0], r[1]) if r else None)
|
d.addCallback(lambda r: _save_claim(r[0], r[1]) if r else None)
|
||||||
|
|
|
@ -80,13 +80,16 @@ class LBRYFileManager(object):
|
||||||
d.addCallback(lambda downloader: downloader.restore())
|
d.addCallback(lambda downloader: downloader.restore())
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def log_error(err):
|
def log_error(err, rowid, stream_hash, options):
|
||||||
log.error("An error occurred while starting a lbry file: %s", err.getErrorMessage())
|
log.error("An error occurred while starting a lbry file: %s", err.getErrorMessage())
|
||||||
|
log.error(rowid)
|
||||||
|
log.error(stream_hash)
|
||||||
|
log.error(options)
|
||||||
|
|
||||||
def start_lbry_files(lbry_files_and_options):
|
def start_lbry_files(lbry_files_and_options):
|
||||||
for rowid, stream_hash, options in lbry_files_and_options:
|
for rowid, stream_hash, options in lbry_files_and_options:
|
||||||
d = set_options_and_restore(rowid, stream_hash, options)
|
d = set_options_and_restore(rowid, stream_hash, options)
|
||||||
d.addErrback(log_error)
|
d.addErrback(lambda err: log_error(err, rowid, stream_hash, options))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
d = self._get_all_lbry_files()
|
d = self._get_all_lbry_files()
|
||||||
|
|
|
@ -39,6 +39,7 @@ from lbrynet.lbrynet_daemon.LBRYDownloader import GetStream
|
||||||
from lbrynet.lbrynet_daemon.LBRYPublisher import Publisher
|
from lbrynet.lbrynet_daemon.LBRYPublisher import Publisher
|
||||||
from lbrynet.lbrynet_daemon.LBRYExchangeRateManager import ExchangeRateManager
|
from lbrynet.lbrynet_daemon.LBRYExchangeRateManager import ExchangeRateManager
|
||||||
from lbrynet.lbrynet_daemon.Lighthouse import LighthouseClient
|
from lbrynet.lbrynet_daemon.Lighthouse import LighthouseClient
|
||||||
|
from lbrynet.core.LBRYMetadata import Metadata
|
||||||
from lbrynet.core import log_support
|
from lbrynet.core import log_support
|
||||||
from lbrynet.core import utils
|
from lbrynet.core import utils
|
||||||
from lbrynet.core.LBRYMetadata import verify_name_characters
|
from lbrynet.core.LBRYMetadata import verify_name_characters
|
||||||
|
@ -376,6 +377,7 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
||||||
log.info("Done writing lbrycrd.conf")
|
log.info("Done writing lbrycrd.conf")
|
||||||
|
|
||||||
def _responseFailed(self, err, call):
|
def _responseFailed(self, err, call):
|
||||||
|
log.error(err.getTraceback())
|
||||||
call.cancel()
|
call.cancel()
|
||||||
|
|
||||||
def render(self, request):
|
def render(self, request):
|
||||||
|
@ -1125,11 +1127,14 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
||||||
|
|
||||||
def _get_est_cost(self, name):
|
def _get_est_cost(self, name):
|
||||||
def _check_est(d, name):
|
def _check_est(d, name):
|
||||||
if isinstance(d.result, float):
|
try:
|
||||||
log.info("Cost est for lbry://" + name + ": " + str(d.result) + "LBC")
|
if d.result:
|
||||||
else:
|
log.info("Cost est for lbry://" + name + ": " + str(d.result) + "LBC")
|
||||||
log.info("Timeout estimating cost for lbry://" + name + ", using key fee")
|
return defer.succeed(None)
|
||||||
d.cancel()
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
log.info("Timeout estimating cost for lbry://" + name + ", using key fee")
|
||||||
|
d.cancel()
|
||||||
return defer.succeed(None)
|
return defer.succeed(None)
|
||||||
|
|
||||||
def _add_key_fee(data_cost):
|
def _add_key_fee(data_cost):
|
||||||
|
@ -1229,7 +1234,7 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
||||||
'stream_name': f.stream_name,
|
'stream_name': f.stream_name,
|
||||||
'suggested_file_name': f.suggested_file_name,
|
'suggested_file_name': f.suggested_file_name,
|
||||||
'upload_allowed': f.upload_allowed, 'sd_hash': f.sd_hash,
|
'upload_allowed': f.upload_allowed, 'sd_hash': f.sd_hash,
|
||||||
'lbry_uri': f.uri, 'txid': f.txid,
|
'lbry_uri': f.uri, 'txid': f.txid, 'claim_id': f.claim_id,
|
||||||
'total_bytes': size,
|
'total_bytes': size,
|
||||||
'written_bytes': written_bytes, 'code': status[0],
|
'written_bytes': written_bytes, 'code': status[0],
|
||||||
'message': message})
|
'message': message})
|
||||||
|
@ -1241,7 +1246,7 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
||||||
'points_paid': f.points_paid, 'stopped': f.stopped, 'stream_hash': f.stream_hash,
|
'points_paid': f.points_paid, 'stopped': f.stopped, 'stream_hash': f.stream_hash,
|
||||||
'stream_name': f.stream_name, 'suggested_file_name': f.suggested_file_name,
|
'stream_name': f.stream_name, 'suggested_file_name': f.suggested_file_name,
|
||||||
'upload_allowed': f.upload_allowed, 'sd_hash': f.sd_hash, 'total_bytes': size,
|
'upload_allowed': f.upload_allowed, 'sd_hash': f.sd_hash, 'total_bytes': size,
|
||||||
'written_bytes': written_bytes, 'lbry_uri': f.uri, 'txid': f.txid,
|
'written_bytes': written_bytes, 'lbry_uri': f.uri, 'txid': f.txid, 'claim_id': f.claim_id,
|
||||||
'code': status[0], 'message': status[1]})
|
'code': status[0], 'message': status[1]})
|
||||||
|
|
||||||
return d
|
return d
|
||||||
|
@ -1272,7 +1277,7 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
||||||
d = self._get_lbry_file_by_sd_hash(val)
|
d = self._get_lbry_file_by_sd_hash(val)
|
||||||
elif search_by == "file_name":
|
elif search_by == "file_name":
|
||||||
d = self._get_lbry_file_by_file_name(val)
|
d = self._get_lbry_file_by_file_name(val)
|
||||||
d.addCallback(_log_get_lbry_file)
|
# d.addCallback(_log_get_lbry_file)
|
||||||
if return_json:
|
if return_json:
|
||||||
d.addCallback(_get_json_for_return)
|
d.addCallback(_get_json_for_return)
|
||||||
return d
|
return d
|
||||||
|
@ -1638,11 +1643,15 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _convert_amount_to_float(r):
|
def _convert_amount_to_float(r):
|
||||||
r['amount'] = float(r['amount']) / 10**8
|
if not r:
|
||||||
return r
|
return False
|
||||||
|
else:
|
||||||
|
r['amount'] = float(r['amount']) / 10**8
|
||||||
|
return r
|
||||||
|
|
||||||
name = p['name']
|
name = p['name']
|
||||||
d = self.session.wallet.get_claim_info(name)
|
txid = p.get('txid', None)
|
||||||
|
d = self.session.wallet.get_claim_info(name, txid)
|
||||||
d.addCallback(_convert_amount_to_float)
|
d.addCallback(_convert_amount_to_float)
|
||||||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||||
return d
|
return d
|
||||||
|
@ -1771,7 +1780,7 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
||||||
List of search results
|
List of search results
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# TODO: change this function to "search", and use cached stream size info from the search server
|
# TODO: change this function to "search"
|
||||||
|
|
||||||
if 'search' in p.keys():
|
if 'search' in p.keys():
|
||||||
search = p['search']
|
search = p['search']
|
||||||
|
@ -1840,26 +1849,31 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
||||||
Claim txid
|
Claim txid
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def _set_address(address, currency, m):
|
||||||
|
log.info("Generated new address for key fee: " + str(address))
|
||||||
|
m['fee'][currency]['address'] = address
|
||||||
|
return m
|
||||||
|
|
||||||
name = p['name']
|
name = p['name']
|
||||||
|
|
||||||
|
log.info("Publish: ")
|
||||||
|
log.info(p)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
verify_name_characters(name)
|
verify_name_characters(name)
|
||||||
except:
|
except AssertionError:
|
||||||
log.error("Bad name")
|
log.error("Bad name")
|
||||||
return defer.fail(InvalidNameError("Bad name"))
|
return defer.fail(InvalidNameError("Bad name"))
|
||||||
|
|
||||||
bid = p['bid']
|
bid = p['bid']
|
||||||
file_path = p['file_path']
|
|
||||||
metadata = p['metadata']
|
|
||||||
|
|
||||||
def _set_address(address, currency):
|
try:
|
||||||
log.info("Generated new address for key fee: " + str(address))
|
metadata = Metadata(p['metadata'])
|
||||||
metadata['fee'][currency]['address'] = address
|
make_lbry_file = False
|
||||||
return defer.succeed(None)
|
except AssertionError:
|
||||||
|
make_lbry_file = True
|
||||||
def _delete_data(lbry_file):
|
metadata = p['metadata']
|
||||||
txid = lbry_file.txid
|
file_path = p['file_path']
|
||||||
d = self._delete_lbry_file(lbry_file, delete_file=False)
|
|
||||||
d.addCallback(lambda _: txid)
|
|
||||||
return d
|
|
||||||
|
|
||||||
if not self.pending_claim_checker.running:
|
if not self.pending_claim_checker.running:
|
||||||
self.pending_claim_checker.start(30)
|
self.pending_claim_checker.start(30)
|
||||||
|
@ -1873,15 +1887,16 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
||||||
for c in metadata['fee']:
|
for c in metadata['fee']:
|
||||||
if 'address' not in metadata['fee'][c]:
|
if 'address' not in metadata['fee'][c]:
|
||||||
d.addCallback(lambda _: self.session.wallet.get_new_address())
|
d.addCallback(lambda _: self.session.wallet.get_new_address())
|
||||||
d.addCallback(lambda addr: _set_address(addr, c))
|
d.addCallback(lambda addr: _set_address(addr, c, metadata))
|
||||||
|
else:
|
||||||
pub = Publisher(self.session, self.lbry_file_manager, self.session.wallet)
|
d.addCallback(lambda _: metadata)
|
||||||
d.addCallback(lambda _: self._get_lbry_file_by_uri(name))
|
if make_lbry_file:
|
||||||
d.addCallbacks(lambda l: None if not l else _delete_data(l), lambda _: None)
|
pub = Publisher(self.session, self.lbry_file_manager, self.session.wallet)
|
||||||
d.addCallback(lambda r: pub.start(name, file_path, bid, metadata, r))
|
d.addCallback(lambda meta: pub.start(name, file_path, bid, meta))
|
||||||
|
else:
|
||||||
|
d.addCallback(lambda meta: self.session.wallet.claim_name(name, bid, meta))
|
||||||
d.addCallback(lambda txid: self._add_to_pending_claims(name, txid))
|
d.addCallback(lambda txid: self._add_to_pending_claims(name, txid))
|
||||||
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||||
d.addErrback(lambda err: self._render_response(err.getTraceback(), BAD_REQUEST))
|
|
||||||
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@ -1911,6 +1926,25 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
||||||
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
def jsonrpc_support_claim(self, p):
|
||||||
|
"""
|
||||||
|
Support a name claim
|
||||||
|
|
||||||
|
Args:
|
||||||
|
'name': name
|
||||||
|
'claim_id': claim id of claim to support
|
||||||
|
'amount': amount to support by
|
||||||
|
Return:
|
||||||
|
txid
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = p['name']
|
||||||
|
claim_id = p['claim_id']
|
||||||
|
amount = p['amount']
|
||||||
|
d = self.session.wallet.support_claim(name, claim_id, amount)
|
||||||
|
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||||
|
return d
|
||||||
|
|
||||||
def jsonrpc_get_name_claims(self):
|
def jsonrpc_get_name_claims(self):
|
||||||
"""
|
"""
|
||||||
Get my name claims
|
Get my name claims
|
||||||
|
@ -1934,6 +1968,21 @@ class LBRYDaemon(jsonrpc.JSONRPC):
|
||||||
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
def jsonrpc_get_claims_for_name(self, p):
|
||||||
|
"""
|
||||||
|
Get claims for a name
|
||||||
|
|
||||||
|
Args:
|
||||||
|
'name': name
|
||||||
|
Returns
|
||||||
|
list of name claims
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = p['name']
|
||||||
|
d = self.session.wallet.get_claims_for_name(name)
|
||||||
|
d.addCallback(lambda r: self._render_response(r, OK_CODE))
|
||||||
|
return d
|
||||||
|
|
||||||
def jsonrpc_get_transaction_history(self):
|
def jsonrpc_get_transaction_history(self):
|
||||||
"""
|
"""
|
||||||
Get transaction history
|
Get transaction history
|
||||||
|
@ -2433,7 +2482,7 @@ class _ResolveNameHelper(object):
|
||||||
d = self.wallet.get_stream_info_for_name(self.name)
|
d = self.wallet.get_stream_info_for_name(self.name)
|
||||||
d.addCallbacks(self._cache_stream_info, lambda _: defer.fail(UnknownNameError))
|
d.addCallbacks(self._cache_stream_info, lambda _: defer.fail(UnknownNameError))
|
||||||
else:
|
else:
|
||||||
log.info("Returning cached stream info for lbry://%s", self.name)
|
log.debug("Returning cached stream info for lbry://%s", self.name)
|
||||||
d = defer.succeed(self.name_data['claim_metadata'])
|
d = defer.succeed(self.name_data['claim_metadata'])
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ class Publisher(object):
|
||||||
self.stream_hash = None
|
self.stream_hash = None
|
||||||
self.metadata = {}
|
self.metadata = {}
|
||||||
|
|
||||||
def start(self, name, file_path, bid, metadata, old_txid):
|
def start(self, name, file_path, bid, metadata):
|
||||||
|
|
||||||
def _show_result():
|
def _show_result():
|
||||||
log.info("Published %s --> lbry://%s txid: %s", self.file_name, self.publish_name, self.txid)
|
log.info("Published %s --> lbry://%s txid: %s", self.file_name, self.publish_name, self.txid)
|
||||||
|
@ -52,7 +52,6 @@ class Publisher(object):
|
||||||
self.file_path = file_path
|
self.file_path = file_path
|
||||||
self.bid_amount = bid
|
self.bid_amount = bid
|
||||||
self.metadata = metadata
|
self.metadata = metadata
|
||||||
self.old_txid = old_txid
|
|
||||||
|
|
||||||
d = self._check_file_path(self.file_path)
|
d = self._check_file_path(self.file_path)
|
||||||
d.addCallback(lambda _: create_lbry_file(self.session, self.lbry_file_manager,
|
d.addCallback(lambda _: create_lbry_file(self.session, self.lbry_file_manager,
|
||||||
|
@ -105,21 +104,12 @@ class Publisher(object):
|
||||||
self.metadata['content-type'] = mimetypes.guess_type(os.path.join(self.lbry_file.download_directory,
|
self.metadata['content-type'] = mimetypes.guess_type(os.path.join(self.lbry_file.download_directory,
|
||||||
self.lbry_file.file_name))[0]
|
self.lbry_file.file_name))[0]
|
||||||
self.metadata['ver'] = CURRENT_METADATA_VERSION
|
self.metadata['ver'] = CURRENT_METADATA_VERSION
|
||||||
|
m = Metadata(self.metadata)
|
||||||
|
|
||||||
if self.old_txid:
|
|
||||||
|
|
||||||
d = self.wallet.abandon_name(self.old_txid)
|
|
||||||
d.addCallback(lambda tx: log.info("Abandoned tx %s" % str(tx)))
|
|
||||||
d.addCallback(lambda _: self.wallet.claim_name(self.publish_name,
|
|
||||||
self.bid_amount,
|
|
||||||
Metadata(self.metadata)))
|
|
||||||
else:
|
|
||||||
d = self.wallet.claim_name(self.publish_name,
|
|
||||||
self.bid_amount,
|
|
||||||
Metadata(self.metadata))
|
|
||||||
def set_tx_hash(txid):
|
def set_tx_hash(txid):
|
||||||
self.txid = txid
|
self.txid = txid
|
||||||
|
|
||||||
|
d = self.wallet.claim_name(self.publish_name, self.bid_amount, m)
|
||||||
d.addCallback(set_tx_hash)
|
d.addCallback(set_tx_hash)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@ -134,4 +124,4 @@ class Publisher(object):
|
||||||
log.error(error_message)
|
log.error(error_message)
|
||||||
log.error(message, str(self.file_name), str(self.publish_name), err.getTraceback())
|
log.error(message, str(self.file_name), str(self.publish_name), err.getTraceback())
|
||||||
|
|
||||||
return defer.succeed(error_message)
|
return defer.fail(Exception("Publish failed"))
|
||||||
|
|
Loading…
Reference in a new issue