-
Notifications
You must be signed in to change notification settings - Fork 3
/
tx_builder.go
112 lines (93 loc) · 2.3 KB
/
tx_builder.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
package htlcbch
import (
"encoding/hex"
"github.com/gcash/bchd/bchec"
"github.com/gcash/bchd/chaincfg/chainhash"
"github.com/gcash/bchd/txscript"
"github.com/gcash/bchd/wire"
"github.com/gcash/bchutil"
)
const (
dustAmt = 546
)
type msgTxBuilder struct {
msgTx *wire.MsgTx
err error
}
func newMsgTxBuilder() *msgTxBuilder {
return &msgTxBuilder{
msgTx: wire.NewMsgTx(2),
}
}
func (builder *msgTxBuilder) addInput(txid []byte, vout uint32, seq uint32, sigScript []byte) *msgTxBuilder {
if builder.err != nil {
return builder
}
// use NewHashFromStr() to byte-reverse txid !!!
utxoHash, err := chainhash.NewHashFromStr(hex.EncodeToString(txid))
if err != nil {
builder.err = err
return builder
}
outPoint := wire.NewOutPoint(utxoHash, vout)
txIn := wire.NewTxIn(outPoint, nil)
if seq > 0 {
txIn.Sequence = seq
}
if len(sigScript) > 0 {
txIn.SignatureScript = sigScript
}
builder.msgTx.AddTxIn(txIn)
return builder
}
func (builder *msgTxBuilder) addOutput(toAddr bchutil.Address, outAmt int64) *msgTxBuilder {
if builder.err != nil {
return builder
}
pkScript, err := txscript.PayToAddrScript(toAddr)
if err != nil {
builder.err = err
return builder
}
txOut := wire.NewTxOut(outAmt, pkScript)
builder.msgTx.AddTxOut(txOut)
return builder
}
func (builder *msgTxBuilder) addOpRet(pkScript []byte) *msgTxBuilder {
txOut := wire.NewTxOut(0, pkScript)
builder.msgTx.AddTxOut(txOut)
return builder
}
func (builder *msgTxBuilder) addChange(toAddr bchutil.Address, changeAmt int64) *msgTxBuilder {
if changeAmt > dustAmt {
return builder.addOutput(toAddr, changeAmt)
}
return builder
}
func (builder *msgTxBuilder) sign(
inIdx int, inAmt int64,
subScript []byte,
privKey *bchec.PrivateKey,
sigScriptFn func(sig []byte) ([]byte, error),
) *msgTxBuilder {
if builder.err != nil {
return builder
}
hashType := txscript.SigHashAll | txscript.SigHashForkID
sig, err := txscript.RawTxInECDSASignature(builder.msgTx,
inIdx, subScript, hashType, privKey, inAmt)
if err != nil {
builder.err = err
return builder
}
sigScript, err := sigScriptFn(sig)
if err != nil {
builder.err = err
return builder
}
builder.msgTx.TxIn[inIdx].SignatureScript = sigScript
return builder
}
func (builder *msgTxBuilder) build() (*wire.MsgTx, error) {
return builder.msgTx, builder.err
}