Merge pull request #2953 from lbryio/ecdsa-executor

fix channel key generation blocking globally
This commit is contained in:
Jack Robison 2020-05-11 15:16:17 -04:00 committed by GitHub
commit 4e4148fc1c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 37 additions and 32 deletions

View file

@ -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

View file

@ -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):

View file

@ -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:

View file

@ -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

View file

@ -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)

View file

@ -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.',

View file

@ -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):