diff --git a/README.md b/README.md index b6ac4bac..f202adfa 100644 --- a/README.md +++ b/README.md @@ -60,12 +60,14 @@ uris: COMMENT # ping the local cluster -curl -X POST --data '{ +curl --location --request POST 'http://localhost:61858/ext/bc/BJfusM2TpHCEfmt5i7qeE1MwVCbw5jU1TcZNz8MYUwG1PGYRL/public' \ +--header 'Content-Type: application/json' \ +--data-raw '{ "jsonrpc": "2.0", "method": "quarkvm.ping", "params":{}, "id": 1 -}' -H 'content-type:application/json;' 127.0.0.1:56239/ext/bc/2VCAhX6vE3UnXC6s1CBPE6jJ4c4cHWMfPgCptuWS59pQ9vbeLM +}' <>>>> -creating requester with URL http://127.0.0.1:9650 and endpoint "/ext/bc/2VCAhX6vE3UnXC6s1CBPE6jJ4c4cHWMfPgCptuWS59pQ9vbeLM" -Submitting tx NpfRjXRGRCXGxfqq6vcvH3GAm3yijJyxYD7QBxQFDS6YvSnXw with BlockID (zgvHpznxkG7xAh2qgsQFVkrioB4ENdKYfum6KWe6rZGiuzdPf): &{0xc00011a0c8 [175 87 123 222 38 232 10 27 198 13 215 107 60 56 102 21 11 12 195 39 191 122 160 156 155 11 183 164 202 22 22 76 231 28 232 58 18 187 198 249 170 168 232 227 43 85 90 54 94 76 49 184 59 9 194 205 222 162 20 67 208 185 115 12] 0} -issued transaction NpfRjXRGRCXGxfqq6vcvH3GAm3yijJyxYD7QBxQFDS6YvSnXw (success true) -polling transaction "NpfRjXRGRCXGxfqq6vcvH3GAm3yijJyxYD7QBxQFDS6YvSnXw" -confirmed transaction "NpfRjXRGRCXGxfqq6vcvH3GAm3yijJyxYD7QBxQFDS6YvSnXw" -prefix pat info &{Owner:0xc00011dd70 LastUpdated:1638591044 Expiry:1638591074 Keys:1} +--endpoint http://localhost:61858/ext/bc/BJfusM2TpHCEfmt5i7qeE1MwVCbw5jU1TcZNz8MYUwG1PGYRL \ +lifeline patrick.avax + +mining in progress[2ty1GmQAatedGd3CeUXzj5YUYVaqeMawpvCRPxqCf12u7fNfM/39]... (elapsed=1.01s, threads=16) +mining complete[469870] (difficulty=169, surplus=690, elapsed=1.31s) +issuing tx 2bJPjSWyr6NoDUE9ZyyamDetjNYDQ87G4dtZnT3LVf4uGYtFtU (fee units=10, load units=10, difficulty=169, blkID=2ty1GmQAatedGd3CeUXzj5YUYVaqeMawpvCRPxqCf12u7fNfM) +issued transaction 2bJPjSWyr6NoDUE9ZyyamDetjNYDQ87G4dtZnT3LVf4uGYtFtU (now polling) +transaction 2bJPjSWyr6NoDUE9ZyyamDetjNYDQ87G4dtZnT3LVf4uGYtFtU confirmed +raw prefix M9Jh5DMRXwMwaTHciFLVAMpc9dZKFpuGE: units=1 expiry=2022-02-09 04:07:07 -0800 PST (721h44m47.312056s remaining) +``` + +# HTTP Examples +## Get Prefix Info +_cGF0cmljay5hdmF4 is "patrick.avax" in base64_ +```bash +curl --location --request POST 'http://localhost:61858/ext/bc/BJfusM2TpHCEfmt5i7qeE1MwVCbw5jU1TcZNz8MYUwG1PGYRL/public' \ +--header 'Content-Type: application/json' \ +--data-raw '{ + "jsonrpc": "2.0", + "method": "quarkvm.prefixInfo", + "params":{ + "prefix":"cGF0cmljay5hdmF4" + }, + "id": 1 +}' + +{ + "jsonrpc": "2.0", + "result": { + "info": { + "owner": [ + 3, + 74, + 255, + 247, + 51, + 219, + 231, + 3, + 243, + 231, + 100, + 99, + 245, + 34, + 43, + 222, + 16, + 61, + 202, + 99, + 39, + 113, + 85, + 197, + 4, + 185, + 122, + 214, + 117, + 141, + 45, + 98, + 196 + ], + "created": 1641809853, + "lastUpdated": 1641810055, + "expiry": 1644408427, + "units": 1, + "rawPrefix": "M9Jh5DMRXwMwaTHciFLVAMpc9dZKFpuGE" + } + }, + "id": 1 +} ``` # Difficulty Estiamtes @@ -104,10 +247,10 @@ goos: darwin goarch: amd64 pkg: github.com/ava-labs/quarkvm/pow cpu: Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz -BenchmarkDifficulty1-16 1145233 1047 ns/op -BenchmarkDifficulty10-16 113216 10335 ns/op -BenchmarkDifficulty50-16 23011 52336 ns/op -BenchmarkDifficulty100-16 11540 102029 ns/op -BenchmarkDifficulty500-16 1962 535265 ns/op -BenchmarkDifficulty1000-16 1132 1082758 ns/op +BenchmarkDifficulty1-16 1300 921956 ns/op +BenchmarkDifficulty10-16 100 11083185 ns/op +BenchmarkDifficulty50-16 100 50243796 ns/op +BenchmarkDifficulty100-16 12 84529354 ns/op +BenchmarkDifficulty500-16 7 251526615 ns/op +BenchmarkDifficulty1000-16 7 571905766 ns/op ``` diff --git a/chain/lifeline_tx.go b/chain/lifeline_tx.go index 98a3fd2a..0f9277cd 100644 --- a/chain/lifeline_tx.go +++ b/chain/lifeline_tx.go @@ -24,12 +24,7 @@ func addLife(db database.KeyValueReaderWriter, prefix []byte) error { } // Lifeline spread across all units lastExpiry := i.Expiry - prefixPenalty := prefixUnits(prefix) / PrefixRenewalDiscount - if prefixPenalty < 1 { // avoid division by 0 - prefixPenalty = 1 - } - - i.Expiry += ExpiryTime / i.Units / prefixPenalty + i.Expiry += ExpiryTime / i.Units return PutPrefixInfo(db, prefix, i, lastExpiry) } @@ -37,6 +32,11 @@ func (l *LifelineTx) Execute(db database.Database, blockTime uint64) error { return addLife(db, l.Prefix) } +func (l *LifelineTx) FeeUnits() uint64 { + prefixUnits := prefixUnits(l.Prefix) / PrefixRenewalDiscount + return l.LoadUnits() + prefixUnits +} + func (l *LifelineTx) Copy() UnsignedTransaction { return &LifelineTx{ BaseTx: l.BaseTx.Copy(), diff --git a/client/client.go b/client/client.go index a64da420..40009fb1 100644 --- a/client/client.go +++ b/client/client.go @@ -7,7 +7,6 @@ package client import ( "context" "fmt" - "strings" "time" "github.com/ava-labs/avalanchego/ids" @@ -47,14 +46,10 @@ type Client interface { } // New creates a new client object. -func New(uri string, endpoint string, reqTimeout time.Duration) Client { - // TODO: automatically append public/private based on method - if !strings.HasPrefix(endpoint, "/") { - endpoint = "/" + endpoint - } +func New(uri string, reqTimeout time.Duration) Client { req := rpc.NewEndpointRequester( uri, - endpoint, + vm.PublicEndpoint, "quarkvm", reqTimeout, ) diff --git a/cmd/quarkcli/claim/claim.go b/cmd/quarkcli/cmd/claim.go similarity index 54% rename from cmd/quarkcli/claim/claim.go rename to cmd/quarkcli/cmd/claim.go index 382da0aa..e41fc638 100644 --- a/cmd/quarkcli/claim/claim.go +++ b/cmd/quarkcli/cmd/claim.go @@ -1,43 +1,25 @@ // Copyright (C) 2019-2021, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package claim +package cmd import ( "bytes" "context" "fmt" "os" - "strings" - "time" - "github.com/fatih/color" "github.com/spf13/cobra" "github.com/ava-labs/quarkvm/chain" "github.com/ava-labs/quarkvm/client" - "github.com/ava-labs/quarkvm/cmd/quarkcli/create" "github.com/ava-labs/quarkvm/parser" ) -func init() { - cobra.EnablePrefixMatching = true -} - -var ( - privateKeyFile string - url string - endpoint string - requestTimeout time.Duration - prefixInfo bool -) - -// NewCommand implements "quark-cli claim" command. -func NewCommand() *cobra.Command { - cmd := &cobra.Command{ - Use: "claim [options] ", - Short: "Claims the given prefix", - Long: ` +var claimCmd = &cobra.Command{ + Use: "claim [options] ", + Short: "Claims the given prefix", + Long: ` Claims the given prefix by issuing claim transaction with the prefix information. @@ -65,44 +47,12 @@ success COMMENT `, - RunE: claimFunc, - } - cmd.PersistentFlags().StringVar( - &privateKeyFile, - "private-key-file", - ".quark-cli-pk", - "private key file path", - ) - cmd.PersistentFlags().StringVar( - &url, - "url", - "http://127.0.0.1:9650", - "RPC URL for VM", - ) - cmd.PersistentFlags().StringVar( - &endpoint, - "endpoint", - "", - "RPC endpoint for VM", - ) - cmd.PersistentFlags().DurationVar( - &requestTimeout, - "request-timeout", - 30*time.Second, - "timeout for transaction issuance and confirmation", - ) - cmd.PersistentFlags().BoolVar( - &prefixInfo, - "prefix-info", - true, - "'true' to print out the prefix owner information", - ) - return cmd + RunE: claimFunc, } // TODO: move all this to a separate client code func claimFunc(cmd *cobra.Command, args []string) error { - priv, err := create.LoadPK(privateKeyFile) + priv, err := LoadPK(privateKeyFile) if err != nil { return err } @@ -112,12 +62,7 @@ func claimFunc(cmd *cobra.Command, args []string) error { } pfx := getClaimOp(args) - - if !strings.HasPrefix(endpoint, "/") { - endpoint = "/" + endpoint - } - color.Blue("creating requester with URL %s and endpoint %q for prefix %q", url, endpoint, pfx) - cli := client.New(url, endpoint, requestTimeout) + cli := client.New(uri, requestTimeout) utx := &chain.ClaimTx{ BaseTx: &chain.BaseTx{ @@ -126,13 +71,8 @@ func claimFunc(cmd *cobra.Command, args []string) error { }, } - opts := []client.OpOption{client.WithPollTx()} - if prefixInfo { - opts = append(opts, client.WithPrefixInfo(pfx)) - } - ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) - _, err = client.MineSignIssueTx(ctx, cli, utx, priv, opts...) - cancel() + opts := []client.OpOption{client.WithPollTx(), client.WithPrefixInfo(pfx)} + _, err = client.MineSignIssueTx(context.Background(), cli, utx, priv, opts...) return err } diff --git a/cmd/quarkcli/create/create.go b/cmd/quarkcli/cmd/create.go similarity index 59% rename from cmd/quarkcli/create/create.go rename to cmd/quarkcli/cmd/create.go index e91e3bd9..2277e825 100644 --- a/cmd/quarkcli/create/create.go +++ b/cmd/quarkcli/cmd/create.go @@ -1,62 +1,30 @@ // Copyright (C) 2019-2021, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -// Package create implements "create" commands. -package create +package cmd import ( "errors" "os" - "path/filepath" "github.com/ava-labs/avalanchego/utils/crypto" "github.com/fatih/color" "github.com/spf13/cobra" ) -var ( - f *crypto.FactorySECP256K1R - - workDir string - privateKeyFile string -) - -func init() { - p, err := os.Getwd() - if err != nil { - panic(err) - } - workDir = p - f = &crypto.FactorySECP256K1R{} - - cobra.EnablePrefixMatching = true -} - -// NewCommand implements "quark-cli create" command. -func NewCommand() *cobra.Command { - cmd := &cobra.Command{ - Use: "create [options]", - Short: "Creates a new key in the default location", - Long: ` +var createCmd = &cobra.Command{ + Use: "create [options]", + Short: "Creates a new key in the default location", + Long: ` Creates a new key in the default location. It will error if the key file already exists. $ quark-cli create `, - RunE: createFunc, - } - cmd.PersistentFlags().StringVar( - &privateKeyFile, - "private-key-file", - filepath.Join(workDir, ".quark-cli-pk"), - "private key file path", - ) - return cmd + RunE: createFunc, } -const fsModeWrite = 0o600 - func createFunc(cmd *cobra.Command, args []string) error { if _, err := os.Stat(privateKeyFile); err == nil { return os.ErrExist diff --git a/cmd/quarkcli/delete/delete.go b/cmd/quarkcli/cmd/delete.go similarity index 61% rename from cmd/quarkcli/delete/delete.go rename to cmd/quarkcli/cmd/delete.go index 11c8bf97..dadc5b1b 100644 --- a/cmd/quarkcli/delete/delete.go +++ b/cmd/quarkcli/cmd/delete.go @@ -1,41 +1,24 @@ // Copyright (C) 2019-2021, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package delete +package cmd import ( "context" "fmt" "os" - "time" - "github.com/fatih/color" "github.com/spf13/cobra" "github.com/ava-labs/quarkvm/chain" "github.com/ava-labs/quarkvm/client" - "github.com/ava-labs/quarkvm/cmd/quarkcli/create" "github.com/ava-labs/quarkvm/parser" ) -func init() { - cobra.EnablePrefixMatching = true -} - -var ( - privateKeyFile string - url string - endpoint string - requestTimeout time.Duration - prefixInfo bool -) - -// NewCommand implements "quark-cli" command. -func NewCommand() *cobra.Command { - cmd := &cobra.Command{ - Use: "delete [options] ", - Short: "Deletes a key-value pair for the given prefix", - Long: ` +var deleteCmd = &cobra.Command{ + Use: "delete [options] ", + Short: "Deletes a key-value pair for the given prefix", + Long: ` Issues "SetTx" to delete key-value pair(s). The prefix is automatically parsed with the delimiter "/". @@ -85,44 +68,12 @@ error COMMENT `, - RunE: deleteFunc, - } - cmd.PersistentFlags().StringVar( - &privateKeyFile, - "private-key-file", - ".quark-cli-pk", - "private key file path", - ) - cmd.PersistentFlags().StringVar( - &url, - "url", - "http://127.0.0.1:9650", - "RPC URL for VM", - ) - cmd.PersistentFlags().StringVar( - &endpoint, - "endpoint", - "", - "RPC endpoint for VM", - ) - cmd.PersistentFlags().DurationVar( - &requestTimeout, - "request-timeout", - 30*time.Second, - "timeout for transaction issuance and confirmation", - ) - cmd.PersistentFlags().BoolVar( - &prefixInfo, - "prefix-info", - true, - "'true' to print out the prefix owner information", - ) - return cmd + RunE: deleteFunc, } // TODO: move all this to a separate client code func deleteFunc(cmd *cobra.Command, args []string) error { - priv, err := create.LoadPK(privateKeyFile) + priv, err := LoadPK(privateKeyFile) if err != nil { return err } @@ -132,9 +83,7 @@ func deleteFunc(cmd *cobra.Command, args []string) error { } pfx, key := getDeleteOp(args) - - color.Blue("creating requester with URL %s and endpoint %q for prefix %q and key %q", url, endpoint, pfx, key) - cli := client.New(url, endpoint, requestTimeout) + cli := client.New(uri, requestTimeout) utx := &chain.SetTx{ BaseTx: &chain.BaseTx{ @@ -145,13 +94,8 @@ func deleteFunc(cmd *cobra.Command, args []string) error { Value: nil, } - opts := []client.OpOption{client.WithPollTx()} - if prefixInfo { - opts = append(opts, client.WithPrefixInfo(pfx)) - } - ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) - _, err = client.MineSignIssueTx(ctx, cli, utx, priv, opts...) - cancel() + opts := []client.OpOption{client.WithPollTx(), client.WithPrefixInfo(pfx)} + _, err = client.MineSignIssueTx(context.Background(), cli, utx, priv, opts...) return err } diff --git a/cmd/quarkcli/genesis/genesis.go b/cmd/quarkcli/cmd/genesis.go similarity index 69% rename from cmd/quarkcli/genesis/genesis.go rename to cmd/quarkcli/cmd/genesis.go index 092eb223..23fbb899 100644 --- a/cmd/quarkcli/genesis/genesis.go +++ b/cmd/quarkcli/cmd/genesis.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2021, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package genesis +package cmd import ( "os" @@ -15,51 +15,37 @@ import ( ) func init() { - p, err := os.Getwd() - if err != nil { - panic(err) - } - workDir = p - - cobra.EnablePrefixMatching = true -} - -var ( - workDir string - genesisFile string - minDifficulty uint64 - minBlockCost uint64 -) - -// NewCommand implements "quark-cli genesis" command. -func NewCommand() *cobra.Command { - cmd := &cobra.Command{ - Use: "genesis [options]", - Short: "Creates a new genesis in the default location", - RunE: genesisFunc, - } - cmd.PersistentFlags().StringVar( + genesisCmd.PersistentFlags().StringVar( &genesisFile, "genesis-file", filepath.Join(workDir, "genesis.json"), "genesis file path", ) - cmd.PersistentFlags().Uint64Var( + genesisCmd.PersistentFlags().Uint64Var( &minDifficulty, "min-difficulty", chain.MinDifficulty, "minimum difficulty for mining", ) - cmd.PersistentFlags().Uint64Var( + genesisCmd.PersistentFlags().Uint64Var( &minBlockCost, "min-block-cost", chain.MinBlockCost, "minimum block cost", ) - return cmd } -const fsModeWrite = 0o600 +var ( + genesisFile string + minDifficulty uint64 + minBlockCost uint64 +) + +var genesisCmd = &cobra.Command{ + Use: "genesis [options]", + Short: "Creates a new genesis in the default location", + RunE: genesisFunc, +} func genesisFunc(cmd *cobra.Command, args []string) error { // Note: genesis block must have the min difficulty and block cost or else diff --git a/cmd/quarkcli/get/get.go b/cmd/quarkcli/cmd/get.go similarity index 69% rename from cmd/quarkcli/get/get.go rename to cmd/quarkcli/cmd/get.go index f0756f5d..8e4baad6 100644 --- a/cmd/quarkcli/get/get.go +++ b/cmd/quarkcli/cmd/get.go @@ -1,12 +1,11 @@ // Copyright (C) 2019-2021, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package get +package cmd import ( "fmt" "os" - "time" "github.com/fatih/color" "github.com/spf13/cobra" @@ -15,26 +14,30 @@ import ( "github.com/ava-labs/quarkvm/parser" ) -func init() { - cobra.EnablePrefixMatching = true -} - var ( - privateKeyFile string - url string - endpoint string - requestTimeout time.Duration - limit uint32 - withPrefix bool - prefixInfo bool + limit uint32 + withPrefix bool ) -// NewCommand implements "quark-cli get" command. -func NewCommand() *cobra.Command { - cmd := &cobra.Command{ - Use: "get [options] ", - Short: "Reads the keys with the given prefix", - Long: ` +func init() { + getCmd.PersistentFlags().Uint32Var( + &limit, + "limit", + 0, + "non-zero to limit the number of key-values in the response", + ) + getCmd.PersistentFlags().BoolVar( + &withPrefix, + "with-prefix", + false, + "'true' for prefix query", + ) +} + +var getCmd = &cobra.Command{ + Use: "get [options] ", + Short: "Reads the keys with the given prefix", + Long: ` If no range end is given, it only reads the value for the specified key if it exists. If a range end is given, it reads all key-values in [start,end) at most "limit" entries. @@ -90,59 +93,13 @@ $ quark-cli get hello.avax/foo1 hello.avax/foo3 COMMENT `, - RunE: getFunc, - } - cmd.PersistentFlags().StringVar( - &privateKeyFile, - "private-key-file", - ".quark-cli-pk", - "private key file path", - ) - cmd.PersistentFlags().StringVar( - &url, - "url", - "http://127.0.0.1:9650", - "RPC URL for VM", - ) - cmd.PersistentFlags().StringVar( - &endpoint, - "endpoint", - "", - "RPC endpoint for VM", - ) - cmd.PersistentFlags().DurationVar( - &requestTimeout, - "request-timeout", - 30*time.Second, - "timeout for transaction issuance and confirmation", - ) - cmd.PersistentFlags().Uint32Var( - &limit, - "limit", - 0, - "non-zero to limit the number of key-values in the response", - ) - cmd.PersistentFlags().BoolVar( - &withPrefix, - "with-prefix", - false, - "'true' for prefix query", - ) - cmd.PersistentFlags().BoolVar( - &prefixInfo, - "prefix-info", - true, - "'true' to print out the prefix owner information", - ) - return cmd + RunE: getFunc, } // TODO: move all this to a separate client code func getFunc(cmd *cobra.Command, args []string) error { pfx, key, rangeEnd := getGetOp(args, withPrefix) - - color.Blue("creating requester with URL %s and endpoint %q for prefix %q and key %q", url, endpoint, pfx, key) - cli := client.New(url, endpoint, requestTimeout) + cli := client.New(uri, requestTimeout) opts := []client.OpOption{} if len(rangeEnd) > 0 { @@ -162,13 +119,6 @@ func getFunc(cmd *cobra.Command, args []string) error { fmt.Printf("key: %q, value: %q\n", kv.Key, kv.Value) } - if prefixInfo { - info, err := cli.PrefixInfo(pfx) - if err != nil { - color.Red("cannot get prefix info %v", err) - } - color.Blue("prefix %q info %+v", pfx, info) - } return nil } diff --git a/cmd/quarkcli/cmd/lifeline.go b/cmd/quarkcli/cmd/lifeline.go new file mode 100644 index 00000000..0dfa3c51 --- /dev/null +++ b/cmd/quarkcli/cmd/lifeline.go @@ -0,0 +1,73 @@ +// Copyright (C) 2019-2021, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package cmd + +import ( + "bytes" + "context" + "fmt" + "os" + + "github.com/spf13/cobra" + + "github.com/ava-labs/quarkvm/chain" + "github.com/ava-labs/quarkvm/client" + "github.com/ava-labs/quarkvm/parser" +) + +var lifelineCmd = &cobra.Command{ + Use: "lifeline [options] ", + Short: "Extends the life of a given prefix", + RunE: lifelineFunc, +} + +// TODO: move all this to a separate client code +func lifelineFunc(cmd *cobra.Command, args []string) error { + priv, err := LoadPK(privateKeyFile) + if err != nil { + return err + } + pk, err := chain.FormatPK(priv.PublicKey()) + if err != nil { + return err + } + + pfx := getLifelineOp(args) + cli := client.New(uri, requestTimeout) + + utx := &chain.LifelineTx{ + BaseTx: &chain.BaseTx{ + Sender: pk, + Prefix: pfx, + }, + } + + opts := []client.OpOption{client.WithPollTx(), client.WithPrefixInfo(pfx)} + _, err = client.MineSignIssueTx(context.Background(), cli, utx, priv, opts...) + return err +} + +func getLifelineOp(args []string) (pfx []byte) { + if len(args) != 1 { + fmt.Fprintf(os.Stderr, "expected exactly 1 argument, got %d", len(args)) + os.Exit(128) + } + + pfx = []byte(args[0]) + if bytes.HasSuffix(pfx, []byte{'/'}) { + pfx = pfx[:len(pfx)-1] + } + + // check here first before parsing in case "pfx" is empty + if err := parser.CheckPrefix(pfx); err != nil { + fmt.Fprintf(os.Stderr, "failed to verify prefix %v", err) + os.Exit(128) + } + if _, _, _, err := parser.ParsePrefixKey(pfx); err != nil { + fmt.Fprintf(os.Stderr, "failed to parse prefix %v", err) + os.Exit(128) + } + + return pfx +} diff --git a/cmd/quarkcli/cmd/root.go b/cmd/quarkcli/cmd/root.go new file mode 100644 index 00000000..74a1a93d --- /dev/null +++ b/cmd/quarkcli/cmd/root.go @@ -0,0 +1,69 @@ +// Copyright (C) 2019-2021, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// "quark-cli" implements quarkvm client operation interface. +package cmd + +import ( + "os" + "time" + + "github.com/spf13/cobra" + + "github.com/ava-labs/avalanchego/utils/crypto" +) + +const ( + requestTimeout = 30 * time.Second + fsModeWrite = 0o600 +) + +var ( + privateKeyFile string + uri string + workDir string + f *crypto.FactorySECP256K1R + + rootCmd = &cobra.Command{ + Use: "quark-cli", + Short: "QuarkVM client CLI", + SuggestFor: []string{"quark-cli", "quarkcli", "quarkctl"}, + } +) + +func init() { + p, err := os.Getwd() + if err != nil { + panic(err) + } + workDir = p + f = &crypto.FactorySECP256K1R{} + + cobra.EnablePrefixMatching = true + rootCmd.AddCommand( + createCmd, + genesisCmd, + claimCmd, + lifelineCmd, + setCmd, + deleteCmd, + getCmd, + ) + + rootCmd.PersistentFlags().StringVar( + &privateKeyFile, + "private-key-file", + ".quark-cli-pk", + "private key file path", + ) + rootCmd.PersistentFlags().StringVar( + &uri, + "endpoint", + "http://127.0.0.1:9650", + "RPC Endpoint for VM", + ) +} + +func Execute() error { + return rootCmd.Execute() +} diff --git a/cmd/quarkcli/set/set.go b/cmd/quarkcli/cmd/set.go similarity index 61% rename from cmd/quarkcli/set/set.go rename to cmd/quarkcli/cmd/set.go index 2839bef4..f29c2a54 100644 --- a/cmd/quarkcli/set/set.go +++ b/cmd/quarkcli/cmd/set.go @@ -1,41 +1,24 @@ // Copyright (C) 2019-2021, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package set +package cmd import ( "context" "fmt" "os" - "time" - "github.com/fatih/color" "github.com/spf13/cobra" "github.com/ava-labs/quarkvm/chain" "github.com/ava-labs/quarkvm/client" - "github.com/ava-labs/quarkvm/cmd/quarkcli/create" "github.com/ava-labs/quarkvm/parser" ) -func init() { - cobra.EnablePrefixMatching = true -} - -var ( - privateKeyFile string - url string - endpoint string - requestTimeout time.Duration - prefixInfo bool -) - -// NewCommand implements "quark-cli set" command. -func NewCommand() *cobra.Command { - cmd := &cobra.Command{ - Use: "set [options] ", - Short: "Writes a key-value pair for the given prefix", - Long: ` +var setCmd = &cobra.Command{ + Use: "set [options] ", + Short: "Writes a key-value pair for the given prefix", + Long: ` Issues "SetTx" to write a key-value pair. The prefix is automatically parsed with the delimiter "/". @@ -81,44 +64,12 @@ success COMMENT `, - RunE: setFunc, - } - cmd.PersistentFlags().StringVar( - &privateKeyFile, - "private-key-file", - ".quark-cli-pk", - "private key file path", - ) - cmd.PersistentFlags().StringVar( - &url, - "url", - "http://127.0.0.1:9650", - "RPC URL for VM", - ) - cmd.PersistentFlags().StringVar( - &endpoint, - "endpoint", - "", - "RPC endpoint for VM", - ) - cmd.PersistentFlags().DurationVar( - &requestTimeout, - "request-timeout", - 30*time.Second, - "timeout for transaction issuance and confirmation", - ) - cmd.PersistentFlags().BoolVar( - &prefixInfo, - "prefix-info", - true, - "'true' to print out the prefix owner information", - ) - return cmd + RunE: setFunc, } // TODO: move all this to a separate client code func setFunc(cmd *cobra.Command, args []string) error { - priv, err := create.LoadPK(privateKeyFile) + priv, err := LoadPK(privateKeyFile) if err != nil { return err } @@ -128,9 +79,7 @@ func setFunc(cmd *cobra.Command, args []string) error { } pfx, key, val := getSetOp(args) - - color.Blue("creating requester with URL %s and endpoint %q for prefix %q and key %q", url, endpoint, pfx, key) - cli := client.New(url, endpoint, requestTimeout) + cli := client.New(uri, requestTimeout) utx := &chain.SetTx{ BaseTx: &chain.BaseTx{ @@ -141,13 +90,8 @@ func setFunc(cmd *cobra.Command, args []string) error { Value: val, } - opts := []client.OpOption{client.WithPollTx()} - if prefixInfo { - opts = append(opts, client.WithPrefixInfo(pfx)) - } - ctx, cancel := context.WithTimeout(context.Background(), requestTimeout) - _, err = client.MineSignIssueTx(ctx, cli, utx, priv, opts...) - cancel() + opts := []client.OpOption{client.WithPollTx(), client.WithPrefixInfo(pfx)} + _, err = client.MineSignIssueTx(context.Background(), cli, utx, priv, opts...) return err } diff --git a/cmd/quarkcli/main.go b/cmd/quarkcli/main.go index 220f65b4..96f45e69 100644 --- a/cmd/quarkcli/main.go +++ b/cmd/quarkcli/main.go @@ -8,39 +8,11 @@ import ( "fmt" "os" - "github.com/spf13/cobra" - - "github.com/ava-labs/quarkvm/cmd/quarkcli/claim" - "github.com/ava-labs/quarkvm/cmd/quarkcli/create" - "github.com/ava-labs/quarkvm/cmd/quarkcli/delete" - "github.com/ava-labs/quarkvm/cmd/quarkcli/genesis" - "github.com/ava-labs/quarkvm/cmd/quarkcli/get" - "github.com/ava-labs/quarkvm/cmd/quarkcli/set" + "github.com/ava-labs/quarkvm/cmd/quarkcli/cmd" ) -var rootCmd = &cobra.Command{ - Use: "quark-cli", - Short: "QuarkVM client CLI", - SuggestFor: []string{"quark-cli", "quarkcli", "quarkctl"}, -} - -func init() { - cobra.EnablePrefixMatching = true -} - -func init() { - rootCmd.AddCommand( - genesis.NewCommand(), - create.NewCommand(), - set.NewCommand(), - delete.NewCommand(), - claim.NewCommand(), - get.NewCommand(), - ) -} - func main() { - if err := rootCmd.Execute(); err != nil { + if err := cmd.Execute(); err != nil { fmt.Fprintf(os.Stderr, "quark-cli failed %v\n", err) os.Exit(1) } diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index fa7a857b..610944e4 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -8,7 +8,6 @@ import ( "bytes" "context" "flag" - "path" "strings" "syscall" "testing" @@ -19,7 +18,6 @@ import ( "github.com/ava-labs/quarkvm/client" "github.com/ava-labs/quarkvm/parser" "github.com/ava-labs/quarkvm/tests" - "github.com/ava-labs/quarkvm/vm" "github.com/fatih/color" ginkgo "github.com/onsi/ginkgo/v2" "github.com/onsi/gomega" @@ -46,7 +44,7 @@ func init() { flag.DurationVar( &requestTimeout, "request-timeout", - 60*time.Second, + 120*time.Second, "timeout for transaction issuance and confirmation", ) flag.StringVar( @@ -96,10 +94,10 @@ var _ = ginkgo.BeforeSuite(func() { instances = make([]instance, n) for i := range instances { - u := clusterInfo.URIs[i] + u := clusterInfo.URIs[i] + clusterInfo.Endpoint instances[i] = instance{ uri: u, - cli: client.New(u, path.Join(clusterInfo.Endpoint, vm.PublicEndpoint), requestTimeout), + cli: client.New(u, requestTimeout), } } color.Blue("created clients with %+v", clusterInfo) diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index bcb67f7d..57eff017 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -51,7 +51,7 @@ func init() { flag.DurationVar( &requestTimeout, "request-timeout", - 60*time.Second, + 120*time.Second, "timeout for transaction issuance and confirmation", ) flag.IntVar( @@ -158,7 +158,7 @@ var _ = ginkgo.BeforeSuite(func() { vm: v, toEngine: toEngine, httpServer: httpServer, - cli: client.New(httpServer.URL, "", requestTimeout), + cli: client.New(httpServer.URL, requestTimeout), builder: mb, } }