github.com/iotexproject/iotex-core@v1.14.1-rc1/blockchain/block/block.go (about) 1 // Copyright (c) 2022 IoTeX Foundation 2 // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability 3 // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. 4 // This source code is governed by Apache License 2.0 that can be found in the LICENSE file. 5 6 package block 7 8 import ( 9 "time" 10 11 "github.com/iotexproject/go-pkgs/hash" 12 "github.com/iotexproject/iotex-proto/golang/iotextypes" 13 "github.com/pkg/errors" 14 "go.uber.org/zap" 15 "google.golang.org/protobuf/proto" 16 17 "github.com/iotexproject/iotex-core/action" 18 "github.com/iotexproject/iotex-core/endorsement" 19 "github.com/iotexproject/iotex-core/pkg/log" 20 ) 21 22 // Block defines the struct of block 23 type Block struct { 24 Header 25 Body 26 Footer 27 28 // TODO: move receipts out of block struct 29 Receipts []*action.Receipt 30 } 31 32 // ConvertToBlockPb converts Block to Block 33 func (b *Block) ConvertToBlockPb() *iotextypes.Block { 34 footer, err := b.ConvertToBlockFooterPb() 35 if err != nil { 36 log.L().Panic("failed to convert block footer to protobuf message") 37 } 38 return &iotextypes.Block{ 39 Header: b.Header.Proto(), 40 Body: b.Body.Proto(), 41 Footer: footer, 42 } 43 } 44 45 // Serialize returns the serialized byte stream of the block 46 func (b *Block) Serialize() ([]byte, error) { 47 return proto.Marshal(b.ConvertToBlockPb()) 48 } 49 50 // VerifyTxRoot verifies the transaction root hash 51 func (b *Block) VerifyTxRoot() error { 52 root, err := b.CalculateTxRoot() 53 if err != nil { 54 log.L().Debug("error in getting hash", zap.Error(err)) 55 return err 56 } 57 if !b.Header.VerifyTransactionRoot(root) { 58 return ErrTxRootMismatch 59 } 60 return nil 61 } 62 63 // RunnableActions abstructs RunnableActions from a Block. 64 func (b *Block) RunnableActions() RunnableActions { 65 return RunnableActions{actions: b.Actions, txHash: b.txRoot} 66 } 67 68 // Finalize creates a footer for the block 69 func (b *Block) Finalize(endorsements []*endorsement.Endorsement, ts time.Time) error { 70 if len(b.endorsements) != 0 { 71 return errors.New("the block has been finalized") 72 } 73 b.endorsements = endorsements 74 b.commitTime = ts 75 76 return nil 77 } 78 79 // TransactionLog returns transaction logs in the block 80 func (b *Block) TransactionLog() *BlkTransactionLog { 81 if len(b.Receipts) == 0 { 82 return nil 83 } 84 85 blkLog := BlkTransactionLog{ 86 actionLogs: []*TransactionLog{}, 87 } 88 for _, r := range b.Receipts { 89 if log := ReceiptTransactionLog(r); log != nil { 90 blkLog.actionLogs = append(blkLog.actionLogs, log) 91 } 92 } 93 94 if len(blkLog.actionLogs) == 0 { 95 return nil 96 } 97 return &blkLog 98 } 99 100 // ActionByHash returns the action of a given hash 101 func (b *Block) ActionByHash(h hash.Hash256) (*action.SealedEnvelope, uint32, error) { 102 for i, act := range b.Actions { 103 actHash, err := act.Hash() 104 if err != nil { 105 return nil, 0, errors.Errorf("hash failed for action %d", i) 106 } 107 if actHash == h { 108 return act, uint32(i), nil 109 } 110 } 111 return nil, 0, errors.Errorf("block does not have action %x", h) 112 }