Skip to content

Commit

Permalink
Add initial foundation for genesis fetch
Browse files Browse the repository at this point in the history
  • Loading branch information
zivkovicmilos committed Sep 24, 2024
1 parent 9897b66 commit 7edb850
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 0 deletions.
1 change: 1 addition & 0 deletions gno.land/cmd/gnoland/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func newGenesisCmd(io commands.IO) *commands.Command {
newVerifyCmd(io),
newBalancesCmd(io),
newTxsCmd(io),
newDownloadCmd(io),
)

return cmd
Expand Down
163 changes: 163 additions & 0 deletions gno.land/cmd/gnoland/genesis_download.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package main

import (
"bufio"
"context"
"crypto/sha256"
"encoding/hex"
"errors"
"flag"
"fmt"
"io"
"net/http"
"os"

"github.com/gnolang/gno/tm2/pkg/commands"
)

var (
errNoChainID = errors.New("no chain ID specified")
errChainNotSupported = errors.New("chain ID not supported")
)

const test4ID = "test4"

const deploymentPathFormat = "https://raw.githubusercontent.com/gnolang/gno/refs/heads/master/misc/deployments/%s.gno.land/genesis.json"

var genesisSHAMap = map[string]string{
test4ID: "beb781dffc09b96e3114fb7439fa85c4fe8ea796f64ec0cd3801a6b518ab023c",
}

type downloadCfg struct {
commonCfg
}

// newDownloadCmd creates the genesis download subcommand
func newDownloadCmd(io commands.IO) *commands.Command {
cfg := &downloadCfg{}

return commands.NewCommand(
commands.Metadata{
Name: "download",
ShortUsage: "download <chain-id>",
ShortHelp: "downloads the specific gno chain's genesis.json",
},
cfg,
func(ctx context.Context, args []string) error {
return execGenesisDownload(ctx, cfg, io, args)
},

Check warning on line 48 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L47-L48

Added lines #L47 - L48 were not covered by tests
)
}

func (c *downloadCfg) RegisterFlags(fs *flag.FlagSet) {
c.commonCfg.RegisterFlags(fs)
}

func execGenesisDownload(
ctx context.Context,
cfg *downloadCfg,
io commands.IO,
args []string,
) error {

Check warning on line 61 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L61

Added line #L61 was not covered by tests
// Make sure the chain ID is specified
if len(args) != 1 {
return errNoChainID

Check warning on line 64 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L63-L64

Added lines #L63 - L64 were not covered by tests
}

// Make sure the chain ID is supported
chainID := args[0]

Check warning on line 68 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L68

Added line #L68 was not covered by tests

genesisSHA, exists := genesisSHAMap[chainID]
if !exists {
return errChainNotSupported

Check warning on line 72 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L70-L72

Added lines #L70 - L72 were not covered by tests
}

// Fetch the genesis file
downloadURL := fmt.Sprintf(deploymentPathFormat, chainID)

Check warning on line 76 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L76

Added line #L76 was not covered by tests

if err := downloadFile(ctx, downloadURL, cfg.genesisPath); err != nil {
return fmt.Errorf("unable to download genesis.json, %w", err)

Check warning on line 79 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L78-L79

Added lines #L78 - L79 were not covered by tests
}

// Verify the SHA
computedSHA, err := computeSHA256(cfg.genesisPath)
if err != nil {
return fmt.Errorf("unable to compute genesis.json SHA, %w", err)

Check warning on line 85 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L83-L85

Added lines #L83 - L85 were not covered by tests
}

if genesisSHA != computedSHA {
return fmt.Errorf("expected genesis SHA %s, got %s", genesisSHA, computedSHA)

Check warning on line 89 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L88-L89

Added lines #L88 - L89 were not covered by tests
}

io.Printfln("Successfully downloaded %s genesis.json", chainID)
io.Printfln("SHA256: %s", computedSHA)

Check warning on line 93 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L92-L93

Added lines #L92 - L93 were not covered by tests

return nil

Check warning on line 95 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L95

Added line #L95 was not covered by tests
}

// downloadFile downloads the file from the specified URL
func downloadFile(
ctx context.Context,
url string,
outPath string,
) error {

Check warning on line 103 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L103

Added line #L103 was not covered by tests
// Create the request
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return fmt.Errorf("unable to create GET request, %w", err)

Check warning on line 107 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L105-L107

Added lines #L105 - L107 were not covered by tests
}

// Execute the fetch
resp, err := http.DefaultClient.Do(req)
if err != nil {
return fmt.Errorf("unable to make GET request, %w", err)

Check warning on line 113 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L111-L113

Added lines #L111 - L113 were not covered by tests
}

if resp.StatusCode != 200 {
return fmt.Errorf("unexpected status code %d", resp.StatusCode)

Check warning on line 117 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L116-L117

Added lines #L116 - L117 were not covered by tests
}

defer resp.Body.Close()

Check warning on line 120 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L120

Added line #L120 was not covered by tests

tempPath := "genesis.json.tmp"
f, err := os.Create(tempPath)
if err != nil {
return fmt.Errorf("unable to create file, %w", err)

Check warning on line 125 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L122-L125

Added lines #L122 - L125 were not covered by tests
}

defer func() {
_ = f.Close()
_ = os.Remove(tempPath)
}()

Check warning on line 131 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L128-L131

Added lines #L128 - L131 were not covered by tests

if _, err = io.Copy(f, resp.Body); err != nil {
return fmt.Errorf("error while downloading, %w", err)

Check warning on line 134 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L133-L134

Added lines #L133 - L134 were not covered by tests
}

// After the file is downloaded, rename the temporary file
if err = os.Rename(tempPath, outPath); err != nil {
return fmt.Errorf("unable to rename file, %w", err)

Check warning on line 139 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L138-L139

Added lines #L138 - L139 were not covered by tests
}

return nil

Check warning on line 142 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L142

Added line #L142 was not covered by tests
}

// computeSHA256 computes the SHA-256 hash of a file
func computeSHA256(path string) (string, error) {

Check warning on line 146 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L146

Added line #L146 was not covered by tests
// Open the file
f, err := os.Open(path)
if err != nil {
return "", fmt.Errorf("unable to open file, %w", err)

Check warning on line 150 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L148-L150

Added lines #L148 - L150 were not covered by tests
}
defer f.Close()

Check warning on line 152 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L152

Added line #L152 was not covered by tests

// Create the hasher
h := sha256.New()

Check warning on line 155 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L155

Added line #L155 was not covered by tests

// Hash the file
if _, err = io.Copy(h, bufio.NewReader(f)); err != nil {
return "", fmt.Errorf("unable to hash file, %w", err)

Check warning on line 159 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L158-L159

Added lines #L158 - L159 were not covered by tests
}

return hex.EncodeToString(h.Sum(nil)), nil

Check warning on line 162 in gno.land/cmd/gnoland/genesis_download.go

View check run for this annotation

Codecov / codecov/patch

gno.land/cmd/gnoland/genesis_download.go#L162

Added line #L162 was not covered by tests
}
12 changes: 12 additions & 0 deletions gno.land/cmd/gnoland/genesis_download_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

import "testing"

func TestGenesis_Download(t *testing.T) {
t.Parallel()

t.Run("", func(t *testing.T) {
t.Parallel()

})

Check failure on line 11 in gno.land/cmd/gnoland/genesis_download_test.go

View workflow job for this annotation

GitHub Actions / Run Main / Go Linter / lint

unnecessary trailing newline (whitespace)
}

0 comments on commit 7edb850

Please sign in to comment.