Skip to content

Commit

Permalink
cli: Support for account addresses and "test:" prefix
Browse files Browse the repository at this point in the history
  • Loading branch information
matevz committed Jul 8, 2022
1 parent 84c1789 commit 38647bb
Show file tree
Hide file tree
Showing 10 changed files with 175 additions and 40 deletions.
32 changes: 21 additions & 11 deletions cli/cmd/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"math/big"
"os"

"github.com/oasisprotocol/oasis-sdk/client-sdk/go/testing"
"github.com/spf13/cobra"
flag "github.com/spf13/pflag"

Expand Down Expand Up @@ -65,7 +66,7 @@ var (
c, err := connection.Connect(ctx, npa.Network)
cobra.CheckErr(err)

addr, err := helpers.ResolveAddress(npa.Network, targetAddress)
addr, err := ResolveLocalAccountOrAddress(npa.Network, targetAddress)
cobra.CheckErr(err)

height, err := common.GetActualHeight(
Expand Down Expand Up @@ -234,7 +235,7 @@ var (
}

// Resolve beneficiary address.
benAddr, err := helpers.ResolveAddress(npa.Network, beneficiary)
benAddr, err := ResolveLocalAccountOrAddress(npa.Network, beneficiary)
cobra.CheckErr(err)

// Parse amount.
Expand Down Expand Up @@ -295,7 +296,7 @@ var (
var toAddr *types.Address
if to != "" {
var err error
toAddr, err = helpers.ResolveAddress(npa.Network, to)
toAddr, err = ResolveLocalAccountOrAddress(npa.Network, to)
cobra.CheckErr(err)
}

Expand Down Expand Up @@ -386,18 +387,27 @@ var (

// Resolve destination address when specified.
var toAddr *types.Address
if to != "" {
var err error
toAddr, err = helpers.ResolveAddress(npa.Network, to)
cobra.CheckErr(err)
var err error
if to == "" {
toAddr, err = helpers.ResolveAddress(npa.Network, npa.Account.Address)
} else {
toAddr, err = ResolveLocalAccountOrAddress(npa.Network, to)
}
cobra.CheckErr(err)

// Safety check for withdrawals to known accounts that are not supported on the consensus layer.
for name, acc := range cliConfig.Global().Wallet.All {
if acc.Address == toAddr.String() && !acc.HasConsensusSigner() {
cobra.CheckErr(fmt.Errorf("account '%s' (%s) will not be able to sign transactions on consensus layer", name, acc.Address))
}
}
for name := range testing.TestAccounts {
testAcc, err := common.LoadTestAccount(name)
cobra.CheckErr(err)
if testAcc.Address().String() == toAddr.String() && testAcc.ConsensusSigner() == nil {
cobra.CheckErr(fmt.Errorf("test account '%s' (%s) will not be able to sign transactions on consensus layer", name, testAcc.Address().String()))
}
}

// Parse amount.
// TODO: This should actually query the ParaTime (or config) to check what the consensus
Expand Down Expand Up @@ -479,7 +489,7 @@ var (
}

// Resolve destination address.
toAddr, err := helpers.ResolveAddress(npa.Network, to)
toAddr, err := ResolveLocalAccountOrAddress(npa.Network, to)
cobra.CheckErr(err)

acc := common.LoadAccount(cfg, npa.AccountName)
Expand Down Expand Up @@ -589,7 +599,7 @@ var (
}

// Resolve destination address.
toAddr, err := helpers.ResolveAddress(npa.Network, to)
toAddr, err := ResolveLocalAccountOrAddress(npa.Network, to)
cobra.CheckErr(err)

acc := common.LoadAccount(cfg, npa.AccountName)
Expand Down Expand Up @@ -642,7 +652,7 @@ var (
}

// Resolve destination address.
fromAddr, err := helpers.ResolveAddress(npa.Network, from)
fromAddr, err := ResolveLocalAccountOrAddress(npa.Network, from)
cobra.CheckErr(err)

acc := common.LoadAccount(cfg, npa.AccountName)
Expand Down Expand Up @@ -712,7 +722,7 @@ var (
now, err = conn.Consensus().Beacon().GetEpoch(ctx, height)
cobra.CheckErr(err)

addr, err := helpers.ResolveAddress(npa.Network, npa.Account.Address)
addr, err := ResolveLocalAccountOrAddress(npa.Network, npa.Account.Address)
cobra.CheckErr(err)

stakingConn := conn.Consensus().Staking()
Expand Down
15 changes: 12 additions & 3 deletions cli/cmd/common/selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package common

import (
"fmt"
"strings"

"github.com/spf13/cobra"
flag "github.com/spf13/pflag"

cliConfig "github.com/oasisprotocol/oasis-sdk/cli/config"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/config"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/helpers"
)

var (
Expand Down Expand Up @@ -66,9 +68,16 @@ func GetNPASelection(cfg *cliConfig.Config) *NPASelection {
s.AccountName = selectedAccount
}
if s.AccountName != "" {
s.Account = cfg.Wallet.All[s.AccountName]
if s.Account == nil {
cobra.CheckErr(fmt.Errorf("account '%s' does not exist in the wallet", s.AccountName))
if strings.HasPrefix(s.AccountName, helpers.AddressExplicitTest+helpers.AddressExplicitSeparator) {
subs := strings.SplitN(s.AccountName, helpers.AddressExplicitSeparator, 2)
testAcc, err := LoadTestAccountConfig(subs[1])
cobra.CheckErr(err)
s.Account = &testAcc
} else {
s.Account = cfg.Wallet.All[s.AccountName]
if s.Account == nil {
cobra.CheckErr(fmt.Errorf("account '%s' does not exist in the wallet", s.AccountName))
}
}
}

Expand Down
39 changes: 39 additions & 0 deletions cli/cmd/common/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,31 @@ package common

import (
"fmt"
"strings"

"github.com/AlecAivazis/survey/v2"
"github.com/spf13/cobra"

"github.com/oasisprotocol/oasis-sdk/cli/config"
"github.com/oasisprotocol/oasis-sdk/cli/wallet"
"github.com/oasisprotocol/oasis-sdk/cli/wallet/test"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/helpers"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/testing"
)

// LoadAccount loads the given named account.
func LoadAccount(cfg *config.Config, name string) wallet.Account {
// Check, if the accounts is test account.
if strings.Contains(name, helpers.AddressExplicitSeparator) {
subs := strings.SplitN(name, helpers.AddressExplicitSeparator, 2)
if subs[0] == helpers.AddressExplicitTest {
testAccount, err := LoadTestAccount(subs[1])
cobra.CheckErr(err)

return testAccount
}
}

// Early check for whether the account exists so that we don't ask for passphrase first.
var (
acfg *config.Account
Expand All @@ -38,3 +53,27 @@ func LoadAccount(cfg *config.Config, name string) wallet.Account {

return acc
}

// LoadTestAccount loads the given named test account.
func LoadTestAccount(name string) (wallet.Account, error) {
if testKey, ok := testing.TestAccounts[name]; ok {
testAccount, err := test.NewTestAccount(testKey)
cobra.CheckErr(err)

return testAccount, nil
}
return nil, fmt.Errorf("test account %s does not exist", name)
}

// LoadTestAccountConfig loads config for the given named test account.
func LoadTestAccountConfig(name string) (config.Account, error) {
testAcc, err := LoadTestAccount(name)
cobra.CheckErr(err)

return config.Account{
Description: "",
Kind: test.Kind,
Address: testAcc.Address().String(),
Config: nil,
}, nil
}
2 changes: 1 addition & 1 deletion cli/cmd/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ func parsePolicy(net *config.Network, wallet *cliConfig.Account, policy string)
return &contracts.Policy{Address: &address}
case strings.HasPrefix(policy, "address:"):
policy = strings.TrimPrefix(policy, "address:")
address, err := helpers.ResolveAddress(net, policy)
address, err := ResolveLocalAccountOrAddress(net, policy)
if err != nil {
cobra.CheckErr(fmt.Errorf("malformed address in policy: %w", err))
}
Expand Down
15 changes: 14 additions & 1 deletion cli/cmd/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ import (
"github.com/oasisprotocol/oasis-sdk/cli/table"
"github.com/oasisprotocol/oasis-sdk/cli/wallet"
walletFile "github.com/oasisprotocol/oasis-sdk/cli/wallet/file"
configSdk "github.com/oasisprotocol/oasis-sdk/client-sdk/go/config"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/helpers"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/types"
)

var (
Expand All @@ -41,7 +43,7 @@ var (
Run: func(cmd *cobra.Command, args []string) {
cfg := config.Global()
table := table.New()
table.SetHeader([]string{"Name", "Kind", "Address"})
table.SetHeader([]string{"Account", "Kind", "Address"})

var output [][]string
for name, acc := range cfg.Wallet.All {
Expand Down Expand Up @@ -349,6 +351,17 @@ func (sf *accountEntitySignerFactory) Load(
return sf.signer, nil
}

// ResolveLocalAccountOrAddress resolves a string address into the corresponding account address.
func ResolveLocalAccountOrAddress(net *configSdk.Network, address string) (*types.Address, error) {
// Check, if address is the account name in the wallet.
if acc, ok := config.Global().Wallet.All[address]; ok {
addr := acc.GetAddress()
return &addr, nil
}

return helpers.ResolveAddress(net, address)
}

func showPublicWalletInfo(wallet wallet.Account) {
fmt.Printf("Public Key: %s\n", wallet.Signer().Public())
fmt.Printf("Address: %s\n", wallet.Address())
Expand Down
50 changes: 50 additions & 0 deletions cli/wallet/test/test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package test

import (
"encoding/base64"

coreSignature "github.com/oasisprotocol/oasis-core/go/common/crypto/signature"
"github.com/oasisprotocol/oasis-sdk/cli/wallet"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/crypto/signature"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/testing"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/types"
)

const (
Kind = "test"
)

type testAccount struct {
testKey testing.TestKey
}

func NewTestAccount(testKey testing.TestKey) (wallet.Account, error) {
return &testAccount{testKey: testKey}, nil
}

func (a *testAccount) ConsensusSigner() coreSignature.Signer {
type wrappedSigner interface {
Unwrap() coreSignature.Signer
}

if ws, ok := a.testKey.Signer.(wrappedSigner); ok {
return ws.Unwrap()
}
return nil
}

func (a *testAccount) Signer() signature.Signer {
return a.testKey.Signer
}

func (a *testAccount) Address() types.Address {
return a.testKey.Address
}

func (a *testAccount) SignatureAddressSpec() types.SignatureAddressSpec {
return a.testKey.SigSpec
}

func (a *testAccount) UnsafeExport() string {
return base64.StdEncoding.EncodeToString(a.testKey.SecretKey)
}
19 changes: 14 additions & 5 deletions client-sdk/go/helpers/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@ import (
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/config"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/crypto/signature/secp256k1"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/modules/rewards"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/testing"
"github.com/oasisprotocol/oasis-sdk/client-sdk/go/types"
)

const (
addressPrefixOasis = "oasis1"
addressPrefixEth = "0x"
addressExplicitSeparator = ":"
addressPrefixOasis = "oasis1"
addressPrefixEth = "0x"

AddressExplicitSeparator = ":"
addressExplicitParaTime = "paratime"
addressExplicitPool = "pool"
AddressExplicitTest = "test"

poolRewards = "rewards"
)
Expand All @@ -46,8 +49,8 @@ func ResolveAddress(net *config.Network, address string) (*types.Address, error)
}
addr := types.NewAddressRaw(types.AddressV0Secp256k1EthContext, ethAddr)
return &addr, nil
case strings.Contains(address, addressExplicitSeparator):
subs := strings.SplitN(address, addressExplicitSeparator, 2)
case strings.Contains(address, AddressExplicitSeparator):
subs := strings.SplitN(address, AddressExplicitSeparator, 2)
switch kind, data := subs[0], subs[1]; kind {
case addressExplicitParaTime:
// ParaTime.
Expand All @@ -67,6 +70,12 @@ func ResolveAddress(net *config.Network, address string) (*types.Address, error)
default:
return nil, fmt.Errorf("unsupported pool kind: %s", data)
}
case AddressExplicitTest:
// Test key.
if testKey, ok := testing.TestAccounts[data]; ok {
return &testKey.Address, nil
}
return nil, fmt.Errorf("unsupported test account: %s", data)
default:
// Unsupported kind.
return nil, fmt.Errorf("unsupported explicit address kind: %s", kind)
Expand Down
1 change: 1 addition & 0 deletions client-sdk/go/helpers/address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func TestResolveAddress(t *testing.T) {
{"pool:", ""},
{"pool:invalid", ""},
{"pool:rewards", "oasis1qp7x0q9qahahhjas0xde8w0v04ctp4pqzu5mhjav"},
{"test:alice", "oasis1qrec770vrek0a9a5lcrv0zvt22504k68svq7kzve"},
{"invalid:", ""},
} {
addr, err := ResolveAddress(&net, tc.address)
Expand Down
11 changes: 11 additions & 0 deletions client-sdk/go/testing/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,15 @@ var (
Frank = newSr25519TestKey("oasis-runtime-sdk/test-keys: frank")
// Grace is the test key G.
Grace = newSr25519TestKey("oasis-runtime-sdk/test-keys: grace")

// TestAccounts all test keys.
TestAccounts = map[string]TestKey{
"alice": Alice,
"bob": Bob,
"charlie": Charlie,
"dave": Dave,
"erin": Erin,
"frank": Frank,
"grace": Grace,
}
)
Loading

0 comments on commit 38647bb

Please sign in to comment.