from_dict() now also handles from_seed()
This commit is contained in:
parent
e996717b60
commit
d4107600a5
4 changed files with 84 additions and 72 deletions
|
@ -92,29 +92,35 @@ class TestHierarchicalDeterministicAccount(unittest.TestCase):
|
|||
|
||||
@defer.inlineCallbacks
|
||||
def test_generate_account_from_seed(self):
|
||||
account = self.ledger.account_class.from_seed(
|
||||
self.ledger,
|
||||
"carbon smart garage balance margin twelve chest sword toast envelope bottom stomach ab"
|
||||
"sent", "torba", {'name': 'deterministic-chain', 'receiving_gap': 3, 'change_gap': 2}
|
||||
account = self.ledger.account_class.from_dict(
|
||||
self.ledger, {
|
||||
"seed": "carbon smart garage balance margin twelve chest sword "
|
||||
"toast envelope bottom stomach absent",
|
||||
"address_generator": {
|
||||
'name': 'deterministic-chain',
|
||||
'receiving': {'gap': 3, 'maximum_uses_per_address': 1},
|
||||
'change': {'gap': 2, 'maximum_uses_per_address': 1}
|
||||
}
|
||||
}
|
||||
)
|
||||
self.assertEqual(
|
||||
account.private_key.extended_key_string(),
|
||||
'xprv9s21ZrQH143K2dyhK7SevfRG72bYDRNv25yKPWWm6dqApNxm1Zb1m5gGcBWYfbsPjTr2v5joit8Af2Zp5P'
|
||||
'6yz3jMbycrLrRMpeAJxR8qDg8'
|
||||
'xprv9s21ZrQH143K3TsAz5efNV8K93g3Ms3FXcjaWB9fVUsMwAoE3ZT4vYymkp5BxK'
|
||||
'Kfnpz8J6sHDFriX1SnpvjNkzcks8XBnxjGLS83BTyfpna'
|
||||
)
|
||||
self.assertEqual(
|
||||
account.public_key.extended_key_string(),
|
||||
'xpub661MyMwAqRbcF84AR8yfHoMzf4S2ct6mPJtvBtvNeyN9hBHuZ6uGJszkTSn5fQUCdz3XU17eBzFeAUwV6f'
|
||||
'iW44g14WF52fYC5J483wqQ5ZP'
|
||||
'xpub661MyMwAqRbcFwwe67Bfjd53h5WXmKm6tqfBJZZH3pQLoy8Nb6mKUMJFc7UbpV'
|
||||
'NzmwFPN2evn3YHnig1pkKVYcvCV8owTd2yAcEkJfCX53g'
|
||||
)
|
||||
address = yield account.receiving.ensure_address_gap()
|
||||
self.assertEqual(address[0], '1PmX9T3sCiDysNtWszJa44SkKcpGc2NaXP')
|
||||
self.assertEqual(address[0], '1CDLuMfwmPqJiNk5C2Bvew6tpgjAGgUk8J')
|
||||
|
||||
private_key = yield self.ledger.get_private_key_for_address('1PmX9T3sCiDysNtWszJa44SkKcpGc2NaXP')
|
||||
private_key = yield self.ledger.get_private_key_for_address('1CDLuMfwmPqJiNk5C2Bvew6tpgjAGgUk8J')
|
||||
self.assertEqual(
|
||||
private_key.extended_key_string(),
|
||||
'xprv9xNEfQ296VTRaEUDZ8oKq74xw2U6kpj486vFUB4K1wT9U25GX4UwuzFgJN1YuRrqkQ5TTwCpkYnjNpSoH'
|
||||
'SBaEigNHPkoeYbuPMRo6mRUjxg'
|
||||
'xprv9xV7rhbg6M4yWrdTeLorz3Q1GrQb4aQzzGWboP3du7W7UUztzNTUrEYTnDfz7o'
|
||||
'ptBygDxXYRppyiuenJpoBTgYP2C26E1Ah5FEALM24CsWi'
|
||||
)
|
||||
|
||||
invalid_key = yield self.ledger.get_private_key_for_address('BcQjRlhDOIrQez1WHfz3whnB33Bp34sUgX')
|
||||
|
@ -122,7 +128,7 @@ class TestHierarchicalDeterministicAccount(unittest.TestCase):
|
|||
|
||||
self.assertEqual(
|
||||
hexlify(private_key.wif()),
|
||||
b'1cc27be89ad47ef932562af80e95085eb0ab2ae3e5c019b1369b8b05ff2e94512f01'
|
||||
b'1c01ae1e4c7d89e39f6d3aa7792c097a30ca7d40be249b6de52c81ec8cf9aab48b01'
|
||||
)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
|
@ -134,11 +140,11 @@ class TestHierarchicalDeterministicAccount(unittest.TestCase):
|
|||
"h absent",
|
||||
'encrypted': False,
|
||||
'private_key':
|
||||
'xprv9s21ZrQH143K2dyhK7SevfRG72bYDRNv25yKPWWm6dqApNxm1Zb1m5gGcBWYfbsPjTr2v5joit8Af2Zp5P'
|
||||
'6yz3jMbycrLrRMpeAJxR8qDg8',
|
||||
'xprv9s21ZrQH143K3TsAz5efNV8K93g3Ms3FXcjaWB9fVUsMwAoE3ZT4vYymkp'
|
||||
'5BxKKfnpz8J6sHDFriX1SnpvjNkzcks8XBnxjGLS83BTyfpna',
|
||||
'public_key':
|
||||
'xpub661MyMwAqRbcF84AR8yfHoMzf4S2ct6mPJtvBtvNeyN9hBHuZ6uGJszkTSn5fQUCdz3XU17eBzFeAUwV6f'
|
||||
'iW44g14WF52fYC5J483wqQ5ZP',
|
||||
'xpub661MyMwAqRbcFwwe67Bfjd53h5WXmKm6tqfBJZZH3pQLoy8Nb6mKUMJFc7'
|
||||
'UbpVNzmwFPN2evn3YHnig1pkKVYcvCV8owTd2yAcEkJfCX53g',
|
||||
'address_generator': {
|
||||
'name': 'deterministic-chain',
|
||||
'receiving': {'gap': 5, 'maximum_uses_per_address': 2},
|
||||
|
@ -244,20 +250,23 @@ class TestSingleKeyAccount(unittest.TestCase):
|
|||
|
||||
@defer.inlineCallbacks
|
||||
def test_generate_account_from_seed(self):
|
||||
account = self.ledger.account_class.from_seed(
|
||||
self.ledger,
|
||||
"carbon smart garage balance margin twelve chest sword toast envelope bottom stomach ab"
|
||||
"sent", "torba", {'name': 'single-address'}
|
||||
account = self.ledger.account_class.from_dict(
|
||||
self.ledger, {
|
||||
"seed":
|
||||
"carbon smart garage balance margin twelve chest sword toas"
|
||||
"t envelope bottom stomach absent",
|
||||
'address_generator': {'name': 'single-address'}
|
||||
}
|
||||
)
|
||||
self.assertEqual(
|
||||
account.private_key.extended_key_string(),
|
||||
'xprv9s21ZrQH143K2dyhK7SevfRG72bYDRNv25yKPWWm6dqApNxm1Zb1m5gGcBWYfbsPjTr2v5joit8Af2Zp5P'
|
||||
'6yz3jMbycrLrRMpeAJxR8qDg8'
|
||||
'xprv9s21ZrQH143K3TsAz5efNV8K93g3Ms3FXcjaWB9fVUsMwAoE3ZT4vYymkp'
|
||||
'5BxKKfnpz8J6sHDFriX1SnpvjNkzcks8XBnxjGLS83BTyfpna',
|
||||
)
|
||||
self.assertEqual(
|
||||
account.public_key.extended_key_string(),
|
||||
'xpub661MyMwAqRbcF84AR8yfHoMzf4S2ct6mPJtvBtvNeyN9hBHuZ6uGJszkTSn5fQUCdz3XU17eBzFeAUwV6f'
|
||||
'iW44g14WF52fYC5J483wqQ5ZP'
|
||||
'xpub661MyMwAqRbcFwwe67Bfjd53h5WXmKm6tqfBJZZH3pQLoy8Nb6mKUMJFc7'
|
||||
'UbpVNzmwFPN2evn3YHnig1pkKVYcvCV8owTd2yAcEkJfCX53g',
|
||||
)
|
||||
address = yield account.receiving.ensure_address_gap()
|
||||
self.assertEqual(address[0], account.public_key.address)
|
||||
|
@ -265,8 +274,8 @@ class TestSingleKeyAccount(unittest.TestCase):
|
|||
private_key = yield self.ledger.get_private_key_for_address(address[0])
|
||||
self.assertEqual(
|
||||
private_key.extended_key_string(),
|
||||
'xprv9s21ZrQH143K2dyhK7SevfRG72bYDRNv25yKPWWm6dqApNxm1Zb1m5gGcBWYfbsPjTr2v5joit8Af2Zp5P'
|
||||
'6yz3jMbycrLrRMpeAJxR8qDg8'
|
||||
'xprv9s21ZrQH143K3TsAz5efNV8K93g3Ms3FXcjaWB9fVUsMwAoE3ZT4vYymkp'
|
||||
'5BxKKfnpz8J6sHDFriX1SnpvjNkzcks8XBnxjGLS83BTyfpna',
|
||||
)
|
||||
|
||||
invalid_key = yield self.ledger.get_private_key_for_address('BcQjRlhDOIrQez1WHfz3whnB33Bp34sUgX')
|
||||
|
@ -274,7 +283,7 @@ class TestSingleKeyAccount(unittest.TestCase):
|
|||
|
||||
self.assertEqual(
|
||||
hexlify(private_key.wif()),
|
||||
b'1c2423f3dc6087d9683f73a684935abc0ccd8bc26370588f56653128c6a6f0bf7c01'
|
||||
b'1c92caa0ef99bfd5e2ceb73b66da8cd726a9370be8c368d448a322f3c5b23aaab901'
|
||||
)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
|
@ -286,11 +295,11 @@ class TestSingleKeyAccount(unittest.TestCase):
|
|||
"h absent",
|
||||
'encrypted': False,
|
||||
'private_key':
|
||||
'xprv9s21ZrQH143K2dyhK7SevfRG72bYDRNv25yKPWWm6dqApNxm1Zb1m5gGcBWYfbsPjTr2v5joit8Af2Zp5P'
|
||||
'6yz3jMbycrLrRMpeAJxR8qDg8',
|
||||
'xprv9s21ZrQH143K3TsAz5efNV8K93g3Ms3FXcjaWB9fVUsMwAoE3ZT4vYymkp'
|
||||
'5BxKKfnpz8J6sHDFriX1SnpvjNkzcks8XBnxjGLS83BTyfpna',
|
||||
'public_key':
|
||||
'xpub661MyMwAqRbcF84AR8yfHoMzf4S2ct6mPJtvBtvNeyN9hBHuZ6uGJszkTSn5fQUCdz3XU17eBzFeAUwV6f'
|
||||
'iW44g14WF52fYC5J483wqQ5ZP',
|
||||
'xpub661MyMwAqRbcFwwe67Bfjd53h5WXmKm6tqfBJZZH3pQLoy8Nb6mKUMJFc7'
|
||||
'UbpVNzmwFPN2evn3YHnig1pkKVYcvCV8owTd2yAcEkJfCX53g',
|
||||
'address_generator': {'name': 'single-address'}
|
||||
}
|
||||
|
||||
|
|
|
@ -141,10 +141,12 @@ class TestTransactionSigning(unittest.TestCase):
|
|||
|
||||
@defer.inlineCallbacks
|
||||
def test_sign(self):
|
||||
account = self.ledger.account_class.from_seed(
|
||||
self.ledger,
|
||||
u"carbon smart garage balance margin twelve chest sword toast envelope bottom stomach ab"
|
||||
u"sent", u"torba", {}
|
||||
account = self.ledger.account_class.from_dict(
|
||||
self.ledger, {
|
||||
"seed": "carbon smart garage balance margin twelve chest sword "
|
||||
"toast envelope bottom stomach absent"
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
yield account.ensure_address_gap()
|
||||
|
@ -160,10 +162,11 @@ class TestTransactionSigning(unittest.TestCase):
|
|||
|
||||
yield tx.sign([account])
|
||||
|
||||
print(hexlify(tx.inputs[0].script.values['signature']))
|
||||
self.assertEqual(
|
||||
hexlify(tx.inputs[0].script.values['signature']),
|
||||
b'304402203d463519290d06891e461ea5256c56097ccdad53379b1bb4e51ec5abc6e9fd02022034ed15b9'
|
||||
b'd7c678716c4aa7c0fd26c688e8f9db8075838f2839ab55d551b62c0a01'
|
||||
b'304402205a1df8cd5d2d2fa5934b756883d6c07e4f83e1350c740992d47a12422'
|
||||
b'226aaa202200098ac8675827aea2b0d6f0e49566143a95d523e311d342172cd99e2021e47cb01'
|
||||
)
|
||||
|
||||
|
||||
|
@ -173,10 +176,11 @@ class TransactionIOBalancing(unittest.TestCase):
|
|||
def setUp(self):
|
||||
self.ledger = ledger_class({'db': ledger_class.database_class(':memory:')})
|
||||
yield self.ledger.db.start()
|
||||
self.account = self.ledger.account_class.from_seed(
|
||||
self.ledger,
|
||||
u"carbon smart garage balance margin twelve chest sword toast envelope bottom stomach ab"
|
||||
u"sent", u"torba", {}
|
||||
self.account = self.ledger.account_class.from_dict(
|
||||
self.ledger, {
|
||||
"seed": "carbon smart garage balance margin twelve chest sword "
|
||||
"toast envelope bottom stomach absent"
|
||||
}
|
||||
)
|
||||
|
||||
addresses = yield self.account.ensure_address_gap()
|
||||
|
|
|
@ -39,11 +39,11 @@ class TestWalletCreation(unittest.TestCase):
|
|||
"h absent",
|
||||
'encrypted': False,
|
||||
'private_key':
|
||||
'xprv9s21ZrQH143K2dyhK7SevfRG72bYDRNv25yKPWWm6dqApNxm1Zb1m5gGcBWYfbsPjTr2v5joit8Af2Zp5P'
|
||||
'6yz3jMbycrLrRMpeAJxR8qDg8',
|
||||
'xprv9s21ZrQH143K3TsAz5efNV8K93g3Ms3FXcjaWB9fVUsMwAoE3Z'
|
||||
'T4vYymkp5BxKKfnpz8J6sHDFriX1SnpvjNkzcks8XBnxjGLS83BTyfpna',
|
||||
'public_key':
|
||||
'xpub661MyMwAqRbcF84AR8yfHoMzf4S2ct6mPJtvBtvNeyN9hBHuZ6uGJszkTSn5fQUCdz3XU17eBzFeAUwV6f'
|
||||
'iW44g14WF52fYC5J483wqQ5ZP',
|
||||
'xpub661MyMwAqRbcFwwe67Bfjd53h5WXmKm6tqfBJZZH3pQLoy8Nb6'
|
||||
'mKUMJFc7UbpVNzmwFPN2evn3YHnig1pkKVYcvCV8owTd2yAcEkJfCX53g',
|
||||
'address_generator': {
|
||||
'name': 'deterministic-chain',
|
||||
'receiving': {'gap': 17, 'maximum_uses_per_address': 3},
|
||||
|
|
|
@ -211,20 +211,12 @@ class BaseAccount:
|
|||
ledger.add_account(self)
|
||||
|
||||
@classmethod
|
||||
def generate(cls, ledger: 'baseledger.BaseLedger', password: str, address_generator: dict = None):
|
||||
seed = cls.mnemonic_class().make_seed()
|
||||
return cls.from_seed(ledger, seed, password, address_generator or {})
|
||||
|
||||
@classmethod
|
||||
def from_seed(cls, ledger: 'baseledger.BaseLedger', seed: str, password: str, address_generator: dict):
|
||||
private_key = cls.get_private_key_from_seed(ledger, seed, password)
|
||||
return cls(
|
||||
ledger=ledger, name='Account #{}'.format(private_key.public_key.address),
|
||||
seed=seed, encrypted=False,
|
||||
private_key=private_key,
|
||||
public_key=private_key.public_key,
|
||||
address_generator=address_generator
|
||||
)
|
||||
def generate(cls, ledger: 'baseledger.BaseLedger', name: str = None, address_generator: dict = None):
|
||||
return cls.from_dict(ledger, {
|
||||
'name': name,
|
||||
'seed': cls.mnemonic_class().make_seed(),
|
||||
'address_generator': address_generator or {}
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def get_private_key_from_seed(cls, ledger: 'baseledger.BaseLedger', seed: str, password: str):
|
||||
|
@ -234,23 +226,30 @@ class BaseAccount:
|
|||
|
||||
@classmethod
|
||||
def from_dict(cls, ledger: 'baseledger.BaseLedger', d: dict):
|
||||
if not d['private_key'] and not d['public_key'] and d['seed']:
|
||||
private_key = cls.get_private_key_from_seed(ledger, d['seed'], '')
|
||||
seed = d.get('seed', '')
|
||||
private_key = d.get('private_key', '')
|
||||
public_key = None
|
||||
encrypted = d.get('encrypted', False)
|
||||
if not encrypted:
|
||||
if seed:
|
||||
private_key = cls.get_private_key_from_seed(ledger, seed, '')
|
||||
public_key = private_key.public_key
|
||||
elif not d['encrypted'] and d['private_key']:
|
||||
private_key = from_extended_key_string(ledger, d['private_key'])
|
||||
elif private_key:
|
||||
private_key = from_extended_key_string(ledger, private_key)
|
||||
public_key = private_key.public_key
|
||||
else:
|
||||
private_key = d['private_key']
|
||||
if public_key is None:
|
||||
public_key = from_extended_key_string(ledger, d['public_key'])
|
||||
name = d.get('name')
|
||||
if not name:
|
||||
name = 'Account #{}'.format(public_key.address)
|
||||
return cls(
|
||||
ledger=ledger,
|
||||
name=d['name'],
|
||||
seed=d['seed'],
|
||||
encrypted=d['encrypted'],
|
||||
name=name,
|
||||
seed=seed,
|
||||
encrypted=encrypted,
|
||||
private_key=private_key,
|
||||
public_key=public_key,
|
||||
address_generator=d['address_generator']
|
||||
address_generator=d.get('address_generator', {})
|
||||
)
|
||||
|
||||
def to_dict(self):
|
||||
|
|
Loading…
Reference in a new issue