cli: support voting

Closes #1206.
This commit is contained in:
Evgenii Stratonikov 2020-08-04 12:35:04 +03:00
parent a3f419f8df
commit 05c24d9401
2 changed files with 93 additions and 1 deletions

View file

@ -13,7 +13,11 @@ import (
"github.com/nspcc-dev/neo-go/cli/options" "github.com/nspcc-dev/neo-go/cli/options"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/urfave/cli" "github.com/urfave/cli"
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
@ -186,6 +190,24 @@ func NewCommands() []cli.Command {
Usage: "work with NEP5 contracts", Usage: "work with NEP5 contracts",
Subcommands: newNEP5Commands(), Subcommands: newNEP5Commands(),
}, },
{
Name: "vote",
Usage: "vote for a validator",
UsageText: "vote -w <path> -r <rpc> [-t <timeout>] [-g gas] -a <addr> -k <public key>",
Action: handleVote,
Flags: append([]cli.Flag{
walletPathFlag,
gasFlag,
flags.AddressFlag{
Name: "addr, a",
Usage: "Address to vote from",
},
cli.StringFlag{
Name: "key, k",
Usage: "Public key of candidate to vote for",
},
}, options.RPC...),
},
}, },
}} }}
} }
@ -513,6 +535,69 @@ func createWallet(ctx *cli.Context) error {
return nil return nil
} }
func handleVote(ctx *cli.Context) error {
wall, err := openWallet(ctx.String("wallet"))
if err != nil {
return cli.NewExitError(err, 1)
}
addrFlag := ctx.Generic("addr").(*flags.Address)
addr := addrFlag.Uint160()
acc := wall.GetAccount(addr)
if acc == nil {
return cli.NewExitError(fmt.Errorf("can't find account for the address: %s", addrFlag), 1)
}
var pub *keys.PublicKey
pubStr := ctx.String("key")
if pubStr != "" {
pub, err = keys.NewPublicKeyFromString(pubStr)
if err != nil {
return cli.NewExitError(fmt.Errorf("invalid public key: '%s'", pubStr), 1)
}
}
gctx, cancel := options.GetTimeoutContext(ctx)
defer cancel()
c, err := options.GetRPCClient(gctx, ctx)
if err != nil {
return err
}
var pubArg interface{}
if pub != nil {
pubArg = pub.Bytes()
}
gas := flags.Fixed8FromContext(ctx, "gas")
w := io.NewBufBinWriter()
emit.AppCallWithOperationAndArgs(w.BinWriter, client.NeoContractHash, "vote", addr.BytesBE(), pubArg)
emit.Opcode(w.BinWriter, opcode.ASSERT)
tx, err := c.CreateTxFromScript(w.Bytes(), acc, int64(gas))
if err != nil {
return cli.NewExitError(err, 1)
}
if pass, err := readPassword("Password > "); err != nil {
return cli.NewExitError(err, 1)
} else if err := acc.Decrypt(pass); err != nil {
return cli.NewExitError(err, 1)
}
if err = acc.SignTx(tx); err != nil {
return cli.NewExitError(fmt.Errorf("can't sign tx: %v", err), 1)
}
res, err := c.SendRawTransaction(tx)
if err != nil {
return cli.NewExitError(err, 1)
}
fmt.Println(res.StringLE())
return nil
}
func readAccountInfo() (string, string, error) { func readAccountInfo() (string, string, error) {
buf := bufio.NewReader(os.Stdin) buf := bufio.NewReader(os.Stdin)
fmt.Print("Enter the name of the account > ") fmt.Print("Enter the name of the account > ")

View file

@ -131,8 +131,15 @@ func (c *Client) CreateNEP5MultiTransferTx(acc *wallet.Account, gas int64, recep
recepients[i].Address, recepients[i].Amount) recepients[i].Address, recepients[i].Amount)
emit.Opcode(w.BinWriter, opcode.ASSERT) emit.Opcode(w.BinWriter, opcode.ASSERT)
} }
return c.CreateTxFromScript(w.Bytes(), acc, gas)
}
script := w.Bytes() // CreateTxFromScript creates transaction and properly sets cosigners and NetworkFee.
func (c *Client) CreateTxFromScript(script []byte, acc *wallet.Account, gas int64) (*transaction.Transaction, error) {
from, err := address.StringToUint160(acc.Address)
if err != nil {
return nil, fmt.Errorf("bad account address: %v", err)
}
result, err := c.InvokeScript(script, []transaction.Signer{ result, err := c.InvokeScript(script, []transaction.Signer{
{ {
Account: from, Account: from,