@@ -39,60 +39,93 @@ type blockchain interface {
39
39
// of the underlying blockchain, it should only possess the block headers
40
40
// and receipts up until the expected chain view head.
41
41
type ChainView struct {
42
- chain blockchain
43
- headNumber uint64
44
- hashes []common.Hash // block hashes starting backwards from headNumber until first canonical hash
42
+ chain blockchain
43
+ finishedHead uint64
44
+ hashes []common.Hash // block hashes starting backwards from finishedHead until first canonical hash
45
45
}
46
46
47
47
// NewChainView creates a new ChainView.
48
48
func NewChainView (chain blockchain , number uint64 , hash common.Hash ) * ChainView {
49
49
cv := & ChainView {
50
- chain : chain ,
51
- headNumber : number ,
52
- hashes : []common.Hash {hash },
50
+ chain : chain ,
51
+ finishedHead : number ,
52
+ hashes : []common.Hash {hash },
53
53
}
54
54
cv .extendNonCanonical ()
55
55
return cv
56
56
}
57
57
58
- // getBlockHash returns the block hash belonging to the given block number.
58
+ // ProcessedHead returns the highest block number where BlockId and Receipts
59
+ // are available.
60
+ // Note that though in the current implementation ProcessedHead is always equal
61
+ // to FinishedHead, the called should expect that ProcessedHead can be one block
62
+ // higher in case the view represents a chain during block processing, when the
63
+ // receipts and block id are already available but the header is not finished
64
+ // yet and therefore the block hash cannot be calculated.
65
+ func (cv * ChainView ) ProcessedHead () uint64 {
66
+ return cv .finishedHead
67
+ }
68
+
69
+ // FinishedHead returns the highest block number where BlockHash and Header
70
+ // are available.
71
+ func (cv * ChainView ) FinishedHead () uint64 {
72
+ return cv .finishedHead
73
+ }
74
+
75
+ // BlockHash returns the block hash belonging to the given block number.
59
76
// Note that the hash of the head block is not returned because ChainView might
60
77
// represent a view where the head block is currently being created.
61
- func (cv * ChainView ) getBlockHash (number uint64 ) common.Hash {
62
- if number >= cv .headNumber {
78
+ func (cv * ChainView ) BlockHash (number uint64 ) common.Hash {
79
+ if number > cv .finishedHead {
63
80
panic ("invalid block number" )
64
81
}
65
82
return cv .blockHash (number )
66
83
}
67
84
68
- // getBlockId returns the unique block id belonging to the given block number.
85
+ // BlockId returns the unique block id belonging to the given block number.
69
86
// Note that it is currently equal to the block hash. In the future it might
70
87
// be a different id for future blocks if the log index root becomes part of
71
88
// consensus and therefore rendering the index with the new head will happen
72
89
// before the hash of that new head is available.
73
- func (cv * ChainView ) getBlockId (number uint64 ) common.Hash {
74
- if number > cv .headNumber {
90
+ func (cv * ChainView ) BlockId (number uint64 ) common.Hash {
91
+ if number > cv .finishedHead {
75
92
panic ("invalid block number" )
76
93
}
77
94
return cv .blockHash (number )
78
95
}
79
96
80
- // getReceipts returns the set of receipts belonging to the block at the given
97
+ // Header returns the block header at the given block number.
98
+ func (cv * ChainView ) Header (number uint64 ) * types.Header {
99
+ return cv .chain .GetHeader (cv .BlockHash (number ), number )
100
+ }
101
+
102
+ // Receipts returns the set of receipts belonging to the block at the given
81
103
// block number.
82
- func (cv * ChainView ) getReceipts (number uint64 ) types.Receipts {
83
- if number > cv .headNumber {
104
+ func (cv * ChainView ) Receipts (number uint64 ) types.Receipts {
105
+ if number > cv .finishedHead {
84
106
panic ("invalid block number" )
85
107
}
86
108
blockHash := cv .blockHash (number )
87
109
if blockHash == (common.Hash {}) {
88
- log .Error ("Chain view: block hash unavailable" , "number" , number , "head" , cv .headNumber )
110
+ log .Error ("Chain view: block hash unavailable" , "number" , number , "head" , cv .finishedHead )
89
111
}
90
112
return cv .chain .GetReceiptsByHash (blockHash )
91
113
}
92
114
115
+ func (cv * ChainView ) SharedRange (cv2 * ChainView ) common.Range [uint64 ] {
116
+ if cv == nil || cv2 == nil {
117
+ return common.Range [uint64 ]{}
118
+ }
119
+ var sharedLen uint64
120
+ for n := min (cv .finishedHead + 1 - uint64 (len (cv .hashes )), cv2 .finishedHead + 1 - uint64 (len (cv2 .hashes ))); n <= cv .finishedHead && n <= cv2 .finishedHead && cv .blockHash (n ) == cv2 .blockHash (n ); n ++ {
121
+ sharedLen = n + 1
122
+ }
123
+ return common .NewRange (0 , sharedLen )
124
+ }
125
+
93
126
// limitedView returns a new chain view that is a truncated version of the parent view.
94
127
func (cv * ChainView ) limitedView (newHead uint64 ) * ChainView {
95
- if newHead >= cv .headNumber {
128
+ if newHead >= cv .finishedHead {
96
129
return cv
97
130
}
98
131
return NewChainView (cv .chain , newHead , cv .blockHash (newHead ))
@@ -103,7 +136,7 @@ func equalViews(cv1, cv2 *ChainView) bool {
103
136
if cv1 == nil || cv2 == nil {
104
137
return false
105
138
}
106
- return cv1 .headNumber == cv2 .headNumber && cv1 .getBlockId (cv1 .headNumber ) == cv2 .getBlockId (cv2 .headNumber )
139
+ return cv1 .finishedHead == cv2 .finishedHead && cv1 .BlockId (cv1 .finishedHead ) == cv2 .BlockId (cv2 .finishedHead )
107
140
}
108
141
109
142
// matchViews returns true if the two chain views are equivalent up until the
@@ -113,13 +146,13 @@ func matchViews(cv1, cv2 *ChainView, number uint64) bool {
113
146
if cv1 == nil || cv2 == nil {
114
147
return false
115
148
}
116
- if cv1 .headNumber < number || cv2 .headNumber < number {
149
+ if cv1 .finishedHead < number || cv2 .finishedHead < number {
117
150
return false
118
151
}
119
- if number == cv1 .headNumber || number == cv2 .headNumber {
120
- return cv1 .getBlockId (number ) == cv2 .getBlockId (number )
152
+ if number == cv1 .finishedHead || number == cv2 .finishedHead {
153
+ return cv1 .BlockId (number ) == cv2 .BlockId (number )
121
154
}
122
- return cv1 .getBlockHash (number ) == cv2 .getBlockHash (number )
155
+ return cv1 .BlockHash (number ) == cv2 .BlockHash (number )
123
156
}
124
157
125
158
// extendNonCanonical checks whether the previously known reverse list of head
@@ -128,7 +161,7 @@ func matchViews(cv1, cv2 *ChainView, number uint64) bool {
128
161
// more hashes to the list.
129
162
func (cv * ChainView ) extendNonCanonical () bool {
130
163
for {
131
- hash , number := cv .hashes [len (cv .hashes )- 1 ], cv .headNumber - uint64 (len (cv .hashes )- 1 )
164
+ hash , number := cv .hashes [len (cv .hashes )- 1 ], cv .finishedHead - uint64 (len (cv .hashes )- 1 )
132
165
if cv .chain .GetCanonicalHash (number ) == hash {
133
166
return true
134
167
}
@@ -147,14 +180,14 @@ func (cv *ChainView) extendNonCanonical() bool {
147
180
148
181
// blockHash returns the given block hash without doing the head number check.
149
182
func (cv * ChainView ) blockHash (number uint64 ) common.Hash {
150
- if number + uint64 (len (cv .hashes )) <= cv .headNumber {
183
+ if number + uint64 (len (cv .hashes )) <= cv .finishedHead {
151
184
hash := cv .chain .GetCanonicalHash (number )
152
185
if ! cv .extendNonCanonical () {
153
186
return common.Hash {}
154
187
}
155
- if number + uint64 (len (cv .hashes )) <= cv .headNumber {
188
+ if number + uint64 (len (cv .hashes )) <= cv .finishedHead {
156
189
return hash
157
190
}
158
191
}
159
- return cv .hashes [cv .headNumber - number ]
192
+ return cv .hashes [cv .finishedHead - number ]
160
193
}
0 commit comments