Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
alfonsobries committed Nov 29, 2024
1 parent 0a0f2ef commit 4105ebe
Show file tree
Hide file tree
Showing 16 changed files with 474 additions and 490 deletions.
11 changes: 3 additions & 8 deletions crypto/identity/private_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,9 @@ def sign(self, message: bytes) -> bytes:
Returns:
bytes: signature of the signed message
"""
from crypto.transactions.signature import Signature

signature = Signature.sign(
hexlify(message),
self
)

return signature.encode()
signature = self.private_key.sign(message)

return hexlify(signature).decode()

def to_hex(self):
"""Returns a private key in hex format
Expand Down
167 changes: 56 additions & 111 deletions crypto/transactions/builder/base.py
Original file line number Diff line number Diff line change
@@ -1,120 +1,65 @@
from binascii import hexlify, unhexlify
from typing import Optional

from crypto.configuration.fee import get_fee
from crypto.constants import TRANSACTION_TYPE_GROUP
from crypto.configuration.network import get_network
from crypto.identity.private_key import PrivateKey
from crypto.identity.public_key import PublicKey
from crypto.transactions.serializer import Serializer
from crypto.transactions.signature import Signature
from crypto.transactions.transaction import Transaction

class BaseTransactionBuilder(object):
transaction: Transaction

def __init__(self):
self.transaction = Transaction()

if hasattr(self, 'transaction_type'):
self.transaction.type = getattr(self, 'transaction_type')

if hasattr(self, 'transaction_type'):
self.transaction.fee = get_fee(getattr(self, 'transaction_type'))

if hasattr(self, 'nonce'):
self.transaction.nonce = getattr(self, 'nonce')

if hasattr(self, 'signatures'):
self.transaction.signatures = getattr(self, 'signatures')

self.transaction.typeGroup = getattr(self, 'typeGroup', int(TRANSACTION_TYPE_GROUP.CORE))
self.transaction.version = getattr(self, 'version', 1)
self.transaction.expiration = getattr(self, 'expiration', 0)
if self.transaction.type != 0:
self.transaction.amount = getattr(self, 'amount', 0)
from crypto.transactions.types.abstract_transaction import AbstractTransaction


class AbstractTransactionBuilder:
def __init__(self, data: Optional[dict] = None):
default_data = {
'value': '0',
'senderPublicKey': '',
'gasPrice': '5',
'nonce': '1',
'network': get_network()['version'],
'gasLimit': 1_000_000,
'data': '',
}
self.transaction = self.get_transaction_instance(data or default_data)

def __str__(self):
return self.to_json()

@classmethod
def new(cls, data: Optional[dict] = None):
return cls(data)

def gas_limit(self, gas_limit: int):
self.transaction.data['gasLimit'] = gas_limit
return self

def recipient_address(self, recipient_address: str):
self.transaction.data['recipientAddress'] = recipient_address
return self

def gas_price(self, gas_price: int):
self.transaction.data['gasPrice'] = gas_price
return self

def nonce(self, nonce: str):
self.transaction.data['nonce'] = nonce
return self

def network(self, network: int):
self.transaction.data['network'] = network
return self

def sign(self, passphrase: str):
keys = PrivateKey.from_passphrase(passphrase)
self.transaction.data['senderPublicKey'] = keys.public_key
self.transaction = self.transaction.sign(keys)
self.transaction.data['id'] = self.transaction.get_id()
return self

def verify(self):
return self.transaction.verify()

def to_dict(self):
return self.transaction.to_dict()

def to_json(self):
return self.transaction.to_json()

def sign(self, passphrase):
"""Sign the transaction using the given passphrase
Args:
passphrase (str): passphrase associated with the account sending this transaction
"""
self.transaction.senderPublicKey = PublicKey.from_passphrase(passphrase)

msg = self.transaction.to_bytes(False, True, False)
secret = unhexlify(PrivateKey.from_passphrase(passphrase).to_hex())
self.transaction.signature = Signature.sign(msg, secret)
self.transaction.id = self.transaction.get_id()

def second_sign(self, passphrase):
"""Sign the transaction using the given second passphrase
Args:
passphrase (str): 2nd passphrase associated with the account sending this transaction
"""
msg = self.transaction.to_bytes(False, True, False)
secret = unhexlify(PrivateKey.from_passphrase(passphrase).to_hex())
self.transaction.signSignature = Signature.sign(msg, secret)
self.transaction.id = self.transaction.get_id()

def multi_sign(self, passphrase, index):
if not self.transaction.signatures:
self.transaction.signatures = []

if self.transaction.senderPublicKey is None:
raise Exception('Sender Public Key is required for multi signature')

index = len(self.transaction.signatures) if index == -1 else index

msg = self.transaction.to_bytes()
secret = unhexlify(PrivateKey.from_passphrase(passphrase).to_hex())
signature = Signature.sign(msg, secret)

index_formatted = hex(index).replace('x', '')
self.transaction.signatures.append(index_formatted + signature)

def serialize(self, skip_signature=False, skip_second_signature=False, skip_multi_signature=False):
"""Perform AIP11 compliant serialization.
Args:
skip_signature (bool, optional): do you want to skip the signature
skip_second_signature (bool, optional): do you want to skip the 2nd signature
skip_multi_signature (bool, optional): do you want to skip multi signature
Returns:
str: Serialized string
"""
return Serializer(self.to_dict()).serialize(skip_signature, skip_second_signature, skip_multi_signature)

def schnorr_verify(self):
return self.transaction.verify_schnorr()

def verify_secondsig_schnorr(self, secondPublicKey):
return self.transaction.verify_secondsig_schnorr(secondPublicKey)

def verify_multisig_schnorr(self):
return self.transaction.verify_multisig_schnorr()

def set_nonce(self, nonce):
self.transaction.nonce = nonce

def set_amount(self, amount: int):
self.transaction.amount = amount

def set_sender_public_key(self, public_key: str):
self.transaction.senderPublicKey = public_key

def set_expiration(self, expiration: int):
self.transaction.expiration = expiration

def set_type_group(self, type_group):
if type(type_group) == int:
self.transaction.typeGroup = type_group
else:
types = {TRANSACTION_TYPE_GROUP.TEST: 0, TRANSACTION_TYPE_GROUP.CORE: 1, TRANSACTION_TYPE_GROUP.RESERVED: 1000}
self.transaction.typeGroup = types[type_group]
def get_transaction_instance(self, data: dict) -> AbstractTransaction:
raise NotImplementedError("Subclasses must implement get_transaction_instance()")
31 changes: 0 additions & 31 deletions crypto/transactions/builder/transfer.py

This file was deleted.

12 changes: 12 additions & 0 deletions crypto/transactions/builder/transfer_builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from crypto.transactions.builder.base import AbstractTransactionBuilder
from crypto.transactions.types.transfer import Transfer


class TransferBuilder(AbstractTransactionBuilder):
def value(self, value: str):
self.transaction.data['value'] = value
self.transaction.refresh_payload_data()
return self

def get_transaction_instance(self, data: dict):
return Transfer(data)
Loading

0 comments on commit 4105ebe

Please sign in to comment.