Skip to content

Commit

Permalink
Merge pull request #10 from skip-mev/zygis/add-util-and-types
Browse files Browse the repository at this point in the history
feat: add types and util
  • Loading branch information
Zygimantass authored Dec 26, 2023
2 parents 66dfe3f + 439c8c5 commit c8037d6
Show file tree
Hide file tree
Showing 29 changed files with 6,888 additions and 49 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,21 @@ permissions:

jobs:
golangci:
strategy:
matrix:
module: ["chain", "node", "types", "util", "wallet"]
name: golangci-lint
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v4
with:
go-version: 1.21.3
- uses: actions/checkout@v4
- name: initialize workspace
run: |
go work init ||:
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
version: latest
only-new-issues: true
args: --timeout=5m
working-directory: ${{ matrix.module }}
323 changes: 323 additions & 0 deletions chain/chain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,323 @@
package chain

import (
"context"
sdkmath "cosmossdk.io/math"
"fmt"
"github.com/cometbft/cometbft/rpc/client"
"github.com/cosmos/cosmos-sdk/types"
"github.com/skip-mev/petri/provider"
petritypes "github.com/skip-mev/petri/types"
"golang.org/x/sync/errgroup"
"google.golang.org/grpc"
"math"
"strings"
"time"
)

type Chain struct {
Config petritypes.ChainConfig

Validators []petritypes.NodeI
Nodes []petritypes.NodeI

ValidatorWallets []petritypes.WalletI
}

var _ petritypes.ChainI = &Chain{}

func CreateChain(ctx context.Context, infraProvider provider.Provider, config petritypes.ChainConfig) (petritypes.ChainI, error) {
var chain Chain

validators := make([]petritypes.NodeI, 0)
nodes := make([]petritypes.NodeI, 0)

for i := 0; i < config.NumValidators; i++ {
validator, err := config.NodeCreator(ctx, petritypes.NodeConfig{
Name: fmt.Sprintf("%s-validator-%d", config.ChainId, i),
IsValidator: true,
Provider: infraProvider,
Chain: &chain,
})

if err != nil {
return nil, err
}

validators = append(validators, validator)
}

for i := 0; i < config.NumNodes; i++ {
node, err := config.NodeCreator(ctx, petritypes.NodeConfig{
Name: fmt.Sprintf("%s-node-%d", config.ChainId, i),
IsValidator: true,
Provider: infraProvider,
Chain: &chain,
})

if err != nil {
return nil, err
}

nodes = append(nodes, node)
}

chain.Nodes = nodes
chain.Validators = validators
chain.Config = config
chain.ValidatorWallets = make([]petritypes.WalletI, config.NumValidators)

return &chain, nil
}

func (c *Chain) GetConfig() petritypes.ChainConfig {
return c.Config
}

func (c *Chain) Height(ctx context.Context) (uint64, error) {
node := c.GetFullNode()

client, err := node.GetTMClient(ctx)

if err != nil {
return 0, err
}

block, err := client.Block(context.Background(), nil)

if err != nil {
return 0, err
}

return uint64(block.Block.Height), nil
}

func (c *Chain) Init(ctx context.Context) error {
decimalPow := int64(math.Pow10(int(c.Config.Decimals)))

genesisCoin := types.Coin{
Amount: sdkmath.NewInt(10_000_000).MulRaw(decimalPow),
Denom: c.Config.Denom,
}

genesisSelfDelegation := types.Coin{
Amount: sdkmath.NewInt(5_000_000).MulRaw(decimalPow),
Denom: c.Config.Denom,
}

genesisAmounts := []types.Coin{genesisCoin}

eg := new(errgroup.Group)

for idx, v := range c.Validators {
v := v
idx := idx
eg.Go(func() error {
if err := v.InitHome(ctx); err != nil {
return err
}

validatorWallet, err := v.CreateWallet(ctx, petritypes.ValidatorKeyName)

if err != nil {
return err
}

c.ValidatorWallets[idx] = validatorWallet

bech32 := validatorWallet.FormattedAddress()

if err != nil {
return err
}

if err := v.AddGenesisAccount(ctx, bech32, genesisAmounts); err != nil {
return err
}

if err := v.GenerateGenTx(ctx, genesisSelfDelegation); err != nil {
return err
}

return nil
})
}

for _, n := range c.Nodes {
n := n

eg.Go(func() error {
if err := n.InitHome(ctx); err != nil {
return err
}

return nil
})
}

if err := eg.Wait(); err != nil {
return err
}

faucetWallet, err := c.BuildWallet(ctx, petritypes.FaucetAccountKeyName, "")

if err != nil {
return err
}

firstValidator := c.Validators[0]

if err := firstValidator.AddGenesisAccount(ctx, faucetWallet.FormattedAddress(), genesisAmounts); err != nil {
return err
}

for i := 1; i < len(c.Validators); i++ {
validatorN := c.Validators[i]
bech32, err := validatorN.KeyBech32(ctx, petritypes.ValidatorKeyName, "acc")

if err != nil {
return err
}

if err := firstValidator.AddGenesisAccount(ctx, bech32, genesisAmounts); err != nil {
return err
}

if err := validatorN.CopyGenTx(ctx, firstValidator); err != nil {
return err
}
}

if err := firstValidator.CollectGenTxs(ctx); err != nil {
return err
}

genbz, err := firstValidator.GenesisFileContent(ctx)

if err != nil {
return err
}

if c.Config.ModifyGenesis != nil {
genbz, err = c.Config.ModifyGenesis(genbz)
if err != nil {
return err
}
}

peers, err := c.PeerStrings(ctx)

if err != nil {
return err
}

if err != nil {
return err
}

for _, v := range c.Validators {
if err := v.OverwriteGenesisFile(ctx, genbz); err != nil {
return err
}
if err := v.SetDefaultConfigs(ctx); err != nil {
return err
}
if err := v.SetPersistentPeers(ctx, peers); err != nil {
return err
}
}

for _, v := range c.Validators {
if err := v.GetTask().Start(ctx, true); err != nil {
return err
}
}

for _, n := range c.Nodes {
if err := n.OverwriteGenesisFile(ctx, genbz); err != nil {
return err
}
if err := n.SetDefaultConfigs(ctx); err != nil {
return err
}
if err := n.SetPersistentPeers(ctx, peers); err != nil {
return err
}
}

for _, n := range c.Nodes {
if err := n.GetTask().Start(ctx, true); err != nil {
return err
}
}

return nil
}

