add new ur registry types for 40000 range including version 3 output-descriptor type

This commit is contained in:
Craig Raw 2023-12-13 14:16:15 +02:00
parent 1a7d56a3a9
commit 2ac6c346cd
20 changed files with 1027 additions and 1 deletions

View file

@ -22,7 +22,17 @@ public enum RegistryType {
CRYPTO_OUTPUT("crypto-output", 308, CryptoOutput.class),
CRYPTO_SSKR("crypto-sskr", 309, CryptoSskr.class),
CRYPTO_PSBT("crypto-psbt", 310, CryptoPSBT.class),
CRYPTO_ACCOUNT("crypto-account", 311, CryptoAccount.class);
CRYPTO_ACCOUNT("crypto-account", 311, CryptoAccount.class),
SEED("seed", 40300, URSeed.class),
HDKEY("hdkey", 40303, URHDKey.class),
KEYPATH("keypath", 40304, URKeypath.class),
COIN_INFO("coininfo", 40305, URCoinInfo.class),
ECKEY("eckey", 40306, URECKey.class),
ADDRESS("address", 40307, URAddress.class),
OUTPUT_DESCRIPTOR("output-descriptor", 40308, UROutputDescriptor.class),
SSKR("sskr", 40309, URSSKR.class),
PSBT("psbt", 40310, URPSBT.class),
ACCOUNT("account", 40311, URAccount.class);
private final String type;
private final Integer tag;

View file

@ -0,0 +1,34 @@
package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.Array;
import co.nstant.in.cbor.model.DataItem;
import co.nstant.in.cbor.model.Map;
import co.nstant.in.cbor.model.UnsignedInteger;
import java.util.ArrayList;
import java.util.List;
public class URAccount extends CryptoAccount {
public URAccount(byte[] masterFingerprint, List<CryptoOutput> outputDescriptors) {
super(masterFingerprint, outputDescriptors);
}
@Override
public RegistryType getRegistryType() {
return RegistryType.ACCOUNT;
}
public static URAccount fromCbor(DataItem cbor) {
Map accountMap = (Map)cbor;
UnsignedInteger uintMasterFingerprint = (UnsignedInteger)accountMap.get(new UnsignedInteger(MASTER_FINGERPRINT_KEY));
byte[] masterFingerprint = bigIntegerToBytes(uintMasterFingerprint.getValue(), 4);
Array outputDescriptors = (Array)accountMap.get(new UnsignedInteger(OUTPUT_DESCRIPTORS_KEY));
List<CryptoOutput> cryptoOutputs = new ArrayList<>(outputDescriptors.getDataItems().size());
for(DataItem item : outputDescriptors.getDataItems()) {
cryptoOutputs.add(CryptoOutput.fromCbor(item));
}
return new URAccount(masterFingerprint, cryptoOutputs);
}
}

View file

@ -0,0 +1,42 @@
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;
public class URAddress extends CryptoAddress {
public URAddress(CryptoCoinInfo info, Type type, byte[] data) {
super(info, type, data);
}
@Override
public RegistryType getRegistryType() {
return RegistryType.ADDRESS;
}
public static URAddress fromCbor(DataItem item) {
URCoinInfo info = null;
Type type = null;
byte[] data = null;
Map map = (Map)item;
for(DataItem key : map.getKeys()) {
UnsignedInteger uintKey = (UnsignedInteger)key;
int intKey = uintKey.getValue().intValue();
if(intKey == INFO) {
info = URCoinInfo.fromCbor(map.get(key));
} else if(intKey == TYPE) {
type = Type.values()[((UnsignedInteger)map.get(key)).getValue().intValue()];
} else if(intKey == DATA) {
data = ((ByteString)map.get(key)).getBytes();
}
}
if(data == null) {
throw new IllegalStateException("Data is null");
}
return new URAddress(info, type, data);
}
}

View file

@ -0,0 +1,39 @@
package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.DataItem;
import co.nstant.in.cbor.model.Map;
import co.nstant.in.cbor.model.UnsignedInteger;
public class URCoinInfo extends CryptoCoinInfo {
public URCoinInfo(Integer type, Integer network) {
super(type, network);
}
public URCoinInfo(Type type, Network network) {
super(type, network);
}
@Override
public RegistryType getRegistryType() {
return RegistryType.COIN_INFO;
}
public static URCoinInfo fromCbor(DataItem item) {
Integer type = null;
Integer network = null;
Map map = (Map)item;
for(DataItem key : map.getKeys()) {
UnsignedInteger uintKey = (UnsignedInteger)key;
int intKey = uintKey.getValue().intValue();
if(intKey == TYPE_KEY) {
type = ((UnsignedInteger)map.get(key)).getValue().intValue();
} else if(intKey == NETWORK_KEY) {
network = ((UnsignedInteger)map.get(key)).getValue().intValue();
}
}
return new URCoinInfo(type, network);
}
}

View file

@ -0,0 +1,39 @@
package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.*;
public class URECKey extends CryptoECKey {
public URECKey(Integer curve, Boolean privateKey, byte[] data) {
super(curve, privateKey, data);
}
@Override
public RegistryType getRegistryType() {
return RegistryType.ECKEY;
}
public static URECKey fromCbor(DataItem item) {
Integer curve = null;
Boolean privateKey = null;
byte[] data = null;
Map map = (Map)item;
for(DataItem key : map.getKeys()) {
UnsignedInteger uintKey = (UnsignedInteger)key;
int intKey = uintKey.getValue().intValue();
if(intKey == CURVE) {
curve = ((UnsignedInteger)map.get(key)).getValue().intValue();
} else if(intKey == PRIVATE) {
privateKey = (map.get(key) == SimpleValue.TRUE);
} else if(intKey == DATA) {
data = ((ByteString)map.get(key)).getBytes();
}
}
if(data == null) {
throw new IllegalStateException("Data is null");
}
return new URECKey(curve, privateKey, data);
}
}

View file

@ -0,0 +1,97 @@
package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.*;
public class URHDKey extends CryptoHDKey {
public URHDKey(byte[] key, byte[] chainCode) {
super(key, chainCode);
}
public URHDKey(Boolean privateKey, byte[] key, byte[] chainCode, CryptoCoinInfo useInfo, CryptoKeypath origin, CryptoKeypath children, byte[] parentFingerprint) {
super(privateKey, key, chainCode, useInfo, origin, children, parentFingerprint);
}
public URHDKey(Boolean privateKey, byte[] key, byte[] chainCode, CryptoCoinInfo useInfo, CryptoKeypath origin, CryptoKeypath children, byte[] parentFingerprint, String name, String note) {
super(privateKey, key, chainCode, useInfo, origin, children, parentFingerprint, name, note);
}
public DataItem toCbor() {
Map map = (Map)super.toCbor();
DataItem useinfo = map.get(new UnsignedInteger(USE_INFO_KEY));
if(useinfo != null) {
useinfo.setTag(RegistryType.COIN_INFO.getTag());
}
DataItem origin = map.get(new UnsignedInteger(ORIGIN_KEY));
if(origin != null) {
origin.setTag(RegistryType.KEYPATH.getTag());
}
DataItem children = map.get(new UnsignedInteger(CHILDREN_KEY));
if(children != null) {
children.setTag(RegistryType.KEYPATH.getTag());
}
return map;
}
@Override
public RegistryType getRegistryType() {
return RegistryType.HDKEY;
}
public static URHDKey fromCbor(DataItem item) {
boolean isMasterKey = false;
Boolean isPrivateKey = null;
byte[] keyData = null;
byte[] chainCode = null;
URCoinInfo useInfo = null;
URKeypath origin = null;
URKeypath children = null;
byte[] parentFingerprint = 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 == IS_MASTER_KEY) {
isMasterKey = (map.get(uintKey) == SimpleValue.TRUE);
} else if(intKey == IS_PRIVATE_KEY) {
isPrivateKey = (map.get(uintKey) == SimpleValue.TRUE);
} else if(intKey == KEY_DATA_KEY) {
keyData = ((ByteString)map.get(uintKey)).getBytes();
} else if(intKey == CHAIN_CODE_KEY) {
chainCode = ((ByteString)map.get(uintKey)).getBytes();
} else if(intKey == USE_INFO_KEY) {
useInfo = URCoinInfo.fromCbor(map.get(uintKey));
} else if(intKey == ORIGIN_KEY) {
origin = URKeypath.fromCbor(map.get(uintKey));
} else if(intKey == CHILDREN_KEY) {
children = URKeypath.fromCbor(map.get(uintKey));
} else if(intKey == PARENT_FINGERPRINT_KEY) {
parentFingerprint = bigIntegerToBytes(((UnsignedInteger)map.get(uintKey)).getValue(), 4);
} else if(intKey == NAME_KEY) {
name = ((UnicodeString)map.get(uintKey)).getString();
} else if(intKey == NOTE_KEY) {
note = ((UnicodeString)map.get(uintKey)).getString();
}
}
if(keyData == null) {
throw new IllegalStateException("Key data is null");
}
if(isMasterKey) {
if(chainCode == null) {
throw new IllegalStateException("Chain code data is null");
}
return new URHDKey(keyData, chainCode);
} else {
return new URHDKey(isPrivateKey, keyData, chainCode, useInfo, origin, children, parentFingerprint, name, note);
}
}
}

