mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-11-04 21:36:45 +00:00
fix cobo vault keystore import
This commit is contained in:
parent
5cd15f21ad
commit
20f5e4d8db
4 changed files with 103 additions and 6 deletions
|
@ -1,12 +1,21 @@
|
||||||
package com.sparrowwallet.sparrow.io;
|
package com.sparrowwallet.sparrow.io;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.sparrowwallet.drongo.ExtendedKey;
|
||||||
|
import com.sparrowwallet.drongo.KeyDerivation;
|
||||||
|
import com.sparrowwallet.drongo.policy.Policy;
|
||||||
|
import com.sparrowwallet.drongo.policy.PolicyType;
|
||||||
import com.sparrowwallet.drongo.protocol.ScriptType;
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
import com.sparrowwallet.drongo.wallet.Keystore;
|
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||||
|
import com.sparrowwallet.drongo.wallet.KeystoreSource;
|
||||||
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
import com.sparrowwallet.drongo.wallet.WalletModel;
|
import com.sparrowwallet.drongo.wallet.WalletModel;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
public class CoboVaultSinglesig extends ColdcardSinglesig {
|
public class CoboVaultSinglesig implements KeystoreFileImport, WalletImport {
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Cobo Vault";
|
return "Cobo Vault";
|
||||||
|
@ -24,10 +33,59 @@ public class CoboVaultSinglesig extends ColdcardSinglesig {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Keystore getKeystore(ScriptType scriptType, InputStream inputStream, String password) throws ImportException {
|
public Keystore getKeystore(ScriptType scriptType, InputStream inputStream, String password) throws ImportException {
|
||||||
Keystore keystore = super.getKeystore(scriptType, inputStream, password);
|
try {
|
||||||
keystore.setLabel("Cobo Vault");
|
Gson gson = new Gson();
|
||||||
keystore.setWalletModel(getWalletModel());
|
CoboVaultKeystore coboKeystore = gson.fromJson(new InputStreamReader(inputStream), CoboVaultKeystore.class);
|
||||||
|
|
||||||
return keystore;
|
Keystore keystore = new Keystore();
|
||||||
|
keystore.setLabel(getName());
|
||||||
|
keystore.setSource(KeystoreSource.HW_AIRGAPPED);
|
||||||
|
keystore.setWalletModel(WalletModel.COBO_VAULT);
|
||||||
|
keystore.setKeyDerivation(new KeyDerivation(coboKeystore.MasterFingerprint.toLowerCase(), "m/" + coboKeystore.AccountKeyPath));
|
||||||
|
keystore.setExtendedPublicKey(ExtendedKey.fromDescriptor(coboKeystore.ExtPubKey));
|
||||||
|
|
||||||
|
ExtendedKey.Header header = ExtendedKey.Header.fromExtendedKey(coboKeystore.ExtPubKey);
|
||||||
|
if(header.getDefaultScriptType() != scriptType) {
|
||||||
|
throw new ImportException("This wallet's script type (" + scriptType + ") does not match the " + getName() + " script type (" + header.getDefaultScriptType() + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
return keystore;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new ImportException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getWalletImportDescription() {
|
||||||
|
return getKeystoreImportDescription();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Wallet importWallet(InputStream inputStream, String password) throws ImportException {
|
||||||
|
//Use default of P2WPKH
|
||||||
|
Keystore keystore = getKeystore(ScriptType.P2WPKH, inputStream, "");
|
||||||
|
|
||||||
|
Wallet wallet = new Wallet();
|
||||||
|
wallet.setPolicyType(PolicyType.SINGLE);
|
||||||
|
wallet.setScriptType(ScriptType.P2WPKH);
|
||||||
|
wallet.getKeystores().add(keystore);
|
||||||
|
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, wallet.getKeystores(), null));
|
||||||
|
|
||||||
|
if(!wallet.isValid()) {
|
||||||
|
throw new ImportException("Wallet is in an inconsistent state.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return wallet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEncrypted(File file) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CoboVaultKeystore {
|
||||||
|
public String ExtPubKey;
|
||||||
|
public String MasterFingerprint;
|
||||||
|
public String AccountKeyPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ public class ColdcardSinglesig implements KeystoreFileImport, WalletImport {
|
||||||
ScriptType ckScriptType = ScriptType.valueOf(ck.name.replace("p2wpkh-p2sh", "p2sh_p2wpkh").toUpperCase());
|
ScriptType ckScriptType = ScriptType.valueOf(ck.name.replace("p2wpkh-p2sh", "p2sh_p2wpkh").toUpperCase());
|
||||||
if(ckScriptType.equals(scriptType)) {
|
if(ckScriptType.equals(scriptType)) {
|
||||||
Keystore keystore = new Keystore();
|
Keystore keystore = new Keystore();
|
||||||
keystore.setLabel("Coldcard");
|
keystore.setLabel(getName());
|
||||||
keystore.setSource(KeystoreSource.HW_AIRGAPPED);
|
keystore.setSource(KeystoreSource.HW_AIRGAPPED);
|
||||||
keystore.setWalletModel(WalletModel.COLDCARD);
|
keystore.setWalletModel(WalletModel.COLDCARD);
|
||||||
keystore.setKeyDerivation(new KeyDerivation(masterFingerprint, ck.deriv));
|
keystore.setKeyDerivation(new KeyDerivation(masterFingerprint, ck.deriv));
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.sparrowwallet.sparrow.io;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.ExtendedKey;
|
||||||
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
|
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class CoboVaultSinglesigTest extends IoTest {
|
||||||
|
@Test
|
||||||
|
public void testImport() throws ImportException {
|
||||||
|
CoboVaultSinglesig coboSingleSig = new CoboVaultSinglesig();
|
||||||
|
Keystore keystore = coboSingleSig.getKeystore(ScriptType.P2WPKH, getInputStream("cobo-singlesig-keystore-1.json"), null);
|
||||||
|
|
||||||
|
Assert.assertEquals("Cobo Vault", keystore.getLabel());
|
||||||
|
Assert.assertEquals("m/84'/0'/0'", keystore.getKeyDerivation().getDerivationPath());
|
||||||
|
Assert.assertEquals("73c5da0a", keystore.getKeyDerivation().getMasterFingerprint());
|
||||||
|
Assert.assertEquals(ExtendedKey.fromDescriptor("zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs"), keystore.getExtendedPublicKey());
|
||||||
|
Assert.assertTrue(keystore.isValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = ImportException.class)
|
||||||
|
public void testIncorrectScriptType() throws ImportException {
|
||||||
|
CoboVaultSinglesig coboSingleSig = new CoboVaultSinglesig();
|
||||||
|
Keystore keystore = coboSingleSig.getKeystore(ScriptType.P2SH_P2WPKH, getInputStream("cobo-singlesig-keystore-1.json"), null);
|
||||||
|
|
||||||
|
Assert.assertEquals("Cobo Vault", keystore.getLabel());
|
||||||
|
Assert.assertEquals("m/84'/0'/0'", keystore.getKeyDerivation().getDerivationPath());
|
||||||
|
Assert.assertEquals("73c5da0a", keystore.getKeyDerivation().getMasterFingerprint());
|
||||||
|
Assert.assertEquals(ExtendedKey.fromDescriptor("zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs"), keystore.getExtendedPublicKey());
|
||||||
|
Assert.assertTrue(keystore.isValid());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"ExtPubKey": "zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs",
|
||||||
|
"MasterFingerprint": "73C5DA0A",
|
||||||
|
"AccountKeyPath": "84'/0'/0'",
|
||||||
|
"CoboVaultFirmwareVersion": "1.7.1(BTC-Only)"
|
||||||
|
}
|
Loading…
Reference in a new issue