fix cobo vault keystore import

This commit is contained in:
Craig Raw 2020-10-09 09:59:26 +02:00
parent 5cd15f21ad
commit 20f5e4d8db
4 changed files with 103 additions and 6 deletions

View file

@ -1,12 +1,21 @@
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.wallet.Keystore;
import com.sparrowwallet.drongo.wallet.KeystoreSource;
import com.sparrowwallet.drongo.wallet.Wallet;
import com.sparrowwallet.drongo.wallet.WalletModel;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
public class CoboVaultSinglesig extends ColdcardSinglesig {
public class CoboVaultSinglesig implements KeystoreFileImport, WalletImport {
@Override
public String getName() {
return "Cobo Vault";
@ -24,10 +33,59 @@ public class CoboVaultSinglesig extends ColdcardSinglesig {
@Override
public Keystore getKeystore(ScriptType scriptType, InputStream inputStream, String password) throws ImportException {
Keystore keystore = super.getKeystore(scriptType, inputStream, password);
keystore.setLabel("Cobo Vault");
keystore.setWalletModel(getWalletModel());
try {
Gson gson = new Gson();
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;
}
}

View file

@ -62,7 +62,7 @@ public class ColdcardSinglesig implements KeystoreFileImport, WalletImport {
ScriptType ckScriptType = ScriptType.valueOf(ck.name.replace("p2wpkh-p2sh", "p2sh_p2wpkh").toUpperCase());
if(ckScriptType.equals(scriptType)) {
Keystore keystore = new Keystore();
keystore.setLabel("Coldcard");
keystore.setLabel(getName());
keystore.setSource(KeystoreSource.HW_AIRGAPPED);
keystore.setWalletModel(WalletModel.COLDCARD);
keystore.setKeyDerivation(new KeyDerivation(masterFingerprint, ck.deriv));

View file

@ -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());
}
}

View file

@ -0,0 +1,6 @@
{
"ExtPubKey": "zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs",
"MasterFingerprint": "73C5DA0A",
"AccountKeyPath": "84'/0'/0'",
"CoboVaultFirmwareVersion": "1.7.1(BTC-Only)"
}