Skip to content

Commit f283394

Browse files
committed
Add ScriptPubkey
1 parent a7c7ade commit f283394

File tree

4 files changed

+113
-5
lines changed

4 files changed

+113
-5
lines changed

TODO.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,13 @@ This document lists the remaining C API functions and data structures from `bitc
1919
## Missing Data Structures
2020

2121
### Core Transaction Types
22-
- **`kernel_ScriptPubkey`** - Script public key operations
2322
- **`kernel_TransactionOutput`** - Transaction output operations
2423
- **`kernel_BlockPointer`** - Non-owned block pointers (from callbacks)
2524
- **`kernel_BlockUndo`** - Block undo data operations
26-
- **`kernel_ByteArray`** - Helper for serialized data
2725

2826
## Missing Functions by Category
2927

3028
### Script Operations
31-
- [ ] `kernel_script_pubkey_create()` - Create script pubkey
32-
- [ ] `kernel_script_pubkey_destroy()` - Cleanup script pubkey
33-
- [ ] `kernel_copy_script_pubkey_data()` - Get serialized script data
3429
- [ ] `kernel_verify_script()` - **Script verification (IMPORTANT!)**
3530

3631
### Transaction Output Operations

kernel/errors.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,8 @@ var (
2121
ErrLoggingConnectionCreation = errors.New("failed to create logging connection")
2222
ErrTransactionCreation = errors.New("failed to create transaction from raw data")
2323
ErrInvalidTransactionData = errors.New("invalid transaction data")
24+
ErrScriptPubkeyCreation = errors.New("failed to create script pubkey from raw data")
25+
ErrInvalidScriptPubkeyData = errors.New("invalid script pubkey data")
26+
ErrInvalidScriptPubkey = errors.New("invalid script pubkey")
27+
ErrScriptPubkeyDataCopy = errors.New("failed to copy script pubkey data")
2428
)

kernel/script_pubkey.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package kernel
2+
3+
/*
4+
#include "kernel/bitcoinkernel.h"
5+
*/
6+
import "C"
7+
import (
8+
"runtime"
9+
"unsafe"
10+
)
11+
12+
// ScriptPubkey wraps the C kernel_ScriptPubkey
13+
type ScriptPubkey struct {
14+
ptr *C.kernel_ScriptPubkey
15+
}
16+
17+
// NewScriptPubkeyFromRaw creates a new script pubkey from raw serialized data
18+
func NewScriptPubkeyFromRaw(rawScriptPubkey []byte) (*ScriptPubkey, error) {
19+
if len(rawScriptPubkey) == 0 {
20+
return nil, ErrInvalidScriptPubkeyData
21+
}
22+
23+
ptr := C.kernel_script_pubkey_create((*C.uchar)(unsafe.Pointer(&rawScriptPubkey[0])), C.size_t(len(rawScriptPubkey)))
24+
if ptr == nil {
25+
return nil, ErrScriptPubkeyCreation
26+
}
27+
28+
scriptPubkey := &ScriptPubkey{ptr: ptr}
29+
runtime.SetFinalizer(scriptPubkey, (*ScriptPubkey).destroy)
30+
return scriptPubkey, nil
31+
}
32+
33+
// Data returns the serialized script pubkey data
34+
func (s *ScriptPubkey) Data() ([]byte, error) {
35+
if s.ptr == nil {
36+
return nil, ErrInvalidScriptPubkey
37+
}
38+
39+
byteArray := C.kernel_copy_script_pubkey_data(s.ptr)
40+
if byteArray == nil {
41+
return nil, ErrScriptPubkeyDataCopy
42+
}
43+
defer C.kernel_byte_array_destroy(byteArray)
44+
45+
size := int(byteArray.size)
46+
if size == 0 {
47+
return nil, nil
48+
}
49+
50+
// Copy the data to Go slice
51+
data := C.GoBytes(unsafe.Pointer(byteArray.data), C.int(size))
52+
return data, nil
53+
}
54+
55+
func (s *ScriptPubkey) destroy() {
56+
if s.ptr != nil {
57+
C.kernel_script_pubkey_destroy(s.ptr)
58+
s.ptr = nil
59+
}
60+
}
61+
62+
func (s *ScriptPubkey) Destroy() {
63+
runtime.SetFinalizer(s, nil)
64+
s.destroy()
65+
}

kernel/script_pubkey_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package kernel
2+
3+
import (
4+
"encoding/hex"
5+
"errors"
6+
"testing"
7+
)
8+
9+
func TestInvalidScriptPubkeyData(t *testing.T) {
10+
// Test with empty data
11+
_, err := NewScriptPubkeyFromRaw([]byte{})
12+
if !errors.Is(err, ErrInvalidScriptPubkeyData) {
13+
t.Errorf("Expected ErrInvalidScriptPubkeyData, got %v", err)
14+
}
15+
}
16+
17+
func TestScriptPubkeyFromRaw(t *testing.T) {
18+
scriptHex := "76a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe26158088ac"
19+
scriptBytes, err := hex.DecodeString(scriptHex)
20+
if err != nil {
21+
t.Fatalf("Failed to decode script hex: %v", err)
22+
}
23+
24+
scriptPubkey, err := NewScriptPubkeyFromRaw(scriptBytes)
25+
if err != nil {
26+
t.Fatalf("NewScriptPubkeyFromRaw() error = %v", err)
27+
}
28+
defer scriptPubkey.Destroy()
29+
30+
// Test getting script pubkey data
31+
data, err := scriptPubkey.Data()
32+
if err != nil {
33+
t.Fatalf("ScriptPubkey.Data() error = %v", err)
34+
}
35+
36+
if len(data) != len(scriptBytes) {
37+
t.Errorf("Expected data length %d, got %d", len(scriptBytes), len(data))
38+
}
39+
40+
hexStr := hex.EncodeToString(data)
41+
if hexStr != scriptHex {
42+
t.Errorf("Expected data hex: %s, got %s", scriptHex, hexStr)
43+
}
44+
}

0 commit comments

Comments
 (0)