all
This commit is contained in:
parent
e74998209d
commit
6653da2973
11 changed files with 42 additions and 15 deletions
|
@ -77,6 +77,7 @@ class JSONResponseEncoder(JSONEncoder):
|
|||
if txo.channel is not None:
|
||||
output['channel_name'] = txo.channel.claim_name
|
||||
try:
|
||||
raise ValueError()
|
||||
output['valid_signature'] = txo.is_signed_by(txo.channel, self.ledger)
|
||||
except BadSignatureError:
|
||||
output['valid_signature'] = False
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from binascii import hexlify
|
||||
|
||||
from google.protobuf.message import DecodeError
|
||||
from google.protobuf.json_format import MessageToDict
|
||||
|
||||
|
@ -23,6 +25,10 @@ class Signable:
|
|||
def is_undetermined(self):
|
||||
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
|
||||
def is_signed(self):
|
||||
return self.signature is not None
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from binascii import hexlify
|
||||
|
||||
from torba.client.basedatabase import BaseDatabase
|
||||
|
||||
|
||||
|
@ -57,7 +59,7 @@ class WalletDatabase(BaseDatabase):
|
|||
for txo in txos:
|
||||
if txo.script.is_claim_name or txo.script.is_update_claim:
|
||||
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:
|
||||
txo.private_key = my_account.get_certificate_private_key(txo.ref)
|
||||
|
||||
|
@ -71,8 +73,7 @@ class WalletDatabase(BaseDatabase):
|
|||
}
|
||||
for txo in txos:
|
||||
if txo.script.is_claim_name or txo.script.is_update_claim:
|
||||
if 'publisherSignature' in txo.claim_dict:
|
||||
txo.channel = channels.get(txo.claim_dict['publisherSignature']['certificateId'])
|
||||
txo.channel = channels.get(txo.claim.signing_channel_hash, None)
|
||||
|
||||
return txos
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ class MainNetLedger(BaseLedger):
|
|||
resolutions = await self.network.get_values_for_uris(self.headers.hash().decode(), *uris)
|
||||
return await resolver._handle_resolutions(resolutions, uris, page, page_size)
|
||||
except Exception as e:
|
||||
log.exception(e)
|
||||
return {'error': str(e)}
|
||||
|
||||
async def get_claim_by_claim_id(self, claim_id):
|
||||
|
|
|
@ -416,12 +416,13 @@ class LbryWalletManager(BaseWalletManager):
|
|||
|
||||
if certificate:
|
||||
claim_output.sign(certificate, first_input_id=b'placeholder')
|
||||
claim_output.script.generate()
|
||||
|
||||
tx = await Transaction.create(inputs, [claim_output], [account], account)
|
||||
|
||||
if certificate:
|
||||
claim_output.sign(certificate)
|
||||
tx._reset()
|
||||
await tx.sign([account])
|
||||
|
||||
await account.ledger.broadcast(tx)
|
||||
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)
|
||||
)
|
||||
key = claim_output.generate_channel_private_key()
|
||||
claim_output.script.generate()
|
||||
tx = await Transaction.create([], [claim_output], [account], account)
|
||||
|
||||
|
||||
await account.ledger.broadcast(tx)
|
||||
account.add_certificate_private_key(tx.outputs[0].ref, key.decode())
|
||||
# TODO: release reserved tx outputs in case anything fails by this point
|
||||
|
|
|
@ -8,6 +8,8 @@ from lbrynet.schema.claim import Claim
|
|||
from google.protobuf.message import DecodeError
|
||||
from lbrynet.schema.uri import parse_lbry_uri
|
||||
from lbrynet.wallet.claim_proofs import verify_proof, InvalidProofError
|
||||
from lbrynet.wallet.transaction import Transaction
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -30,6 +32,7 @@ class Resolver:
|
|||
await self._handle_resolve_uri_response(uri, resolution, page, page_size)
|
||||
)
|
||||
except (UnknownNameError, UnknownClaimID, UnknownURI) as err:
|
||||
log.exception(err)
|
||||
results[uri] = {'error': str(err)}
|
||||
else:
|
||||
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:
|
||||
return claim_result
|
||||
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:
|
||||
certificate_id = hexlify(certificate_id[::-1]).decode()
|
||||
certificate = await self.network.get_claims_by_ids(certificate_id)
|
||||
certificate = certificate.pop(certificate_id) if certificate else None
|
||||
return await self.parse_and_validate_claim_result(claim_result, certificate=certificate)
|
||||
|
@ -175,6 +179,8 @@ class Resolver:
|
|||
if decoded:
|
||||
claim_result['has_signature'] = False
|
||||
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:
|
||||
log.info("fetching certificate to check claim signature")
|
||||
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['signature_is_valid'] = False
|
||||
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
|
||||
if validated:
|
||||
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"}
|
||||
|
||||
|
||||
def validate_claim_signature_and_get_channel_name(claim, certificate_claim,
|
||||
claim_address, name, decoded_certificate=None):
|
||||
def validate_claim_signature_and_get_channel_name(claim_result, certificate_claim,
|
||||
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:
|
||||
return False, None
|
||||
if 'value' not in certificate_claim:
|
||||
log.warning('Got an invalid claim while parsing certificates, please report: %s', certificate_claim)
|
||||
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):
|
||||
raise TypeError("Certificate is not a ClaimDict: %s" % str(type(certificate)))
|
||||
if _validate_signed_claim(claim, claim_address, name, certificate):
|
||||
|
|
|
@ -149,7 +149,7 @@ class LBRYBlockProcessor(BlockProcessor):
|
|||
try:
|
||||
parse_lbry_uri(name.decode()) # skip invalid names
|
||||
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:
|
||||
return cert_id
|
||||
if cert_id:
|
||||
|
|
|
@ -114,7 +114,7 @@ class Output(BaseOutput):
|
|||
return True
|
||||
|
||||
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([
|
||||
first_input_id or self.tx_ref.tx.inputs[0].txo_ref.id.encode(),
|
||||
self.claim.signing_channel_id,
|
||||
|
|
|
@ -109,7 +109,7 @@ class EpicAdventuresOfChris45(CommandTestCase):
|
|||
# After abandoning he just waits for his LBCs to be returned to his account
|
||||
await self.generate(5)
|
||||
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
|
||||
# who says that it is of utmost urgency that Chris transfer him
|
||||
|
@ -126,7 +126,7 @@ class EpicAdventuresOfChris45(CommandTestCase):
|
|||
await self.generate(5)
|
||||
result = await self.daemon.jsonrpc_account_balance()
|
||||
# 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
|
||||
result = await self.daemon.jsonrpc_account_balance(ramsey_account_id)
|
||||
|
|
|
@ -62,7 +62,7 @@ class CommandTestCase(IntegrationTestCase):
|
|||
timeout = 180
|
||||
LEDGER = lbrynet.wallet
|
||||
MANAGER = LbryWalletManager
|
||||
VERBOSITY = logging.WARN
|
||||
VERBOSITY = logging.DEBUG
|
||||
|
||||
async def asyncSetUp(self):
|
||||
await super().asyncSetUp()
|
||||
|
|
2
tox.ini
2
tox.ini
|
@ -9,7 +9,7 @@ extras = test
|
|||
changedir = {toxinidir}/tests
|
||||
setenv =
|
||||
HOME=/tmp
|
||||
TORBA_LEDGER=lbrynet.extras.wallet
|
||||
TORBA_LEDGER=lbrynet.wallet
|
||||
commands =
|
||||
orchstr8 download
|
||||
coverage run -p --source={envsitepackagesdir}/lbrynet -m unittest discover -vv integration
|
||||
|
|
Loading…
Reference in a new issue