Skip to content

Commit

Permalink
feat: ledger support for Byron TX inputs/outputs
Browse files Browse the repository at this point in the history
Fixes #285
  • Loading branch information
agaffney committed Mar 27, 2024
1 parent f54eb30 commit f03682c
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 16 deletions.
137 changes: 128 additions & 9 deletions ledger/byron.go
Expand Up @@ -107,7 +107,7 @@ func (h *ByronMainBlockHeader) SlotNumber() uint64 {

func (h *ByronMainBlockHeader) IssuerVkey() IssuerVkey {
// Byron blocks don't have an issuer
return IssuerVkey([]byte{})
return IssuerVkey{}
}

func (h *ByronMainBlockHeader) BlockBodySize() uint64 {
Expand All @@ -123,8 +123,8 @@ type ByronTransaction struct {
cbor.StructAsArray
cbor.DecodeStoreCbor
// TODO: flesh these out
TxInputs []any
TxOutputs []any
TxInputs []ByronTransactionInput
TxOutputs []ByronTransactionOutput
Attributes *cbor.Value
}

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

func (t *ByronTransaction) Inputs() []TransactionInput {
// TODO
return nil
ret := []TransactionInput{}
for _, input := range t.TxInputs {
ret = append(ret, input)
}
return ret
}

func (t *ByronTransaction) Outputs() []TransactionOutput {
// TODO
return nil
ret := []TransactionOutput{}
for _, output := range t.TxOutputs {
output := output
ret = append(ret, &output)
}
return ret
}

func (t *ByronTransaction) Fee() uint64 {
Expand Down Expand Up @@ -170,6 +177,114 @@ func (t *ByronTransaction) Utxorpc() *utxorpc.Tx {
return &utxorpc.Tx{}
}

type ByronTransactionInput struct {
cbor.StructAsArray
TxId Blake2b256
OutputIndex uint32
}

func (i *ByronTransactionInput) UnmarshalCBOR(data []byte) error {
id, err := cbor.DecodeIdFromList(data)
if err != nil {
return err
}
switch id {
case 0:
var tmpData struct {
cbor.StructAsArray
Id int
Cbor []byte
}
if _, err := cbor.Decode(data, &tmpData); err != nil {
return err
}
if err := cbor.DecodeGeneric(tmpData.Cbor, i); err != nil {
return err
}
default:
// [u8 .ne 0, encoded-cbor]
return fmt.Errorf("can't parse yet")
}
return nil
}

func (i ByronTransactionInput) Id() Blake2b256 {
return i.TxId
}

func (i ByronTransactionInput) Index() uint32 {
return i.OutputIndex
}

func (i ByronTransactionInput) Utxorpc() *utxorpc.TxInput {
return &utxorpc.TxInput{
TxHash: i.TxId.Bytes(),
OutputIndex: i.OutputIndex,
// AsOutput: i.AsOutput,
// Redeemer: i.Redeemer,
}
}

func (i ByronTransactionInput) String() string {
return fmt.Sprintf("%s#%d", i.TxId, i.OutputIndex)
}

func (i ByronTransactionInput) MarshalJSON() ([]byte, error) {
return []byte("\"" + i.String() + "\""), nil
}

type ByronTransactionOutput struct {
cbor.StructAsArray
cbor.DecodeStoreCbor
OutputAddress Address `json:"address"`
OutputAmount uint64 `json:"amount"`
}

func (o *ByronTransactionOutput) UnmarshalCBOR(data []byte) error {
// Save original CBOR
o.SetCbor(data)
var tmpData struct {
cbor.StructAsArray
WrappedAddress cbor.RawMessage
Amount uint64
}
if _, err := cbor.Decode(data, &tmpData); err != nil {
return err
}
o.OutputAmount = tmpData.Amount
if _, err := cbor.Decode(tmpData.WrappedAddress, &o.OutputAddress); err != nil {
return err
}
return nil
}

func (o ByronTransactionOutput) Address() Address {
return o.OutputAddress
}

func (o ByronTransactionOutput) Amount() uint64 {
return o.OutputAmount
}

func (o ByronTransactionOutput) Assets() *MultiAsset[MultiAssetTypeOutput] {
return nil
}

func (o ByronTransactionOutput) DatumHash() *Blake2b256 {
return nil
}

func (o ByronTransactionOutput) Datum() *cbor.LazyValue {
return nil
}

func (o ByronTransactionOutput) Utxorpc() *utxorpc.TxOutput {
return &utxorpc.TxOutput{
Address: o.OutputAddress.Bytes(),
Coin: o.Amount(),
}
}

type ByronMainBlockBody struct {
cbor.StructAsArray
// TODO: split this to its own type
Expand Down Expand Up @@ -279,8 +394,12 @@ func (b *ByronMainBlock) Era() Era {
}

func (b *ByronMainBlock) Transactions() []Transaction {
// TODO
return nil
ret := make([]Transaction, len(b.Body.TxPayload))
for idx, payload := range b.Body.TxPayload {
payload := payload
ret[idx] = &payload.Transaction
}
return ret
}

func (b *ByronMainBlock) Utxorpc() *utxorpc.Block {
Expand Down
18 changes: 11 additions & 7 deletions ledger/common.go
Expand Up @@ -336,14 +336,18 @@ func (a *Address) populateFromBytes(data []byte) error {
}

func (a *Address) UnmarshalCBOR(data []byte) error {
// Decode bytes from CBOR
// Try to unwrap as bytestring (Shelley and forward)
tmpData := []byte{}
if _, err := cbor.Decode(data, &tmpData); err != nil {
return err
}
err := a.populateFromBytes(tmpData)
if err != nil {
return err
if _, err := cbor.Decode(data, &tmpData); err == nil {
err := a.populateFromBytes(tmpData)
if err != nil {
return err
}
} else {
// Probably a Byron address
if err := a.populateFromBytes(data); err != nil {
return err
}
}
return nil
}
Expand Down
5 changes: 5 additions & 0 deletions ledger/common_test.go
Expand Up @@ -139,6 +139,11 @@ func TestAddressFromBytes(t *testing.T) {
addressBytesHex: "015bad085057ac10ecc7060f7ac41edd6f63068d8963ef7d86ca58669e5ecf2d283418a60be5a848a2380eb721000da1e0bbf39733134beca4cb57afb0b35fc89c63061c9914e055001a518c7516",
expectedAddress: "addr1q9d66zzs27kppmx8qc8h43q7m4hkxp5d39377lvxefvxd8j7eukjsdqc5c97t2zg5guqadepqqx6rc9m7wtnxy6tajjvk4a0kze4ljyuvvrpexg5up2sqxj33363v35gtew",
},
// Byron address
{
addressBytesHex: "82d818584283581caf56de241bcca83d72c51e74d18487aa5bc68b45e2caa170fa329d3aa101581e581cea1425ccdd649b25af5deb7e6335da2eb8167353a55e77925122e95f001a3a858621",
expectedAddress: "DdzFFzCqrht2ii4Vc7KRchSkVvQtCqdGkQt4nF4Yxg1NpsubFBity2Tpt2eSEGrxBH1eva8qCFKM2Y5QkwM1SFBizRwZgz1N452WYvgG",
},
}
for _, testDef := range testDefs {
addr := Address{}
Expand Down

0 comments on commit f03682c

Please sign in to comment.