forked from libsv/go-bt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinternalsigner.go
78 lines (63 loc) · 2.09 KB
/
internalsigner.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package bt
import (
"encoding/hex"
"github.com/bitcoinsv/bsvd/bsvec"
"github.com/libsv/go-bt/bscript"
"github.com/libsv/go-bt/crypto"
"github.com/libsv/go-bt/sighash"
)
// InternalSigner implements the Signer interface. It is used to sign a Tx locally
// given a PrivateKey and SIGHASH type.
type InternalSigner struct {
PrivateKey *bsvec.PrivateKey
SigHashFlag sighash.Flag
}
// Sign a transaction at a given input index using the PrivateKey passed in through the
// InternalSigner struct.
func (is *InternalSigner) Sign(index uint32, unsignedTx *Tx) (*Tx, error) {
if is.SigHashFlag == 0 {
is.SigHashFlag = sighash.AllForkID
}
sh, err := unsignedTx.GetInputSignatureHash(index, is.SigHashFlag)
if err != nil {
return nil, err
}
var sig *bsvec.Signature
sig, err = is.PrivateKey.Sign(ReverseBytes(sh)) // little endian sign
if err != nil {
return nil, err
}
var s *bscript.Script
if s, err = bscript.NewP2PKHUnlockingScript(
is.PrivateKey.PubKey().SerializeCompressed(),
sig.Serialize(),
is.SigHashFlag,
); err != nil {
return nil, err
}
if err = unsignedTx.ApplyUnlockingScript(index, s); err != nil {
return nil, err
}
return unsignedTx, nil
}
// SignAuto goes through each input of the transaction and automatically
// signs the P2PKH inputs that it is able to sign using the specific
// PrivateKey passed in through the InternalSigner struct.
func (is *InternalSigner) SignAuto(unsignedTx *Tx) (*Tx, error) {
if is.SigHashFlag == 0 {
is.SigHashFlag = sighash.AllForkID
}
for i, in := range unsignedTx.Inputs {
pubKeyHash, _ := in.PreviousTxScript.GetPublicKeyHash() // doesn't matter if returns error (not p2pkh)
pubKeyHashStr := hex.EncodeToString(pubKeyHash)
pubKeyHashStrFromPriv := hex.EncodeToString(crypto.Hash160(is.PrivateKey.PubKey().SerializeCompressed()))
// check if able to sign (public key matches pubKeyHash in script)
if pubKeyHashStr == pubKeyHashStrFromPriv {
// todo: not sure if the tx value should be used or not? @mrz
if _, err := is.Sign(uint32(i), unsignedTx); err != nil {
return nil, err
}
}
}
return unsignedTx, nil
}