From c871bf829af1df7350949386cd77d5b6e7e06e82 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Sat, 23 May 2020 18:10:04 +0200 Subject: [PATCH] refactor to parametrize with keypurpose --- .../com/sparrowwallet/drongo/KeyPurpose.java | 15 +++++++++++ .../sparrowwallet/drongo/wallet/Keystore.java | 18 ++++--------- .../sparrowwallet/drongo/wallet/Wallet.java | 21 ++++++++-------- .../drongo/wallet/WalletTest.java | 25 ++++++++++--------- 4 files changed, 44 insertions(+), 35 deletions(-) create mode 100644 src/main/java/com/sparrowwallet/drongo/KeyPurpose.java diff --git a/src/main/java/com/sparrowwallet/drongo/KeyPurpose.java b/src/main/java/com/sparrowwallet/drongo/KeyPurpose.java new file mode 100644 index 0000000..756bcbb --- /dev/null +++ b/src/main/java/com/sparrowwallet/drongo/KeyPurpose.java @@ -0,0 +1,15 @@ +package com.sparrowwallet.drongo; + +public enum KeyPurpose { + RECEIVE(0), CHANGE(1); + + private final int pathIndex; + + KeyPurpose(int pathIndex) { + this.pathIndex = pathIndex; + } + + public int getPathIndex() { + return pathIndex; + } +} diff --git a/src/main/java/com/sparrowwallet/drongo/wallet/Keystore.java b/src/main/java/com/sparrowwallet/drongo/wallet/Keystore.java index 1421124..30593dd 100644 --- a/src/main/java/com/sparrowwallet/drongo/wallet/Keystore.java +++ b/src/main/java/com/sparrowwallet/drongo/wallet/Keystore.java @@ -2,6 +2,7 @@ package com.sparrowwallet.drongo.wallet; import com.sparrowwallet.drongo.ExtendedKey; import com.sparrowwallet.drongo.KeyDerivation; +import com.sparrowwallet.drongo.KeyPurpose; import com.sparrowwallet.drongo.Utils; import com.sparrowwallet.drongo.crypto.*; @@ -103,22 +104,13 @@ public class Keystore { return new ExtendedKey(derivedKey, derivedKey.getParentFingerprint(), derivation.get(derivation.size() - 1)); } - public DeterministicKey getReceivingKey(int keyIndex) { - List receivingDerivation = List.of(extendedPublicKey.getKeyChildNumber(), new ChildNumber(0), new ChildNumber(keyIndex)); + public DeterministicKey getKey(KeyPurpose keyPurpose, int keyIndex) { + List receivingDerivation = List.of(extendedPublicKey.getKeyChildNumber(), new ChildNumber(keyPurpose.getPathIndex()), new ChildNumber(keyIndex)); return extendedPublicKey.getKey(receivingDerivation); } - public KeyDerivation getReceivingDerivation(int keyIndex) { - return getKeyDerivation().extend(new ChildNumber(0)).extend(new ChildNumber(keyIndex)); - } - - public DeterministicKey getChangeKey(int keyIndex) { - List receivingDerivation = List.of(extendedPublicKey.getKeyChildNumber(), new ChildNumber(1), new ChildNumber(keyIndex)); - return extendedPublicKey.getKey(receivingDerivation); - } - - public KeyDerivation getChangeDerivation(int keyIndex) { - return getKeyDerivation().extend(new ChildNumber(1)).extend(new ChildNumber(keyIndex)); + public KeyDerivation getDerivation(KeyPurpose keyPurpose, int keyIndex) { + return getKeyDerivation().extend(new ChildNumber(keyPurpose.getPathIndex())).extend(new ChildNumber(keyIndex)); } public boolean isValid() { diff --git a/src/main/java/com/sparrowwallet/drongo/wallet/Wallet.java b/src/main/java/com/sparrowwallet/drongo/wallet/Wallet.java index 17ebbfd..b580970 100644 --- a/src/main/java/com/sparrowwallet/drongo/wallet/Wallet.java +++ b/src/main/java/com/sparrowwallet/drongo/wallet/Wallet.java @@ -1,5 +1,6 @@ package com.sparrowwallet.drongo.wallet; +import com.sparrowwallet.drongo.KeyPurpose; import com.sparrowwallet.drongo.address.Address; import com.sparrowwallet.drongo.crypto.DeterministicKey; import com.sparrowwallet.drongo.crypto.ECKey; @@ -75,31 +76,31 @@ public class Wallet { this.keystores = keystores; } - public Address getReceivingAddress(int index) { + public Address getAddress(KeyPurpose keyPurpose, int index) { if(policyType == PolicyType.SINGLE) { Keystore keystore = getKeystores().get(0); - DeterministicKey key = keystore.getReceivingKey(index); + DeterministicKey key = keystore.getKey(keyPurpose, index); return scriptType.getAddress(key); } else if(policyType == PolicyType.MULTI) { - List pubKeys = getKeystores().stream().map(keystore -> keystore.getReceivingKey(index)).collect(Collectors.toList()); + List pubKeys = getKeystores().stream().map(keystore -> keystore.getKey(keyPurpose, index)).collect(Collectors.toList()); Script script = ScriptType.MULTISIG.getOutputScript(defaultPolicy.getNumSignaturesRequired(), pubKeys); return scriptType.getAddress(script); } else { - throw new UnsupportedOperationException("Cannot determine receiving addresses for custom policies"); + throw new UnsupportedOperationException("Cannot determine addresses for custom policies"); } } - public Address getChangeAddress(int index) { + public Script getOutputScript(KeyPurpose keyPurpose, int index) { if(policyType == PolicyType.SINGLE) { Keystore keystore = getKeystores().get(0); - DeterministicKey key = keystore.getChangeKey(index); - return scriptType.getAddress(key); + DeterministicKey key = keystore.getKey(keyPurpose, index); + return scriptType.getOutputScript(key); } else if(policyType == PolicyType.MULTI) { - List pubKeys = getKeystores().stream().map(keystore -> keystore.getChangeKey(index)).collect(Collectors.toList()); + List pubKeys = getKeystores().stream().map(keystore -> keystore.getKey(keyPurpose, index)).collect(Collectors.toList()); Script script = ScriptType.MULTISIG.getOutputScript(defaultPolicy.getNumSignaturesRequired(), pubKeys); - return scriptType.getAddress(script); + return scriptType.getOutputScript(script); } else { - throw new UnsupportedOperationException("Cannot determine change addresses for custom policies"); + throw new UnsupportedOperationException("Cannot determine output script for custom policies"); } } diff --git a/src/test/java/com/sparrowwallet/drongo/wallet/WalletTest.java b/src/test/java/com/sparrowwallet/drongo/wallet/WalletTest.java index 402b5c5..bf78eb7 100644 --- a/src/test/java/com/sparrowwallet/drongo/wallet/WalletTest.java +++ b/src/test/java/com/sparrowwallet/drongo/wallet/WalletTest.java @@ -1,5 +1,6 @@ package com.sparrowwallet.drongo.wallet; +import com.sparrowwallet.drongo.KeyPurpose; import com.sparrowwallet.drongo.crypto.Argon2KeyDeriver; import com.sparrowwallet.drongo.crypto.Key; import com.sparrowwallet.drongo.crypto.KeyDeriver; @@ -78,8 +79,8 @@ public class WalletTest { wallet.getKeystores().add(keystore); wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2PKH, wallet.getKeystores(), 1)); - Assert.assertEquals("12kTQjuWDp7Uu6PwY6CsS1KLTt3d1DBHZa", wallet.getReceivingAddress(0).toString()); - Assert.assertEquals("1HbQwQCitHQxVtP39isXmUdHx7hQCZovrK", wallet.getReceivingAddress(1).toString()); + Assert.assertEquals("12kTQjuWDp7Uu6PwY6CsS1KLTt3d1DBHZa", wallet.getAddress(KeyPurpose.RECEIVE, 0).toString()); + Assert.assertEquals("1HbQwQCitHQxVtP39isXmUdHx7hQCZovrK", wallet.getAddress(KeyPurpose.RECEIVE, 1).toString()); } @Test @@ -93,8 +94,8 @@ public class WalletTest { wallet.getKeystores().add(keystore); wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2SH_P2WPKH, wallet.getKeystores(), 1)); - Assert.assertEquals("3NZLE4TntsjtcZ5MbrfxwtYo9meBVybVQj", wallet.getReceivingAddress(0).toString()); - Assert.assertEquals("32YBBuRsp8XTeLx4T6BmD2L4nANGaNDkSg", wallet.getReceivingAddress(1).toString()); + Assert.assertEquals("3NZLE4TntsjtcZ5MbrfxwtYo9meBVybVQj", wallet.getAddress(KeyPurpose.RECEIVE, 0).toString()); + Assert.assertEquals("32YBBuRsp8XTeLx4T6BmD2L4nANGaNDkSg", wallet.getAddress(KeyPurpose.RECEIVE, 1).toString()); } @Test @@ -108,8 +109,8 @@ public class WalletTest { wallet.getKeystores().add(keystore); wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, wallet.getKeystores(), 1)); - Assert.assertEquals("bc1quvxdut936uswuxwxrk6nvjmgwxh463r0fjwn55", wallet.getReceivingAddress(0).toString()); - Assert.assertEquals("bc1q95j2862dz7mqpraw6qdjc70gumyu5z7adgq9x9", wallet.getReceivingAddress(1).toString()); + Assert.assertEquals("bc1quvxdut936uswuxwxrk6nvjmgwxh463r0fjwn55", wallet.getAddress(KeyPurpose.RECEIVE, 0).toString()); + Assert.assertEquals("bc1q95j2862dz7mqpraw6qdjc70gumyu5z7adgq9x9", wallet.getAddress(KeyPurpose.RECEIVE, 1).toString()); } @Test @@ -133,8 +134,8 @@ public class WalletTest { wallet.getKeystores().add(keystore2); wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.MULTI, ScriptType.P2SH, wallet.getKeystores(), 2)); - Assert.assertEquals("38kq6yz4VcYymTExQPY3gppbz38mtPLveK", wallet.getReceivingAddress(0).toString()); - Assert.assertEquals("3EdKaNsnjBTBggWcSMRyVju6GbHWy68mAH", wallet.getChangeAddress(1).toString()); + Assert.assertEquals("38kq6yz4VcYymTExQPY3gppbz38mtPLveK", wallet.getAddress(KeyPurpose.RECEIVE, 0).toString()); + Assert.assertEquals("3EdKaNsnjBTBggWcSMRyVju6GbHWy68mAH", wallet.getAddress(KeyPurpose.CHANGE, 1).toString()); } @Test @@ -158,8 +159,8 @@ public class WalletTest { wallet.getKeystores().add(keystore2); wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.MULTI, ScriptType.P2SH_P2WSH, wallet.getKeystores(), 2)); - Assert.assertEquals("3Mw8xqAHh8g3eBvh7q1UEUmoexqdXDK9Tf", wallet.getReceivingAddress(0).toString()); - Assert.assertEquals("35dFo1ivJ8jyHpyf42MWvnYf5LBU8Siren", wallet.getChangeAddress(1).toString()); + Assert.assertEquals("3Mw8xqAHh8g3eBvh7q1UEUmoexqdXDK9Tf", wallet.getAddress(KeyPurpose.RECEIVE, 0).toString()); + Assert.assertEquals("35dFo1ivJ8jyHpyf42MWvnYf5LBU8Siren", wallet.getAddress(KeyPurpose.CHANGE, 1).toString()); } @Test @@ -183,7 +184,7 @@ public class WalletTest { wallet.getKeystores().add(keystore2); wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.MULTI, ScriptType.P2WSH, wallet.getKeystores(), 2)); - Assert.assertEquals("bc1q20e4vm656h5lvmngz9ztz6hjzftvh39yzngqhuqzk8qzj7tqnzaqgclrwc", wallet.getReceivingAddress(0).toString()); - Assert.assertEquals("bc1q2epdx7dplwaas2jucfrzmxm8350rqh68hs6vqreysku80ye44mfqla85f2", wallet.getChangeAddress(1).toString()); + Assert.assertEquals("bc1q20e4vm656h5lvmngz9ztz6hjzftvh39yzngqhuqzk8qzj7tqnzaqgclrwc", wallet.getAddress(KeyPurpose.RECEIVE, 0).toString()); + Assert.assertEquals("bc1q2epdx7dplwaas2jucfrzmxm8350rqh68hs6vqreysku80ye44mfqla85f2", wallet.getAddress(KeyPurpose.CHANGE, 1).toString()); } }