github.com/ava-labs/avalanchego@v1.11.11/genesis/generate/checkpoints/main.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package main 5 6 import ( 7 "context" 8 "encoding/json" 9 "fmt" 10 "log" 11 12 "github.com/ava-labs/avalanchego/ids" 13 "github.com/ava-labs/avalanchego/indexer" 14 "github.com/ava-labs/avalanchego/utils/constants" 15 "github.com/ava-labs/avalanchego/utils/perms" 16 "github.com/ava-labs/avalanchego/utils/set" 17 ) 18 19 const ( 20 fujiURI = "http://localhost:9650" 21 mainnetURI = "http://localhost:9660" 22 23 maxNumCheckpoints = 100 24 ) 25 26 var ( 27 fujiXChainID = ids.FromStringOrPanic("2JVSBoinj9C2J33VntvzYtVJNZdN2NKiwwKjcumHUWEb5DbBrm") 28 fujiCChainID = ids.FromStringOrPanic("yH8D7ThNJkxmtkuv2jgBa4P1Rn3Qpr4pPr7QYNfcdoS6k6HWp") 29 mainnetXChainID = ids.FromStringOrPanic("2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM") 30 mainnetCChainID = ids.FromStringOrPanic("2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5") 31 ) 32 33 // This fetches IDs of blocks periodically accepted on the P-chain, X-chain, and 34 // C-chain on both Fuji and Mainnet. 35 // 36 // This expects to be able to communicate with a Fuji node at [fujiURI] and a 37 // Mainnet node at [mainnetURI]. Both nodes must have the index API enabled. 38 func main() { 39 ctx := context.Background() 40 41 fujiPChainCheckpoints, err := getCheckpoints(ctx, fujiURI, "P") 42 if err != nil { 43 log.Fatalf("failed to fetch Fuji P-chain checkpoints: %v", err) 44 } 45 fujiXChainCheckpoints, err := getCheckpoints(ctx, fujiURI, "X") 46 if err != nil { 47 log.Fatalf("failed to fetch Fuji X-chain checkpoints: %v", err) 48 } 49 fujiCChainCheckpoints, err := getCheckpoints(ctx, fujiURI, "C") 50 if err != nil { 51 log.Fatalf("failed to fetch Fuji C-chain checkpoints: %v", err) 52 } 53 54 mainnetPChainCheckpoints, err := getCheckpoints(ctx, mainnetURI, "P") 55 if err != nil { 56 log.Fatalf("failed to fetch Mainnet P-chain checkpoints: %v", err) 57 } 58 mainnetXChainCheckpoints, err := getCheckpoints(ctx, mainnetURI, "X") 59 if err != nil { 60 log.Fatalf("failed to fetch Mainnet X-chain checkpoints: %v", err) 61 } 62 mainnetCChainCheckpoints, err := getCheckpoints(ctx, mainnetURI, "C") 63 if err != nil { 64 log.Fatalf("failed to fetch Mainnet C-chain checkpoints: %v", err) 65 } 66 67 checkpoints := map[string]map[ids.ID]set.Set[ids.ID]{ 68 constants.FujiName: { 69 constants.PlatformChainID: fujiPChainCheckpoints, 70 fujiXChainID: fujiXChainCheckpoints, 71 fujiCChainID: fujiCChainCheckpoints, 72 }, 73 constants.MainnetName: { 74 constants.PlatformChainID: mainnetPChainCheckpoints, 75 mainnetXChainID: mainnetXChainCheckpoints, 76 mainnetCChainID: mainnetCChainCheckpoints, 77 }, 78 } 79 checkpointsJSON, err := json.MarshalIndent(checkpoints, "", "\t") 80 if err != nil { 81 log.Fatalf("failed to marshal checkpoints: %v", err) 82 } 83 84 if err := perms.WriteFile("checkpoints.json", checkpointsJSON, perms.ReadWrite); err != nil { 85 log.Fatalf("failed to write checkpoints: %v", err) 86 } 87 } 88 89 func getCheckpoints( 90 ctx context.Context, 91 uri string, 92 chainAlias string, 93 ) (set.Set[ids.ID], error) { 94 var ( 95 chainURI = fmt.Sprintf("%s/ext/index/%s/block", uri, chainAlias) 96 client = indexer.NewClient(chainURI) 97 ) 98 99 // If there haven't been any blocks accepted, this will return an error. 100 _, lastIndex, err := client.GetLastAccepted(ctx) 101 if err != nil { 102 return nil, err 103 } 104 105 var ( 106 numAccepted = lastIndex + 1 107 // interval is rounded up to ensure that the number of checkpoints 108 // fetched is at most maxNumCheckpoints. 109 interval = (numAccepted + maxNumCheckpoints - 1) / maxNumCheckpoints 110 checkpoints set.Set[ids.ID] 111 ) 112 for index := interval - 1; index <= lastIndex; index += interval { 113 container, err := client.GetContainerByIndex(ctx, index) 114 if err != nil { 115 return nil, err 116 } 117 118 checkpoints.Add(container.ID) 119 } 120 return checkpoints, nil 121 }