Merge branch 'develop' into feature/docs

pull/845/head
Dominik Muhs 6 years ago
commit 88be48d230
  1. 6
      .circleci/config.yml
  2. 25
      mythril/alarm.py
  3. 3
      mythril/analysis/modules/base.py
  4. 6
      mythril/analysis/security.py
  5. 12
      mythril/analysis/symbolic.py
  6. 4
      mythril/exceptions.py
  7. 12
      mythril/laser/ethereum/call.py
  8. 11
      mythril/laser/ethereum/cfg.py
  9. 19
      mythril/laser/ethereum/instructions.py
  10. 2
      mythril/laser/ethereum/state/account.py
  11. 8
      mythril/laser/ethereum/state/calldata.py
  12. 6
      mythril/laser/ethereum/state/environment.py
  13. 8
      mythril/laser/ethereum/state/memory.py
  14. 106
      mythril/laser/ethereum/svm.py
  15. 14
      mythril/laser/ethereum/transaction/concolic.py
  16. 31
      mythril/laser/ethereum/transaction/symbolic.py
  17. 14
      mythril/laser/ethereum/transaction/transaction_models.py
  18. 54
      mythril/mythril.py
  19. 2
      mythril/support/truffle.py
  20. 2
      requirements.txt
  21. 2
      setup.py
  22. 8
      tests/native_test.py

@ -74,6 +74,12 @@ jobs:
# command: if [ -z "$CIRCLE_PR_NUMBER" ]; then ./run-integration-tests.sh; fi
# working_directory: /home
- run:
name: Call webhook
command: |
curl -I -X POST -H -d "https://circleci.com/api/v1/project/${ORGANIZATION}/${WEBHOOK_PROJECT}/tree/master?circle-token=${CIRCLE_TOKEN}" | head -n 1 | cut -d$' ' -f2
pypi_release:
<<: *defaults
steps:

@ -0,0 +1,25 @@
import signal
from types import FrameType
from mythril.exceptions import OutOfTimeError
def sigalrm_handler(signum: int, frame: FrameType) -> None:
raise OutOfTimeError
def start_timeout(timeout: int) -> None:
"""
Starts a timeout
:param timeout: Time in seconds to set the timeout for
:return: None
"""
signal.signal(signal.SIGALRM, sigalrm_handler)
signal.alarm(timeout)
def disable_timeout() -> None:
"""
Ensures that the timeout is disabled
:return: None
"""
signal.alarm(0)

@ -48,7 +48,8 @@ class DetectionModule:
"DetectionModule "
"name={0.name} "
"swc_id={0.swc_id} "
"hooks={0.hooks} "
"pre_hooks={0.pre_hooks} "
"post_hooks={0.post_hooks} "
"description={0.description}"
">"
).format(self)

@ -89,6 +89,12 @@ def fire_lasers(statespace, module_names=()):
log.info("Executing " + module.detector.name)
issues += module.detector.execute(statespace)
issues += retrieve_callback_issues(module_names)
return issues
def retrieve_callback_issues(module_names=()):
issues = []
for module in get_detection_modules(
entrypoint="callback", include_modules=module_names
):

