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, "_") {
|
if strings.HasPrefix(name, "_") {
|
||||||
return errors.New("invalid method name (starts with '_')")
|
return errors.New("invalid method name (starts with '_')")
|
||||||
}
|
}
|
||||||
curr, err := ic.DAO.GetContractState(ic.VM.GetCurrentScriptHash())
|
ctx := ic.VM.Context()
|
||||||
if err == nil {
|
if ctx != nil && ctx.IsDeployed() {
|
||||||
if !curr.Manifest.CanCall(u, &cs.Manifest, name) {
|
curr, err := ic.DAO.GetContractState(ic.VM.GetCurrentScriptHash())
|
||||||
return errors.New("disallowed method call")
|
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)
|
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) {
|
runInvalid := func(args ...interface{}) func(t *testing.T) {
|
||||||
return func(t *testing.T) {
|
return func(t *testing.T) {
|
||||||
loadScript(ic, currScript, 42)
|
loadScriptWithHashAndFlags(ic, currScript, h, smartcontract.All, 42)
|
||||||
for i := range args {
|
for i := range args {
|
||||||
ic.VM.Estack().PushVal(args[i])
|
ic.VM.Estack().PushVal(args[i])
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,9 @@ type Context struct {
|
||||||
// Caller's contract script hash.
|
// Caller's contract script hash.
|
||||||
callingScriptHash util.Uint160
|
callingScriptHash util.Uint160
|
||||||
|
|
||||||
|
// Set to true when running deployed contracts.
|
||||||
|
isDeployed bool
|
||||||
|
|
||||||
// Call flags this context was created with.
|
// Call flags this context was created with.
|
||||||
callFlag smartcontract.CallFlag
|
callFlag smartcontract.CallFlag
|
||||||
|
|
||||||
|
@ -256,6 +259,11 @@ func (c *Context) String() string {
|
||||||
return "execution context"
|
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
|
// getContextScriptHash returns script hash of the invocation stack element
|
||||||
// number n.
|
// number n.
|
||||||
func (v *VM) getContextScriptHash(n int) util.Uint160 {
|
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
|
// LoadScriptWithHash if similar to the LoadScriptWithFlags method, but it also loads
|
||||||
// given script hash directly into the Context to avoid its recalculations. It's
|
// given script hash directly into the Context to avoid its recalculations and to make
|
||||||
// up to user of this function to make sure the script and hash match each other.
|
// 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) {
|
func (v *VM) LoadScriptWithHash(b []byte, hash util.Uint160, f smartcontract.CallFlag) {
|
||||||
shash := v.GetCurrentScriptHash()
|
shash := v.GetCurrentScriptHash()
|
||||||
v.LoadScriptWithFlags(b, f)
|
v.LoadScriptWithFlags(b, f)
|
||||||
ctx := v.Context()
|
ctx := v.Context()
|
||||||
|
ctx.isDeployed = true
|
||||||
ctx.scriptHash = hash
|
ctx.scriptHash = hash
|
||||||
ctx.callingScriptHash = shash
|
ctx.callingScriptHash = shash
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue