This commit is contained in:
Victor Shyba 2019-03-21 20:46:37 -03:00 committed by Lex Berezhny
parent e74998209d
commit 6653da2973
11 changed files with 42 additions and 15 deletions

View file

@ -77,6 +77,7 @@ class JSONResponseEncoder(JSONEncoder):
if txo.channel is not None: if txo.channel is not None:
output['channel_name'] = txo.channel.claim_name output['channel_name'] = txo.channel.claim_name
try: try:
raise ValueError()
output['valid_signature'] = txo.is_signed_by(txo.channel, self.ledger) output['valid_signature'] = txo.is_signed_by(txo.channel, self.ledger)
except BadSignatureError: except BadSignatureError:
output['valid_signature'] = False output['valid_signature'] = False

View file

@ -1,3 +1,5 @@
from binascii import hexlify
from google.protobuf.message import DecodeError from google.protobuf.message import DecodeError
from google.protobuf.json_format import MessageToDict from google.protobuf.json_format import MessageToDict
@ -23,6 +25,10 @@ class Signable:
def is_undetermined(self): def is_undetermined(self):
return self.message.WhichOneof('type') is None return self.message.WhichOneof('type') is None
@property
def signing_channel_hash(self):
return hexlify(self.signing_channel_id[::-1]).decode() if self.signing_channel_id else None
@property @property
def is_signed(self): def is_signed(self):
return self.signature is not None return self.signature is not None

View file

@ -1,3 +1,5 @@
from binascii import hexlify
from torba.client.basedatabase import BaseDatabase from torba.client.basedatabase import BaseDatabase
@ -57,7 +59,7 @@ class WalletDatabase(BaseDatabase):
for txo in txos: for txo in txos:
if txo.script.is_claim_name or txo.script.is_update_claim: if txo.script.is_claim_name or txo.script.is_update_claim:
if txo.claim.is_signed: if txo.claim.is_signed:
channel_ids.add(txo.claim.signing_channel_id) channel_ids.add(hexlify(txo.claim.signing_channel_id[::-1]).decode())
if txo.claim_name.startswith('@') and my_account is not None: if txo.claim_name.startswith('@') and my_account is not None:
txo.private_key = my_account.get_certificate_private_key(txo.ref) txo.private_key = my_account.get_certificate_private_key(txo.ref)
@ -71,8 +73,7 @@ class WalletDatabase(BaseDatabase):
} }
for txo in txos: for txo in txos:
if txo.script.is_claim_name or txo.script.is_update_claim: if txo.script.is_claim_name or txo.script.is_update_claim:
if 'publisherSignature' in txo.claim_dict: txo.channel = channels.get(txo.claim.signing_channel_hash, None)
txo.channel = channels.get(txo.claim_dict['publisherSignature']['certificateId'])
return txos return txos

View file

@ -67,6 +67,7 @@ class MainNetLedger(BaseLedger):
resolutions = await self.network.get_values_for_uris(self.headers.hash().decode(), *uris) resolutions = await self.network.get_values_for_uris(self.headers.hash().decode(), *uris)
return await resolver._handle_resolutions(resolutions, uris, page, page_size) return await resolver._handle_resolutions(resolutions, uris, page, page_size)
except Exception as e: except Exception as e:
log.exception(e)
return {'error': str(e)} return {'error': str(e)}
async def get_claim_by_claim_id(self, claim_id): async def get_claim_by_claim_id(self, claim_id):

View file

@ -416,12 +416,13 @@ class LbryWalletManager(BaseWalletManager):
if certificate: if certificate:
claim_output.sign(certificate, first_input_id=b'placeholder') claim_output.sign(certificate, first_input_id=b'placeholder')
claim_output.script.generate()
tx = await Transaction.create(inputs, [claim_output], [account], account) tx = await Transaction.create(inputs, [claim_output], [account], account)
if certificate: if certificate:
claim_output.sign(certificate) claim_output.sign(certificate)
tx._reset() await tx.sign([account])
await account.ledger.broadcast(tx) await account.ledger.broadcast(tx)
await self.old_db.save_claims([self._old_get_temp_claim_info( await self.old_db.save_claims([self._old_get_temp_claim_info(
@ -475,8 +476,10 @@ class LbryWalletManager(BaseWalletManager):
amount, channel_name, claim, account.ledger.address_to_hash160(address) amount, channel_name, claim, account.ledger.address_to_hash160(address)
) )
key = claim_output.generate_channel_private_key() key = claim_output.generate_channel_private_key()
claim_output.script.generate()
tx = await Transaction.create([], [claim_output], [account], account) tx = await Transaction.create([], [claim_output], [account], account)
await account.ledger.broadcast(tx) await account.ledger.broadcast(tx)
account.add_certificate_private_key(tx.outputs[0].ref, key.decode()) account.add_certificate_private_key(tx.outputs[0].ref, key.decode())
# TODO: release reserved tx outputs in case anything fails by this point # TODO: release reserved tx outputs in case anything fails by this point

View file

@ -8,6 +8,8 @@ from lbrynet.schema.claim import Claim
from google.protobuf.message import DecodeError from google.protobuf.message import DecodeError
from lbrynet.schema.uri import parse_lbry_uri from lbrynet.schema.uri import parse_lbry_uri
from lbrynet.wallet.claim_proofs import verify_proof, InvalidProofError from lbrynet.wallet.claim_proofs import verify_proof, InvalidProofError
from lbrynet.wallet.transaction import Transaction
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -30,6 +32,7 @@ class Resolver:
await self._handle_resolve_uri_response(uri, resolution, page, page_size) await self._handle_resolve_uri_response(uri, resolution, page, page_size)
) )
except (UnknownNameError, UnknownClaimID, UnknownURI) as err: except (UnknownNameError, UnknownClaimID, UnknownURI) as err:
log.exception(err)
results[uri] = {'error': str(err)} results[uri] = {'error': str(err)}
else: else:
results[uri] = {'error': "URI lbry://{} cannot be resolved".format(uri.replace("lbry://", ""))} results[uri] = {'error': "URI lbry://{} cannot be resolved".format(uri.replace("lbry://", ""))}
@ -151,8 +154,9 @@ class Resolver:
if not claim_result or 'value' not in claim_result: if not claim_result or 'value' not in claim_result:
return claim_result return claim_result
certificate = None certificate = None
certificate_id = Claim.from_bytes(claim_result['value']).signing_channel_id certificate_id = Claim.from_bytes(unhexlify(claim_result['value'])).signing_channel_id
if certificate_id: if certificate_id:
certificate_id = hexlify(certificate_id[::-1]).decode()
certificate = await self.network.get_claims_by_ids(certificate_id) certificate = await self.network.get_claims_by_ids(certificate_id)
certificate = certificate.pop(certificate_id) if certificate else None certificate = certificate.pop(certificate_id) if certificate else None
return await self.parse_and_validate_claim_result(claim_result, certificate=certificate) return await self.parse_and_validate_claim_result(claim_result, certificate=certificate)
@ -175,6 +179,8 @@ class Resolver:
if decoded: if decoded:
claim_result['has_signature'] = False claim_result['has_signature'] = False
if decoded.is_signed: if decoded.is_signed:
claim_tx = await self.network.get_transaction(claim_result['txid'])
cert_tx = await self.network.get_transaction(certificate['txid'])
if certificate is None: if certificate is None:
log.info("fetching certificate to check claim signature") log.info("fetching certificate to check claim signature")
certificate = await self.network.get_claims_by_ids(decoded.signing_channel_id) certificate = await self.network.get_claims_by_ids(decoded.signing_channel_id)
@ -183,7 +189,9 @@ class Resolver:
claim_result['has_signature'] = True claim_result['has_signature'] = True
claim_result['signature_is_valid'] = False claim_result['signature_is_valid'] = False
validated, channel_name = validate_claim_signature_and_get_channel_name( validated, channel_name = validate_claim_signature_and_get_channel_name(
decoded, certificate, claim_result['address'], claim_result['name']) claim_result, certificate, claim_result['address'], claim_result['name'],
claim_tx=claim_tx, cert_tx=cert_tx
)
claim_result['channel_name'] = channel_name claim_result['channel_name'] = channel_name
if validated: if validated:
claim_result['signature_is_valid'] = True claim_result['signature_is_valid'] = True
@ -382,14 +390,21 @@ def _verify_proof(name, claim_trie_root, result, height, depth, transaction_clas
return {'error': "proof not in result"} return {'error': "proof not in result"}
def validate_claim_signature_and_get_channel_name(claim, certificate_claim, def validate_claim_signature_and_get_channel_name(claim_result, certificate_claim,
claim_address, name, decoded_certificate=None): claim_address, name, decoded_certificate=None,
claim_tx=None, cert_tx=None):
if cert_tx and certificate_claim and claim_tx and claim_result:
tx = Transaction(unhexlify(claim_tx))
cert_tx = Transaction(unhexlify(cert_tx))
is_signed = tx.outputs[claim_result['nout']].is_signed_by(cert_tx.outputs[certificate_claim['nout']])
return is_signed, certificate_claim['name']
return False, None
if not certificate_claim: if not certificate_claim:
return False, None return False, None
if 'value' not in certificate_claim: if 'value' not in certificate_claim:
log.warning('Got an invalid claim while parsing certificates, please report: %s', certificate_claim) log.warning('Got an invalid claim while parsing certificates, please report: %s', certificate_claim)
return False, None return False, None
certificate = decoded_certificate or Claim.from_bytes(certificate_claim['value']) certificate = decoded_certificate or certificate_claim['value']
if not isinstance(certificate, Claim): if not isinstance(certificate, Claim):
raise TypeError("Certificate is not a ClaimDict: %s" % str(type(certificate))) raise TypeError("Certificate is not a ClaimDict: %s" % str(type(certificate)))
if _validate_signed_claim(claim, claim_address, name, certificate): if _validate_signed_claim(claim, claim_address, name, certificate):

View file

@ -149,7 +149,7 @@ class LBRYBlockProcessor(BlockProcessor):
try: try:
parse_lbry_uri(name.decode()) # skip invalid names parse_lbry_uri(name.decode()) # skip invalid names
claim_dict = Claim.from_bytes(value) claim_dict = Claim.from_bytes(value)
cert_id = unhexlify(claim_dict.signing_channel_id)[::-1] cert_id = claim_dict.signing_channel_id
if not self.should_validate_signatures: if not self.should_validate_signatures:
return cert_id return cert_id
if cert_id: if cert_id:

View file

@ -114,7 +114,7 @@ class Output(BaseOutput):
return True return True
def sign(self, channel: 'Output', first_input_id=None): def sign(self, channel: 'Output', first_input_id=None):
self.claim.signing_channel_id = unhexlify(channel.claim_id) self.claim.signing_channel_id = unhexlify(channel.claim_id)[::-1]
digest = sha256(b''.join([ digest = sha256(b''.join([
first_input_id or self.tx_ref.tx.inputs[0].txo_ref.id.encode(), first_input_id or self.tx_ref.tx.inputs[0].txo_ref.id.encode(),
self.claim.signing_channel_id, self.claim.signing_channel_id,

View file

@ -109,7 +109,7 @@ class EpicAdventuresOfChris45(CommandTestCase):
# After abandoning he just waits for his LBCs to be returned to his account # After abandoning he just waits for his LBCs to be returned to his account
await self.generate(5) await self.generate(5)
result = await self.daemon.jsonrpc_account_balance() result = await self.daemon.jsonrpc_account_balance()
self.assertEqual(result, '8.9693585') self.assertEqual(result, '8.969381')
# Amidst all this Chris receives a call from his friend Ramsey # Amidst all this Chris receives a call from his friend Ramsey
# who says that it is of utmost urgency that Chris transfer him # who says that it is of utmost urgency that Chris transfer him
@ -126,7 +126,7 @@ class EpicAdventuresOfChris45(CommandTestCase):
await self.generate(5) await self.generate(5)
result = await self.daemon.jsonrpc_account_balance() result = await self.daemon.jsonrpc_account_balance()
# Chris' balance was correct # Chris' balance was correct
self.assertEqual(result, '7.9692345') self.assertEqual(result, '7.969257')
# Ramsey too assured him that he had received the 1 LBC and thanks him # Ramsey too assured him that he had received the 1 LBC and thanks him
result = await self.daemon.jsonrpc_account_balance(ramsey_account_id) result = await self.daemon.jsonrpc_account_balance(ramsey_account_id)

View file

@ -62,7 +62,7 @@ class CommandTestCase(IntegrationTestCase):
timeout = 180 timeout = 180
LEDGER = lbrynet.wallet LEDGER = lbrynet.wallet
MANAGER = LbryWalletManager MANAGER = LbryWalletManager
VERBOSITY = logging.WARN VERBOSITY = logging.DEBUG
async def asyncSetUp(self): async def asyncSetUp(self):
await super().asyncSetUp() await super().asyncSetUp()

View file

@ -9,7 +9,7 @@ extras = test
changedir = {toxinidir}/tests changedir = {toxinidir}/tests
setenv = setenv =
HOME=/tmp HOME=/tmp
TORBA_LEDGER=lbrynet.extras.wallet TORBA_LEDGER=lbrynet.wallet
commands = commands =
orchstr8 download orchstr8 download
coverage run -p --source={envsitepackagesdir}/lbrynet -m unittest discover -vv integration coverage run -p --source={envsitepackagesdir}/lbrynet -m unittest discover -vv integration