View file

@ -0,0 +1,45 @@
package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.DataItem;
import co.nstant.in.cbor.model.Map;
import co.nstant.in.cbor.model.UnsignedInteger;
import com.sparrowwallet.hummingbird.registry.pathcomponent.PathComponent;
import java.util.ArrayList;
import java.util.List;
public class URKeypath extends CryptoKeypath {
public URKeypath(List<PathComponent> components, byte[] sourceFingerprint) {
super(components, sourceFingerprint);
}
public URKeypath(List<PathComponent> components, byte[] sourceFingerprint, Integer depth) {
super(components, sourceFingerprint, depth);
}
@Override
public RegistryType getRegistryType() {
return RegistryType.KEYPATH;
}
public static URKeypath fromCbor(DataItem item) {
List<PathComponent> components = new ArrayList<>();
byte[] sourceFingerprint = null;
Integer depth = null;
Map map = (Map)item;
for(DataItem key : map.getKeys()) {
UnsignedInteger uintKey = (UnsignedInteger)key;
int intKey = uintKey.getValue().intValue();
if(intKey == COMPONENTS_KEY) {
components = PathComponent.fromCbor(map.get(key));
} else if(intKey == SOURCE_FINGERPRINT_KEY) {
sourceFingerprint = bigIntegerToBytes(((UnsignedInteger)map.get(key)).getValue(), 4);
} else if(intKey == DEPTH_KEY) {
depth = ((UnsignedInteger)map.get(key)).getValue().intValue();
}
}
return new URKeypath(components, sourceFingerprint, depth);
}
}

View file

@ -0,0 +1,121 @@
package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.*;
import java.util.ArrayList;
import java.util.List;
public class UROutputDescriptor extends RegistryItem {
public static final long SOURCE = 1;
public static final long KEYS = 2;
public static final long NAME = 3;
public static final long NOTE = 4;
private final String source;
private final List<RegistryItem> keys;
private final String name;
private final String note;
public UROutputDescriptor(String source) {
this(source, null);
}
public UROutputDescriptor(String source, List<RegistryItem> keys) {
this(source, keys, null, null);
}
public UROutputDescriptor(String source, List<RegistryItem> keys, String name, String note) {
this.source = source;
this.keys = keys;
this.name = name;
this.note = note;
if(keys != null && !keys.stream().allMatch(item -> item instanceof URHDKey || item instanceof URECKey || item instanceof URAddress)) {
throw new IllegalArgumentException("All keys must be one of HDKey, ECKey or Address");
}
}
public String getSource() {
return source;
}
public List<RegistryItem> getKeys() {
return keys;
}
public String getName() {
return name;
}
public String getNote() {
return note;
}
public DataItem toCbor() {
Map map = new Map();
map.put(new UnsignedInteger(SOURCE), new UnicodeString(source));
if(keys != null && !keys.isEmpty()) {
Array array = new Array();
for(RegistryItem key : keys) {
array.add(key.toCbor());
}
map.put(new UnsignedInteger(KEYS), array);
}
if(name != null) {
map.put(new UnsignedInteger(NAME), new UnicodeString(name));
}
if(note != null) {
map.put(new UnsignedInteger(NOTE), new UnicodeString(note));
}
return map;
}
@Override
public RegistryType getRegistryType() {
return RegistryType.OUTPUT_DESCRIPTOR;
}
public static UROutputDescriptor fromCbor(DataItem item) {
String source = null;
List<RegistryItem> keys = 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 == SOURCE) {
source = ((UnicodeString)map.get(key)).getString();
} else if(intKey == KEYS) {
Array keyArray = (Array)map.get(key);
keys = new ArrayList<>(keyArray.getDataItems().size());
for(DataItem keyItem : keyArray.getDataItems()) {
if(keyItem.getTag().getValue() == RegistryType.HDKEY.getTag()) {
keys.add(URHDKey.fromCbor(keyItem));
} else if(keyItem.getTag().getValue() == RegistryType.ECKEY.getTag()) {
keys.add(URECKey.fromCbor(keyItem));
} else if(keyItem.getTag().getValue() == RegistryType.ADDRESS.getTag()) {
keys.add(URAddress.fromCbor(keyItem));
} else {
throw new IllegalArgumentException("All keys must be one of HDKey, ECKey or Address");
}
}
} else if(intKey == NAME) {
name = ((UnicodeString)map.get(key)).getString();
} else if(intKey == NOTE) {
note = ((UnicodeString)map.get(key)).getString();
}
}
if(source == null) {
throw new IllegalStateException("Source is null");
}
return new UROutputDescriptor(source, keys, name, note);
}
}

View file

@ -0,0 +1,19 @@
package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.ByteString;
import co.nstant.in.cbor.model.DataItem;
public class URPSBT extends CryptoPSBT {
public URPSBT(byte[] psbt) {
super(psbt);
}
@Override
public RegistryType getRegistryType() {
return RegistryType.PSBT;
}
public static URPSBT fromCbor(DataItem item) {
return new URPSBT(((ByteString)item).getBytes());
}
}

View file

@ -0,0 +1,23 @@
package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.ByteString;
import co.nstant.in.cbor.model.DataItem;
import java.util.Arrays;
public class URSSKR extends CryptoSskr {
public URSSKR(byte[] split) {
super(split);
}
@Override
public RegistryType getRegistryType() {
return RegistryType.SSKR;
}
public static URSSKR fromCbor(DataItem item) {
byte[] itemBytes = ((ByteString)item).getBytes();
byte[] normalisedSplit = Arrays.copyOfRange(itemBytes, 1, itemBytes.length);
return new URSSKR(normalisedSplit);
}
}

View file

@ -0,0 +1,48 @@
package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.*;
import java.util.Date;
public class URSeed extends CryptoSeed {
public URSeed(byte[] seed, Date birthdate) {
super(seed, birthdate);
}
public URSeed(byte[] seed, Date birthdate, String name, String note) {
super(seed, birthdate, name, note);
}
@Override
public RegistryType getRegistryType() {
return RegistryType.SEED;
}
public static URSeed 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_KEY) {
seed = ((ByteString)map.get(key)).getBytes();
} 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();
}
}
if(seed == null) {
throw new IllegalStateException("Seed is null");
}
return new URSeed(seed, birthdate, name, note);
}
}

View file

