Skip to content

Commit 06bac64

Browse files
authored
Merge pull request #311 from blinklabs-io/feat/ledger-tx-script-datum
feat: support for parsing TX output datum
2 parents e290f37 + 43e725a commit 06bac64

File tree

7 files changed

+130
-7
lines changed

7 files changed

+130
-7
lines changed

cbor/value.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,20 @@ func (v *Value) UnmarshalCBOR(data []byte) error {
9292
func (v Value) Cbor() []byte {
9393
return []byte(v.cborData)
9494
}
95+
96+
type LazyValue struct {
97+
*Value
98+
}
99+
100+
func (l *LazyValue) UnmarshalCBOR(data []byte) error {
101+
if l.Value == nil {
102+
l.Value = &Value{}
103+
}
104+
l.cborData = string(data[:])
105+
return nil
106+
}
107+
108+
func (l *LazyValue) Decode() (*Value, error) {
109+
err := l.Value.UnmarshalCBOR([]byte(l.cborData))
110+
return l.Value, err
111+
}

cmd/block-fetch/main.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,14 @@ func main() {
114114
}
115115
}
116116
}
117+
if output.Datum() != nil {
118+
datumValue, err := output.Datum().Decode()
119+
if err != nil {
120+
fmt.Printf(" Datum (hex): %x\n", output.Datum().Cbor())
121+
} else {
122+
fmt.Printf(" Datum: %#v\n", datumValue.Value)
123+
}
124+
}
117125
fmt.Println("")
118126
}
119127
}

