compiler: check for contract permissions

On many occassions we can determine at compile-time if contract config lacks
some properties it needs. This includes all native contract invocations
through stdlib, as both hashes and methods are known at compile-time
there.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
Evgeniy Stratonikov 2021-06-24 18:36:40 +03:00
parent 16a8edaa17
commit 4249674ddc
7 changed files with 261 additions and 36 deletions

View file

@ -43,6 +43,11 @@ type Options struct {
// This setting has effect only if manifest is emitted.
NoStandardCheck bool
// NoPermissionsCheck specifies if permissions in YAML config need to be checked
// against invocations performed by the contract.
// This setting has effect only if manifest is emitted.
NoPermissionsCheck bool
// Name is contract's name to be written to manifest.
Name string
@ -291,5 +296,31 @@ func CreateManifest(di *DebugInfo, o *Options) (*manifest.Manifest, error) {
}
}
}
if !o.NoPermissionsCheck {
// We can't perform full check for 2 reasons:
// 1. Contract hash may not be available at compile time.
// 2. Permission may be specified for a group of contracts by public key.
// Thus only basic checks are performed.
for h, methods := range di.InvokedContracts {
methodLoop:
for _, m := range methods {
for _, p := range o.Permissions {
// Group or wildcard permission is ok to try.
if p.Contract.Type == manifest.PermissionHash && !p.Contract.Hash().Equals(h) {
continue
}
if p.Methods.Contains(m) {
continue methodLoop
}
}
return nil, fmt.Errorf("method '%s' of contract %s is invoked but"+
" corresponding permission is missing", m, h.StringLE())
}
}
}
return m, nil
}