Skip to content

Commit

Permalink
Merge pull request #50 from ainblockchain/release/v1.3.0
Browse files Browse the repository at this point in the history
Release/v1.3.0
  • Loading branch information
platfowner authored Jul 11, 2024
2 parents 4116ea3 + 381a525 commit e9b7218
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 22 deletions.
5 changes: 3 additions & 2 deletions ain/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,15 @@ def __init__(self, privateKey: Union[bytes, str] = None):
self.address = privateToAddress(privateKeyBytes)

@classmethod
def fromMnemonic(cls, mnemonic: str, index: int = 0):
def fromMnemonic(cls, mnemonic: str, index: int = 0, chain: str = "AIN"):
"""Inits an `Account` with the given mnemonic.
Args:
mnemonic (str): The mnemonic of account.
index (int): The index of account. Defaults to 0.
chain (str): The chain to use the derivation path of. Defaults to "AIN".
"""
return cls(mnemonicToPrivatekey(mnemonic, index))
return cls(mnemonicToPrivatekey(mnemonic, index, chain))

@classmethod
def create(cls, entropy: str = None):
Expand Down
13 changes: 9 additions & 4 deletions ain/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,11 @@ def encodeVarInt(number: int) -> bytes:
SIGNED_MESSAGE_PREFIX = "AINetwork Signed Message:\n"
SIGNED_MESSAGE_PREFIX_BYTES = bytes(SIGNED_MESSAGE_PREFIX, "utf-8")
SIGNED_MESSAGE_PREFIX_LENGTH = encodeVarInt(len(SIGNED_MESSAGE_PREFIX))
# TODO(platfowner): Migrate to Ethereum HD derivation path 'm/44'/60'/0'/0/'.
AIN_HD_DERIVATION_PATH = "m/44'/412'/0'/0/" # The hardware wallet derivation path of AIN
# NOTE(platfowner): In AI Network, we decided to use both Ethereum Network's
# derivation path ("m/44'/60'/0'/0/") and
# its own ("m/44'/412'/0'/0/").
AIN_HD_DERIVATION_PATH = "m/44'/412'/0'/0/"
ETH_HD_DERIVATION_PATH = "m/44'/60'/0'/0/"

def getTimestamp() -> int:
"""Gets the current unix timestamp.
Expand Down Expand Up @@ -530,12 +533,13 @@ def generateMnemonic() -> str:
"""
return Mnemonic("english").generate()

