forked from LBRYCommunity/lbry-sdk
Merge pull request #2953 from lbryio/ecdsa-executor
fix channel key generation blocking globally
This commit is contained in:
commit
4e4148fc1c
7 changed files with 37 additions and 32 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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.',
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in a new issue