generated from bitcoin-sv/template
-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathlockup.go
More file actions
81 lines (73 loc) · 2.22 KB
/
lockup.go
File metadata and controls
81 lines (73 loc) · 2.22 KB
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
package lockup
import (
"bytes"
"encoding/binary"
"log"
"math/big"
ec "github.com/bsv-blockchain/go-sdk/primitives/ec"
"github.com/bsv-blockchain/go-sdk/script"
"github.com/bsv-blockchain/go-sdk/script/interpreter"
"github.com/bsv-blockchain/go-sdk/transaction"
sighash "github.com/bsv-blockchain/go-sdk/transaction/sighash"
"github.com/bsv-blockchain/go-sdk/transaction/template/p2pkh"
)
type Lock struct {
Address *script.Address `json:"address"`
Until uint32 `json:"until"`
}
func Decode(scr *script.Script, mainnet bool) *Lock {
lockPrefixIndex := bytes.Index(*scr, LockPrefix)
if lockPrefixIndex > -1 && bytes.Contains((*scr)[lockPrefixIndex:], LockSuffix) {
lock := &Lock{}
pos := lockPrefixIndex + len(LockPrefix)
if op, err := scr.ReadOp(&pos); err != nil {
log.Println(err)
} else if len(op.Data) != 20 {
return nil
} else if lock.Address, err = script.NewAddressFromPublicKeyHash(op.Data, mainnet); err != nil {
return nil
}
if op, err := scr.ReadOp(&pos); err != nil {
log.Println(err)
} else {
until := make([]byte, 4)
copy(until, op.Data)
lock.Until = binary.LittleEndian.Uint32(until)
}
return lock
}
return nil
}
func (l Lock) Lock() *script.Script {
s := script.NewFromBytes(LockPrefix)
_ = s.AppendPushData(l.Address.PublicKeyHash)
_ = s.AppendPushData((&interpreter.ScriptNumber{
Val: big.NewInt(int64(l.Until)),
AfterGenesis: true,
}).Bytes())
return script.NewFromBytes(append(*s, LockSuffix...))
}
type LockUnlocker struct {
PrivateKey *ec.PrivateKey
SigHashFlag *sighash.Flag
}
func (lu LockUnlocker) Sign(tx *transaction.Transaction, inputIndex uint32) (*script.Script, error) {
if s, err := (&p2pkh.P2PKH{
PrivateKey: lu.PrivateKey,
SigHashFlag: lu.SigHashFlag,
}).Sign(tx, inputIndex); err != nil {
return nil, err
} else if preimage, err := tx.CalcInputPreimage(inputIndex, *lu.SigHashFlag); err != nil {
return nil, err
} else {
_ = s.AppendPushData(preimage)
return s, nil
}
}
func (lu LockUnlocker) EstimateLength(tx *transaction.Transaction, inputIndex uint32) uint32 {
if u, err := lu.Sign(tx, inputIndex); err != nil {
return 0
} else {
return uint32(len(*u)) //nolint:gosec // G115: len() always returns non-negative
}
}