From e5be93fe32d99ad5a6f7ee8843a98c0114164cf2 Mon Sep 17 00:00:00 2001
From: Moul <moul@moul.re>
Date: Thu, 24 Jun 2021 18:58:12 +0200
Subject: [PATCH] [mod] #173: Allow to pass an instance or a list of SigningKey
 and pubkey

in Transaction.{__init__(),multi_sign(),check_signatures()}
if instance: store in a list

Do not erase previous signatures when signing
To allow different key owner to sign additonally the Tx doc
---
 duniterpy/documents/transaction.py | 29 ++++++++++++++++++-----------
 examples/send_transaction.py       |  6 +++---
 2 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/duniterpy/documents/transaction.py b/duniterpy/documents/transaction.py
index d2802757..674eee6d 100644
--- a/duniterpy/documents/transaction.py
+++ b/duniterpy/documents/transaction.py
@@ -550,7 +550,7 @@ class Transaction(Document):
         outputs: List[OutputSource],
         comment: str,
         time: Optional[int] = None,
-        signing_keys: Optional[List[SigningKey]] = None,
+        signing_keys: Optional[Union[SigningKey, List[SigningKey]]] = None,
         version: int = VERSION,
         currency: str = G1_CURRENCY_CODENAME,
     ) -> None:
@@ -565,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_keys: SigningKey instance to sign the document (default=None)
+        :param signing_keys: SigningKey or list of SigningKey instances to sign the document (default=None)
         :param version: Document version (default=transaction.VERSION)
         :param currency: Currency codename (default=constants.CURRENCY_CODENAME_G1)
         """
@@ -580,7 +580,9 @@ class Transaction(Document):
         self.time = time
         self.signatures: List[str] = list()
 
-        if signing_keys is not None:
+        if isinstance(signing_keys, SigningKey):
+            signing_keys = [signing_keys]
+        if signing_keys:
             self.multi_sign(signing_keys)
 
     def __eq__(self, other: Any) -> bool:
@@ -930,15 +932,17 @@ Currency: {1}
         return signed_raw
 
     def sign(self, key: SigningKey) -> None:
-        raise NotImplementedError("sign() is not implemented, use multi_sign([key])")
+        raise NotImplementedError("sign() is not implemented, use multi_sign()")
 
-    def multi_sign(self, keys: List[SigningKey]) -> None:
+    def multi_sign(self, keys: Union[SigningKey, List[SigningKey]]) -> None:
         """
         Sign the current document with multiple keys
 
-        :param keys: List of libnacl keys instance
+        :param keys: Libnacl key or list of them
         """
-        self.signatures = list()
+        if isinstance(keys, SigningKey):
+            keys = [keys]
+
         for key in keys:
             signature = base64.b64encode(key.signature(bytes(self.raw(), "ascii")))
             logging.debug("Signature : \n%s", signature.decode("ascii"))
@@ -946,20 +950,23 @@ Currency: {1}
 
     def check_signature(self, pubkey: str):
         raise NotImplementedError(
-            "check_signature() is not implemented, use check_signatures([pubkey])"
+            "check_signature() is not implemented, use check_signatures()"
         )
 
-    def check_signatures(self, pubkeys: List[str]):
+    def check_signatures(self, pubkeys: Union[str, List[str]]):
         """
         Check if the signatures matches the pubkeys
 
-        :param pubkeys: List of Base58 public keys
+        :param pubkeys: Base58 public key or list of them
 
         :return:
         """
         if not self.signatures:
             raise Exception("No signatures, can not check signatures")
 
+        if isinstance(pubkeys, str):
+            pubkeys = [pubkeys]
+
         if len(self.signatures) != len(pubkeys):
             raise Exception("Number of pubkeys not equal to number of signatures")
 
@@ -991,7 +998,7 @@ class SimpleTransaction(Transaction):
         outputs: List[OutputSource],
         comment: str,
         time: int = 0,
-        signing_keys: Optional[List[SigningKey]] = None,
+        signing_keys: Optional[Union[SigningKey, List[SigningKey]]] = None,
         version: int = VERSION,
         currency: str = G1_CURRENCY_CODENAME,
     ) -> None:
diff --git a/examples/send_transaction.py b/examples/send_transaction.py
index d65643d0..1ddf631b 100644
--- a/examples/send_transaction.py
+++ b/examples/send_transaction.py
@@ -15,7 +15,7 @@
 
 import getpass
 import urllib
-from typing import List
+from typing import List, Union
 
 from duniterpy.api import bma
 from duniterpy.api.client import Client
@@ -43,7 +43,7 @@ def get_transaction_document(
     source: dict,
     from_pubkey: str,
     to_pubkey: str,
-    signing_keys: List[SigningKey],
+    signing_keys: Union[SigningKey, List[SigningKey]],
 ) -> Transaction:
     """
     Return a Transaction document
@@ -143,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
-- 
GitLab