@blinklabs/dingo 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/.dingo/blob/000001.sst +0 -0
  2. package/.dingo/blob/000001.vlog +0 -0
  3. package/.dingo/blob/DISCARD +0 -0
  4. package/.dingo/blob/KEYREGISTRY +2 -0
  5. package/.dingo/blob/MANIFEST +0 -0
  6. package/.dingo/metadata.sqlite +0 -0
  7. package/.github/workflows/golangci-lint.yml +1 -1
  8. package/.github/workflows/publish.yml +1 -7
  9. package/README.md +2 -1
  10. package/{bin/dingo → dingo} +0 -0
  11. package/dingo.yaml.example +53 -0
  12. package/package.json +2 -2
  13. package/Dockerfile +0 -25
  14. package/Makefile +0 -53
  15. package/blockfetch.go +0 -144
  16. package/chain/chain.go +0 -504
  17. package/chain/chain_test.go +0 -468
  18. package/chain/errors.go +0 -80
  19. package/chain/event.go +0 -33
  20. package/chain/iter.go +0 -64
  21. package/chainsync/chainsync.go +0 -97
  22. package/chainsync.go +0 -223
  23. package/cmd/dingo/load.go +0 -52
  24. package/cmd/dingo/main.go +0 -118
  25. package/cmd/dingo/serve.go +0 -49
  26. package/config/cardano/node.go +0 -192
  27. package/config/cardano/node_test.go +0 -85
  28. package/config/cardano/preview/README.md +0 -4
  29. package/config/cardano/preview/alonzo-genesis.json +0 -196
  30. package/config/cardano/preview/byron-genesis.json +0 -117
  31. package/config/cardano/preview/config.json +0 -114
  32. package/config/cardano/preview/conway-genesis.json +0 -297
  33. package/config/cardano/preview/shelley-genesis.json +0 -68
  34. package/config.go +0 -245
  35. package/connmanager/connection_manager.go +0 -105
  36. package/connmanager/connection_manager_test.go +0 -185
  37. package/connmanager/event.go +0 -37
  38. package/connmanager/listener.go +0 -140
  39. package/connmanager/outbound.go +0 -93
  40. package/connmanager/socket.go +0 -55
  41. package/connmanager/unix.go +0 -78
  42. package/custom-p2p-topology.json +0 -24
  43. package/custom-p2p-topology.json.backup +0 -24
  44. package/custom-p2p-topology.json.mainnet +0 -37
  45. package/database/account.go +0 -180
  46. package/database/block.go +0 -362
  47. package/database/certs.go +0 -53
  48. package/database/commit_timestamp.go +0 -77
  49. package/database/database.go +0 -118
  50. package/database/database_test.go +0 -62
  51. package/database/drep.go +0 -47
  52. package/database/epoch.go +0 -121
  53. package/database/immutable/chunk.go +0 -182
  54. package/database/immutable/immutable.go +0 -350
  55. package/database/immutable/immutable_test.go +0 -59
  56. package/database/immutable/primary.go +0 -106
  57. package/database/immutable/secondary.go +0 -103
  58. package/database/immutable/testdata/08893.chunk +0 -0
  59. package/database/immutable/testdata/08893.primary +0 -0
  60. package/database/immutable/testdata/08893.secondary +0 -0
  61. package/database/immutable/testdata/08894.chunk +0 -0
  62. package/database/immutable/testdata/08894.primary +0 -0
  63. package/database/immutable/testdata/08894.secondary +0 -0
  64. package/database/immutable/testdata/README.md +0 -4
  65. package/database/plugin/blob/badger/commit_timestamp.go +0 -50
  66. package/database/plugin/blob/badger/database.go +0 -152
  67. package/database/plugin/blob/badger/logger.go +0 -63
  68. package/database/plugin/blob/badger/metrics.go +0 -98
  69. package/database/plugin/blob/blob.go +0 -19
  70. package/database/plugin/blob/store.go +0 -40
  71. package/database/plugin/log.go +0 -27
  72. package/database/plugin/metadata/metadata.go +0 -19
  73. package/database/plugin/metadata/sqlite/account.go +0 -313
  74. package/database/plugin/metadata/sqlite/certs.go +0 -58
  75. package/database/plugin/metadata/sqlite/commit_timestamp.go +0 -68
  76. package/database/plugin/metadata/sqlite/database.go +0 -218
  77. package/database/plugin/metadata/sqlite/drep.go +0 -140
  78. package/database/plugin/metadata/sqlite/epoch.go +0 -120
  79. package/database/plugin/metadata/sqlite/models/account.go +0 -118
  80. package/database/plugin/metadata/sqlite/models/auth_committee_hot.go +0 -26
  81. package/database/plugin/metadata/sqlite/models/drep.go +0 -52
  82. package/database/plugin/metadata/sqlite/models/epoch.go +0 -31
  83. package/database/plugin/metadata/sqlite/models/models.go +0 -46
  84. package/database/plugin/metadata/sqlite/models/pool.go +0 -97
  85. package/database/plugin/metadata/sqlite/models/pparam_update.go +0 -27
  86. package/database/plugin/metadata/sqlite/models/pparams.go +0 -27
  87. package/database/plugin/metadata/sqlite/models/resign_committee_cold.go +0 -27
  88. package/database/plugin/metadata/sqlite/models/stake_vote_delegation.go +0 -27
  89. package/database/plugin/metadata/sqlite/models/tip.go +0 -26
  90. package/database/plugin/metadata/sqlite/models/update_drep.go +0 -27
  91. package/database/plugin/metadata/sqlite/models/utxo.go +0 -30
  92. package/database/plugin/metadata/sqlite/models/vote_delegation.go +0 -26
  93. package/database/plugin/metadata/sqlite/models/vote_registration_delegation.go +0 -15
  94. package/database/plugin/metadata/sqlite/pool.go +0 -240
  95. package/database/plugin/metadata/sqlite/pparams.go +0 -110
  96. package/database/plugin/metadata/sqlite/tip.go +0 -83
  97. package/database/plugin/metadata/sqlite/utxo.go +0 -292
  98. package/database/plugin/metadata/store.go +0 -198
  99. package/database/plugin/option.go +0 -190
  100. package/database/plugin/plugin.go +0 -20
  101. package/database/plugin/register.go +0 -118
  102. package/database/pparams.go +0 -145
  103. package/database/tip.go +0 -45
  104. package/database/txn.go +0 -147
  105. package/database/types/types.go +0 -74
  106. package/database/types/types_test.go +0 -83
  107. package/database/utxo.go +0 -263
  108. package/dist/artifacts.json +0 -1
  109. package/dist/checksums.txt +0 -22
  110. package/dist/config.yaml +0 -253
  111. package/dist/dingo-0.5.0-SNAPSHOT-d9431e4.tar.gz +0 -0
  112. package/dist/dingo-0.5.0-SNAPSHOT-d9431e4.tar.gz.sbom.json +0 -1
  113. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_darwin_arm64.tar.gz +0 -0
  114. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_darwin_arm64.tar.gz.sbom.json +0 -1
  115. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_darwin_x86_64.tar.gz +0 -0
  116. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_darwin_x86_64.tar.gz.sbom.json +0 -1
  117. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.apk +0 -0
  118. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.apk.sbom.json +0 -1
  119. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.deb +0 -0
  120. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.deb.sbom.json +0 -1
  121. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.rpm +0 -0
  122. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.rpm.sbom.json +0 -1
  123. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.apk +0 -0
  124. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.apk.sbom.json +0 -1
  125. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.deb +0 -0
  126. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.deb.sbom.json +0 -1
  127. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.rpm +0 -0
  128. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.rpm.sbom.json +0 -1
  129. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.tar.gz +0 -0
  130. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.tar.gz.sbom.json +0 -1
  131. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_x86_64.tar.gz +0 -0
  132. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_x86_64.tar.gz.sbom.json +0 -1
  133. package/dist/dingo_darwin_amd64_v1/dingo +0 -0
  134. package/dist/dingo_darwin_arm64_v8.0/dingo +0 -0
  135. package/dist/dingo_linux_amd64_v1/dingo +0 -0
  136. package/dist/dingo_linux_arm64_v8.0/dingo +0 -0
  137. package/dist/homebrew/dingo.rb +0 -51
  138. package/dist/metadata.json +0 -1
  139. package/event/event.go +0 -141
  140. package/event/event_test.go +0 -115
  141. package/event/metrics.go +0 -44
  142. package/go.mod +0 -98
  143. package/go.sum +0 -358
  144. package/internal/config/config.go +0 -145
  145. package/internal/config/config_test.go +0 -118
  146. package/internal/node/load.go +0 -149
  147. package/internal/node/node.go +0 -176
  148. package/internal/version/version.go +0 -33
  149. package/ledger/certs.go +0 -164
  150. package/ledger/chainsync.go +0 -504
  151. package/ledger/delta.go +0 -99
  152. package/ledger/eras/allegra.go +0 -154
  153. package/ledger/eras/alonzo.go +0 -156
  154. package/ledger/eras/babbage.go +0 -154
  155. package/ledger/eras/byron.go +0 -42
  156. package/ledger/eras/conway.go +0 -166
  157. package/ledger/eras/eras.go +0 -44
  158. package/ledger/eras/mary.go +0 -154
  159. package/ledger/eras/shelley.go +0 -164
  160. package/ledger/error.go +0 -19
  161. package/ledger/event.go +0 -50
  162. package/ledger/metrics.go +0 -53
  163. package/ledger/queries.go +0 -258
  164. package/ledger/slot.go +0 -127
  165. package/ledger/slot_test.go +0 -147
  166. package/ledger/state.go +0 -821
  167. package/ledger/view.go +0 -73
  168. package/localstatequery.go +0 -50
  169. package/localtxmonitor.go +0 -44
  170. package/localtxsubmission.go +0 -52
  171. package/mempool/consumer.go +0 -98
  172. package/mempool/mempool.go +0 -322
  173. package/node.go +0 -320
  174. package/peergov/event.go +0 -27
  175. package/peergov/peer.go +0 -67
  176. package/peergov/peergov.go +0 -290
  177. package/peersharing.go +0 -70
  178. package/preview-local-topology.json +0 -23
  179. package/topology/topology.go +0 -69
  180. package/topology/topology_test.go +0 -179
  181. package/tracing.go +0 -65
  182. package/txsubmission.go +0 -233
  183. package/utxorpc/query.go +0 -311
  184. package/utxorpc/submit.go +0 -395
  185. package/utxorpc/sync.go +0 -276
  186. package/utxorpc/utxorpc.go +0 -166
  187. package/utxorpc/watch.go +0 -310
