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