Skip to content

Commit ea934b5

Browse files
authored
feat: ledger support for Byron TX inputs/outputs (#567)
Fixes #285
1 parent f54eb30 commit ea934b5

File tree

3 files changed

+144
-16
lines changed

3 files changed

+144
-16
lines changed

ledger/byron.go

Lines changed: 128 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func (h *ByronMainBlockHeader) SlotNumber() uint64 {
107107

108108
func (h *ByronMainBlockHeader) IssuerVkey() IssuerVkey {
109109
// Byron blocks don't have an issuer
110-
return IssuerVkey([]byte{})
110+
return IssuerVkey{}
111111
}
112112

113113
func (h *ByronMainBlockHeader) BlockBodySize() uint64 {
@@ -123,8 +123,8 @@ type ByronTransaction struct {
123123
cbor.StructAsArray
124124
cbor.DecodeStoreCbor
125125
// TODO: flesh these out
126-
TxInputs []any
127-
TxOutputs []any
126+
TxInputs []ByronTransactionInput
127+
TxOutputs []ByronTransactionOutput
128128
Attributes *cbor.Value
129129
}
130130

@@ -134,13 +134,20 @@ func (t *ByronTransaction) Hash() string {
134134
}
135135

136136
func (t *ByronTransaction) Inputs() []TransactionInput {
137-
// TODO
138-
return nil
137+
ret := []TransactionInput{}
138+
for _, input := range t.TxInputs {
139+
ret = append(ret, input)
140+
}
141+
return ret
139142
}
140143

141144
func (t *ByronTransaction) Outputs() []TransactionOutput {
142-
// TODO
143-
return nil
145+
ret := []TransactionOutput{}
146+
for _, output := range t.TxOutputs {
147+
output := output
148+
ret = append(ret, &output)
149+
}
150+
return ret
144151
}
145152

146153
func (t *ByronTransaction) Fee() uint64 {
@@ -170,6 +177,114 @@ func (t *ByronTransaction) Utxorpc() *utxorpc.Tx {
170177
return &utxorpc.Tx{}
171178
}
172179

180+
type ByronTransactionInput struct {
181+
cbor.StructAsArray
182+
TxId Blake2b256
183+
OutputIndex uint32
184+
}
185+
186+
func (i *ByronTransactionInput) UnmarshalCBOR(data []byte) error {
187+
id, err := cbor.DecodeIdFromList(data)
188+
if err != nil {
189+
return err
190+
}
191+
switch id {
192+
case 0:
193+
var tmpData struct {
194+
cbor.StructAsArray
195+
Id int
196+
Cbor []byte
197+
}
198+
if _, err := cbor.Decode(data, &tmpData); err != nil {
199+
return err
200+
}
201+
if err := cbor.DecodeGeneric(tmpData.Cbor, i); err != nil {
202+
return err
203+
}
204+
default:
205+
// [u8 .ne 0, encoded-cbor]
206+
return fmt.Errorf("can't parse yet")
207+
}
208+
return nil
209+
}
210+
211+
func (i ByronTransactionInput) Id() Blake2b256 {
212+
return i.TxId
213+
}
214+
215+
func (i ByronTransactionInput) Index() uint32 {
216+
return i.OutputIndex
217+
}
218+
219+
func (i ByronTransactionInput) Utxorpc() *utxorpc.TxInput {
220+
return &utxorpc.TxInput{
221+
TxHash: i.TxId.Bytes(),
222+
OutputIndex: i.OutputIndex,
223+
// AsOutput: i.AsOutput,
224+
// Redeemer: i.Redeemer,
225+
}
226+
}
227+
228+
func (i ByronTransactionInput) String() string {
229+
return fmt.Sprintf("%s#%d", i.TxId, i.OutputIndex)
230+
}
231+
232+
func (i ByronTransactionInput) MarshalJSON() ([]byte, error) {
233+
return []byte("\"" + i.String() + "\""), nil
234+
}
235+
236+
type ByronTransactionOutput struct {
237+
cbor.StructAsArray
238+
cbor.DecodeStoreCbor
239+
OutputAddress Address `json:"address"`
240+
OutputAmount uint64 `json:"amount"`
241+
}
242+
243+
func (o *ByronTransactionOutput) UnmarshalCBOR(data []byte) error {
244+
// Save original CBOR
245+
o.SetCbor(data)
246+
var tmpData struct {
247+
cbor.StructAsArray
248+
WrappedAddress cbor.RawMessage
249+
Amount uint64
250+
}
251+
if _, err := cbor.Decode(data, &tmpData); err != nil {
252+
return err
253+
}
254+
o.OutputAmount = tmpData.Amount
255+
if _, err := cbor.Decode(tmpData.WrappedAddress, &o.OutputAddress); err != nil {
256+
return err
257+
}
258+
return nil
259+
}
260+
261+
func (o ByronTransactionOutput) Address() Address {
262+
return o.OutputAddress
263+
}
264+
265+
func (o ByronTransactionOutput) Amount() uint64 {
266+
return o.OutputAmount
267+
}
268+
269+
func (o ByronTransactionOutput) Assets() *MultiAsset[MultiAssetTypeOutput] {
270+
return nil
271+
}
272+
273+
func (o ByronTransactionOutput) DatumHash() *Blake2b256 {
274+
return nil
275+
}
276+
277+
func (o ByronTransactionOutput) Datum() *cbor.LazyValue {
278+
return nil
279+
}
280+
281+
func (o ByronTransactionOutput) Utxorpc() *utxorpc.TxOutput {
282+
return &utxorpc.TxOutput{
283+
Address: o.OutputAddress.Bytes(),
284+
Coin: o.Amount(),
285+
}
286+
}
287+
173288
type ByronMainBlockBody struct {
174289
cbor.StructAsArray
175290
// TODO: split this to its own type
@@ -279,8 +394,12 @@ func (b *ByronMainBlock) Era() Era {
279394
}
280395

281396
func (b *ByronMainBlock) Transactions() []Transaction {
282-
// TODO
283-
return nil
397+
ret := make([]Transaction, len(b.Body.TxPayload))
398+
for idx, payload := range b.Body.TxPayload {
399+
payload := payload
400+
ret[idx] = &payload.Transaction
401+
}
402+
return ret
284403
}
285404

286405
func (b *ByronMainBlock) Utxorpc() *utxorpc.Block {

ledger/common.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -336,14 +336,18 @@ func (a *Address) populateFromBytes(data []byte) error {
336336
}
337337

338338
func (a *Address) UnmarshalCBOR(data []byte) error {
339-
// Decode bytes from CBOR
339+
// Try to unwrap as bytestring (Shelley and forward)
340340
tmpData := []byte{}
341-
if _, err := cbor.Decode(data, &tmpData); err != nil {
342-
return err
343-
}
344-
err := a.populateFromBytes(tmpData)
345-
if err != nil {
346-
return err
341+
if _, err := cbor.Decode(data, &tmpData); err == nil {
342+
err := a.populateFromBytes(tmpData)
343+
if err != nil {
344+
return err
345+
}
346+
} else {
347+
// Probably a Byron address
348+
if err := a.populateFromBytes(data); err != nil {
349+
return err
350+
}
347351
}
348352
return nil
349353
}

ledger/common_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ func TestAddressFromBytes(t *testing.T) {
139139
addressBytesHex: "015bad085057ac10ecc7060f7ac41edd6f63068d8963ef7d86ca58669e5ecf2d283418a60be5a848a2380eb721000da1e0bbf39733134beca4cb57afb0b35fc89c63061c9914e055001a518c7516",
140140
expectedAddress: "addr1q9d66zzs27kppmx8qc8h43q7m4hkxp5d39377lvxefvxd8j7eukjsdqc5c97t2zg5guqadepqqx6rc9m7wtnxy6tajjvk4a0kze4ljyuvvrpexg5up2sqxj33363v35gtew",
141141
},
142+
// Byron address
143+
{
144+
addressBytesHex: "82d818584283581caf56de241bcca83d72c51e74d18487aa5bc68b45e2caa170fa329d3aa101581e581cea1425ccdd649b25af5deb7e6335da2eb8167353a55e77925122e95f001a3a858621",
145+
expectedAddress: "DdzFFzCqrht2ii4Vc7KRchSkVvQtCqdGkQt4nF4Yxg1NpsubFBity2Tpt2eSEGrxBH1eva8qCFKM2Y5QkwM1SFBizRwZgz1N452WYvgG",
146+
},
142147
}
143148
for _, testDef := range testDefs {
144149
addr := Address{}

0 commit comments

Comments
 (0)