package/chain/chain.go DELETED
@@ -1,504 +0,0 @@
1
- // Copyright 2025 Blink Labs Software
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
14
-
15
- package chain
16
-
17
- import (
18
- "encoding/hex"
19
- "errors"
20
- "fmt"
21
- "slices"
22
- "sync"
23
-
24
- "github.com/blinklabs-io/dingo/database"
25
- "github.com/blinklabs-io/dingo/event"
26
- "github.com/blinklabs-io/gouroboros/ledger"
27
- ochainsync "github.com/blinklabs-io/gouroboros/protocol/chainsync"
28
- ocommon "github.com/blinklabs-io/gouroboros/protocol/common"
29
- )
30
-
31
- const (
32
- initialBlockIndex uint64 = 1
33
- )
34
-
35
- type Chain struct {
36
- mutex sync.RWMutex
37
- db *database.Database
38
- eventBus *event.EventBus
39
- currentTip ochainsync.Tip
40
- tipBlockIndex uint64
41
- persistent bool
42
- lastDbSlot uint64
43
- lastDbBlockIndex uint64
44
- blocks []database.Block
45
- headers []ledger.BlockHeader
46
- waitingChan chan struct{}
47
- waitingChanMutex sync.Mutex
48
- iterators []*ChainIterator
49
- }
50
-
51
- func NewChain(
52
- db *database.Database,
53
- eventBus *event.EventBus,
54
- persistent bool,
55
- ) (*Chain, error) {
56
- c := &Chain{
57
- db: db,
58
- eventBus: eventBus,
59
- persistent: persistent,
60
- }
61
- if persistent && db == nil {
62
- return nil, errors.New("persistence enabled but no database provided")
63
- }
64
- if db != nil {
65
- if err := c.load(); err != nil {
66
- return nil, fmt.Errorf("failed to load chain: %w", err)
67
- }
68
- // Set last block index and slot from database
69
- c.lastDbBlockIndex = c.tipBlockIndex
70
- c.lastDbSlot = c.currentTip.Point.Slot
71
- }
72
- return c, nil
73
- }
74
-
75
- func (c *Chain) load() error {
76
- recentBlocks, err := database.BlocksRecent(c.db, 1)
77
- if err != nil {
78
- return err
79
- }
80
- if len(recentBlocks) > 0 {
81
- c.currentTip = ochainsync.Tip{
82
- Point: ocommon.Point{
83
- Slot: recentBlocks[0].Slot,
84
- Hash: recentBlocks[0].Hash,
85
- },
86
- BlockNumber: recentBlocks[0].Number,
87
- }
88
- c.tipBlockIndex = recentBlocks[0].ID
89
- }
90
- return nil
91
- }
92
-
93
- func (c *Chain) Tip() ochainsync.Tip {
94
- c.mutex.RLock()
95
- defer c.mutex.RUnlock()
96
- return c.currentTip
97
- }
98
-
99
- func (c *Chain) HeaderTip() ochainsync.Tip {
100
- c.mutex.RLock()
101
- defer c.mutex.RUnlock()
102
- return c.headerTip()
103
- }
104
-
105
- func (c *Chain) headerTip() ochainsync.Tip {
106
- if len(c.headers) == 0 {
107
- return c.currentTip
108
- }
109
- lastHeader := c.headers[len(c.headers)-1]
110
- return ochainsync.Tip{
111
- Point: ocommon.Point{
112
- Slot: lastHeader.SlotNumber(),
113
- Hash: lastHeader.Hash().Bytes(),
114
- },
115
- BlockNumber: lastHeader.BlockNumber(),
116
- }
117
- }
118
-
119
- func (c *Chain) AddBlockHeader(header ledger.BlockHeader) error {
120
- c.mutex.Lock()
121
- defer c.mutex.Unlock()
122
- // Make sure header fits on chain tip
123
- if c.tipBlockIndex >= initialBlockIndex ||
124
- len(c.headers) > 0 {
125
- headerTip := c.headerTip()
126
- if string(header.PrevHash().Bytes()) != string(headerTip.Point.Hash) {
127
- return NewBlockNotFitChainTipError(
128
- header.Hash().String(),
129
- header.PrevHash().String(),
130
- hex.EncodeToString(headerTip.Point.Hash),
131
- )
132
- }
133
- }
134
- // Add header
135
- c.headers = append(c.headers, header)
136
- return nil
137
- }
138
-
139
- func (c *Chain) AddBlock(
140
- block ledger.Block,
141
- blockNonce []byte,
142
- txn *database.Txn,
143
- ) error {
144
- c.mutex.Lock()
145
- defer c.mutex.Unlock()
146
- // Check that the new block matches our first header, if any
147
- if len(c.headers) > 0 {
148
- firstHeader := c.headers[0]
149
- if block.Hash().String() != firstHeader.Hash().String() {
150
- return NewBlockNotMatchHeaderError(
151
- block.Hash().String(),
152
- firstHeader.Hash().String(),
153
- )
154
- }
155
- }
156
- // Check that this block fits on the current chain tip
157
- if c.tipBlockIndex >= initialBlockIndex {
158
- if string(block.PrevHash().Bytes()) != string(c.currentTip.Point.Hash) {
159
- return NewBlockNotFitChainTipError(
160
- block.Hash().String(),
161
- block.PrevHash().String(),
162
- hex.EncodeToString(c.currentTip.Point.Hash),
163
- )
164
- }
165
- }
166
- // Build new block record
167
- tmpPoint := ocommon.NewPoint(
168
- block.SlotNumber(),
169
- block.Hash().Bytes(),
170
- )
171
- newBlockIndex := c.tipBlockIndex + 1
172
- tmpBlock := database.Block{
173
- ID: newBlockIndex,
174
- Slot: tmpPoint.Slot,
175
- Hash: tmpPoint.Hash,
176
- Number: block.BlockNumber(),
177
- Type: uint(block.Type()), //nolint:gosec
178
- PrevHash: block.PrevHash().Bytes(),
179
- Nonce: blockNonce,
180
- Cbor: block.Cbor(),
181
- }
182
- if c.persistent {
183
- // Add block to database
184
- if err := c.db.BlockCreate(tmpBlock, txn); err != nil {
185
- return err
186
- }
187
- c.lastDbBlockIndex = newBlockIndex
188
- c.lastDbSlot = tmpPoint.Slot
189
- } else {
190
- // Add block to memory buffer
191
- c.blocks = append(
192
- c.blocks,
193
- tmpBlock,
194
- )
195
- }
196
- // Remove matching header entry, if any
197
- if len(c.headers) > 0 {
198
- c.headers = slices.Delete(c.headers, 0, 1)
199
- }
200
- // Update tip
201
- c.currentTip = ochainsync.Tip{
202
- Point: tmpPoint,
203
- BlockNumber: block.BlockNumber(),
204
- }
205
- c.tipBlockIndex = newBlockIndex
206
- // Notify waiting iterators
207
- if c.waitingChan != nil {
208
- close(c.waitingChan)
209
- c.waitingChan = nil
210
- }
211
- // Generate event
212
- if c.eventBus != nil {
213
- c.eventBus.Publish(
214
- ChainUpdateEventType,
215
- event.NewEvent(
216
- ChainUpdateEventType,
217
- ChainBlockEvent{
218
- Point: tmpPoint,
219
- Block: tmpBlock,
220
- },
221
- ),
222
- )
223
- }
224
- return nil
225
- }
226
-
227
- func (c *Chain) AddBlocks(blocks []ledger.Block) error {
228
- batchOffset := 0
229
- batchSize := 0
230
- for {
231
- batchSize = min(
232
- 50,
233
- len(blocks)-batchOffset,
234
- )
235
- if batchSize == 0 {
236
- break
237
- }
238
- txn := c.db.BlobTxn(true)
239
- err := txn.Do(func(txn *database.Txn) error {
240
- for _, tmpBlock := range blocks[batchOffset : batchOffset+batchSize] {
241
- if err := c.AddBlock(tmpBlock, nil, txn); err != nil {
242
- return err
243
- }
244
- }
245
- return nil
246
- })
247
- if err != nil {
248
- return err
249
- }
250
- batchOffset += batchSize
251
- }
252
- return nil
253
- }
254
-
255
- func (c *Chain) Rollback(point ocommon.Point) error {
256
- c.mutex.Lock()
257
- defer c.mutex.Unlock()
258
- // Check headers for rollback point
259
- if len(c.headers) > 0 {
260
- for idx, header := range c.headers {
261
- if header.SlotNumber() == point.Slot &&
262
- string(header.Hash().Bytes()) == string(point.Hash) {
263
- // Remove headers after rollback point
264
- if idx < len(c.headers)-1 {
265
- c.headers = slices.Delete(c.headers, idx+1, len(c.headers))
266
- }
267
- return nil
268
- }
269
- }
270
- }
271
- // Lookup block for rollback point
272
- var rollbackBlockIndex uint64
273
- var tmpBlock database.Block
274
- if point.Slot > 0 {
275
- var err error
276
- tmpBlock, err = c.BlockByPoint(point, nil)
277
- if err != nil {
278
- return err
279
- }
280
- rollbackBlockIndex = tmpBlock.ID
281
- }
282
- // Delete any rolled-back blocks
283
- for i := c.tipBlockIndex; i > rollbackBlockIndex; i-- {
284
- if c.persistent {
285
- // Remove from database
286
- txn := c.db.BlobTxn(true)
287
- err := txn.Do(func(txn *database.Txn) error {
288
- tmpBlock, err := c.db.BlockByIndex(i, txn)
289
- if err != nil {
290
- return err
291
- }
292
- if err := database.BlockDeleteTxn(txn, tmpBlock); err != nil {
293
- return err
294
- }
295
- return nil
296
- })
297
- if err != nil {
298
- return err
299
- }
300
- } else {
301
- // Return an error if we try to rollback beyond memory buffer
302
- if i <= c.lastDbBlockIndex {
303
- return ErrRollbackBeyondEphemeralChain
304
- }
305
- // Remove from memory buffer
306
- memBlockIndex := int(i - c.lastDbBlockIndex - initialBlockIndex) //nolint:gosec
307
- c.blocks = slices.Delete(
308
- c.blocks,
309
- memBlockIndex,
310
- memBlockIndex+1,
311
- )
312
- }
313
- }
314
- // Clear out any headers
315
- c.headers = slices.Delete(c.headers, 0, len(c.headers))
316
- // Update tip
317
- c.currentTip = ochainsync.Tip{
318
- Point: point,
319
- BlockNumber: tmpBlock.Number,
320
- }
321
- c.tipBlockIndex = rollbackBlockIndex
322
- // Update iterators for rollback
323
- for _, iter := range c.iterators {
324
- if iter.lastPoint.Slot > point.Slot {
325
- // Don't update rollback point if the iterator already has an older one pending
326
- if iter.needsRollback && point.Slot > iter.rollbackPoint.Slot {
327
- continue
328
- }
329
- iter.rollbackPoint = point
330
- iter.needsRollback = true
331
- }
332
- }
333
- // Generate event
334
- if c.eventBus != nil {
335
- c.eventBus.Publish(
336
- ChainUpdateEventType,
337
- event.NewEvent(
338
- ChainUpdateEventType,
339
- ChainRollbackEvent{
340
- Point: point,
341
- },
342
- ),
343
- )
344
- }
345
- return nil
346
- }
347
-
348
- func (c *Chain) HeaderCount() int {
349
- c.mutex.RLock()
350
- defer c.mutex.RUnlock()
351
- return len(c.headers)
352
- }
353
-
354
- func (c *Chain) HeaderRange(count int) (ocommon.Point, ocommon.Point) {
355
- c.mutex.RLock()
356
- defer c.mutex.RUnlock()
357
- var startPoint, endPoint ocommon.Point
358
- if len(c.headers) > 0 {
359
- firstHeader := c.headers[0]
360
- startPoint = ocommon.Point{
361
- Slot: firstHeader.SlotNumber(),
362
- Hash: firstHeader.Hash().Bytes(),
363
- }
364
- lastHeaderIdx := min(count, len(c.headers)) - 1
365
- lastHeader := c.headers[lastHeaderIdx]
366
- endPoint = ocommon.Point{
367
- Slot: lastHeader.SlotNumber(),
368
- Hash: lastHeader.Hash().Bytes(),
369
- }
370
- }
371
- return startPoint, endPoint
372
- }
373
-
374
- // FromPoint returns a ChainIterator starting at the specified point. If inclusive is true, the iterator
375
- // will start at the specified point. Otherwise it will start at the point following the specified point
376
- func (c *Chain) FromPoint(
377
- point ocommon.Point,
378
- inclusive bool,
379
- ) (*ChainIterator, error) {
380
- c.mutex.Lock()
381
- defer c.mutex.Unlock()
382
- iter, err := newChainIterator(
383
- c,
384
- point,
385
- inclusive,
386
- )
387
- if err != nil {
388
- return nil, err
389
- }
390
- c.iterators = append(c.iterators, iter)
391
- return iter, nil
392
- }
393
-
394
- func (c *Chain) BlockByPoint(
395
- point ocommon.Point,
396
- txn *database.Txn,
397
- ) (database.Block, error) {
398
- if point.Slot <= c.lastDbSlot {
399
- // Query database
400
- tmpBlock, err := database.BlockByPoint(c.db, point)
401
- if err != nil {
402
- if errors.Is(err, database.ErrBlockNotFound) {
403
- return database.Block{}, ErrBlockNotFound
404
- }
405
- return database.Block{}, err
406
- }
407
- return tmpBlock, nil
408
- }
409
- // Search memory buffer
410
- for _, block := range c.blocks {
411
- if point.Slot != block.Slot {
412
- continue
413
- }
414
- if string(point.Hash) != string(block.Hash) {
415
- continue
416
- }
417
- return block, nil
418
- }
419
- return database.Block{}, ErrBlockNotFound
420
- }
421
-
422
- func (c *Chain) blockByIndex(
423
- blockIndex uint64,
424
- txn *database.Txn,
425
- ) (database.Block, error) {
426
- if blockIndex <= c.lastDbBlockIndex {
427
- // Query database
428
- tmpBlock, err := c.db.BlockByIndex(blockIndex, txn)
429
- if err != nil {
430
- if errors.Is(err, database.ErrBlockNotFound) {
431
- return database.Block{}, ErrBlockNotFound
432
- }
433
- return database.Block{}, err
434
- }
435
- return tmpBlock, nil
436
- }
437
- // Get from memory buffer
438
- //nolint:gosec
439
- memBlockIndex := int(
440
- blockIndex - c.lastDbBlockIndex - initialBlockIndex,
441
- )
442
- if memBlockIndex < 0 || len(c.blocks) < memBlockIndex+1 {
443
- return database.Block{}, ErrBlockNotFound
444
- }
445
- return c.blocks[memBlockIndex], nil
446
- }
447
-
448
- func (c *Chain) iterNext(
449
- iter *ChainIterator,
450
- blocking bool,
451
- ) (*ChainIteratorResult, error) {
452
- c.mutex.RLock()
453
- // Check for pending rollback
454
- if iter.needsRollback {
455
- ret := &ChainIteratorResult{}
456
- ret.Point = iter.rollbackPoint
457
- ret.Rollback = true
458
- iter.lastPoint = iter.rollbackPoint
459
- iter.needsRollback = false
460
- if iter.rollbackPoint.Slot > 0 {
461
- // Lookup block index for rollback point
462
- tmpBlock, err := c.BlockByPoint(iter.rollbackPoint, nil)
463
- if err != nil {
464
- c.mutex.RUnlock()
465
- return nil, err
466
- }
467
- iter.nextBlockIndex = tmpBlock.ID + 1
468
- }
469
- c.mutex.RUnlock()
470
- return ret, nil
471
- }
472
- ret := &ChainIteratorResult{}
473
- // Lookup next block in metadata DB
474
- tmpBlock, err := c.blockByIndex(iter.nextBlockIndex, nil)
475
- // Return immedidately if a block is found
476
- if err == nil {
477
- ret.Point = ocommon.NewPoint(tmpBlock.Slot, tmpBlock.Hash)
478
- ret.Block = tmpBlock
479
- iter.nextBlockIndex++
480
- iter.lastPoint = ret.Point
481
- c.mutex.RUnlock()
482
- return ret, nil
483
- }
484
- // Return any actual error
485
- if !errors.Is(err, ErrBlockNotFound) {
486
- c.mutex.RUnlock()
487
- return ret, err
488
- }
489
- // Return immediately if we're not blocking
490
- if !blocking {
491
- c.mutex.RUnlock()
492
- return nil, ErrIteratorChainTip
493
- }
494
- c.mutex.RUnlock()
495
- // Wait for chain update
496
- c.waitingChanMutex.Lock()
497
- if c.waitingChan == nil {
498
- c.waitingChan = make(chan struct{})
499
- }
500
- c.waitingChanMutex.Unlock()
501
- <-c.waitingChan
502
- // Call ourselves again now that we should have new data
503
- return c.iterNext(iter, blocking)
504
- }