@ -0,0 +1,174 @@
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.*;
import org.junit.Assert;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class URAccountTest {
@Test
public void testSeedPreCosigner() throws CborException {
String hex = "A2011A37B5EED40287D90193D9012FA403582103EB3E2863911826374DE86C231A4B76F0B89DFA174AFB78D7F478199884D9DD320458206456A5DF2DB0F6D9AF72B2A1AF4B25F45200ED6FCC29C3440B311D4796B70B5B06D90130A10186182CF500F500F5081A99F9CDF7D90190D90194D9012FA403582102C7E4823730F6EE2CF864E2C352060A88E60B51A84E89E4C8C75EC22590AD6B690458209D2F86043276F9251A4A4F577166A5ABEB16B6EC61E226B5B8FA11038BFDA42D06D90130A101861831F500F500F5081AA80F7CDBD90194D9012FA403582103FD433450B6924B4F7EFDD5D1ED017D364BE95AB2B592DC8BDDB3B00C1C24F63F04582072EDE7334D5ACF91C6FDA622C205199C595A31F9218ED30792D301D5EE9E3A8806D90130A101861854F500F500F5081A0D5DE1D7D90190D9012FA4035821035CCD58B63A2CDC23D0812710603592E7457573211880CB59B1EF012E168E059A04582088D3299B448F87215D96B0C226235AFC027F9E7DC700284F3E912A34DAEB1A2306D90130A10182182DF5081A37B5EED4D90190D90191D9012FA4035821032C78EBFCABDAC6D735A0820EF8732F2821B4FB84CD5D6B26526938F90C0507110458207953EFE16A73E5D3F9F2D4C6E49BD88E22093BBD85BE5A7E862A4B98A16E0AB606D90130A101881830F500F500F501F5081A59B69B2AD90191D9012FA40358210260563EE80C26844621B06B74070BAF0E23FB76CE439D0237E87502EBBD3CA3460458202FA0E41C9DC43DC4518659BFCEF935BA8101B57DBC0812805DD983BC1D34B81306D90130A101881830F500F500F502F5081A59B69B2AD90199D9012FA403582102BBB97CF9EFA176B738EFD6EE1D4D0FA391A973394FBC16E4C5E78E536CD14D2D0458204B4693E1F794206ED1355B838DA24949A92B63D02E58910BF3BD3D9C242281E606D90130A101861856F500F500F5081ACEC7070C";
byte[] data = TestUtils.hexToBytes(hex);
List<DataItem> items = CborDecoder.decode(data);
URAccount urAccount = URAccount.fromCbor(items.get(0));
Assert.assertEquals("37b5eed4", TestUtils.bytesToHex(urAccount.getMasterFingerprint()));
CryptoOutput cryptoOutput1 = urAccount.getOutputDescriptors().get(0);
Assert.assertEquals(Collections.singletonList(ScriptExpression.PUBLIC_KEY_HASH), cryptoOutput1.getScriptExpressions());
Assert.assertEquals("03eb3e2863911826374de86c231a4b76f0b89dfa174afb78d7f478199884d9dd32", TestUtils.bytesToHex(cryptoOutput1.getHdKey().getKey()));
Assert.assertEquals("6456a5df2db0f6d9af72b2a1af4b25f45200ed6fcc29c3440b311d4796b70b5b", TestUtils.bytesToHex(cryptoOutput1.getHdKey().getChainCode()));
Assert.assertEquals("44'/0'/0'", cryptoOutput1.getHdKey().getOrigin().getPath());
Assert.assertEquals("99f9cdf7", TestUtils.bytesToHex(cryptoOutput1.getHdKey().getParentFingerprint()));
Assert.assertNull(cryptoOutput1.getHdKey().getChildren());
CryptoOutput cryptoOutput2 = urAccount.getOutputDescriptors().get(1);
Assert.assertEquals(Arrays.asList(ScriptExpression.SCRIPT_HASH, ScriptExpression.WITNESS_PUBLIC_KEY_HASH), cryptoOutput2.getScriptExpressions());
Assert.assertEquals("02c7e4823730f6ee2cf864e2c352060a88e60b51a84e89e4c8c75ec22590ad6b69", TestUtils.bytesToHex(cryptoOutput2.getHdKey().getKey()));
Assert.assertEquals("9d2f86043276f9251a4a4f577166a5abeb16b6ec61e226b5b8fa11038bfda42d", TestUtils.bytesToHex(cryptoOutput2.getHdKey().getChainCode()));
Assert.assertEquals("49'/0'/0'", cryptoOutput2.getHdKey().getOrigin().getPath());
Assert.assertEquals("a80f7cdb", TestUtils.bytesToHex(cryptoOutput2.getHdKey().getParentFingerprint()));
Assert.assertNull(cryptoOutput2.getHdKey().getChildren());
CryptoOutput cryptoOutput3 = urAccount.getOutputDescriptors().get(2);
Assert.assertEquals(Collections.singletonList(ScriptExpression.WITNESS_PUBLIC_KEY_HASH), cryptoOutput3.getScriptExpressions());
Assert.assertEquals("03fd433450b6924b4f7efdd5d1ed017d364be95ab2b592dc8bddb3b00c1c24f63f", TestUtils.bytesToHex(cryptoOutput3.getHdKey().getKey()));
Assert.assertEquals("72ede7334d5acf91c6fda622c205199c595a31f9218ed30792d301d5ee9e3a88", TestUtils.bytesToHex(cryptoOutput3.getHdKey().getChainCode()));
Assert.assertEquals("84'/0'/0'", cryptoOutput3.getHdKey().getOrigin().getPath());
Assert.assertEquals("0d5de1d7", TestUtils.bytesToHex(cryptoOutput3.getHdKey().getParentFingerprint()));
Assert.assertNull(cryptoOutput3.getHdKey().getChildren());
CryptoOutput cryptoOutput4 = urAccount.getOutputDescriptors().get(3);
Assert.assertEquals(Collections.singletonList(ScriptExpression.SCRIPT_HASH), cryptoOutput4.getScriptExpressions());
Assert.assertEquals("035ccd58b63a2cdc23d0812710603592e7457573211880cb59b1ef012e168e059a", TestUtils.bytesToHex(cryptoOutput4.getHdKey().getKey()));
Assert.assertEquals("88d3299b448f87215d96b0c226235afc027f9e7dc700284f3e912a34daeb1a23", TestUtils.bytesToHex(cryptoOutput4.getHdKey().getChainCode()));
Assert.assertEquals("45'", cryptoOutput4.getHdKey().getOrigin().getPath());
Assert.assertEquals("37b5eed4", TestUtils.bytesToHex(cryptoOutput4.getHdKey().getParentFingerprint()));
Assert.assertNull(cryptoOutput4.getHdKey().getChildren());
CryptoOutput cryptoOutput5 = urAccount.getOutputDescriptors().get(4);
Assert.assertEquals(Arrays.asList(ScriptExpression.SCRIPT_HASH, ScriptExpression.WITNESS_SCRIPT_HASH), cryptoOutput5.getScriptExpressions());
Assert.assertEquals("032c78ebfcabdac6d735a0820ef8732f2821b4fb84cd5d6b26526938f90c050711", TestUtils.bytesToHex(cryptoOutput5.getHdKey().getKey()));
Assert.assertEquals("7953efe16a73e5d3f9f2d4c6e49bd88e22093bbd85be5a7e862a4b98a16e0ab6", TestUtils.bytesToHex(cryptoOutput5.getHdKey().getChainCode()));
Assert.assertEquals("48'/0'/0'/1'", cryptoOutput5.getHdKey().getOrigin().getPath());
Assert.assertEquals("59b69b2a", TestUtils.bytesToHex(cryptoOutput5.getHdKey().getParentFingerprint()));
Assert.assertNull(cryptoOutput5.getHdKey().getChildren());
CryptoOutput cryptoOutput6 = urAccount.getOutputDescriptors().get(5);
Assert.assertEquals(Collections.singletonList(ScriptExpression.WITNESS_SCRIPT_HASH), cryptoOutput6.getScriptExpressions());
Assert.assertEquals("0260563ee80c26844621b06b74070baf0e23fb76ce439d0237e87502ebbd3ca346", TestUtils.bytesToHex(cryptoOutput6.getHdKey().getKey()));
Assert.assertEquals("2fa0e41c9dc43dc4518659bfcef935ba8101b57dbc0812805dd983bc1d34b813", TestUtils.bytesToHex(cryptoOutput6.getHdKey().getChainCode()));
Assert.assertEquals("48'/0'/0'/2'", cryptoOutput6.getHdKey().getOrigin().getPath());
Assert.assertEquals("59b69b2a", TestUtils.bytesToHex(cryptoOutput6.getHdKey().getParentFingerprint()));
Assert.assertNull(cryptoOutput6.getHdKey().getChildren());
CryptoOutput cryptoOutput7 = urAccount.getOutputDescriptors().get(6);
Assert.assertEquals(Collections.singletonList(ScriptExpression.TAPROOT), cryptoOutput7.getScriptExpressions());
Assert.assertEquals("02bbb97cf9efa176b738efd6ee1d4d0fa391a973394fbc16e4c5e78e536cd14d2d", TestUtils.bytesToHex(cryptoOutput7.getHdKey().getKey()));
Assert.assertEquals("4b4693e1f794206ed1355b838da24949a92b63d02e58910bf3bd3d9c242281e6", TestUtils.bytesToHex(cryptoOutput7.getHdKey().getChainCode()));
Assert.assertEquals("86'/0'/0'", cryptoOutput7.getHdKey().getOrigin().getPath());
Assert.assertEquals("cec7070c", TestUtils.bytesToHex(cryptoOutput7.getHdKey().getParentFingerprint()));
Assert.assertNull(cryptoOutput7.getHdKey().getChildren());
Assert.assertEquals("a2011a37b5eed40287d90134d90193d9012fa403582103eb3e2863911826374de86c231a4b76f0b89dfa174afb78d7f478199884d9dd320458206456a5df2db0f6d9af72b2a1af4b25f45200ed6fcc29c3440b311d4796b70b5b06d90130a10186182cf500f500f5081a99f9cdf7d90134d90190d90194d9012fa403582102c7e4823730f6ee2cf864e2c352060a88e60b51a84e89e4c8c75ec22590ad6b690458209d2f86043276f9251a4a4f577166a5abeb16b6ec61e226b5b8fa11038bfda42d06d90130a101861831f500f500f5081aa80f7cdbd90134d90194d9012fa403582103fd433450b6924b4f7efdd5d1ed017d364be95ab2b592dc8bddb3b00c1c24f63f04582072ede7334d5acf91c6fda622c205199c595a31f9218ed30792d301d5ee9e3a8806d90130a101861854f500f500f5081a0d5de1d7d90134d90190d9012fa4035821035ccd58b63a2cdc23d0812710603592e7457573211880cb59b1ef012e168e059a04582088d3299b448f87215d96b0c226235afc027f9e7dc700284f3e912a34daeb1a2306d90130a10182182df5081a37b5eed4d90134d90190d90191d9012fa4035821032c78ebfcabdac6d735a0820ef8732f2821b4fb84cd5d6b26526938f90c0507110458207953efe16a73e5d3f9f2d4c6e49bd88e22093bbd85be5a7e862a4b98a16e0ab606d90130a101881830f500f500f501f5081a59b69b2ad90134d90191d9012fa40358210260563ee80c26844621b06b74070baf0e23fb76ce439d0237e87502ebbd3ca3460458202fa0e41c9dc43dc4518659bfcef935ba8101b57dbc0812805dd983bc1d34b81306d90130a101881830f500f500f502f5081a59b69b2ad90134d90199d9012fa403582102bbb97cf9efa176b738efd6ee1d4d0fa391a973394fbc16e4c5e78e536cd14d2d0458204b4693e1f794206ed1355b838da24949a92b63d02e58910bf3bd3d9c242281e606d90130a101861856f500f500f5081acec7070c", TestUtils.encode(urAccount.toCbor()));
String ur = "ur:account/oeadcyemrewytyaolttaadeetaadmutaaddloxaxhdclaxwmfmdeiamecsdsemgtvsjzcncygrkowtrontzschgezokstswkkscfmklrtauteyaahdcxiehfonurdppfyntapejpproypegrdawkgmaewejlsfdtsrfybdehcaflmtrlbdhpamtaaddyoyadlncsdwykaeykaeykaycynlytsnyltaadeetaadmhtaadmwtaaddloxaxhdclaostvelfemdyynwydwyaievosrgmambklovabdgypdglldvespsthysadamhpmjeinaahdcxntdllnaaeykoytdacygegwhgjsiyonpywmcmrpwphsvodsrerozsbyaxluzcoxdpamtaaddyoyadlncsehykaeykaeykaycypdbskeuytaadeetaadmwtaaddloxaxhdclaxzcfxeegdrpmogrgwkbzctlttweadkiengrwlhtprremouoluutqdpfbncedkynfhaahdcxjpwevdeogthttkmeswzcolcpsaahcfnshkhtehytclmnteatmoteadtlwynnftloamtaaddyoyadlncsghykaeykaeykaycybthlvytstaadeetaadmhtaaddloxaxhdclaxhhsnhdrpftdwuocntilydibehnecmovdfekpjkclcslasbhkpawsaddmcmmnahnyaahdcxlotedtndfymyltclhlmtpfsadscnhtztaolbnnkistaedegwfmmedreetnwmcycnamtaaddyoyadlfcsdpykaycyemrewytytaadeetaadmhtaadmetaaddloxaxhdclaxdwkswmztpytnswtsecnblfbayajkdldeclqzzolrsnhljedsgminetytbnahatbyaahdcxkkguwsvyimjkvwteytwztyswvendtpmncpasfrrylprnhtkblndrgrmkoyjtbkrpamtaaddyoyadlocsdyykaeykaeykadykaycyhkrpnddrtaadeetaadmetaaddloxaxhdclaohnhffmvsbndslrfgclpfjejyatbdpebacnzokotofxntaoemvskpaowmryfnotfgaahdcxdlnbvecentssfsssgylnhkrstoytecrdlyadrekirfaybglahltalsrfcaeerobwamtaaddyoyadlocsdyykaeykaeykaoykaycyhkrpnddrtaadeetaadnltaaddloxaxhdclaorkrhkeytwsoykorletwstbwycagtbsotmeptjkesgwrfcmveskvdmngujzttgtdpaahdcxgrfgmuvyylmwcxjtttechplslgoegagaptdniatidmhdmebdwfryfsnsdkcplyvaamtaaddyoyadlncshfykaeykaeykaycytostatbnfpghsgbd";
Assert.assertEquals(ur, urAccount.toUR().toString());
}
@Test
public void testSeed() throws CborException {
String hex = "a2011a37b5eed40287d90134d90193d9012fa403582103eb3e2863911826374de86c231a4b76f0b89dfa174afb78d7f478199884d9dd320458206456a5df2db0f6d9af72b2a1af4b25f45200ed6fcc29c3440b311d4796b70b5b06d90130a20186182cf500f500f5021a37b5eed4081a99f9cdf7d90134d90190d90194d9012fa403582102c7e4823730f6ee2cf864e2c352060a88e60b51a84e89e4c8c75ec22590ad6b690458209d2f86043276f9251a4a4f577166a5abeb16b6ec61e226b5b8fa11038bfda42d06d90130a201861831f500f500f5021a37b5eed4081aa80f7cdbd90134d90194d9012fa403582103fd433450b6924b4f7efdd5d1ed017d364be95ab2b592dc8bddb3b00c1c24f63f04582072ede7334d5acf91c6fda622c205199c595a31f9218ed30792d301d5ee9e3a8806d90130a201861854f500f500f5021a37b5eed4081a0d5de1d7d90134d90190d9019ad9012fa4035821035ccd58b63a2cdc23d0812710603592e7457573211880cb59b1ef012e168e059a04582088d3299b448f87215d96b0c226235afc027f9e7dc700284f3e912a34daeb1a2306d90130a20182182df5021a37b5eed4081a37b5eed4d90134d90190d90191d9019ad9012fa4035821032c78ebfcabdac6d735a0820ef8732f2821b4fb84cd5d6b26526938f90c0507110458207953efe16a73e5d3f9f2d4c6e49bd88e22093bbd85be5a7e862a4b98a16e0ab606d90130a201881830f500f500f501f5021a37b5eed4081a59b69b2ad90134d90191d9019ad9012fa40358210260563ee80c26844621b06b74070baf0e23fb76ce439d0237e87502ebbd3ca3460458202fa0e41c9dc43dc4518659bfcef935ba8101b57dbc0812805dd983bc1d34b81306d90130a201881830f500f500f502f5021a37b5eed4081a59b69b2ad90134d90199d9012fa403582102bbb97cf9efa176b738efd6ee1d4d0fa391a973394fbc16e4c5e78e536cd14d2d0458204b4693e1f794206ed1355b838da24949a92b63d02e58910bf3bd3d9c242281e606d90130a201861856f500f500f5021a37b5eed4081acec7070c";
byte[] data = TestUtils.hexToBytes(hex);
List<DataItem> items = CborDecoder.decode(data);
URAccount urAccount = URAccount.fromCbor(items.get(0));
Assert.assertEquals("37b5eed4", TestUtils.bytesToHex(urAccount.getMasterFingerprint()));
CryptoOutput cryptoOutput1 = urAccount.getOutputDescriptors().get(0);
Assert.assertEquals(Collections.singletonList(ScriptExpression.PUBLIC_KEY_HASH), cryptoOutput1.getScriptExpressions());
Assert.assertEquals("03eb3e2863911826374de86c231a4b76f0b89dfa174afb78d7f478199884d9dd32", TestUtils.bytesToHex(cryptoOutput1.getHdKey().getKey()));
Assert.assertEquals("6456a5df2db0f6d9af72b2a1af4b25f45200ed6fcc29c3440b311d4796b70b5b", TestUtils.bytesToHex(cryptoOutput1.getHdKey().getChainCode()));
Assert.assertEquals("44'/0'/0'", cryptoOutput1.getHdKey().getOrigin().getPath());
Assert.assertEquals("99f9cdf7", TestUtils.bytesToHex(cryptoOutput1.getHdKey().getParentFingerprint()));
Assert.assertNull(cryptoOutput1.getHdKey().getChildren());
CryptoOutput cryptoOutput2 = urAccount.getOutputDescriptors().get(1);
Assert.assertEquals(Arrays.asList(ScriptExpression.SCRIPT_HASH, ScriptExpression.WITNESS_PUBLIC_KEY_HASH), cryptoOutput2.getScriptExpressions());
Assert.assertEquals("02c7e4823730f6ee2cf864e2c352060a88e60b51a84e89e4c8c75ec22590ad6b69", TestUtils.bytesToHex(cryptoOutput2.getHdKey().getKey()));
Assert.assertEquals("9d2f86043276f9251a4a4f577166a5abeb16b6ec61e226b5b8fa11038bfda42d", TestUtils.bytesToHex(cryptoOutput2.getHdKey().getChainCode()));
Assert.assertEquals("49'/0'/0'", cryptoOutput2.getHdKey().getOrigin().getPath());
Assert.assertEquals("a80f7cdb", TestUtils.bytesToHex(cryptoOutput2.getHdKey().getParentFingerprint()));
Assert.assertNull(cryptoOutput2.getHdKey().getChildren());
CryptoOutput cryptoOutput3 = urAccount.getOutputDescriptors().get(2);
Assert.assertEquals(Collections.singletonList(ScriptExpression.WITNESS_PUBLIC_KEY_HASH), cryptoOutput3.getScriptExpressions());
Assert.assertEquals("03fd433450b6924b4f7efdd5d1ed017d364be95ab2b592dc8bddb3b00c1c24f63f", TestUtils.bytesToHex(cryptoOutput3.getHdKey().getKey()));
Assert.assertEquals("72ede7334d5acf91c6fda622c205199c595a31f9218ed30792d301d5ee9e3a88", TestUtils.bytesToHex(cryptoOutput3.getHdKey().getChainCode()));
Assert.assertEquals("84'/0'/0'", cryptoOutput3.getHdKey().getOrigin().getPath());
Assert.assertEquals("0d5de1d7", TestUtils.bytesToHex(cryptoOutput3.getHdKey().getParentFingerprint()));
Assert.assertNull(cryptoOutput3.getHdKey().getChildren());
CryptoOutput cryptoOutput4 = urAccount.getOutputDescriptors().get(3);
Assert.assertEquals(Arrays.asList(ScriptExpression.SCRIPT_HASH, ScriptExpression.COSIGNER), cryptoOutput4.getScriptExpressions());
Assert.assertEquals("035ccd58b63a2cdc23d0812710603592e7457573211880cb59b1ef012e168e059a", TestUtils.bytesToHex(cryptoOutput4.getHdKey().getKey()));
Assert.assertEquals("88d3299b448f87215d96b0c226235afc027f9e7dc700284f3e912a34daeb1a23", TestUtils.bytesToHex(cryptoOutput4.getHdKey().getChainCode()));
Assert.assertEquals("45'", cryptoOutput4.getHdKey().getOrigin().getPath());
Assert.assertEquals("37b5eed4", TestUtils.bytesToHex(cryptoOutput4.getHdKey().getParentFingerprint()));
Assert.assertNull(cryptoOutput4.getHdKey().getChildren());
CryptoOutput cryptoOutput5 = urAccount.getOutputDescriptors().get(4);
Assert.assertEquals(Arrays.asList(ScriptExpression.SCRIPT_HASH, ScriptExpression.WITNESS_SCRIPT_HASH, ScriptExpression.COSIGNER), cryptoOutput5.getScriptExpressions());
Assert.assertEquals("032c78ebfcabdac6d735a0820ef8732f2821b4fb84cd5d6b26526938f90c050711", TestUtils.bytesToHex(cryptoOutput5.getHdKey().getKey()));
Assert.assertEquals("7953efe16a73e5d3f9f2d4c6e49bd88e22093bbd85be5a7e862a4b98a16e0ab6", TestUtils.bytesToHex(cryptoOutput5.getHdKey().getChainCode()));
Assert.assertEquals("48'/0'/0'/1'", cryptoOutput5.getHdKey().getOrigin().getPath());
Assert.assertEquals("59b69b2a", TestUtils.bytesToHex(cryptoOutput5.getHdKey().getParentFingerprint()));
Assert.assertNull(cryptoOutput5.getHdKey().getChildren());
CryptoOutput cryptoOutput6 = urAccount.getOutputDescriptors().get(5);
Assert.assertEquals(Arrays.asList(ScriptExpression.WITNESS_SCRIPT_HASH, ScriptExpression.COSIGNER), cryptoOutput6.getScriptExpressions());
Assert.assertEquals("0260563ee80c26844621b06b74070baf0e23fb76ce439d0237e87502ebbd3ca346", TestUtils.bytesToHex(cryptoOutput6.getHdKey().getKey()));
Assert.assertEquals("2fa0e41c9dc43dc4518659bfcef935ba8101b57dbc0812805dd983bc1d34b813", TestUtils.bytesToHex(cryptoOutput6.getHdKey().getChainCode()));
Assert.assertEquals("48'/0'/0'/2'", cryptoOutput6.getHdKey().getOrigin().getPath());
Assert.assertEquals("59b69b2a", TestUtils.bytesToHex(cryptoOutput6.getHdKey().getParentFingerprint()));
Assert.assertNull(cryptoOutput6.getHdKey().getChildren());
CryptoOutput cryptoOutput7 = urAccount.getOutputDescriptors().get(6);
Assert.assertEquals(Collections.singletonList(ScriptExpression.TAPROOT), cryptoOutput7.getScriptExpressions());
Assert.assertEquals("02bbb97cf9efa176b738efd6ee1d4d0fa391a973394fbc16e4c5e78e536cd14d2d", TestUtils.bytesToHex(cryptoOutput7.getHdKey().getKey()));
Assert.assertEquals("4b4693e1f794206ed1355b838da24949a92b63d02e58910bf3bd3d9c242281e6", TestUtils.bytesToHex(cryptoOutput7.getHdKey().getChainCode()));
Assert.assertEquals("86'/0'/0'", cryptoOutput7.getHdKey().getOrigin().getPath());
Assert.assertEquals("cec7070c", TestUtils.bytesToHex(cryptoOutput7.getHdKey().getParentFingerprint()));
Assert.assertNull(cryptoOutput7.getHdKey().getChildren());
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(urAccount.toCbor()));
String ur = "ur:account/oeadcyemrewytyaolttaadeetaadmutaaddloxaxhdclaxwmfmdeiamecsdsemgtvsjzcncygrkowtrontzschgezokstswkkscfmklrtauteyaahdcxiehfonurdppfyntapejpproypegrdawkgmaewejlsfdtsrfybdehcaflmtrlbdhpamtaaddyoeadlncsdwykaeykaeykaocyemrewytyaycynlytsnyltaadeetaadmhtaadmwtaaddloxaxhdclaostvelfemdyynwydwyaievosrgmambklovabdgypdglldvespsthysadamhpmjeinaahdcxntdllnaaeykoytdacygegwhgjsiyonpywmcmrpwphsvodsrerozsbyaxluzcoxdpamtaaddyoeadlncsehykaeykaeykaocyemrewytyaycypdbskeuytaadeetaadmwtaaddloxaxhdclaxzcfxeegdrpmogrgwkbzctlttweadkiengrwlhtprremouoluutqdpfbncedkynfhaahdcxjpwevdeogthttkmeswzcolcpsaahcfnshkhtehytclmnteatmoteadtlwynnftloamtaaddyoeadlncsghykaeykaeykaocyemrewytyaycybthlvytstaadeetaadmhtaadnytaaddloxaxhdclaxhhsnhdrpftdwuocntilydibehnecmovdfekpjkclcslasbhkpawsaddmcmmnahnyaahdcxlotedtndfymyltclhlmtpfsadscnhtztaolbnnkistaedegwfmmedreetnwmcycnamtaaddyoeadlfcsdpykaocyemrewytyaycyemrewytytaadeetaadmhtaadmetaadnytaaddloxaxhdclaxdwkswmztpytnswtsecnblfbayajkdldeclqzzolrsnhljedsgminetytbnahatbyaahdcxkkguwsvyimjkvwteytwztyswvendtpmncpasfrrylprnhtkblndrgrmkoyjtbkrpamtaaddyoeadlocsdyykaeykaeykadykaocyemrewytyaycyhkrpnddrtaadeetaadmetaadnytaaddloxaxhdclaohnhffmvsbndslrfgclpfjejyatbdpebacnzokotofxntaoemvskpaowmryfnotfgaahdcxdlnbvecentssfsssgylnhkrstoytecrdlyadrekirfaybglahltalsrfcaeerobwamtaaddyoeadlocsdyykaeykaeykaoykaocyemrewytyaycyhkrpnddrtaadeetaadnltaaddloxaxhdclaorkrhkeytwsoykorletwstbwycagtbsotmeptjkesgwrfcmveskvdmngujzttgtdpaahdcxgrfgmuvyylmwcxjtttechplslgoegagaptdniatidmhdmebdwfryfsnsdkcplyvaamtaaddyoeadlncshfykaeykaeykaocyemrewytyaycytostatbngmdavolk";
Assert.assertEquals(ur, urAccount.toUR().toString());
}
@Test
public void testAccount() throws Exception {
byte[] cbor = TestUtils.hexToBytes("A2011A37B5EED40286D90193D9012FA403582103EB3E2863911826374DE86C231A4B76F0B89DFA174AFB78D7F478199884D9DD320458206456A5DF2DB0F6D9AF72B2A1AF4B25F45200ED6FCC29C3440B311D4796B70B5B06D90130A10186182CF500F500F5081A99F9CDF7D90190D90194D9012FA403582102C7E4823730F6EE2CF864E2C352060A88E60B51A84E89E4C8C75EC22590AD6B690458209D2F86043276F9251A4A4F577166A5ABEB16B6EC61E226B5B8FA11038BFDA42D06D90130A101861831F500F500F5081AA80F7CDBD90194D9012FA403582103FD433450B6924B4F7EFDD5D1ED017D364BE95AB2B592DC8BDDB3B00C1C24F63F04582072EDE7334D5ACF91C6FDA622C205199C595A31F9218ED30792D301D5EE9E3A8806D90130A101861854F500F500F5081A0D5DE1D7D90190D9012FA4035821035CCD58B63A2CDC23D0812710603592E7457573211880CB59B1EF012E168E059A04582088D3299B448F87215D96B0C226235AFC027F9E7DC700284F3E912A34DAEB1A2306D90130A10182182DF5081A37B5EED4D90190D90191D9012FA4035821032C78EBFCABDAC6D735A0820EF8732F2821B4FB84CD5D6B26526938F90C0507110458207953EFE16A73E5D3F9F2D4C6E49BD88E22093BBD85BE5A7E862A4B98A16E0AB606D90130A101881830F500F500F501F5081A59B69B2AD90191D9012FA40358210260563EE80C26844621B06B74070BAF0E23FB76CE439D0237E87502EBBD3CA3460458202FA0E41C9DC43DC4518659BFCEF935BA8101B57DBC0812805DD983BC1D34B81306D90130A101881830F500F500F502F5081A59B69B2A");
UR ur = new UR("account", cbor);
String encoded = UREncoder.encode(ur);
Assert.assertEquals("ur:account/oeadcyemrewytyaolntaadmutaaddloxaxhdclaxwmfmdeiamecsdsemgtvsjzcncygrkowtrontzschgezokstswkkscfmklrtauteyaahdcxiehfonurdppfyntapejpproypegrdawkgmaewejlsfdtsrfybdehcaflmtrlbdhpamtaaddyoyadlncsdwykaeykaeykaycynlytsnyltaadmhtaadmwtaaddloxaxhdclaostvelfemdyynwydwyaievosrgmambklovabdgypdglldvespsthysadamhpmjeinaahdcxntdllnaaeykoytdacygegwhgjsiyonpywmcmrpwphsvodsrerozsbyaxluzcoxdpamtaaddyoyadlncsehykaeykaeykaycypdbskeuytaadmwtaaddloxaxhdclaxzcfxeegdrpmogrgwkbzctlttweadkiengrwlhtprremouoluutqdpfbncedkynfhaahdcxjpwevdeogthttkmeswzcolcpsaahcfnshkhtehytclmnteatmoteadtlwynnftloamtaaddyoyadlncsghykaeykaeykaycybthlvytstaadmhtaaddloxaxhdclaxhhsnhdrpftdwuocntilydibehnecmovdfekpjkclcslasbhkpawsaddmcmmnahnyaahdcxlotedtndfymyltclhlmtpfsadscnhtztaolbnnkistaedegwfmmedreetnwmcycnamtaaddyoyadlfcsdpykaycyemrewytytaadmhtaadmetaaddloxaxhdclaxdwkswmztpytnswtsecnblfbayajkdldeclqzzolrsnhljedsgminetytbnahatbyaahdcxkkguwsvyimjkvwteytwztyswvendtpmncpasfrrylprnhtkblndrgrmkoyjtbkrpamtaaddyoyadlocsdyykaeykaeykadykaycyhkrpnddrtaadmetaaddloxaxhdclaohnhffmvsbndslrfgclpfjejyatbdpebacnzokotofxntaoemvskpaowmryfnotfgaahdcxdlnbvecentssfsssgylnhkrstoytecrdlyadrekirfaybglahltalsrfcaeerobwamtaaddyoyadlocsdyykaeykaeykaoykaycyhkrpnddrgdaogykb", encoded);
}
@Test
public void testPairPathComponent() throws Exception {
String ur = "ur:account/oeadcylpvefyjeaolttaadeetaadmutaaddlonaxhdclaxhkfzdphtkplevtqzprkgnnsacagesgctzmspytctdstocsbgmkamurrdpffmtsseaahdcxpdnbdysgfeaycfsegwmhwfjewzfwdmesrlqdhglagahkytcflbrtsedraefwbweyamtaaddyoeadlncsdwykaeykaeykaocylpvefyjeattaaddyoyadlslraewkadwklawkaycypsjpsbfntaadeetaadmhtaadmwtaaddlonaxhdclaouypakomsrlhlqzvwlymesadevybkueqdoxhdcximrdhgfhtybwvyhdkeyklddpmwaahdcxwnvsaxgsdldtmurknyfpcedyiaiopautyafrpejoaxjncfhhhtpfdetteotnknsramtaaddyoeadlncsehykaeykaeykaocylpvefyjeattaaddyoyadlslraewkadwklawkaycyoeyagmmstaadeetaadmwtaaddlonaxhdclaorernoyonguhlfsdecnmohnuydwnnchjpuyroftdnaadkatcfkirdtkispsiajycxaahdcxlyutkbnymklbdskesbihbelysedwlupklfmhnntlfwsegsvwwspkghkgvwheiejoamtaaddyoeadlncsghykaeykaeykaocylpvefyjeattaaddyoyadlslraewkadwklawkaycywyqzwzkptaadeetaadmhtaadnytaaddlonaxhdclaoiorpcxecynfloxtamhlsaarkkotpclcydahtamluhnimkertlgftknoerymobaneaahdcxrsatfdqdenvtspvdieindaztrpcazsknzsoywkghfhtyswdkkpjstbneayfncxoxamtaaddyoeadlfcsdpykaocylpvefyjeattaaddyoyadlslraewkadwklawkaycylpvefyjetaadeetaadmhtaadmetaadnytaaddlonaxhdclaoldpfglrkwntlvwlarsdmnbzefmghkeeeoteerdpfframuoidstpacswmnnutcwkkaahdcxhkrozmjneceoldplnluetscyjnbdhsldenontncafgdkmdvlsnidamlnvwfzsstaamtaaddyoeadlocsdyykaeykaeykadykaocylpvefyjeattaaddyoyadlslraewkadwklawkaycyrhimryuotaadeetaadmetaadnytaaddlonaxhdclaowysfahwsqdclsnfmwmjlgoeerhzoteherosnmyhkinolrlspdadsasswlarpvtpfaahdcxwybnryoewshycwghlfhhwtbscxpyylenpkolmoftgymksbdpvsgtlbdefhrswnyaamtaaddyoeadlocsdyykaeykaeykaoykaocylpvefyjeattaaddyoyadlslraewkadwklawkaycyrhimryuotaadeetaadnltaaddlonaxhdclaxpmctzmjzemjspsplgrlgtyvssffrzcrlgogojnmncwbdtytelblyhlflmtdnkifdaahdcxgytkgujnjtaszejprdpmoskseehkamvlcersoxdlghsglagmjkjewmrlpfonwldwamtaaddyoeadlncshfykaeykaeykaocylpvefyjeattaaddyoyadlslraewkadwklawkaycynsmwdtfzryrorncp";
URDecoder urDecoder = new URDecoder();
urDecoder.receivePart(ur);
URDecoder.Result urResult = urDecoder.getResult();
if(urResult.type == ResultType.SUCCESS) {
if(urResult.ur.getRegistryType().equals(RegistryType.CRYPTO_ACCOUNT)) {
URAccount urAccount = (URAccount)urResult.ur.decodeFromRegistry();
Assert.assertEquals("<0;1>/*", urAccount.getOutputDescriptors().get(0).getHdKey().getChildren().getPath());
}
}
}
}

