diff --git a/kernel/script_pubkey.go b/kernel/script_pubkey.go index 70585f2..1acb08c 100644 --- a/kernel/script_pubkey.go +++ b/kernel/script_pubkey.go @@ -35,7 +35,11 @@ func newScriptPubkey(ptr *C.btck_ScriptPubkey, fromOwned bool) *ScriptPubkey { // Parameters: // - rawScriptPubkey: Serialized script pubkey data func NewScriptPubkey(rawScriptPubkey []byte) *ScriptPubkey { - ptr := C.btck_script_pubkey_create(unsafe.Pointer(&rawScriptPubkey[0]), C.size_t(len(rawScriptPubkey))) + var buf unsafe.Pointer + if len(rawScriptPubkey) > 0 { + buf = unsafe.Pointer(&rawScriptPubkey[0]) + } + ptr := C.btck_script_pubkey_create(buf, C.size_t(len(rawScriptPubkey))) return newScriptPubkey(check(ptr), true) } diff --git a/kernel/script_pubkey_test.go b/kernel/script_pubkey_test.go index cab9a2b..24ac3aa 100644 --- a/kernel/script_pubkey_test.go +++ b/kernel/script_pubkey_test.go @@ -7,28 +7,44 @@ import ( ) func TestScriptPubkeyFromRaw(t *testing.T) { - scriptHex := "76a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe26158088ac" - scriptBytes, err := hex.DecodeString(scriptHex) - if err != nil { - t.Fatalf("Failed to decode script hex: %v", err) + tests := []struct { + name string + scriptHex string + }{ + { + name: "standard_p2pkh", + scriptHex: "76a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe26158088ac", + }, + { + name: "empty_script", + scriptHex: "", + }, } - scriptPubkey := NewScriptPubkey(scriptBytes) - defer scriptPubkey.Destroy() + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + scriptBytes, err := hex.DecodeString(tt.scriptHex) + if err != nil { + t.Fatalf("Failed to decode script hex: %v", err) + } - // Test getting the serialized script pubkey - data, err := scriptPubkey.Bytes() - if err != nil { - t.Fatalf("ScriptPubkey.Bytes() error = %v", err) - } + scriptPubkey := NewScriptPubkey(scriptBytes) + defer scriptPubkey.Destroy() - if len(data) != len(scriptBytes) { - t.Errorf("Expected data length %d, got %d", len(scriptBytes), len(data)) - } + data, err := scriptPubkey.Bytes() + if err != nil { + t.Fatalf("ScriptPubkey.Bytes() error = %v", err) + } - hexStr := hex.EncodeToString(data) - if hexStr != scriptHex { - t.Errorf("Expected data hex: %s, got %s", scriptHex, hexStr) + if len(data) != len(scriptBytes) { + t.Errorf("Expected data length %d, got %d", len(scriptBytes), len(data)) + } + + hexStr := hex.EncodeToString(data) + if hexStr != tt.scriptHex { + t.Errorf("Expected data hex: %s, got %s", tt.scriptHex, hexStr) + } + }) } } @@ -173,6 +189,16 @@ func TestInvalidScripts(t *testing.T) { inputIndex: 0, description: "a random segwit transaction from the blockchain using native segwit - WITH WRONG SEGWIT", }, + { + name: "empty_scriptpubkey", + scriptPubkeyHex: "", + amount: 0, + // Minimal coinbase-style transaction with a single empty scriptSig and zero-value output; + // used to trigger verification paths. + txToHex: "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff0100000000000000000000000000", + inputIndex: 0, + description: "empty scriptPubkey should fail verification", + }, } for _, tt := range tests {