@ -1,8 +1,7 @@
"""This module contains a wrapper around LASER for extended analysis
purposes."""
import copy
from mythril.analysis.security import get_detection_module_hooks
from mythril.analysis.security import get_detection_module_hooks, get_detection_modules
from mythril.laser.ethereum import svm
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.strategy.basic import (
@ -33,6 +32,7 @@ class SymExecWrapper:
create_timeout=None,
transaction_count=2,
modules=(),
compulsory_statespace=True,
):
"""
@ -63,7 +63,9 @@ class SymExecWrapper:
dynamic_loader=dynloader,
contract_name=contract.name,
)
requires_statespace = (
compulsory_statespace or len(get_detection_modules("post", modules)) > 0
)
self.accounts = {address: account}
self.laser = svm.LaserEVM(
@ -74,6 +76,7 @@ class SymExecWrapper:
strategy=s_strategy,
create_timeout=create_timeout,
transaction_count=transaction_count,
requires_statespace=requires_statespace,
)
self.laser.register_hooks(
hook_type="pre",
@ -95,6 +98,9 @@ class SymExecWrapper:
else:
self.laser.sym_exec(address)
if not requires_statespace:
return
self.nodes = self.laser.nodes
self.edges = self.laser.edges

@ -7,6 +7,10 @@ class MythrilBaseException(Exception):
pass
class OutOfTimeError(MythrilBaseException):
pass
class CompilerError(MythrilBaseException):
"""A Mythril exception denoting an error during code compilation."""

@ -11,10 +11,9 @@ from mythril.laser.smt import simplify, Expression, symbol_factory
import mythril.laser.ethereum.util as util
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.calldata import (
CalldataType,
BaseCalldata,
SymbolicCalldata,
ConcreteCalldata,
BaseCalldata,
)
from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.support.loader import DynLoader
@ -48,9 +47,7 @@ def get_call_parameters(
callee_address = get_callee_address(global_state, dynamic_loader, to)
callee_account = None
call_data, call_data_type = get_call_data(
global_state, memory_input_offset, memory_input_size
)
call_data = get_call_data(global_state, memory_input_offset, memory_input_size)
if int(callee_address, 16) >= 5 or int(callee_address, 16) == 0:
callee_account = get_callee_account(
@ -62,7 +59,6 @@ def get_call_parameters(
callee_account,
call_data,
value,
call_data_type,
gas,
memory_out_offset,
memory_out_size,
@ -189,14 +185,12 @@ def get_call_data(
)
]
call_data = ConcreteCalldata(transaction_id, calldata_from_mem)
call_data_type = CalldataType.CONCRETE
log.debug("Calldata: " + str(call_data))
except TypeError:
log.debug("Unsupported symbolic calldata offset")
call_data_type = CalldataType.SYMBOLIC
call_data = SymbolicCalldata("{}_internalcall".format(transaction_id))
return call_data, call_data_type
return call_data
def native_call(

@ -26,8 +26,13 @@ class NodeFlags(Flags):
class Node:
"""The representation of a call graph node."""
def __init__(self, contract_name: str, start_addr=0, constraints=None):
def __init__(
self,
contract_name: str,
start_addr=0,
constraints=None,
function_name="unknown",
):
"""
:param contract_name:
@ -39,7 +44,7 @@ class Node:
self.start_addr = start_addr
self.states = []
self.constraints = constraints
self.function_name = "unknown"
self.function_name = function_name
self.flags = NodeFlags()
# Self-assign a unique ID

