@blinklabs/dingo 0.6.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 (195) hide show
  1. package/.dockerignore +5 -0
  2. package/.github/CODEOWNERS +5 -0
  3. package/.github/assets/dingo-ate-my-blockchain.png +0 -0
  4. package/.github/assets/dingo-illustration.png +0 -0
  5. package/.github/assets/dingo-logo-with-text-horizontal.png +0 -0
  6. package/.github/assets/dingo-logo-with-text.png +0 -0
  7. package/.github/dependabot.yml +19 -0
  8. package/.github/dingo-20241210.png +0 -0
  9. package/.github/dingo.md +56 -0
  10. package/.github/workflows/ci-docker.yml +36 -0
  11. package/.github/workflows/conventional-commits.yml +17 -0
  12. package/.github/workflows/go-test.yml +29 -0
  13. package/.github/workflows/golangci-lint.yml +23 -0
  14. package/.github/workflows/publish.yml +207 -0
  15. package/.golangci.yml +71 -0
  16. package/Dockerfile +25 -0
  17. package/LICENSE +201 -0
  18. package/Makefile +53 -0
  19. package/README.md +150 -0
  20. package/blockfetch.go +144 -0
  21. package/chain/chain.go +504 -0
  22. package/chain/chain_test.go +468 -0
  23. package/chain/errors.go +80 -0
  24. package/chain/event.go +33 -0
  25. package/chain/iter.go +64 -0
  26. package/chainsync/chainsync.go +97 -0
  27. package/chainsync.go +223 -0
  28. package/cmd/dingo/load.go +52 -0
  29. package/cmd/dingo/main.go +118 -0
  30. package/cmd/dingo/serve.go +49 -0
  31. package/config/cardano/node.go +192 -0
  32. package/config/cardano/node_test.go +85 -0
  33. package/config/cardano/preview/README.md +4 -0
  34. package/config/cardano/preview/alonzo-genesis.json +196 -0
  35. package/config/cardano/preview/byron-genesis.json +117 -0
  36. package/config/cardano/preview/config.json +114 -0
  37. package/config/cardano/preview/conway-genesis.json +297 -0
  38. package/config/cardano/preview/shelley-genesis.json +68 -0
  39. package/config.go +245 -0
  40. package/connmanager/connection_manager.go +105 -0
  41. package/connmanager/connection_manager_test.go +185 -0
  42. package/connmanager/event.go +37 -0
  43. package/connmanager/listener.go +140 -0
  44. package/connmanager/outbound.go +93 -0
  45. package/connmanager/socket.go +55 -0
  46. package/connmanager/unix.go +78 -0
  47. package/custom-p2p-topology.json +24 -0
  48. package/custom-p2p-topology.json.backup +24 -0
  49. package/custom-p2p-topology.json.mainnet +37 -0
  50. package/database/account.go +138 -0
  51. package/database/block.go +362 -0
  52. package/database/certs.go +53 -0
  53. package/database/commit_timestamp.go +77 -0
  54. package/database/database.go +118 -0
  55. package/database/database_test.go +62 -0
  56. package/database/drep.go +27 -0
  57. package/database/epoch.go +121 -0
  58. package/database/immutable/chunk.go +182 -0
  59. package/database/immutable/immutable.go +350 -0
  60. package/database/immutable/immutable_test.go +59 -0
  61. package/database/immutable/primary.go +106 -0
  62. package/database/immutable/secondary.go +103 -0
  63. package/database/immutable/testdata/08893.chunk +0 -0
  64. package/database/immutable/testdata/08893.primary +0 -0
  65. package/database/immutable/testdata/08893.secondary +0 -0
  66. package/database/immutable/testdata/08894.chunk +0 -0
  67. package/database/immutable/testdata/08894.primary +0 -0
  68. package/database/immutable/testdata/08894.secondary +0 -0
  69. package/database/immutable/testdata/README.md +4 -0
  70. package/database/plugin/blob/badger/commit_timestamp.go +50 -0
  71. package/database/plugin/blob/badger/database.go +152 -0
  72. package/database/plugin/blob/badger/logger.go +63 -0
  73. package/database/plugin/blob/badger/metrics.go +98 -0
  74. package/database/plugin/blob/blob.go +19 -0
  75. package/database/plugin/blob/store.go +40 -0
  76. package/database/plugin/log.go +27 -0
  77. package/database/plugin/metadata/metadata.go +19 -0
  78. package/database/plugin/metadata/sqlite/account.go +224 -0
  79. package/database/plugin/metadata/sqlite/certs.go +58 -0
  80. package/database/plugin/metadata/sqlite/commit_timestamp.go +68 -0
  81. package/database/plugin/metadata/sqlite/database.go +218 -0
  82. package/database/plugin/metadata/sqlite/epoch.go +120 -0
  83. package/database/plugin/metadata/sqlite/models/account.go +81 -0
  84. package/database/plugin/metadata/sqlite/models/auth_committee_hot.go +26 -0
  85. package/database/plugin/metadata/sqlite/models/deregistration_drep.go +26 -0
  86. package/database/plugin/metadata/sqlite/models/drep.go +27 -0
  87. package/database/plugin/metadata/sqlite/models/epoch.go +31 -0
  88. package/database/plugin/metadata/sqlite/models/models.go +45 -0
  89. package/database/plugin/metadata/sqlite/models/pool.go +97 -0
  90. package/database/plugin/metadata/sqlite/models/pparam_update.go +27 -0
  91. package/database/plugin/metadata/sqlite/models/pparams.go +27 -0
  92. package/database/plugin/metadata/sqlite/models/registration_drep.go +28 -0
  93. package/database/plugin/metadata/sqlite/models/resign_committee_cold.go +27 -0
  94. package/database/plugin/metadata/sqlite/models/stake_registration_delegation.go +27 -0
  95. package/database/plugin/metadata/sqlite/models/stake_vote_delegation.go +27 -0
  96. package/database/plugin/metadata/sqlite/models/stake_vote_registration_delegation.go +27 -0
  97. package/database/plugin/metadata/sqlite/models/tip.go +26 -0
  98. package/database/plugin/metadata/sqlite/models/update_drep.go +27 -0
  99. package/database/plugin/metadata/sqlite/models/utxo.go +30 -0
  100. package/database/plugin/metadata/sqlite/models/vote_delegation.go +26 -0
  101. package/database/plugin/metadata/sqlite/models/vote_registration_delegation.go +26 -0
  102. package/database/plugin/metadata/sqlite/pool.go +240 -0
  103. package/database/plugin/metadata/sqlite/pparams.go +110 -0
  104. package/database/plugin/metadata/sqlite/tip.go +83 -0
  105. package/database/plugin/metadata/sqlite/utxo.go +292 -0
  106. package/database/plugin/metadata/store.go +168 -0
  107. package/database/plugin/option.go +190 -0
  108. package/database/plugin/plugin.go +20 -0
  109. package/database/plugin/register.go +118 -0
  110. package/database/pparams.go +145 -0
  111. package/database/tip.go +45 -0
  112. package/database/txn.go +147 -0
  113. package/database/types/types.go +74 -0
  114. package/database/types/types_test.go +83 -0
  115. package/database/utxo.go +263 -0
  116. package/dist/artifacts.json +1 -0
  117. package/dist/checksums.txt +22 -0
  118. package/dist/config.yaml +253 -0
  119. package/dist/dingo-0.5.0-SNAPSHOT-d9431e4.tar.gz +0 -0
  120. package/dist/dingo-0.5.0-SNAPSHOT-d9431e4.tar.gz.sbom.json +1 -0
  121. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_darwin_arm64.tar.gz +0 -0
  122. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_darwin_arm64.tar.gz.sbom.json +1 -0
  123. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_darwin_x86_64.tar.gz +0 -0
  124. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_darwin_x86_64.tar.gz.sbom.json +1 -0
  125. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.apk +0 -0
  126. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.apk.sbom.json +1 -0
  127. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.deb +0 -0
  128. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.deb.sbom.json +1 -0
  129. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.rpm +0 -0
  130. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_amd64.rpm.sbom.json +1 -0
  131. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.apk +0 -0
  132. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.apk.sbom.json +1 -0
  133. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.deb +0 -0
  134. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.deb.sbom.json +1 -0
  135. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.rpm +0 -0
  136. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.rpm.sbom.json +1 -0
  137. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.tar.gz +0 -0
  138. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_arm64.tar.gz.sbom.json +1 -0
  139. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_x86_64.tar.gz +0 -0
  140. package/dist/dingo_0.5.0-SNAPSHOT-d9431e4_linux_x86_64.tar.gz.sbom.json +1 -0
  141. package/dist/dingo_darwin_amd64_v1/dingo +0 -0
  142. package/dist/dingo_darwin_arm64_v8.0/dingo +0 -0
  143. package/dist/dingo_linux_amd64_v1/dingo +0 -0
  144. package/dist/dingo_linux_arm64_v8.0/dingo +0 -0
  145. package/dist/homebrew/dingo.rb +51 -0
  146. package/dist/metadata.json +1 -0
  147. package/event/event.go +141 -0
  148. package/event/event_test.go +115 -0
  149. package/event/metrics.go +44 -0
  150. package/go.mod +98 -0
  151. package/go.sum +358 -0
  152. package/internal/config/config.go +145 -0
  153. package/internal/config/config_test.go +118 -0
  154. package/internal/node/load.go +149 -0
  155. package/internal/node/node.go +176 -0
  156. package/internal/version/version.go +33 -0
  157. package/ledger/certs.go +113 -0
  158. package/ledger/chainsync.go +578 -0
  159. package/ledger/eras/allegra.go +154 -0
  160. package/ledger/eras/alonzo.go +156 -0
  161. package/ledger/eras/babbage.go +154 -0
  162. package/ledger/eras/byron.go +42 -0
  163. package/ledger/eras/conway.go +158 -0
  164. package/ledger/eras/eras.go +44 -0
  165. package/ledger/eras/mary.go +154 -0
  166. package/ledger/eras/shelley.go +164 -0
  167. package/ledger/error.go +19 -0
  168. package/ledger/event.go +50 -0
  169. package/ledger/metrics.go +53 -0
  170. package/ledger/queries.go +260 -0
  171. package/ledger/slot.go +127 -0
  172. package/ledger/slot_test.go +147 -0
  173. package/ledger/state.go +726 -0
  174. package/ledger/view.go +73 -0
  175. package/localstatequery.go +50 -0
  176. package/localtxmonitor.go +44 -0
  177. package/localtxsubmission.go +52 -0
  178. package/mempool/consumer.go +98 -0
  179. package/mempool/mempool.go +322 -0
  180. package/node.go +320 -0
  181. package/package.json +33 -0
  182. package/peergov/event.go +27 -0
  183. package/peergov/peer.go +67 -0
  184. package/peergov/peergov.go +290 -0
  185. package/peersharing.go +70 -0
  186. package/preview-local-topology.json +23 -0
  187. package/topology/topology.go +69 -0
  188. package/topology/topology_test.go +179 -0
  189. package/tracing.go +65 -0
  190. package/txsubmission.go +233 -0
  191. package/utxorpc/query.go +311 -0
  192. package/utxorpc/submit.go +395 -0
  193. package/utxorpc/sync.go +276 -0
  194. package/utxorpc/utxorpc.go +166 -0
  195. package/utxorpc/watch.go +310 -0
@@ -0,0 +1,290 @@
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 peergov
16
+
17
+ import (
18
+ "fmt"
19
+ "io"
20
+ "log/slog"
21
+ "net"
22
+ "strconv"
23
+ "sync"
24
+ "time"
25
+
26
+ "github.com/blinklabs-io/dingo/connmanager"
27
+ "github.com/blinklabs-io/dingo/event"
28
+ "github.com/blinklabs-io/dingo/topology"
29
+ ouroboros "github.com/blinklabs-io/gouroboros"
30
+ )
31
+
32
+ const (
33
+ initialReconnectDelay = 1 * time.Second
34
+ maxReconnectDelay = 128 * time.Second
35
+ reconnectBackoffFactor = 2
36
+ )
37
+
38
+ type PeerGovernor struct {
39
+ mu sync.Mutex
40
+ config PeerGovernorConfig
41
+ peers []*Peer
42
+ }
43
+
44
+ type PeerGovernorConfig struct {
45
+ Logger *slog.Logger
46
+ EventBus *event.EventBus
47
+ ConnManager *connmanager.ConnectionManager
48
+ }
49
+
50
+ func NewPeerGovernor(cfg PeerGovernorConfig) *PeerGovernor {
51
+ if cfg.Logger == nil {
52
+ cfg.Logger = slog.New(slog.NewJSONHandler(io.Discard, nil))
53
+ }
54
+ cfg.Logger = cfg.Logger.With("component", "peergov")
55
+ return &PeerGovernor{
56
+ config: cfg,
57
+ }
58
+ }
59
+
60
+ func (p *PeerGovernor) Start() error {
61
+ // Setup connmanager event listeners
62
+ p.config.EventBus.SubscribeFunc(
63
+ connmanager.InboundConnectionEventType,
64
+ p.handleInboundConnectionEvent,
65
+ )
66
+ p.config.EventBus.SubscribeFunc(
67
+ connmanager.ConnectionClosedEventType,
68
+ p.handleConnectionClosedEvent,
69
+ )
70
+ // Start outbound connections
71
+ p.startOutboundConnections()
72
+ return nil
73
+ }
74
+
75
+ func (p *PeerGovernor) LoadTopologyConfig(
76
+ topologyConfig *topology.TopologyConfig,
77
+ ) {
78
+ p.mu.Lock()
79
+ defer p.mu.Unlock()
80
+ // Remove peers originally sourced from the topology
81
+ tmpPeers := []*Peer{}
82
+ for _, tmpPeer := range p.peers {
83
+ if tmpPeer.Source == PeerSourceTopologyBootstrapPeer ||
84
+ tmpPeer.Source == PeerSourceTopologyLocalRoot ||
85
+ tmpPeer.Source == PeerSourceTopologyPublicRoot {
86
+ continue
87
+ }
88
+ tmpPeers = append(tmpPeers, tmpPeer)
89
+ }
90
+ p.peers = tmpPeers
91
+ // Add topology bootstrap peers
92
+ for _, bootstrapPeer := range topologyConfig.BootstrapPeers {
93
+ tmpAddress := net.JoinHostPort(
94
+ bootstrapPeer.Address,
95
+ strconv.FormatUint(uint64(bootstrapPeer.Port), 10),
96
+ )
97
+ p.peers = append(
98
+ p.peers,
99
+ &Peer{
100
+ Address: tmpAddress,
101
+ Source: PeerSourceTopologyBootstrapPeer,
102
+ },
103
+ )
104
+ }
105
+ // Add topology local roots
106
+ for _, localRoot := range topologyConfig.LocalRoots {
107
+ for _, ap := range localRoot.AccessPoints {
108
+ tmpAddress := net.JoinHostPort(
109
+ ap.Address,
110
+ strconv.FormatUint(uint64(ap.Port), 10),
111
+ )
112
+ tmpPeer := &Peer{
113
+ Address: tmpAddress,
114
+ Source: PeerSourceTopologyLocalRoot,
115
+ Sharable: localRoot.Advertise,
116
+ }
117
+ for i, peer := range p.peers {
118
+ // This peer already appears, remove it
119
+ if peer.Address == tmpAddress {
120
+ copy(p.peers[i:], p.peers[i+1:]) // shift left
121
+ p.peers[len(p.peers)-1] = nil // clear last
122
+ p.peers = p.peers[:len(p.peers)-1] // truncate
123
+ }
124
+ }
125
+ p.peers = append(p.peers, tmpPeer)
126
+ }
127
+ }
128
+ // Add topology public roots
129
+ for _, publicRoot := range topologyConfig.PublicRoots {
130
+ for _, ap := range publicRoot.AccessPoints {
131
+ tmpAddress := net.JoinHostPort(
132
+ ap.Address,
133
+ strconv.FormatUint(uint64(ap.Port), 10),
134
+ )
135
+ tmpPeer := &Peer{
136
+ Address: tmpAddress,
137
+ Source: PeerSourceTopologyPublicRoot,
138
+ Sharable: publicRoot.Advertise,
139
+ }
140
+ for i, peer := range p.peers {
141
+ // This peer already appears, remove it
142
+ if peer.Address == tmpAddress {
143
+ copy(p.peers[i:], p.peers[i+1:]) // shift left
144
+ p.peers[len(p.peers)-1] = nil // clear last
145
+ p.peers = p.peers[:len(p.peers)-1] // truncate
146
+ }
147
+ }
148
+ p.peers = append(p.peers, tmpPeer)
149
+ }
150
+ }
151
+ }
152
+
153
+ func (p *PeerGovernor) GetPeers() []Peer {
154
+ p.mu.Lock()
155
+ defer p.mu.Unlock()
156
+ ret := make([]Peer, len(p.peers))
157
+ for idx, peer := range p.peers {
158
+ ret[idx] = *peer
159
+ }
160
+ return ret
161
+ }
162
+
163
+ func (p *PeerGovernor) peerIndexByAddress(address string) int {
164
+ for idx, tmpPeer := range p.peers {
165
+ if tmpPeer.Address == address {
166
+ return idx
167
+ }
168
+ }
169
+ return -1
170
+ }
171
+
172
+ func (p *PeerGovernor) peerIndexByConnId(connId ouroboros.ConnectionId) int {
173
+ for idx, tmpPeer := range p.peers {
174
+ if tmpPeer.Connection == nil {
175
+ continue
176
+ }
177
+ if tmpPeer.Connection.Id == connId {
178
+ return idx
179
+ }
180
+ }
181
+ return -1
182
+ }
183
+
184
+ func (p *PeerGovernor) startOutboundConnections() {
185
+ p.config.Logger.Debug(
186
+ "starting connections",
187
+ "role", "client",
188
+ )
189
+ for _, tmpPeer := range p.peers {
190
+ go p.createOutboundConnection(tmpPeer)
191
+ }
192
+ }
193
+
194
+ func (p *PeerGovernor) createOutboundConnection(peer *Peer) {
195
+ for {
196
+ conn, err := p.config.ConnManager.CreateOutboundConn(peer.Address)
197
+ if err == nil {
198
+ connId := conn.Id()
199
+ peer.ReconnectCount = 0
200
+ peer.setConnection(conn, true)
201
+ // Generate event
202
+ if p.config.EventBus != nil {
203
+ p.config.EventBus.Publish(
204
+ OutboundConnectionEventType,
205
+ event.NewEvent(
206
+ OutboundConnectionEventType,
207
+ OutboundConnectionEvent{
208
+ ConnectionId: connId,
209
+ },
210
+ ),
211
+ )
212
+ }
213
+ return
214
+ }
215
+ p.config.Logger.Error(
216
+ fmt.Sprintf(
217
+ "outbound: failed to establish connection to %s: %s",
218
+ peer.Address,
219
+ err,
220
+ ),
221
+ )
222
+ if peer.ReconnectDelay == 0 {
223
+ peer.ReconnectDelay = initialReconnectDelay
224
+ } else if peer.ReconnectDelay < maxReconnectDelay {
225
+ peer.ReconnectDelay = peer.ReconnectDelay * reconnectBackoffFactor
226
+ }
227
+ peer.ReconnectCount += 1
228
+ p.config.Logger.Info(
229
+ fmt.Sprintf(
230
+ "outbound: delaying %s (retry %d) before reconnecting to %s",
231
+ peer.ReconnectDelay,
232
+ peer.ReconnectCount,
233
+ peer.Address,
234
+ ),
235
+ )
236
+ time.Sleep(peer.ReconnectDelay)
237
+ }
238
+ }
239
+
240
+ func (p *PeerGovernor) handleInboundConnectionEvent(evt event.Event) {
241
+ p.mu.Lock()
242
+ defer p.mu.Unlock()
243
+ e := evt.Data.(connmanager.InboundConnectionEvent)
244
+ var tmpPeer *Peer
245
+ peerIdx := p.peerIndexByAddress(e.RemoteAddr.String())
246
+ if peerIdx == -1 {
247
+ tmpPeer = &Peer{
248
+ Address: e.RemoteAddr.String(),
249
+ Source: PeerSourceInboundConn,
250
+ }
251
+ // Add inbound peer
252
+ p.peers = append(
253
+ p.peers,
254
+ tmpPeer,
255
+ )
256
+ } else {
257
+ tmpPeer = p.peers[peerIdx]
258
+ }
259
+ conn := p.config.ConnManager.GetConnectionById(e.ConnectionId)
260
+ tmpPeer.setConnection(conn, false)
261
+ if tmpPeer.Connection != nil {
262
+ tmpPeer.Sharable = tmpPeer.Connection.VersionData.PeerSharing()
263
+ }
264
+ }
265
+
266
+ func (p *PeerGovernor) handleConnectionClosedEvent(evt event.Event) {
267
+ p.mu.Lock()
268
+ defer p.mu.Unlock()
269
+ e := evt.Data.(connmanager.ConnectionClosedEvent)
270
+ if e.Error != nil {
271
+ p.config.Logger.Error(
272
+ fmt.Sprintf(
273
+ "unexpected connection failure: %s",
274
+ e.Error,
275
+ ),
276
+ "connection_id", e.ConnectionId.String(),
277
+ )
278
+ } else {
279
+ p.config.Logger.Info("connection closed",
280
+ "connection_id", e.ConnectionId.String(),
281
+ )
282
+ }
283
+ peerIdx := p.peerIndexByConnId(e.ConnectionId)
284
+ if peerIdx != -1 {
285
+ p.peers[peerIdx].Connection = nil
286
+ if p.peers[peerIdx].Source != PeerSourceInboundConn {
287
+ go p.createOutboundConnection(p.peers[peerIdx])
288
+ }
289
+ }
290
+ }
package/peersharing.go ADDED
@@ -0,0 +1,70 @@
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 dingo
16
+
17
+ import (
18
+ "net"
19
+ "strconv"
20
+
21
+ opeersharing "github.com/blinklabs-io/gouroboros/protocol/peersharing"
22
+ )
23
+
24
+ func (n *Node) peersharingServerConnOpts() []opeersharing.PeerSharingOptionFunc {
25
+ return []opeersharing.PeerSharingOptionFunc{
26
+ opeersharing.WithShareRequestFunc(n.peersharingShareRequest),
27
+ }
28
+ }
29
+
30
+ func (n *Node) peersharingClientConnOpts() []opeersharing.PeerSharingOptionFunc {
31
+ // We don't provide any client options, but we have this here for consistency
32
+ return []opeersharing.PeerSharingOptionFunc{}
33
+ }
34
+
35
+ func (n *Node) peersharingShareRequest(
36
+ ctx opeersharing.CallbackContext,
37
+ amount int,
38
+ ) ([]opeersharing.PeerAddress, error) {
39
+ peers := []opeersharing.PeerAddress{}
40
+ var cnt int
41
+ for _, peer := range n.peerGov.GetPeers() {
42
+ cnt++
43
+ if cnt > amount {
44
+ break
45
+ }
46
+ if peer.Sharable {
47
+ host, port, err := net.SplitHostPort(peer.Address)
48
+ if err != nil {
49
+ // Skip on error
50
+ n.config.logger.Debug("failed to split peer address, skipping")
51
+ continue
52
+ }
53
+ portNum, err := strconv.ParseUint(port, 10, 16)
54
+ if err != nil {
55
+ // Skip on error
56
+ n.config.logger.Debug("failed to parse peer port, skipping")
57
+ continue
58
+ }
59
+ n.config.logger.Debug(
60
+ "adding peer for sharing: " + peer.Address,
61
+ )
62
+ peers = append(peers, opeersharing.PeerAddress{
63
+ IP: net.ParseIP(host),
64
+ Port: uint16(portNum),
65
+ },
66
+ )
67
+ }
68
+ }
69
+ return peers, nil
70
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "bootstrapPeers": [
3
+ {
4
+ "address": "192.168.4.56",
5
+ "port": 3001
6
+ }
7
+ ],
8
+ "localRoots": [
9
+ {
10
+ "accessPoints": [],
11
+ "advertise": false,
12
+ "trustable": false,
13
+ "valency": 1
14
+ }
15
+ ],
16
+ "publicRoots": [
17
+ {
18
+ "accessPoints": [],
19
+ "advertise": false
20
+ }
21
+ ],
22
+ "useLedgerAfterSlot": 53827185
23
+ }
@@ -0,0 +1,69 @@
1
+ // Copyright 2024 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 topology
16
+
17
+ import (
18
+ "encoding/json"
19
+ "io"
20
+ "os"
21
+ )
22
+
23
+ // TopologyConfig represents a cardano-node topology config
24
+ type TopologyConfig struct {
25
+ LocalRoots []TopologyConfigP2PLocalRoot `json:"localRoots"`
26
+ PublicRoots []TopologyConfigP2PPublicRoot `json:"publicRoots"`
27
+ BootstrapPeers []TopologyConfigP2PBootstrapPeer `json:"bootstrapPeers"`
28
+ UseLedgerAfterSlot int64 `json:"useLedgerAfterSlot"`
29
+ }
30
+
31
+ type TopologyConfigP2PAccessPoint struct {
32
+ Address string `json:"address"`
33
+ Port uint `json:"port"`
34
+ }
35
+
36
+ type TopologyConfigP2PLocalRoot struct {
37
+ AccessPoints []TopologyConfigP2PAccessPoint `json:"accessPoints"`
38
+ Advertise bool `json:"advertise"`
39
+ Trustable bool `json:"trustable"`
40
+ Valency uint `json:"valency"`
41
+ }
42
+
43
+ type TopologyConfigP2PPublicRoot struct {
44
+ AccessPoints []TopologyConfigP2PAccessPoint `json:"accessPoints"`
45
+ Advertise bool `json:"advertise"`
46
+ Valency uint `json:"valency"`
47
+ }
48
+
49
+ type TopologyConfigP2PBootstrapPeer = TopologyConfigP2PAccessPoint
50
+
51
+ func NewTopologyConfigFromFile(path string) (*TopologyConfig, error) {
52
+ dataFile, err := os.Open(path)
53
+ if err != nil {
54
+ return nil, err
55
+ }
56
+ return NewTopologyConfigFromReader(dataFile)
57
+ }
58
+
59
+ func NewTopologyConfigFromReader(r io.Reader) (*TopologyConfig, error) {
60
+ t := &TopologyConfig{}
61
+ data, err := io.ReadAll(r)
62
+ if err != nil {
63
+ return nil, err
64
+ }
65
+ if err := json.Unmarshal(data, t); err != nil {
66
+ return nil, err
67
+ }
68
+ return t, nil
69
+ }
@@ -0,0 +1,179 @@
1
+ // Copyright 2024 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 topology_test
16
+
17
+ import (
18
+ "reflect"
19
+ "strings"
20
+ "testing"
21
+
22
+ "github.com/blinklabs-io/dingo/topology"
23
+ )
24
+
25
+ type topologyTestDefinition struct {
26
+ jsonData string
27
+ expectedObject *topology.TopologyConfig
28
+ }
29
+
30
+ var topologyTests = []topologyTestDefinition{
31
+ {
32
+ jsonData: `
33
+ {
34
+ "localRoots": [
35
+ {
36
+ "accessPoints": [],
37
+ "advertise": false,
38
+ "valency": 1
39
+ }
40
+ ],
41
+ "publicRoots": [
42
+ {
43
+ "accessPoints": [
44
+ {
45
+ "address": "backbone.cardano.iog.io",
46
+ "port": 3001
47
+ }
48
+ ],
49
+ "advertise": false
50
+ },
51
+ {
52
+ "accessPoints": [
53
+ {
54
+ "address": "backbone.mainnet.emurgornd.com",
55
+ "port": 3001
56
+ }
57
+ ],
58
+ "advertise": false
59
+ }
60
+ ],
61
+ "useLedgerAfterSlot": 99532743
62
+ }
63
+ `,
64
+ expectedObject: &topology.TopologyConfig{
65
+ LocalRoots: []topology.TopologyConfigP2PLocalRoot{
66
+ {
67
+ AccessPoints: []topology.TopologyConfigP2PAccessPoint{},
68
+ Advertise: false,
69
+ Valency: 1,
70
+ },
71
+ },
72
+ PublicRoots: []topology.TopologyConfigP2PPublicRoot{
73
+ {
74
+ AccessPoints: []topology.TopologyConfigP2PAccessPoint{
75
+ {
76
+ Address: "backbone.cardano.iog.io",
77
+ Port: 3001,
78
+ },
79
+ },
80
+ Advertise: false,
81
+ },
82
+ {
83
+ AccessPoints: []topology.TopologyConfigP2PAccessPoint{
84
+ {
85
+ Address: "backbone.mainnet.emurgornd.com",
86
+ Port: 3001,
87
+ },
88
+ },
89
+ Advertise: false,
90
+ },
91
+ },
92
+ UseLedgerAfterSlot: 99532743,
93
+ },
94
+ },
95
+ {
96
+ jsonData: `
97
+ {
98
+ "bootstrapPeers": [
99
+ {
100
+ "address": "backbone.cardano.iog.io",
101
+ "port": 3001
102
+ },
103
+ {
104
+ "address": "backbone.mainnet.emurgornd.com",
105
+ "port": 3001
106
+ },
107
+ {
108
+ "address": "backbone.mainnet.cardanofoundation.org",
109
+ "port": 3001
110
+ }
111
+ ],
112
+ "localRoots": [
113
+ {
114
+ "accessPoints": [],
115
+ "advertise": false,
116
+ "trustable": false,
117
+ "valency": 1
118
+ }
119
+ ],
120
+ "publicRoots": [
121
+ {
122
+ "accessPoints": [],
123
+ "advertise": false
124
+ }
125
+ ],
126
+ "useLedgerAfterSlot": 128908821
127
+ }
128
+ `,
129
+ expectedObject: &topology.TopologyConfig{
130
+ LocalRoots: []topology.TopologyConfigP2PLocalRoot{
131
+ {
132
+ AccessPoints: []topology.TopologyConfigP2PAccessPoint{},
133
+ Advertise: false,
134
+ Trustable: false,
135
+ Valency: 1,
136
+ },
137
+ },
138
+ PublicRoots: []topology.TopologyConfigP2PPublicRoot{
139
+ {
140
+ AccessPoints: []topology.TopologyConfigP2PAccessPoint{},
141
+ Advertise: false,
142
+ },
143
+ },
144
+ BootstrapPeers: []topology.TopologyConfigP2PBootstrapPeer{
145
+ {
146
+ Address: "backbone.cardano.iog.io",
147
+ Port: 3001,
148
+ },
149
+ {
150
+ Address: "backbone.mainnet.emurgornd.com",
151
+ Port: 3001,
152
+ },
153
+ {
154
+ Address: "backbone.mainnet.cardanofoundation.org",
155
+ Port: 3001,
156
+ },
157
+ },
158
+ UseLedgerAfterSlot: 128908821,
159
+ },
160
+ },
161
+ }
162
+
163
+ func TestParseTopologyConfig(t *testing.T) {
164
+ for _, test := range topologyTests {
165
+ topology, err := topology.NewTopologyConfigFromReader(
166
+ strings.NewReader(test.jsonData),
167
+ )
168
+ if err != nil {
169
+ t.Fatalf("failed to load TopologyConfig from JSON data: %s", err)
170
+ }
171
+ if !reflect.DeepEqual(topology, test.expectedObject) {
172
+ t.Fatalf(
173
+ "did not get expected object\n got:\n %#v\n wanted:\n %#v",
174
+ topology,
175
+ test.expectedObject,
176
+ )
177
+ }
178
+ }
179
+ }
package/tracing.go ADDED
@@ -0,0 +1,65 @@
1
+ // Copyright 2024 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 dingo
16
+
17
+ import (
18
+ "context"
19
+ "log/slog"
20
+
21
+ "go.opentelemetry.io/otel"
22
+ "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
23
+ "go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
24
+ "go.opentelemetry.io/otel/propagation"
25
+ "go.opentelemetry.io/otel/sdk/trace"
26
+ )
27
+
28
+ func (n *Node) setupTracing() error {
29
+ // Set up propagator.
30
+ otel.SetTextMapPropagator(
31
+ propagation.NewCompositeTextMapPropagator(
32
+ propagation.TraceContext{},
33
+ propagation.Baggage{},
34
+ ),
35
+ )
36
+
37
+ // Set up trace provider.
38
+ var traceExporter trace.SpanExporter
39
+ var err error
40
+ if n.config.tracingStdout {
41
+ traceExporter, err = stdouttrace.New(
42
+ stdouttrace.WithPrettyPrint(),
43
+ )
44
+ } else {
45
+ // TODO: make options configurable (#387)
46
+ traceExporter, err = otlptracehttp.New(context.TODO())
47
+ }
48
+ if err != nil {
49
+ return err
50
+ }
51
+ tracerProvider := trace.NewTracerProvider(
52
+ trace.WithBatcher(traceExporter),
53
+ )
54
+ n.shutdownFuncs = append(n.shutdownFuncs, tracerProvider.Shutdown)
55
+ otel.SetTracerProvider(tracerProvider)
56
+ otel.SetErrorHandler(
57
+ otel.ErrorHandlerFunc(
58
+ func(err error) {
59
+ slog.Error(err.Error())
60
+ },
61
+ ),
62
+ )
63
+
64
+ return nil
65
+ }