forked from TrueCloudLab/neoneo-go
contract: avoid going to the DB for entry scripts
This optimizes out DB access for non-deployed contracts under the assumption that deployed ones are always loaded via `LoadScriptWithHash` (and if they're not --- it's a bug anyway with the new hashing model) which actually is a very popular case (every entry script does that).
This commit is contained in:
parent
49f6b33eae
commit
d93aa745bb
4 changed files with 22 additions and 7 deletions
|
@ -46,10 +46,13 @@ func callExInternal(ic *interop.Context, h []byte, name string, args []stackitem
|
|||
if strings.HasPrefix(name, "_") {
|
||||
return errors.New("invalid method name (starts with '_')")
|
||||
}
|
||||
curr, err := ic.DAO.GetContractState(ic.VM.GetCurrentScriptHash())
|
||||
if err == nil {
|
||||
if !curr.Manifest.CanCall(u, &cs.Manifest, name) {
|
||||
return errors.New("disallowed method call")
|
||||
ctx := ic.VM.Context()
|
||||
if ctx != nil && ctx.IsDeployed() {
|
||||
curr, err := ic.DAO.GetContractState(ic.VM.GetCurrentScriptHash())
|
||||
if err == nil {
|
||||
if !curr.Manifest.CanCall(u, &cs.Manifest, name) {
|
||||
return errors.New("disallowed method call")
|
||||
}
|
||||
}
|
||||
}
|
||||
return CallExInternal(ic, cs, name, args, f, vm.EnsureNotEmpty, nil)
|
||||
|
|
|
@ -581,7 +581,7 @@ func TestContractCall(t *testing.T) {
|
|||
|
||||
runInvalid := func(args ...interface{}) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
loadScript(ic, currScript, 42)
|
||||
loadScriptWithHashAndFlags(ic, currScript, h, smartcontract.All, 42)
|
||||
for i := range args {
|
||||
ic.VM.Estack().PushVal(args[i])
|
||||
}
|
||||
|
|
|
@ -42,6 +42,9 @@ type Context struct {
|
|||
// Caller's contract script hash.
|
||||
callingScriptHash util.Uint160
|
||||
|
||||
// Set to true when running deployed contracts.
|
||||
isDeployed bool
|
||||
|
||||
// Call flags this context was created with.
|
||||
callFlag smartcontract.CallFlag
|
||||
|
||||
|
@ -256,6 +259,11 @@ func (c *Context) String() string {
|
|||
return "execution context"
|
||||
}
|
||||
|
||||
// IsDeployed returns whether this context contains deployed contract.
|
||||
func (c *Context) IsDeployed() bool {
|
||||
return c.isDeployed
|
||||
}
|
||||
|
||||
// getContextScriptHash returns script hash of the invocation stack element
|
||||
// number n.
|
||||
func (v *VM) getContextScriptHash(n int) util.Uint160 {
|
||||
|
|
|
@ -284,12 +284,16 @@ func (v *VM) LoadScriptWithFlags(b []byte, f smartcontract.CallFlag) {
|
|||
}
|
||||
|
||||
// LoadScriptWithHash if similar to the LoadScriptWithFlags method, but it also loads
|
||||
// given script hash directly into the Context to avoid its recalculations. It's
|
||||
// up to user of this function to make sure the script and hash match each other.
|
||||
// given script hash directly into the Context to avoid its recalculations and to make
|
||||
// is possible to override it for deployed contracts with special hashes (the function
|
||||
// assumes that it is used for deployed contracts setting context's parameters
|
||||
// accordingly). It's up to user of this function to make sure the script and hash match
|
||||
// each other.
|
||||
func (v *VM) LoadScriptWithHash(b []byte, hash util.Uint160, f smartcontract.CallFlag) {
|
||||
shash := v.GetCurrentScriptHash()
|
||||
v.LoadScriptWithFlags(b, f)
|
||||
ctx := v.Context()
|
||||
ctx.isDeployed = true
|
||||
ctx.scriptHash = hash
|
||||
ctx.callingScriptHash = shash
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue