-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathscript_pubkey.go
More file actions
155 lines (134 loc) · 5.9 KB
/
script_pubkey.go
File metadata and controls
155 lines (134 loc) · 5.9 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
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package kernel
/*
#include "bitcoinkernel.h"
*/
import "C"
import (
"unsafe"
)
type scriptPubkeyCFuncs struct{}
func (scriptPubkeyCFuncs) destroy(ptr unsafe.Pointer) {
C.btck_script_pubkey_destroy((*C.btck_ScriptPubkey)(ptr))
}
func (scriptPubkeyCFuncs) copy(ptr unsafe.Pointer) unsafe.Pointer {
return unsafe.Pointer(C.btck_script_pubkey_copy((*C.btck_ScriptPubkey)(ptr)))
}
type ScriptPubkey struct {
*handle
scriptPubkeyApi
}
func newScriptPubkey(ptr *C.btck_ScriptPubkey, fromOwned bool) *ScriptPubkey {
h := newHandle(unsafe.Pointer(ptr), scriptPubkeyCFuncs{}, fromOwned)
return &ScriptPubkey{handle: h, scriptPubkeyApi: scriptPubkeyApi{(*C.btck_ScriptPubkey)(h.ptr)}}
}
// NewScriptPubkey creates a new script pubkey from raw serialized script data.
//
// The script pubkey defines the conditions that must be met to spend a transaction output.
//
// Parameters:
// - rawScriptPubkey: Serialized script pubkey data
func NewScriptPubkey(rawScriptPubkey []byte) *ScriptPubkey {
ptr := C.btck_script_pubkey_create(unsafe.Pointer(unsafe.SliceData(rawScriptPubkey)), C.size_t(len(rawScriptPubkey)))
return newScriptPubkey(check(ptr), true)
}
type ScriptPubkeyView struct {
scriptPubkeyApi
ptr *C.btck_ScriptPubkey
}
func newScriptPubkeyView(ptr *C.btck_ScriptPubkey) *ScriptPubkeyView {
return &ScriptPubkeyView{
scriptPubkeyApi: scriptPubkeyApi{ptr},
ptr: ptr,
}
}
type scriptPubkeyApi struct {
ptr *C.btck_ScriptPubkey
}
// Copy creates a copy of the script pubkey.
func (s *scriptPubkeyApi) Copy() *ScriptPubkey {
return newScriptPubkey(s.ptr, false)
}
// Bytes returns the serialized representation of the script pubkey.
//
// Returns an error if the serialization fails.
func (s *scriptPubkeyApi) Bytes() ([]byte, error) {
bytes, ok := writeToBytes(func(writer C.btck_WriteBytes, user_data unsafe.Pointer) C.int {
return C.btck_script_pubkey_to_bytes(s.ptr, writer, user_data)
})
if !ok {
return nil, &SerializationError{"Failed to serialize script pubkey"}
}
return bytes, nil
}
// Verify verifies if the input at inputIndex of txTo spends the script pubkey
// under the constraints specified by flags. If the witness flag is set in flags,
// the amount parameter is used. If the taproot flag is set, spentOutputs is used
// to validate taproot transactions.
//
// Parameters:
// - amount: Amount of the script pubkey's associated output. May be zero if the witness flag is not set.
// - txTo: Transaction spending the script pubkey.
// - spentOutputs: Outputs spent by the transaction. May be nil if the taproot flag is not set.
// - inputIndex: Index of the input in txTo spending the script pubkey.
// - flags: ScriptFlags controlling validation constraints.
//
// Returns:
// - bool: true if the script is valid, false if invalid (only meaningful when error is nil)
// - error: non-nil if verification could not be performed due to malformed input;
// nil if verification completed successfully (check bool for validity result)
func (s *scriptPubkeyApi) Verify(amount int64, txTo *Transaction, spentOutputs []*TransactionOutput, inputIndex uint, flags ScriptFlags) (bool, error) {
inputCount := txTo.CountInputs()
if inputIndex >= uint(inputCount) {
return false, ErrVerifyScriptVerifyTxInputIndex
}
if len(spentOutputs) > 0 && uint64(len(spentOutputs)) != inputCount {
return false, ErrVerifyScriptVerifySpentOutputsMismatch
}
allFlags := ScriptFlagsVerifyAll
if (flags & ^ScriptFlags(allFlags)) != 0 {
return false, ErrVerifyScriptVerifyInvalidFlags
}
var cSpentOutputsPtr **C.btck_TransactionOutput
if len(spentOutputs) > 0 {
cSpentOutputs := make([]*C.btck_TransactionOutput, len(spentOutputs))
for i, output := range spentOutputs {
cSpentOutputs[i] = (*C.btck_TransactionOutput)(output.handle.ptr)
}
cSpentOutputsPtr = (**C.btck_TransactionOutput)(unsafe.Pointer(&cSpentOutputs[0]))
}
var cStatus C.btck_ScriptVerifyStatus
result := C.btck_script_pubkey_verify(
s.ptr,
C.int64_t(amount),
(*C.btck_Transaction)(txTo.handle.ptr),
cSpentOutputsPtr,
C.size_t(len(spentOutputs)),
C.uint(inputIndex),
C.btck_ScriptVerificationFlags(flags),
&cStatus,
)
// Check for errors that prevented verification
if cStatus == C.btck_ScriptVerifyStatus_ERROR_INVALID_FLAGS_COMBINATION {
return false, ErrVerifyScriptVerifyInvalidFlagsCombination
}
if cStatus == C.btck_ScriptVerifyStatus_ERROR_SPENT_OUTPUTS_REQUIRED {
return false, ErrVerifyScriptVerifySpentOutputsRequired
}
// Verification completed: result indicates validity
// result == 1: script is valid
// result != 1: script is invalid
return result == 1, nil
}
// ScriptFlags represents script verification flags that may be composed with each other.
type ScriptFlags C.btck_ScriptVerificationFlags
const (
ScriptFlagsVerifyNone ScriptFlags = C.btck_ScriptVerificationFlags_NONE // No verification flags
ScriptFlagsVerifyP2SH ScriptFlags = C.btck_ScriptVerificationFlags_P2SH // Evaluate P2SH (BIP16) subscripts
ScriptFlagsVerifyDERSig ScriptFlags = C.btck_ScriptVerificationFlags_DERSIG // Enforce strict DER (BIP66) compliance
ScriptFlagsVerifyNullDummy ScriptFlags = C.btck_ScriptVerificationFlags_NULLDUMMY // Enforce NULLDUMMY (BIP147)
ScriptFlagsVerifyCheckLockTimeVerify ScriptFlags = C.btck_ScriptVerificationFlags_CHECKLOCKTIMEVERIFY // Enable CHECKLOCKTIMEVERIFY (BIP65)
ScriptFlagsVerifyCheckSequenceVerify ScriptFlags = C.btck_ScriptVerificationFlags_CHECKSEQUENCEVERIFY // Enable CHECKSEQUENCEVERIFY (BIP112)
ScriptFlagsVerifyWitness ScriptFlags = C.btck_ScriptVerificationFlags_WITNESS // Enable WITNESS (BIP141)
ScriptFlagsVerifyTaproot ScriptFlags = C.btck_ScriptVerificationFlags_TAPROOT // Enable TAPROOT (BIPs 341 & 342)
ScriptFlagsVerifyAll ScriptFlags = C.btck_ScriptVerificationFlags_ALL // All verification flags combined
)