Skip to content

Commit

Permalink
ci: add gentx validation
Browse files Browse the repository at this point in the history
  • Loading branch information
jim380 committed Feb 6, 2024
1 parent 886f577 commit bb47ca8
Show file tree
Hide file tree
Showing 6 changed files with 611 additions and 0 deletions.
46 changes: 46 additions & 0 deletions .github/workflows/validate_gentx.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Validate Gentx

on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches:
- main

env:
GO_VERSION: "1.21.0"

permissions:
contents: read
repository-projects: read
packages: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_VERSION }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build Docker Image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
tags: validate-gentx

- name: Run Docker image
run: docker run validate-gentx
14 changes: 14 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
ARG GO_VERSION="1.21"
ARG RUNNER_IMAGE="alpine:3.17"

FROM golang:${GO_VERSION}-alpine

WORKDIR /app

COPY go.mod ./
RUN go mod download
COPY . .

RUN go build -o validate-gentx .

CMD ["./validate-gentx"]
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/sedaprotocol/seda-networks

go 1.21.3
279 changes: 279 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
package main

import (
"encoding/json"
"io"
"log"
"math/big"
"net/http"
"os"
"os/exec"
"path/filepath"
"strconv"
"time"
)

var (
/* =================================================== */
/* Change as needed */
/* =================================================== */
CHAIN_ID = "seda-1-testnet"
WORKING_DIR = "./testnet/" + CHAIN_ID
BINARY_URL = "https://github.com/sedaprotocol/seda-chain/releases/download/v0.0.5/seda-chaind-amd64"
BINARY = "seda-chaind"

/* =================================================== */
/* The followings should rarely change */
/* =================================================== */
GENTX_DIR = WORKING_DIR + "/gentx"
BINARY_PATH = "./" + BINARY
SEDA_HOME = os.Getenv("HOME") + "/.seda-chain"
PREFIX = "seda"
DENOM = "aseda"

TEST_KEY_NAME = "test-key"
GENESIS_ALLOCATION = "1000000000000000000000000000000000000" + DENOM
DEFAULT_BOND = "300000000000000000000000000000000000" + DENOM
MAXBOND = "600000000000000000000000000000000000"
)

func main() {
var files []string

log.Println("Checking if any gentx.json files exist under " + GENTX_DIR)
err := filepath.Walk(GENTX_DIR, func(path string, info os.FileInfo, err error) error {
if !info.IsDir() {
files = append(files, path)
}
return nil
})
if err != nil {
log.Fatal("Error checking for gentx.json files: ", err)
}

for _, file := range files {
if filepath.Ext(file) != ".json" {
log.Println("No gentx.json found under " + GENTX_DIR + ", exiting...")
os.Exit(1)
}

validateGentx()
}
}

