Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect compilation for runtime.script_container.hash #1273

Open
Hecate2 opened this issue Jun 20, 2024 · 2 comments
Open

Incorrect compilation for runtime.script_container.hash #1273

Hecate2 opened this issue Jun 20, 2024 · 2 comments
Labels
bug Something isn't working

Comments

@Hecate2
Copy link

Hecate2 commented Jun 20, 2024

Describe the bug

PUSH0
PICKITEM

is used to load runtime.script_container.hash into the evaluation stack, which seems incorrect.

How to Reproduce
Contract abstract_account.py:

from boa3.builtin.compile_time import public
from boa3.builtin.interop import runtime, storage, crypto
from boa3.builtin.type import UInt160

@public
def customVerify(user_hash: UInt160, signature: bytes) -> bool:
    """
    Custom verification method.
    """
    
    user_hash : bytes = user_hash
    signature : bytes = signature
    user_public_key = storage.get_ecpoint(user_hash)
    isValid = crypto.verify_with_ecdsa(runtime.script_container.hash, user_public_key, signature, crypto.NamedCurve.SECP256R1)
    return isValid

neo-fairy-test:

from neo_fairy_client import FairyClient, Hash160Str  # pip install neo-fairy-client

c = FairyClient(fairy_session='abstract_account')
c.virutal_deploy_from_path('./abstract_account.nef')

# c.delete_source_code_breakpoints()
# c.delete_assembly_breakpoints()
# c.set_assembly_breakpoints(64)

# c.debug_function_with_session(...)
result = c.invokefunction('customVerify', [
    Hash160Str('0x4b87c8bd516cb64dd7efe45a5e7e9759db7ab58a'),
    bytes.fromhex('f7bf6c19c9b1e91c60639b45b1b74a54587aa3128ff83c98922a5fad538dd570d52796c6ca3b3d30f7ac524d52c6100627c313aa3ce2fd523518d8d7b227b88a')
])

print(result)
print()

Compiled .nef assembly:

# Method Start customVerify.abstract_account
00 INITSLOT 02-02 # 2 local variables, 2 arguments
# Code abstract_account.py line 11: " user_hash : bytes = user_hash"
03 LDARG0
04 STARG0
# Code abstract_account.py line 12: " signature : bytes = signature"
05 LDARG1
06 STARG1
# Code abstract_account.py line 13: " user_public_key = storage.get_ecpoint(user_hash)"
07 LDARG0
08 SYSCALL 9B-F6-67-CE # System.Storage.GetContext SysCall
13 SYSCALL 92-5D-E8-31 # System.Storage.Get SysCall
18 DUP
19 ISNULL
20 JMPIFNOT 26 # pos: 58 (offset: 38)
22 DROP
23 PUSHDATA1 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 # as text: "                                 "
58 STLOC0
# Code abstract_account.py line 14: " isValid = crypto.verify_with_ecdsa(runtime.script_container.hash, user_public_key, signature, crypto.NamedCurve.SECP256R1)"
59 PUSHINT8 17 # 23
61 LDARG1
62 LDLOC0
63 PUSH0
64 PICKITEM
65 CALLT 00-00 # CryptoLib.verifyWithECDsa token call
68 STLOC1
# Code abstract_account.py line 15: " return isValid"
69 LDLOC1
70 RET

Here runtime.script_container.hash is compiled as:

63 PUSH0
64 PICKITEM

And the exception is:

