Skip to content

Commit 5fff385

Browse files
authored
fix: update second_sign method to use schnorr (#106)
* fix - update secondsign to use schnorr * feat - add schnorr second verify * feat - add second verify function to base.py * Update base.py * Update transaction.py * Update serializer.py * Update base.py * Update test_transfer.py * Update base.py * Update test_transfer.py
1 parent a40c15f commit 5fff385

File tree

4 files changed

+41
-4
lines changed

4 files changed

+41
-4
lines changed

crypto/transactions/builder/base.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,9 @@ def second_sign(self, passphrase):
4747
Args:
4848
passphrase (str): 2nd passphrase associated with the account sending this transaction
4949
"""
50-
message = Message.sign(self.transaction.to_bytes(skip_signature=False), passphrase)
51-
self.transaction.signSignature = message.signature
50+
msg = hashlib.sha256(self.transaction.to_bytes(False, True, False)).digest()
51+
secret = unhexlify(PrivateKey.from_passphrase(passphrase).to_hex())
52+
self.transaction.signSignature = hexlify(schnorr.bcrypto410_sign(msg, secret))
5253
self.transaction.id = self.transaction.get_id()
5354

5455
def multi_sign(self, passphrase, index):
@@ -66,6 +67,9 @@ def multi_sign(self, passphrase, index):
6667

6768
def schnorr_verify(self):
6869
return self.transaction.verify_schnorr()
70+
71+
def schnorr_verify_second(self, secondPublicKey):
72+
return self.transaction.verify_schnorr_secondsig(secondPublicKey)
6973

7074
def schnorr_verify_multisig(self):
7175
return self.transaction.verify_schnorr_multisig()

crypto/transactions/serializer.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,8 @@ def _handle_signature(self, bytes_data, skip_signature, skip_second_signature, s
9494

9595
if not skip_second_signature and self.transaction.get('secondSignature'):
9696
bytes_data += unhexlify(self.transaction['secondSignature'])
97-
elif self.transaction.get('signSignature'):
97+
if not skip_second_signature and self.transaction.get('signSignature'):
9898
bytes_data += unhexlify(self.transaction['signSignature'])
99-
10099
if not skip_multi_signature and self.transaction.get('signatures'):
101100
bytes_data += unhexlify(''.join(self.transaction['signatures']))
102101

crypto/transactions/transaction.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,15 @@ def verify_schnorr(self):
162162

163163
return is_valid
164164

165+
def verify_schnorr_secondsig(self, secondPublicKey):
166+
"""Verify the transaction. Method will raise an exception if invalid, if it's valid it will
167+
returns True
168+
"""
169+
is_valid = schnorr.b410_schnorr_verify(self.to_bytes(False, True), secondPublicKey, self.signSignature)
170+
171+
if not is_valid:
172+
raise ArkInvalidTransaction('Transaction could not be verified')
173+
165174
def verify_schnorr_multisig(self):
166175
"""Verify the multisignatures transaction. Method will raise an exception if invalid, it will
167176
returns True

tests/transactions/builder/test_transfer.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from crypto.configuration.network import set_network
22
from crypto.constants import TRANSACTION_TRANSFER, TRANSACTION_TYPE_GROUP
3+
from crypto.identity.public_key import PublicKey
34
from crypto.networks.devnet import Devnet
45
from crypto.transactions.builder.transfer import Transfer
56

@@ -27,6 +28,30 @@ def test_transfer_transaction():
2728
transaction.schnorr_verify() # if no exception is raised, it means the transaction is valid
2829

2930

31+
def test_transfer_secondsig_transaction():
32+
"""Test if a transfer transaction with second signature gets built
33+
"""
34+
transaction = Transfer(
35+
recipientId='AGeYmgbg2LgGxRW2vNNJvQ88PknEJsYizC',
36+
amount=200000000,
37+
)
38+
transaction.set_type_group(TRANSACTION_TYPE_GROUP.CORE)
39+
transaction.set_nonce(1)
40+
transaction.schnorr_sign('this is a top secret passphrase')
41+
transaction.second_sign('second top secret passphrase')
42+
transaction_dict = transaction.to_dict()
43+
44+
assert transaction_dict['nonce'] == 1
45+
assert transaction_dict['signature']
46+
assert transaction_dict['signSignature']
47+
assert transaction_dict['type'] is TRANSACTION_TRANSFER
48+
assert transaction_dict['typeGroup'] == 1
49+
assert transaction_dict['typeGroup'] == TRANSACTION_TYPE_GROUP.CORE.value
50+
51+
transaction.schnorr_verify() # if no exception is raised, it means the transaction is valid
52+
transaction.schnorr_verify_second(PublicKey.from_passphrase('second top secret passphrase')) # if no exception is raised, it means the transaction is valid
53+
54+
3055
def test_parse_signatures(transaction_type_0):
3156
"""Test if parse signature works when parsing serialized data
3257
"""

0 commit comments

Comments
 (0)