-
Notifications
You must be signed in to change notification settings - Fork 12
/
script.go
137 lines (126 loc) · 3.75 KB
/
script.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package bitcoin
import (
"fmt"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/lightningnetwork/lnd/input"
)
const (
TXID = "bff785da9f8169f49be92fa95e31f0890c385bfb1bd24d6b94d7900057c617ae"
COIN = 100_000_000
)
func Step0CarolPrivateKey() *secp256k1.PrivateKey {
key, err := btcec.NewPrivateKey()
if err != nil {
return nil
}
return key
}
func Step0CarolCheckSigRedeemScript(C_ secp256k1.PublicKey) []byte {
TxInRedeemScript, err := txscript.NewScriptBuilder().AddData(C_.SerializeCompressed()).AddOp(txscript.OP_CHECKSIG).Script()
if err != nil {
return nil
}
return TxInRedeemScript
}
/*
step1_carol_create_p2sh_address
*/
func Step1CarolCreateP2SHAddress(txInRedeemScript []byte) (*btcutil.AddressScriptHash, error) {
script, err := txscript.NewScriptBuilder().AddOp(txscript.OP_HASH160).AddData(btcutil.Hash160(txInRedeemScript)).AddOp(txscript.OP_EQUAL).Script()
if err != nil {
return nil, err
}
return btcutil.NewAddressScriptHashFromHash(script[2:22], &chaincfg.MainNetParams)
}
/*
step1_bob_carol_create_tx
*/
func Step1BobCarolCreateTx(txInP2SHAddress []byte) (*wire.MsgTx, error) {
tx := wire.NewMsgTx(1)
txin := make([]*wire.TxIn, 0)
h, err := chainhash.NewHashFromStr(TXID)
if err != nil {
return nil, err
}
// set the sequence number to uint32 max, because python btc library does this as well.
txin = append(txin, &wire.TxIn{PreviousOutPoint: *wire.NewOutPoint(h, 0), Sequence: 4294967295})
tx.TxIn = txin
txout := make([]*wire.TxOut, 0)
script, err := txscript.NewScriptBuilder().AddOp(txscript.OP_HASH160).AddData(txInP2SHAddress).AddOp(txscript.OP_EQUAL).Script()
if err != nil {
return nil, err
}
txout = append(txout, &wire.TxOut{Value: int64(0.0005 * COIN), PkScript: script})
tx.TxOut = txout
return tx, nil
}
func Step2CarolSignTx(txInRedeemScript []byte, privateKey *btcec.PrivateKey) (*wire.TxIn, error) {
txInP2SHAddress, err := Step1CarolCreateP2SHAddress(txInRedeemScript)
if err != nil {
return nil, err
}
tx, err := Step1BobCarolCreateTx(txInP2SHAddress.ScriptAddress())
if err != nil {
return nil, err
}
sig, err := txscript.RawTxInSignature(tx, 0, txInRedeemScript, txscript.SigHashAll, privateKey)
if err != nil {
return nil, err
}
// sig script
signatureScript, err := txscript.NewScriptBuilder().AddData(sig).AddData(txInRedeemScript).Script()
if err != nil {
return nil, err
}
tx.TxIn[0].SignatureScript = signatureScript
return tx.TxIn[0], nil
}
func Step3BobVerifyScript(txInSignature, txInRedeemScript []byte, tx *wire.MsgTx) error {
txInScriptPubKey, err := input.GenerateP2SH(txInRedeemScript)
if err != nil {
return err
}
fmt.Println(txInRedeemScript)
// set the received signature script
tx.TxIn[0].SignatureScript = txInSignature
if txscript.IsPayToScriptHash(txInScriptPubKey) {
vm, err := txscript.NewEngine(
txInScriptPubKey, tx, 0,
txscript.ScriptBip16, nil, nil,
0.0005*COIN, txscript.NewCannedPrevOutputFetcher(
txInRedeemScript, int64(0.0005*COIN),
))
if err != nil {
return err
}
err = vm.Execute()
if err != nil {
return err
}
}
return nil
}
func VerifyScript(pubScriptKey, sig []byte) (txInP2SHAddress *btcutil.AddressScriptHash, err error) {
// create p2sh address from public script key
txInP2SHAddress, err = Step1CarolCreateP2SHAddress(pubScriptKey)
if err != nil {
return
}
// create transaction
tx, err := Step1BobCarolCreateTx(txInP2SHAddress.ScriptAddress())
if err != nil {
return
}
// verify the script
err = Step3BobVerifyScript(sig, pubScriptKey, tx)
if err != nil {
return nil, err
}
return
}