Skip to content

Commit

Permalink
feat(crypto,examples): adding bls multisig. (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
kehiy authored Nov 29, 2024
1 parent b86af8e commit 912e534
Show file tree
Hide file tree
Showing 12 changed files with 68 additions and 17 deletions.
18 changes: 18 additions & 0 deletions examples/example_multisig.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from pactus.crypto.bls.signature import Signature


def main() -> None:
sig1 = Signature.from_string(
"a628a8709fe00366d7150244447cc43e8637d76a20674b006b00f7a61109dab53ba5f1f66cd07219fd1e4a6bc7299d2d"
)
sig2 = Signature.from_string(
"b0d544e501408283ac11ca8ae180f0991349252cc76f9db72011ea4917eca87d4640bcf3fab7b0ab95e9b94f05113587"
)

sig3 = Signature.aggregate([sig1, sig2])

print(f"{sig3.string()}")


if __name__ == "__main__":
main()
4 changes: 3 additions & 1 deletion pactus/crypto/address.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from enum import Enum

from pactus.crypto import CryptoConfig
Expand Down Expand Up @@ -27,7 +29,7 @@ def __init__(self, address_type: AddressType, data: bytes) -> None:
self.data.extend(data)

@classmethod
def from_string(cls, text: str) -> "Address":
def from_string(cls, text: str) -> Address:
if text == TREASURY_ADDRESS_STRING:
return bytes([0])

Expand Down
8 changes: 5 additions & 3 deletions pactus/crypto/bls/private_key.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from math import ceil, log2

from pactus.crypto import CryptoConfig
Expand All @@ -18,11 +20,11 @@ def __init__(self, scalar: any) -> None:
self.scalar = scalar

@classmethod
def from_bytes(cls, buffer: bytes) -> "PrivateKey":
def from_bytes(cls, buffer: bytes) -> PrivateKey:
return cls(int.from_bytes(buffer, "big") % curve_order)

@classmethod
def key_gen(cls, ikm: bytes, key_info: bytes = b"") -> "PrivateKey":
def key_gen(cls, ikm: bytes, key_info: bytes = b"") -> PrivateKey:
salt = b"BLS-SIG-KEYGEN-SALT-"
sk = 0
while sk == 0:
Expand All @@ -35,7 +37,7 @@ def key_gen(cls, ikm: bytes, key_info: bytes = b"") -> "PrivateKey":
return cls(sk)

@classmethod
def from_string(cls, text: str) -> "PrivateKey":
def from_string(cls, text: str) -> PrivateKey:
hrp, typ, data = utils.decode_to_base256_with_type(text)

if hrp != CryptoConfig.PRIVATE_KEY_HRP:
Expand Down
4 changes: 3 additions & 1 deletion pactus/crypto/bls/public_key.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import hashlib

from ripemd.ripemd160 import ripemd160
Expand All @@ -18,7 +20,7 @@ def __init__(self, point_g2: any) -> None:
self.point_g2 = point_g2

@classmethod
def from_string(cls, text: str) -> "PublicKey":
def from_string(cls, text: str) -> PublicKey:
hrp, typ, data = utils.decode_to_base256_with_type(text)

if hrp != CryptoConfig.PUBLIC_KEY_HRP:
Expand Down
12 changes: 11 additions & 1 deletion pactus/crypto/bls/signature.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from __future__ import annotations

from .bls12_381.bls_sig_g1 import aggregate
from .bls12_381.serdesZ import deserialize, serialize

SIGNATURE_SIZE = 48
Expand All @@ -10,7 +13,7 @@ def __init__(self, point_g1: any) -> None:
self.point_g1 = point_g1

@classmethod
def from_string(cls, text: str) -> "Signature":
def from_string(cls, text: str) -> Signature:
data = bytes.fromhex(text)

if len(data) != SIGNATURE_SIZE:
Expand All @@ -21,6 +24,13 @@ def from_string(cls, text: str) -> "Signature":

return cls(point_g1)

@classmethod
def aggregate(cls, sigs: list[Signature]) -> Signature:
point_g1s = []
point_g1s.extend(sig for sig in sigs)

return cls(aggregate(point_g1s))

def raw_bytes(self) -> bytes:
return serialize(self.point_g1)

Expand Down
8 changes: 5 additions & 3 deletions pactus/crypto/ed25519/private_key.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from cryptography.hazmat.primitives.asymmetric import ed25519

from pactus.crypto import CryptoConfig
Expand All @@ -14,16 +16,16 @@ def __init__(self, scalar: ed25519.Ed25519PrivateKey) -> None:
self.scalar = scalar

@classmethod
def from_bytes(cls, buffer: bytes) -> "PrivateKey":
def from_bytes(cls, buffer: bytes) -> PrivateKey:
return cls(ed25519.Ed25519PrivateKey.from_private_bytes(buffer))

@classmethod
def key_gen(cls) -> "PrivateKey":
def key_gen(cls) -> PrivateKey:
sk = ed25519.Ed25519PrivateKey.generate()
return cls(sk)

@classmethod
def from_string(cls, text: str) -> "PrivateKey":
def from_string(cls, text: str) -> PrivateKey:
hrp, typ, data = utils.decode_to_base256_with_type(text)

if hrp != CryptoConfig.PRIVATE_KEY_HRP:
Expand Down
4 changes: 3 additions & 1 deletion pactus/crypto/ed25519/public_key.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import hashlib

from cryptography.exceptions import InvalidSignature
Expand All @@ -18,7 +20,7 @@ def __init__(self, pub: ed25519.Ed25519PublicKey) -> None:
self.pub = pub

@classmethod
def from_string(cls, text: str) -> "PublicKey":
def from_string(cls, text: str) -> PublicKey:
hrp, typ, data = utils.decode_to_base256_with_type(text)

if hrp != CryptoConfig.PUBLIC_KEY_HRP:
Expand Down
4 changes: 3 additions & 1 deletion pactus/crypto/ed25519/signature.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

SIGNATURE_SIZE = 64
SIGNATURE_TYPE_ED25519 = 3

Expand All @@ -7,7 +9,7 @@ def __init__(self, sig: bytes) -> None:
self.sig = sig

@classmethod
def from_string(cls, text: str) -> "Signature":
def from_string(cls, text: str) -> Signature:
data = bytes.fromhex(text)

if len(data) != SIGNATURE_SIZE:
Expand Down
10 changes: 7 additions & 3 deletions pactus/crypto/private_key.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
from __future__ import annotations

from abc import ABC, abstractmethod
from typing import TYPE_CHECKING

from .public_key import PublicKey
from .signature import Signature
if TYPE_CHECKING:
from .public_key import PublicKey
from .signature import Signature


class PrivateKey(ABC):
@classmethod
@abstractmethod
def from_string(cls, text: str) -> "PrivateKey":
def from_string(cls, text: str) -> PrivateKey:
pass

@abstractmethod
Expand Down
8 changes: 6 additions & 2 deletions pactus/crypto/public_key.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
from __future__ import annotations

from abc import ABC, abstractmethod
from typing import TYPE_CHECKING

from .signature import Signature
if TYPE_CHECKING:
from .signature import Signature


class PublicKey(ABC):
@classmethod
@abstractmethod
def from_string(cls, text: str) -> "PublicKey":
def from_string(cls, text: str) -> PublicKey:
pass

@abstractmethod
Expand Down
4 changes: 3 additions & 1 deletion pactus/crypto/signature.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from __future__ import annotations

from abc import ABC, abstractmethod


class Signature(ABC):
@classmethod
@abstractmethod
def from_string(cls, text: str) -> "Signature":
def from_string(cls, text: str) -> Signature:
pass

@abstractmethod
Expand Down
1 change: 1 addition & 0 deletions pactus/types/amount.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
NANO_PAC_PER_PAC = 1e9
MAX_NANO_PAC = 42e6 * NANO_PAC_PER_PAC


class Amount:
"""
Amount represents the atomic unit in the Pactus blockchain.
Expand Down

0 comments on commit 912e534

Please sign in to comment.