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  }