-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
611 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module github.com/sedaprotocol/seda-networks | ||
|
||
go 1.21.3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
1 change: 1 addition & 0 deletions
1
testnet/seda-1-testnet/gentx/gentx-c24f01b4a897b37dd958633943c5b1d1ec5809f1.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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=="]} |
Oops, something went wrong.