mirror of
https://github.com/sparrowwallet/hummingbird.git
synced 2024-11-02 18:46:45 +00:00
add new ur registry types for 40000 range including version 3 output-descriptor type
This commit is contained in:
parent
1a7d56a3a9
commit
2ac6c346cd
20 changed files with 1027 additions and 1 deletions
|
@ -22,7 +22,17 @@ public enum RegistryType {
|
||||||
CRYPTO_OUTPUT("crypto-output", 308, CryptoOutput.class),
|
CRYPTO_OUTPUT("crypto-output", 308, CryptoOutput.class),
|
||||||
CRYPTO_SSKR("crypto-sskr", 309, CryptoSskr.class),
|
CRYPTO_SSKR("crypto-sskr", 309, CryptoSskr.class),
|
||||||
CRYPTO_PSBT("crypto-psbt", 310, CryptoPSBT.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 String type;
|
||||||
private final Integer tag;
|
private final Integer tag;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue