Skip to content
This repository has been archived by the owner on Mar 28, 2023. It is now read-only.

GetCallingScriptHash from module returns incorrect value #83

Closed
nickfujita opened this issue Jun 23, 2018 · 4 comments
Closed

GetCallingScriptHash from module returns incorrect value #83

nickfujita opened this issue Jun 23, 2018 · 4 comments

Comments

@nickfujita
Copy link

When using GetCallingScriptHash along with RegisterAppCall or DynamicAppCall, I expected to get the hash of the contract which called the contract with GetCallingScriptHash in all cases, but it seems that when GetCallingScriptHash is used in a file that is separate from the root file that contains the Main method, it is returning the hash of itself rather that the hash of the contract that invoked it.

I have created the following example code to demonstrate this issue:
https://github.com/nickfujita/neo-examples/tree/master/smartContracts/callerHash

  • Contract B will be invoked, and will call Contract A
  • Contract A prints 2 things:
    • Return value of GetCallingScriptHash when called from the Main method
    • Return value of GetCallingScriptHash when called from the printTest method, located at src/printCaller.py

Expected result:

  • Contract A will print the script hash of Contract B when calling GetCallingScriptHash from both the Main and printTest methods

Actual result:

  • Contract A prints the script hash of Contract B when calling GetCallingScriptHash from the Main method, but prints the script hash of Contract A when called from the printTest method

Please let me know if this issue should be moved to neo-python instead.

@igormcoelho
Copy link

igormcoelho commented Jun 23, 2018

I did some quick simulations with both Python and C#, and they seem to behave the same way. I expanded the test to include functions: GetCallingScriptHash(), GetEntryScriptHash() and GetExecutingScriptHash()

    caller = GetCallingScriptHash()
    caller2 = GetEntryScriptHash()
    caller3 = GetExecutingScriptHash()
contracts:
(A): #6edabfbf75265d2dd024416183f69aec677ee8e9
(B): # fb593745178a682d6df4dda9aa160af23d3444d4

#python
b'caller_main'
b'\xd4D4=\xf2\n\x16\xaa\xa9\xdd\xf4m-h\x8a\x17E7Y\xfb'  #b'd444343df20a16aaa9ddf46d2d688a17453759fb'
b'caller2_main'
b'v\xf1\xb4sZ\x9e\x0c\x8f\xb5\xb2s\xb8p\x10`\x1a\xcd\xa9\x04\xa9'  #b'76f1b4735a9e0c8fb5b273b87010601acda904a9'
b'caller3_main'
b'\xe9\xe8~g\xec\x9a\xf6\x83aA$\xd0-]&u\xbf\xbf\xdan' #b'e9e87e67ec9af683614124d02d5d2675bfbfda6e'
b'caller_printCaller'
b'\xe9\xe8~g\xec\x9a\xf6\x83aA$\xd0-]&u\xbf\xbf\xdan' #b'e9e87e67ec9af683614124d02d5d2675bfbfda6e'
b'caller2_printCaller'
b'v\xf1\xb4sZ\x9e\x0c\x8f\xb5\xb2s\xb8p\x10`\x1a\xcd\xa9\x04\xa9' #b'76f1b4735a9e0c8fb5b273b87010601acda904a9'
b'caller3_printCaller'
b'\xe9\xe8~g\xec\x9a\xf6\x83aA$\xd0-]&u\xbf\xbf\xdan' #b'e9e87e67ec9af683614124d02d5d2675bfbfda6e'

