forked from TrueCloudLab/neoneo-go
cli: add tests for multisig sign
This test is also a good example of how to create and sign multisig transaction from scratch.
This commit is contained in:
parent
9817da7c4e
commit
6e5a637da9
5 changed files with 118 additions and 41 deletions
|
@ -6,6 +6,7 @@ import (
|
|||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -19,6 +20,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/network"
|
||||
"github.com/nspcc-dev/neo-go/pkg/rpc/server"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/urfave/cli"
|
||||
"go.uber.org/zap"
|
||||
|
@ -177,3 +179,29 @@ func (e *executor) run(args ...string) error {
|
|||
e.Err.Reset()
|
||||
return e.CLI.Run(args)
|
||||
}
|
||||
|
||||
func (e *executor) checkTxPersisted(t *testing.T) {
|
||||
line, err := e.Out.ReadString('\n')
|
||||
require.NoError(t, err)
|
||||
|
||||
line = strings.TrimSpace(line)
|
||||
h, err := util.Uint256DecodeStringLE(line)
|
||||
require.NoError(t, err, "can't decode tx hash: %s", line)
|
||||
|
||||
tx := e.GetTransaction(t, h)
|
||||
aer, err := e.Chain.GetAppExecResult(tx.Hash())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, vm.HaltState, aer.VMState)
|
||||
}
|
||||
|
||||
func generateKeys(t *testing.T, n int) ([]*keys.PrivateKey, keys.PublicKeys) {
|
||||
privs := make([]*keys.PrivateKey, n)
|
||||
pubs := make(keys.PublicKeys, n)
|
||||
for i := range privs {
|
||||
var err error
|
||||
privs[i], err = keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
pubs[i] = privs[i].PublicKey()
|
||||
}
|
||||
return privs, pubs
|
||||
}
|
||||
|
|
85
cli/multisig_test.go
Normal file
85
cli/multisig_test.go
Normal file
|
@ -0,0 +1,85 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||
"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/smartcontract"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// Test signing of multisig transactions.
|
||||
// 1. Transfer funds to a created multisig address.
|
||||
// 2. Transfer from multisig to another account.
|
||||
func TestSignMultisigTx(t *testing.T) {
|
||||
e := newExecutor(t, true)
|
||||
defer e.Close(t)
|
||||
|
||||
privs, pubs := generateKeys(t, 3)
|
||||
script, err := smartcontract.CreateMultiSigRedeemScript(2, pubs)
|
||||
require.NoError(t, err)
|
||||
multisigHash := hash.Hash160(script)
|
||||
multisigAddr := address.Uint160ToString(multisigHash)
|
||||
|
||||
// Create 2 wallets participating in multisig.
|
||||
tmpDir := os.TempDir()
|
||||
wallet1Path := path.Join(tmpDir, "multiWallet1.json")
|
||||
defer os.Remove(wallet1Path)
|
||||
wallet2Path := path.Join(tmpDir, "multiWallet2.json")
|
||||
defer os.Remove(wallet2Path)
|
||||
|
||||
addAccount := func(w string, wif string) {
|
||||
e.In.WriteString("acc\rpass\rpass\r")
|
||||
e.Run(t, "neo-go", "wallet", "init", "--wallet", w)
|
||||
e.Run(t, "neo-go", "wallet", "import-multisig",
|
||||
"--wallet", w,
|
||||
"--wif", wif,
|
||||
"--min", "2",
|
||||
hex.EncodeToString(pubs[0].Bytes()),
|
||||
hex.EncodeToString(pubs[1].Bytes()),
|
||||
hex.EncodeToString(pubs[2].Bytes()))
|
||||
}
|
||||
addAccount(wallet1Path, privs[0].WIF())
|
||||
addAccount(wallet2Path, privs[1].WIF())
|
||||
|
||||
// Transfer funds to the multisig.
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, "neo-go", "wallet", "nep5", "multitransfer",
|
||||
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
|
||||
"--wallet", validatorWallet,
|
||||
"--from", validatorAddr,
|
||||
"neo:"+multisigAddr+":4",
|
||||
"gas:"+multisigAddr+":1")
|
||||
e.checkTxPersisted(t)
|
||||
|
||||
// Sign and transfer funds to another account.
|
||||
priv, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
txPath := path.Join(tmpDir, "multisigtx.json")
|
||||
defer os.Remove(txPath)
|
||||
e.In.WriteString("pass\r")
|
||||
e.Run(t, "neo-go", "wallet", "nep5", "transfer",
|
||||
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
|
||||
"--wallet", wallet1Path, "--from", multisigAddr,
|
||||
"--to", priv.Address(), "--token", "neo", "--amount", "1",
|
||||
"--out", txPath)
|
||||
|
||||
e.In.WriteString("pass\r")
|
||||
e.Run(t, "neo-go", "wallet", "multisig", "sign",
|
||||
"--unittest", "--rpc-endpoint", "http://"+e.RPC.Addr,
|
||||
"--wallet", wallet2Path, "--addr", multisigAddr,
|
||||
"--in", txPath, "--out", txPath)
|
||||
e.checkTxPersisted(t)
|
||||
|
||||
b, _ := e.Chain.GetGoverningTokenBalance(priv.GetScriptHash())
|
||||
require.Equal(t, big.NewInt(1), b)
|
||||
b, _ = e.Chain.GetGoverningTokenBalance(multisigHash)
|
||||
require.Equal(t, big.NewInt(3), b)
|
||||
}
|
|
@ -6,14 +6,11 @@ import (
|
|||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"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/rpc/client"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -82,15 +79,7 @@ func TestNEP5Transfer(t *testing.T) {
|
|||
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, args...)
|
||||
line, err := e.Out.ReadString('\n')
|
||||
require.NoError(t, err)
|
||||
h, err := util.Uint256DecodeStringLE(strings.TrimSpace(line))
|
||||
require.NoError(t, err, "can't decode tx hash: %s", line)
|
||||
|
||||
tx := e.GetTransaction(t, h)
|
||||
aer, err := e.Chain.GetAppExecResult(tx.Hash())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, vm.HaltState, aer.VMState)
|
||||
e.checkTxPersisted(t)
|
||||
|
||||
sh, err := address.StringToUint160(w.Accounts[0].Address)
|
||||
require.NoError(t, err)
|
||||
|
@ -99,12 +88,7 @@ func TestNEP5Transfer(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestNEP5MultiTransfer(t *testing.T) {
|
||||
privs := make([]*keys.PrivateKey, 3)
|
||||
for i := range privs {
|
||||
var err error
|
||||
privs[i], err = keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
privs, _ := generateKeys(t, 3)
|
||||
|
||||
e := newExecutor(t, true)
|
||||
defer e.Close(t)
|
||||
|
@ -120,15 +104,7 @@ func TestNEP5MultiTransfer(t *testing.T) {
|
|||
|
||||
e.In.WriteString("one\r")
|
||||
e.Run(t, args...)
|
||||
line, err := e.Out.ReadString('\n')
|
||||
require.NoError(t, err)
|
||||
h, err := util.Uint256DecodeStringLE(strings.TrimSpace(line))
|
||||
require.NoError(t, err, "can't decode tx hash: %s", line)
|
||||
|
||||
tx := e.GetTransaction(t, h)
|
||||
aer, err := e.Chain.GetAppExecResult(tx.Hash())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, vm.HaltState, aer.VMState)
|
||||
e.checkTxPersisted(t)
|
||||
|
||||
b, _ := e.Chain.GetGoverningTokenBalance(privs[0].GetScriptHash())
|
||||
require.Equal(t, big.NewInt(42), b)
|
||||
|
|
|
@ -3,7 +3,6 @@ package wallet
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/cli/options"
|
||||
|
@ -60,7 +59,7 @@ func signMultisig(ctx *cli.Context) error {
|
|||
if !ok {
|
||||
return cli.NewExitError("verifiable item is not a transaction", 1)
|
||||
}
|
||||
printTxInfo(ctx.App.Writer, tx)
|
||||
fmt.Fprintln(ctx.App.Writer, tx.Hash().StringLE())
|
||||
|
||||
priv := acc.PrivateKey()
|
||||
sign := priv.Sign(tx.GetSignedPart())
|
||||
|
@ -116,7 +115,3 @@ func writeParameterContext(c *context.ParameterContext, filename string) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func printTxInfo(w io.Writer, t *transaction.Transaction) {
|
||||
fmt.Fprintf(w, "Hash: %s\n", t.Hash().StringLE())
|
||||
}
|
||||
|
|
|
@ -98,14 +98,7 @@ func TestWalletInit(t *testing.T) {
|
|||
require.NoError(t, actual.Decrypt("somepass"))
|
||||
})
|
||||
t.Run("Multisig", func(t *testing.T) {
|
||||
privs := make([]*keys.PrivateKey, 4)
|
||||
pubs := make(keys.PublicKeys, 4)
|
||||
for i := range privs {
|
||||
var err error
|
||||
privs[i], err = keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
pubs[i] = privs[i].PublicKey()
|
||||
}
|
||||
privs, pubs := generateKeys(t, 4)
|
||||
|
||||
cmd := []string{"neo-go", "wallet", "import-multisig",
|
||||
"--wallet", walletPath,
|
||||
|
|
Loading…
Reference in a new issue