View file

@ -0,0 +1,24 @@
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 URAddressTest {
@Test
public void testAddress() throws CborException {
String hex = "A1035477BFF20C60E522DFAA3350C39B030A5D004E839A";
byte[] data = TestUtils.hexToBytes(hex);
List<DataItem> items = CborDecoder.decode(data);
URAddress urAddress = URAddress.fromCbor(items.get(0));
Assert.assertEquals("77bff20c60e522dfaa3350c39b030a5d004e839a", TestUtils.bytesToHex(urAddress.getData()));
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(urAddress.toCbor()));
String ur = "ur:address/oyaxghktrswzbnhnvwcpurpkeogdsrndaxbkhlaegllsnyolrsemgu";
Assert.assertEquals(ur, urAddress.toUR().toString());
}
}

View file

@ -0,0 +1,41 @@
package com.sparrowwallet.hummingbird.registry;
import org.junit.Assert;
import org.junit.Test;
public class URCoinInfoTest {
@Test
public void testBitcoinCoinInfo() {
URCoinInfo urCoinInfo = new URCoinInfo(URCoinInfo.Type.BITCOIN, URCoinInfo.Network.MAINNET);
Assert.assertSame(urCoinInfo.getType().typeValue, URCoinInfo.Type.BITCOIN.typeValue);
}
@Test
public void testEthereumCoinInfo() {
URCoinInfo urCoinInfo = new URCoinInfo(URCoinInfo.Type.ETHEREUM, URCoinInfo.Network.MAINNET);
Assert.assertSame(urCoinInfo.getType().typeValue, URCoinInfo.Type.ETHEREUM.typeValue);
}
@Test
public void testGoerliEthereumCoinInfo() {
URCoinInfo urCoinInfo = new URCoinInfo(URCoinInfo.Type.ETHEREUM, URCoinInfo.Network.GOERLI);
Assert.assertSame(urCoinInfo.getType().typeValue, URCoinInfo.Type.ETHEREUM.typeValue);
Assert.assertSame(urCoinInfo.getNetwork().networkValue, URCoinInfo.Network.GOERLI.networkValue);
}
@Test(expected = IllegalArgumentException.class)
public void testGoerliSupportedOnlyWithEthereum() {
new URCoinInfo(URCoinInfo.Type.BITCOIN, URCoinInfo.Network.GOERLI);
}
@Test(expected = IllegalArgumentException.class)
public void testGoerliSupportedOnlyWithEthereumWithValues() {
new URCoinInfo(URCoinInfo.Type.BITCOIN.typeValue, URCoinInfo.Network.GOERLI.networkValue);
}
@Test
public void testNullTypeCoinInfo() {
URCoinInfo urCoinInfo = new URCoinInfo(null, URCoinInfo.Network.MAINNET);
Assert.assertSame(urCoinInfo.getType(), URCoinInfo.Type.BITCOIN);
}
}

View file

@ -0,0 +1,26 @@
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 URECKeyTest {
@Test
public void testECKey() throws CborException {
String hex = "A202F50358208C05C4B4F3E88840A4F4B5F155CFD69473EA169F3D0431B7A6787A23777F08AA";
byte[] data = TestUtils.hexToBytes(hex);
List<DataItem> items = CborDecoder.decode(data);
URECKey urECKey = URECKey.fromCbor(items.get(0));
Assert.assertEquals(0, urECKey.getCurve());
Assert.assertTrue(urECKey.isPrivateKey());
Assert.assertEquals("8c05c4b4f3e88840a4f4b5f155cfd69473ea169f3d0431b7a6787a23777f08aa", TestUtils.bytesToHex(urECKey.getData()));
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(urECKey.toCbor()));
String ur = "ur:eckey/oeaoykaxhdcxlkahssqzwfvslofzoxwkrewngotktbmwjkwdcmnefsaaehrlolkskncnktlbaypkrphsmyid";
Assert.assertEquals(ur, urECKey.toUR().toString());
}
}

View file

@ -0,0 +1,97 @@
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 URHDKeyTest {
@Test
public void testMasterKey() throws CborException {
String hex = "a301f503582100e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35045820873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508";
byte[] data = TestUtils.hexToBytes(hex);
List<DataItem> items = CborDecoder.decode(data);
URHDKey urHDKey = URHDKey.fromCbor(items.get(0));
Assert.assertTrue(urHDKey.isMaster());
Assert.assertEquals("00e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35", TestUtils.bytesToHex(urHDKey.getKey()));
Assert.assertEquals("873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508", TestUtils.bytesToHex(urHDKey.getChainCode()));
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(urHDKey.toCbor()));
String ur = "ur:hdkey/otadykaxhdclaevswfdmjpfswpwkahcywspsmndwmusoskprbbehetchsnpfcybbmwrhchspfxjeecaahdcxltfszmlyrtdlgmhfcnzcctvwcmkbpsftgonbgauefsehgrqzdmvodizmweemtlaybakiylat";
Assert.assertEquals(ur, urHDKey.toUR().toString());
}
@Test
public void testPublicTestnet() throws CborException {
String hex = "a5035821026fe2355745bb2db3630bbc80ef5d58951c963c841f54170ba6e5c12be7fc12a6045820ced155c72456255881793514edc5bd9447e7f74abb88c6d6b6480fd016ee8c8505d99d71a1020106d99d70a1018a182cf501f501f500f401f4081ae9181cf3";
byte[] data = TestUtils.hexToBytes(hex);
List<DataItem> items = CborDecoder.decode(data);
URHDKey urHDKey = URHDKey.fromCbor(items.get(0));
Assert.assertFalse(urHDKey.isMaster());
Assert.assertFalse(urHDKey.isPrivateKey());
Assert.assertEquals("026fe2355745bb2db3630bbc80ef5d58951c963c841f54170ba6e5c12be7fc12a6", TestUtils.bytesToHex(urHDKey.getKey()));
Assert.assertEquals("ced155c72456255881793514edc5bd9447e7f74abb88c6d6b6480fd016ee8c85", TestUtils.bytesToHex(urHDKey.getChainCode()));
Assert.assertEquals(urHDKey.getUseInfo().getNetwork(), URCoinInfo.Network.TESTNET);
Assert.assertEquals("44'/1'/1'/0/1", urHDKey.getOrigin().getPath());
Assert.assertNull(urHDKey.getOrigin().getDepth());
Assert.assertEquals("e9181cf3", TestUtils.bytesToHex(urHDKey.getParentFingerprint()));
Assert.assertNull(urHDKey.getChildren());
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(urHDKey.toCbor()));
String ur = "ur:hdkey/onaxhdclaojlvoechgferkdpqdiabdrflawshlhdmdcemtfnlrctghchbdolvwsednvdztbgolaahdcxtottgostdkhfdahdlykkecbbweskrymwflvdylgerkloswtbrpfdbsticmwylklpahtantjsoyaoadamtantjooyadlecsdwykadykadykaewkadwkaycywlcscewfjnkpvllt";
Assert.assertEquals(ur, urHDKey.toUR().toString());
}
@Test
public void testMasterPublicKey() throws CborException {
String hex = "a303582103ac3df08ec59f6f1cdc55b3007f90f1a98435ec345c3cac400ede1dd533d75fa9045820e8145db627e79188e14c1fd6c772998509961d358fe8ecf3d7cc43bb1d0f952006d99d70a20180021a854bc782";
byte[] data = TestUtils.hexToBytes(hex);
List<DataItem> items = CborDecoder.decode(data);
URHDKey urHDKey = URHDKey.fromCbor(items.get(0));
Assert.assertFalse(urHDKey.isMaster());
Assert.assertFalse(urHDKey.isPrivateKey());
Assert.assertEquals("03ac3df08ec59f6f1cdc55b3007f90f1a98435ec345c3cac400ede1dd533d75fa9", TestUtils.bytesToHex(urHDKey.getKey()));
Assert.assertEquals("e8145db627e79188e14c1fd6c772998509961d358fe8ecf3d7cc43bb1d0f9520", TestUtils.bytesToHex(urHDKey.getChainCode()));
Assert.assertNull(urHDKey.getOrigin().getPath());
Assert.assertEquals("854bc782", TestUtils.bytesToHex(urHDKey.getOrigin().getSourceFingerprint()));
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(urHDKey.toCbor()));
String ur = "ur:hdkey/otaxhdclaxpsfswtmnsknejlceuogoqdaelbmhwnptlrecwpeehhfnpsfzbauecatleotsheptaahdcxvsbbhlrpdivdmelovygscttbstjpnllpasmtcaecmyvswpwftssffxrkcabsmdcxamtantjooeadlaaocylpgrstlfdtflonhd";
Assert.assertEquals(ur, urHDKey.toUR().toString());
}
@Test
public void testZeroMasterFingerprint() throws CborException {
String hex = "a303582103ac3df08ec59f6f1cdc55b3007f90f1a98435ec345c3cac400ede1dd533d75fa9045820e8145db627e79188e14c1fd6c772998509961d358fe8ecf3d7cc43bb1d0f952006d99d70a201800200";
byte[] data = TestUtils.hexToBytes(hex);
List<DataItem> items = CborDecoder.decode(data);
URHDKey urHDKey = URHDKey.fromCbor(items.get(0));
Assert.assertFalse(urHDKey.isMaster());
Assert.assertFalse(urHDKey.isPrivateKey());
Assert.assertEquals("03ac3df08ec59f6f1cdc55b3007f90f1a98435ec345c3cac400ede1dd533d75fa9", TestUtils.bytesToHex(urHDKey.getKey()));
Assert.assertEquals("e8145db627e79188e14c1fd6c772998509961d358fe8ecf3d7cc43bb1d0f9520", TestUtils.bytesToHex(urHDKey.getChainCode()));
Assert.assertNull(urHDKey.getOrigin().getPath());
Assert.assertEquals("00000000", TestUtils.bytesToHex(urHDKey.getOrigin().getSourceFingerprint()));
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(urHDKey.toCbor()));
String ur = "ur:hdkey/otaxhdclaxpsfswtmnsknejlceuogoqdaelbmhwnptlrecwpeehhfnpsfzbauecatleotsheptaahdcxvsbbhlrpdivdmelovygscttbstjpnllpasmtcaecmyvswpwftssffxrkcabsmdcxamtantjooeadlaaoaedpmwehrt";
Assert.assertEquals(ur, urHDKey.toUR().toString());
}
@Test
public void testShortMasterFingerprint() throws CborException {
String hex = "a303582103ac3df08ec59f6f1cdc55b3007f90f1a98435ec345c3cac400ede1dd533d75fa9045820e8145db627e79188e14c1fd6c772998509961d358fe8ecf3d7cc43bb1d0f952006d99d70a201800218ff";
byte[] data = TestUtils.hexToBytes(hex);
List<DataItem> items = CborDecoder.decode(data);
URHDKey urHDKey = URHDKey.fromCbor(items.get(0));
Assert.assertFalse(urHDKey.isMaster());
Assert.assertFalse(urHDKey.isPrivateKey());
Assert.assertEquals("03ac3df08ec59f6f1cdc55b3007f90f1a98435ec345c3cac400ede1dd533d75fa9", TestUtils.bytesToHex(urHDKey.getKey()));
Assert.assertEquals("e8145db627e79188e14c1fd6c772998509961d358fe8ecf3d7cc43bb1d0f9520", TestUtils.bytesToHex(urHDKey.getChainCode()));
Assert.assertNull(urHDKey.getOrigin().getPath());
Assert.assertEquals("000000ff", TestUtils.bytesToHex(urHDKey.getOrigin().getSourceFingerprint()));
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(urHDKey.toCbor()));
String ur = "ur:hdkey/otaxhdclaxpsfswtmnsknejlceuogoqdaelbmhwnptlrecwpeehhfnpsfzbauecatleotsheptaahdcxvsbbhlrpdivdmelovygscttbstjpnllpasmtcaecmyvswpwftssffxrkcabsmdcxamtantjooeadlaaocszmvagmtotp";
Assert.assertEquals(ur, urHDKey.toUR().toString());
}
}

