Skip to content

refactor: eip 155 support #174

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: feat/mainsail
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions crypto/enums/constants.py

This file was deleted.

3 changes: 1 addition & 2 deletions crypto/identity/private_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from base58 import b58decode

from crypto.configuration.network import Network
from crypto.enums.constants import Constants

class PrivateKey(object):
def __init__(self, private_key: str):
Expand All @@ -26,7 +25,7 @@ def sign(self, message: bytes) -> bytes:

der = self.private_key.sign_recoverable(message_hash, hasher=None)

return bytes([der[64] + Constants.ETHEREUM_RECOVERY_ID_OFFSET.value]) + der[0:64]
return bytes([der[64]]) + der[0:64]

def to_hex(self):
"""Returns a private key in hex format
Expand Down
12 changes: 3 additions & 9 deletions crypto/transactions/builder/abstract_transaction_builder.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from crypto.configuration.network import Network
from crypto.identity.private_key import PrivateKey
from crypto.transactions.types.abstract_transaction import AbstractTransaction

Expand All @@ -9,9 +8,8 @@ def __init__(self, data: dict):
'value': 0,
'senderPublicKey': '',
'gasPrice': '5',
'gasLimit': 1_000_000,
'nonce': '1',
'network': Network.get_network().chain_id(),
'gas': 1_000_000,
'data': '',

**data,
Expand All @@ -26,8 +24,8 @@ def __str__(self):
def new(cls):
return cls({})

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

def to(self, to: str):
Expand All @@ -42,10 +40,6 @@ 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
Expand Down
25 changes: 12 additions & 13 deletions crypto/transactions/deserializer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from binascii import unhexlify
from typing import Optional
from crypto.enums.constants import Constants
from crypto.configuration.network import Network
from crypto.enums.contract_abi_type import ContractAbiType
from crypto.transactions.types.abstract_transaction import AbstractTransaction
from crypto.transactions.types.multipayment import Multipayment
Expand All @@ -26,7 +26,7 @@ def __init__(self, serialized: str):
self.serialized = unhexlify(serialized) if isinstance(serialized, str) else serialized
self.pointer = 0

self.encoded_rlp = '0x' + serialized[2:]
self.encoded_rlp = '0x' + serialized

@staticmethod
def new(serialized: str):
Expand All @@ -36,19 +36,18 @@ def deserialize(self) -> AbstractTransaction:
decoded_rlp = RlpDecoder.decode(self.encoded_rlp)

data = {
'network': Deserializer.__parse_number(decoded_rlp[0]),
'nonce': Deserializer.__parse_big_number(decoded_rlp[1]),
'gasPrice': Deserializer.__parse_number(decoded_rlp[3]),
'gas': Deserializer.__parse_number(decoded_rlp[4]),
'to': Deserializer.__parse_address(decoded_rlp[5]),
'value': Deserializer.__parse_big_number(decoded_rlp[6]),
'data': Deserializer.__parse_hex(decoded_rlp[7]),
'nonce': Deserializer.__parse_big_number(decoded_rlp[0]),
'gasPrice': Deserializer.__parse_number(decoded_rlp[1]),
'gasLimit': Deserializer.__parse_number(decoded_rlp[2]),
'to': Deserializer.__parse_address(decoded_rlp[3]),
'value': Deserializer.__parse_big_number(decoded_rlp[4]),
'data': Deserializer.__parse_hex(decoded_rlp[5]),
}

if len(decoded_rlp) == 12:
data['v'] = Deserializer.__parse_number(decoded_rlp[9]) + Constants.ETHEREUM_RECOVERY_ID_OFFSET.value
data['r'] = Deserializer.__parse_hex(decoded_rlp[10])
data['s'] = Deserializer.__parse_hex(decoded_rlp[11])
if len(decoded_rlp) >= 9:
data['v'] = Deserializer.__parse_number(decoded_rlp[6]) - (Network.get_network().chain_id() * 2 + 35)
data['r'] = Deserializer.__parse_hex(decoded_rlp[7])
data['s'] = Deserializer.__parse_hex(decoded_rlp[8])

transaction = self.__guess_transaction_from_data(data)

Expand Down
4 changes: 2 additions & 2 deletions crypto/transactions/types/abstract_transaction.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json
from typing import Optional

from crypto.enums.constants import Constants
from crypto.configuration.network import Network
from crypto.enums.contract_abi_type import ContractAbiType
from crypto.identity.address import Address
from crypto.identity.private_key import PrivateKey
Expand Down Expand Up @@ -73,7 +73,7 @@ def hash(self, skip_signature: bool) -> str:
return TransactionUtils.to_hash(self.data, skip_signature=skip_signature)

def _get_signature(self):
recover_id = int(self.data.get('v', 0)) - Constants.ETHEREUM_RECOVERY_ID_OFFSET.value
recover_id = int(self.data.get('v', 0))
r = self.data.get('r')
s = self.data.get('s')

Expand Down
2 changes: 1 addition & 1 deletion crypto/utils/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def verify(self):
signature_s = signature[32:64]
signature_v = signature[64]

signature = signature_r + signature_s + bytes([signature_v - 27])
signature = signature_r + signature_s + bytes([signature_v])

public_key = PublicKey.recover(message_hash, signature)

Expand Down
21 changes: 12 additions & 9 deletions crypto/utils/transaction_utils.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from binascii import unhexlify
import hashlib
import re

from Cryptodome.Hash import keccak
from crypto.enums.constants import Constants
from crypto.configuration.network import Network
from crypto.utils.rlp_encoder import RlpEncoder

class TransactionUtils:
Expand All @@ -19,25 +18,29 @@ def to_buffer(cls, transaction: dict, skip_signature: bool = False) -> bytes:

# Build the fields array
fields = [
cls.to_be_array(int(transaction['network'])),
cls.to_be_array(int(transaction.get('nonce', 0))),
cls.to_be_array(0),
cls.to_be_array(int(transaction['gasPrice'])),
cls.to_be_array(int(transaction['gas'])),
cls.to_be_array(int(transaction['gasLimit'])),
to,
cls.to_be_array(int(transaction.get('value', 0))),
bytes.fromhex(cls.parse_hex_from_str(transaction.get('data', ''))) if transaction.get('data') else b'',
[],
]

if not skip_signature and 'v' in transaction and 'r' in transaction and 's' in transaction:
fields.append(cls.to_be_array(int(transaction['v']) - Constants.ETHEREUM_RECOVERY_ID_OFFSET.value))
if not skip_signature and 'v' in transaction and transaction['v'] is not None and 'r' in transaction and 's' in transaction:
fields.append(cls.to_be_array(int(transaction['v']) + (Network.get_network().chain_id() * 2 + 35)))
fields.append(bytes.fromhex(transaction['r']))
fields.append(bytes.fromhex(transaction['s']))
else:
# Push chainId + 0s for r and s
fields.append(cls.to_be_array(Network.get_network().chain_id()))
fields.append(cls.to_be_array(0))
fields.append(cls.to_be_array(0))

# TODO: second signature handling

encoded = RlpEncoder.encode(fields)

hash_input = Constants.EIP_1559_PREFIX.value + encoded
hash_input = encoded

return hash_input.encode()

Expand Down
199 changes: 0 additions & 199 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,202 +37,3 @@ def passphrase():
"""Passphrase used for tests"""

return 'found lobster oblige describe ready addict body brave live vacuum display salute lizard combine gift resemble race senior quality reunion proud tell adjust angle'

@pytest.fixture
def transaction_type_0():
"""Transaction of type "transfer"
"""
data = {
"version": 1,
"network": 30,
"typeGroup": 1,
"type": 0,
"nonce": 5,
"senderPublicKey": '023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3',
"fee": 10000000,
"value": 1,
"expiration": 0,
"to": '0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A',
"signature": '95abbcadcfb4b8991392b1ce819777abd471d837ae8bfbf28f39cad4c7b2e815116622f3ceb099386ec19b781d7b38bdf008e1851a7f848bb88382f893ff85ea',
"hash": '0ba2a3bf50747a89e5527235ec9beaab055ceadedfa347e81e95ba97e5166c6b',
"serialized": "ff011e0100000000000500000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3809698000000000000010000000000000000000000b693449adda7efc015d87944eae8b7c37eb1690a95abbcadcfb4b8991392b1ce819777abd471d837ae8bfbf28f39cad4c7b2e815116622f3ceb099386ec19b781d7b38bdf008e1851a7f848bb88382f893ff85ea",
}
return data


@pytest.fixture
def transaction_type_2():
"""Transaction of type "validator registration"
"""
data = {
'version': 1,
'network': 30,
'typeGroup': 1,
'type': 2,
'nonce': 5,
'senderPublicKey': '023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3',
'fee': 2500000000,
'asset': {
'validatorPublicKey': 'a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d3141118'
},
'signature': '5a1a0dba931a1b0a9055801578109a657fd4a2551fdb42dfd24a2c3a70835648d576f1d6b76b7a1cfedb4061d877c0a0f8adb3b47c7bbcb43b1b038da6b3ab19', # noqa
'value': 0,
'hash': '89b3df28b9069b9cba26ba8a4d2b970bb7e87a37271a96a0e9e0dd831e831f8d',
'serialized': 'ff011e0100000002000500000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300f902950000000000a08058db53e2665c84a40f5152e76dd2b652125a6079130d4c315e728bcf4dd1dfb44ac26e82302331d61977d31411185a1a0dba931a1b0a9055801578109a657fd4a2551fdb42dfd24a2c3a70835648d576f1d6b76b7a1cfedb4061d877c0a0f8adb3b47c7bbcb43b1b038da6b3ab19' # noqa
}
return data


@pytest.fixture
def transaction_type_3():
"""Transaction of type "vote"
"""
data = {
"version": 1,
"network": 30,
"typeGroup": 1,
"type": 3,
"nonce": 5,
"senderPublicKey": "023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3",
"fee": 100000000,
"asset": {
"unvotes": [],
"votes": ["03f25455408f9a7e6c6a056b121e68fbda98f3511d22e9ef27b0ebaf1ef9e4eabc"]
},
"signature": "5946eea46e46026bd5feb5335ba9411fa30677c9a9a9a788065cf1e95bf2896659485fd26b78613640b1209827ce6d4587a05a4721c63e8af24d3351e1eeaa6c", # noqa
"value": 0,
"hash": "a2ff7837281cb978d6f293b46da7bb0342fe09923eede0bfbef9dd57ffee9158",
"serialized":
"ff011e0100000003000500000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300e1f50500000000000103f25455408f9a7e6c6a056b121e68fbda98f3511d22e9ef27b0ebaf1ef9e4eabc005946eea46e46026bd5feb5335ba9411fa30677c9a9a9a788065cf1e95bf2896659485fd26b78613640b1209827ce6d4587a05a4721c63e8af24d3351e1eeaa6c" # noqa
}
return data


@pytest.fixture
def transaction_type_4():
"""Transaction of type "multi signature registration"
"""
data = {
'version': 1,
'network': 30,
'typeGroup': 1,
'type': 4,
'nonce': 5,
'senderPublicKey': '023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3',
'hash': 'f140e52f89c3b782da2fc47111abc85610e784ab3a55115712fe5fb2aa061f16',
'value': 0,
'fee': 500000000,
'signature': '5cc5dc6ca87dd1b3bd24dba27e72cce6b32284821f217f1a0195ba319e3ad3b8c9bdae225da62cd52ee911e7ffecd5e4d1197421070a8c92ee57e00398cf3dcb', # noqa
'asset': {
'multiSignature': {
'publicKeys': [
"029fab3cb2f5e248ae7cbb4de646741da4d73c493b2a03ab5c71507fb2c0dcca92",
"03629f9dbf7f1e91cefa845126189816ceae357bdd1f41bd14787318a7d5b55d48",
"027941d2059f89a26d89e87d3385e261a0ede1234aaeaa487012b69d6b67962dc5",
],
'min': 2,
}
},
'signatures': [
'003eeb63ff599b2d2255127323522f0559dd9444873b08203f998515bfb107cee68edb9e393622d93913a1afdb28768d6accd2b725c75942a638719795de344156', # noqa
'017aeccd6d60ae1b6ab5121f59225fe8246d58f8cfae76deb3e492a87abe4e37f622cc07948f7c9b62c0447deef05f4960bae25354699f9d8f9ddfa4be4de04923', # noqa
'02e6df01f999919f1a6236c8ac8ce54e3e41042e14547b1aa86b44c4c05e02f1ac89a44d0ad8a5f0374b00b5285d0b9b1cb64e4212a792bf5e4775c4d761c44c9d' # noqa
],
'serialized': 'ff011e0100000004000500000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d30065cd1d00000000000203029fab3cb2f5e248ae7cbb4de646741da4d73c493b2a03ab5c71507fb2c0dcca9203629f9dbf7f1e91cefa845126189816ceae357bdd1f41bd14787318a7d5b55d48027941d2059f89a26d89e87d3385e261a0ede1234aaeaa487012b69d6b67962dc55cc5dc6ca87dd1b3bd24dba27e72cce6b32284821f217f1a0195ba319e3ad3b8c9bdae225da62cd52ee911e7ffecd5e4d1197421070a8c92ee57e00398cf3dcb003eeb63ff599b2d2255127323522f0559dd9444873b08203f998515bfb107cee68edb9e393622d93913a1afdb28768d6accd2b725c75942a638719795de344156017aeccd6d60ae1b6ab5121f59225fe8246d58f8cfae76deb3e492a87abe4e37f622cc07948f7c9b62c0447deef05f4960bae25354699f9d8f9ddfa4be4de0492302e6df01f999919f1a6236c8ac8ce54e3e41042e14547b1aa86b44c4c05e02f1ac89a44d0ad8a5f0374b00b5285d0b9b1cb64e4212a792bf5e4775c4d761c44c9d' # noqa
}
return data


@pytest.fixture
def transaction_type_6():
"""Transaction of type "multi payment"
"""
data = {
'version': 1,
'network': 30,
'typeGroup': 1,
'type': 6,
'nonce': 5,
'senderPublicKey': '023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3',
'fee': 10000000,
'value': 0,
'asset': {
'payments': [
{
'value': 100000000,
'recipientId': '0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A'
},
{
'value': 200000000,
'recipientId': '0xb693449AdDa7EFc015D87944EAE8b7C37EB1690A'
},
],
},
'signature': '220b5d1597716c63f7945da495793f6fcb9997481108e9c1e4e7b72c6ec31fe11b2015b4940938ca8979e84ec06550825b3c0a24e23fdae087173d4d74e4d8bc',
'hash': 'c42df7851d62e99ef52363b6344a7f81069e5a2e239144853990839aa4084fb3',
'serialized': 'ff011e0100000006000500000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3809698000000000000020000e1f50500000000b693449adda7efc015d87944eae8b7c37eb1690a00c2eb0b00000000b693449adda7efc015d87944eae8b7c37eb1690a220b5d1597716c63f7945da495793f6fcb9997481108e9c1e4e7b72c6ec31fe11b2015b4940938ca8979e84ec06550825b3c0a24e23fdae087173d4d74e4d8bc'
}
return data


@pytest.fixture
def transaction_type_7():
"""Transaction of type "validator resignation"
"""
data = {
'version': 1,
'network': 30,
'typeGroup': 1,
'type': 7,
'nonce': 5,
'senderPublicKey': '023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3',
'fee': 2500000000,
'value': 0,
'signature': '34ec032ec41273043cf4f809e16e0892104743fac7da1d7ff33fb75b5569cc1c59e03558ceb2f28daf1cfaec8b88ce994c2114177f4bfeca03c0b0533d58dc1f',
'hash': '4579323b640090f5a43f1b22d29082348a6f0016b2b28ad3bc44f1838647c83d',
'serialized': 'ff011e0100000007000500000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300f90295000000000034ec032ec41273043cf4f809e16e0892104743fac7da1d7ff33fb75b5569cc1c59e03558ceb2f28daf1cfaec8b88ce994c2114177f4bfeca03c0b0533d58dc1f'
}
return data


@pytest.fixture
def transaction_type_8():
"""Transaction of type "username registration"
"""
data = {
'version': 1,
'network': 30,
'typeGroup': 1,
'type': 8,
'nonce': 9,
'senderPublicKey': '023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3',
'fee': 2500000000,
'asset': {
'username': 'test_username'
},
'signature': 'd6886e48b8df120f5f51d22c00583ef9cda61c32fd578cd07812f95cca16cdf98972e7f0789221cf1e0ad8fe174f68b4b3fe57a32692c83e0f7b1bd18c9b1640', # noqa
'value': 0,
'hash': 'f6ae0049bc3b79ddac96e37ceb6dadbf311b817d70ae1613ca5a97ceba6c8d40',
'serialized': 'ff011e0100000008000900000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300f9029500000000000d746573745f757365726e616d65d6886e48b8df120f5f51d22c00583ef9cda61c32fd578cd07812f95cca16cdf98972e7f0789221cf1e0ad8fe174f68b4b3fe57a32692c83e0f7b1bd18c9b1640' # noqa
}
return data


@pytest.fixture
def transaction_type_9():
"""Transaction of type "username resignation"
"""
data = {
'version': 1,
'network': 30,
'typeGroup': 1,
'type': 9,
'nonce': 9,
'senderPublicKey': '023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d3',
'fee': 2500000000,
'value': 0,
'signature': '728c2c5d5f090e8c5dfd433bb2b15b30442cbafb9b882117f7b6f284da4093c6a96e8456f764628ec809514ac4e8b06d5450978b9b763f7d01f696b8881f702a',
'hash': '9d01eb12cb47d5acbfe0ba0aff501e24e8313e2b08ecba118bb45332903d776b',
'serialized': 'ff011e0100000009000900000000000000023efc1da7f315f3c533a4080e491f32cd4219731cef008976c3876539e1f192d300f902950000000000728c2c5d5f090e8c5dfd433bb2b15b30442cbafb9b882117f7b6f284da4093c6a96e8456f764628ec809514ac4e8b06d5450978b9b763f7d01f696b8881f702a'
}
return data
2 changes: 1 addition & 1 deletion tests/fixtures/message-sign.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"message": "Hello, world!",
"publicKey": "0243333347c8cbf4e3cbc7a96964181d02a2b0c854faa2fef86b4b8d92afcf473d",
"signature": "0e2e53409be748834cac44052817ecef569b429a0492aa6bbc0d934eb71a09547e77aeef33d45669bbcba0498149f0e2b637fe8905186e08a5410c6f2b013bb41b"
"signature": "0e2e53409be748834cac44052817ecef569b429a0492aa6bbc0d934eb71a09547e77aeef33d45669bbcba0498149f0e2b637fe8905186e08a5410c6f2b013bb400"
}
Loading