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

Commit

Permalink
Merge pull request #133 from simplitech/fix-abi-hash
Browse files Browse the repository at this point in the history
Fix generating incorrect hash for ABI file
  • Loading branch information
melanke committed May 29, 2020
2 parents 33e8483 + f9ea864 commit e1eb134
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 6 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
venv/
__pycache__
.avm
*.avmdbgnfo
*.abi.json
dist
build
neo_boa.egg-info
*.egg-info
/build
vm_instructions.log
vm_instructions.log
11 changes: 6 additions & 5 deletions boa/code/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from boa.util import BlockType, get_block_type
from bytecode import UNSET, Bytecode, BasicBlock, ControlFlowGraph, dump_bytecode, Label
from boa.interop import VMOp
from boa.interop import VMOp, Neo
import importlib
from logzero import logger
from collections import OrderedDict
Expand Down Expand Up @@ -468,9 +468,9 @@ def export_abi_json(self, output_path):
"""
this method is used to generate a debug map for NEO debugger
"""
file = open(output_path, 'rb')
file_hash = hashlib.md5(file.read()).hexdigest()
file.close()
with open(output_path, 'rb') as file:
script = Neo.to_script_hash(file.read())
file_hash = Neo.to_hex_str(script)

avm_name = os.path.splitext(os.path.basename(output_path))[0]

Expand All @@ -479,7 +479,6 @@ def export_abi_json(self, output_path):

with open(abi_json_filename, 'w+') as out_file:
out_file.write(abi_info)
out_file.close()

def generate_abi_json(self, avm_name, file_hash):
# Initialize if needed
Expand All @@ -500,6 +499,8 @@ def generate_abi_json(self, avm_name, file_hash):
data['entrypoint'] = 'Main'
elif len(self.abi_methods) > 0:
data['entrypoint'] = self.abi_methods.get(0)
else:
data['entrypoint'] = self.main.name

data['functions'] = functions
data['events'] = events
Expand Down
31 changes: 31 additions & 0 deletions boa/interop/Neo/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import hashlib


def to_script_hash(byte_array) -> bytes:
"""
Converts a data to a script hash.
:param byte_array: data to hash.
:type byte_array: bytearray or bytes
:return: the script hash of the data
:rtype: bytes
"""
intermed = hashlib.sha256(byte_array).digest()
return hashlib.new('ripemd160', intermed).digest()


def to_hex_str(data_bytes: bytes) -> str:
"""
Converts bytes into its string hex representation.
:param data_bytes: data to represent as hex.
:type data_bytes: bytearray or bytes
:return: the hex representation of the data
:rtype: str
"""
if isinstance(data_bytes, bytes):
data_bytes = bytearray(data_bytes)
data_bytes.reverse()
return '0x' + data_bytes.hex()
11 changes: 11 additions & 0 deletions boa_test/example/AbiMethods8.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
def method(operation, args):
if operation == 'add':
a = args[0]
b = args[1]
return add(a, b)
else:
return False


def add(a, b):
return a + b
38 changes: 38 additions & 0 deletions boa_test/tests/test_abi_methods.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import json
import os

from boa.compiler import Compiler
from boa_test.tests.boa_test import BoaTest

Expand Down Expand Up @@ -34,6 +36,32 @@ def test_abi_methods_success(self):
self.assertEqual(add_params[1]['name'], 'b')
self.assertEqual(add_params[1]['type'], 'Integer')

def test_abi_script_hash_fail(self):
path = '%s/boa_test/example/AbiMethods1.py' % TestContract.dirname
abi_path = path.replace('.py', '.abi.json')
Compiler.load_and_save(path)

self.assertTrue(os.path.exists(abi_path))
with open(abi_path, 'r') as abi_file:
json_file = json.loads(abi_file.read())

self.assertIn('hash', json_file)
script_hash = json_file['hash']
self.assertNotEqual(script_hash, 'a623cc41d62bf5783acde35fd105cdc4')

def test_abi_script_hash_success(self):
path = '%s/boa_test/example/AbiMethods1.py' % TestContract.dirname
abi_path = path.replace('.py', '.abi.json')
Compiler.load_and_save(path)

self.assertTrue(os.path.exists(abi_path))
with open(abi_path, 'r') as abi_file:
json_file = json.loads(abi_file.read())

self.assertIn('hash', json_file)
script_hash = json_file['hash']
self.assertEqual(script_hash, '0xd0fce96885b76b14beed1c401af22d438ace50d4')

def test_abi_methods_only_entry_point(self):
path = '%s/boa_test/example/AbiMethods2.py' % TestContract.dirname
output = Compiler.load(path).default
Expand Down Expand Up @@ -92,3 +120,13 @@ def test_abi_method_without_return_type(self):
self.assertEqual(main_params[0]['type'], 'String')
self.assertEqual(main_params[1]['name'], 'args')
self.assertEqual(main_params[1]['type'], 'Array')

def test_abi_method_without_decorator(self):
path = '%s/boa_test/example/AbiMethods8.py' % TestContract.dirname
output = Compiler.load(path).default
json_file = json.loads(output.generate_abi_json('AbiMethods8.avm', 'test'))

entry_point = json_file['entrypoint']
self.assertEqual(entry_point, 'method')
functions = json_file['functions']
self.assertEqual(len(functions), 0)

0 comments on commit e1eb134

Please sign in to comment.