I’ve achieved all attainable checks: signhash and taproot calculation, no adjustments in BASE64 processes, empty symbols, Shnorr validity and that BASE64 is precisely 64 (not 64 + 1), however I get the identical error each time.
Logic: 1. Obtain psbt and decode -> Signal inputs (I do not finalise, the server does) utilizing Default technique (ALL the identical end result)-> encode in Base64 -> return partially signed PSBT to server.
I get the “Invalid Schnorr” error each time by server. You see, when you examine script PSBT and output psbt, they’re 99% similar apart from Shnorr (area unknown 13). I’ve connected a screenshot to indicate the distinction.
- I believed the issue could be within the codecs for the server, but additionally Bitcoin cli analyse returns an ‘updater’ standing for my script output:
{ { ‘end result’: { { ‘inputs’: [ { ‘has_utxo": true, ‘is_final": false, { ‘next’: { ‘updater’. }, { ‘has_utxo": true, ‘is_final": false, { ‘next’: { ‘updater’. } ], ‘estimated_vsize": 286, ‘estimated_feerate": 6.0e-5, ‘payment": 1.716e-5, ‘subsequent": { ‘updater’. }, ‘error": null, ‘id": null }
- Though if I signal by way of Unisat or every other extension pockets – it’ll return:
{ ‘end result": { { ‘inputs’: [ { ‘has_utxo": true, ‘is_final": false, { ‘next’: { ‘updater’. }, { ‘has_utxo": true, ‘is_final": false, { ‘next’: ‘finalizer’. } ], ‘payment": 1.716e-5, ‘subsequent": { ‘updater’ }, ‘error": null, ‘id": null }
Code:
func most important() {
wifKeyStr := "WIF"
psbtBase64 := "cHNidP8BAPwCAAAAAgupxw+/SJhtowTzcr1wx9c/uanFKaJ3yU3J6UKjMTMzlAEAAAD/////Q9g6nnkQbdroR/sr2jeNqZ9nlZbVuqSNdjakxTxLgYADAAAAAP////8ETQEAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOmGDAAAAAAAAIlEgsxHYe7mlcSxOwOnapg4WHRT5UuB+vWF8uMz6Oxu5Bf9DAgAAAAAAABYAFAnkWBtaeW/v/BxPBmkgboAct6nrVkwAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOgAAAAAI/AJtZQNzaWdAvHgNmehOZ6jBZiu5ckCncLnVeViAr3PlKIgR2v8NPzhW/OXpu8oaK4b3bgRIL/qrMT5WlpgdybZGXVaAxSJVIwv8Am1lBnNpZ2V4cAhCeTbOW+ZAAAABAStNAQAAAAAAACJRIDCs9kAJfdTiQei7Cf+RSH3Cwr5oxFjNj27APixQD2L4ARcgc+G1jBTUGzdWX447VOZ6zEec2eeffMqg8KTrQ6plriIAAQErrtgAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOgEXIK0XtHBW7oxyV677kvzIL56kaRx0i5AADj3yumRxQD17AAAAAAA="
cleanPSBTBase64 := cleanBase64(psbtBase64)
psbtBytes, _ := base64.StdEncoding.DecodeString(cleanPSBTBase64)
packet, _ := psbt.NewFromRawBytes(bytes.NewReader(psbtBytes), false)
prevOutFetcher := txscript.NewMultiPrevOutFetcher(nil)
for i, enter := vary packet.Inputs {
if enter.WitnessUtxo != nil {
prevOutFetcher.AddPrevOut(packet.UnsignedTx.TxIn[i].PreviousOutPoint, &wire.TxOut{
Worth: enter.WitnessUtxo.Worth,
PkScript: enter.WitnessUtxo.PkScript,
})
}
}
inputToSign := 1
if len(packet.Inputs[inputToSign].TaprootInternalKey) > 0 {
sigHashes := txscript.NewTxSigHashes(packet.UnsignedTx, prevOutFetcher)
pkScript, _ := getInputScript(packet, inputToSign)
quantity, _ := getInputAmount(packet, inputToSign)
taprootInternalKey := packet.Inputs[inputToSign].TaprootInternalKey
wifKey, _ := btcutil.DecodeWIF(wifKeyStr)
publicKeyFromWIF := schnorr.SerializePubKey(wifKey.PrivKey.PubKey())
if bytes.Equal(taprootInternalKey, publicKeyFromWIF) {
sighashType := txscript.SigHashDefault
sighash, _ := txscript.CalcTaprootSignatureHash(sigHashes, sighashType, packet.UnsignedTx, inputToSign, txscript.NewCannedPrevOutputFetcher(pkScript, quantity))
signature, _ := schnorr.Signal(wifKey.PrivKey, sighash)
serializedSig := signature.Serialize()
packet.Inputs[inputToSign].TaprootKeySpendSig = serializedSig
}
}
signedPsbtBase64, _ := packet.B64Encode()
fmt.Printf("Signed PSBT (Base64): %sn", signedPsbtBase64)
}
func cleanBase64(s string) string {
return strings.Be part of(strings.Fields(s), "")
}
func getInputScript(packet *psbt.Packet, idx int) ([]byte, error) {
enter := packet.Inputs[idx]
if enter.WitnessUtxo != nil && len(enter.WitnessUtxo.PkScript) > 0 {
return enter.WitnessUtxo.PkScript, nil
}
if enter.NonWitnessUtxo != nil {
prevTx := enter.NonWitnessUtxo
outPoint := packet.UnsignedTx.TxIn[idx].PreviousOutPoint
if int(outPoint.Index) >= len(prevTx.TxOut) {
return nil, fmt.Errorf("Invalid outpoint index %d for enter %d", outPoint.Index, idx)
}
return prevTx.TxOut[outPoint.Index].PkScript, nil
}
return nil, fmt.Errorf("PkScript not discovered for enter %d", idx)
}
func getInputAmount(packet *psbt.Packet, idx int) (int64, error) {
enter := packet.Inputs[idx]
if enter.WitnessUtxo != nil {
return enter.WitnessUtxo.Worth, nil
}
if enter.NonWitnessUtxo != nil {
prevTx := enter.NonWitnessUtxo
outPoint := packet.UnsignedTx.TxIn[idx].PreviousOutPoint
if int(outPoint.Index) >= len(prevTx.TxOut) {
return 0, fmt.Errorf("Invalid outpoint index %d for enter %d", outPoint.Index, idx)
}
return prevTx.TxOut[outPoint.Index].Worth, nil
}
return 0, fmt.Errorf("WitnessUtxo or NonWitnessUtxo not discovered for enter %d", idx)
}
OUTPUT:
cHNidP8BAPwCAAAAAgupxw+/SJhtowTzcr1wx9c/uanFKaJ3yU3J6UKjMTMzlAEAAAD/////Q9g6nnkQbdroR/sr2jeNqZ9nlZbVuqSNdjakxTxLgYADAAAAAP////8ETQEAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOmGDAAAAAAAAIlEgsxHYe7mlcSxOwOnapg4WHRT5UuB+vWF8uMz6Oxu5Bf9DAgAAAAAAABYAFAnkWBtaeW/v/BxPBmkgboAct6nrVkwAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOgAAAAAI/AJtZQNzaWdAvHgNmehOZ6jBZiu5ckCncLnVeViAr3PlKIgR2v8NPzhW/OXpu8oaK4b3bgRIL/qrMT5WlpgdybZGXVaAxSJVIwv8Am1lBnNpZ2V4cAhCeTbOW+ZAAAABAStNAQAAAAAAACJRIDCs9kAJfdTiQei7Cf+RSH3Cwr5oxFjNj27APixQD2L4ARcgc+G1jBTUGzdWX447VOZ6zEec2eeffMqg8KTrQ6plriIAAQErrtgAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOgEXIK0XtHBW7oxyV677kvzIL56kaRx0i5AADj3yumRxQD17AAAAAAA=
Calculating Taproot deal with...
Taproot Deal with: bc1p38pg0767rhujdn569lug887yea73rn7vpwz546y7czzcptql9caq6cafwt
TapKeyBytes: 89c287fb5e1df926ce9a2ff8839fc4cf7d11cfcc0b854ae89ec08580ac1f2e3a
2024/11/27 12:13:42 Taproot Deal with: bc1p38pg0767rhujdn569lug887yea73rn7vpwz546y7czzcptql9caq6cafwt
Public Key (Hex): ad17b47056ee8c7257aefb92fcc82f9ea4691c748b90000e3df2ba6471403d7b
Decoding PSBT...
PSBT efficiently decoded.
Parsing PSBT...
PSBT efficiently parsed.
Creating MultiPrevOutFetcher...
Including earlier output for enter 0
Including earlier output for enter 1
MultiPrevOutFetcher efficiently created.
Signing enter 1...
Enter makes use of Taproot.
Creating TxSigHashes...
TxSigHashes efficiently created.
PkScript: 512089c287fb5e1df926ce9a2ff8839fc4cf7d11cfcc0b854ae89ec08580ac1f2e3a
Quantity: 55470
TaprootInternalKey of enter 1: ad17b47056ee8c7257aefb92fcc82f9ea4691c748b90000e3df2ba6471403d7b
Public key from WIF: ad17b47056ee8c7257aefb92fcc82f9ea4691c748b90000e3df2ba6471403d7b
The signing key matches the TaprootInternalKey of the enter.
Calculating sighash...
Sighash: 92aec029f002090d7621fffce4ebac7ff333d971e832db3980bb93112cb851ce
Creating signature...
Signature: 98dcfc29a85bc89ed35a86fa8073d5708ea93e095f4171b65c72ed12227d537a849b539ef6f9b845aeef61ff0bd4e94b664981e14a29e2443ddca98ecb9360f3
Signature for enter 1 added.
Serializing signed PSBT...
Signed PSBT (Base64): cHNidP8BAPwCAAAAAgupxw+/SJhtowTzcr1wx9c/uanFKaJ3yU3J6UKjMTMzlAEAAAD/////Q9g6nnkQbdroR/sr2jeNqZ9nlZbVuqSNdjakxTxLgYADAAAAAP////8ETQEAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOmGDAAAAAAAAIlEgsxHYe7mlcSxOwOnapg4WHRT5UuB+vWF8uMz6Oxu5Bf9DAgAAAAAAABYAFAnkWBtaeW/v/BxPBmkgboAct6nrVkwAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOgAAAAAI/AJtZQNzaWdAvHgNmehOZ6jBZiu5ckCncLnVeViAr3PlKIgR2v8NPzhW/OXpu8oaK4b3bgRIL/qrMT5WlpgdybZGXVaAxSJVIwv8Am1lBnNpZ2V4cAhCeTbOW+ZAAAABAStNAQAAAAAAACJRIDCs9kAJfdTiQei7Cf+RSH3Cwr5oxFjNj27APixQD2L4ARcgc+G1jBTUGzdWX447VOZ6zEec2eeffMqg8KTrQ6plriIAAQErrtgAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOgETQJjc/CmoW8ie01qG+oBz1XCOqT4JX0Fxtlxy7RIifVN6hJtTnvb5uEWu72H/C9TpS2ZJgeFKKeJEPdypjsuTYPMBFyCtF7RwVu6Mcleu+5L8yC+epGkcdIuQAA498rpkcUA9ewAAAAAA
PSBT MY Script output:
cHNidP8BAPwCAAAAAgupxw+/SJhtowTzcr1wx9c/uanFKaJ3yU3J6UKjMTMzlAEAAAD/////Q9g6nnkQbdroR/sr2jeNqZ9nlZbVuqSNdjakxTxLgYADAAAAAP////8ETQEAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOmGDAAAAAAAAIlEgsxHYe7mlcSxOwOnapg4WHRT5UuB+vWF8uMz6Oxu5Bf9DAgAAAAAAABYAFAnkWBtaeW/v/BxPBmkgboAct6nrVkwAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOgAAAAAI/AJtZQNzaWdAvHgNmehOZ6jBZiu5ckCncLnVeViAr3PlKIgR2v8NPzhW/OXpu8oaK4b3bgRIL/qrMT5WlpgdybZGXVaAxSJVIwv8Am1lBnNpZ2V4cAhCeTbOW+ZAAAABAStNAQAAAAAAACJRIDCs9kAJfdTiQei7Cf+RSH3Cwr5oxFjNj27APixQD2L4ARcgc+G1jBTUGzdWX447VOZ6zEec2eeffMqg8KTrQ6plriIAAQErrtgAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOgETQJjc/CmoW8ie01qG+oBz1XCOqT4JX0Fxtlxy7RIifVN6hJtTnvb5uEWu72H/C9TpS2ZJgeFKKeJEPdypjsuTYPMBFyCtF7RwVu6Mcleu+5L8yC+epGkcdIuQAA498rpkcUA9ewAAAAAA
Pockets extension PSBT:
cHNidP8BAPwCAAAAAgupxw+/SJhtowTzcr1wx9c/uanFKaJ3yU3J6UKjMTMzlAEAAAD/////Q9g6nnkQbdroR/sr2jeNqZ9nlZbVuqSNdjakxTxLgYADAAAAAP////8ETQEAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOmGDAAAAAAAAIlEgsxHYe7mlcSxOwOnapg4WHRT5UuB+vWF8uMz6Oxu5Bf9DAgAAAAAAABYAFAnkWBtaeW/v/BxPBmkgboAct6nrVkwAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOgAAAAAI/AJtZQNzaWdAvHgNmehOZ6jBZiu5ckCncLnVeViAr3PlKIgR2v8NPzhW/OXpu8oaK4b3bgRIL/qrMT5WlpgdybZGXVaAxSJVIwv8Am1lBnNpZ2V4cAhCeTbOW+ZAAAABAStNAQAAAAAAACJRIDCs9kAJfdTiQei7Cf+RSH3Cwr5oxFjNj27APixQD2L4ARcgc+G1jBTUGzdWX447VOZ6zEec2eeffMqg8KTrQ6plriIAAQErrtgAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOgETQF/kABzHRRZdy9+33rcvJZxMBYhwywu6TY0f+XOEbwBdvcjHcy2tYjR2VM2YbAFCaS9xtHx+SgfAS6RmvTh4xh0BFyCtF7RwVu6Mcleu+5L8yC+epGkcdIuQAA498rpkcUA9ewAAAAAA
Uncooked PSBT (enter psbt fot scirpt and extension):
cHNidP8BAPwCAAAAAgupxw+/SJhtowTzcr1wx9c/uanFKaJ3yU3J6UKjMTMzlAEAAAD/////Q9g6nnkQbdroR/sr2jeNqZ9nlZbVuqSNdjakxTxLgYADAAAAAP////8ETQEAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOmGDAAAAAAAAIlEgsxHYe7mlcSxOwOnapg4WHRT5UuB+vWF8uMz6Oxu5Bf9DAgAAAAAAABYAFAnkWBtaeW/v/BxPBmkgboAct6nrVkwAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOgAAAAAI/AJtZQNzaWdAvHgNmehOZ6jBZiu5ckCncLnVeViAr3PlKIgR2v8NPzhW/OXpu8oaK4b3bgRIL/qrMT5WlpgdybZGXVaAxSJVIwv8Am1lBnNpZ2V4cAhCeTbOW+ZAAAABAStNAQAAAAAAACJRIDCs9kAJfdTiQei7Cf+RSH3Cwr5oxFjNj27APixQD2L4ARcgc+G1jBTUGzdWX447VOZ6zEec2eeffMqg8KTrQ6plriIAAQErrtgAAAAAAAAiUSCJwof7Xh35Js6aL/iDn8TPfRHPzAuFSuiewIWArB8uOgEXIK0XtHBW7oxyV677kvzIL56kaRx0i5AADj3yumRxQD17AAAAAAA=
The massive downside is that I do not perceive why sighash is wrong (and therefore Schnorr’s signature), however I do not assume the issue is the formation of the schnorr signature. I feel I am contemplating one thing improper to calculate the sighash OR not contemplating, though I am unable to work out what precisely, since I do not get errors at any stage in my code apart from checking the BTC CLI or POST to the server