Skip to content
Snippets Groups Projects
Commit 8bd0c7c9 authored by Moul's avatar Moul
Browse files

[mod] #173: Make Transaction multi-sign by default

Store SigningKey and Signature arguments/attributes in Lists.
Overwrite Document.{sign(),check_signature()} as undefined.

Disable pylint error at Transaction class scope:
https://stackoverflow.com/a/22224042
Because of NotImplementedError exception, not happening with Exception
parent 53affdfe
No related branches found
No related tags found
No related merge requests found
......@@ -467,6 +467,7 @@ class Unlock:
TransactionType = TypeVar("TransactionType", bound="Transaction")
# pylint: disable=W0223
class Transaction(Document):
"""
.. note:: A transaction document is specified by the following format :
......@@ -549,7 +550,7 @@ class Transaction(Document):
outputs: List[OutputSource],
comment: str,
time: Optional[int] = None,
signing_key: SigningKey = None,
signing_keys: Optional[List[SigningKey]] = None,
version: int = VERSION,
currency: str = G1_CURRENCY_CODENAME,
) -> None:
......@@ -564,7 +565,7 @@ class Transaction(Document):
:param outputs: List of OutputSource instances
:param comment: Comment field
:param time: time when the transaction enters the blockchain
:param signing_key: SigningKey instance to sign the document (default=None)
:param signing_keys: SigningKey instance to sign the document (default=None)
:param version: Document version (default=transaction.VERSION)
:param currency: Currency codename (default=constants.CURRENCY_CODENAME_G1)
"""
......@@ -579,8 +580,8 @@ class Transaction(Document):
self.time = time
self.signatures: List[str] = list()
if signing_key is not None:
self.sign(signing_key)
if signing_keys is not None:
self.multi_sign(signing_keys)
def __eq__(self, other: Any) -> bool:
"""
......@@ -591,7 +592,6 @@ class Transaction(Document):
return (
self.version == other.version
and self.currency == other.currency
and self.signature == other.signature
and self.signatures == other.signatures
and self.blockstamp == other.blockstamp
and self.locktime == other.locktime
......@@ -608,7 +608,6 @@ class Transaction(Document):
(
self.version,
self.currency,
self.signature,
self.signatures,
self.blockstamp,
self.locktime,
......@@ -744,10 +743,7 @@ Comment: {comment}
)
# return transaction with signatures
if len(signatures) > 1:
transaction.signatures = signatures
else:
transaction.signature = signatures[0]
return transaction
@classmethod
......@@ -837,11 +833,7 @@ Comment: {comment}
)
# return transaction with signatures
if len(signatures) > 1:
transaction.signatures = signatures
else:
transaction.signature = signatures[0]
return transaction
def raw(self) -> str:
......@@ -917,9 +909,6 @@ Currency: {1}
doc += "{0}\n".format(o.inline())
if self.comment != "":
doc += "{0}\n".format(self.comment)
if self.signature is not None:
doc += "{0}\n".format(self.signature)
else:
for signature in self.signatures:
doc += "{0}\n".format(signature)
......@@ -931,25 +920,22 @@ Currency: {1}
:return:
"""
if self.signature is None and len(self.signatures) == 0:
if not self.signatures:
raise MalformedDocumentError("No signature, can not create raw format")
raw = self.raw()
if self.signature is not None:
signed_raw = raw + self.signature + "\n"
else:
signed_raw = raw
signed_raw = self.raw()
for signature in self.signatures:
signed_raw += "{0}\n".format(signature)
signed_raw += f"{signature}\n"
return signed_raw
def sign(self, key: SigningKey) -> None:
raise NotImplementedError("sign() is not implemented, use multi_sign([key])")
def multi_sign(self, keys: List[SigningKey]) -> None:
"""
Sign the current document with multiple keys
Warning : current signatures will be replaced with the new ones.
:param keys: List of libnacl keys instance
"""
self.signatures = list()
......@@ -958,6 +944,11 @@ Currency: {1}
logging.debug("Signature : \n%s", signature.decode("ascii"))
self.signatures.append(signature.decode("ascii"))
def check_signature(self, pubkey: str):
raise NotImplementedError(
"check_signature() is not implemented, use check_signatures([pubkey])"
)
def check_signatures(self, pubkeys: List[str]):
"""
Check if the signatures matches the pubkeys
......@@ -966,7 +957,7 @@ Currency: {1}
:return:
"""
if len(self.signatures) == 0:
if not self.signatures:
raise Exception("No signatures, can not check signatures")
if len(self.signatures) != len(pubkeys):
......@@ -1000,7 +991,7 @@ class SimpleTransaction(Transaction):
outputs: List[OutputSource],
comment: str,
time: int = 0,
signing_key: SigningKey = None,
signing_keys: Optional[List[SigningKey]] = None,
version: int = VERSION,
currency: str = G1_CURRENCY_CODENAME,
) -> None:
......@@ -1015,7 +1006,7 @@ class SimpleTransaction(Transaction):
:param outputs: List of OutputSource instances
:param comment: Comment field
:param time: time when the transaction enters the blockchain (default=0)
:param signing_key: SigningKey instance to sign the document (default=None)
:param signing_keys: SigningKey instance to sign the document (default=None)
:param version: Document version (default=transaction.VERSION)
:param currency: Currency codename (default=constants.CURRENCY_CODENAME_G1)
"""
......@@ -1028,7 +1019,7 @@ class SimpleTransaction(Transaction):
outputs,
comment,
time=time,
signing_key=signing_key,
signing_keys=signing_keys,
version=version,
currency=currency,
)
......
......@@ -15,6 +15,7 @@
import getpass
import urllib
from typing import List
from duniterpy.api import bma
from duniterpy.api.client import Client
......@@ -42,7 +43,7 @@ def get_transaction_document(
source: dict,
from_pubkey: str,
to_pubkey: str,
signing_key: SigningKey,
signing_keys: List[SigningKey],
) -> Transaction:
"""
Return a Transaction document
......@@ -96,7 +97,7 @@ def get_transaction_document(
unlocks=unlocks,
outputs=outputs,
comment="",
signing_key=signing_key,
signing_keys=signing_keys,
currency=current_block["currency"],
)
......@@ -142,7 +143,7 @@ def send_transaction():
# create the transaction document
transaction = get_transaction_document(
current_block, source, pubkey_from, pubkey_to, key
current_block, source, pubkey_from, pubkey_to, [key]
)
# send the Transaction document to the node
......
......@@ -147,4 +147,4 @@ Solde huile Millepertuis
rgjOmzFH5h+hkDbJLk1b88X7Z83HMgTa5rBckeMSdF/yZtItN3zMn09MphcXjffdrKcK+MebwoisLJqV+jXrDg==
"""
tx = Transaction.from_compact(transaction_document, "g1")
self.assertTrue(tx.check_signature(tx.issuers[0]))
self.assertTrue(tx.check_signatures(tx.issuers))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment