Skip to content

Commit 3bbd004

Browse files
authored
feat: support for decoding script ref (#1053)
Fixes #1052 Signed-off-by: Aurora Gaffney <[email protected]>
1 parent 33ce3ea commit 3bbd004

File tree

8 files changed

+123
-16
lines changed

8 files changed

+123
-16
lines changed

ledger/alonzo/alonzo.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ func (o AlonzoTransactionOutput) Address() common.Address {
324324
return o.OutputAddress
325325
}
326326

327-
func (o AlonzoTransactionOutput) ScriptRef() *cbor.LazyValue {
327+
func (o AlonzoTransactionOutput) ScriptRef() common.Script {
328328
return nil
329329
}
330330

ledger/babbage/babbage.go

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -420,11 +420,11 @@ func (d *BabbageTransactionOutputDatumOption) MarshalCBOR() ([]byte, error) {
420420

421421
type BabbageTransactionOutput struct {
422422
cbor.DecodeStoreCbor
423-
OutputAddress common.Address `cbor:"0,keyasint,omitempty"`
424-
OutputAmount mary.MaryTransactionOutputValue `cbor:"1,keyasint,omitempty"`
425-
DatumOption *BabbageTransactionOutputDatumOption `cbor:"2,keyasint,omitempty"`
426-
TxScriptRef *cbor.Tag `cbor:"3,keyasint,omitempty"`
427-
legacyOutput bool
423+
OutputAddress common.Address `cbor:"0,keyasint,omitempty"`
424+
OutputAmount mary.MaryTransactionOutputValue `cbor:"1,keyasint,omitempty"`
425+
DatumOption *BabbageTransactionOutputDatumOption `cbor:"2,keyasint,omitempty"`
426+
TxOutScriptRef *common.ScriptRef `cbor:"3,keyasint,omitempty"`
427+
legacyOutput bool
428428
}
429429

430430
func (o *BabbageTransactionOutput) UnmarshalCBOR(cborData []byte) error {
@@ -486,14 +486,11 @@ func (o BabbageTransactionOutput) Address() common.Address {
486486
return o.OutputAddress
487487
}
488488

489-
func (o BabbageTransactionOutput) ScriptRef() *cbor.LazyValue {
490-
if o.TxScriptRef == nil {
489+
func (o BabbageTransactionOutput) ScriptRef() common.Script {
490+
if o.TxOutScriptRef == nil {
491491
return nil
492492
}
493-
if lazyVal, ok := o.TxScriptRef.Content.(*cbor.LazyValue); ok {
494-
return lazyVal
495-
}
496-
return nil
493+
return o.TxOutScriptRef.Script
497494
}
498495

499496
func (o BabbageTransactionOutput) Amount() uint64 {

ledger/byron/byron.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ func (o ByronTransactionOutput) Address() common.Address {
414414
return o.OutputAddress
415415
}
416416

417-
func (o ByronTransactionOutput) ScriptRef() *cbor.LazyValue {
417+
func (o ByronTransactionOutput) ScriptRef() common.Script {
418418
return nil
419419
}
420420

ledger/common/native_script.go renamed to ledger/common/script.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,87 @@
1515
package common
1616

1717
import (
18+
"errors"
1819
"fmt"
1920

2021
"github.com/blinklabs-io/gouroboros/cbor"
2122
)
2223

24+
const (
25+
ScriptRefTypeNativeScript = 0
26+
ScriptRefTypePlutusV1 = 1
27+
ScriptRefTypePlutusV2 = 2
28+
ScriptRefTypePlutusV3 = 3
29+
)
30+
31+
type Script interface {
32+
isScript()
33+
}
34+
35+
type ScriptRef struct {
36+
Type uint
37+
Script Script
38+
}
39+
40+
func (s *ScriptRef) UnmarshalCBOR(data []byte) error {
41+
// Unwrap outer CBOR tag
42+
var tmpTag cbor.Tag
43+
if _, err := cbor.Decode(data, &tmpTag); err != nil {
44+
return err
45+
}
46+
innerCbor, ok := tmpTag.Content.([]byte)
47+
if !ok {
48+
return errors.New("unexpected tag type")
49+
}
50+
// Determine script type
51+
var rawScript struct {
52+
cbor.StructAsArray
53+
Type uint
54+
Raw cbor.RawMessage
55+
}
56+
if _, err := cbor.Decode(innerCbor, &rawScript); err != nil {
57+
return err
58+
}
59+
var tmpScript Script
60+
switch rawScript.Type {
61+
case ScriptRefTypeNativeScript:
62+
tmpScript = &NativeScript{}
63+
case ScriptRefTypePlutusV1:
64+
tmpScript = &PlutusV1Script{}
65+
case ScriptRefTypePlutusV2:
66+
tmpScript = &PlutusV2Script{}
67+
case ScriptRefTypePlutusV3:
68+
tmpScript = &PlutusV3Script{}
69+
default:
70+
return fmt.Errorf("unknown script type %d", rawScript.Type)
71+
}
72+
// Decode script
73+
if _, err := cbor.Decode(rawScript.Raw, tmpScript); err != nil {
74+
return err
75+
}
76+
s.Type = rawScript.Type
77+
s.Script = tmpScript
78+
return nil
79+
}
80+
81+
type PlutusV1Script []byte
82+
83+
func (PlutusV1Script) isScript() {}
84+
85+
type PlutusV2Script []byte
86+
87+
func (PlutusV2Script) isScript() {}
88+
89+
type PlutusV3Script []byte
90+
91+
func (PlutusV3Script) isScript() {}
92+
2393
type NativeScript struct {
2494
item any
2595
}
2696

97+
func (NativeScript) isScript() {}
98+
2799
func (n *NativeScript) Item() any {
28100
return n.item
29101
}

ledger/common/script_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2025 Blink Labs Software
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package common_test
16+
17+
import (
18+
"encoding/hex"
19+
"reflect"
20+
"testing"
21+
22+
"github.com/blinklabs-io/gouroboros/cbor"
23+
"github.com/blinklabs-io/gouroboros/ledger/common"
24+
)
25+
26+
func TestScriptRefDecode(t *testing.T) {
27+
// 24_0(<<[3, h'480123456789abcdef']>>)
28+
testCbor, _ := hex.DecodeString("d8184c820349480123456789abcdef")
29+
scriptCbor, _ := hex.DecodeString("480123456789abcdef")
30+
expectedScript := common.PlutusV3Script(scriptCbor)
31+
var testScriptRef common.ScriptRef
32+
if _, err := cbor.Decode(testCbor, &testScriptRef); err != nil {
33+
t.Fatalf("unexpected error decoding script ref CBOR: %s", err)
34+
}
35+
if !reflect.DeepEqual(testScriptRef.Script, &expectedScript) {
36+
t.Fatalf("did not get expected script\n got: %#v\n wanted: %#v", testScriptRef.Script, &expectedScript)
37+
}
38+
}

ledger/common/tx.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ type TransactionOutput interface {
7171
DatumHash() *Blake2b256
7272
Cbor() []byte
7373
Utxorpc() (*utxorpc.TxOutput, error)
74-
ScriptRef() *cbor.LazyValue
74+
ScriptRef() Script
7575
}
7676

7777
type TransactionWitnessSet interface {

ledger/mary/mary.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ func (o MaryTransactionOutput) Address() common.Address {
446446
return o.OutputAddress
447447
}
448448

449-
func (txo MaryTransactionOutput) ScriptRef() *cbor.LazyValue {
449+
func (txo MaryTransactionOutput) ScriptRef() common.Script {
450450
return nil
451451
}
452452

ledger/shelley/shelley.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ func (o ShelleyTransactionOutput) Address() common.Address {
388388
return o.OutputAddress
389389
}
390390

391-
func (o ShelleyTransactionOutput) ScriptRef() *cbor.LazyValue {
391+
func (o ShelleyTransactionOutput) ScriptRef() common.Script {
392392
return nil
393393
}
394394

0 commit comments

Comments
 (0)