@blinklabs/dingo 0.6.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 (188) 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/{dist/dingo_darwin_amd64_v1/dingo → dingo} +0 -0
  11. package/dingo.yaml.example +53 -0
  12. package/package.json +5 -5
  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 -138
  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 -27
  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 -224
  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/epoch.go +0 -120
  78. package/database/plugin/metadata/sqlite/models/account.go +0 -81
  79. package/database/plugin/metadata/sqlite/models/auth_committee_hot.go +0 -26
  80. package/database/plugin/metadata/sqlite/models/deregistration_drep.go +0 -26
  81. package/database/plugin/metadata/sqlite/models/drep.go +0 -27
  82. package/database/plugin/metadata/sqlite/models/epoch.go +0 -31
  83. package/database/plugin/metadata/sqlite/models/models.go +0 -45
  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/registration_drep.go +0 -28
  88. package/database/plugin/metadata/sqlite/models/resign_committee_cold.go +0 -27
  89. package/database/plugin/metadata/sqlite/models/stake_registration_delegation.go +0 -27
  90. package/database/plugin/metadata/sqlite/models/stake_vote_delegation.go +0 -27
  91. package/database/plugin/metadata/sqlite/models/stake_vote_registration_delegation.go +0 -27
  92. package/database/plugin/metadata/sqlite/models/tip.go +0 -26
  93. package/database/plugin/metadata/sqlite/models/update_drep.go +0 -27
  94. package/database/plugin/metadata/sqlite/models/utxo.go +0 -30
  95. package/database/plugin/metadata/sqlite/models/vote_delegation.go +0 -26
  96. package/database/plugin/metadata/sqlite/models/vote_registration_delegation.go +0 -26
  97. package/database/plugin/metadata/sqlite/pool.go +0 -240
  98. package/database/plugin/metadata/sqlite/pparams.go +0 -110
  99. package/database/plugin/metadata/sqlite/tip.go +0 -83
  100. package/database/plugin/metadata/sqlite/utxo.go +0 -292
  101. package/database/plugin/metadata/store.go +0 -168
  102. package/database/plugin/option.go +0 -190
  103. package/database/plugin/plugin.go +0 -20
  104. package/database/plugin/register.go +0 -118
  105. package/database/pparams.go +0 -145
  106. package/database/tip.go +0 -45
  107. package/database/txn.go +0 -147
  108. package/database/types/types.go +0 -74
  109. package/database/types/types_test.go +0 -83
  110. package/database/utxo.go +0 -263
  111. package/dist/artifacts.json +0 -1
  112. package/dist/checksums.txt +0 -22
  113. package/dist/config.yaml +0 -253
  114. package/dist/dingo-0.5.0-SNAPSHOT-d9431e4.tar.gz +0 -0
  115. package/dist/dingo-0.5.0-SNAPSHOT-d9431e4.tar.gz.sbom.json +0 -1
  116. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_darwin_arm64.tar.gz +0 -0
  117. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_darwin_arm64.tar.gz.sbom.json +0 -1
  118. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_darwin_x86_64.tar.gz +0 -0
  119. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_darwin_x86_64.tar.gz.sbom.json +0 -1
  120. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.apk +0 -0
  121. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.apk.sbom.json +0 -1
  122. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.deb +0 -0
  123. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.deb.sbom.json +0 -1
  124. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.rpm +0 -0
  125. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.rpm.sbom.json +0 -1
  126. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.apk +0 -0
  127. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.apk.sbom.json +0 -1
  128. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.deb +0 -0
  129. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.deb.sbom.json +0 -1
  130. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.rpm +0 -0
  131. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.rpm.sbom.json +0 -1
  132. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.tar.gz +0 -0
  133. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.tar.gz.sbom.json +0 -1
  134. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_x86_64.tar.gz +0 -0
  135. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_x86_64.tar.gz.sbom.json +0 -1
  136. package/dist/dingo_darwin_arm64_v8.0/dingo +0 -0
  137. package/dist/dingo_linux_amd64_v1/dingo +0 -0
  138. package/dist/dingo_linux_arm64_v8.0/dingo +0 -0
  139. package/dist/homebrew/dingo.rb +0 -51
  140. package/dist/metadata.json +0 -1
  141. package/event/event.go +0 -141
  142. package/event/event_test.go +0 -115
  143. package/event/metrics.go +0 -44
  144. package/go.mod +0 -98
  145. package/go.sum +0 -358
  146. package/internal/config/config.go +0 -145
  147. package/internal/config/config_test.go +0 -118
  148. package/internal/node/load.go +0 -149
  149. package/internal/node/node.go +0 -176
  150. package/internal/version/version.go +0 -33
  151. package/ledger/certs.go +0 -113
  152. package/ledger/chainsync.go +0 -578
  153. package/ledger/eras/allegra.go +0 -154
  154. package/ledger/eras/alonzo.go +0 -156
  155. package/ledger/eras/babbage.go +0 -154
  156. package/ledger/eras/byron.go +0 -42
  157. package/ledger/eras/conway.go +0 -158
  158. package/ledger/eras/eras.go +0 -44
  159. package/ledger/eras/mary.go +0 -154
  160. package/ledger/eras/shelley.go +0 -164
  161. package/ledger/error.go +0 -19
  162. package/ledger/event.go +0 -50
  163. package/ledger/metrics.go +0 -53
  164. package/ledger/queries.go +0 -260
  165. package/ledger/slot.go +0 -127
  166. package/ledger/slot_test.go +0 -147
  167. package/ledger/state.go +0 -726
  168. package/ledger/view.go +0 -73
  169. package/localstatequery.go +0 -50
  170. package/localtxmonitor.go +0 -44
  171. package/localtxsubmission.go +0 -52
  172. package/mempool/consumer.go +0 -98
  173. package/mempool/mempool.go +0 -322
  174. package/node.go +0 -320
  175. package/peergov/event.go +0 -27
  176. package/peergov/peer.go +0 -67
  177. package/peergov/peergov.go +0 -290
  178. package/peersharing.go +0 -70
  179. package/preview-local-topology.json +0 -23
  180. package/topology/topology.go +0 -69
  181. package/topology/topology_test.go +0 -179
  182. package/tracing.go +0 -65
  183. package/txsubmission.go +0 -233
  184. package/utxorpc/query.go +0 -311
  185. package/utxorpc/submit.go +0 -395
  186. package/utxorpc/sync.go +0 -276
  187. package/utxorpc/utxorpc.go +0 -166
  188. 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
- }