Skip to content

Commit

Permalink
go/oasis-node/cmd/stake: Add pubkey2address command
Browse files Browse the repository at this point in the history
  • Loading branch information
tjanez committed Jun 16, 2020
1 parent c905cce commit c1bf3eb
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 11 deletions.
4 changes: 4 additions & 0 deletions .changelog/3003.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
go/oasis-node/cmd/stake: Add `pubkey2address` commmand

Add `oasis-node stake pubkey2address` CLI command for converting a public key
(e.g. an entity's ID) to a staking account address.
44 changes: 42 additions & 2 deletions go/oasis-node/cmd/stake/stake.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import (

"github.com/spf13/cobra"
flag "github.com/spf13/pflag"
"github.com/spf13/viper"
"google.golang.org/grpc"

"github.com/oasisprotocol/oasis-core/go/common/crypto/signature"
"github.com/oasisprotocol/oasis-core/go/common/errors"
"github.com/oasisprotocol/oasis-core/go/common/logging"
"github.com/oasisprotocol/oasis-core/go/common/quantity"
Expand All @@ -19,8 +21,12 @@ import (
cmdFlags "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common/flags"
cmdGrpc "github.com/oasisprotocol/oasis-core/go/oasis-node/cmd/common/grpc"
"github.com/oasisprotocol/oasis-core/go/staking/api"
staking "github.com/oasisprotocol/oasis-core/go/staking/api"
)

// CfgPublicKey configures the public key.
const CfgPublicKey = "public_key"

var (
stakeCmd = &cobra.Command{
Use: "stake",
Expand All @@ -39,10 +45,17 @@ var (
Run: doList,
}

pubkey2AddressCmd = &cobra.Command{
Use: "pubkey2address",
Short: "convert a public key (e.g. entity's ID) to an account address",
Run: doPubkey2Address,
}

logger = logging.GetLogger("cmd/stake")

infoFlags = flag.NewFlagSet("", flag.ContinueOnError)
listFlags = flag.NewFlagSet("", flag.ContinueOnError)
infoFlags = flag.NewFlagSet("", flag.ContinueOnError)
listFlags = flag.NewFlagSet("", flag.ContinueOnError)
pubkey2AddressFlags = flag.NewFlagSet("", flag.ContinueOnError)
)

func doConnect(cmd *cobra.Command) (*grpc.ClientConn, api.Backend) {
Expand Down Expand Up @@ -207,19 +220,43 @@ func getAccount(ctx context.Context, cmd *cobra.Command, addr api.Address, clien
return acct
}

func doPubkey2Address(cmd *cobra.Command, args []string) {
if err := cmdCommon.Init(); err != nil {
cmdCommon.EarlyLogAndExit(err)
}

pkString := viper.GetString(CfgPublicKey)
if pkString == "" {
logger.Error("cannot convert an empty public key")
os.Exit(1)
}

var pk signature.PublicKey
if err := pk.UnmarshalText([]byte(pkString)); err != nil {
logger.Error("failed to parse public key",
"err", err,
)
os.Exit(1)
}

fmt.Printf("%v\n", staking.NewAddress(pk))
}

// Register registers the stake sub-command and all of it's children.
func Register(parentCmd *cobra.Command) {
registerAccountCmd()
for _, v := range []*cobra.Command{
infoCmd,
listCmd,
pubkey2AddressCmd,
accountCmd,
} {
stakeCmd.AddCommand(v)
}

infoCmd.Flags().AddFlagSet(infoFlags)
listCmd.Flags().AddFlagSet(listFlags)
pubkey2AddressCmd.Flags().AddFlagSet(pubkey2AddressFlags)

parentCmd.AddCommand(stakeCmd)
}
Expand All @@ -231,4 +268,7 @@ func init() {
listFlags.AddFlagSet(cmdFlags.RetriesFlags)
listFlags.AddFlagSet(cmdFlags.VerboseFlags)
listFlags.AddFlagSet(cmdGrpc.ClientFlags)

pubkey2AddressFlags.String(CfgPublicKey, "", "Public key (Base64-encoded)")
_ = viper.BindPFlags(pubkey2AddressFlags)
}
74 changes: 65 additions & 9 deletions go/oasis-test-runner/scenario/e2e/stake_cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,26 @@ const (

// Transaction fee gas.
feeGas = 10000

// Testing source account public key (hex-encoded).
srcPubkeyHex = "4ea5328f943ef6f66daaed74cb0e99c3b1c45f76307b425003dbc7cb3638ed35"

// Testing destination account public key (hex-encoded).
dstPubkeyHex = "5ea5328f943ef6f66daaed74cb0e99c3b1c45f76307b425003dbc7cb3638ed35"

// Testing escrow account public key (hex-encoded).
escrowPubkeyHex = "6ea5328f943ef6f66daaed74cb0e99c3b1c45f76307b425003dbc7cb3638ed35"
)

var (
// Testing source account address.
srcAddress = api.NewAddress(
signature.NewPublicKey("4ea5328f943ef6f66daaed74cb0e99c3b1c45f76307b425003dbc7cb3638ed35"),
)
srcAddress = api.NewAddress(signature.NewPublicKey(srcPubkeyHex))

// Testing destination account address.
dstAddress = api.NewAddress(
signature.NewPublicKey("5ea5328f943ef6f66daaed74cb0e99c3b1c45f76307b425003dbc7cb3638ed35"),
)
dstAddress = api.NewAddress(signature.NewPublicKey(dstPubkeyHex))

// Testing escrow account address.
escrowAddress = api.NewAddress(
signature.NewPublicKey("6ea5328f943ef6f66daaed74cb0e99c3b1c45f76307b425003dbc7cb3638ed35"),
)
escrowAddress = api.NewAddress(signature.NewPublicKey(escrowPubkeyHex))

// StakeCLI is the staking scenario.
StakeCLI scenario.Scenario = &stakeCLIImpl{
Expand Down Expand Up @@ -137,6 +142,32 @@ func (s *stakeCLIImpl) Run(childEnv *env.Env) error {
}

// Run the tests

// Ensure converting public keys to staking account addresses works.
pubkey2AddressTestVectors := []struct {
publicKeyText string
addressText string
expectError bool
}{
{signature.NewPublicKey(srcPubkeyHex).String(), srcAddress.String(), false},
{signature.NewPublicKey(dstPubkeyHex).String(), dstAddress.String(), false},
{signature.NewPublicKey(escrowPubkeyHex).String(), escrowAddress.String(), false},
// Empty public key.
{"", "", true},
// Invalid public key.
{"BadPubKey=", "", true},
}
s.logger.Info("test converting public keys to staking account addresses")
for _, vector := range pubkey2AddressTestVectors {
err = s.testPubkey2Address(childEnv, vector.publicKeyText, vector.addressText)
if err != nil && !vector.expectError {
return fmt.Errorf("scenario/e2e/stake: unexpected pubkey2address error: %w", err)
}
if err == nil && vector.expectError {
return fmt.Errorf("scenario/e2e/stake: pubkey2address for public key '%s' should error", vector.publicKeyText)
}
}

// Transfer
if err = s.testTransfer(childEnv, cli, srcAddress, dstAddress); err != nil {
return fmt.Errorf("scenario/e2e/stake: error while running Transfer test: %w", err)
Expand Down Expand Up @@ -169,6 +200,31 @@ func (s *stakeCLIImpl) Run(childEnv *env.Env) error {
return nil
}

func (s *stakeCLIImpl) testPubkey2Address(childEnv *env.Env, publicKeyText string, addressText string) error {
args := []string{
"stake", "pubkey2address",
"--" + stake.CfgPublicKey, publicKeyText,
}

out, err := cli.RunSubCommandWithOutput(childEnv, s.logger, "info", s.runtimeImpl.net.Config().NodeBinary, args)
if err != nil {
return fmt.Errorf("failed to convert public key to address: error: %w output: %s", err, out.String())
}

var addr api.Address
if err = addr.UnmarshalText(bytes.TrimSpace(out.Bytes())); err != nil {
return err
}

if addr.String() != addressText {
return fmt.Errorf("pubkey2address converted public key %s to address %s (expected address: %s)",
publicKeyText, addr, addressText,
)
}

return nil
}

// testTransfer tests transfer of transferAmount tokens from src to dst.
func (s *stakeCLIImpl) testTransfer(childEnv *env.Env, cli *cli.Helpers, src api.Address, dst api.Address) error {
transferTxPath := filepath.Join(childEnv.Dir(), "stake_transfer.json")
Expand Down

0 comments on commit c1bf3eb

Please sign in to comment.