ledger/alonzo.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,9 @@ func (b *AlonzoTransactionBody) Outputs() []TransactionOutput {
114114
type AlonzoTransactionOutput struct {
115115
cbor.StructAsArray
116116
cbor.DecodeStoreCbor
117-
OutputAddress Address
118-
OutputAmount MaryTransactionOutputValue
119-
DatumHash Blake2b256
117+
OutputAddress Address
118+
OutputAmount MaryTransactionOutputValue
119+
TxOutputDatumHash *Blake2b256
120120
}
121121

122122
func (o *AlonzoTransactionOutput) UnmarshalCBOR(cborData []byte) error {
@@ -157,6 +157,14 @@ func (o AlonzoTransactionOutput) Assets() *MultiAsset[MultiAssetTypeOutput] {
157157
return o.OutputAmount.Assets
158158
}
159159

160+
func (o AlonzoTransactionOutput) DatumHash() *Blake2b256 {
161+
return o.TxOutputDatumHash
162+
}
163+
164+
func (o AlonzoTransactionOutput) Datum() *cbor.LazyValue {
165+
return nil
166+
}
167+
160168
type AlonzoTransactionWitnessSet struct {
161169
ShelleyTransactionWitnessSet
162170
PlutusScripts []cbor.RawMessage `cbor:"3,keyasint,omitempty"`

ledger/babbage.go

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,69 @@ func (b *BabbageTransactionBody) Outputs() []TransactionOutput {
155155
return ret
156156
}
157157

158+
const (
159+
DatumOptionTypeHash = 0
160+
DatumOptionTypeData = 1
161+
)
162+
163+
type BabbageTransactionOutputDatumOption struct {
164+
hash *Blake2b256
165+
data *cbor.LazyValue
166+
}
167+
168+
func (d *BabbageTransactionOutputDatumOption) UnmarshalCBOR(data []byte) error {
169+
datumOptionType, err := cbor.DecodeIdFromList(data)
170+
if err != nil {
171+
return err
172+
}
173+
switch datumOptionType {
174+
case DatumOptionTypeHash:
175+
var tmpDatumHash struct {
176+
cbor.StructAsArray
177+
Type int
178+
Hash Blake2b256
179+
}
180+
if _, err := cbor.Decode(data, &tmpDatumHash); err != nil {
181+
return err
182+
}
183+
d.hash = &(tmpDatumHash.Hash)
184+
case DatumOptionTypeData:
185+
var tmpDatumData struct {
186+
cbor.StructAsArray
187+
Type int
188+
DataCbor []byte
189+
}
190+
if _, err := cbor.Decode(data, &tmpDatumData); err != nil {
191+
return err
192+
}
193+
var datumValue cbor.LazyValue
194+
if _, err := cbor.Decode(tmpDatumData.DataCbor, &datumValue); err != nil {
195+
return err
196+
}
197+
d.data = &(datumValue)
198+
default:
199+
return fmt.Errorf("unsupported datum option type: %d", datumOptionType)
200+
}
201+
return nil
202+
}
203+
204+
func (d *BabbageTransactionOutputDatumOption) MarshalCBOR() ([]byte, error) {
205+
var tmpObj []interface{}
206+
if d.hash != nil {
207+
tmpObj = []interface{}{DatumOptionTypeHash, d.hash}
208+
} else if d.data != nil {
209+
tmpObj = []interface{}{DatumOptionTypeData, cbor.Tag{Number: 24, Content: d.data.Cbor()}}
210+
} else {
211+
return nil, fmt.Errorf("unknown datum option type")
212+
}
213+
return cbor.Encode(&tmpObj)
214+
}
215+
158216
type BabbageTransactionOutput struct {
159-
OutputAddress Address `cbor:"0,keyasint,omitempty"`
160-
OutputAmount MaryTransactionOutputValue `cbor:"1,keyasint,omitempty"`
161-
DatumOption []cbor.RawMessage `cbor:"2,keyasint,omitempty"`
162-
ScriptRef cbor.Tag `cbor:"3,keyasint,omitempty"`
217+
OutputAddress Address `cbor:"0,keyasint,omitempty"`
218+
OutputAmount MaryTransactionOutputValue `cbor:"1,keyasint,omitempty"`
219+
DatumOption *BabbageTransactionOutputDatumOption `cbor:"2,keyasint,omitempty"`
220+
ScriptRef *cbor.Tag `cbor:"3,keyasint,omitempty"`
163221
legacyOutput bool
164222
}
165223

@@ -202,6 +260,20 @@ func (o BabbageTransactionOutput) Assets() *MultiAsset[MultiAssetTypeOutput] {
202260
return o.OutputAmount.Assets
203261
}
204262

263+
func (o BabbageTransactionOutput) DatumHash() *Blake2b256 {
264+
if o.DatumOption != nil {
265+
return o.DatumOption.hash
266+
}
267+
return nil
268+
}
269+
270+
func (o BabbageTransactionOutput) Datum() *cbor.LazyValue {
271+
if o.DatumOption != nil {
272+
return o.DatumOption.data
273+
}
274+
return nil
275+
}
276+
205277
type BabbageTransactionWitnessSet struct {
206278
AlonzoTransactionWitnessSet
207279
PlutusV2Scripts []cbor.RawMessage `cbor:"6,keyasint,omitempty"`

ledger/mary.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,14 @@ func (o MaryTransactionOutput) Assets() *MultiAsset[MultiAssetTypeOutput] {
154154
return o.OutputAmount.Assets
155155
}
156156

157+
func (o MaryTransactionOutput) DatumHash() *Blake2b256 {
158+
return nil
159+
}
160+
161+
func (o MaryTransactionOutput) Datum() *cbor.LazyValue {
162+
return nil
163+
}
164+
157165
type MaryTransactionOutputValue struct {
158166
cbor.StructAsArray
159167
Amount uint64

ledger/shelley.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,14 @@ func (o ShelleyTransactionOutput) Assets() *MultiAsset[MultiAssetTypeOutput] {
208208
return nil
209209
}
210210

211+
func (o ShelleyTransactionOutput) DatumHash() *Blake2b256 {
212+
return nil
213+
}
214+
215+
func (o ShelleyTransactionOutput) Datum() *cbor.LazyValue {
216+
return nil
217+
}
218+
211219
type ShelleyTransactionWitnessSet struct {
212220
VkeyWitnesses []interface{} `cbor:"0,keyasint,omitempty"`
213221
MultisigScripts []interface{} `cbor:"1,keyasint,omitempty"`

ledger/tx.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ type TransactionOutput interface {
4343
Address() Address
4444
Amount() uint64
4545
Assets() *MultiAsset[MultiAssetTypeOutput]
46+
Datum() *cbor.LazyValue
47+
DatumHash() *Blake2b256
4648
}
4749

4850
func NewTransactionFromCbor(txType uint, data []byte) (interface{}, error) {

0 commit comments

Comments
 (0)