Traceback (most recent call last):
  File "C:\Users\RhantolkYtriHistoria\NEO\abstract_account_py\fairy_abstract_account.py", line 11, in <module>
    result = c.invokefunction('customVerify', [
  File "C:\Program Files\Python38\lib\site-packages\neo_fairy_client\rpc\fairy_client.py", line 468, in invokefunction
    return self.invokefunction_of_any_contract(self.contract_scripthash, operation, params,
  File "C:\Program Files\Python38\lib\site-packages\neo_fairy_client\rpc\fairy_client.py", line 455, in invokefunction_of_any_contract
    result = self.meta_rpc_method(
  File "C:\Program Files\Python38\lib\site-packages\neo_fairy_client\rpc\fairy_client.py", line 218, in meta_rpc_method
    raise ValueError(result_result['traceback'])
ValueError: CallingScriptHash=0xfc7f52ef142e5aa9703a853b771fa1e13c2b83f1[]
CurrentScriptHash=0x061022bf155f27c81df26b19f33f9e0c0cfb1a72[abstract_account]
EntryScriptHash=0xfc7f52ef142e5aa9703a853b771fa1e13c2b83f1
   at Neo.SmartContract.ApplicationEngine.OnCallT(ExecutionEngine engine, Instruction instruction) in C:\Users\RhantolkYtriHistoria\NEO\neo-node-mainnet\src\Neo\SmartContract\ApplicationEngine.cs:line 209
   at Neo.VM.ExecutionEngine.ExecuteNext() in C:\Users\RhantolkYtriHistoria\NEO\neo-node-mainnet\src\Neo.VM\ExecutionEngine.cs:line 148
	InstructionPointer=132, OpCode , Script Length=132 0xfc7f52ef142e5aa9703a853b771fa1e13c2b83f1[]
File , line 0: 
	InstructionPointer=65, OpCode CALLT, Script Length=82 0x061022bf155f27c81df26b19f33f9e0c0cfb1a72[abstract_account]
   at Neo.SmartContract.ApplicationEngine.OnCallT(ExecutionEngine engine, Instruction instruction) in C:\Users\RhantolkYtriHistoria\NEO\neo-node-mainnet\src\Neo\SmartContract\ApplicationEngine.cs:line 209
   at Neo.VM.ExecutionEngine.ExecuteNext() in C:\Users\RhantolkYtriHistoria\NEO\neo-node-mainnet\src\Neo.VM\ExecutionEngine.cs:line 148
Operation is not valid due to the current state of the object.

Expected behavior
Smooth invocation

Screenshots
screenshot

Platform:

  • OS: Windows 10 x64
  • Version: neo3-boa==1.2.1 58d33fd
  • Python version: Python 3.11.9
@Hecate2 Hecate2 added the bug Something isn't working label Jun 20, 2024
@Hecate2
Copy link
Author

Hecate2 commented Jun 21, 2024

The workaround is:

    container = runtime.script_container
    h = container.hash
    isValid = crypto.verify_with_ecdsa(h, user_public_key, signature, crypto.NamedCurve.SECP256R1)
# Code abstract_account.py line 14: " container = runtime.script_container"
59 SYSCALL 2D-51-08-30 # System.Runtime.GetScriptContainer SysCall
64 STLOC1
# Code abstract_account.py line 15: " h = container.hash"
65 LDLOC1
66 PUSH0
67 PICKITEM
68 STLOC2
# Code abstract_account.py line 16: " isValid = crypto.verify_with_ecdsa(h, user_public_key, signature, crypto.NamedCurve.SECP256R1)"
69 PUSHINT8 17 # 23
71 LDARG1
72 LDLOC0
73 LDLOC2
74 CALLT 00-00 # CryptoLib.verifyWithECDsa token call
77 STLOC3

@Hecate2
Copy link
Author

Hecate2 commented Jul 11, 2024

By the way,

h = runtime.script_container.hash

gives an error:

ERROR: 14:8 - Unresolved reference 'None.hash'

In

if hasattr(value, 'symbols') and attribute.attr in value.symbols:
attribute_symbol = value.symbols[attribute.attr]
elif isinstance(value, Package) and attribute.attr in value.inner_packages:
attribute_symbol = value.inner_packages[attribute.attr]
elif Builtin.get_symbol(attribute.attr) is not None:
attribute_symbol = Builtin.get_symbol(attribute.attr)
elif isinstance(value, UndefinedType):
attribute_symbol = value

attribute_symbol remains None, while the type of value is not judged (should be Transaction).

ixje added a commit that referenced this issue Aug 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant