support encoding registry objects to cbor and ur

This commit is contained in:
Craig Raw 2021-04-13 16:18:55 +02:00
parent e2fd1cd209
commit c91cf12e77
22 changed files with 448 additions and 42 deletions

View file

@ -0,0 +1,7 @@
package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.DataItem;
public interface CborSerializable {
DataItem toCbor();
}

View file

@ -2,11 +2,12 @@ package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.*;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class CryptoAccount {
public class CryptoAccount extends RegistryItem {
public static final long MASTER_FINGERPRINT_KEY = 1;
public static final long OUTPUT_DESCRIPTORS_KEY = 2;
@ -26,6 +27,22 @@ public class CryptoAccount {
return outputDescriptors;
}
public DataItem toCbor() {
Map map = new Map();
map.put(new UnsignedInteger(MASTER_FINGERPRINT_KEY), new UnsignedInteger(new BigInteger(1, masterFingerprint)));
Array array = new Array();
for(CryptoOutput cryptoOutput : outputDescriptors) {
array.add(cryptoOutput.toCbor());
}
map.put(new UnsignedInteger(OUTPUT_DESCRIPTORS_KEY), array);
return map;
}
@Override
public RegistryType getRegistryType() {
return RegistryType.CRYPTO_ACCOUNT;
}
public static CryptoAccount fromCbor(DataItem cbor) {
Map cryptoAccountMap = (Map)cbor;

View file

@ -2,7 +2,7 @@ package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.*;
public class CryptoAddress {
public class CryptoAddress extends RegistryItem {
public static final long INFO = 1;
public static final long TYPE = 2;
public static final long DATA = 3;
@ -29,9 +29,26 @@ public class CryptoAddress {
return data;
}
public DataItem toCbor() {
Map map = new Map();
if(info != null) {
map.put(new UnsignedInteger(INFO), info.toCbor());
}
if(type != null) {
map.put(new UnsignedInteger(TYPE), new UnsignedInteger(type.ordinal()));
}
map.put(new UnsignedInteger(DATA), new ByteString(data));
return map;
}
@Override
public RegistryType getRegistryType() {
return RegistryType.CRYPTO_ADDRESS;
}
public static CryptoAddress fromCbor(DataItem item) {
CryptoCoinInfo info = null;
Type type = Type.P2PKH;
Type type = null;
byte[] data = null;
Map map = (Map)item;

View file

@ -5,7 +5,7 @@ import co.nstant.in.cbor.model.*;
import java.util.ArrayList;
import java.util.List;
public class CryptoBip39 {
public class CryptoBip39 extends RegistryItem {
public static final long WORDS = 1;
public static final long LANG = 2;
@ -25,9 +25,27 @@ public class CryptoBip39 {
return language;
}
public DataItem toCbor() {
Map map = new Map();
Array wordsArray = new Array();
for(String word : words) {
wordsArray.add(new UnicodeString(word));
}
map.put(new UnsignedInteger(WORDS), wordsArray);
if(language != null) {
map.put(new UnsignedInteger(LANG), new UnicodeString(language));
}
return map;
}
@Override
public RegistryType getRegistryType() {
return RegistryType.CRYPTO_BIP39;
}
public static CryptoBip39 fromCbor(DataItem item) {
List<String> words = new ArrayList<>();
String language = "en";
String language = null;
Map map = (Map)item;
for(DataItem key : map.getKeys()) {

View file

@ -4,29 +4,45 @@ import co.nstant.in.cbor.model.DataItem;
import co.nstant.in.cbor.model.Map;
import co.nstant.in.cbor.model.UnsignedInteger;
public class CryptoCoinInfo {
public class CryptoCoinInfo extends RegistryItem {
public static final int TYPE_KEY = 1;
public static final int NETWORK_KEY = 2;
private final int type;
private final int network;
private final Integer type;
private final Integer network;
public CryptoCoinInfo(int type, int network) {
public CryptoCoinInfo(Integer type, Integer network) {
this.type = type;
this.network = network;
}
public Type getType() {
return Type.values()[type];
return type == null ? Type.BITCOIN : Type.values()[type];
}
public Network getNetwork() {
return Network.values()[network];
return network == null ? Network.MAINNET : Network.values()[network];
}
public DataItem toCbor() {
Map map = new Map();
if(type != null) {
map.put(new UnsignedInteger(TYPE_KEY), new UnsignedInteger(type));
}
if(network != null) {
map.put(new UnsignedInteger(NETWORK_KEY), new UnsignedInteger(network));
}
return map;
}
@Override
public RegistryType getRegistryType() {
return RegistryType.CRYPTO_COIN_INFO;
}
public static CryptoCoinInfo fromCbor(DataItem item) {
int type = 0;
int network = 0;
Integer type = null;
Integer network = null;
Map map = (Map)item;
for(DataItem key : map.getKeys()) {

View file

@ -2,36 +2,53 @@ package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.*;
public class CryptoECKey {
public class CryptoECKey extends RegistryItem {
public static final long CURVE = 1;
public static final long PRIVATE = 2;
public static final long DATA = 3;
private final int curve;
private final boolean privateKey;
private final Integer curve;
private final Boolean privateKey;
private final byte[] data;
public CryptoECKey(int curve, boolean privateKey, byte[] data) {
public CryptoECKey(Integer curve, Boolean privateKey, byte[] data) {
this.curve = curve;
this.privateKey = privateKey;
this.data = data;
}
public int getCurve() {
return curve;
return curve == null ? 0 : curve;
}
public boolean isPrivateKey() {
return privateKey;
return privateKey == null ? false : privateKey;
}
public byte[] getData() {
return data;
}
public DataItem toCbor() {
Map map = new Map();
if(curve != null) {
map.put(new UnsignedInteger(CURVE), new UnsignedInteger(curve));
}
if(privateKey != null) {
map.put(new UnsignedInteger(PRIVATE), privateKey ? SimpleValue.TRUE : SimpleValue.FALSE);
}
map.put(new UnsignedInteger(DATA), new ByteString(data));
return map;
}
@Override
public RegistryType getRegistryType() {
return RegistryType.CRYPTO_ECKEY;
}
public static CryptoECKey fromCbor(DataItem item) {
int curve = 0;
boolean privateKey = false;
Integer curve = null;
Boolean privateKey = null;
byte[] data = null;
Map map = (Map)item;

View file

@ -2,9 +2,10 @@ package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.*;
import java.math.BigInteger;
import java.util.Arrays;
public class CryptoHDKey {
public class CryptoHDKey extends RegistryItem {
public static final int IS_MASTER_KEY = 1;
public static final int IS_PRIVATE_KEY = 2;
public static final int KEY_DATA_KEY = 3;
@ -13,15 +14,19 @@ public class CryptoHDKey {
public static final int ORIGIN_KEY = 6;
public static final int CHILDREN_KEY = 7;
public static final int PARENT_FINGERPRINT_KEY = 8;
public static final int NAME_KEY = 9;
public static final int NOTE_KEY = 10;
private final boolean master;
private final boolean privateKey;
private final Boolean privateKey;
private final byte[] key;
private final byte[] chainCode;
private final CryptoCoinInfo useInfo;
private final CryptoKeypath origin;
private final CryptoKeypath children;
private final byte[] parentFingerprint;
private final String name;
private final String note;
public CryptoHDKey(byte[] key, byte[] chainCode) {
this.master = true;
@ -32,9 +37,15 @@ public class CryptoHDKey {
this.origin = null;
this.children = null;
this.parentFingerprint = null;
this.name = null;
this.note = null;
}
public CryptoHDKey(boolean privateKey, byte[] key, byte[] chainCode, CryptoCoinInfo useInfo, CryptoKeypath origin, CryptoKeypath children, byte[] parentFingerprint) {
public CryptoHDKey(Boolean privateKey, byte[] key, byte[] chainCode, CryptoCoinInfo useInfo, CryptoKeypath origin, CryptoKeypath children, byte[] parentFingerprint) {
this(privateKey, key, chainCode, useInfo, origin, children, parentFingerprint, null, null);
}
public CryptoHDKey(Boolean privateKey, byte[] key, byte[] chainCode, CryptoCoinInfo useInfo, CryptoKeypath origin, CryptoKeypath children, byte[] parentFingerprint, String name, String note) {
this.master = false;
this.privateKey = privateKey;
this.key = key;
@ -43,6 +54,8 @@ public class CryptoHDKey {
this.origin = origin;
this.children = children;
this.parentFingerprint = parentFingerprint == null ? null : Arrays.copyOfRange(parentFingerprint, parentFingerprint.length - 4, parentFingerprint.length);
this.name = name;
this.note = note;
}
public boolean isMaster() {
@ -50,7 +63,7 @@ public class CryptoHDKey {
}
public boolean isPrivateKey() {
return privateKey;
return privateKey == null ? false : privateKey;
}
public byte[] getKey() {
@ -77,15 +90,72 @@ public class CryptoHDKey {
return parentFingerprint;
}
public String getName() {
return name;
}
public String getNote() {
return note;
}
public DataItem toCbor() {
Map map = new Map();
if(master) {
map.put(new UnsignedInteger(IS_MASTER_KEY), SimpleValue.TRUE);
map.put(new UnsignedInteger(KEY_DATA_KEY), new ByteString(key));
map.put(new UnsignedInteger(CHAIN_CODE_KEY), new ByteString(chainCode));
} else {
if(privateKey != null) {
map.put(new UnsignedInteger(IS_PRIVATE_KEY), privateKey ? SimpleValue.TRUE : SimpleValue.FALSE);
}
map.put(new UnsignedInteger(KEY_DATA_KEY), new ByteString(key));
if(chainCode != null) {
map.put(new UnsignedInteger(CHAIN_CODE_KEY), new ByteString(chainCode));
}
if(useInfo != null) {
DataItem useInfoItem = useInfo.toCbor();
useInfoItem.setTag(RegistryType.CRYPTO_COIN_INFO.getTag());
map.put(new UnsignedInteger(USE_INFO_KEY), useInfoItem);
}
if(origin != null) {
DataItem originItem = origin.toCbor();
originItem.setTag(RegistryType.CRYPTO_KEYPATH.getTag());
map.put(new UnsignedInteger(ORIGIN_KEY), originItem);
}
if(children != null) {
DataItem childrenItem = children.toCbor();
childrenItem.setTag(RegistryType.CRYPTO_KEYPATH.getTag());
map.put(new UnsignedInteger(CHILDREN_KEY), childrenItem);
}
if(parentFingerprint != null) {
map.put(new UnsignedInteger(PARENT_FINGERPRINT_KEY), new UnsignedInteger(new BigInteger(1, parentFingerprint)));
}
if(name != null) {
map.put(new UnsignedInteger(NAME_KEY), new UnicodeString(name));
}
if(note != null) {
map.put(new UnsignedInteger(NOTE_KEY), new UnicodeString(note));
}
}
return map;
}
@Override
public RegistryType getRegistryType() {
return RegistryType.CRYPTO_HDKEY;
}
public static CryptoHDKey fromCbor(DataItem item) {
boolean isMasterKey = false;
boolean isPrivateKey = false;
Boolean isPrivateKey = null;
byte[] keyData = null;
byte[] chainCode = null;
CryptoCoinInfo useInfo = null;
CryptoKeypath origin = null;
CryptoKeypath children = null;
byte[] parentFingerprint = null;
String name = null;
String note = null;
Map map = (Map)item;
for(DataItem key : map.getKeys()) {
@ -107,6 +177,10 @@ public class CryptoHDKey {
children = CryptoKeypath.fromCbor(map.get(uintKey));
} else if(intKey == PARENT_FINGERPRINT_KEY) {
parentFingerprint = ((UnsignedInteger)map.get(uintKey)).getValue().toByteArray();
} else if(intKey == NAME_KEY) {
name = ((UnicodeString)map.get(uintKey)).getString();
} else if(intKey == NOTE_KEY) {
note = ((UnicodeString)map.get(uintKey)).getString();
}
}
@ -115,9 +189,13 @@ public class CryptoHDKey {
}
if(isMasterKey) {
if(chainCode == null) {
throw new IllegalStateException("Chain code data is null");
}
return new CryptoHDKey(keyData, chainCode);
} else {
return new CryptoHDKey(isPrivateKey, keyData, chainCode, useInfo, origin, children, parentFingerprint);
return new CryptoHDKey(isPrivateKey, keyData, chainCode, useInfo, origin, children, parentFingerprint, name, note);
}
}
}

View file

@ -2,12 +2,13 @@ package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.*;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringJoiner;
public class CryptoKeypath {
public class CryptoKeypath extends RegistryItem {
public static final int COMPONENTS_KEY = 1;
public static final int SOURCE_FINGERPRINT_KEY = 2;
public static final int DEPTH_KEY = 3;
@ -50,6 +51,34 @@ public class CryptoKeypath {
return depth;
}
public DataItem toCbor() {
Map map = new Map();
Array componentArray = new Array();
for(PathComponent pathComponent : components) {
if(pathComponent.isWildcard()) {
componentArray.add(new Array());
} else {
componentArray.add(new UnsignedInteger(pathComponent.getIndex()));
}
componentArray.add(pathComponent.isHardened() ? SimpleValue.TRUE : SimpleValue.FALSE);
}
if(!componentArray.getDataItems().isEmpty()) {
map.put(new UnsignedInteger(COMPONENTS_KEY), componentArray);
}
if(sourceFingerprint != null) {
map.put(new UnsignedInteger(SOURCE_FINGERPRINT_KEY), new UnsignedInteger(new BigInteger(1, sourceFingerprint)));
}
if(depth != null) {
map.put(new UnsignedInteger(DEPTH_KEY), new UnsignedInteger(depth));
}
return map;
}
@Override
public RegistryType getRegistryType() {
return RegistryType.CRYPTO_KEYPATH;
}
public static CryptoKeypath fromCbor(DataItem item) {
List<PathComponent> components = new ArrayList<>();
byte[] sourceFingerprint = null;

View file

@ -8,7 +8,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CryptoOutput {
public class CryptoOutput extends RegistryItem {
private final List<ScriptExpression> scriptExpressions;
//Only one of the following will be not null
@ -53,6 +53,37 @@ public class CryptoOutput {
return multiKey;
}
public DataItem toCbor() {
DataItem item = null;
if(multiKey != null) {
item = multiKey.toCbor();
} else if(ecKey != null) {
item = ecKey.toCbor();
item.setTag(RegistryType.CRYPTO_ECKEY.getTag());
} else if(hdKey != null) {
item = hdKey.toCbor();
item.setTag(RegistryType.CRYPTO_HDKEY.getTag());
}
Tag tag = item.getTag();
for(int i = scriptExpressions.size() - 1; i >= 0; i--) {
Tag newTag = new Tag(scriptExpressions.get(i).getTagValue());
if(tag == null) {
item.setTag(newTag);
} else {
tag.setTag(newTag);
}
tag = newTag;
}
return item;
}
@Override
public RegistryType getRegistryType() {
return RegistryType.CRYPTO_OUTPUT;
}
public static CryptoOutput fromCbor(DataItem cbor) {
List<ScriptExpression> expressions = new ArrayList<>();

View file

@ -3,7 +3,7 @@ package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.ByteString;
import co.nstant.in.cbor.model.DataItem;
public class CryptoPSBT {
public class CryptoPSBT extends RegistryItem {
private final byte[] psbt;
public CryptoPSBT(byte[] psbt) {
@ -14,6 +14,15 @@ public class CryptoPSBT {
return psbt;
}
public DataItem toCbor() {
return new ByteString(psbt);
}
@Override
public RegistryType getRegistryType() {
return RegistryType.CRYPTO_PSBT;
}
public static CryptoPSBT fromCbor(DataItem item) {
return new CryptoPSBT(((ByteString)item).getBytes());
}

View file

@ -1,22 +1,29 @@
package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.ByteString;
import co.nstant.in.cbor.model.DataItem;
import co.nstant.in.cbor.model.Map;
import co.nstant.in.cbor.model.UnsignedInteger;
import co.nstant.in.cbor.model.*;
import java.util.Date;
public class CryptoSeed {
public static final long PAYLOAD = 1;
public static final long BIRTHDATE = 2;
public class CryptoSeed extends RegistryItem {
public static final long PAYLOAD_KEY = 1;
public static final long BIRTHDATE_KEY = 2;
public static final long NAME_KEY = 3;
public static final long NOTE_KEY = 4;
private final byte[] seed;
private final Date birthdate;
private final String name;
private final String note;
public CryptoSeed(byte[] seed, Date birthdate) {
this(seed, birthdate, null, null);
}
public CryptoSeed(byte[] seed, Date birthdate, String name, String note) {
this.seed = seed;
this.birthdate = birthdate;
this.name = name;
this.note = note;
}
public byte[] getSeed() {
@ -27,18 +34,54 @@ public class CryptoSeed {
return birthdate;
}
public String getName() {
return name;
}
public String getNote() {
return note;
}
public DataItem toCbor() {
Map map = new Map();
map.put(new UnsignedInteger(PAYLOAD_KEY), new ByteString(seed));
if(birthdate != null) {
DataItem birthdateItem = new UnsignedInteger(birthdate.getTime() / (1000 * 60 * 60 * 24));
birthdateItem.setTag(100);
map.put(new UnsignedInteger(BIRTHDATE_KEY), birthdateItem);
}
if(name != null) {
map.put(new UnsignedInteger(NAME_KEY), new UnicodeString(name));
}
if(note != null) {
map.put(new UnsignedInteger(NOTE_KEY), new UnicodeString(note));
}
return map;
}
@Override
public RegistryType getRegistryType() {
return RegistryType.CRYPTO_SEED;
}
public static CryptoSeed fromCbor(DataItem item) {
byte[] seed = null;
Date birthdate = null;
String name = null;
String note = null;
Map map = (Map)item;
for(DataItem key : map.getKeys()) {
UnsignedInteger uintKey = (UnsignedInteger)key;
int intKey = uintKey.getValue().intValue();
if(intKey == PAYLOAD) {
if(intKey == PAYLOAD_KEY) {
seed = ((ByteString)map.get(key)).getBytes();
} else if(intKey == BIRTHDATE) {
} else if(intKey == BIRTHDATE_KEY) {
birthdate = new Date(((UnsignedInteger)map.get(key)).getValue().longValue() * 1000 * 60 * 60 * 24);
} else if(intKey == NAME_KEY) {
name = ((UnicodeString)map.get(key)).getString();
} else if(intKey == NOTE_KEY) {
note = ((UnicodeString)map.get(key)).getString();
}
}
@ -46,6 +89,6 @@ public class CryptoSeed {
throw new IllegalStateException("Seed is null");
}
return new CryptoSeed(seed, birthdate);
return new CryptoSeed(seed, birthdate, name, note);
}
}

View file

@ -8,7 +8,7 @@ import co.nstant.in.cbor.model.UnsignedInteger;
import java.util.ArrayList;
import java.util.List;
public class MultiKey {
public class MultiKey implements CborSerializable {
public static final int THRESHOLD_KEY = 1;
public static final int KEYS_KEY = 2;
@ -34,6 +34,27 @@ public class MultiKey {
return hdKeys;
}
public DataItem toCbor() {
Map map = new Map();
map.put(new UnsignedInteger(THRESHOLD_KEY), new UnsignedInteger(threshold));
Array array = new Array();
if(ecKeys != null && !ecKeys.isEmpty()) {
for(CryptoECKey cryptoECKey : ecKeys) {
DataItem eckeyItem = cryptoECKey.toCbor();
eckeyItem.setTag(RegistryType.CRYPTO_ECKEY.getTag());
array.add(eckeyItem);
}
} else if(hdKeys != null) {
for(CryptoHDKey cryptoHDKey : hdKeys) {
DataItem hdkeyItem = cryptoHDKey.toCbor();
hdkeyItem.setTag(RegistryType.CRYPTO_HDKEY.getTag());
array.add(hdkeyItem);
}
}
map.put(new UnsignedInteger(KEYS_KEY), array);
return map;
}
public static MultiKey fromCbor(DataItem item) {
int threshold = 0;
List<CryptoECKey> ecKeys = new ArrayList<>();
@ -57,6 +78,10 @@ public class MultiKey {
}
}
if(ecKeys.isEmpty() && hdKeys.isEmpty()) {
throw new IllegalStateException("One or more of eckey or hdkey must be specified");
}
return new MultiKey(threshold, ecKeys, hdKeys);
}
}

View file

@ -0,0 +1,22 @@
package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.CborEncoder;
import co.nstant.in.cbor.CborException;
import com.sparrowwallet.hummingbird.UR;
import java.io.ByteArrayOutputStream;
public abstract class RegistryItem implements CborSerializable {
public abstract RegistryType getRegistryType();
public UR toUR() {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
CborEncoder encoder = new CborEncoder(baos);
encoder.encode(toCbor());
return new UR(getRegistryType(), baos.toByteArray());
} catch(CborException | UR.InvalidTypeException e) {
throw new IllegalArgumentException(e);
}
}
}

View file

@ -1,5 +1,11 @@
package com.sparrowwallet.hummingbird;
import co.nstant.in.cbor.CborEncoder;
import co.nstant.in.cbor.CborException;
import co.nstant.in.cbor.model.DataItem;
import java.io.ByteArrayOutputStream;
public class TestUtils {
public static byte[] hexToBytes(String s) {
int len = s.length();
@ -21,4 +27,11 @@ public class TestUtils {
}
return new String(hexChars);
}
public static String encode(DataItem item) throws CborException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
CborEncoder encoder = new CborEncoder(baos);
encoder.encode(item);
return bytesToHex(baos.toByteArray());
}
}

View file

@ -69,6 +69,10 @@ public class CryptoAccountTest {
Assert.assertEquals("48'/0'/0'/2'", cryptoOutput6.getHdKey().getOrigin().getPath());
Assert.assertEquals("59b69b2a", TestUtils.bytesToHex(cryptoOutput6.getHdKey().getParentFingerprint()));
Assert.assertNull(cryptoOutput6.getHdKey().getChildren());
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(cryptoAccount.toCbor()));
String ur = "ur:crypto-account/oeadcyemrewytyaolntaadmutaaddloxaxhdclaxwmfmdeiamecsdsemgtvsjzcncygrkowtrontzschgezokstswkkscfmklrtauteyaahdcxiehfonurdppfyntapejpproypegrdawkgmaewejlsfdtsrfybdehcaflmtrlbdhpamtaaddyoyadlncsdwykaeykaeykaycynlytsnyltaadmhtaadmwtaaddloxaxhdclaostvelfemdyynwydwyaievosrgmambklovabdgypdglldvespsthysadamhpmjeinaahdcxntdllnaaeykoytdacygegwhgjsiyonpywmcmrpwphsvodsrerozsbyaxluzcoxdpamtaaddyoyadlncsehykaeykaeykaycypdbskeuytaadmwtaaddloxaxhdclaxzcfxeegdrpmogrgwkbzctlttweadkiengrwlhtprremouoluutqdpfbncedkynfhaahdcxjpwevdeogthttkmeswzcolcpsaahcfnshkhtehytclmnteatmoteadtlwynnftloamtaaddyoyadlncsghykaeykaeykaycybthlvytstaadmhtaaddloxaxhdclaxhhsnhdrpftdwuocntilydibehnecmovdfekpjkclcslasbhkpawsaddmcmmnahnyaahdcxlotedtndfymyltclhlmtpfsadscnhtztaolbnnkistaedegwfmmedreetnwmcycnamtaaddyoyadlfcsdpykaycyemrewytytaadmhtaadmetaaddloxaxhdclaxdwkswmztpytnswtsecnblfbayajkdldeclqzzolrsnhljedsgminetytbnahatbyaahdcxkkguwsvyimjkvwteytwztyswvendtpmncpasfrrylprnhtkblndrgrmkoyjtbkrpamtaaddyoyadlocsdyykaeykaeykadykaycyhkrpnddrtaadmetaaddloxaxhdclaohnhffmvsbndslrfgclpfjejyatbdpebacnzokotofxntaoemvskpaowmryfnotfgaahdcxdlnbvecentssfsssgylnhkrstoytecrdlyadrekirfaybglahltalsrfcaeerobwamtaaddyoyadlocsdyykaeykaeykaoykaycyhkrpnddrgdaogykb";
Assert.assertEquals(ur, cryptoAccount.toUR().toString());
}
@Test

View file

@ -17,5 +17,8 @@ public class CryptoAddressTest {
List<DataItem> items = CborDecoder.decode(data);
CryptoAddress cryptoAddress = CryptoAddress.fromCbor(items.get(0));
Assert.assertEquals("77bff20c60e522dfaa3350c39b030a5d004e839a", TestUtils.bytesToHex(cryptoAddress.getData()));
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(cryptoAddress.toCbor()));
String ur = "ur:crypto-address/oyaxghktrswzbnhnvwcpurpkeogdsrndaxbkhlaegllsnyolrsemgu";
Assert.assertEquals(ur, cryptoAddress.toUR().toString());
}
}

View file

@ -13,11 +13,14 @@ import java.util.List;
public class CryptoBip39Test {
@Test
public void testSeed() throws CborException {
String hex = "A2018C66736869656C646567726F75706565726F6465656177616B65646C6F636B6773617573616765646361736865676C6172656477617665646372657765666C616D6565676C6F76650262656E1947DA";
String hex = "A2018C66736869656C646567726F75706565726F6465656177616B65646C6F636B6773617573616765646361736865676C6172656477617665646372657765666C616D6565676C6F76650262656E";
byte[] data = TestUtils.hexToBytes(hex);
List<DataItem> items = CborDecoder.decode(data);
CryptoBip39 cryptoSeed = CryptoBip39.fromCbor(items.get(0));
Assert.assertEquals(Arrays.asList("shield", "group", "erode", "awake", "lock", "sausage", "cash", "glare", "wave", "crew", "flame", "glove"), cryptoSeed.getWords());
Assert.assertEquals("en", cryptoSeed.getLanguage());
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(cryptoSeed.toCbor()));
String ur = "ur:crypto-bip39/oeadlkiyjkisinihjzieihiojpjlkpjoihihjpjlieihihhskthsjeihiejzjliajeiojkhskpjkhsioihieiahsjkisihiojzhsjpihiekthskoihieiajpihktihiyjzhsjnihihiojzjlkoihaoidihjtrkkndede";
Assert.assertEquals(ur, cryptoSeed.toUR().toString());
}
}

View file

@ -19,5 +19,8 @@ public class CryptoECKeyTest {
Assert.assertEquals(0, cryptoECKey.getCurve());
Assert.assertTrue(cryptoECKey.isPrivateKey());
Assert.assertEquals("8c05c4b4f3e88840a4f4b5f155cfd69473ea169f3d0431b7a6787a23777f08aa", TestUtils.bytesToHex(cryptoECKey.getData()));
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(cryptoECKey.toCbor()));
String ur = "ur:crypto-eckey/oeaoykaxhdcxlkahssqzwfvslofzoxwkrewngotktbmwjkwdcmnefsaaehrlolkskncnktlbaypkrphsmyid";
Assert.assertEquals(ur, cryptoECKey.toUR().toString());
}
}

View file

@ -19,6 +19,9 @@ public class CryptoHDKeyTest {
Assert.assertTrue(cryptoHDKey.isMaster());
Assert.assertEquals("00e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35", TestUtils.bytesToHex(cryptoHDKey.getKey()));
Assert.assertEquals("873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508", TestUtils.bytesToHex(cryptoHDKey.getChainCode()));
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(cryptoHDKey.toCbor()));
String ur = "ur:crypto-hdkey/otadykaxhdclaevswfdmjpfswpwkahcywspsmndwmusoskprbbehetchsnpfcybbmwrhchspfxjeecaahdcxltfszmlyrtdlgmhfcnzcctvwcmkbpsftgonbgauefsehgrqzdmvodizmweemtlaybakiylat";
Assert.assertEquals(ur, cryptoHDKey.toUR().toString());
}
@Test
@ -35,5 +38,8 @@ public class CryptoHDKeyTest {
Assert.assertEquals("44'/1'/1'/0/1", cryptoHDKey.getOrigin().getPath());
Assert.assertEquals("e9181cf3", TestUtils.bytesToHex(cryptoHDKey.getParentFingerprint()));
Assert.assertNull(cryptoHDKey.getChildren());
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(cryptoHDKey.toCbor()));
String ur = "ur:crypto-hdkey/onaxhdclaojlvoechgferkdpqdiabdrflawshlhdmdcemtfnlrctghchbdolvwsednvdztbgolaahdcxtottgostdkhfdahdlykkecbbweskrymwflvdylgerkloswtbrpfdbsticmwylklpahtaadehoyaoadamtaaddyoyadlecsdwykadykadykaewkadwkaycywlcscewfihbdaehn";
Assert.assertEquals(ur, cryptoHDKey.toUR().toString());
}
}

View file

@ -20,6 +20,9 @@ public class CryptoOutputTest {
CryptoOutput cryptoOutput = CryptoOutput.fromCbor(items.get(0));
Assert.assertEquals(Collections.singletonList(ScriptExpression.PUBLIC_KEY_HASH), cryptoOutput.getScriptExpressions());
Assert.assertEquals("02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5", TestUtils.bytesToHex(cryptoOutput.getEcKey().getData()));
Assert.assertEquals(hex, TestUtils.encode(cryptoOutput.toCbor()));
String ur = "ur:crypto-output/taadmutaadeyoyaxhdclaoswaalbmwfpwekijndyfefzjtmdrtketphhktmngrlkwsfnospypsasrhhhjonnvwtsqzwljy";
Assert.assertEquals(ur, cryptoOutput.toUR().toString());
}
@Test
@ -30,6 +33,9 @@ public class CryptoOutputTest {
CryptoOutput cryptoOutput = CryptoOutput.fromCbor(items.get(0));
Assert.assertEquals(Arrays.asList(ScriptExpression.SCRIPT_HASH, ScriptExpression.WITNESS_PUBLIC_KEY_HASH), cryptoOutput.getScriptExpressions());
Assert.assertEquals("03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556", TestUtils.bytesToHex(cryptoOutput.getEcKey().getData()));
Assert.assertEquals(hex, TestUtils.encode(cryptoOutput.toCbor()));
String ur = "ur:crypto-output/taadmhtaadmwtaadeyoyaxhdclaxzmytkgtlkphywyoxcxfeftbbecgmectelfynfldllpisoyludlahknbbhndtkphfhlehmust";
Assert.assertEquals(ur, cryptoOutput.toUR().toString());
}
@Test
@ -47,6 +53,10 @@ public class CryptoOutputTest {
CryptoECKey secondKey = cryptoOutput.getMultiKey().getEcKeys().get(1);
Assert.assertEquals("03acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe", TestUtils.bytesToHex(secondKey.getData()));
Assert.assertEquals(hex, TestUtils.encode(cryptoOutput.toCbor()));
String ur = "ur:crypto-output/taadmhtaadmtoeadaoaolftaadeyoyaxhdclaodladvwvyhhsgeccapewflrfhrlbsfndlbkcwutahvwpeloleioksglwfvybkdradtaadeyoyaxhdclaxpstylrvowtstynguaspmchlenegonyryvtmsmtmsgshgvdbbsrhebybtztdisfrnpfadremh";
Assert.assertEquals(ur, cryptoOutput.toUR().toString());
}
@Test
@ -63,6 +73,9 @@ public class CryptoOutputTest {
Assert.assertEquals("78412e3a", TestUtils.bytesToHex(cryptoOutput.getHdKey().getParentFingerprint()));
Assert.assertEquals("1/*", cryptoOutput.getHdKey().getChildren().getPath());
Assert.assertNull(cryptoOutput.getHdKey().getChildren().getSourceFingerprint());
Assert.assertEquals(hex, TestUtils.encode(cryptoOutput.toCbor()));
String ur = "ur:crypto-output/taadmutaaddlonaxhdclaotdqdinaeesjzmolfzsbbidlpiyhddlcximhltirfsptlvsmohscsamsgzoaxadwtaahdcxiaksataxbtgotictnybnqdoslsmdbztsmtryatjoialnolweuramsfdtolhtbadtamtaaddyoeadlncsdwykaeykaeykaocytegtqdfhattaaddyoyadlradwklawkaycyksfpdmftpyaaeelb";
Assert.assertEquals(ur, cryptoOutput.toUR().toString());
}
@Test
@ -92,5 +105,9 @@ public class CryptoOutputTest {
Assert.assertNull(secondKey.getOrigin().getDepth());
Assert.assertEquals("0/0/*", secondKey.getChildren().getPath());
Assert.assertNull(secondKey.getChildren().getSourceFingerprint());
Assert.assertEquals(hex, TestUtils.encode(cryptoOutput.toCbor()));
String ur = "ur:crypto-output/taadmetaadmtoeadadaolftaaddloxaxhdclaxsbsgptsolkltkndsmskiaelfhhmdimcnmnlgutzotecpsfveylgrbdhptbpsveosaahdcxhnganelacwldjnlschnyfxjyplrllfdrplpswdnbuyctlpwyfmmhgsgtwsrymtldamtaaddyoyaxaeattaaddyoyadlnadwkaewklawktaaddloxaxhdclaoztnnhtwtpslgndfnwpzedrlomnclchrdfsayntlplplojznslfjejecpptlgbgwdaahdcxwtmhnyzmpkkbvdpyvwutglbeahmktyuogusnjonththhdwpsfzvdfpdlcndlkensamtaaddyoeadlfaewkaocyrycmrnvwattaaddyoyadlnaewkaewklawkkkztdlon";
Assert.assertEquals(ur, cryptoOutput.toUR().toString());
}
}

View file

@ -0,0 +1,25 @@
package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.CborDecoder;
import co.nstant.in.cbor.CborException;
import co.nstant.in.cbor.model.DataItem;
import com.sparrowwallet.hummingbird.TestUtils;
import org.junit.Assert;
import org.junit.Test;
import java.util.List;
public class CryptoPSBTTest {
@Test
public void testEncode() throws CborException {
String hex = "58A770736274FF01009A020000000258E87A21B56DAF0C23BE8E7070456C336F7CBAA5C8757924F545887BB2ABDD750000000000FFFFFFFF838D0427D0EC650A68AA46BB0B098AEA4422C071B2CA78352A077959D07CEA1D0100000000FFFFFFFF0270AAF00800000000160014D85C2B71D0060B09C9886AEB815E50991DDA124D00E1F5050000000016001400AEA9A2E5F0F876A588DF5546E8742D1D87008F000000000000000000";
byte[] data = TestUtils.hexToBytes(hex);
List<DataItem> items = CborDecoder.decode(data);
CryptoPSBT cryptoPSBT = CryptoPSBT.fromCbor(items.get(0));
String psbtHex = "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000000000000000000";
Assert.assertArrayEquals(TestUtils.hexToBytes(psbtHex), cryptoPSBT.getPsbt());
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(cryptoPSBT.toCbor()));
String ur = "ur:crypto-psbt/hdosjojkidjyzmadaenyaoaeaeaeaohdvsknclrejnpebncnrnmnjojofejzeojlkerdonspkpkkdkykfelokgprpyutkpaeaeaeaeaezmzmzmzmlslgaaditiwpihbkispkfgrkbdaslewdfycprtjsprsgksecdratkkhktikewdcaadaeaeaeaezmzmzmzmaojopkwtayaeaeaeaecmaebbtphhdnjstiambdassoloimwmlyhygdnlcatnbggtaevyykahaeaeaeaecmaebbaeplptoevwwtyakoonlourgofgvsjydpcaltaemyaeaeaeaeaeaeaeaeaebkgdcarh";
Assert.assertEquals(ur, cryptoPSBT.toUR().toString());
}
}

View file

@ -22,5 +22,8 @@ public class CryptoSeedTest {
CryptoSeed cryptoSeed = CryptoSeed.fromCbor(items.get(0));
Assert.assertEquals("c7098580125e2ab0981253468b2dbc52", TestUtils.bytesToHex(cryptoSeed.getSeed()));
Assert.assertEquals("12 May 2020", dateFormat.format(cryptoSeed.getBirthdate()));
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(cryptoSeed.toCbor()));
String ur = "ur:crypto-seed/oeadgdstaslplabghydrpfmkbggufgludprfgmaotpiecffltnlpqdenos";
Assert.assertEquals(ur, cryptoSeed.toUR().toString());
}
}