diff --git a/duniterpy/documents/block.py b/duniterpy/documents/block.py index 70061828e4c40287d343bd3e5171ea1e345a791f..a465c4ff9bccc1cf5b0db9c00eb6cff31aed5a1e 100644 --- a/duniterpy/documents/block.py +++ b/duniterpy/documents/block.py @@ -174,7 +174,6 @@ class Block(Document): transactions: List[Transaction], inner_hash: str, nonce: int, - signature: str, ) -> None: """ Constructor @@ -205,9 +204,8 @@ class Block(Document): :param transactions: transactions documents :param inner_hash: the block hash :param nonce: the nonce value of the block - :param signature: the block signature """ - super().__init__(version, currency, [signature]) + super().__init__(version, currency) documents_versions = max( max([1] + [i.version for i in identities]), max([1] + [m.version for m in actives + leavers + joiners]), @@ -245,6 +243,7 @@ class Block(Document): self.transactions = transactions self.inner_hash = inner_hash self.nonce = nonce + self.signatures = list() @property def blockUID(self) -> BlockUID: @@ -283,7 +282,6 @@ class Block(Document): "transactions": b["transactions"], "inner_hash": b["inner_hash"], "nonce": b["nonce"], - "signature": b["signature"], } # parameters: Optional[Sequence[str]] if arguments["parameters"]: @@ -325,8 +323,11 @@ class Block(Document): Transaction.from_bma_history(currency, i) for i in arguments["transactions"] ] - # now that the arguments are ready, return the block - return cls(**arguments) + block = cls(**arguments) + + # return the block with signature + block.signatures = [b["signature"]] + return block @classmethod def from_signed_raw(cls: Type[BlockType], signed_raw: str) -> BlockType: @@ -497,7 +498,7 @@ class Block(Document): signature = Block.parse_field("Signature", lines[n]) - return cls( + block = cls( version, currency, number, @@ -524,9 +525,12 @@ class Block(Document): transactions, inner_hash, nonce, - signature, ) + # return block with signature + block.signatures = [signature] + return block + def raw(self) -> str: doc = """Version: {version} Type: Block diff --git a/duniterpy/documents/certification.py b/duniterpy/documents/certification.py index ede06b5420cc92689f7df497488d161aea22447a..c17e6c284f4b30a5c412a4ece5bd7bbf35fe21cf 100644 --- a/duniterpy/documents/certification.py +++ b/duniterpy/documents/certification.py @@ -89,7 +89,6 @@ class Certification(Document): pubkey_from: str, identity: Union[Identity, str], timestamp: BlockUID, - signature: str, ) -> None: """ Constructor @@ -99,9 +98,8 @@ class Certification(Document): :param pubkey_from: Pubkey of the certifier :param identity: Document instance of the certified identity or identity pubkey string :param timestamp: the blockuid - :param signature: the signature of the document """ - super().__init__(version, currency, [signature]) + super().__init__(version, currency) self.pubkey_from = pubkey_from self.identity = identity if isinstance(identity, Identity) else None self.pubkey_to = identity.pubkey if isinstance(identity, Identity) else identity @@ -154,15 +152,15 @@ class Certification(Document): signature = Certification.parse_field("Signature", lines[n]) identity = Identity( - version, - currency, - identity_pubkey, - identity_uid, - identity_timestamp, - identity_signature, + version, currency, identity_pubkey, identity_uid, identity_timestamp ) + identity.signatures = [identity_signature] - return cls(version, currency, pubkey_from, identity, timestamp, signature) + certification = cls(version, currency, pubkey_from, identity, timestamp) + + # return certification with signature + certification.signatures = [signature] + return certification @classmethod def from_inline( @@ -196,7 +194,11 @@ class Certification(Document): timestamp = BlockUID(blockid, blockhash) signature = cert_data.group(4) - return cls(version, currency, pubkey_from, pubkey_to, timestamp, signature) + certification = cls(version, currency, pubkey_from, pubkey_to, timestamp) + + # return certification with signature + certification.signatures = [signature] + return certification def raw(self) -> str: """ diff --git a/duniterpy/documents/document.py b/duniterpy/documents/document.py index f089032875639f47099ab9d319dfb2e92020ce45..1d9f55368a4e5988e103214d0ecc39aae9754fd0 100644 --- a/duniterpy/documents/document.py +++ b/duniterpy/documents/document.py @@ -53,20 +53,16 @@ class Document: "Signature": re_signature, } - def __init__(self, version: int, currency: str, signatures: List[str]) -> None: + def __init__(self, version: int, currency: str) -> None: """ Init Document instance :param version: Version of the Document :param currency: Name of the currency - :param signatures: List of signatures """ self.version = version self.currency = currency - if signatures: - self.signatures = [s for s in signatures if s is not None] - else: - self.signatures = [] + self.signatures: List[str] = list() @classmethod def parse_field(cls: Type[DocumentType], field_name: str, line: str) -> Any: diff --git a/duniterpy/documents/identity.py b/duniterpy/documents/identity.py index 3bc878b309ba2e560d27f36cef6e8cf04d7781bb..b59f0d9fc00889e07d1976ea73df2a0d428ed9f4 100644 --- a/duniterpy/documents/identity.py +++ b/duniterpy/documents/identity.py @@ -14,7 +14,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import re -from typing import Optional, Type, TypeVar +from typing import Type, TypeVar from ..constants import BLOCK_UID_REGEX, PUBKEY_REGEX, SIGNATURE_REGEX, UID_REGEX from .block_uid import BlockUID @@ -60,13 +60,7 @@ class Identity(Document): } def __init__( - self, - version: int, - currency: str, - pubkey: str, - uid: str, - ts: BlockUID, - signature: Optional[str], + self, version: int, currency: str, pubkey: str, uid: str, timestamp: BlockUID ) -> None: """ Create an identity document @@ -75,15 +69,12 @@ class Identity(Document): :param currency: Name of the currency :param pubkey: Public key of the account linked to the identity :param uid: Unique identifier - :param ts: Block timestamp - :param signature: Signature of the document + :param timestamp: BlockUID instance """ - if signature: - super().__init__(version, currency, [signature]) - else: - super().__init__(version, currency, []) + super().__init__(version, currency) + self.pubkey = pubkey - self.timestamp = ts + self.timestamp = timestamp self.uid = uid @classmethod @@ -102,10 +93,14 @@ class Identity(Document): raise MalformedDocumentError("Inline self certification") pubkey = selfcert_data.group(1) signature = selfcert_data.group(2) - ts = BlockUID.from_str(selfcert_data.group(3)) + blockstamp = BlockUID.from_str(selfcert_data.group(3)) uid = selfcert_data.group(4) - return cls(version, currency, pubkey, uid, ts, signature) + identity = cls(version, currency, pubkey, uid, blockstamp) + + # return identity with signature + identity.signatures = [signature] + return identity @classmethod def from_signed_raw(cls: Type[IdentityType], signed_raw: str) -> IdentityType: @@ -132,12 +127,16 @@ class Identity(Document): uid = Identity.parse_field("UniqueID", lines[n]) n += 1 - ts = BlockUID.from_str(Identity.parse_field("Timestamp", lines[n])) + blockstamp = BlockUID.from_str(Identity.parse_field("Timestamp", lines[n])) n += 1 signature = Identity.parse_field("Signature", lines[n]) - return cls(version, currency, pubkey, uid, ts, signature) + identity = cls(version, currency, pubkey, uid, blockstamp) + + # return identity with signature + identity.signatures = [signature] + return identity def raw(self) -> str: """ diff --git a/duniterpy/documents/membership.py b/duniterpy/documents/membership.py index d79c79d5c0d6de0e549ae3d7171a6ebce07153f1..2b80ec5b7c5c62b58de5b7c908f9cda14dc35ff8 100644 --- a/duniterpy/documents/membership.py +++ b/duniterpy/documents/membership.py @@ -14,7 +14,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import re -from typing import Optional, Type, TypeVar +from typing import Type, TypeVar from ..constants import BLOCK_UID_REGEX, PUBKEY_REGEX, SIGNATURE_REGEX from .block_uid import BlockUID @@ -82,7 +82,6 @@ class Membership(Document): membership_type: str, uid: str, identity_ts: BlockUID, - signature: Optional[str] = None, ) -> None: """ Create a membership document @@ -94,13 +93,8 @@ class Membership(Document): :param membership_type: "IN" or "OUT" to enter or quit the community :param uid: Unique identifier of the identity :param identity_ts: BlockUID of the identity - :param signature: Signature of the document """ - if signature: - signatures = [signature] - else: - signatures = [] - super().__init__(version, currency, signatures) + super().__init__(version, currency) self.issuer = issuer self.membership_ts = membership_ts @@ -130,20 +124,23 @@ class Membership(Document): raise MalformedDocumentError("Inline membership ({0})".format(inline)) issuer = data.group(1) signature = data.group(2) - membership_ts = BlockUID.from_str(data.group(3)) - identity_ts = BlockUID.from_str(data.group(4)) + membership_blockstamp = BlockUID.from_str(data.group(3)) + identity_blockstamp = BlockUID.from_str(data.group(4)) uid = data.group(5) - return cls( + membership = cls( version, currency, issuer, - membership_ts, + membership_blockstamp, membership_type, uid, - identity_ts, - signature, + identity_blockstamp, ) + # return membership with signature + membership.signatures = [signature] + return membership + @classmethod def from_signed_raw(cls: Type[MembershipType], signed_raw: str) -> MembershipType: """ @@ -167,7 +164,9 @@ class Membership(Document): issuer = Membership.parse_field("Issuer", lines[n]) n += 1 - membership_ts = BlockUID.from_str(Membership.parse_field("Block", lines[n])) + membership_blockstamp = BlockUID.from_str( + Membership.parse_field("Block", lines[n]) + ) n += 1 membership_type = Membership.parse_field("Membership", lines[n]) @@ -176,23 +175,28 @@ class Membership(Document): uid = Membership.parse_field("UserID", lines[n]) n += 1 - identity_ts = BlockUID.from_str(Membership.parse_field("CertTS", lines[n])) + identity_blockstamp = BlockUID.from_str( + Membership.parse_field("CertTS", lines[n]) + ) n += 1 signature = Membership.parse_field("Signature", lines[n]) n += 1 - return cls( + membership = cls( version, currency, issuer, - membership_ts, + membership_blockstamp, membership_type, uid, - identity_ts, - signature, + identity_blockstamp, ) + # return membership with signature + membership.signatures = [signature] + return membership + def raw(self) -> str: """ Return signed raw format string of the Membership instance diff --git a/duniterpy/documents/peer.py b/duniterpy/documents/peer.py index b5bb076f1d80fdcb29ab65ad2054e8320a7c4b86..b995c650e2bde805557f5930fb86323b6beee5a3 100644 --- a/duniterpy/documents/peer.py +++ b/duniterpy/documents/peer.py @@ -69,7 +69,6 @@ class Peer(Document): pubkey: str, block_uid: BlockUID, endpoints: List[Endpoint], - signature: str, ) -> None: """ Init Peer instance @@ -79,9 +78,8 @@ class Peer(Document): :param pubkey: Public key of the issuer :param block_uid: BlockUID instance timestamp :param endpoints: List of endpoints string - :param signature: Signature of the document """ - super().__init__(version, currency, [signature]) + super().__init__(version, currency) self.pubkey = pubkey self.blockUID = block_uid @@ -126,7 +124,11 @@ class Peer(Document): raise MalformedDocumentError("Peer") signature = data.group(1) - return cls(version, currency, pubkey, block_uid, endpoints, signature) + peer = cls(version, currency, pubkey, block_uid, endpoints) + + # return peer with signature + peer.signatures = [signature] + return peer def raw(self) -> str: """ @@ -163,4 +165,8 @@ Endpoints: signature = str(Peer.re_signature.match(data["signature"])) - return cls(version, currency, pubkey, block_uid, endpoints, signature) + peer = cls(version, currency, pubkey, block_uid, endpoints) + + # return peer with signature + peer.signatures = [signature] + return peer diff --git a/duniterpy/documents/revocation.py b/duniterpy/documents/revocation.py index 4efeb4236fc1f54a6ac221dcb861a6c2e1ffea40..1ea45443873e6907e3858835d4a2dc38e79c0090 100644 --- a/duniterpy/documents/revocation.py +++ b/duniterpy/documents/revocation.py @@ -61,11 +61,7 @@ class Revocation(Document): } def __init__( - self, - version: int, - currency: str, - identity: Union[Identity, str], - signature: str, + self, version: int, currency: str, identity: Union[Identity, str] ) -> None: """ Init Revocation instance @@ -73,9 +69,8 @@ class Revocation(Document): :param version: Version number :param currency: Name of the currency :param identity: Identity instance or identity pubkey - :param signature: Signature """ - super().__init__(version, currency, [signature]) + super().__init__(version, currency) self.identity = identity if isinstance(identity, Identity) else None self.pubkey = identity.pubkey if isinstance(identity, Identity) else identity @@ -101,7 +96,11 @@ class Revocation(Document): raise MalformedDocumentError("Revokation") pubkey = cert_data.group(1) signature = cert_data.group(2) - return cls(version, currency, pubkey, signature) + revocation = cls(version, currency, pubkey) + + # return revocation with signature + revocation.signatures = [signature] + return revocation @classmethod def from_signed_raw(cls: Type[RevocationType], signed_raw: str) -> RevocationType: @@ -140,16 +139,14 @@ class Revocation(Document): signature = Revocation.parse_field("Signature", lines[n]) n += 1 - identity = Identity( - version, - currency, - issuer, - identity_uid, - identity_timestamp, - identity_signature, - ) + identity = Identity(version, currency, issuer, identity_uid, identity_timestamp) + identity.signatures = [identity_signature] - return cls(version, currency, identity, signature) + revocation = cls(version, currency, identity) + + # return revocation with signature + revocation.signatures = [signature] + return revocation @staticmethod def extract_self_cert(signed_raw: str) -> Identity: @@ -183,7 +180,11 @@ class Revocation(Document): signature = Revocation.parse_field("IdtySignature", lines[n]) n += 1 - return Identity(version, currency, issuer, unique_id, timestamp, signature) + identity = Identity(version, currency, issuer, unique_id, timestamp) + + # return signed Identity + identity.signatures = [signature] + return identity def inline(self) -> str: """ diff --git a/duniterpy/documents/transaction.py b/duniterpy/documents/transaction.py index 21a4b3ebd566e0138530bcaf0d3a47375d21bfa7..054347616fae56c491ab278a26f8f4680a290442 100644 --- a/duniterpy/documents/transaction.py +++ b/duniterpy/documents/transaction.py @@ -545,7 +545,6 @@ class Transaction(Document): unlocks: List[Unlock], outputs: List[OutputSource], comment: str, - signatures: List[str], time: Optional[int] = None, ) -> None: """ @@ -561,9 +560,8 @@ class Transaction(Document): :param outputs: List of OutputSource instances :param comment: Comment field :param time: time when the transaction enters the blockchain - :param signatures: List of signatures """ - super().__init__(version, currency, signatures) + super().__init__(version, currency) self.blockstamp = blockstamp self.locktime = locktime self.issuers = issuers @@ -721,7 +719,7 @@ Comment: {comment} else: raise MalformedDocumentError("Compact TX Signatures") - return cls( + transaction = cls( version, currency, blockstamp, @@ -731,9 +729,12 @@ Comment: {comment} unlocks, outputs, comment, - signatures, ) + # return transaction with signatures + transaction.signatures = signatures + return transaction + @classmethod def from_signed_raw( cls: Type[TransactionType], raw: str, time: int = 0 @@ -807,7 +808,7 @@ Comment: {comment} signatures.append(sign) n += 1 - return cls( + transaction = cls( version, currency, blockstamp, @@ -817,10 +818,13 @@ Comment: {comment} unlocks, outputs, comment, - signatures, time, ) + # return transaction with signatures + transaction.signatures = signatures + return transaction + def raw(self) -> str: """ Return raw string format from the instance @@ -917,7 +921,6 @@ class SimpleTransaction(Transaction): unlocks: List[Unlock], outputs: List[OutputSource], comment: str, - signature: str, time: int, ) -> None: """ @@ -933,7 +936,6 @@ class SimpleTransaction(Transaction): :param outputs: List of OutputSource instances :param comment: Comment field :param time: time when the transaction enters the blockchain - :param signature: Signature """ super().__init__( version, @@ -945,7 +947,6 @@ class SimpleTransaction(Transaction): unlocks, outputs, comment, - [signature], time, ) diff --git a/duniterpy/documents/ws2p/messages.py b/duniterpy/documents/ws2p/messages.py index a5f7a90419385d7dfcafb18fb612c27be75ec351..a42803aad82002547d1ca7a9137801447aa1e91c 100644 --- a/duniterpy/documents/ws2p/messages.py +++ b/duniterpy/documents/ws2p/messages.py @@ -40,12 +40,7 @@ class HandshakeMessage(Document): :param challenge: [Optional, default=None] Big random string, typically an uuid :param signature: [Optional, default=None] Base64 encoded signature of raw formated document """ - if signature is not None: - signatures = [signature] - else: - signatures = [] - - super().__init__(self.version, currency, signatures) + super().__init__(self.version, currency) self.pubkey = pubkey @@ -56,6 +51,7 @@ class HandshakeMessage(Document): self.challenge = challenge if signature is not None: + self.signatures = [signature] # verify signature verifying_key = VerifyingKey(self.pubkey) verifying_key.verify_document(self) diff --git a/examples/save_revoke_document.py b/examples/save_revoke_document.py index 8f1ba26afdc83e691c5cda8d3e44285751717bd3..9c4596ad61ad19a653c8b5cee1f64f09d40ecd60 100644 --- a/examples/save_revoke_document.py +++ b/examples/save_revoke_document.py @@ -84,9 +84,9 @@ def get_identity_document( currency=current_block["currency"], pubkey=pubkey, uid=uid, - ts=timestamp, - signature=signature, + timestamp=timestamp, ) + identity.signatures = [signature] break return identity @@ -104,7 +104,7 @@ def get_signed_raw_revocation_document( :rtype: str """ - revocation = Revocation(PROTOCOL_VERSION, identity.currency, identity, "") + revocation = Revocation(PROTOCOL_VERSION, identity.currency, identity) key = SigningKey.from_credentials(salt, password) revocation.sign([key]) diff --git a/examples/send_certification.py b/examples/send_certification.py index b9bc7c0f832284acc5e561ad43dcae6f8fbaa10a..a14db4c970fdf39e6292ca5dafe69d16be4d98c2 100644 --- a/examples/send_certification.py +++ b/examples/send_certification.py @@ -65,9 +65,9 @@ def get_identity_document( currency=current_block["currency"], pubkey=pubkey, uid=uid, - ts=timestamp, - signature=signature, + timestamp=timestamp, ) + identity.signatures = [signature] break return identity @@ -92,7 +92,6 @@ def get_certification_document( pubkey_from=from_pubkey, identity=self_cert_document, timestamp=BlockUID(current_block["number"], current_block["hash"]), - signature="", ) diff --git a/examples/send_identity.py b/examples/send_identity.py index aa59e829b7b125f73d7588832223579c3c42da19..c777a75ec565943a0a7d453f83d6df2b854a60d4 100644 --- a/examples/send_identity.py +++ b/examples/send_identity.py @@ -56,8 +56,7 @@ def get_identity_document( currency=current_block["currency"], pubkey=key.pubkey, uid=uid, - ts=timestamp, - signature=None, + timestamp=timestamp, ) # sign document diff --git a/examples/send_transaction.py b/examples/send_transaction.py index 77462fe7f0aea02fe25c5036783ce2c206b4c196..983c17a2a8b1b5c94da41a7b77903393feed5c5c 100644 --- a/examples/send_transaction.py +++ b/examples/send_transaction.py @@ -97,7 +97,6 @@ def get_transaction_document( unlocks=unlocks, outputs=outputs, comment="", - signatures=[], ) return transaction diff --git a/tests/api/ws2p/test_ws2p.py b/tests/api/ws2p/test_ws2p.py index 209fa1f552ad03fedeabb73c2d1413b0f840f696..9461c78fff6ded921e841482e58d1e11f1d5d304 100644 --- a/tests/api/ws2p/test_ws2p.py +++ b/tests/api/ws2p/test_ws2p.py @@ -193,7 +193,6 @@ class TestWs2p(unittest.TestCase): "HgTTJLAQ5sqfknMq7yLPZbehtuLSsKj9CxWN7k8QvYJd", "lolcat", BlockUID(32, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD"), - "J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci", ) # get json string message json_document_message = document_message.get_json( diff --git a/tests/documents/test_certification.py b/tests/documents/test_certification.py index 510f832a98cc522500dd67c89c30940c4b711a06..315be00ad7dd0683b445cfed4b68ea35673f0bca 100644 --- a/tests/documents/test_certification.py +++ b/tests/documents/test_certification.py @@ -77,7 +77,8 @@ class TestCertification(unittest.TestCase): timestamp = BlockUID(32, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD") signature = "J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci" - selfcert = Identity(version, currency, issuer, uid, timestamp, signature) + selfcert = Identity(version, currency, issuer, uid, timestamp) + selfcert.signatures = [signature] result = """Version: 2 Type: Identity @@ -139,12 +140,15 @@ J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBf pubkey_to, "lolcat", BlockUID(32, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD"), - "J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci", ) + identity.signatures = [ + "J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci" + ] certification = Certification( - version, currency, pubkey_from, identity, timestamp, signature + version, currency, pubkey_from, identity, timestamp ) + certification.signatures = [signature] result = """Version: 2 Type: Certification @@ -185,9 +189,13 @@ SoKwoa8PFfCDJWZ6dNCv7XstezHcc2BbKiJgVDXv82R5zYR83nis9dShLgWJ5w48noVUHimdngzYQneN pubkey, "lolcat", BlockUID(32, "DB30D958EE5CB75186972286ED3F4686B8A1C2CD"), - "J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci", ) - revokation = Revocation(version, currency, identity, signature) + identity.signatures = [ + "J3G9oM5AKYZNLAB5Wx499w61NuUoS57JVccTShUbGpCMjCqj9yXXqNq7dyZpDWA6BxipsiaMZhujMeBfCznzyci" + ] + + revokation = Revocation(version, currency, identity) + revokation.signatures = [signature] result = """Version: 2 Type: Revocation diff --git a/tests/documents/test_transaction.py b/tests/documents/test_transaction.py index 6f0a598c786a9182b1efe3c6bc75eade3604f35c..78367187920b37efc4af3fd9bf7a5d6e0a7450b7 100644 --- a/tests/documents/test_transaction.py +++ b/tests/documents/test_transaction.py @@ -443,7 +443,6 @@ class TestTransaction(unittest.TestCase): unlocks=[Unlock(index=0, parameters=[SIGParameter(0)])], outputs=[OutputSource.from_inline(output_source_str)], comment="", - signatures=[], ) self.assertTrue(transaction.time is None) self.assertTrue(transaction.currency == "gtest")