Skip to content

Commit

Permalink
Separate Shared Components (#260)
Browse files Browse the repository at this point in the history
* experimenting with CLI

* move more cli commands over

* port storage

* more progress

* fix prompt chain

* rewrite tokenvm action

* tokenvm chain

* make chain shared

* abstract watch

* rewrite key operations

* add support for prometheus

* introduce sendAndWait

* abstract submitDummy

* remove old submit dummy

* progress on cli spam

* generic spam implemented

* general spam

* remove unused errors

* close db earlier

* start cleanup of basevm

* cleaning up base

* basevm actions passing

* making progress with cleanup

* fix chain for basevm

* cleanup spam

* remove unnecessary errors

* fix lint in base and hypersk

* fix license spacing

* remove gosec from spam

* fix license header application

* add license to right files in token-cli
  • Loading branch information
patrick-ogrady authored Jul 22, 2023
1 parent c73969e commit 4542f00
Show file tree
Hide file tree
Showing 57 changed files with 2,363 additions and 3,112 deletions.
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ linters:
- staticcheck
- bodyclose
- structcheck
- lll
# - lll
# - gomnd
- goprintffuncname
- interfacer
Expand Down
1 change: 1 addition & 0 deletions chain/mock_action.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions chain/mock_auth.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions chain/mock_auth_factory.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions chain/mock_rules.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

270 changes: 270 additions & 0 deletions cli/chain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package cli

import (
"context"
"fmt"
"math"
"os"
"strings"
"time"

runner "github.com/ava-labs/avalanche-network-runner/client"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/hypersdk/chain"
"github.com/ava-labs/hypersdk/consts"
"github.com/ava-labs/hypersdk/rpc"
"github.com/ava-labs/hypersdk/utils"
"github.com/ava-labs/hypersdk/window"
"gopkg.in/yaml.v2"
)

func (h *Handler) ImportChain() error {
chainID, err := h.PromptID("chainID")
if err != nil {
return err
}
uri, err := h.PromptString("uri", 0, consts.MaxInt)
if err != nil {
return err
}
if err := h.StoreChain(chainID, uri); err != nil {
return err
}
if err := h.StoreDefaultChain(chainID); err != nil {
return err
}
return nil
}

func (h *Handler) ImportANR() error {
ctx := context.Background()

// Delete previous items
oldChains, err := h.DeleteChains()
if err != nil {
return err
}
if len(oldChains) > 0 {
utils.Outf("{{yellow}}deleted old chains:{{/}} %+v\n", oldChains)
}

// Load new items from ANR
anrCli, err := runner.New(runner.Config{
Endpoint: "0.0.0.0:12352",
DialTimeout: 10 * time.Second,
}, logging.NoLog{})
if err != nil {
return err
}
status, err := anrCli.Status(ctx)
if err != nil {
return err
}
subnets := map[ids.ID][]ids.ID{}
for chain, chainInfo := range status.ClusterInfo.CustomChains {
chainID, err := ids.FromString(chain)
if err != nil {
return err
}
subnetID, err := ids.FromString(chainInfo.SubnetId)
if err != nil {
return err
}
chainIDs, ok := subnets[subnetID]
if !ok {
chainIDs = []ids.ID{}
}
chainIDs = append(chainIDs, chainID)
subnets[subnetID] = chainIDs
}
var filledChainID ids.ID
for _, nodeInfo := range status.ClusterInfo.NodeInfos {
if len(nodeInfo.WhitelistedSubnets) == 0 {
continue
}
trackedSubnets := strings.Split(nodeInfo.WhitelistedSubnets, ",")
for _, subnet := range trackedSubnets {
subnetID, err := ids.FromString(subnet)
if err != nil {
return err
}
for _, chainID := range subnets[subnetID] {
uri := fmt.Sprintf("%s/ext/bc/%s", nodeInfo.Uri, chainID)
if err := h.StoreChain(chainID, uri); err != nil {
return err
}
utils.Outf(
"{{yellow}}stored chainID:{{/}} %s {{yellow}}uri:{{/}} %s\n",
chainID,
uri,
)
filledChainID = chainID
}
}
}
return h.StoreDefaultChain(filledChainID)
}

type AvalancheOpsConfig struct {
Resources struct {
CreatedNodes []struct {
HTTPEndpoint string `yaml:"httpEndpoint"`
} `yaml:"created_nodes"`
} `yaml:"resources"`
}

func (h *Handler) ImportOps(schainID string, opsPath string) error {
oldChains, err := h.DeleteChains()
if err != nil {
return err
}
if len(oldChains) > 0 {
utils.Outf("{{yellow}}deleted old chains:{{/}} %+v\n", oldChains)
}

// Load chainID
chainID, err := ids.FromString(schainID)
if err != nil {
return err
}

// Load yaml file
var opsConfig AvalancheOpsConfig
yamlFile, err := os.ReadFile(opsPath)
if err != nil {
return err
}
err = yaml.Unmarshal(yamlFile, &opsConfig)
if err != nil {
return err
}

// Add chains
for _, node := range opsConfig.Resources.CreatedNodes {
uri := fmt.Sprintf("%s/ext/bc/%s", node.HTTPEndpoint, chainID)
if err := h.StoreChain(chainID, uri); err != nil {
return err
}
utils.Outf(
"{{yellow}}stored chainID:{{/}} %s {{yellow}}uri:{{/}} %s\n",
chainID,
uri,
)
}
return h.StoreDefaultChain(chainID)
}

func (h *Handler) SetDefaultChain() error {
chainID, _, err := h.PromptChain("set default chain", nil)
if err != nil {
return err
}
return h.StoreDefaultChain(chainID)
}

func (h *Handler) PrintChainInfo() error {
_, uris, err := h.PromptChain("select chainID", nil)
if err != nil {
return err
}
cli := rpc.NewJSONRPCClient(uris[0])
networkID, subnetID, chainID, err := cli.Network(context.Background())
if err != nil {
return err
}
utils.Outf(
"{{cyan}}networkID:{{/}} %d {{cyan}}subnetID:{{/}} %s {{cyan}}chainID:{{/}} %s",
networkID,
subnetID,
chainID,
)
return nil
}

func (h *Handler) WatchChain(hideTxs bool, getParser func(string, uint32, ids.ID) (chain.Parser, error), handleTx func(*chain.Transaction, *chain.Result)) error {
ctx := context.Background()
chainID, uris, err := h.PromptChain("select chainID", nil)
if err != nil {
return err
}
if err := h.CloseDatabase(); err != nil {
return err
}
utils.Outf("{{yellow}}uri:{{/}} %s\n", uris[0])
rcli := rpc.NewJSONRPCClient(uris[0])
networkID, _, _, err := rcli.Network(context.TODO())
if err != nil {
return err
}
parser, err := getParser(uris[0], networkID, chainID)
if err != nil {
return err
}
scli, err := rpc.NewWebSocketClient(uris[0])
if err != nil {
return err
}
defer scli.Close()
if err := scli.RegisterBlocks(); err != nil {
return err
}
utils.Outf("{{green}}watching for new blocks on %s 👀{{/}}\n", chainID)
var (
start time.Time
lastBlock int64
lastBlockDetailed time.Time
tpsWindow = window.Window{}
)
for ctx.Err() == nil {
blk, results, err := scli.ListenBlock(ctx, parser)
if err != nil {
return err
}
now := time.Now()
if start.IsZero() {
start = now
}
if lastBlock != 0 {
since := now.Unix() - lastBlock
newWindow, err := window.Roll(tpsWindow, int(since))
if err != nil {
return err
}
tpsWindow = newWindow
window.Update(&tpsWindow, window.WindowSliceSize-consts.Uint64Len, uint64(len(blk.Txs)))
runningDuration := time.Since(start)
tpsDivisor := math.Min(window.WindowSize, runningDuration.Seconds())
utils.Outf(
"{{green}}height:{{/}}%d {{green}}txs:{{/}}%d {{green}}units:{{/}}%d {{green}}root:{{/}}%s {{green}}TPS:{{/}}%.2f {{green}}split:{{/}}%dms\n",
blk.Hght,
len(blk.Txs),
blk.UnitsConsumed,
blk.StateRoot,
float64(window.Sum(tpsWindow))/tpsDivisor,
time.Since(lastBlockDetailed).Milliseconds(),
)
} else {
utils.Outf(
"{{green}}height:{{/}}%d {{green}}txs:{{/}}%d {{green}}units:{{/}}%d {{green}}root:{{/}}%s\n",
blk.Hght,
len(blk.Txs),
blk.UnitsConsumed,
blk.StateRoot,
)
window.Update(&tpsWindow, window.WindowSliceSize-consts.Uint64Len, uint64(len(blk.Txs)))
}
lastBlock = now.Unix()
lastBlockDetailed = now
if hideTxs {
continue
}
for i, tx := range blk.Txs {
handleTx(tx, results[i])
}
}
return nil
}
23 changes: 23 additions & 0 deletions cli/cli.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package cli

import (
"github.com/ava-labs/avalanchego/database"
"github.com/ava-labs/hypersdk/pebble"
)

type Handler struct {
c Controller

db database.Database
}

func New(c Controller) (*Handler, error) {
db, err := pebble.New(c.DatabasePath(), pebble.NewDefaultConfig())
if err != nil {
return nil, err
}
return &Handler{c, db}, nil
}
15 changes: 15 additions & 0 deletions cli/dependencies.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package cli

import (
"github.com/ava-labs/hypersdk/crypto"
)

type Controller interface {
DatabasePath() string
Symbol() string
Address(crypto.PublicKey) string
ParseAddress(string) (crypto.PublicKey, error)
}
18 changes: 18 additions & 0 deletions cli/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package cli

import "errors"

var (
ErrInputEmpty = errors.New("input is empty")
ErrInputTooLarge = errors.New("input is too large")
ErrInvalidChoice = errors.New("invalid choice")
ErrIndexOutOfRange = errors.New("index out-of-range")
ErrInsufficientBalance = errors.New("insufficient balance")
ErrDuplicate = errors.New("duplicate")
ErrNoChains = errors.New("no available chains")
ErrNoKeys = errors.New("no available keys")
ErrTxFailed = errors.New("tx failed")
)
Loading

0 comments on commit 4542f00

Please sign in to comment.