View file

@ -0,0 +1,65 @@
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 UROutputDescriptorTest {
@Test
public void testECKeyPublic() throws CborException {
String hex = "d99d74a20166706b284030290281d99d72a103582103e220e776d811c44075a4a260734445c8967865f5357ba98ead3bc6a6552c36f2";
byte[] data = TestUtils.hexToBytes(hex);
List<DataItem> items = CborDecoder.decode(data);
UROutputDescriptor urOutputDescriptor = UROutputDescriptor.fromCbor(items.get(0));
Assert.assertEquals("pk(@0)", urOutputDescriptor.getSource());
Assert.assertTrue(urOutputDescriptor.getKeys().size() == 1 && urOutputDescriptor.getKeys().get(0) instanceof URECKey);
URECKey urECKey = (URECKey) urOutputDescriptor.getKeys().get(0);
Assert.assertEquals("03e220e776d811c44075a4a260734445c8967865f5357ba98ead3bc6a6552c36f2", TestUtils.bytesToHex(urECKey.getData()));
}
@Test
public void testAddress() throws CborException {
String hex = "d99d74a2016861646472284030290281d99d73a301d99d71a10201020203544efd3ded47d967e4122982422c9d84db60503972";
byte[] data = TestUtils.hexToBytes(hex);
List<DataItem> items = CborDecoder.decode(data);
UROutputDescriptor urOutputDescriptor = UROutputDescriptor.fromCbor(items.get(0));
Assert.assertEquals("addr(@0)", urOutputDescriptor.getSource());
Assert.assertTrue(urOutputDescriptor.getKeys().size() == 1 && urOutputDescriptor.getKeys().get(0) instanceof URAddress);
URAddress urAddress = (URAddress) urOutputDescriptor.getKeys().get(0);
Assert.assertEquals("4efd3ded47d967e4122982422c9d84db60503972", TestUtils.bytesToHex(urAddress.getData()));
}
@Test
public void testECKeyPrivate() throws CborException {
String hex = "d99d74a20167706b68284030290281d99d72a202f5035820347c4acb73f7bf2268b958230e215986eda87a984959c4ddbd4d62c07de6310e";
byte[] data = TestUtils.hexToBytes(hex);
List<DataItem> items = CborDecoder.decode(data);
UROutputDescriptor urOutputDescriptor = UROutputDescriptor.fromCbor(items.get(0));
Assert.assertEquals("pkh(@0)", urOutputDescriptor.getSource());
Assert.assertTrue(urOutputDescriptor.getKeys().size() == 1 && urOutputDescriptor.getKeys().get(0) instanceof URECKey);
URECKey urECKey = (URECKey) urOutputDescriptor.getKeys().get(0);
Assert.assertEquals("347c4acb73f7bf2268b958230e215986eda87a984959c4ddbd4d62c07de6310e", TestUtils.bytesToHex(urECKey.getData()));
}
@Test
public void testMulti() throws CborException {
String hex = "d99d74a301781c77736828736f727465646d756c746928322c40302c40312c403229290283d99d6fa5035821021c0b479ecf6e67713ddf0c43b634592f51c037b6f951fb1dc6361a98b1e5735e0458206b3a4cfb6a45f6305efe6e0e976b5d26ba27f7c344d7fc7abef7be2d06d52dfd06d99d70a201881830f500f500f502f5021adc56727607d99d70a101838400f401f480f4081a18f8c2e7d99d6fa50358210397fcf2274abd243d42d42d3c248608c6d1935efca46138afef43af08e9712896045820c887c72d9d8ac29cddd5b2b060e8b0239039a149c784abe6079e24445db4aa8a06d99d70a201881830f500f500f502f5021af245ae3807d99d70a101838400f401f480f4081a221eb5a0d99d6fa5035821028342f5f7773f6fab374e1c2d3ccdba26bc0933fc4f63828b662b4357e4cc37910458205afed56d755c088320ec9bc6acd84d33737b580083759e0a0ff8f26e429e0b7706d99d70a201881830f500f500f502f5021ac5d8729707d99d70a101838400f401f480f4081a1c0ae906036f5361746f7368692773205374617368";
byte[] data = TestUtils.hexToBytes(hex);
List<DataItem> items = CborDecoder.decode(data);
UROutputDescriptor urOutputDescriptor = UROutputDescriptor.fromCbor(items.get(0));
Assert.assertEquals("wsh(sortedmulti(2,@0,@1,@2))", urOutputDescriptor.getSource());
Assert.assertTrue(urOutputDescriptor.getKeys().size() == 3 && urOutputDescriptor.getKeys().stream().allMatch(item -> item instanceof URHDKey));
URHDKey urHDKey1 = (URHDKey) urOutputDescriptor.getKeys().get(0);
Assert.assertNull(urHDKey1.getUseInfo());
Assert.assertEquals("dc567276", TestUtils.bytesToHex(urHDKey1.getOrigin().getSourceFingerprint()));
Assert.assertEquals("48'/0'/0'/2'", urHDKey1.getOrigin().getPath());
Assert.assertEquals("021c0b479ecf6e67713ddf0c43b634592f51c037b6f951fb1dc6361a98b1e5735e", TestUtils.bytesToHex(urHDKey1.getKey()));
Assert.assertEquals("6b3a4cfb6a45f6305efe6e0e976b5d26ba27f7c344d7fc7abef7be2d06d52dfd", TestUtils.bytesToHex(urHDKey1.getChainCode()));
Assert.assertEquals("Satoshi's Stash", urOutputDescriptor.getName());
}
}

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 URPSBTTest {
@Test
public void testEncode() throws CborException {
String hex = "58A770736274FF01009A020000000258E87A21B56DAF0C23BE8E7070456C336F7CBAA5C8757924F545887BB2ABDD750000000000FFFFFFFF838D0427D0EC650A68AA46BB0B098AEA4422C071B2CA78352A077959D07CEA1D0100000000FFFFFFFF0270AAF00800000000160014D85C2B71D0060B09C9886AEB815E50991DDA124D00E1F5050000000016001400AEA9A2E5F0F876A588DF5546E8742D1D87008F000000000000000000";
byte[] data = TestUtils.hexToBytes(hex);
List<DataItem> items = CborDecoder.decode(data);
URPSBT urPsbt = URPSBT.fromCbor(items.get(0));
String psbtHex = "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000000000000000000";
Assert.assertArrayEquals(TestUtils.hexToBytes(psbtHex), urPsbt.getPsbt());
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(urPsbt.toCbor()));
String ur = "ur:psbt/hdosjojkidjyzmadaenyaoaeaeaeaohdvsknclrejnpebncnrnmnjojofejzeojlkerdonspkpkkdkykfelokgprpyutkpaeaeaeaeaezmzmzmzmlslgaaditiwpihbkispkfgrkbdaslewdfycprtjsprsgksecdratkkhktikewdcaadaeaeaeaezmzmzmzmaojopkwtayaeaeaeaecmaebbtphhdnjstiambdassoloimwmlyhygdnlcatnbggtaevyykahaeaeaeaecmaebbaeplptoevwwtyakoonlourgofgvsjydpcaltaemyaeaeaeaeaeaeaeaeaebkgdcarh";
Assert.assertEquals(ur, urPsbt.toUR().toString());
}
}