func validateGentx() {
log.Println("Downloading binary...")
err := downloadFile(BINARY_PATH, BINARY_URL)
if err != nil {
log.Fatal("Error downloading binary: ", err)
}

// make binary executable
err = os.Chmod(BINARY_PATH, 0755)
if err != nil {
log.Fatal("Error making binary executable: ", err)
}

log.Println("Removing existing seda home directory...")
_, err = exec.Command("rm", "-rf", SEDA_HOME).Output()
if err != nil {
log.Fatal("Error removing existing seda home directory: ", err)
}

log.Println("Setting chain id...")
_, err = exec.Command(BINARY_PATH, "config", "set", "client", "chain-id", CHAIN_ID).Output()
if err != nil {
log.Fatal("Error setting chain id: ", err)
}

log.Println("Setting keyring backend...")
_, err = exec.Command(BINARY_PATH, "config", "set", "client", "keyring-backend", "test").Output()
if err != nil {
log.Fatal("Error setting keyring backend: ", err)
}

log.Println("Initializing node...")
_, err = exec.Command(BINARY_PATH, "init", "node", "--default-denom", DENOM).Output()
if err != nil {
log.Fatal("Error initializing node: ", err)
}

log.Println("Removing existing genesis file...")
err = os.Remove(SEDA_HOME + "/config/genesis.json")
if err != nil {
log.Fatal("Error removing existing genesis file: ", err)
}

// replace with pre-genesis.json
log.Println("Replacing genesis.json...")
err = copyFile(WORKING_DIR+"/pre-genesis.json", SEDA_HOME+"/config/genesis.json")
if err != nil {
log.Fatal("Error replacing default genesis.json: ", err)
}

// modify genesis time to be in the past
log.Println("Modifying genesis time...")
err = modifyGenesisTime(SEDA_HOME+"/config/genesis.json", "2024-01-01T18:00:00Z")
if err != nil {
log.Fatal("Error modifying genesis time: ", err)
}

// perform validation
log.Println("Validation began...")
gentxFiles, err := filepath.Glob(WORKING_DIR + "/gentx/*.json")
if err != nil {
log.Fatal("Error reading gentx files: ", err)
}

for i, file := range gentxFiles {
// add keys
keyName := TEST_KEY_NAME + "-" + strconv.Itoa(i)
_, err = exec.Command(BINARY_PATH, "keys", "add", keyName, "--keyring-backend", "test").Output()
if err != nil {
log.Fatal("Error adding key: ", err)
}

gentxFile, err := os.ReadFile(file)
if err != nil {
log.Fatal("Error reading gentx file: ", err)
}

var gentx map[string]interface{}
err = json.Unmarshal(gentxFile, &gentx)
if err != nil {
log.Fatal("Error unmarshalling gentx file: ", err)
}

body := gentx["body"].(map[string]interface{})
messages := body["messages"].([]interface{})
message := messages[0].(map[string]interface{})
validatorAddress := message["validator_address"].(string)
value := message["value"].(map[string]interface{})
denom := value["denom"].(string)
amount, ok := new(big.Int).SetString(value["amount"].(string), 10)
if !ok {
log.Fatal("Error converting bond amount to big.Int")
}

_, err = exec.Command(BINARY_PATH, "debug", "addr", validatorAddress).Output()
if err != nil {
log.Fatal("Error debugging validator address: ", err)
}

if denom != DENOM {
log.Fatal("invalid denomination")
}

maxBond, ok := new(big.Int).SetString(MAXBOND, 10)
if !ok {
log.Fatal("Error converting max bonding amount to big.Int")
}

if amount.Cmp(maxBond) == 1 {
log.Fatalf("Bonded stake exceeds limit: %d > %d", amount, maxBond)
}

// add genesis account
log.Println("Adding genesis account:", keyName)
log.Println("Amount:", GENESIS_ALLOCATION)
_, err = exec.Command(BINARY_PATH, "add-genesis-account", keyName, GENESIS_ALLOCATION, "--keyring-backend", "test").Output()
if err != nil {
log.Fatalf("Error adding genesis account: %s", err)
}

// create gentx
_, err = exec.Command(BINARY_PATH, "gentx", keyName, DEFAULT_BOND).Output()
if err != nil {
log.Fatal("Error creating gentx: ", err)
}

}

log.Println("Validating finished...")

log.Println("Collecting gentx...")
_, err = exec.Command(BINARY_PATH, "collect-gentxs").Output()
if err != nil {
log.Fatal("Error collecting gentxs: ", err)
}

log.Println("Validating gentx...")
_, err = exec.Command(BINARY_PATH, "validate-genesis").Output()
if err != nil {
log.Fatal("Error validating gentxs: ", err)
}

log.Println("Starting localnet...")
cmd := exec.Command(BINARY_PATH, "start")
// cmd.Stdout = os.Stdout
// cmd.Stderr = os.Stderr
err = cmd.Start()
if err != nil {
log.Fatal("Error starting localnet: ", err)
}

// wait for the chain to start
time.Sleep(10 * time.Second)

log.Println("Checking node status...")
cmd = exec.Command(BINARY_PATH, "status")
output, err := cmd.CombinedOutput()
if err != nil {
log.Fatalf("Error checking node status: %v, output: %s", err, output)
}

log.Println("✅ ✅ ✅ Gentx validation passed successfully...")
}

func downloadFile(filepath string, url string) error {
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()

out, err := os.Create(filepath)
if err != nil {
return err
}
defer out.Close()

_, err = io.Copy(out, resp.Body)
return err
}

func copyFile(src, dst string) error {
data, err := os.ReadFile(src)
if err != nil {
return err
}

err = os.WriteFile(dst, data, 0644)
if err != nil {
return err
}
return nil
}

func modifyGenesisTime(genesisFileNamePath, timestamp string) error {
genesisFile, err := os.ReadFile(genesisFileNamePath)
if err != nil {
log.Fatal(err)
}

var genesis map[string]interface{}
err = json.Unmarshal(genesisFile, &genesis)
if err != nil {
log.Fatal(err)
}

genesis["genesis_time"] = timestamp
newGenesisFile, err := json.MarshalIndent(genesis, "", " ")
if err != nil {
log.Fatal(err)
}

err = os.WriteFile(genesisFileNamePath, newGenesisFile, 0644)

return err
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.MsgCreateValidator","description":{"moniker":"node0","identity":"","website":"","security_contact":"","details":""},"commission":{"rate":"0.100000000000000000","max_rate":"0.200000000000000000","max_change_rate":"0.010000000000000000"},"min_self_delegation":"1","delegator_address":"","validator_address":"sedavaloper1x06lxmcnczmvzlgjmzxulznl8rzgtfv6eavgzy","pubkey":{"@type":"/cosmos.crypto.ed25519.PubKey","key":"h2CqXMybmYTaW7Fv/XT6BKqG54hwZu2IhrgDgtDq1OU="},"value":{"denom":"aseda","amount":"300000000000000000000000000000000000"}}],"memo":"[email protected]:26656","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[{"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A7lwZ1v1cqA3im4H6G7LE9mXjkC7zCkrmkPgAe9SGLtM"},"mode_info":{"single":{"mode":"SIGN_MODE_DIRECT"}},"sequence":"0"}],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""},"tip":null},"signatures":["gjcj6VPM8slg7BYJJRMfg2DCbESTPJzCBSVH1n0QiyY9StzEshwn+v+cP0ipcY9V2d0VxwKSA3MP8LET3gTsWA=="]}
Loading

0 comments on commit bb47ca8

Please sign in to comment.