# C#
{"txid":"0x1ebc29295160470cede06e4e05008b850f1a321c46606862538e85ecc15ed352","vmstate":"HALT, BREAK","gas_consumed":"0.101","stack":[{"type":"ByteArray","value":""},
{"type":"ByteArray","value":""},{"type":"ByteArray","value":""}],
"notifications":[{"contract":"0x6edabfbf75265d2dd024416183f69aec677ee8e9","state":{"type":"ByteArray","value":"caller_main"}},
{"contract":"0x6edabfbf75265d2dd024416183f69aec677ee8e9","state":{"type":"ByteArray","value":"d444343df20a16aaa9ddf46d2d688a17453759fb"}},
{"contract":"0x6edabfbf75265d2dd024416183f69aec677ee8e9","state":{"type":"ByteArray","value":"caller2_main"}},
{"contract":"0x6edabfbf75265d2dd024416183f69aec677ee8e9","state":{"type":"ByteArray","value":"76f1b4735a9e0c8fb5b273b87010601acda904a9"}},
{"contract":"0x6edabfbf75265d2dd024416183f69aec677ee8e9","state":{"type":"ByteArray","value":"caller3_main"}},
{"contract":"0x6edabfbf75265d2dd024416183f69aec677ee8e9","state":{"type":"ByteArray","value":"e9e87e67ec9af683614124d02d5d2675bfbfda6e"}},
{"contract":"0x6edabfbf75265d2dd024416183f69aec677ee8e9","state":{"type":"ByteArray","value":"caller_printCaller"}},
{"contract":"0x6edabfbf75265d2dd024416183f69aec677ee8e9","state":{"type":"ByteArray","value":"e9e87e67ec9af683614124d02d5d2675bfbfda6e"}},
{"contract":"0x6edabfbf75265d2dd024416183f69aec677ee8e9","state":{"type":"ByteArray","value":"caller2_printCaller"}},
{"contract":"0x6edabfbf75265d2dd024416183f69aec677ee8e9","state":{"type":"ByteArray","value":"76f1b4735a9e0c8fb5b273b87010601acda904a9"}},
{"contract":"0x6edabfbf75265d2dd024416183f69aec677ee8e9","state":{"type":"ByteArray","value":"caller3_printCaller"}},
{"contract":"0x6edabfbf75265d2dd024416183f69aec677ee8e9","state":{"type":"ByteArray","value":"e9e87e67ec9af683614124d02d5d2675bfbfda6e"}}]}

It seems the only way to get the right contract calling information is on Main scope (and store it for further usage). GetCallingScriptHash() seems to return the scriphash of the contract which performed the last CALL operation, while GetExecutingScriptHash() seems to be consistent.

@igormcoelho
Copy link

igormcoelho commented Jun 23, 2018

@nickfujita @localhuman That is the correct behavior.

Let's assume InvocationStack is currently:
0: 6edabfbf75265d2dd024416183f69aec677ee8e9 (ContractA)
1: fb593745178a682d6df4dda9aa160af23d3444d4 (ContractB)

CurrentContext (in GetExecutingScriptHash) is: 6edabfbf75265d2dd024416183f69aec677ee8e9 (ContractA). GetCallingScriptHash returns position 1 of InvocationStack: fb593745178a682d6df4dda9aa160af23d3444d4 (ContractB).

After you perform a (function) CALL: https://github.com/neo-project/neo-vm/blob/e2f3b1aa42073ce27343c9a95bf076ce7d19d787/src/neo-vm/ExecutionEngine.cs#L124
you clone CurrentContext and put on InvocationStack, which becomes:
0: 6edabfbf75265d2dd024416183f69aec677ee8e9 (ContractA)
1: 6edabfbf75265d2dd024416183f69aec677ee8e9 (ContractA)
2: fb593745178a682d6df4dda9aa160af23d3444d4 (ContractB)

So, GetCallingScriptHash will change value, and it is actually information that the contract itself performed the last CALL operation (not ContractB anymore).

@igormcoelho
Copy link

igormcoelho commented Jun 23, 2018

@shargon @vncoelho it is amazing that I got interested by this post (by chance), because it seems to break my idea of function CALL inlining in NeonOpt project, when people are using GetCallingScriptHash information... in fact, if @nickfujita used my function inliner, he wouldn't have had this issue, because auxiliar function would have been moved to main scope :D hahahah

@ixje
Copy link
Member

ixje commented Jun 24, 2018

@nickfujita unfortunately this is expected. I reported this issue some months ago here neo-project/neo-vm#29 and Erik Zhang said it's expected and intended behaviour.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants