Created
May 27, 2024 21:18
-
-
Save trevormil/7c8c3bec3cac94a2af3c1d4edf95ac2b to your computer and use it in GitHub Desktop.
BIP 322 P2WPKH BIP322 Verification in Go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/base64" | |
"log" | |
"github.com/btcsuite/btcd/btcutil" | |
"github.com/btcsuite/btcd/chaincfg" | |
"github.com/btcsuite/btcd/txscript" | |
"github.com/btcsuite/btcd/wire" | |
bip322 "github.com/unisat-wallet/libbrc20-indexer/utils/bip322" | |
) | |
func convertAddressToScriptPubkey(address string) []byte { | |
btcAddress, err := btcutil.DecodeAddress(address, &chaincfg.MainNetParams) | |
if err != nil { | |
panic(err) | |
} | |
outputScript, err := txscript.PayToAddrScript(btcAddress) | |
if err != nil { | |
panic(err) | |
} | |
return outputScript | |
} | |
func main() { | |
//You can replace these with the actual values you want to verify | |
//These are in the format used by bip322-js | |
//This is for P2WPKH BIP322 verification | |
message := "Hello World" | |
signature := "AkcwRAIgZRfIY3p7/DoVTty6YZbWS71bc5Vct9p9Fia83eRmw2QCICK/ENGfwLtptFluMGs2KsqoNSk89pO7F29zJLUx9a/sASECx/EgAxlkQpQ9hYjgGu6EBCPMVPwVIVJqO4XCsMvViHI=" | |
signerAddress := "bc1q9vza2e8x573nczrlzms0wvx3gsqjx7vavgkx0l" | |
//These will be in the following format: | |
//[0x02 or 0x03] [LENGTH_BYTE, ...(LENGTH bytes that go into witness[0])] [0x21, ...(33 byte (len = 0x21) public key that was used to sign the message)] | |
//- First byte is either a 0x02 or 0x03 (not sure exactly why but apparently it is - https://github.com/ACken2/bip322-js/blob/f0f9373b3a1da19e017c518b891522eaa4bcccdd/src/helpers/Address.ts#L85) | |
//- Next part is the details that go into witness[0] (length of this part is determined by the second byte) - again, not exactly sure what this is | |
//- Last part is the public key that was used to sign the message (33 bytes) - There is a length byte 0x21 before this part to denote the length of the public key (0x21 = 33) | |
encodedSigBytes, err := base64.StdEncoding.DecodeString(signature) | |
if err != nil { | |
panic(err) | |
} | |
//Convert the address to a public key script (I believe this is the denotation for a pay-to-this-address script but not 100% sure) | |
pkScript := convertAddressToScriptPubkey(signerAddress) | |
//Decode the length of the witness[0] part | |
encodedSigLenByte := encodedSigBytes[1] | |
encodedSigLen := int(encodedSigLenByte) | |
//Extract witness[0] and witness[1] from the encoded signature | |
PUB_KEY_LEN := 33 | |
encodedSig := encodedSigBytes[len(encodedSigBytes)-PUB_KEY_LEN-1-encodedSigLen : len(encodedSigBytes)-PUB_KEY_LEN-1] | |
pubKey := encodedSigBytes[len(encodedSigBytes)-33:] | |
//Recreate the witness to pass into the VerifySignature function | |
witness := wire.TxWitness{ | |
encodedSig, | |
pubKey, | |
} | |
//This is the BIP322 verification function from the Unisat wallet | |
verified := bip322.VerifySignature(witness, pkScript, message) | |
log.Println("BIP 322 Verified:", verified) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment