core: do not check manifest size on deploy/update
Manifest will be a part of the state.Contract which will be checked on its way to the storage. Tiny optimisation which allows not to serialize manifest twice. Ref. https://github.com/nspcc-dev/neo-go/pull/3218#discussion_r1402374232. Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
This commit is contained in:
parent
1d189fd90c
commit
910d53b27b
5 changed files with 25 additions and 22 deletions
|
@ -109,7 +109,7 @@ func readManifest(filename string, hash util.Uint160) (*manifest.Manifest, []byt
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if err := m.IsValid(hash); err != nil {
|
if err := m.IsValid(hash, true); err != nil {
|
||||||
return nil, nil, fmt.Errorf("manifest is invalid: %w", err)
|
return nil, nil, fmt.Errorf("manifest is invalid: %w", err)
|
||||||
}
|
}
|
||||||
return m, manifestBytes, nil
|
return m, manifestBytes, nil
|
||||||
|
|
|
@ -447,7 +447,7 @@ func CreateManifest(di *DebugInfo, o *Options) (*manifest.Manifest, error) {
|
||||||
return m, fmt.Errorf("method %s is marked as safe but missing from manifest", name)
|
return m, fmt.Errorf("method %s is marked as safe but missing from manifest", name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = m.IsValid(util.Uint160{}) // Check as much as possible without hash.
|
err = m.IsValid(util.Uint160{}, true) // Check as much as possible without hash.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return m, fmt.Errorf("manifest is invalid: %w", err)
|
return m, fmt.Errorf("manifest is invalid: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -389,7 +389,7 @@ func (m *Management) Deploy(ic *interop.Context, sender util.Uint160, neff *nef.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = manif.IsValid(h)
|
err = manif.IsValid(h, false) // do not check manifest size, the whole state.Contract will be checked later.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid manifest: %w", err)
|
return nil, fmt.Errorf("invalid manifest: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -458,7 +458,7 @@ func (m *Management) Update(ic *interop.Context, hash util.Uint160, neff *nef.Fi
|
||||||
if manif.Name != contract.Manifest.Name {
|
if manif.Name != contract.Manifest.Name {
|
||||||
return nil, errors.New("contract name can't be changed")
|
return nil, errors.New("contract name can't be changed")
|
||||||
}
|
}
|
||||||
err = manif.IsValid(contract.Hash)
|
err = manif.IsValid(contract.Hash, false) // do not check manifest size, the whole state.Contract will be checked later.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid manifest: %w", err)
|
return nil, fmt.Errorf("invalid manifest: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ func (m *Manifest) CanCall(hash util.Uint160, toCall *Manifest, method string) b
|
||||||
// IsValid checks manifest internal consistency and correctness, one of the
|
// IsValid checks manifest internal consistency and correctness, one of the
|
||||||
// checks is for group signature correctness, contract hash is passed for it.
|
// checks is for group signature correctness, contract hash is passed for it.
|
||||||
// If hash is empty, then hash-related checks are omitted.
|
// If hash is empty, then hash-related checks are omitted.
|
||||||
func (m *Manifest) IsValid(hash util.Uint160) error {
|
func (m *Manifest) IsValid(hash util.Uint160, checkSize bool) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if m.Name == "" {
|
if m.Name == "" {
|
||||||
|
@ -122,6 +122,9 @@ func (m *Manifest) IsValid(hash util.Uint160) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if !checkSize {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
si, err := m.ToStackItem()
|
si, err := m.ToStackItem()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to check manifest serialisation: %w", err)
|
return fmt.Errorf("failed to check manifest serialisation: %w", err)
|
||||||
|
|
|
@ -125,13 +125,13 @@ func TestIsValid(t *testing.T) {
|
||||||
m := &Manifest{}
|
m := &Manifest{}
|
||||||
|
|
||||||
t.Run("invalid, no name", func(t *testing.T) {
|
t.Run("invalid, no name", func(t *testing.T) {
|
||||||
require.Error(t, m.IsValid(contractHash))
|
require.Error(t, m.IsValid(contractHash, true))
|
||||||
})
|
})
|
||||||
|
|
||||||
m = NewManifest("Test")
|
m = NewManifest("Test")
|
||||||
|
|
||||||
t.Run("invalid, no ABI methods", func(t *testing.T) {
|
t.Run("invalid, no ABI methods", func(t *testing.T) {
|
||||||
require.Error(t, m.IsValid(contractHash))
|
require.Error(t, m.IsValid(contractHash, true))
|
||||||
})
|
})
|
||||||
|
|
||||||
m.ABI.Methods = append(m.ABI.Methods, Method{
|
m.ABI.Methods = append(m.ABI.Methods, Method{
|
||||||
|
@ -141,7 +141,7 @@ func TestIsValid(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("valid, no groups/events", func(t *testing.T) {
|
t.Run("valid, no groups/events", func(t *testing.T) {
|
||||||
require.NoError(t, m.IsValid(contractHash))
|
require.NoError(t, m.IsValid(contractHash, true))
|
||||||
})
|
})
|
||||||
|
|
||||||
m.ABI.Events = append(m.ABI.Events, Event{
|
m.ABI.Events = append(m.ABI.Events, Event{
|
||||||
|
@ -150,7 +150,7 @@ func TestIsValid(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("valid, with events", func(t *testing.T) {
|
t.Run("valid, with events", func(t *testing.T) {
|
||||||
require.NoError(t, m.IsValid(contractHash))
|
require.NoError(t, m.IsValid(contractHash, true))
|
||||||
})
|
})
|
||||||
|
|
||||||
m.ABI.Events = append(m.ABI.Events, Event{
|
m.ABI.Events = append(m.ABI.Events, Event{
|
||||||
|
@ -162,52 +162,52 @@ func TestIsValid(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("invalid, bad event", func(t *testing.T) {
|
t.Run("invalid, bad event", func(t *testing.T) {
|
||||||
require.Error(t, m.IsValid(contractHash))
|
require.Error(t, m.IsValid(contractHash, true))
|
||||||
})
|
})
|
||||||
m.ABI.Events = m.ABI.Events[:1]
|
m.ABI.Events = m.ABI.Events[:1]
|
||||||
|
|
||||||
m.Permissions = append(m.Permissions, *NewPermission(PermissionHash, util.Uint160{1, 2, 3}))
|
m.Permissions = append(m.Permissions, *NewPermission(PermissionHash, util.Uint160{1, 2, 3}))
|
||||||
t.Run("valid, with permissions", func(t *testing.T) {
|
t.Run("valid, with permissions", func(t *testing.T) {
|
||||||
require.NoError(t, m.IsValid(contractHash))
|
require.NoError(t, m.IsValid(contractHash, true))
|
||||||
})
|
})
|
||||||
|
|
||||||
m.Permissions = append(m.Permissions, *NewPermission(PermissionHash, util.Uint160{1, 2, 3}))
|
m.Permissions = append(m.Permissions, *NewPermission(PermissionHash, util.Uint160{1, 2, 3}))
|
||||||
t.Run("invalid, with permissions", func(t *testing.T) {
|
t.Run("invalid, with permissions", func(t *testing.T) {
|
||||||
require.Error(t, m.IsValid(contractHash))
|
require.Error(t, m.IsValid(contractHash, true))
|
||||||
})
|
})
|
||||||
m.Permissions = m.Permissions[:1]
|
m.Permissions = m.Permissions[:1]
|
||||||
|
|
||||||
m.SupportedStandards = append(m.SupportedStandards, "NEP-17")
|
m.SupportedStandards = append(m.SupportedStandards, "NEP-17")
|
||||||
t.Run("valid, with standards", func(t *testing.T) {
|
t.Run("valid, with standards", func(t *testing.T) {
|
||||||
require.NoError(t, m.IsValid(contractHash))
|
require.NoError(t, m.IsValid(contractHash, true))
|
||||||
})
|
})
|
||||||
|
|
||||||
m.SupportedStandards = append(m.SupportedStandards, "")
|
m.SupportedStandards = append(m.SupportedStandards, "")
|
||||||
t.Run("invalid, with nameless standard", func(t *testing.T) {
|
t.Run("invalid, with nameless standard", func(t *testing.T) {
|
||||||
require.Error(t, m.IsValid(contractHash))
|
require.Error(t, m.IsValid(contractHash, true))
|
||||||
})
|
})
|
||||||
m.SupportedStandards = m.SupportedStandards[:1]
|
m.SupportedStandards = m.SupportedStandards[:1]
|
||||||
|
|
||||||
m.SupportedStandards = append(m.SupportedStandards, "NEP-17")
|
m.SupportedStandards = append(m.SupportedStandards, "NEP-17")
|
||||||
t.Run("invalid, with duplicate standards", func(t *testing.T) {
|
t.Run("invalid, with duplicate standards", func(t *testing.T) {
|
||||||
require.Error(t, m.IsValid(contractHash))
|
require.Error(t, m.IsValid(contractHash, true))
|
||||||
})
|
})
|
||||||
m.SupportedStandards = m.SupportedStandards[:1]
|
m.SupportedStandards = m.SupportedStandards[:1]
|
||||||
|
|
||||||
d := PermissionDesc{Type: PermissionHash, Value: util.Uint160{1, 2, 3}}
|
d := PermissionDesc{Type: PermissionHash, Value: util.Uint160{1, 2, 3}}
|
||||||
m.Trusts.Add(d)
|
m.Trusts.Add(d)
|
||||||
t.Run("valid, with trust", func(t *testing.T) {
|
t.Run("valid, with trust", func(t *testing.T) {
|
||||||
require.NoError(t, m.IsValid(contractHash))
|
require.NoError(t, m.IsValid(contractHash, true))
|
||||||
})
|
})
|
||||||
|
|
||||||
m.Trusts.Add(PermissionDesc{Type: PermissionHash, Value: util.Uint160{3, 2, 1}})
|
m.Trusts.Add(PermissionDesc{Type: PermissionHash, Value: util.Uint160{3, 2, 1}})
|
||||||
t.Run("valid, with trusts", func(t *testing.T) {
|
t.Run("valid, with trusts", func(t *testing.T) {
|
||||||
require.NoError(t, m.IsValid(contractHash))
|
require.NoError(t, m.IsValid(contractHash, true))
|
||||||
})
|
})
|
||||||
|
|
||||||
m.Trusts.Add(d)
|
m.Trusts.Add(d)
|
||||||
t.Run("invalid, with trusts", func(t *testing.T) {
|
t.Run("invalid, with trusts", func(t *testing.T) {
|
||||||
require.Error(t, m.IsValid(contractHash))
|
require.Error(t, m.IsValid(contractHash, true))
|
||||||
})
|
})
|
||||||
m.Trusts.Restrict()
|
m.Trusts.Restrict()
|
||||||
|
|
||||||
|
@ -225,11 +225,11 @@ func TestIsValid(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("valid", func(t *testing.T) {
|
t.Run("valid", func(t *testing.T) {
|
||||||
require.NoError(t, m.IsValid(contractHash))
|
require.NoError(t, m.IsValid(contractHash, true))
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("invalid, wrong contract hash", func(t *testing.T) {
|
t.Run("invalid, wrong contract hash", func(t *testing.T) {
|
||||||
require.Error(t, m.IsValid(util.Uint160{4, 5, 6}))
|
require.Error(t, m.IsValid(util.Uint160{4, 5, 6}, true))
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("invalid, wrong group signature", func(t *testing.T) {
|
t.Run("invalid, wrong group signature", func(t *testing.T) {
|
||||||
|
@ -241,7 +241,7 @@ func TestIsValid(t *testing.T) {
|
||||||
// of the contract hash.
|
// of the contract hash.
|
||||||
Signature: pk.Sign([]byte{1, 2, 3}),
|
Signature: pk.Sign([]byte{1, 2, 3}),
|
||||||
})
|
})
|
||||||
require.Error(t, m.IsValid(contractHash))
|
require.Error(t, m.IsValid(contractHash, true))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
m.Groups = m.Groups[:0]
|
m.Groups = m.Groups[:0]
|
||||||
|
@ -253,7 +253,7 @@ func TestIsValid(t *testing.T) {
|
||||||
Parameters: []Parameter{},
|
Parameters: []Parameter{},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
err := m.IsValid(contractHash)
|
err := m.IsValid(contractHash, true)
|
||||||
require.ErrorIs(t, err, stackitem.ErrTooBig)
|
require.ErrorIs(t, err, stackitem.ErrTooBig)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue