commit 5fc715cdee8c54ecb260ac256a5baccecc358e4b
parent 9cff42328d5b6c92c87a2b41bb1f4e463c39aab7
Author: SomberNight <somber.night@protonmail.com>
Date: Sun, 20 Jan 2019 15:49:42 +0100
commands: add convert_xkey for converting between {x,y,z}|{pub,prv}
Diffstat:
2 files changed, 56 insertions(+), 0 deletions(-)
diff --git a/electrum/commands.py b/electrum/commands.py
@@ -38,6 +38,7 @@ from .import util, ecc
from .util import bfh, bh2u, format_satoshis, json_decode, print_error, json_encode
from . import bitcoin
from .bitcoin import is_address, hash_160, COIN, TYPE_ADDRESS
+from . import bip32
from .i18n import _
from .transaction import Transaction, multisig_script, TxOutput
from .paymentrequest import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED
@@ -429,6 +430,16 @@ class Commands:
"""Get master private key. Return your wallet\'s master private key"""
return str(self.wallet.keystore.get_master_private_key(password))
+ @command('')
+ def convert_xkey(self, xkey, xtype):
+ """Convert xtype of a master key. e.g. xpub -> ypub"""
+ is_xprv = bip32.is_xprv(xkey)
+ if not bip32.is_xpub(xkey) and not is_xprv:
+ raise Exception('xkey should be a master public/private key')
+ _, depth, fingerprint, child_number, c, cK = bip32.deserialize_xkey(xkey, is_xprv)
+ serialize = bip32.serialize_xprv if is_xprv else bip32.serialize_xpub
+ return serialize(xtype, c, cK, depth, fingerprint, child_number)
+
@command('wp')
def getseed(self, password=None):
"""Get seed phrase. Print the generation seed of your wallet."""
diff --git a/electrum/tests/test_commands.py b/electrum/tests/test_commands.py
@@ -3,6 +3,8 @@ from decimal import Decimal
from electrum.commands import Commands, eval_bool
+from . import TestCaseForTestnet
+
class TestCommands(unittest.TestCase):
@@ -39,3 +41,46 @@ class TestCommands(unittest.TestCase):
self.assertTrue(eval_bool("True"))
self.assertTrue(eval_bool("true"))
self.assertTrue(eval_bool("1"))
+
+ def test_convert_xkey(self):
+ cmds = Commands(config=None, wallet=None, network=None)
+ xpubs = {
+ ("xpub6CCWFbvCbqF92kGwm9nV7t7RvVoQUKaq5USMdyVP6jvv1NgN52KAX6NNYCeE8Ca7JQC4K5tZcnQrubQcjJ6iixfPs4pwAQJAQgTt6hBjg11", "standard"),
+ ("ypub6X2mZGb7kWnct3U4bWa7KyCw6TwrQwaKzaxaRNPGUkJo4UVbKgUj9A2WZQbp87E2i3Js4ZV85SmQnt2BSzWjXCLzjQXMkK7egQXXVHT4eKn", "p2wpkh-p2sh"),
+ ("zpub6qs2rwG2uCL6jLfBRsMjY4JSGS6JMZZpuhUoCmH9rkgg7aJpaLeHmDgeacZQ81sx7gRfp35gY77xgAdkAgvkKS2bbkDnLDw8x8bAsuKBrvP", "p2wpkh"),
+ }
+ for xkey1, xtype1 in xpubs:
+ for xkey2, xtype2 in xpubs:
+ self.assertEqual(xkey2, cmds.convert_xkey(xkey1, xtype2))
+
+ xprvs = {
+ ("xprv9yD9r6PJmTgqpGCUf8FUkkAhNTxv4rryiFWkqb5mYQPw8aMDXUzuyJ3tgv5vUqYkdK1E6Q5jKxPss4HkMBYV4q8AfG8t7rxgyS4xQX4ndAm", "standard"),
+ ("yprvAJ3R9m4Dv9EKfZPbVV36xqGCYS7N1UrUdN2ycyyevQmpBgASn9AUbMi2i83WUkCg2x82qsgHnckRkLuK4sxVs4omXbqJhmnBFA8bo8ssinK", "p2wpkh-p2sh"),
+ ("zprvAcsgTRj94pmoWraiKqpjAvMhiQFox6qyYUZCQNsYJR9hEmyg2oL3DRNAjL16UerbSbEqbMGrFH6yddWsnaNWfJVNPwXjHgbfWtCFBgDxFkX", "p2wpkh"),
+ }
+ for xkey1, xtype1 in xprvs:
+ for xkey2, xtype2 in xprvs:
+ self.assertEqual(xkey2, cmds.convert_xkey(xkey1, xtype2))
+
+
+class TestCommandsTestnet(TestCaseForTestnet):
+
+ def test_convert_xkey(self):
+ cmds = Commands(config=None, wallet=None, network=None)
+ xpubs = {
+ ("tpubD8p5qNfjczgTGbh9qgNxsbFgyhv8GgfVkmp3L88qtRm5ibUYiDVCrn6WYfnGey5XVVw6Bc5QNQUZW5B4jFQsHjmaenvkFUgWtKtgj5AdPm9", "standard"),
+ ("upub59wfQ8qJTg6ZSuvwtR313Qdp8gP8TSBwTof5dPQ3QVsYp1N9t29Rr9TGF1pj8kAXUg3mKbmrTKasA2qmBJKb1bGUzB6ApDZpVC7LoHhyvBo", "p2wpkh-p2sh"),
+ ("vpub5UmvhoWDcMe3JD84impdFVjKJeXaQ4BSNvBJQnHvnWFRs7BP8gJzUD7QGDnK8epStKAa55NQuywR3KTKtzjbopx5rWnbQ8PJkvAzBtgaGBc", "p2wpkh"),
+ }
+ for xkey1, xtype1 in xpubs:
+ for xkey2, xtype2 in xpubs:
+ self.assertEqual(xkey2, cmds.convert_xkey(xkey1, xtype2))
+
+ xprvs = {
+ ("tprv8c83gxdVUcznP8fMx2iNUBbaQgQC7MUbBUDG3c6YU9xgt7Dn5pfcgHUeNZTAvuYmNgVHjyTzYzGWwJr7GvKCm2FkPaaJipyipbfJeB3tdPW", "standard"),
+ ("uprv8vxJzdJQdJYGERrUnPVzgGh5aeYe3yU66ajUpzzRrALZwD31LUqBJM8nPmQkvpCgnKc6VT4Z1ed4pbTfzcjDZFwMFvGjJjoD6Kix2pCwVe7", "p2wpkh-p2sh"),
+ ("vprv9FnaJHyKmz5k5j3bckHctMnakch5zbTb1hFhcPtKEAiSzJrEb8zjvQnvQyNLvircBxiuEvf7UJycht5EiK9EMVcx8Fy9techN3nbRQRFhEv", "p2wpkh"),
+ }
+ for xkey1, xtype1 in xprvs:
+ for xkey2, xtype2 in xprvs:
+ self.assertEqual(xkey2, cmds.convert_xkey(xkey1, xtype2))