View file

@ -0,0 +1,27 @@
package com.sparrowwallet.hummingbird.registry;
import co.nstant.in.cbor.model.ByteString;
import com.sparrowwallet.hummingbird.TestUtils;
import com.sparrowwallet.hummingbird.UR;
import com.sparrowwallet.hummingbird.URDecoder;
import org.junit.Assert;
import org.junit.Test;
public class URSSKRTest {
private final String splitVector = "4bbf1101025abd490ee65b6084859854ee67736e75";
private final String urVector = "ur:sskr/gogrrsbyadaohtrygabavahphnlrlpmkghwyiojkjtkpmdkncfjp";
@Test
public void testSskrToUR() {
byte[] data = TestUtils.hexToBytes(splitVector);
URSSKR sskr = new URSSKR(data);
Assert.assertEquals(urVector, sskr.toUR().toString());
}
@Test
public void testURtoSskr() throws UR.URException {
UR ur = URDecoder.decode(urVector);
URSSKR sskr = URSSKR.fromCbor(new ByteString(ur.getCborBytes()));
Assert.assertEquals(splitVector, TestUtils.bytesToHex(sskr.getSplit()));
}
}

View file

@ -0,0 +1,30 @@
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.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
public class URSeedTest {
private final DateFormat dateFormat = new SimpleDateFormat("dd MMM yyyy", Locale.ENGLISH);
@Test
public void testSeed() throws CborException {
String hex = "A20150C7098580125E2AB0981253468B2DBC5202D8641947DA";
byte[] data = TestUtils.hexToBytes(hex);
List<DataItem> items = CborDecoder.decode(data);
URSeed urSeed = URSeed.fromCbor(items.get(0));
Assert.assertEquals("c7098580125e2ab0981253468b2dbc52", TestUtils.bytesToHex(urSeed.getSeed()));
Assert.assertEquals("12 May 2020", dateFormat.format(urSeed.getBirthdate()));
Assert.assertEquals(hex.toLowerCase(), TestUtils.encode(urSeed.toCbor()));
String ur = "ur:seed/oeadgdstaslplabghydrpfmkbggufgludprfgmaotpiecffltnlpqdenos";
Assert.assertEquals(ur, urSeed.toUR().toString());
}
}