Example #1
0
 def finalize_block(self, block: BlockAPI) -> BlockAPI:
     block = super().finalize_block(block)
     nonce, mix_hash = pow.mine_pow_nonce(block.number,
                                          block.header.mining_hash,
                                          block.header.difficulty)
     return block.copy(
         header=block.header.copy(nonce=nonce, mix_hash=mix_hash))
Example #2
0
 def finalize_block(self, block):
     from eth.consensus import pow
     block = super().finalize_block(block)
     nonce, mix_hash = pow.mine_pow_nonce(block.number,
                                          block.header.mining_hash,
                                          block.header.difficulty)
     return block.copy(
         header=block.header.copy(nonce=nonce, mix_hash=mix_hash))
Example #3
0
 def mine_next_block(self):
     block = self.chain.get_vm().finalize_block(self.chain.get_block())
     nonce, mix_hash = mine_pow_nonce(block.number,
                                      block.header.mining_hash,
                                      block.header.difficulty)
     self.chain.mine_block(mix_hash=mix_hash, nonce=nonce)
     self.vm = self.chain.get_vm()
     return self.chain.get_block_by_header(self.chain.get_canonical_head())
Example #4
0
    def fuzz(self, log=None):
        '''Mines a block, executing a number of transactions to fuzz the contracts being tested.
        '''
        for _ in range(self.txs):
            contract_address = choice(list(self.contracts))
            contract_name = self.contract_names[contract_address]
            function_name = choice(list(self.contracts[contract_address]))

            function_hash = self.contracts[contract_address][function_name][
                'hash']
            call = self.fuzzer.generate_args(
                contract_name,
                function_name, [
                    arg for arg in self.contracts[contract_address]
                    [function_name]['in']
                ],
                value=self.contracts[contract_address][function_name]
                ['payable'])

            _, _, computation = self.call_function(contract_address,
                                                   function_hash, call)

            self.log_function_call(contract_name, function_name, call['pk'],
                                   call['args'], call['value'],
                                   computation.get_gas_used())
            out_types = [
                arg['type'] for arg in self.contracts[contract_address]
                [function_name]['out']
            ]
            try:
                computation.raise_if_error()
                logging.log(
                    0,
                    f" Returned value: {decode_abi(out_types, computation.output)}"
                )
            except Revert as r:
                logging.log(0, f" Call reverted. {r.args[0]}")
            except VMError as e:
                logging.log(0, f" Call resulted in error: {e}")
            except Exception as e:
                logging.log(
                    0, f" Something went wrong while decoding the output. {e}")

            if self.progress:
                with self.progress:
                    self.progress.update()

        block = self.get_vm().finalize_block(self.get_block())

        nonce, mix_hash = mine_pow_nonce(block.number,
                                         block.header.mining_hash,
                                         block.header.difficulty)

        self.mine_block(mix_hash=mix_hash, nonce=nonce)
Example #5
0
    def finalize_block(self, block: BlockAPI) -> BlockAndMetaWitness:
        block_result = super().finalize_block(block)
        block = block_result.block

        nonce, mix_hash = pow.mine_pow_nonce(block.number,
                                             block.header.mining_hash,
                                             block.header.difficulty)

        mined_block = block.copy(
            header=block.header.copy(nonce=nonce, mix_hash=mix_hash))

        return BlockAndMetaWitness(mined_block, block_result.meta_witness)
Example #6
0
 def _mine_block(self):
     """
     Mines a new block with everything that needs to be done. The computation classes reset with every
     block that is mined, so they are set again within this function.
     :return:
     """
     block = self.chain.get_vm().finalize_block(self.chain.get_block())
     nonce, mix_hash = mine_pow_nonce(block.number,
                                      block.header.mining_hash,
                                      block.header.difficulty)
     self.chain.mine_block(mix_hash=mix_hash, nonce=nonce)
     logger.info("Mined block {no} with nonce {n} and hash {h}".format(
         no=block.number,
         n=int.from_bytes(nonce, "big", signed=False),
         h=mix_hash.hex()))
     self.vm = self.chain.get_vm()
     self.vm.state.computation_class = MyComputation
     self.vm.get_state_class().computation_class = MyComputation
Example #7
0
    data=b'',
)

signed_tx1 = tx1.as_signed_transaction(SENDER_PRIVATE_KEY)

chain.apply_transaction(signed_tx1)

# We have to finalize the block first in order to be able read the
# attributes that are important for the PoW algorithm
block_result = chain.get_vm().finalize_block(chain.get_block())
block = block_result.block

# based on mining_hash, block number and difficulty we can perform
# the actual Proof of Work (PoW) mechanism to mine the correct
# nonce and mix_hash for this block
nonce, mix_hash = mine_pow_nonce(block.number, block.header.mining_hash,
                                 block.header.difficulty)

block = chain.mine_block(mix_hash=mix_hash, nonce=nonce)

print("BLOCK1 SENDER BALANCE : {}".format(vm.state.get_balance(SENDER)))
print("BLOCK1 RECEIVER BALANCE : {}".format(vm.state.get_balance(RECEIVER)))

######### Tx2 ###########################
# nonce = vm.get_transaction_nonce(SENDER)
vm = chain.get_vm()
nonce = vm.state.get_nonce(SENDER)

tx2 = vm.create_unsigned_transaction(
    nonce=nonce,
    gas_price=0,
    gas=21000,
Example #8
0
    def init(cls, contracts, ast, tx=10, progress=None, **kwargs):
        '''Builds a new MiningChain, with the given contract bytecodes, and an AtomicDB database.
        '''
        GENESIS_PARAMS = {
            'parent_hash': constants.GENESIS_PARENT_HASH,
            'uncles_hash': constants.EMPTY_UNCLE_HASH,
            'coinbase': constants.ZERO_ADDRESS,
            'transaction_root': constants.BLANK_ROOT_HASH,
            'receipt_root': constants.BLANK_ROOT_HASH,
            'difficulty': 1,
            'block_number': constants.GENESIS_BLOCK_NUMBER,
            'gas_limit': 100000000,
            'timestamp': 1514764800,
            'extra_data': constants.GENESIS_EXTRA_DATA,
            'nonce': constants.GENESIS_NONCE
        }

        sk = keys.PrivateKey(
            randint(1, 2**32 - 1).to_bytes(32, byteorder='big'))
        pk = Address(sk.public_key.to_canonical_address())

        _faucet = {'sk': sk, 'pk': pk}

        GENESIS_STATE = {
            _faucet['pk']: {
                # Practically infinite
                'balance': to_wei(2**32 - 1, 'ether'),
                'nonce': 0,
                'code': b'',
                'storage': {}
            }
        }

        chain = cls.from_genesis(AtomicDB(), GENESIS_PARAMS, GENESIS_STATE)

        chain._faucet = _faucet
        logging.log(0, f"Faucet initialized at address: {pk}")

        chain.fuzzer = SolidityFuzzer(chain.transfer_from_faucet,
                                      faucet_sk=_faucet['sk'],
                                      **kwargs)

        chain.fuzzing_data = FuzzingData()
        chain.progress = progress

        # Number of transactions per block
        chain.txs = tx
        """
        Adresses of all the contracts being tested
        Dictionary defined as :
        {
            [address]: {
                [function]: {
                    'hash': [hash],
                    'args: [
                        arg1,
                        arg2,
                        ...
                    ],
                    'compilation_estimate': [estimate]
                }
            }
        }
        """
        chain.contracts = {}
        chain.contract_names = {}

        logging.log(0, "CONTRACT TRANSACTIONS BEGIN\n")

        for filename, contracts in contracts.items():
            # Find the ast for this file
            ast_nodes = ast[filename]['ast']['nodes']
            for contract_name, desc in contracts.items():
                if all(abi['type'] != 'constructor' for abi in desc['abi']):
                    logging.log(
                        0,
                        f"Skipped contract {contract_name} because it didn't have a constructor"
                    )
                    continue

                # Find the ast object for this contract
                contract_nodes = [
                    node for node in ast_nodes
                    if (node['nodeType'] == 'ContractDefinition'
                        and node['name'] == contract_name)
                ][0]['nodes']

                # Find the variable definitions in this contract

                variables = [
                    [node['name'], node['typeName']['name']]
                    for node in contract_nodes
                    if node['nodeType'] == 'VariableDeclaration'
                    and node['typeName']['nodeType'] == 'ElementaryTypeName'
                ]

                chain.fuzzer.register_contract(contract_name, variables)

                # Register all the functions in the fuzzer
                for node in contract_nodes:
                    if node['nodeType'] != 'FunctionDefinition':
                        continue
                    name = node['name'] if not node[
                        'isConstructor'] else '__constructor__'
                    parameters = [
                        [paramNode['name'], paramNode['typeName']['name']]
                        for paramNode in node['parameters']['parameters']
                        if 'typeName' in paramNode and paramNode['typeName']
                        ['nodeType'] == 'ElementaryTypeName'
                    ]

                    def reduce_ast(acc, node):
                        if (type(node) is dict and 'nodeType' in node
                                and node['nodeType'] == 'ExpressionStatement'
                                and node['expression']['nodeType']
                                == 'FunctionCall' and
                                node['expression']['expression']['nodeType']
                                == 'Identifier'
                                and node['expression']['expression']['name']
                                == 'require'):

                            try:
                                constraint = new_constraint(
                                    node['expression']['arguments'][0],
                                    [name for name, type in parameters],
                                    chain.get_state_contract(contract_name))

                                if constraint:
                                    acc.append(constraint)
                            except NotImplementedError as e:
                                logging.warning(
                                    f'Operation {e} not implemented for constraints'
                                )

                        elif type(node) is list:
                            acc += reduce(reduce_ast, node, [])
                        elif type(node) is dict:
                            acc += reduce(reduce_ast, node.values(), [])

                        return acc

                    # Extract the explicit constraints defined in the source code
                    constraints = reduce(reduce_ast,
                                         node['body']['statements'], [])
                    """ 
                    [
                        new_constraint(
                            expression['expression']['arguments'][0])
                        for expression in node['body']['statements']
                        if expression['nodeType'] == 'ExpressionStatement'
                        and expression['expression']['nodeType'] == 'FunctionCall'
                        and expression['expression']['expression']['name'] == 'require'
                    ] """

                    logging.info(
                        f'{len(constraints)} constraint{"" if len(constraints) == 1 else "s"} extracted for {contract_name}.{name}'
                    )

                    chain.fuzzer.register_function(contract_name, name,
                                                   parameters, constraints)

                constructor = [
                    abi for abi in desc['abi'] if abi['type'] == 'constructor'
                ][0]
                call = chain.fuzzer.generate_args(
                    contract_name,
                    '__constructor__', [arg for arg in constructor['inputs']],
                    value=False)

                _, _, computation = chain.call_function(
                    constants.CREATE_CONTRACT_ADDRESS,
                    decode_hex(desc['evm']['bytecode']['object']), call)

                chain.log_function_call(contract_name, f"constructor",
                                        call['pk'], call['args'],
                                        call['value'],
                                        computation.get_gas_used())
                chain.fuzzing_data.set_expected_cost(
                    contract_name, f"constructor",
                    desc['evm']['gasEstimates']['creation']['totalCost'])

                contract_address = computation.msg.storage_address

                chain.fuzzer.set_contract_address(contract_name,
                                                  contract_address)

                chain.contract_names[contract_address] = contract_name
                chain.contracts[contract_address] = {}

                for abi in desc['abi']:
                    if abi['type'] != 'function':
                        continue
                    fname = abi['name']
                    fin = [inp for inp in abi['inputs']]
                    fout = [out for out in abi['outputs']]

                    chain.fuzzer.set_args(contract_name, fname,
                                          [arg for arg in fin])

                    chain.fuzzer.set_out(contract_name, fname,
                                         [arg['type'] for arg in fout])

                    chain.fuzzer.set_mutability(
                        contract_name, fname, abi['stateMutability'] == 'view'
                        or abi['stateMutability'] == 'pure')

                    chain.contracts[contract_address][fname] = {
                        'in': fin,
                        'out': fout,
                        'payable': abi['payable']
                    }

                logging.log(0, " Compilation gas estimates:")

                for function, fhash_encoded in desc['evm'][
                        'methodIdentifiers'].items():
                    fname = function.split("(")[0]

                    fhash = decode_hex(fhash_encoded)

                    chain.fuzzer.set_function_hash(contract_name, fname, fhash)

                    chain.contracts[contract_address][fname]['hash'] = fhash
                    chain.contracts[contract_address][fname][
                        'compilation_estimate'] = desc['evm']['gasEstimates'][
                            'external'][function]

                    function_signature = f"{function} => ({', '.join(arg['type'] for arg in chain.contracts[contract_address][fname]['out'])})"

                    logging.log(
                        0,
                        f" {function_signature}: {desc['evm']['gasEstimates']['external'][function]}{' payable' if chain.contracts[contract_address][fname]['payable'] else ''}"
                    )
                    chain.fuzzing_data.set_expected_cost(
                        contract_name, fname,
                        desc['evm']['gasEstimates']['external'][function])

        block = chain.get_vm().finalize_block(chain.get_block())

        nonce, mix_hash = mine_pow_nonce(block.number,
                                         block.header.mining_hash,
                                         block.header.difficulty)

        chain.mine_block(mix_hash=mix_hash, nonce=nonce)

        return chain
Example #9
0
)
signed_tx = tx.as_signed_transaction(
    keys.PrivateKey(decode_hex(SHARDS_CONFIG[0]['PRI_KEYS'][0])))

print("[*] Making a new StretchXMessage that corresponds to the transaction:")
print("\t", 'to', ":", encode_hex(signed_tx['to']))
for x in ['data', 'gas_price', 'gas', 'nonce', 'value']:
    print("\t", x, ":", signed_tx[x])
print("\t", 'sender', ":", encode_hex(signed_tx.sender))

xmessage = StretchXMessage.from_transaction(signed_tx, 1,
                                            constants.ZERO_HASH32)
print("[*] Applying XMessage to chain")
chains[0].apply_xmessage_sent(xmessage)
blockA0 = chains[0].get_vm().finalize_block(chains[0].get_block())
nonce, mix_hash = mine_pow_nonce(blockA0.number, blockA0.header.mining_hash,
                                 blockA0.header.difficulty)
print("[*] Mined on Shard 0:", chains[0].mine_block(mix_hash=mix_hash,
                                                    nonce=nonce))
print("\tSent Message Log", blockA0.xmessage_sent)

# ------------------------------------------------
print("=========================================")
print("                SHARD 1                  ")
print("=========================================")
nonce = chains[1].get_vm().state.account_db.get_nonce(MAGIC_ADDRESS)
tx_dict = blockA0.xmessage_sent[0].get_transaction_dict()
tx = chains[1].get_vm().create_unsigned_transaction(
    nonce=nonce,
    gas_price=tx_dict['gas_price'],
    gas=tx_dict['gas'],
    to=tx_dict['to'],