func (c *Chain) PeerStrings(ctx context.Context) (string, error) {
peerStrings := []string{}

for _, n := range append(c.Validators, c.Nodes...) {
ip, err := n.GetIP(ctx)

if err != nil {
return "", err
}

nodeId, err := n.NodeId(ctx)

if err != nil {
return "", err
}

peerStrings = append(peerStrings, fmt.Sprintf("%s@%s:26656", nodeId, ip))
}

return strings.Join(peerStrings, ","), nil
}

func (c *Chain) GetGRPCClient(ctx context.Context) (*grpc.ClientConn, error) {
return c.GetFullNode().GetGRPCClient(ctx)
}

func (c *Chain) GetTMClient(ctx context.Context) (client.Client, error) {
return c.GetFullNode().GetTMClient(ctx)
}

func (c *Chain) GetFullNode() petritypes.NodeI {
if len(c.Nodes) > 0 {
// use first full node
return c.Nodes[0]
}
// use first validator
return c.Validators[0]
}

func (c *Chain) WaitForBlocks(ctx context.Context, delta uint64) error {
start, err := c.Height(ctx)

if err != nil {
return err
}

cur := start

for {
if cur-start >= delta {
break
}

cur, err = c.Height(ctx)
if err != nil {
continue
}
// We assume the chain will eventually return a non-zero height, otherwise
// this may block indefinitely.
if cur == 0 {
continue
}

time.Sleep(2 * time.Second)
}
return nil
}
46 changes: 46 additions & 0 deletions chain/chain_wallet.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package chain

import (
"context"
"fmt"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/types"
petritypes "github.com/skip-mev/petri/types"
"github.com/skip-mev/petri/wallet"
)

func (c *Chain) BuildWallet(ctx context.Context, keyName, mnemonic string) (petritypes.WalletI, error) {
// if mnemonic is empty, we just generate a wallet
if mnemonic == "" {
return c.CreateWallet(ctx, keyName)
}

if err := c.RecoverKey(ctx, keyName, mnemonic); err != nil {
return nil, fmt.Errorf("failed to recover key with name %q on chain %s: %w", keyName, c.Config.ChainId, err)
}

coinType, err := hd.NewParamsFromPath(c.Config.CoinType)

if err != nil {
return nil, err
}

return wallet.NewWallet(keyName, mnemonic, c.Config.Bech32Prefix, coinType)
}

func (c *Chain) RecoverKey(ctx context.Context, keyName, mnemonic string) error {
return c.GetFullNode().RecoverKey(ctx, keyName, mnemonic)
}

func (c *Chain) CreateWallet(ctx context.Context, keyName string) (petritypes.WalletI, error) {
return c.GetFullNode().CreateWallet(ctx, keyName)
}

func (c *Chain) GetAddress(ctx context.Context, keyName string) ([]byte, error) {
b32Addr, err := c.GetFullNode().KeyBech32(ctx, keyName, "acc")
if err != nil {
return nil, err
}

return types.GetFromBech32(b32Addr, c.Config.Bech32Prefix)
}
Loading

0 comments on commit c8037d6

Please sign in to comment.