@ -516,7 +516,9 @@ class Instruction:
)
else:
state.stack.append(pow(base.value, exponent.value, 2 ** 256))
state.stack.append(
symbol_factory.BitVecVal(pow(base.value, exponent.value, 2 ** 256), 256)
)
return [global_state]
@ -1678,7 +1680,7 @@ class Instruction:
environment = global_state.environment
try:
callee_address, callee_account, call_data, value, call_data_type, gas, memory_out_offset, memory_out_size = get_call_parameters(
callee_address, callee_account, call_data, value, gas, memory_out_offset, memory_out_size = get_call_parameters(
global_state, self.dynamic_loader, True
)
except ValueError as e:
@ -1712,7 +1714,6 @@ class Instruction:
),
callee_account=callee_account,
call_data=call_data,
call_data_type=call_data_type,
call_value=value,
)
raise TransactionStartSignal(transaction, self.op_code)
@ -1795,7 +1796,7 @@ class Instruction:
environment = global_state.environment
try:
callee_address, callee_account, call_data, value, call_data_type, gas, _, _ = get_call_parameters(
callee_address, callee_account, call_data, value, gas, _, _ = get_call_parameters(
global_state, self.dynamic_loader, True
)
except ValueError as e:
@ -1818,7 +1819,6 @@ class Instruction:
caller=environment.address,
callee_account=environment.active_account,
call_data=call_data,
call_data_type=call_data_type,
call_value=value,
)
raise TransactionStartSignal(transaction, self.op_code)
@ -1833,7 +1833,7 @@ class Instruction:
instr = global_state.get_current_instruction()
try:
callee_address, _, _, value, _, _, memory_out_offset, memory_out_size = get_call_parameters(
callee_address, _, _, value, _, memory_out_offset, memory_out_size = get_call_parameters(
global_state, self.dynamic_loader, True
)
except ValueError as e:
@ -1899,7 +1899,7 @@ class Instruction:
environment = global_state.environment
try:
callee_address, callee_account, call_data, value, call_data_type, gas, _, _ = get_call_parameters(
callee_address, callee_account, call_data, value, gas, _, _ = get_call_parameters(
global_state, self.dynamic_loader
)
except ValueError as e:
@ -1922,7 +1922,6 @@ class Instruction:
caller=environment.sender,
callee_account=environment.active_account,
call_data=call_data,
call_data_type=call_data_type,
call_value=environment.callvalue,
)
raise TransactionStartSignal(transaction, self.op_code)
@ -1937,7 +1936,7 @@ class Instruction:
instr = global_state.get_current_instruction()
try:
callee_address, _, _, value, _, _, memory_out_offset, memory_out_size = get_call_parameters(
callee_address, _, _, value, _, memory_out_offset, memory_out_size = get_call_parameters(
global_state, self.dynamic_loader
)
except ValueError as e:
@ -2002,7 +2001,7 @@ class Instruction:
# TODO: implement me
instr = global_state.get_current_instruction()
try:
callee_address, callee_account, call_data, value, call_data_type, gas, memory_out_offset, memory_out_size = get_call_parameters(
callee_address, callee_account, call_data, value, gas, memory_out_offset, memory_out_size = get_call_parameters(
global_state, self.dynamic_loader
)
except ValueError as e:

@ -47,7 +47,7 @@ class Storage:
except ValueError:
pass
if self.concrete:
return 0
return symbol_factory.BitVecVal(0, 256)
self._storage[item] = symbol_factory.BitVecVal(0, 256)
return self._storage[item]

@ -1,4 +1,7 @@
"""This module declares classes to represent call data."""
from typing import Union, Any
from mythril.laser.smt import K, Array, If, simplify, Concat, Expression, BitVec
from enum import Enum
from typing import Any, Union
@ -19,11 +22,6 @@ from mythril.laser.smt import (
)
class CalldataType(Enum):
CONCRETE = 1
SYMBOLIC = 2
class BaseCalldata:
"""Base calldata class This represents the calldata provided when sending a
transaction to a contract."""

@ -5,8 +5,7 @@ from typing import Dict
from z3 import ExprRef
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.calldata import BaseCalldata, CalldataType
from mythril.laser.smt import symbol_factory
from mythril.laser.ethereum.state.calldata import BaseCalldata
class Environment:
@ -22,7 +21,6 @@ class Environment:
callvalue: ExprRef,
origin: ExprRef,
code=None,
calldata_type=CalldataType.SYMBOLIC,
):
"""
@ -47,7 +45,6 @@ class Environment:
self.sender = sender
self.calldata = calldata
self.calldata_type = calldata_type
self.gasprice = gasprice
self.origin = origin
self.callvalue = callvalue
@ -72,5 +69,4 @@ class Environment:
gasprice=self.gasprice,
callvalue=self.callvalue,
origin=self.origin,
calldata_type=self.calldata_type,
)

@ -43,8 +43,12 @@ class Memory:
:return: 32 byte word at the specified index
"""
try:
return util.concrete_int_from_bytes(
bytes([util.get_concrete_int(b) for b in self[index : index + 32]]), 0
return symbol_factory.BitVecVal(
util.concrete_int_from_bytes(
bytes([util.get_concrete_int(b) for b in self[index : index + 32]]),
0,
),
256,
)
except:
result = simplify(

@ -6,8 +6,11 @@ from datetime import datetime, timedelta
from functools import reduce
from typing import Callable, Dict, List, Tuple, Union
from mythril.laser.ethereum.cfg import Edge, JumpType, Node, NodeFlags
from mythril.laser.ethereum.evm_exceptions import StackUnderflowException, VmException
from mythril import alarm
from mythril.exceptions import OutOfTimeError
from mythril.laser.ethereum.cfg import NodeFlags, Node, Edge, JumpType
from mythril.laser.ethereum.evm_exceptions import StackUnderflowException
from mythril.laser.ethereum.evm_exceptions import VmException
from mythril.laser.ethereum.instructions import Instruction
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.global_state import GlobalState
@ -50,6 +53,7 @@ class LaserEVM:
create_timeout=10,
strategy=DepthFirstSearchStrategy,
transaction_count=2,
requires_statespace=True,
):
"""
@ -67,8 +71,6 @@ class LaserEVM:
self.world_state = world_state
self.open_states = [world_state]
self.nodes = {}
self.edges = []
self.coverage = {}
self.total_states = 0
@ -79,9 +81,14 @@ class LaserEVM:
self.max_depth = max_depth
self.transaction_count = transaction_count
self.execution_timeout = execution_timeout
self.execution_timeout = execution_timeout or 0
self.create_timeout = create_timeout
self.requires_statespace = requires_statespace
if self.requires_statespace:
self.nodes = {}
self.edges = []
self.time = None
self.pre_hooks = defaultdict(list)
@ -125,37 +132,46 @@ class LaserEVM:
:param contract_name:
"""
log.debug("Starting LASER execution")
self.time = datetime.now()
if main_address:
log.info("Starting message call transaction to {}".format(main_address))
self._execute_transactions(main_address)
try:
alarm.start_timeout(self.execution_timeout)
self.time = datetime.now()
elif creation_code:
log.info("Starting contract creation transaction")
created_account = execute_contract_creation(
self, creation_code, contract_name
)
log.info(
"Finished contract creation, found {} open states".format(
len(self.open_states)
if main_address:
log.info("Starting message call transaction to {}".format(main_address))
self._execute_transactions(main_address)
elif creation_code:
log.info("Starting contract creation transaction")
created_account = execute_contract_creation(
self, creation_code, contract_name
)
)
if len(self.open_states) == 0:
log.warning(
"No contract was created during the execution of contract creation "
"Increase the resources for creation execution (--max-depth or --create-timeout)"
log.info(
"Finished contract creation, found {} open states".format(
len(self.open_states)
)
)
if len(self.open_states) == 0:
log.warning(
"No contract was created during the execution of contract creation "
"Increase the resources for creation execution (--max-depth or --create-timeout)"
)
self._execute_transactions(created_account.address)
self._execute_transactions(created_account.address)
except OutOfTimeError:
log.warning("Timeout occurred, ending symbolic execution")
finally:
alarm.disable_timeout()
log.info("Finished symbolic execution")
log.info(
"%d nodes, %d edges, %d total states",
len(self.nodes),
len(self.edges),
self.total_states,
)
if self.requires_statespace:
log.info(
"%d nodes, %d edges, %d total states",
len(self.nodes),
len(self.edges),
self.total_states,
)
for code, coverage in self.coverage.items():
cov = (
reduce(lambda sum_, val: sum_ + 1 if val else sum_, coverage[1])
@ -176,7 +192,11 @@ class LaserEVM:
initial_coverage = self._get_covered_instructions()
self.time = datetime.now()
log.info("Starting message call transaction, iteration: {}".format(i))
log.info(
"Starting message call transaction, iteration: {}, {} initial states".format(
i, len(self.open_states)
)
)
execute_message_call(self, address)
@ -209,15 +229,12 @@ class LaserEVM:
"""
final_states = []
for global_state in self.strategy:
if self.execution_timeout and not create:
if (
self.time + timedelta(seconds=self.execution_timeout)
<= datetime.now()
):
return final_states + [global_state] if track_gas else None
elif self.create_timeout and create:
if self.time + timedelta(seconds=self.create_timeout) <= datetime.now():
return final_states + [global_state] if track_gas else None
if (
self.create_timeout
and create
and self.time + timedelta(seconds=self.create_timeout) <= datetime.now()
):
return final_states + [global_state] if track_gas else None
try:
new_states, op_code = self.execute_state(global_state)
@ -423,10 +440,13 @@ class LaserEVM:
old_node = state.node
state.node = new_node
new_node.constraints = state.mstate.constraints
self.nodes[new_node.uid] = new_node
self.edges.append(
Edge(old_node.uid, new_node.uid, edge_type=edge_type, condition=condition)
)
if self.requires_statespace:
self.nodes[new_node.uid] = new_node
self.edges.append(
Edge(
old_node.uid, new_node.uid, edge_type=edge_type, condition=condition
)
)
if edge_type == JumpType.RETURN:
new_node.flags |= NodeFlags.CALL_RETURN

@ -4,7 +4,7 @@ from typing import List, Union
from mythril.disassembler.disassembly import Disassembly
from mythril.laser.ethereum.cfg import Node, Edge, JumpType
from mythril.laser.ethereum.state.calldata import CalldataType, ConcreteCalldata
from mythril.laser.ethereum.state.calldata import ConcreteCalldata
from mythril.laser.ethereum.state.global_state import GlobalState
from mythril.laser.ethereum.transaction.transaction_models import (
MessageCallTransaction,
@ -54,7 +54,6 @@ def execute_message_call(
caller=caller_address,
callee_account=open_world_state[callee_address],
call_data=ConcreteCalldata(next_transaction_id, data),
call_data_type=CalldataType.SYMBOLIC,
call_value=value,
)
@ -73,10 +72,14 @@ def _setup_global_state_for_execution(laser_evm, transaction) -> None:
global_state = transaction.initial_global_state()
global_state.transaction_stack.append((transaction, None))
new_node = Node(global_state.environment.active_account.contract_name)
new_node = Node(
global_state.environment.active_account.contract_name,
function_name=global_state.environment.active_function_name,
)
laser_evm.nodes[new_node.uid] = new_node
if transaction.world_state.node:
if laser_evm.requires_statespace:
laser_evm.nodes[new_node.uid] = new_node
if transaction.world_state.node and laser_evm.requires_statespace:
laser_evm.edges.append(
Edge(
transaction.world_state.node.uid,
@ -85,6 +88,7 @@ def _setup_global_state_for_execution(laser_evm, transaction) -> None:
condition=None,
)
)
global_state.node = new_node
new_node.states.append(global_state)
laser_evm.work_list.append(global_state)

@ -6,11 +6,7 @@ import logging
from mythril.laser.smt import symbol_factory
from mythril.disassembler.disassembly import Disassembly
from mythril.laser.ethereum.cfg import Node, Edge, JumpType
from mythril.laser.ethereum.state.calldata import (
CalldataType,
BaseCalldata,
SymbolicCalldata,
)
from mythril.laser.ethereum.state.calldata import BaseCalldata, SymbolicCalldata
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.transaction.transaction_models import (
MessageCallTransaction,
@ -53,7 +49,6 @@ def execute_message_call(laser_evm, callee_address: str) -> None:
caller=symbol_factory.BitVecVal(ATTACKER_ADDRESS, 256),
callee_account=open_world_state[callee_address],
call_data=SymbolicCalldata(next_transaction_id),
call_data_type=CalldataType.SYMBOLIC,
call_value=symbol_factory.BitVecSym(
"call_value{}".format(next_transaction_id), 256
),
@ -99,7 +94,6 @@ def execute_contract_creation(
caller=symbol_factory.BitVecVal(CREATOR_ADDRESS, 256),
callee_account=new_account,
call_data=[],
call_data_type=CalldataType.SYMBOLIC,
call_value=symbol_factory.BitVecSym(
"call_value{}".format(next_transaction_id), 256
),
@ -120,18 +114,23 @@ def _setup_global_state_for_execution(laser_evm, transaction) -> None:
global_state = transaction.initial_global_state()
global_state.transaction_stack.append((transaction, None))
new_node = Node(global_state.environment.active_account.contract_name)
new_node = Node(
global_state.environment.active_account.contract_name,
function_name=global_state.environment.active_function_name,
)
if laser_evm.requires_statespace:
laser_evm.nodes[new_node.uid] = new_node
laser_evm.nodes[new_node.uid] = new_node
if transaction.world_state.node:
laser_evm.edges.append(
Edge(
transaction.world_state.node.uid,
new_node.uid,
edge_type=JumpType.Transaction,
condition=None,
if laser_evm.requires_statespace:
laser_evm.edges.append(
Edge(
transaction.world_state.node.uid,
new_node.uid,
edge_type=JumpType.Transaction,
condition=None,
)
)
)
global_state.mstate.constraints += transaction.world_state.node.constraints
new_node.constraints = global_state.mstate.constraints

@ -2,11 +2,11 @@
execution."""
import array
from typing import Union
from z3 import ExprRef
from typing import Union
from mythril.disassembler.disassembly import Disassembly
from mythril.laser.ethereum.state.environment import Environment
from mythril.laser.ethereum.state.calldata import BaseCalldata, SymbolicCalldata
from mythril.laser.ethereum.state.account import Account
from mythril.laser.ethereum.state.calldata import BaseCalldata, SymbolicCalldata
from mythril.laser.ethereum.state.environment import Environment
@ -61,7 +61,6 @@ class BaseTransaction:
gas_limit=None,
origin=None,
code=None,
call_data_type=None,
call_value=None,
init_call_data=True,
):
@ -90,11 +89,6 @@ class BaseTransaction:
else:
self.call_data = call_data if isinstance(call_data, BaseCalldata) else None
self.call_data_type = (
call_data_type
if call_data_type is not None
else symbol_factory.BitVecSym("call_data_type{}".format(identifier), 256)
)
self.call_value = (
call_value
if call_value is not None
@ -132,7 +126,6 @@ class MessageCallTransaction(BaseTransaction):
self.call_value,
self.origin,
code=self.code or self.callee_account.code,
calldata_type=self.call_data_type,
)
return super().initial_global_state_from_environment(
environment, active_function="fallback"
@ -169,7 +162,6 @@ class ContractCreationTransaction(BaseTransaction):
self.call_value,
self.origin,
self.code,
calldata_type=self.call_data_type,
)
return super().initial_global_state_from_environment(
environment, active_function="constructor"

@ -10,7 +10,7 @@ import logging
import os
import platform
import re
from configparser import ConfigParser
import traceback
from pathlib import Path
from shutil import copyfile
@ -32,7 +32,13 @@ from mythril.exceptions import CompilerError, CriticalError, NoContractFoundErro
from mythril.solidity.soliditycontract import SolidityContract, get_contracts_from_file
from mythril.support import signatures
from mythril.support.loader import DynLoader
from mythril.support.truffle import analyze_truffle_project
from mythril.exceptions import CompilerError, NoContractFoundError, CriticalError
from mythril.analysis.symbolic import SymExecWrapper
from mythril.analysis.callgraph import generate_graph
from mythril.analysis.traceexplore import get_serializable_statespace
from mythril.analysis.security import fire_lasers, retrieve_callback_issues
from mythril.analysis.report import Report
from mythril.ethereum.interface.leveldb.client import EthLevelDB
log = logging.getLogger(__name__)
@ -558,23 +564,33 @@ class Mythril(object):
"""
all_issues = []
for contract in contracts or self.contracts:
sym = SymExecWrapper(
contract,
address,
strategy,
dynloader=DynLoader(
self.eth,
storage_loading=self.onchain_storage_access,
contract_loading=self.dynld,
),
max_depth=max_depth,
execution_timeout=execution_timeout,
create_timeout=create_timeout,
transaction_count=transaction_count,
modules=modules,
)
issues = fire_lasers(sym, modules)
try:
sym = SymExecWrapper(
contract,
address,
strategy,
dynloader=DynLoader(
self.eth,
storage_loading=self.onchain_storage_access,
contract_loading=self.dynld,
),
max_depth=max_depth,
execution_timeout=execution_timeout,
create_timeout=create_timeout,
transaction_count=transaction_count,
modules=modules,
compulsory_statespace=False,
)
issues = fire_lasers(sym, modules)
except KeyboardInterrupt:
log.critical("Keyboard Interrupt")
issues = retrieve_callback_issues(modules)
except Exception:
log.critical(
"Exception occurred, aborting analysis. Please report this issue to the Mythril GitHub page.\n"
+ traceback.format_exc()
)
issues = retrieve_callback_issues(modules)
if type(contract) == SolidityContract:
for issue in issues:

@ -63,6 +63,8 @@ def analyze_truffle_project(sigs, args):
create_timeout=args.create_timeout,
execution_timeout=args.execution_timeout,
transaction_count=args.transaction_count,
modules=args.modules or [],
compulsory_statespace=False,
)
issues = fire_lasers(sym)

@ -10,7 +10,7 @@ eth-hash>=0.1.0
eth-keyfile>=0.5.1
eth-keys>=0.2.0b3
eth-rlp>=0.1.0
eth-tester>=0.1.0b21
eth-tester==0.1.0b32
eth-typing>=2.0.0
eth-utils>=1.0.1
jinja2>=2.9

@ -86,7 +86,7 @@ setup(
"eth-keyfile>=0.5.1",
"eth-keys>=0.2.0b3",
"eth-rlp>=0.1.0",
"eth-tester>=0.1.0b21",
"eth-tester==0.1.0b32",
"eth-typing>=2.0.0",
"coverage",
"jinja2>=2.9",

@ -75,13 +75,8 @@ def _all_info(laser):
def _test_natives(laser_info, test_list, test_name):
success = 0
for i, j in test_list:
if (str(i) in laser_info or str(int(i, 16)) in laser_info) == j:
success += 1
else:
print("Failed:", str(int(i, 16)), str(j))
assert success == len(test_list)
assert (str(i) in laser_info or str(int(i, 16)) in laser_info) == j
class NativeTests(BaseTestCase):
@ -99,7 +94,6 @@ class NativeTests(BaseTestCase):
laser_info = str(_all_info(laser))
print(laser_info)
_test_natives(laser_info, SHA256_TEST, "SHA256")
_test_natives(laser_info, RIPEMD160_TEST, "RIPEMD160")
_test_natives(laser_info, ECRECOVER_TEST, "ECRECOVER")

Loading…
Cancel
Save