core: hangle CallingScriptHash correctly
When using native contracts, script hash of second-to-top context on invocation stack does not always correspond to a real calling contract.
This commit is contained in:
parent
e903e40085
commit
e63191d31f
4 changed files with 33 additions and 5 deletions
|
@ -22,8 +22,13 @@ func GetExecutingScriptHash(ic *interop.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCallingScriptHash returns calling script hash.
|
// GetCallingScriptHash returns calling script hash.
|
||||||
|
// While Executing and Entry script hashes are always valid for non-native contracts,
|
||||||
|
// Calling hash is set explicitly when native contracts are used, because when switching from
|
||||||
|
// one native to another, no operations are performed on invocation stack.
|
||||||
func GetCallingScriptHash(ic *interop.Context) error {
|
func GetCallingScriptHash(ic *interop.Context) error {
|
||||||
return ic.VM.PushContextScriptHash(1)
|
h := ic.VM.GetCallingScriptHash()
|
||||||
|
ic.VM.Estack().PushVal(h.BytesBE())
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEntryScriptHash returns entry script hash.
|
// GetEntryScriptHash returns entry script hash.
|
||||||
|
|
|
@ -440,7 +440,8 @@ func getTestContractState() (*state.Contract, *state.Contract) {
|
||||||
emit.Syscall(w.BinWriter, interopnames.SystemStorageGet)
|
emit.Syscall(w.BinWriter, interopnames.SystemStorageGet)
|
||||||
emit.Opcodes(w.BinWriter, opcode.RET)
|
emit.Opcodes(w.BinWriter, opcode.RET)
|
||||||
onPaymentOff := w.Len()
|
onPaymentOff := w.Len()
|
||||||
emit.Int(w.BinWriter, 3)
|
emit.Syscall(w.BinWriter, interopnames.SystemRuntimeGetCallingScriptHash)
|
||||||
|
emit.Int(w.BinWriter, 4)
|
||||||
emit.Opcodes(w.BinWriter, opcode.PACK)
|
emit.Opcodes(w.BinWriter, opcode.PACK)
|
||||||
emit.String(w.BinWriter, "LastPayment")
|
emit.String(w.BinWriter, "LastPayment")
|
||||||
emit.Syscall(w.BinWriter, interopnames.SystemRuntimeNotify)
|
emit.Syscall(w.BinWriter, interopnames.SystemRuntimeNotify)
|
||||||
|
|
|
@ -317,11 +317,32 @@ func TestNEO_TransferOnPayment(t *testing.T) {
|
||||||
aer, err := bc.GetAppExecResults(tx.Hash(), trigger.Application)
|
aer, err := bc.GetAppExecResults(tx.Hash(), trigger.Application)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, vm.HaltState, aer[0].VMState)
|
require.Equal(t, vm.HaltState, aer[0].VMState)
|
||||||
require.Len(t, aer[0].Events, 3) // transfer + auto GAS claim + onPayment
|
require.Len(t, aer[0].Events, 3) // transfer + GAS claim for sender + onPayment
|
||||||
|
|
||||||
e := aer[0].Events[2]
|
e := aer[0].Events[2]
|
||||||
require.Equal(t, "LastPayment", e.Name)
|
require.Equal(t, "LastPayment", e.Name)
|
||||||
arr := e.Item.Value().([]stackitem.Item)
|
arr := e.Item.Value().([]stackitem.Item)
|
||||||
require.Equal(t, neoOwner.BytesBE(), arr[0].Value())
|
require.Equal(t, bc.contracts.NEO.Hash.BytesBE(), arr[0].Value())
|
||||||
require.Equal(t, big.NewInt(amount), arr[1].Value())
|
require.Equal(t, neoOwner.BytesBE(), arr[1].Value())
|
||||||
|
require.Equal(t, big.NewInt(amount), arr[2].Value())
|
||||||
|
|
||||||
|
tx = transferTokenFromMultisigAccount(t, bc, cs.Hash, bc.contracts.NEO.Hash, amount)
|
||||||
|
aer, err = bc.GetAppExecResults(tx.Hash(), trigger.Application)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, vm.HaltState, aer[0].VMState)
|
||||||
|
// Now we must also have GAS claim for contract and corresponding `onPayment`.
|
||||||
|
require.Len(t, aer[0].Events, 5)
|
||||||
|
|
||||||
|
e = aer[0].Events[2] // onPayment for GAS claim
|
||||||
|
require.Equal(t, "LastPayment", e.Name)
|
||||||
|
arr = e.Item.Value().([]stackitem.Item)
|
||||||
|
require.Equal(t, stackitem.Null{}, arr[1])
|
||||||
|
require.Equal(t, bc.contracts.GAS.Hash.BytesBE(), arr[0].Value())
|
||||||
|
|
||||||
|
e = aer[0].Events[4] // onPayment for NEO transfer
|
||||||
|
require.Equal(t, "LastPayment", e.Name)
|
||||||
|
arr = e.Item.Value().([]stackitem.Item)
|
||||||
|
require.Equal(t, bc.contracts.NEO.Hash.BytesBE(), arr[0].Value())
|
||||||
|
require.Equal(t, neoOwner.BytesBE(), arr[1].Value())
|
||||||
|
require.Equal(t, big.NewInt(amount), arr[2].Value())
|
||||||
}
|
}
|
||||||
|
|
|
@ -284,6 +284,7 @@ func (v *VM) LoadScriptWithFlags(b []byte, f smartcontract.CallFlag) {
|
||||||
ctx.tryStack = NewStack("exception")
|
ctx.tryStack = NewStack("exception")
|
||||||
ctx.callFlag = f
|
ctx.callFlag = f
|
||||||
ctx.static = newSlot(v.refs)
|
ctx.static = newSlot(v.refs)
|
||||||
|
ctx.callingScriptHash = v.GetCurrentScriptHash()
|
||||||
v.istack.PushVal(ctx)
|
v.istack.PushVal(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue