From f2d90fcc399ade4846b0e9681c9f6bf06d630ce5 Mon Sep 17 00:00:00 2001 From: Chris Gianelloni Date: Thu, 25 Sep 2025 16:53:53 -0400 Subject: [PATCH] feat(ledger): leios ledger primitives Signed-off-by: Chris Gianelloni --- ledger/allegra/allegra.go | 6 +- ledger/alonzo/alonzo.go | 6 +- ledger/babbage/babbage.go | 15 +- ledger/block.go | 6 + ledger/byron/byron.go | 6 +- ledger/common/certs.go | 38 +++++ ledger/common/tx.go | 15 +- ledger/conway/conway.go | 6 +- ledger/leios.go | 50 ++++++ ledger/leios/leios.go | 292 ++++++++++++++++++++++++++++++++++++ ledger/leios/pparams.go | 27 ++++ ledger/leios/tx.go | 25 +++ ledger/mary/mary.go | 6 +- ledger/shelley/shelley.go | 6 +- ledger/verify_block_body.go | 4 +- 15 files changed, 496 insertions(+), 12 deletions(-) create mode 100644 ledger/leios.go create mode 100644 ledger/leios/leios.go create mode 100644 ledger/leios/pparams.go create mode 100644 ledger/leios/tx.go diff --git a/ledger/allegra/allegra.go b/ledger/allegra/allegra.go index a53aa91e..ff89c892 100644 --- a/ledger/allegra/allegra.go +++ b/ledger/allegra/allegra.go @@ -257,7 +257,11 @@ func (AllegraTransaction) Type() int { } func (t AllegraTransaction) Hash() common.Blake2b256 { - return t.Body.Hash() + return t.Id() +} + +func (t AllegraTransaction) Id() common.Blake2b256 { + return t.Body.Id() } func (t AllegraTransaction) Inputs() []common.TransactionInput { diff --git a/ledger/alonzo/alonzo.go b/ledger/alonzo/alonzo.go index 116f1da0..197ef095 100644 --- a/ledger/alonzo/alonzo.go +++ b/ledger/alonzo/alonzo.go @@ -609,7 +609,11 @@ func (AlonzoTransaction) Type() int { } func (t AlonzoTransaction) Hash() common.Blake2b256 { - return t.Body.Hash() + return t.Id() +} + +func (t AlonzoTransaction) Id() common.Blake2b256 { + return t.Body.Id() } func (t AlonzoTransaction) Inputs() []common.TransactionInput { diff --git a/ledger/babbage/babbage.go b/ledger/babbage/babbage.go index 7298e6b1..c2469027 100644 --- a/ledger/babbage/babbage.go +++ b/ledger/babbage/babbage.go @@ -236,6 +236,7 @@ type BabbageTransactionPparamUpdate struct { type BabbageTransactionBody struct { common.TransactionBodyBase + hash *common.Blake2b256 TxInputs shelley.ShelleyTransactionInputSet `cbor:"0,keyasint,omitempty"` TxOutputs []BabbageTransactionOutput `cbor:"1,keyasint,omitempty"` TxFee uint64 `cbor:"2,keyasint,omitempty"` @@ -266,6 +267,14 @@ func (b *BabbageTransactionBody) UnmarshalCBOR(cborData []byte) error { return nil } +func (b *BabbageTransactionBody) Id() common.Blake2b256 { + if b.hash == nil { + tmpHash := common.Blake2b256Hash(b.Cbor()) + b.hash = &tmpHash + } + return *b.hash +} + func (b *BabbageTransactionBody) Inputs() []common.TransactionInput { ret := []common.TransactionInput{} for _, input := range b.TxInputs.Items() { @@ -742,7 +751,11 @@ func (BabbageTransaction) Type() int { } func (t BabbageTransaction) Hash() common.Blake2b256 { - return t.Body.Hash() + return t.Id() +} + +func (t BabbageTransaction) Id() common.Blake2b256 { + return t.Body.Id() } func (t BabbageTransaction) Inputs() []common.TransactionInput { diff --git a/ledger/block.go b/ledger/block.go index b5ebad34..71f135e2 100644 --- a/ledger/block.go +++ b/ledger/block.go @@ -44,6 +44,10 @@ func NewBlockFromCbor(blockType uint, data []byte) (Block, error) { return NewBabbageBlockFromCbor(data) case BlockTypeConway: return NewConwayBlockFromCbor(data) + case BlockTypeLeiosEndorser: + return NewLeiosEndorserBlockFromCbor(data) + case BlockTypeLeiosRanking: + return NewLeiosRankingBlockFromCbor(data) } return nil, fmt.Errorf("unknown node-to-client block type: %d", blockType) } @@ -66,6 +70,8 @@ func NewBlockHeaderFromCbor(blockType uint, data []byte) (BlockHeader, error) { return NewBabbageBlockHeaderFromCbor(data) case BlockTypeConway: return NewConwayBlockHeaderFromCbor(data) + case BlockTypeLeiosRanking: + return NewLeiosBlockHeaderFromCbor(data) default: return nil, fmt.Errorf("unknown node-to-node block type: %d", blockType) } diff --git a/ledger/byron/byron.go b/ledger/byron/byron.go index 9f6144c4..28658004 100644 --- a/ledger/byron/byron.go +++ b/ledger/byron/byron.go @@ -161,6 +161,10 @@ func (ByronTransaction) Type() int { } func (t *ByronTransaction) Hash() common.Blake2b256 { + return t.Id() +} + +func (t *ByronTransaction) Id() common.Blake2b256 { if t.hash == nil { tmpHash := common.Blake2b256Hash(t.Cbor()) t.hash = &tmpHash @@ -289,7 +293,7 @@ func (t *ByronTransaction) Produced() []common.Utxo { ret = append( ret, common.Utxo{ - Id: NewByronTransactionInput(t.Hash().String(), idx), + Id: NewByronTransactionInput(t.Id().String(), idx), Output: output, }, ) diff --git a/ledger/common/certs.go b/ledger/common/certs.go index 2dc612dc..c390369a 100644 --- a/ledger/common/certs.go +++ b/ledger/common/certs.go @@ -46,6 +46,7 @@ const ( CertificateTypeRegistrationDrep = 16 CertificateTypeDeregistrationDrep = 17 CertificateTypeUpdateDrep = 18 + CertificateTypeLeiosEb = 19 ) type CertificateWrapper struct { @@ -99,6 +100,8 @@ func (c *CertificateWrapper) UnmarshalCBOR(data []byte) error { tmpCert = &DeregistrationDrepCertificate{} case CertificateTypeUpdateDrep: tmpCert = &UpdateDrepCertificate{} + case CertificateTypeLeiosEb: + tmpCert = &LeiosEbCertificate{} default: return fmt.Errorf("unknown certificate type: %d", certType) } @@ -1361,3 +1364,38 @@ func (c *UpdateDrepCertificate) Utxorpc() (*utxorpc.Certificate, error) { func (c *UpdateDrepCertificate) Type() uint { return c.CertType } + +type LeiosEbCertificate struct { + cbor.StructAsArray + cbor.DecodeStoreCbor + CertType uint + ElectionId Blake2b256 + EndorserBlockHash Blake2b256 + PersistentVoters []any + NonpersistentVoters map[Blake2b256]any + AggregateEligSig *any + AggregateVoteSig any +} + +func (c LeiosEbCertificate) isCertificate() {} + +func (c *LeiosEbCertificate) UnmarshalCBOR( + cborData []byte, +) error { + type tLeiosEbCertificate LeiosEbCertificate + var tmp tLeiosEbCertificate + if _, err := cbor.Decode(cborData, &tmp); err != nil { + return err + } + *c = LeiosEbCertificate(tmp) + c.SetCbor(cborData) + return nil +} + +func (c *LeiosEbCertificate) Utxorpc() (*utxorpc.Certificate, error) { + return &utxorpc.Certificate{}, nil +} + +func (c *LeiosEbCertificate) Type() uint { + return c.CertType +} diff --git a/ledger/common/tx.go b/ledger/common/tx.go index e5d4c211..4bda1511 100644 --- a/ledger/common/tx.go +++ b/ledger/common/tx.go @@ -26,6 +26,7 @@ type Transaction interface { TransactionBody Type() int Cbor() []byte + Hash() Blake2b256 Metadata() *cbor.LazyValue IsValid() bool Consumed() []TransactionInput @@ -36,7 +37,7 @@ type Transaction interface { type TransactionBody interface { Cbor() []byte Fee() uint64 - Hash() Blake2b256 + Id() Blake2b256 Inputs() []TransactionInput Outputs() []TransactionOutput TTL() uint64 @@ -97,6 +98,14 @@ type TransactionWitnessRedeemers interface { Iter() iter.Seq2[RedeemerKey, RedeemerValue] } +// TxReference provides a reference to a transaction which includes a hash of the full transaction +// body bytes and the total transaction size in bytes +type TxReference struct { + cbor.StructAsArray + TxHash Blake2b256 + TxSize uint16 +} + type Utxo struct { cbor.StructAsArray Id TransactionInput @@ -111,7 +120,7 @@ type TransactionBodyBase struct { hash *Blake2b256 } -func (b *TransactionBodyBase) Hash() Blake2b256 { +func (b *TransactionBodyBase) Id() Blake2b256 { if b.hash == nil { tmpHash := Blake2b256Hash(b.Cbor()) b.hash = &tmpHash @@ -230,7 +239,7 @@ func TransactionBodyToUtxorpc(tx TransactionBody) (*utxorpc.Tx, error) { // Validity: tx.Validity(), // Successful: tx.Successful(), // Auxiliary: tx.AuxData(), - Hash: tx.Hash().Bytes(), + Hash: tx.Id().Bytes(), // Proposals: tx.ProposalProcedures(), } for _, ri := range tx.ReferenceInputs() { diff --git a/ledger/conway/conway.go b/ledger/conway/conway.go index 1b635c55..3e014ebf 100644 --- a/ledger/conway/conway.go +++ b/ledger/conway/conway.go @@ -536,7 +536,11 @@ func (ConwayTransaction) Type() int { } func (t ConwayTransaction) Hash() common.Blake2b256 { - return t.Body.Hash() + return t.Id() +} + +func (t ConwayTransaction) Id() common.Blake2b256 { + return t.Body.Id() } func (t ConwayTransaction) Inputs() []common.TransactionInput { diff --git a/ledger/leios.go b/ledger/leios.go new file mode 100644 index 00000000..38c1dd56 --- /dev/null +++ b/ledger/leios.go @@ -0,0 +1,50 @@ +// Copyright 2025 Blink Labs Software +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ledger + +import "github.com/blinklabs-io/gouroboros/ledger/leios" + +// The below are compatibility types, constants, and functions for the Leios era +// to keep existing code working after a refactor of the ledger package + +// Leios types +type ( + LeiosBlockHeader = leios.LeiosBlockHeader + LeiosEndorderBlock = leios.LeiosEndorserBlock + LeiosRankingBlock = leios.LeiosRankingBlock + LeiosTransaction = leios.LeiosTransaction + LeiosTransactionBody = leios.LeiosTransactionBody + LeiosTransactionWitnessSet = leios.LeiosTransactionWitnessSet + LeiosProtocolParameters = leios.LeiosProtocolParameters + LeiosProtocolParameterUpdate = leios.LeiosProtocolParameterUpdate +) + +// Leios constants +const ( + EraIdLeios = leios.EraIdLeios + BlockTypeLeiosRanking = leios.BlockTypeLeiosRanking + BlockTypeLeiosEndorser = leios.BlockTypeLeiosEndorser + BlockHeaderTypeLeios = leios.BlockHeaderTypeLeios + TxTypeLeios = leios.TxTypeLeios +) + +// Leios functions +var ( + NewLeiosEndorserBlockFromCbor = leios.NewLeiosEndorserBlockFromCbor + NewLeiosRankingBlockFromCbor = leios.NewLeiosRankingBlockFromCbor + NewLeiosBlockHeaderFromCbor = leios.NewLeiosBlockHeaderFromCbor + NewLeiosTransactionFromCbor = leios.NewLeiosTransactionFromCbor + NewLeiosTransactionBodyFromCbor = leios.NewLeiosTransactionBodyFromCbor +) diff --git a/ledger/leios/leios.go b/ledger/leios/leios.go new file mode 100644 index 00000000..685f2664 --- /dev/null +++ b/ledger/leios/leios.go @@ -0,0 +1,292 @@ +// Copyright 2025 Blink Labs Software +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package leios + +import ( + "fmt" + + "github.com/blinklabs-io/gouroboros/cbor" + "github.com/blinklabs-io/gouroboros/ledger/babbage" + "github.com/blinklabs-io/gouroboros/ledger/common" + "github.com/blinklabs-io/gouroboros/ledger/conway" + utxorpc "github.com/utxorpc/go-codegen/utxorpc/v1alpha/cardano" +) + +const ( + EraIdLeios = 7 + EraNameLeios = "Leios" + + BlockTypeLeiosRanking = 8 + BlockTypeLeiosEndorser = 9 + + BlockHeaderTypeLeios = 7 + + TxTypeLeios = 7 +) + +var EraLeios = common.Era{ + Id: EraIdLeios, + Name: EraNameLeios, +} + +func init() { + common.RegisterEra(EraLeios) +} + +type LeiosBlockHeader struct { + cbor.StructAsArray + cbor.DecodeStoreCbor + hash *common.Blake2b256 + Body LeiosBlockHeaderBody + Signature []byte +} + +type LeiosBlockHeaderBody struct { + babbage.BabbageBlockHeaderBody + AnnouncedEb *common.Blake2b256 + AnnouncedEbSize *uint32 + CertifiedEb *bool +} + +type LeiosEndorserBlock struct { + cbor.DecodeStoreCbor + cbor.StructAsArray + hash *common.Blake2b256 + TxReferences []common.TxReference +} + +func (h *LeiosBlockHeader) UnmarshalCBOR(cborData []byte) error { + type tLeiosBlockHeader LeiosBlockHeader + var tmp tLeiosBlockHeader + if _, err := cbor.Decode(cborData, &tmp); err != nil { + return err + } + *h = LeiosBlockHeader(tmp) + h.SetCbor(cborData) + return nil +} + +func (h *LeiosBlockHeader) Hash() common.Blake2b256 { + if h.hash == nil { + tmpHash := common.Blake2b256Hash(h.Cbor()) + h.hash = &tmpHash + } + return *h.hash +} + +func (h *LeiosBlockHeader) PrevHash() common.Blake2b256 { + return h.Body.PrevHash +} + +func (h *LeiosBlockHeader) BlockNumber() uint64 { + return h.Body.BlockNumber +} + +func (h *LeiosBlockHeader) SlotNumber() uint64 { + return h.Body.Slot +} + +func (h *LeiosBlockHeader) IssuerVkey() common.IssuerVkey { + return h.Body.IssuerVkey +} + +func (h *LeiosBlockHeader) BlockBodySize() uint64 { + return h.Body.BlockBodySize +} + +func (h *LeiosBlockHeader) Era() common.Era { + return EraLeios +} + +func (LeiosEndorserBlock) Type() int { + return BlockTypeLeiosEndorser +} + +func (b *LeiosEndorserBlock) BlockBodySize() uint64 { + // Get size for the entire block + return uint64(len(b.Cbor())) +} + +func (b *LeiosEndorserBlock) BlockNumber() uint64 { + return 0 +} + +func (b *LeiosEndorserBlock) SlotNumber() uint64 { + return 0 +} + +func (b *LeiosEndorserBlock) Era() common.Era { + return EraLeios +} + +func (b *LeiosEndorserBlock) Hash() common.Blake2b256 { + if b.hash == nil { + tmpHash := common.Blake2b256Hash(b.Cbor()) + b.hash = &tmpHash + } + return *b.hash +} + +func (b *LeiosEndorserBlock) Header() common.BlockHeader { + return &LeiosBlockHeader{} +} + +func (b *LeiosEndorserBlock) IssuerVkey() common.IssuerVkey { + // TODO: This will cause a problem in validation code + return common.IssuerVkey{} +} + +func (b *LeiosEndorserBlock) PrevHash() common.Blake2b256 { + return common.Blake2b256{} +} + +func (b *LeiosEndorserBlock) Transactions() []common.Transaction { + // TODO: convert TxReferences into []Transaction + // TxReferences []common.TxReference + return []common.Transaction{} +} + +func (b *LeiosEndorserBlock) Utxorpc() (*utxorpc.Block, error) { + // TODO: figure out how this fits into UTxO RPC + return &utxorpc.Block{}, nil +} + +type LeiosRankingBlock struct { + conway.ConwayBlock + BlockHeader *LeiosBlockHeader `cbor:"0,keyasint"` + EbCertificate *common.LeiosEbCertificate `cbor:"5,keyasint,omitempty,omitzero"` +} + +func (LeiosRankingBlock) Type() int { + return BlockTypeLeiosRanking +} + +func (b *LeiosRankingBlock) BlockBodySize() uint64 { + return b.BlockHeader.BlockBodySize() +} + +func (b *LeiosRankingBlock) BlockNumber() uint64 { + return b.BlockHeader.BlockNumber() +} + +func (b *LeiosRankingBlock) SlotNumber() uint64 { + return b.BlockHeader.SlotNumber() +} + +func (b *LeiosRankingBlock) Era() common.Era { + return EraLeios +} + +func (b *LeiosRankingBlock) Hash() common.Blake2b256 { + return b.BlockHeader.Hash() +} + +func (b *LeiosRankingBlock) Header() common.BlockHeader { + return b.BlockHeader +} + +func (b *LeiosRankingBlock) IssuerVkey() common.IssuerVkey { + return b.BlockHeader.IssuerVkey() +} + +func (b *LeiosRankingBlock) PrevHash() common.Blake2b256 { + return b.BlockHeader.PrevHash() +} + +func (b *LeiosRankingBlock) Transactions() []common.Transaction { + // TODO: decide if we resolve EB transactions here and return them + invalidTxMap := make(map[uint]bool, len(b.InvalidTransactions)) + for _, invalidTxIdx := range b.InvalidTransactions { + invalidTxMap[invalidTxIdx] = true + } + + ret := make([]common.Transaction, len(b.TransactionBodies)) + // #nosec G115 + for idx := range b.TransactionBodies { + ret[idx] = &conway.ConwayTransaction{ + Body: b.TransactionBodies[idx], + WitnessSet: b.TransactionWitnessSets[idx], + TxMetadata: b.TransactionMetadataSet[uint(idx)], + TxIsValid: !invalidTxMap[uint(idx)], + } + } + return ret +} + +func (b *LeiosRankingBlock) Utxorpc() (*utxorpc.Block, error) { + txs := []*utxorpc.Tx{} + for _, t := range b.Transactions() { + tx, err := t.Utxorpc() + if err != nil { + return nil, err + } + txs = append(txs, tx) + } + body := &utxorpc.BlockBody{ + Tx: txs, + } + header := &utxorpc.BlockHeader{ + Hash: b.Hash().Bytes(), + Height: b.BlockNumber(), + Slot: b.SlotNumber(), + } + block := &utxorpc.Block{ + Body: body, + Header: header, + } + return block, nil +} + +func NewLeiosEndorserBlockFromCbor(data []byte) (*LeiosEndorserBlock, error) { + var leiosEndorserBlock LeiosEndorserBlock + if _, err := cbor.Decode(data, &leiosEndorserBlock); err != nil { + return nil, fmt.Errorf("decode Leios endorser block error: %w", err) + } + return &leiosEndorserBlock, nil +} + +func NewLeiosRankingBlockFromCbor(data []byte) (*LeiosRankingBlock, error) { + var leiosRankingBlock LeiosRankingBlock + if _, err := cbor.Decode(data, &leiosRankingBlock); err != nil { + return nil, fmt.Errorf("decode Leios ranking block error: %w", err) + } + return &leiosRankingBlock, nil +} + +func NewLeiosBlockHeaderFromCbor(data []byte) (*LeiosBlockHeader, error) { + var leiosBlockHeader LeiosBlockHeader + if _, err := cbor.Decode(data, &leiosBlockHeader); err != nil { + return nil, fmt.Errorf("decode Leios block header error: %w", err) + } + return &leiosBlockHeader, nil +} + +func NewLeiosTransactionBodyFromCbor( + data []byte, +) (*LeiosTransactionBody, error) { + var leiosTx LeiosTransactionBody + if _, err := cbor.Decode(data, &leiosTx); err != nil { + return nil, fmt.Errorf("decode Leios transaction body error: %w", err) + } + return &leiosTx, nil +} + +func NewLeiosTransactionFromCbor(data []byte) (*LeiosTransaction, error) { + var leiosTx LeiosTransaction + if _, err := cbor.Decode(data, &leiosTx); err != nil { + return nil, fmt.Errorf("decode Leios transaction error: %w", err) + } + return &leiosTx, nil +} diff --git a/ledger/leios/pparams.go b/ledger/leios/pparams.go new file mode 100644 index 00000000..790dd091 --- /dev/null +++ b/ledger/leios/pparams.go @@ -0,0 +1,27 @@ +// Copyright 2025 Blink Labs Software +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package leios + +import ( + "github.com/blinklabs-io/gouroboros/ledger/conway" +) + +type LeiosProtocolParameters struct { + conway.ConwayProtocolParameters +} + +type LeiosProtocolParameterUpdate struct { + conway.ConwayProtocolParameterUpdate +} diff --git a/ledger/leios/tx.go b/ledger/leios/tx.go new file mode 100644 index 00000000..cfdb0e34 --- /dev/null +++ b/ledger/leios/tx.go @@ -0,0 +1,25 @@ +// Copyright 2025 Blink Labs Software +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package leios + +import ( + "github.com/blinklabs-io/gouroboros/ledger/conway" +) + +type ( + LeiosTransaction = conway.ConwayTransaction + LeiosTransactionBody = conway.ConwayTransactionBody + LeiosTransactionWitnessSet = conway.ConwayTransactionWitnessSet +) diff --git a/ledger/mary/mary.go b/ledger/mary/mary.go index 8b164e63..f71137a3 100644 --- a/ledger/mary/mary.go +++ b/ledger/mary/mary.go @@ -265,7 +265,11 @@ func (MaryTransaction) Type() int { } func (t MaryTransaction) Hash() common.Blake2b256 { - return t.Body.Hash() + return t.Id() +} + +func (t MaryTransaction) Id() common.Blake2b256 { + return t.Body.Id() } func (t MaryTransaction) Inputs() []common.TransactionInput { diff --git a/ledger/shelley/shelley.go b/ledger/shelley/shelley.go index 83f09799..043804d6 100644 --- a/ledger/shelley/shelley.go +++ b/ledger/shelley/shelley.go @@ -558,7 +558,11 @@ func (ShelleyTransaction) Type() int { } func (t ShelleyTransaction) Hash() common.Blake2b256 { - return t.Body.Hash() + return t.Id() +} + +func (t ShelleyTransaction) Id() common.Blake2b256 { + return t.Body.Id() } func (t ShelleyTransaction) Inputs() []common.TransactionInput { diff --git a/ledger/verify_block_body.go b/ledger/verify_block_body.go index f36a17dd..e563366c 100644 --- a/ledger/verify_block_body.go +++ b/ledger/verify_block_body.go @@ -423,7 +423,7 @@ func GetBlockOutput( var regisCerts []RegisCert var deRegisCerts []DeRegisCert for txIndex, tx := range txBodies { - txHash := tx.Hash().String() + txId := tx.Id().String() txOutputs := tx.Outputs() for outputIndex, txOutput := range txOutputs { cborDatum := []byte{} @@ -441,7 +441,7 @@ func GetBlockOutput( ) } tmpOutput := UTXOOutput{ - TxHash: txHash, + TxHash: txId, OutputIndex: strconv.Itoa(outputIndex), Tokens: tokens, DatumHex: cborDatumHex,