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