def mnemonicToPrivatekey(mnemonic: str, index: int = 0) -> bytes:
def mnemonicToPrivatekey(mnemonic: str, index: int = 0, chain: str = "AIN") -> bytes:
"""Returns an private key with the given mnemonic.
Args:
mnemonic (str): The mnemonic of account.
index (int): The index of account. Defaults to 0.
chain (str): The chain to use the derivation path of. Defaults to "AIN".
Returns:
bytes: The private key with the given mnemonic.
Expand All @@ -548,7 +552,8 @@ def mnemonicToPrivatekey(mnemonic: str, index: int = 0) -> bytes:

seed = Mnemonic.to_seed(mnemonic)
bip32 = BIP32.from_seed(seed)
path = AIN_HD_DERIVATION_PATH + f"{index}"
prefix = AIN_HD_DERIVATION_PATH if chain == "AIN" else ETH_HD_DERIVATION_PATH
path = prefix + f"{index}"
return bip32.get_privkey_from_path(path)

# NOTE(kriii): Referenced https://github.com/bitchan/eccrypto/blob/master/index.js#L195-L258
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@
test_suite="tests",
tests_require=test_requirements,
url="https://github.com/ainblockchain/ain-py",
version="1.2.1",
version="1.3.0",
zip_safe=False,
)
12 changes: 9 additions & 3 deletions tests/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@
pk = bytes.fromhex("cf0ba8241cd1452c282c4dfa33d48e43ca34e60f5da9a2422293aa34ac14b018991d0cbc42089e4dcf3b3cc2907d51f06baed00cad7f855182572c77cbfad2b3")
sk = bytes.fromhex("cef602325bc0882591e5768e94cd94a326947e8ee5d3b02fb29d1b89a9334d99")
mnemonic = "lab diesel rule gas student bulb menu option play habit ski result"
mnemonicPrivateKey = bytes.fromhex("1fa9d5e22aa39d264c7c939f99b47696cf534bead88e4ca81da767b1ed122fa8")
mnemonicPublicKey = bytes.fromhex("6ab3e3c1d727fe72e06a6243a05ee6b1607c162a1696629ac9f19b0c1661d586554cadb17ea9d1ae246f60735f9d0e399c61139d7afef72de28809edb695990e")
mnemonicAddress = "0xe402A6296233F2DfefE35cbC3203802965B4E4d7"
# NOTE(platfowner): In AI Network, we decided to use both Ethereum Network's
# derivation path ("m/44'/60'/0'/0/") and
# its own ("m/44'/412'/0'/0/").
mnemonicPrivateKeyAin = bytes.fromhex("1fa9d5e22aa39d264c7c939f99b47696cf534bead88e4ca81da767b1ed122fa8")
mnemonicPublicKeyAin = bytes.fromhex("6ab3e3c1d727fe72e06a6243a05ee6b1607c162a1696629ac9f19b0c1661d586554cadb17ea9d1ae246f60735f9d0e399c61139d7afef72de28809edb695990e")
mnemonicAddressAin = "0xe402A6296233F2DfefE35cbC3203802965B4E4d7"
mnemonicPrivateKeyEth = bytes.fromhex("6819573717d78a332c67460c9f6d4ed8cc72457620646ba365673177a7aa34dd")
mnemonicPublicKeyEth = bytes.fromhex("98cea6be654001ec6c47cd13dd7e193fc82b69954a2726949cbcc724088081657b51b12b2bfbd6055c060a86d4b6e189faa44a0e43157503f78e929f01cd7742")
mnemonicAddressEth = "0xCb6D24618842a9dE0a1f73Ab55DEB301D811ad13"
checksumAddresses = [
"0x21fE266480080535b0CCe687669e5DBe13f42559",
"0x32F9c01ab1247C9366C8A22B6929eB0A905dBBd1",
Expand Down
2 changes: 1 addition & 1 deletion tests/snapshots/snap_test_ain.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@
}
}

snapshots['TestDatabase::test03GetProofHash 1'] = '0x88496dfee3566db91f487aa4cbf69a0c42a3e2a5d0a65bfd4897d699e8734785'
snapshots['TestDatabase::test03GetProofHash 1'] = '0x596d0fd28fd56eea0e286985a17e8b1374b7a7557539fd137dcdea0187da6956'

snapshots['TestDatabase::test03GetStateInfo 1'] = {
'#num_children': 1,
Expand Down
23 changes: 16 additions & 7 deletions tests/test_ain_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,26 @@
from ain.utils import *
from .data import (
mnemonic,
mnemonicPrivateKey,
mnemonicPublicKey,
mnemonicAddress,
mnemonicPrivateKeyAin,
mnemonicPublicKeyAin,
mnemonicAddressAin,
mnemonicPrivateKeyEth,
mnemonicPublicKeyEth,
mnemonicAddressEth,
)

class TestAccount(TestCase):
def testAccountFromMnemonic(self):
def testAccountFromMnemonicAin(self):
account = Account.fromMnemonic(mnemonic)
self.assertEqual(account.private_key, mnemonicPrivateKey.hex())
self.assertEqual(account.public_key, mnemonicPublicKey.hex())
self.assertEqual(account.address, mnemonicAddress)
self.assertEqual(account.private_key, mnemonicPrivateKeyAin.hex())
self.assertEqual(account.public_key, mnemonicPublicKeyAin.hex())
self.assertEqual(account.address, mnemonicAddressAin)

def testAccountFromMnemonicEth(self):
account = Account.fromMnemonic(mnemonic, 0, "ETH")
self.assertEqual(account.private_key, mnemonicPrivateKeyEth.hex())
self.assertEqual(account.public_key, mnemonicPublicKeyEth.hex())
self.assertEqual(account.address, mnemonicAddressEth)

def testAccountCreateFromEntropyNone(self):
account = Account.create()
Expand Down
13 changes: 9 additions & 4 deletions tests/test_ain_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
pk,
sk,
mnemonic,
mnemonicPrivateKey,
mnemonicPrivateKeyAin,
mnemonicPrivateKeyEth,
checksumAddresses,
message,
correctSignature,
Expand Down Expand Up @@ -477,9 +478,13 @@ def testEcVerifySigIncorrectAddress(self):
def testEcVerifySigDifferentMessage(self):
self.assertFalse(ecVerifySig("Hello World", correctSignature, address))

class TestMnemonicToPrivatekey(TestCase):
def testMnemonicToPrivatekey(self):
self.assertEqual(mnemonicToPrivatekey(mnemonic), mnemonicPrivateKey)
class TestMnemonicToPrivatekeyAin(TestCase):
def testMnemonicToPrivatekeyAin(self):
self.assertEqual(mnemonicToPrivatekey(mnemonic), mnemonicPrivateKeyAin)

class TestMnemonicToPrivatekeyEth(TestCase):
def testMnemonicToPrivatekeyEth(self):
self.assertEqual(mnemonicToPrivatekey(mnemonic, 0, "ETH"), mnemonicPrivateKeyEth)

class TestEncryption(TestCase):
def testEncryptToDecrypt(self):
Expand Down

0 comments on commit e9b7218

Please sign in to comment.