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();
|
||||
}
|
||||
|
||||
// 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.
|
||||
*/
|
||||
|
|
@ -428,14 +433,119 @@ public class ECKey {
|
|||
return verify(sigHash.getBytes(), signature);
|
||||
}
|
||||
|
||||
|
||||
public ECKey getTweakedOutputKey() {
|
||||
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 internalKey: " + 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 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 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?
|
||||
|
|
|
|||
|
|
@ -250,6 +250,75 @@ public class PSBTInput {
|
|||
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() {
|
||||
List<PSBTEntry> entries = new ArrayList<>();
|
||||
|
||||
|
|
@ -573,6 +642,15 @@ public class PSBTInput {
|
|||
if(isTaproot() && tapKeyPathSignature != null) {
|
||||
ECKey outputKey = P2TR.getPublicKeyFromScript(getUtxo().getScript());
|
||||
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");
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import java.util.Locale;
|
|||
|
||||
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,
|
||||
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) {
|
||||
return valueOf(model.toUpperCase(Locale.ROOT));
|
||||
|
|
@ -70,6 +70,19 @@ public enum WalletModel {
|
|||
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) {
|
||||
for(WalletModel model : values()) {
|
||||
if(model.getType().equalsIgnoreCase(type)) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue