Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BIP322 signing #2117

Open
gamedevod opened this issue Jan 31, 2024 · 4 comments
Open

BIP322 signing #2117

gamedevod opened this issue Jan 31, 2024 · 4 comments

Comments

@gamedevod
Copy link

gamedevod commented Jan 31, 2024

I want to make implementation of BIP322 signature logic as here
https://github.com/unisat-wallet/wallet-sdk/blob/8cac086d87daf85d654a0d15efe52d3f53508b73/src/message/bip322-simple.ts
, but I get wrong result, who knows, please advise and help me where I make a mistake.


func main() {
	      // Your parameters (adapt as necessary)
	      message := "Quantum Cats by Taproot Wizards\r\nSigning this message is only for authentication and will NOT authorize the spending of any existing funds."
	      messageHash := bip0322Hash(message)
      
	      address, err := btcutil.DecodeAddress("my address", &chaincfg.MainNetParams)
      
	      outputScript, _ := txscript.PayToAddrScript(address)
      
	      scriptSigPrefix := []byte{0x00, 0x20} // This corresponds to "0020" in hex
	      scriptSig := append(scriptSigPrefix, messageHash...)
	      println(scriptSig)
	      // Convert prevoutHash from hex
	      prevoutHash, err := chainhash.NewHashFromStr("0000000000000000000000000000000000000000000000000000000000000000")
	      if err != nil {
		      log.Fatal(err)
	      }
	      prevoutIndex := uint32(0xffffffff)
      
	      // Create a new transaction
	      txToSpend := wire.NewMsgTx(0)
	      // Add an input without a scriptSig, as PSBT requires unsigned inputs
	      txToSpend.AddTxIn(wire.NewTxIn(wire.NewOutPoint(prevoutHash, prevoutIndex), scriptSig, nil))
      
	      txToSpend.AddTxOut(wire.NewTxOut(0, outputScript))
      
	      // Create a new PSBT
	      psbtToSign, _, _, err := psbt.NewFromSignedTx(txToSpend)
	      if err != nil {
		      log.Fatal(err)
	      }
	      // Set data as part of the PSBT input, not as scriptSig
	      psbtToSign.Inputs[0].WitnessUtxo = &wire.TxOut{
		      Value:    0,
		      PkScript: outputScript,
	      }
      
	      // Serialize PSBT
	      var buf bytes.Buffer
	      err = psbtToSign.Serialize(&buf)
	      if err != nil {
		      log.Fatal(err)
	      }
	      psbtHex := hex.EncodeToString(buf.Bytes())
	      log.Println("PSBT:", psbtHex)
      
	      // Encode PSBT to Base64
	      psbtBase64 := base64.StdEncoding.EncodeToString(buf.Bytes())
	      log.Println("PSBT Base64:", psbtBase64)
      
	      u, err := psbt.NewUpdater(psbtToSign)
	      wif, err := btcutil.DecodeWIF("")
	      if err != nil {
		      log.Fatal(err)
	      }
      
	      privKey := wif.PrivKey
      
	      prevPkScript := u.Upsbt.Inputs[0].WitnessUtxo.PkScript
      
	      outPoint := wire.NewOutPoint(prevoutHash, prevoutIndex)
	      a := txscript.NewMultiPrevOutFetcher(map[wire.OutPoint]*wire.TxOut{
		      *outPoint: {},
	      })
	      sigHashes := txscript.NewTxSigHashes(txToSpend, a)
	      witness, err := txscript.TaprootWitnessSignature(u.Upsbt.UnsignedTx, sigHashes,
		      0, u.Upsbt.Inputs[0].WitnessUtxo.Value, prevPkScript, hashType, privKey)
      
	      u.Upsbt.Inputs[0].TaprootKeySpendSig = witness[0]
	      u.Upsbt.UnsignedTx.TxIn[0].SignatureScript = scriptSig
      
	      _, err = psbt.MaybeFinalize(u.Upsbt, 0)
	      buyerSignedTx, err := psbt.Extract(u.Upsbt)
      
	      if err != nil {
		      log.Fatal(err)
	      }
	      if len(buyerSignedTx.TxIn) > 0 {
		      var witnessBuf bytes.Buffer
      
		      witness := buyerSignedTx.TxIn[0].Witness
		      witnessLen := len(witness)
		      encodeVarInt(&witnessBuf, uint64(witnessLen))
      
		      for _, witnessElem := range witness {
			      encodeVarInt(&witnessBuf, uint64(len(witnessElem)))
			      witnessBuf.Write(witnessElem)
		      }
      
		      sigBase64 := base64.StdEncoding.EncodeToString(witnessBuf.Bytes())
		      log.Println("Signature Base64:", sigBase64)
	      }
      }
      
      func encodeVarInt(buffer *bytes.Buffer, value uint64) {
	      if value < 0xfd {
		      buffer.WriteByte(byte(value))
	      } else if value <= 0xffff {
		      buffer.WriteByte(0xfd)
		      buffer.Write([]byte{byte(value), byte(value >> 8)})
	      } else if value <= 0xffffffff {
		      buffer.WriteByte(0xfe)
		      buffer.Write([]byte{byte(value), byte(value >> 8), byte(value >> 16), byte(value >> 24)})
	      } else {
		      buffer.WriteByte(0xff)
		      buffer.Write([]byte{byte(value), byte(value >> 8), byte(value >> 16), byte(value >> 24),
			      byte(value >> 32), byte(value >> 40), byte(value >> 48), byte(value >> 56)})
	      }
      }
      
      // bip0322Hash создает хеш по алгоритму BIP0322.
      func bip0322Hash(message string) []byte {
	      tag := "BIP0322-signed-message"
	      tagHash := sha256.Sum256([]byte(tag))
	      hash := sha256.Sum256(append(tagHash[:], append(tagHash[:], []byte(message)...)...))
	      return hash[:]
      }
`
@jerempjerem
Copy link

Hi, did you finally suceed ?

@gamedevod
Copy link
Author

Hi, did you finally suceed ?

NO(

@yemmyharry
Copy link

yemmyharry commented Apr 23, 2024

@gamedevod pls whats the wrong result you said you kept getting?
Meanwhile, you can look at https://github.com/LegReq/bip0322-signatures.

@trevormil
Copy link

Update: See #2077 (comment) for a working Go version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants