@@ -18,9 +18,11 @@ import (
1818 "encoding/hex"
1919 "encoding/json"
2020 "errors"
21+ "fmt"
2122 "io"
2223 "math/big"
2324 "os"
25+ "reflect"
2426 "time"
2527
2628 "github.com/blinklabs-io/gouroboros/cbor"
@@ -47,36 +49,8 @@ type ShelleyGenesis struct {
4749}
4850
4951type 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"`
8054}
8155
8256func (g ShelleyGenesis ) MarshalCBOR () ([]byte , error ) {
@@ -107,27 +81,21 @@ func (g ShelleyGenesis) MarshalCBOR() ([]byte, error) {
10781 if err != nil {
10882 return nil , err
10983 }
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 ()
11886 cborPools [cbor .NewByteString (poolIdBytes )] = []any {
11987 pool .Cost ,
12088 pool .Margin ,
12189 pool .Pledge ,
122- pool .PublicKey ,
90+ pool .Operator . Bytes () ,
12391 []any {
12492 []byte {0 },
12593 rewardAccountBytes ,
12694 },
127- pool .Owners ,
128- pool .Relays ,
95+ convertAddrKeyHashesToBytes ( pool .PoolOwners ) ,
96+ convertPoolRelays ( pool .Relays ) ,
12997 vrfBytes ,
130- pool .Metadata ,
98+ pool .PoolMetadata ,
13199 }
132100 }
133101
@@ -176,6 +144,67 @@ func (g ShelleyGenesis) MarshalCBOR() ([]byte, error) {
176144 return cbor .Encode (tmpData )
177145}
178146
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+
179208func (g * ShelleyGenesis ) GenesisUtxos () ([]common.Utxo , error ) {
180209 ret := []common.Utxo {}
181210 for address , amount := range g .InitialFunds {
@@ -204,30 +233,119 @@ func (g *ShelleyGenesis) GenesisUtxos() ([]common.Utxo, error) {
204233 return ret , nil
205234}
206235
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
210248 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+ }
212292 }
213- return g .Staking .Pools , poolStake , nil
293+
294+ return pools , poolStake , nil
214295}
215296
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+
218304 pool , exists := g .Staking .Pools [poolId ]
219305 if ! exists {
220306 return nil , nil , errors .New ("pool not found" )
221307 }
222308
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
224316 for stakeAddr , pId := range g .Staking .Stake {
225317 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 )
227334 }
228335 }
229336
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
231349}
232350
233351type ShelleyGenesisProtocolParams struct {
0 commit comments