mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-23 13:41:37 +00:00
interop/vm: use more robust CalledByEntry check
Directly check contexts.
This commit is contained in:
parent
13f5fdbe8a
commit
99e2681d3a
6 changed files with 24 additions and 8 deletions
|
@ -41,6 +41,10 @@ func getContractGroups(v *vm.VM, ic *interop.Context, h util.Uint160) (manifest.
|
||||||
return manifest.Groups(cs.Manifest.Groups), nil
|
return manifest.Groups(cs.Manifest.Groups), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sc scopeContext) IsCalledByEntry() bool {
|
||||||
|
return sc.VM.Context().IsCalledByEntry()
|
||||||
|
}
|
||||||
|
|
||||||
func (sc scopeContext) checkScriptGroups(h util.Uint160, k *keys.PublicKey) (bool, error) {
|
func (sc scopeContext) checkScriptGroups(h util.Uint160, k *keys.PublicKey) (bool, error) {
|
||||||
groups, err := getContractGroups(sc.VM, sc.ic, h)
|
groups, err := getContractGroups(sc.VM, sc.ic, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -69,9 +73,7 @@ func checkScope(ic *interop.Context, hash util.Uint160) (bool, error) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
if c.Scopes&transaction.CalledByEntry != 0 {
|
if c.Scopes&transaction.CalledByEntry != 0 {
|
||||||
callingScriptHash := ic.VM.GetCallingScriptHash()
|
if ic.VM.Context().IsCalledByEntry() {
|
||||||
entryScriptHash := ic.VM.GetEntryScriptHash()
|
|
||||||
if callingScriptHash.Equals(util.Uint160{}) || callingScriptHash == entryScriptHash {
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,9 +63,9 @@ type WitnessCondition interface {
|
||||||
type MatchContext interface {
|
type MatchContext interface {
|
||||||
GetCallingScriptHash() util.Uint160
|
GetCallingScriptHash() util.Uint160
|
||||||
GetCurrentScriptHash() util.Uint160
|
GetCurrentScriptHash() util.Uint160
|
||||||
GetEntryScriptHash() util.Uint160
|
|
||||||
CallingScriptHasGroup(*keys.PublicKey) (bool, error)
|
CallingScriptHasGroup(*keys.PublicKey) (bool, error)
|
||||||
CurrentScriptHasGroup(*keys.PublicKey) (bool, error)
|
CurrentScriptHasGroup(*keys.PublicKey) (bool, error)
|
||||||
|
IsCalledByEntry() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -394,8 +394,7 @@ func (c ConditionCalledByEntry) Type() WitnessConditionType {
|
||||||
// Match implements the WitnessCondition interface checking whether this condition
|
// Match implements the WitnessCondition interface checking whether this condition
|
||||||
// matches given context.
|
// matches given context.
|
||||||
func (c ConditionCalledByEntry) Match(ctx MatchContext) (bool, error) {
|
func (c ConditionCalledByEntry) Match(ctx MatchContext) (bool, error) {
|
||||||
entry := ctx.GetEntryScriptHash()
|
return ctx.IsCalledByEntry(), nil
|
||||||
return entry.Equals(ctx.GetCallingScriptHash()) || entry.Equals(ctx.GetCurrentScriptHash()), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeBinary implements the WitnessCondition interface allowing to serialize condition.
|
// EncodeBinary implements the WitnessCondition interface allowing to serialize condition.
|
||||||
|
|
|
@ -170,6 +170,9 @@ func (t *TestMC) GetCurrentScriptHash() util.Uint160 {
|
||||||
func (t *TestMC) GetEntryScriptHash() util.Uint160 {
|
func (t *TestMC) GetEntryScriptHash() util.Uint160 {
|
||||||
return t.entry
|
return t.entry
|
||||||
}
|
}
|
||||||
|
func (t *TestMC) IsCalledByEntry() bool {
|
||||||
|
return t.entry.Equals(t.calling) || t.calling.Equals(util.Uint160{})
|
||||||
|
}
|
||||||
func (t *TestMC) CallingScriptHasGroup(k *keys.PublicKey) (bool, error) {
|
func (t *TestMC) CallingScriptHasGroup(k *keys.PublicKey) (bool, error) {
|
||||||
res, err := t.CurrentScriptHasGroup(k)
|
res, err := t.CurrentScriptHasGroup(k)
|
||||||
return !res, err // To differentiate from current we invert the logic value.
|
return !res, err // To differentiate from current we invert the logic value.
|
||||||
|
|
|
@ -13,7 +13,7 @@ type WitnessScope byte
|
||||||
const (
|
const (
|
||||||
// None specifies that no contract was witnessed. Only sign the transaction.
|
// None specifies that no contract was witnessed. Only sign the transaction.
|
||||||
None WitnessScope = 0
|
None WitnessScope = 0
|
||||||
// CalledByEntry means that this condition must hold: EntryScriptHash == CallingScriptHash.
|
// CalledByEntry witness is only valid in entry script and ones directly called by it.
|
||||||
// No params is needed, as the witness/permission/signature given on first invocation will
|
// No params is needed, as the witness/permission/signature given on first invocation will
|
||||||
// automatically expire if entering deeper internal invokes. This can be default safe
|
// automatically expire if entering deeper internal invokes. This can be default safe
|
||||||
// choice for native NEO/GAS (previously used on Neo 2 as "attach" mode).
|
// choice for native NEO/GAS (previously used on Neo 2 as "attach" mode).
|
||||||
|
|
|
@ -37,6 +37,9 @@ type scriptContext struct {
|
||||||
// Caller's contract script hash.
|
// Caller's contract script hash.
|
||||||
callingScriptHash util.Uint160
|
callingScriptHash util.Uint160
|
||||||
|
|
||||||
|
// Caller's scriptContext, if not entry.
|
||||||
|
callingContext *scriptContext
|
||||||
|
|
||||||
// Call flags this context was created with.
|
// Call flags this context was created with.
|
||||||
callFlag callflag.CallFlag
|
callFlag callflag.CallFlag
|
||||||
|
|
||||||
|
@ -326,6 +329,12 @@ func (v *VM) getContextScriptHash(n int) util.Uint160 {
|
||||||
return ctx.ScriptHash()
|
return ctx.ScriptHash()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsCalledByEntry checks parent script contexts and return true if the current one
|
||||||
|
// is an entry script (the first loaded into the VM) or one called by it.
|
||||||
|
func (c *Context) IsCalledByEntry() bool {
|
||||||
|
return c.sc.callingContext == nil || c.sc.callingContext.callingContext == nil
|
||||||
|
}
|
||||||
|
|
||||||
// PushContextScriptHash pushes the script hash of the
|
// PushContextScriptHash pushes the script hash of the
|
||||||
// invocation stack element number n to the evaluation stack.
|
// invocation stack element number n to the evaluation stack.
|
||||||
func (v *VM) PushContextScriptHash(n int) error {
|
func (v *VM) PushContextScriptHash(n int) error {
|
||||||
|
|
|
@ -340,15 +340,18 @@ func (v *VM) loadScriptWithCallingHash(b []byte, exe *nef.File, caller util.Uint
|
||||||
if rvcount != -1 || v.estack.Len() != 0 {
|
if rvcount != -1 || v.estack.Len() != 0 {
|
||||||
v.estack = subStack(v.estack)
|
v.estack = subStack(v.estack)
|
||||||
}
|
}
|
||||||
|
parent := v.Context()
|
||||||
ctx.sc.estack = v.estack
|
ctx.sc.estack = v.estack
|
||||||
initStack(&ctx.tryStack, "exception", nil)
|
initStack(&ctx.tryStack, "exception", nil)
|
||||||
ctx.sc.callFlag = f
|
ctx.sc.callFlag = f
|
||||||
ctx.sc.scriptHash = hash
|
ctx.sc.scriptHash = hash
|
||||||
ctx.sc.callingScriptHash = caller
|
ctx.sc.callingScriptHash = caller
|
||||||
|
if parent != nil {
|
||||||
|
ctx.sc.callingContext = parent.sc
|
||||||
|
}
|
||||||
ctx.sc.NEF = exe
|
ctx.sc.NEF = exe
|
||||||
if v.invTree != nil {
|
if v.invTree != nil {
|
||||||
curTree := v.invTree
|
curTree := v.invTree
|
||||||
parent := v.Context()
|
|
||||||
if parent != nil {
|
if parent != nil {
|
||||||
curTree = parent.sc.invTree
|
curTree = parent.sc.invTree
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue