forked from TrueCloudLab/neoneo-go
Merge pull request #1973 from nspcc-dev/custom-contracts
cli: allow to specify CustomContracts/Groups signer
This commit is contained in:
commit
1a16068b0a
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/cli/flags"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"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/encoding/address"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
|
@ -53,11 +54,52 @@ func parseCosigner(c string) (transaction.Signer, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
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 {
|
if err != nil {
|
||||||
return transaction.Signer{}, err
|
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
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package cmdargs
|
package cmdargs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"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/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/smartcontract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -12,6 +15,10 @@ import (
|
||||||
|
|
||||||
func TestParseCosigner(t *testing.T) {
|
func TestParseCosigner(t *testing.T) {
|
||||||
acc := util.Uint160{1, 3, 5, 7}
|
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{
|
testCases := map[string]transaction.Signer{
|
||||||
acc.StringLE(): {
|
acc.StringLE(): {
|
||||||
Account: acc,
|
Account: acc,
|
||||||
|
@ -33,25 +40,36 @@ func TestParseCosigner(t *testing.T) {
|
||||||
Account: acc,
|
Account: acc,
|
||||||
Scopes: transaction.None,
|
Scopes: transaction.None,
|
||||||
},
|
},
|
||||||
acc.StringLE() + ":CalledByEntry,CustomContracts": {
|
acc.StringLE() + ":CalledByEntry,CustomContracts:" + c1.StringLE() + ":0x" + c2.StringLE(): {
|
||||||
Account: acc,
|
Account: acc,
|
||||||
Scopes: transaction.CalledByEntry | transaction.CustomContracts,
|
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 {
|
for s, expected := range testCases {
|
||||||
actual, err := parseCosigner(s)
|
actual, err := parseCosigner(s)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, expected, actual)
|
require.Equal(t, expected, actual, s)
|
||||||
}
|
}
|
||||||
errorCases := []string{
|
errorCases := []string{
|
||||||
acc.StringLE() + "0",
|
acc.StringLE() + "0",
|
||||||
acc.StringLE() + ":Unknown",
|
acc.StringLE() + ":Unknown",
|
||||||
acc.StringLE() + ":Global,CustomContracts",
|
acc.StringLE() + ":Global,CustomContracts",
|
||||||
acc.StringLE() + ":Global,None",
|
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 {
|
for _, s := range errorCases {
|
||||||
_, err := parseCosigner(s)
|
_, 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
|
entering deeper internal invokes. This can be default
|
||||||
safe choice for native NEO/GAS.
|
safe choice for native NEO/GAS.
|
||||||
- 'CustomContracts' - define valid custom contract hashes for witness check.
|
- '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
|
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
|
specified, no array is passed. Note that scopes are properly handled by
|
||||||
|
@ -287,7 +293,10 @@ func NewCommands() []cli.Command {
|
||||||
* 'NNQk4QXsxvsrr3GSozoWBUxEmfag7B6hz5'
|
* 'NNQk4QXsxvsrr3GSozoWBUxEmfag7B6hz5'
|
||||||
* 'NVquyZHoPirw6zAEPvY1ZezxM493zMWQqs:Global'
|
* 'NVquyZHoPirw6zAEPvY1ZezxM493zMWQqs:Global'
|
||||||
* '0x0000000009070e030d0f0e020d0c06050e030c02'
|
* '0x0000000009070e030d0f0e020d0c06050e030c02'
|
||||||
* '0000000009070e030d0f0e020d0c06050e030c02:CalledByEntry,CustomGroups'
|
* '0000000009070e030d0f0e020d0c06050e030c02:CalledByEntry,` +
|
||||||
|
`CustomGroups:0206d7495ceb34c197093b5fc1cccf1996ada05e69ef67e765462a7f5d88ee14d0'
|
||||||
|
* '0000000009070e030d0f0e020d0c06050e030c02:CalledByEntry,` +
|
||||||
|
`CustomContracts:1011120009070e030d0f0e020d0c06050e030c02:0x1211100009070e030d0f0e020d0c06050e030c02'
|
||||||
`,
|
`,
|
||||||
Action: testInvokeFunction,
|
Action: testInvokeFunction,
|
||||||
Flags: options.RPC,
|
Flags: options.RPC,
|
||||||
|
|
Loading…
Reference in a new issue