diff --git a/lbry/extras/daemon/daemon.py b/lbry/extras/daemon/daemon.py index d83f73abb..67df0ae8d 100644 --- a/lbry/extras/daemon/daemon.py +++ b/lbry/extras/daemon/daemon.py @@ -2550,7 +2550,7 @@ class Daemon(metaclass=JSONRPCServerType): name, claim, amount, claim_address, funding_accounts, funding_accounts[0] ) txo = tx.outputs[0] - txo.generate_channel_private_key() + await txo.generate_channel_private_key() await tx.sign(funding_accounts) @@ -2702,7 +2702,7 @@ class Daemon(metaclass=JSONRPCServerType): new_txo = tx.outputs[0] if new_signing_key: - new_txo.generate_channel_private_key() + await new_txo.generate_channel_private_key() else: new_txo.private_key = old_txo.private_key diff --git a/lbry/wallet/account.py b/lbry/wallet/account.py index 3a3d4c3f3..fdefde985 100644 --- a/lbry/wallet/account.py +++ b/lbry/wallet/account.py @@ -525,11 +525,13 @@ class Account: channel_pubkey_hash = self.ledger.public_key_to_address(public_key_bytes) self.channel_keys[channel_pubkey_hash] = private_key.to_pem().decode() - def get_channel_private_key(self, public_key_bytes): + async def get_channel_private_key(self, public_key_bytes): channel_pubkey_hash = self.ledger.public_key_to_address(public_key_bytes) private_key_pem = self.channel_keys.get(channel_pubkey_hash) if private_key_pem: - return ecdsa.SigningKey.from_pem(private_key_pem, hashfunc=sha256) + return await asyncio.get_event_loop().run_in_executor( + None, ecdsa.SigningKey.from_pem, private_key_pem, sha256 + ) async def maybe_migrate_certificates(self): def to_der(private_key_pem): diff --git a/lbry/wallet/database.py b/lbry/wallet/database.py index 9c8ad7695..15c866017 100644 --- a/lbry/wallet/database.py +++ b/lbry/wallet/database.py @@ -918,7 +918,7 @@ class Database(SQLiteMixin): channel_ids.add(txo.claim.signing_channel_id) if txo.claim.is_channel and wallet: for account in wallet.accounts: - private_key = account.get_channel_private_key( + private_key = await account.get_channel_private_key( txo.claim.channel.public_key_bytes ) if private_key: diff --git a/lbry/wallet/transaction.py b/lbry/wallet/transaction.py index df9beddcf..0f32ffdd3 100644 --- a/lbry/wallet/transaction.py +++ b/lbry/wallet/transaction.py @@ -2,6 +2,7 @@ import struct import hashlib import logging import typing +import asyncio from binascii import hexlify, unhexlify from typing import List, Iterable, Optional, Tuple @@ -412,8 +413,10 @@ class Output(InputOutput): self.channel = None self.claim.clear_signature() - def generate_channel_private_key(self): - self.private_key = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1, hashfunc=hashlib.sha256) + async def generate_channel_private_key(self): + self.private_key = await asyncio.get_event_loop().run_in_executor( + None, ecdsa.SigningKey.generate, ecdsa.SECP256k1, None, hashlib.sha256 + ) self.claim.channel.public_key_bytes = self.private_key.get_verifying_key().to_der() self.script.generate() return self.private_key diff --git a/tests/integration/blockchain/test_internal_transaction_api.py b/tests/integration/blockchain/test_internal_transaction_api.py index 2bb4ac944..6eba5e229 100644 --- a/tests/integration/blockchain/test_internal_transaction_api.py +++ b/tests/integration/blockchain/test_internal_transaction_api.py @@ -31,7 +31,7 @@ class BasicTransactionTest(IntegrationTestCase): channel_txo = Output.pay_claim_name_pubkey_hash( l2d('1.0'), '@bar', channel, self.account.ledger.address_to_hash160(address1) ) - channel_txo.generate_channel_private_key() + await channel_txo.generate_channel_private_key() channel_txo.script.generate() channel_tx = await Transaction.create([], [channel_txo], [self.account], self.account) diff --git a/tests/unit/comments/test_comment_signing.py b/tests/unit/comments/test_comment_signing.py index 9cdfd3d69..ceee8a8a2 100644 --- a/tests/unit/comments/test_comment_signing.py +++ b/tests/unit/comments/test_comment_signing.py @@ -18,31 +18,31 @@ class TestSigningComments(AsyncioTestCase): 'comment_id': hashlib.sha256(comment.encode()).hexdigest() } - def test01_successful_create_sign_and_validate_comment(self): - channel = get_channel('@BusterBluth') + async def test01_successful_create_sign_and_validate_comment(self): + channel = await get_channel('@BusterBluth') stream = get_stream('pop secret') comment = self.create_claim_comment_body('Cool stream', stream, channel) sign_comment(comment, channel) self.assertTrue(is_comment_signed_by_channel(comment, channel)) - def test02_fail_to_validate_spoofed_channel(self): - pdiddy = get_channel('@PDitty') - channel2 = get_channel('@TomHaverford') + async def test02_fail_to_validate_spoofed_channel(self): + pdiddy = await get_channel('@PDitty') + channel2 = await get_channel('@TomHaverford') stream = get_stream() comment = self.create_claim_comment_body('Woahh This is Sick!! Shout out 2 my boy Tommy H', stream, pdiddy) sign_comment(comment, channel2) self.assertFalse(is_comment_signed_by_channel(comment, pdiddy)) - def test03_successful_sign_abandon_comment(self): - rswanson = get_channel('@RonSwanson') + async def test03_successful_sign_abandon_comment(self): + rswanson = await get_channel('@RonSwanson') dsilver = get_stream('Welcome to the Pawnee, and give a big round for Ron Swanson, AKA Duke Silver') comment_body = self.create_claim_comment_body('COMPUTER, DELETE ALL VIDEOS OF RON.', dsilver, rswanson) sign_comment(comment_body, rswanson, abandon=True) self.assertTrue(is_comment_signed_by_channel(comment_body, rswanson, abandon=True)) - def test04_invalid_signature(self): - rswanson = get_channel('@RonSwanson') - jeanralphio = get_channel('@JeanRalphio') + async def test04_invalid_signature(self): + rswanson = await get_channel('@RonSwanson') + jeanralphio = await get_channel('@JeanRalphio') chair = get_stream('This is a nice chair. I made it with Mahogany wood and this electric saw') chair_comment = self.create_claim_comment_body( 'Hah. You use an electric saw? Us swansons have been making chairs with handsaws just three after birth.', diff --git a/tests/unit/wallet/test_schema_signing.py b/tests/unit/wallet/test_schema_signing.py index dbe31943e..08b61ce9d 100644 --- a/tests/unit/wallet/test_schema_signing.py +++ b/tests/unit/wallet/test_schema_signing.py @@ -21,9 +21,9 @@ def get_tx(): return Transaction().add_inputs([get_input()]) -def get_channel(claim_name='@foo'): +async def get_channel(claim_name='@foo'): channel_txo = Output.pay_claim_name_pubkey_hash(CENT, claim_name, Claim(), b'abc') - channel_txo.generate_channel_private_key() + await channel_txo.generate_channel_private_key() get_tx().add_outputs([channel_txo]) return channel_txo @@ -36,32 +36,32 @@ def get_stream(claim_name='foo'): class TestSigningAndValidatingClaim(AsyncioTestCase): - def test_successful_create_sign_and_validate(self): - channel = get_channel() + async def test_successful_create_sign_and_validate(self): + channel = await get_channel() stream = get_stream() stream.sign(channel) self.assertTrue(stream.is_signed_by(channel)) - def test_fail_to_validate_on_wrong_channel(self): + async def test_fail_to_validate_on_wrong_channel(self): stream = get_stream() - stream.sign(get_channel()) - self.assertFalse(stream.is_signed_by(get_channel())) + stream.sign(await get_channel()) + self.assertFalse(stream.is_signed_by(await get_channel())) - def test_fail_to_validate_altered_claim(self): - channel = get_channel() + async def test_fail_to_validate_altered_claim(self): + channel = await get_channel() stream = get_stream() stream.sign(channel) self.assertTrue(stream.is_signed_by(channel)) stream.claim.stream.title = 'hello' self.assertFalse(stream.is_signed_by(channel)) - def test_valid_private_key_for_cert(self): - channel = get_channel() + async def test_valid_private_key_for_cert(self): + channel = await get_channel() self.assertTrue(channel.is_channel_private_key(channel.private_key)) - def test_fail_to_load_wrong_private_key_for_cert(self): - channel = get_channel() - self.assertFalse(channel.is_channel_private_key(get_channel().private_key)) + async def test_fail_to_load_wrong_private_key_for_cert(self): + channel = await get_channel() + self.assertFalse(channel.is_channel_private_key((await get_channel()).private_key)) class TestValidatingOldSignatures(AsyncioTestCase):