forked from TrueCloudLab/neoneo-go
cli: allow to specify CustomContracts/Groups signer
The syntax is `CalledByEntry,CustomContracts:hash1:hash2`.
This commit is contained in:
parent
93a331818e
commit
e3e0e2a8a8
3 changed files with 78 additions and 9 deletions
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neo-go/cli/flags"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"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/smartcontract"
|
||||
|
@ -53,11 +54,52 @@ func parseCosigner(c string) (transaction.Signer, error) {
|
|||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if len(data) > 1 {
|
||||
res.Scopes, err = transaction.ScopesFromString(data[1])
|
||||
|
||||
if len(data) == 1 {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
res.Scopes = 0
|
||||
scopes := strings.Split(data[1], ",")
|
||||
for _, s := range scopes {
|
||||
sub := strings.Split(s, ":")
|
||||
scope, err := transaction.ScopesFromString(sub[0])
|
||||
if err != nil {
|
||||
return transaction.Signer{}, err
|
||||
}
|
||||
if scope == transaction.Global && res.Scopes&^transaction.Global != 0 ||
|
||||
scope != transaction.Global && res.Scopes&transaction.Global != 0 {
|
||||
return transaction.Signer{}, errors.New("Global scope can not be combined with other scopes")
|
||||
}
|
||||
|
||||
res.Scopes |= scope
|
||||
|
||||
switch scope {
|
||||
case transaction.CustomContracts:
|
||||
if len(sub) == 1 {
|
||||
return transaction.Signer{}, errors.New("CustomContracts scope must refer to at least one contract")
|
||||
}
|
||||
for _, s := range sub[1:] {
|
||||
addr, err := flags.ParseAddress(s)
|
||||
if err != nil {
|
||||
return transaction.Signer{}, err
|
||||
}
|
||||
|
||||
res.AllowedContracts = append(res.AllowedContracts, addr)
|
||||
}
|
||||
case transaction.CustomGroups:
|
||||
if len(sub) == 1 {
|
||||
return transaction.Signer{}, errors.New("CustomGroups scope must refer to at least one group")
|
||||
}
|
||||
for _, s := range sub[1:] {
|
||||
pub, err := keys.NewPublicKeyFromString(s)
|
||||
if err != nil {
|
||||
return transaction.Signer{}, err
|
||||
}
|
||||
|
||||
res.AllowedGroups = append(res.AllowedGroups, pub)
|
||||
}
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package cmdargs
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/internal/random"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -12,6 +15,10 @@ import (
|
|||
|
||||
func TestParseCosigner(t *testing.T) {
|
||||
acc := util.Uint160{1, 3, 5, 7}
|
||||
c1, c2 := random.Uint160(), random.Uint160()
|
||||
priv, err := keys.NewPrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := map[string]transaction.Signer{
|
||||
acc.StringLE(): {
|
||||
Account: acc,
|
||||
|
@ -33,25 +40,36 @@ func TestParseCosigner(t *testing.T) {
|
|||
Account: acc,
|
||||
Scopes: transaction.None,
|
||||
},
|
||||
acc.StringLE() + ":CalledByEntry,CustomContracts": {
|
||||
Account: acc,
|
||||
Scopes: transaction.CalledByEntry | transaction.CustomContracts,
|
||||
acc.StringLE() + ":CalledByEntry,CustomContracts:" + c1.StringLE() + ":0x" + c2.StringLE(): {
|
||||
Account: acc,
|
||||
Scopes: transaction.CalledByEntry | transaction.CustomContracts,
|
||||
AllowedContracts: []util.Uint160{c1, c2},
|
||||
},
|
||||
acc.StringLE() + ":CustomGroups:" + hex.EncodeToString(priv.PublicKey().Bytes()): {
|
||||
Account: acc,
|
||||
Scopes: transaction.CustomGroups,
|
||||
AllowedGroups: keys.PublicKeys{priv.PublicKey()},
|
||||
},
|
||||
}
|
||||
for s, expected := range testCases {
|
||||
actual, err := parseCosigner(s)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expected, actual)
|
||||
require.Equal(t, expected, actual, s)
|
||||
}
|
||||
errorCases := []string{
|
||||
acc.StringLE() + "0",
|
||||
acc.StringLE() + ":Unknown",
|
||||
acc.StringLE() + ":Global,CustomContracts",
|
||||
acc.StringLE() + ":Global,None",
|
||||
acc.StringLE() + ":CustomContracts:" + acc.StringLE() + ",Global",
|
||||
acc.StringLE() + ":CustomContracts",
|
||||
acc.StringLE() + ":CustomContracts:xxx",
|
||||
acc.StringLE() + ":CustomGroups",
|
||||
acc.StringLE() + ":CustomGroups:xxx",
|
||||
}
|
||||
for _, s := range errorCases {
|
||||
_, err := parseCosigner(s)
|
||||
require.Error(t, err)
|
||||
require.Error(t, err, s)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -277,7 +277,13 @@ func NewCommands() []cli.Command {
|
|||
entering deeper internal invokes. This can be default
|
||||
safe choice for native NEO/GAS.
|
||||
- 'CustomContracts' - define valid custom contract hashes for witness check.
|
||||
- 'CustomGroups' - define custom pubkey for group members.
|
||||
Hashes are be provided as hex-encoded LE value string.
|
||||
At lest one hash must be provided. Multiple hashes
|
||||
are separated by ':'.
|
||||
- 'CustomGroups' - define custom public keys for group members. Public keys are
|
||||
provided as short-form (1-byte prefix + 32 bytes) hex-encoded
|
||||
values. At least one key must be provided. Multiple keys
|
||||
are separated by ':'.
|
||||
|
||||
If no scopes were specified, 'CalledByEntry' used as default. If no signers were
|
||||
specified, no array is passed. Note that scopes are properly handled by
|
||||
|
@ -287,7 +293,10 @@ func NewCommands() []cli.Command {
|
|||
* 'NNQk4QXsxvsrr3GSozoWBUxEmfag7B6hz5'
|
||||
* 'NVquyZHoPirw6zAEPvY1ZezxM493zMWQqs:Global'
|
||||
* '0x0000000009070e030d0f0e020d0c06050e030c02'
|
||||
* '0000000009070e030d0f0e020d0c06050e030c02:CalledByEntry,CustomGroups'
|
||||
* '0000000009070e030d0f0e020d0c06050e030c02:CalledByEntry,` +
|
||||
`CustomGroups:0206d7495ceb34c197093b5fc1cccf1996ada05e69ef67e765462a7f5d88ee14d0'
|
||||
* '0000000009070e030d0f0e020d0c06050e030c02:CalledByEntry,` +
|
||||
`CustomContracts:1011120009070e030d0f0e020d0c06050e030c02:0x1211100009070e030d0f0e020d0c06050e030c02'
|
||||
`,
|
||||
Action: testInvokeFunction,
|
||||
Flags: options.RPC,
|
||||
|
|
Loading…
Reference in a new issue