mirror of
https://github.com/sparrowwallet/drongo.git
synced 2025-11-05 11:56:38 +00:00
Add satochip support: initial commit with debug traces
todo: clean code
This commit is contained in:
parent
2b7b650fae
commit
2f1644ee16
3 changed files with 202 additions and 1 deletions
|
|
@ -307,6 +307,11 @@ public class ECKey {
|
||||||
return pub.getEncoded();
|
return pub.getEncoded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SATOCHIP
|
||||||
|
public byte[] getPubKey(Boolean compressed) {
|
||||||
|
return pub.getEncoded(compressed);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the x coordinate of the raw public key value. This appears in transaction scriptPubKeys for Taproot outputs.
|
* Gets the x coordinate of the raw public key value. This appears in transaction scriptPubKeys for Taproot outputs.
|
||||||
*/
|
*/
|
||||||
|
|
@ -428,14 +433,119 @@ public class ECKey {
|
||||||
return verify(sigHash.getBytes(), signature);
|
return verify(sigHash.getBytes(), signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ECKey getTweakedOutputKey() {
|
public ECKey getTweakedOutputKey() {
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey START");
|
||||||
TaprootPubKey taprootPubKey = liftX(getPubKeyXCoord());
|
TaprootPubKey taprootPubKey = liftX(getPubKeyXCoord());
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey taprootPubKey: " + taprootPubKey);
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey taprootPubKey.ecPoint: " + taprootPubKey.ecPoint);
|
||||||
ECPoint internalKey = taprootPubKey.ecPoint;
|
ECPoint internalKey = taprootPubKey.ecPoint;
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey internalKey: " + internalKey);
|
||||||
|
//debug
|
||||||
|
ECKey tmp2 = ECKey.fromPublicOnly(internalKey, true);
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey internalKey: " + Utils.bytesToHex(tmp2.getPubKey()));
|
||||||
|
//endbug
|
||||||
|
|
||||||
byte[] taggedHash = Utils.taggedHash("TapTweak", internalKey.getXCoord().getEncoded());
|
byte[] taggedHash = Utils.taggedHash("TapTweak", internalKey.getXCoord().getEncoded());
|
||||||
ECKey tweakValue = ECKey.fromPrivate(taggedHash);
|
ECKey tweakValue = ECKey.fromPrivate(taggedHash);
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey tweakValue: " + Utils.bytesToHex(tweakValue.getPubKey()));
|
||||||
ECPoint outputKey = internalKey.add(tweakValue.getPubKeyPoint());
|
ECPoint outputKey = internalKey.add(tweakValue.getPubKeyPoint());
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey outputKey: " + outputKey);
|
||||||
|
|
||||||
|
//debug
|
||||||
|
ECKey tmp = ECKey.fromPublicOnly(outputKey, true);
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey outputKey: " + Utils.bytesToHex(tmp.getPubKey()));
|
||||||
|
//endbug
|
||||||
|
|
||||||
if(hasPrivKey()) {
|
if(hasPrivKey()) {
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey PRIVKEY NEW VERSION");
|
||||||
|
|
||||||
|
// isEven => used to determine private key for tweaking
|
||||||
|
Boolean isEven = (getPubKey()[0] == 0x02);
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey getPubKey(): " + Utils.bytesToHex(getPubKey()));
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey isEven getPubKey()[0]: " + getPubKey()[0]);
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey isEven: " + isEven);
|
||||||
|
|
||||||
|
BigInteger taprootPriv;
|
||||||
|
if (isEven){
|
||||||
|
taprootPriv = priv;
|
||||||
|
} else {
|
||||||
|
taprootPriv = CURVE_PARAMS.getCurve().getOrder().subtract(priv);
|
||||||
|
}
|
||||||
|
BigInteger tweakedPrivKey = taprootPriv.add(tweakValue.getPrivKey()).mod(CURVE_PARAMS.getCurve().getOrder());
|
||||||
|
|
||||||
|
//debug
|
||||||
|
ECKey tmp3 = new ECKey(tweakedPrivKey, outputKey, true);
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey outputKey with private: " + Utils.bytesToHex(tmp3.getPubKey()));
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey outputKey private: " + tmp3.getPrivKey());
|
||||||
|
//endbug
|
||||||
|
|
||||||
|
|
||||||
|
/* log.debug("SATOCHIP ECKey getTweakedOutputKey PRIVKEY NEW VERSION SWITCH EVENNESS");
|
||||||
|
if (isEven){
|
||||||
|
//taprootPriv = priv;
|
||||||
|
taprootPriv = CURVE_PARAMS.getCurve().getOrder().subtract(priv);
|
||||||
|
} else {
|
||||||
|
taprootPriv = priv;
|
||||||
|
//taprootPriv = CURVE_PARAMS.getCurve().getOrder().subtract(priv);
|
||||||
|
}
|
||||||
|
tweakedPrivKey = taprootPriv.add(tweakValue.getPrivKey()).mod(CURVE_PARAMS.getCurve().getOrder());
|
||||||
|
|
||||||
|
//debug
|
||||||
|
ECKey tmp5 = new ECKey(tweakedPrivKey, outputKey, true);
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey outputKey with private: " + Utils.bytesToHex(tmp5.getPubKey()));
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey outputKey private: " + tmp5.getPrivKey());
|
||||||
|
//endbug*/
|
||||||
|
|
||||||
|
|
||||||
|
/* // ORIGNAL VERSION
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey PRIVKEY OLD VERSION");
|
||||||
|
taprootPriv = priv;
|
||||||
|
tweakedPrivKey = taprootPriv.add(tweakValue.getPrivKey()).mod(CURVE_PARAMS.getCurve().getOrder());
|
||||||
|
//TODO: Improve on this hack. How do we know whether to negate the private key before tweaking it?
|
||||||
|
if(!ECKey.fromPrivate(tweakedPrivKey).getPubKeyPoint().equals(outputKey)) {
|
||||||
|
taprootPriv = CURVE_PARAMS.getCurve().getOrder().subtract(priv);
|
||||||
|
tweakedPrivKey = taprootPriv.add(tweakValue.getPrivKey()).mod(CURVE_PARAMS.getCurve().getOrder());
|
||||||
|
}
|
||||||
|
//debug
|
||||||
|
ECKey tmp4 = new ECKey(tweakedPrivKey, outputKey, true);
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey outputKey with private: " + Utils.bytesToHex(tmp4.getPubKey()));
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey outputKey private: " + tmp4.getPrivKey());
|
||||||
|
//endbug*/
|
||||||
|
|
||||||
|
|
||||||
|
return new ECKey(tweakedPrivKey, outputKey, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ECKey.fromPublicOnly(outputKey, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ECKey getTweakedOutputKeyOLD() {
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey START");
|
||||||
|
TaprootPubKey taprootPubKey = liftX(getPubKeyXCoord());
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey taprootPubKey: " + taprootPubKey);
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey taprootPubKey.ecPoint: " + taprootPubKey.ecPoint);
|
||||||
|
ECPoint internalKey = taprootPubKey.ecPoint;
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey internalKey: " + internalKey);
|
||||||
|
//debug
|
||||||
|
ECKey tmp2 = ECKey.fromPublicOnly(internalKey, true);
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey outputKey: " + Utils.bytesToHex(tmp2.getPubKey()));
|
||||||
|
//endbug
|
||||||
|
|
||||||
|
byte[] taggedHash = Utils.taggedHash("TapTweak", internalKey.getXCoord().getEncoded());
|
||||||
|
ECKey tweakValue = ECKey.fromPrivate(taggedHash);
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey tweakValue: " + Utils.bytesToHex(tweakValue.getPubKey()));
|
||||||
|
ECPoint outputKey = internalKey.add(tweakValue.getPubKeyPoint());
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey outputKey: " + outputKey);
|
||||||
|
|
||||||
|
//debug
|
||||||
|
ECKey tmp = ECKey.fromPublicOnly(outputKey, true);
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey outputKey: " + Utils.bytesToHex(tmp.getPubKey()));
|
||||||
|
//endbug
|
||||||
|
|
||||||
|
if(hasPrivKey()) {
|
||||||
|
log.debug("SATOCHIP ECKey getTweakedOutputKey hasPrivKey(): true");
|
||||||
BigInteger taprootPriv = priv;
|
BigInteger taprootPriv = priv;
|
||||||
BigInteger tweakedPrivKey = taprootPriv.add(tweakValue.getPrivKey()).mod(CURVE_PARAMS.getCurve().getOrder());
|
BigInteger tweakedPrivKey = taprootPriv.add(tweakValue.getPrivKey()).mod(CURVE_PARAMS.getCurve().getOrder());
|
||||||
//TODO: Improve on this hack. How do we know whether to negate the private key before tweaking it?
|
//TODO: Improve on this hack. How do we know whether to negate the private key before tweaking it?
|
||||||
|
|
|
||||||
|
|
@ -250,6 +250,75 @@ public class PSBTInput {
|
||||||
this.index = index;
|
this.index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// satochip debug
|
||||||
|
public void printDebugInfo(){
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() START");
|
||||||
|
// partialSignatures
|
||||||
|
try{
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() partialSignatures: Map<ECKey, TransactionSignature>");
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() partialSignatures.size(): " + partialSignatures.size());
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() partialSignatures: " + partialSignatures);
|
||||||
|
for (Map.Entry<ECKey, TransactionSignature> entry : partialSignatures.entrySet()) {
|
||||||
|
ECKey key = entry.getKey();
|
||||||
|
TransactionSignature value = entry.getValue();
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() partialSignatures pubkey: " + Utils.bytesToHex(key.getPubKey()));
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() partialSignatures sig: " + Utils.bytesToHex(value.encodeToBitcoin()));
|
||||||
|
}
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() partialSignatures END");
|
||||||
|
} catch(Exception e) {
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() partialSignatures exception: " + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// derivedPublicKeys
|
||||||
|
try{
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() derivedPublicKeys: Map<ECKey, KeyDerivation>");
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() derivedPublicKeys.size(): " + derivedPublicKeys.size());
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() derivedPublicKeys: " + derivedPublicKeys);
|
||||||
|
for (Map.Entry<ECKey, KeyDerivation> entry : derivedPublicKeys.entrySet()) {
|
||||||
|
ECKey key = entry.getKey();
|
||||||
|
KeyDerivation value = entry.getValue();
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() derivedPublicKeys pubkey: " + Utils.bytesToHex(key.getPubKey()));
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() derivedPublicKeys derivation: " + value.getDerivationPath());
|
||||||
|
}
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() derivedPublicKeys END");
|
||||||
|
} catch(Exception e) {
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() derivedPublicKeys exception: " + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransactionSignature tapKeyPathSignature;
|
||||||
|
if (tapKeyPathSignature!=null) {
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() tapKeyPathSignature: " + Utils.bytesToHex(tapKeyPathSignature.encodeToBitcoin()));
|
||||||
|
} else {
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() tapKeyPathSignature: null");
|
||||||
|
}
|
||||||
|
// ECKey tapInternalKey
|
||||||
|
if (tapInternalKey!=null) {
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() tapInternalKey: " + Utils.bytesToHex(tapInternalKey.getPubKey()));
|
||||||
|
} else {
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() tapInternalKey: null");
|
||||||
|
}
|
||||||
|
// tapDerivedPublicKeys
|
||||||
|
|
||||||
|
try {
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() tapDerivedPublicKeys: Map<ECKey, Map<KeyDerivation, List<Sha256Hash>>>");
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() tapDerivedPublicKeys.size(): " + tapDerivedPublicKeys.size());
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() tapDerivedPublicKeys: " + tapDerivedPublicKeys);
|
||||||
|
for (Map.Entry<ECKey, Map<KeyDerivation, List<Sha256Hash>>> entry : tapDerivedPublicKeys.entrySet()) {
|
||||||
|
ECKey key = entry.getKey();
|
||||||
|
Map<KeyDerivation, List<Sha256Hash>> value = entry.getValue();
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() tapDerivedPublicKeys pubkey: " + Utils.bytesToHex(key.getPubKey()));
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() tapDerivedPublicKeys map<keyderivation, listhash>: " + value);
|
||||||
|
}
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() tapDerivedPublicKeys END");
|
||||||
|
} catch(Exception e) {
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() tapDerivedPublicKeys exception: " + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("SATOCHIP PSBTInput printDebugInfo() END");
|
||||||
|
|
||||||
|
}
|
||||||
|
// endbug
|
||||||
|
|
||||||
public List<PSBTEntry> getInputEntries() {
|
public List<PSBTEntry> getInputEntries() {
|
||||||
List<PSBTEntry> entries = new ArrayList<>();
|
List<PSBTEntry> entries = new ArrayList<>();
|
||||||
|
|
||||||
|
|
@ -573,6 +642,15 @@ public class PSBTInput {
|
||||||
if(isTaproot() && tapKeyPathSignature != null) {
|
if(isTaproot() && tapKeyPathSignature != null) {
|
||||||
ECKey outputKey = P2TR.getPublicKeyFromScript(getUtxo().getScript());
|
ECKey outputKey = P2TR.getPublicKeyFromScript(getUtxo().getScript());
|
||||||
if(!outputKey.verify(hash, tapKeyPathSignature)) {
|
if(!outputKey.verify(hash, tapKeyPathSignature)) {
|
||||||
|
log.error("SATOCHIP PSBTInput verifySignatures error: " + "Tweaked internal key does not verify against provided taproot keypath signature");
|
||||||
|
log.error("SATOCHIP PSBTInput verifySignatures error: psbtinput: " + this);
|
||||||
|
log.error("SATOCHIP PSBTInput verifySignatures error: outputKey: " + Utils.bytesToHex(outputKey.getPubKey()));
|
||||||
|
log.error("SATOCHIP PSBTInput verifySignatures error: hash: " + Utils.bytesToHex(hash.getBytes()));
|
||||||
|
log.error("SATOCHIP PSBTInput verifySignatures error: tapKeyPathSignature: " + Utils.bytesToHex(tapKeyPathSignature.encodeToBitcoin()));
|
||||||
|
log.error("SATOCHIP PSBTInput verifySignatures error: getUtxo().getScript(): " + getUtxo().getScript());
|
||||||
|
log.error("SATOCHIP PSBTInput verifySignatures error: getUtxo(): " + getUtxo());
|
||||||
|
log.error("SATOCHIP PSBTInput verifySignatures error: getUtxo().getHash(): " + getUtxo().getHash());
|
||||||
|
log.error("SATOCHIP PSBTInput verifySignatures error: getUtxo().getIndex(): " + getUtxo().getIndex());
|
||||||
throw new PSBTSignatureException("Tweaked internal key does not verify against provided taproot keypath signature");
|
throw new PSBTSignatureException("Tweaked internal key does not verify against provided taproot keypath signature");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import java.util.Locale;
|
||||||
|
|
||||||
public enum WalletModel {
|
public enum WalletModel {
|
||||||
SEED, SPARROW, BITCOIN_CORE, ELECTRUM, TREZOR_1, TREZOR_T, COLDCARD, LEDGER_NANO_S, LEDGER_NANO_X, DIGITALBITBOX_01, KEEPKEY, SPECTER_DESKTOP, COBO_VAULT,
|
SEED, SPARROW, BITCOIN_CORE, ELECTRUM, TREZOR_1, TREZOR_T, COLDCARD, LEDGER_NANO_S, LEDGER_NANO_X, DIGITALBITBOX_01, KEEPKEY, SPECTER_DESKTOP, COBO_VAULT,
|
||||||
BITBOX_02, SPECTER_DIY, PASSPORT, BLUE_WALLET, KEYSTONE, SEEDSIGNER, CARAVAN, GORDIAN_SEED_TOOL, JADE, LEDGER_NANO_S_PLUS, EPS, TAPSIGNER, SATSCARD, LABELS, BSMS;
|
BITBOX_02, SPECTER_DIY, PASSPORT, BLUE_WALLET, KEYSTONE, SEEDSIGNER, CARAVAN, GORDIAN_SEED_TOOL, JADE, LEDGER_NANO_S_PLUS, EPS, TAPSIGNER, SATSCARD, SATOCHIP, LABELS, BSMS;
|
||||||
|
|
||||||
public static WalletModel getModel(String model) {
|
public static WalletModel getModel(String model) {
|
||||||
return valueOf(model.toUpperCase(Locale.ROOT));
|
return valueOf(model.toUpperCase(Locale.ROOT));
|
||||||
|
|
@ -70,6 +70,19 @@ public enum WalletModel {
|
||||||
return (this == TAPSIGNER || this == SATSCARD);
|
return (this == TAPSIGNER || this == SATSCARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for card devices that require a PIN code, returns the minimum size of valid PIN code
|
||||||
|
public int getMinPinLength() {
|
||||||
|
if (this == TAPSIGNER || this == SATSCARD){
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
else if (this == SATOCHIP){
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 0; // default?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static WalletModel fromType(String type) {
|
public static WalletModel fromType(String type) {
|
||||||
for(WalletModel model : values()) {
|
for(WalletModel model : values()) {
|
||||||
if(model.getType().equalsIgnoreCase(type)) {
|
if(model.getType().equalsIgnoreCase(type)) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue