@@ -18,9 +18,11 @@ import (
18
18
"encoding/hex"
19
19
"encoding/json"
20
20
"errors"
21
+ "fmt"
21
22
"io"
22
23
"math/big"
23
24
"os"
25
+ "reflect"
24
26
"time"
25
27
26
28
"github.com/blinklabs-io/gouroboros/cbor"
@@ -47,36 +49,8 @@ type ShelleyGenesis struct {
47
49
}
48
50
49
51
type GenesisStaking struct {
50
- Pools map [string ]GenesisPool `json:"pools"`
51
- Stake map [string ]string `json:"stake"`
52
- }
53
-
54
- type GenesisPool struct {
55
- Cost int64 `json:"cost"`
56
- Margin float64 `json:"margin"`
57
- Metadata interface {} `json:"metadata"`
58
- Owners []string `json:"owners"`
59
- Pledge int64 `json:"pledge"`
60
- PublicKey string `json:"publicKey"`
61
- Relays []GenesisRelay `json:"relays"`
62
- RewardAccount GenesisReward `json:"rewardAccount"`
63
- Vrf string `json:"vrf"`
64
- }
65
-
66
- type GenesisRelay struct {
67
- SingleHostName * SingleHostName `json:"single host name,omitempty"`
68
- }
69
-
70
- type SingleHostName struct {
71
- DNSName string `json:"dnsName"`
72
- Port int `json:"port"`
73
- }
74
-
75
- type GenesisReward struct {
76
- Credential struct {
77
- KeyHash string `json:"key hash"`
78
- } `json:"credential"`
79
- Network string `json:"network"`
52
+ Pools map [string ]common.PoolRegistrationCertificate `json:"pools"`
53
+ Stake map [string ]string `json:"stake"`
80
54
}
81
55
82
56
func (g ShelleyGenesis ) MarshalCBOR () ([]byte , error ) {
@@ -107,27 +81,21 @@ func (g ShelleyGenesis) MarshalCBOR() ([]byte, error) {
107
81
if err != nil {
108
82
return nil , err
109
83
}
110
- vrfBytes , err := hex .DecodeString (pool .Vrf )
111
- if err != nil {
112
- return nil , err
113
- }
114
- rewardAccountBytes , err := hex .DecodeString (pool .RewardAccount .Credential .KeyHash )
115
- if err != nil {
116
- return nil , err
117
- }
84
+ vrfBytes := pool .VrfKeyHash .Bytes ()
85
+ rewardAccountBytes := pool .RewardAccount .Bytes ()
118
86
cborPools [cbor .NewByteString (poolIdBytes )] = []any {
119
87
pool .Cost ,
120
88
pool .Margin ,
121
89
pool .Pledge ,
122
- pool .PublicKey ,
90
+ pool .Operator . Bytes () ,
123
91
[]any {
124
92
[]byte {0 },
125
93
rewardAccountBytes ,
126
94
},
127
- pool .Owners ,
128
- pool .Relays ,
95
+ convertAddrKeyHashesToBytes ( pool .PoolOwners ) ,
96
+ convertPoolRelays ( pool .Relays ) ,
129
97
vrfBytes ,
130
- pool .Metadata ,
98
+ pool .PoolMetadata ,
131
99
}
132
100
}
133
101
@@ -176,6 +144,67 @@ func (g ShelleyGenesis) MarshalCBOR() ([]byte, error) {
176
144
return cbor .Encode (tmpData )
177
145
}
178
146
147
+ func convertAddrKeyHashesToBytes (hashes []common.AddrKeyHash ) [][]byte {
148
+ result := make ([][]byte , len (hashes ))
149
+ for i , h := range hashes {
150
+ result [i ] = h .Bytes ()
151
+ }
152
+ return result
153
+ }
154
+
155
+ func convertPoolRelays (relays []common.PoolRelay ) []any {
156
+ result := make ([]any , len (relays ))
157
+ for i , relay := range relays {
158
+ switch relay .Type {
159
+ case 0 : // SingleHostAddr
160
+ var ipv4 , ipv6 []byte
161
+ var port uint32
162
+ if relay .Ipv4 != nil {
163
+ ipv4 = relay .Ipv4 .To4 ()
164
+ }
165
+ if relay .Ipv6 != nil {
166
+ ipv6 = relay .Ipv6 .To16 ()
167
+ }
168
+ if relay .Port != nil {
169
+ port = * relay .Port
170
+ }
171
+ result [i ] = map [string ]any {
172
+ "single host addr" : []any {
173
+ ipv4 ,
174
+ ipv6 ,
175
+ port ,
176
+ },
177
+ }
178
+ case 1 : // SingleHostName
179
+ var hostname string
180
+ var port uint32
181
+ if relay .Hostname != nil {
182
+ hostname = * relay .Hostname
183
+ }
184
+ if relay .Port != nil {
185
+ port = * relay .Port
186
+ }
187
+ result [i ] = map [string ]any {
188
+ "single host name" : []any {
189
+ hostname ,
190
+ port ,
191
+ },
192
+ }
193
+ case 2 : // MultiHostName
194
+ var hostname string
195
+ if relay .Hostname != nil {
196
+ hostname = * relay .Hostname
197
+ }
198
+ result [i ] = map [string ]any {
199
+ "multi host name" : hostname ,
200
+ }
201
+ default :
202
+ result [i ] = nil
203
+ }
204
+ }
205
+ return result
206
+ }
207
+
179
208
func (g * ShelleyGenesis ) GenesisUtxos () ([]common.Utxo , error ) {
180
209
ret := []common.Utxo {}
181
210
for address , amount := range g .InitialFunds {
@@ -204,30 +233,119 @@ func (g *ShelleyGenesis) GenesisUtxos() ([]common.Utxo, error) {
204
233
return ret , nil
205
234
}
206
235
207
- // GetInitialPools returns all initial stake pools with their delegators
208
- func (g * ShelleyGenesis ) GetInitialPools () (map [string ]GenesisPool , map [string ][]string , error ) {
209
- poolStake := make (map [string ][]string )
236
+ // InitialPools returns all pools and their delegators from the genesis data
237
+ func (g * ShelleyGenesis ) InitialPools () (map [string ]common.PoolRegistrationCertificate , map [string ][]common.Address , error ) {
238
+
239
+ pools := make (map [string ]common.PoolRegistrationCertificate )
240
+ poolStake := make (map [string ][]common.Address )
241
+
242
+ // Check for empty staking data
243
+ if reflect .DeepEqual (g .Staking , GenesisStaking {}) {
244
+ return pools , poolStake , nil
245
+ }
246
+
247
+ // Process stake delegations first
210
248
for stakeAddr , poolId := range g .Staking .Stake {
211
- poolStake [poolId ] = append (poolStake [poolId ], stakeAddr )
249
+ // Validate stake address format
250
+ if len (stakeAddr ) != 56 {
251
+ return nil , nil , fmt .Errorf ("invalid stake address length: %d (expected 56 hex chars)" , len (stakeAddr ))
252
+ }
253
+
254
+ stakeKeyBytes , err := hex .DecodeString (stakeAddr )
255
+ if err != nil {
256
+ return nil , nil , fmt .Errorf ("failed to decode stake key %s: %w" , stakeAddr , err )
257
+ }
258
+
259
+ // Create stake address
260
+ stakeAddrBytes := append ([]byte {0xE1 }, stakeKeyBytes ... )
261
+ addr , err := common .NewAddressFromBytes (stakeAddrBytes )
262
+ if err != nil {
263
+ return nil , nil , fmt .Errorf ("failed to create stake address: %w" , err )
264
+ }
265
+
266
+ poolStake [poolId ] = append (poolStake [poolId ], addr )
267
+ }
268
+
269
+ // Process pools
270
+ for poolId , pool := range g .Staking .Pools {
271
+ // Validate pool ID format
272
+ if len (poolId ) != 56 {
273
+ return nil , nil , fmt .Errorf ("invalid pool ID length: %d (expected 56 hex chars)" , len (poolId ))
274
+ }
275
+
276
+ operatorBytes , err := hex .DecodeString (poolId )
277
+ if err != nil {
278
+ return nil , nil , fmt .Errorf ("failed to decode pool operator key: %w" , err )
279
+ }
280
+
281
+ pools [poolId ] = common.PoolRegistrationCertificate {
282
+ Operator : common .Blake2b224 (operatorBytes ),
283
+ VrfKeyHash : pool .VrfKeyHash ,
284
+ Pledge : pool .Pledge ,
285
+ Cost : pool .Cost ,
286
+ Margin : pool .Margin ,
287
+ RewardAccount : pool .RewardAccount ,
288
+ PoolOwners : pool .PoolOwners ,
289
+ Relays : pool .Relays ,
290
+ PoolMetadata : pool .PoolMetadata ,
291
+ }
212
292
}
213
- return g .Staking .Pools , poolStake , nil
293
+
294
+ return pools , poolStake , nil
214
295
}
215
296
216
- // GetPoolById returns a specific pool by its ID along with its delegators
217
- func (g * ShelleyGenesis ) GetPoolById (poolId string ) (* GenesisPool , []string , error ) {
297
+ // PoolById returns a specific pool by its ID along with its delegators
298
+ func (g * ShelleyGenesis ) PoolById (poolId string ) (* common.PoolRegistrationCertificate , []common.Address , error ) {
299
+ // Validate input
300
+ if len (poolId ) != 56 {
301
+ return nil , nil , errors .New ("invalid pool ID length" )
302
+ }
303
+
218
304
pool , exists := g .Staking .Pools [poolId ]
219
305
if ! exists {
220
306
return nil , nil , errors .New ("pool not found" )
221
307
}
222
308
223
- var delegators []string
309
+ // Decode pool operator key
310
+ operatorBytes , err := hex .DecodeString (poolId )
311
+ if err != nil {
312
+ return nil , nil , errors .New ("failed to decode pool operator key" )
313
+ }
314
+
315
+ var delegators []common.Address
224
316
for stakeAddr , pId := range g .Staking .Stake {
225
317
if pId == poolId {
226
- delegators = append (delegators , stakeAddr )
318
+ if len (stakeAddr ) != 56 {
319
+ return nil , nil , errors .New ("invalid stake address length" )
320
+ }
321
+
322
+ stakeKeyBytes , err := hex .DecodeString (stakeAddr )
323
+ if err != nil {
324
+ return nil , nil , errors .New ("failed to decode stake key" )
325
+ }
326
+
327
+ stakeAddrBytes := append ([]byte {0xE1 }, stakeKeyBytes ... )
328
+ addr , err := common .NewAddressFromBytes (stakeAddrBytes )
329
+ if err != nil {
330
+ return nil , nil , errors .New ("failed to create stake address" )
331
+ }
332
+
333
+ delegators = append (delegators , addr )
227
334
}
228
335
}
229
336
230
- return & pool , delegators , nil
337
+ // Return pool with delegators
338
+ return & common.PoolRegistrationCertificate {
339
+ Operator : common .Blake2b224 (operatorBytes ),
340
+ VrfKeyHash : pool .VrfKeyHash ,
341
+ Pledge : pool .Pledge ,
342
+ Cost : pool .Cost ,
343
+ Margin : pool .Margin ,
344
+ RewardAccount : pool .RewardAccount ,
345
+ PoolOwners : pool .PoolOwners ,
346
+ Relays : pool .Relays ,
347
+ PoolMetadata : pool .PoolMetadata ,
348
+ }, delegators , nil
231
349
}
232
350
233
351
type ShelleyGenesisProtocolParams struct {
0 commit comments