diff --git a/monero/seed.py b/monero/seed.py index a3b8813..3accabc 100644 --- a/monero/seed.py +++ b/monero/seed.py @@ -30,6 +30,7 @@ # https://github.com/bigreddmachine/MoneroPy/blob/master/moneropy/mnemonic.py ch: 80cc16c39b16c55a8d052fbf7fae68644f7a5f02 # https://github.com/spesmilo/electrum/blob/master/lib/old_mnemonic.py ch:9a0aa9b4783ea03ea13c6d668e080e0cdf261c5b +from monero import address from monero import wordlists from monero import ed25519 from monero import base58 @@ -146,7 +147,7 @@ class Seed(object): def sc_reduce(self, input): integer = ed25519.decodeint(unhexlify(input)) modulo = integer % ed25519.l - return hexlify(ed25519.encodeint(modulo)) + return hexlify(ed25519.encodeint(modulo)).decode() def hex_seed(self): return self.hex @@ -162,18 +163,28 @@ class Seed(object): def public_spend_key(self): keyInt = ed25519.decodeint(unhexlify(self.secret_spend_key())) aG = ed25519.scalarmultbase(keyInt) - return hexlify(ed25519.encodepoint(aG)) + return hexlify(ed25519.encodepoint(aG)).decode() def public_view_key(self): keyInt = ed25519.decodeint(unhexlify(self.secret_view_key())) aG = ed25519.scalarmultbase(keyInt) - return hexlify(ed25519.encodepoint(aG)) + return hexlify(ed25519.encodepoint(aG)).decode() - def public_address(self): - data = str.encode("12") + self.public_spend_key() + self.public_view_key() + def public_address(self, net='mainnet'): + """Returns the master :class:`Address ` represented by the seed. + + :param net: the network, one of 'mainnet', 'testnet', 'stagenet'. Default is 'mainnet'. + + :rtype: :class:`Address ` + """ + if net not in ('mainnet', 'testnet', 'stagenet'): + raise ValueError( + "Invalid net argument. Must be one of ('mainnet', 'testnet', 'stagenet').") + netbyte = 18 if net == 'mainnet' else 53 if net == 'testnet' else 24 + data = "{:x}{:s}{:s}".format(netbyte, self.public_spend_key(), self.public_view_key()) h = keccak_256() h.update(unhexlify(data)) - checksum = str.encode(h.hexdigest()) + checksum = h.hexdigest() return base58.encode(data + checksum[0:8]) diff --git a/tests/test_seed.py b/tests/test_seed.py index cde0c84..177f39e 100644 --- a/tests/test_seed.py +++ b/tests/test_seed.py @@ -61,5 +61,31 @@ class SeedTestCase(unittest.TestCase): Seed("\\x008") self.assertEqual(ts.expected, ValueError) + + def test_keys(self): + seed = Seed("adjust mugged vaults atlas nasty mews damp toenail suddenly toxic possible "\ + "framed succeed fuzzy return demonstrate nucleus album noises peculiar virtual "\ + "rowboat inorganic jester fuzzy") + self.assertTrue(seed.validate_checksum()) + self.assertEqual( + seed.secret_spend_key(), + '482700617ba810f94035d7f4d7ccc1a29878e165b4867872b705204c85406906') + self.assertEqual( + seed.secret_view_key(), + '09ed72c713d3e9e19bef2f5204cf85f6cb25de7842aa0722abeb12697f171903') + self.assertEqual( + seed.public_spend_key(), + '4ee576f52b9c6a824a3d5c2832d117177d2bb9992507c2c78788bb8dbaf4b640') + self.assertEqual( + seed.public_view_key(), + 'e1ef99d66312ec0b16b17c66c591ab59594e21621588b63b62fa69fe615a768e') + self.assertEqual( + seed.public_address(), + '44cWztNFdAqNnycvZbUoj44vsbAEmKnx9aNgkjHdjtMsBrSeKiY8J4s2raH7EMawA2Fwo9utaRTV7Aw8EcTMNMxhH4YtKdH') + self.assertEqual( + seed.public_address(net='stagenet'), + '54pZ5jHDGmwNnycvZbUoj44vsbAEmKnx9aNgkjHdjtMsBrSeKiY8J4s2raH7EMawA2Fwo9utaRTV7Aw8EcTMNMxhH6cuARW') + + if __name__ == "__main__": unittest.main()