Skip to content
This repository was archived by the owner on Mar 19, 2025. It is now read-only.

Commit f6eff15

Browse files
authored
Merge pull request #87 from keithsue/sufay/verify-signatures
Add psbt signature verification
2 parents 56cdfe6 + a4814e5 commit f6eff15

File tree

2 files changed

+63
-2
lines changed

2 files changed

+63
-2
lines changed

x/btcbridge/keeper/msg_server.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,9 @@ func (m msgServer) SubmitWithdrawSignatures(goCtx context.Context, msg *types.Ms
178178
}
179179

180180
// verify the signatures
181+
if !types.VerifyPsbtSignatures(packet) {
182+
return nil, types.ErrInvalidSignatures
183+
}
181184

182185
// Set the signing request status to signed
183186
request := m.GetSigningRequest(ctx, msg.Txid)

x/btcbridge/types/signature.go

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,64 @@
11
package types
22

3-
func (m *BitcoinSigningRequest) ValidateSignatures(sigs []string) bool {
3+
import (
4+
secp256k1 "github.com/btcsuite/btcd/btcec/v2"
5+
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
6+
"github.com/btcsuite/btcd/btcutil/psbt"
7+
"github.com/btcsuite/btcd/txscript"
8+
)
49

5-
return false
10+
// VerifyPsbtSignatures verifies the signatures of the given psbt
11+
// Note: assume that the psbt is valid and all inputs are native segwit
12+
func VerifyPsbtSignatures(p *psbt.Packet) bool {
13+
// build previous output fetcher
14+
prevOutputFetcher := txscript.NewMultiPrevOutFetcher(nil)
15+
16+
for i, txIn := range p.UnsignedTx.TxIn {
17+
prevOutput := p.Inputs[i].WitnessUtxo
18+
if prevOutput == nil {
19+
return false
20+
}
21+
22+
prevOutputFetcher.AddPrevOut(txIn.PreviousOutPoint, prevOutput)
23+
}
24+
25+
// verify signatures
26+
for i := range p.Inputs {
27+
output := p.Inputs[i].WitnessUtxo
28+
hashType := p.Inputs[i].SighashType
29+
30+
witness := p.Inputs[i].FinalScriptWitness
31+
if len(witness) < 72+33 {
32+
return false
33+
}
34+
35+
sigBytes := witness[0 : len(witness)-33]
36+
pkBytes := witness[len(witness)-33:]
37+
38+
if sigBytes[len(sigBytes)-1] != byte(hashType) {
39+
return false
40+
}
41+
42+
sig, err := ecdsa.ParseDERSignature(sigBytes[0 : len(sigBytes)-1])
43+
if err != nil {
44+
return false
45+
}
46+
47+
pk, err := secp256k1.ParsePubKey(pkBytes)
48+
if err != nil {
49+
return false
50+
}
51+
52+
sigHash, err := txscript.CalcWitnessSigHash(output.PkScript, txscript.NewTxSigHashes(p.UnsignedTx, prevOutputFetcher),
53+
hashType, p.UnsignedTx, i, output.Value)
54+
if err != nil {
55+
return false
56+
}
57+
58+
if !sig.Verify(sigHash, pk) {
59+
return false
60+
}
61+
}
62+
63+
return true
664
}

0 commit comments

Comments
 (0)