Exemple #1
0
def setup(host, port, contract, gas, gas_price, private_key):
    gas = int(gas)
    gas_price = int(gas_price)
    json_rpc = EthJsonRpc(host, port)
    coinbase = json_rpc.eth_coinbase()["result"]
    if private_key:
        print "Your address for your private key: {}".format(
            privtoaddr(private_key.decode('hex')).encode('hex'))
    else:
        print "Your coinbase: {}".format(coinbase)
    contract_abi = json.loads(
        '[{"inputs": [], "constant": true, "type": "function", "name": "startDate", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "CROWDFUNDING_PERIOD", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": false, "type": "function", "name": "emergencyCall", "outputs": [{"type": "bool", "name": ""}]}, {"inputs": [{"type": "address", "name": "singularDTVFundAddress"}, {"type": "address", "name": "singularDTVTokenAddress"}], "constant": false, "type": "function", "name": "setup", "outputs": [{"type": "bool", "name": ""}]}, {"inputs": [], "constant": false, "type": "function", "name": "withdrawFunding", "outputs": [{"type": "bool", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "fundBalance", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "singularDTVFund", "outputs": [{"type": "address", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "baseValue", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "TOKEN_TARGET", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "singularDTVToken", "outputs": [{"type": "address", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "owner", "outputs": [{"type": "address", "name": ""}]}, {"inputs": [{"type": "uint256", "name": "valueInWei"}], "constant": false, "type": "function", "name": "changeBaseValue", "outputs": [{"type": "bool", "name": ""}]}, {"inputs": [{"type": "address", "name": ""}], "constant": true, "type": "function", "name": "investments", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": false, "type": "function", "name": "fund", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "stage", "outputs": [{"type": "uint8", "name": ""}]}, {"inputs": [], "constant": false, "type": "function", "name": "updateStage", "outputs": [{"type": "uint8", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "valuePerShare", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "TOKEN_LOCKING_PERIOD", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "campaignEndedSuccessfully", "outputs": [{"type": "bool", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "workshopWaited2Years", "outputs": [{"type": "bool", "name": ""}]}, {"inputs": [], "constant": true, "type": "function", "name": "CAP", "outputs": [{"type": "uint256", "name": ""}]}, {"inputs": [], "constant": false, "type": "function", "name": "withdrawForWorkshop", "outputs": [{"type": "bool", "name": ""}]}, {"inputs": [], "type": "constructor"}]'
    )
    translator = ContractTranslator(contract_abi)
    data = translator.encode("emergencyCall", ()).encode("hex")
    bc_return_val = json_rpc.eth_call(to_address=contract, data=data)["result"]
    result_decoded = translator.decode("emergencyCall",
                                       bc_return_val[2:].decode("hex"))[0]
    if result_decoded:
        if private_key:
            address = privtoaddr(private_key.decode('hex'))
            nonce = int(
                json_rpc.eth_getTransactionCount('0x' + address.encode('hex'))
                ["result"][2:], 16)
            tx = Transaction(nonce, gas_price, gas, contract, 0,
                             data.decode('hex'))
            tx.sign(private_key.decode('hex'))
            raw_tx = rlp.encode(tx).encode('hex')
            transaction_hash = json_rpc.eth_sendRawTransaction(
                "0x" + raw_tx)["result"]
        else:
            transaction_hash = json_rpc.eth_sendTransaction(
                coinbase,
                to_address=contract,
                data=data,
                gas=gas,
                gas_price=gas_price)["result"]
        wait_for_transaction_receipt(json_rpc, transaction_hash)
        print 'Transaction {} for contract {} completed.'.format(
            "emergencyCall", contract)
Exemple #2
0
class ContractWrapper:
    def __init__(
        self,
        the_code=False,
        the_sig=None,
        the_args=None,
        the_address=False,
        events_callback=False,
        deploy_callback=False,
        blocking_sleep_time=0.1,
        rpc_host=DEFAULT_RPC_HOST,
        rpc_port=DEFAULT_RPC_PORT,
        settings_confirm_states={},
        contract_address=False,
        start_at_current_block=False,
        auto_deploy=True,
        contract_thread_sleep_time=1.0,
        reorg_callback=False,
    ):
        """
        Simple contract wrapper, assists with deploying contract, sending transactions, and tracking event logs.
        
        Args:
        - the_code: solidity code for contract that should be deployed, prior to any operations.
        - the_address: address of already-deployed main contract.
        - contract_address: contract address, from previous `deploy()` call.
        - the_sig: optional constructor signature.
        - the_args: optional constructor args.
        - events_callback: callback for event messages e.g. `TheLog()`, `MintEvent()`, `LockupTokEvent()`, `TransferTokEvent()`.
        - deploy_callback: callback for contract deploys.
        - blocking_sleep_time: time to sleep when blocking and polling for a transaction receipt.
        """

        self.block_details = {}

        self.reorg_callback = reorg_callback
        self.confirmation_tracker = {
        }  ## {'block_hash':{'prev_block_hash':xx, 'block_num':yy}}

        self.done_block_nums = {}  ## {confirm_state:set()}
        self.done_transactions = {}  ## {confirm_state:set()}
        self.prev_block_num = {}  ## {confirm_state:set()}

        self.blocking_sleep_time = blocking_sleep_time

        self.c = EthJsonRpc(rpc_host, rpc_port)

        self.contract_thread_sleep_time = contract_thread_sleep_time

        self.start_at_current_block = start_at_current_block

        self.current_block_at_init = self.c.eth_blockNumber()

        if self.start_at_current_block:
            self.last_incoming_block = max(0, self.current_block_at_init - 1)
        else:
            self.last_incoming_block = 0

        self.starting_block_num = self.last_incoming_block

        self.msgs = {}  ## {block_num:[msg, msg, msg]}

        self.the_code = the_code
        self.the_sig = the_sig
        self.the_args = the_args

        self.contract_address = the_address

        assert self.the_code or self.contract_address

        self.loop_block_num = -1

        self.confirm_states = settings_confirm_states

        self.events_callback = events_callback

        self.pending_transactions = {}  ## {tx:callback}
        self.pending_logs = {}
        self.latest_block_num = -1

        self.latest_block_num_done = 0

        self.send_transaction_queue = Queue()

        self.is_deployed = False

        if auto_deploy:
            if the_address:
                assert self.check_anything_deployed(the_address), (
                    'NOTHING DEPLOYED AT SPECIFIED ADDRESS:', the_address)
                self.is_deployed = True
            elif the_code:
                self.deploy()

    def check_anything_deployed(self, address):
        """ Basic sanity check, checks if ANY code is deployed at provided address. """
        if self.c.eth_getCode(address) == '0x0':
            return False
        return True

    def deploy(
        self,
        the_sig=False,
        the_args=False,
        block=False,
        deploy_from=False,
        callback=False,
    ):
        """ Deploy contract. Optional args_sig and args used to pass arguments to contract constructor."""

        if the_sig is not False:
            self.the_sig = the_sig

        if the_args is not False:
            self.the_args = the_args

        assert self.the_code

        if deploy_from is False:
            deploy_from = self.c.eth_coinbase()

        print('DEPLOYING_CONTRACT...', 'deploy_from:', deploy_from, 'the_sig:',
              the_sig, 'the_args:', the_args)
        # get contract address
        xx = self.c.eth_compileSolidity(self.the_code)
        #print ('GOT',xx)
        compiled = get_compiled_code(xx)

        contract_tx = self.c.create_contract(
            from_=deploy_from,
            code=compiled,
            gas=3000000,
            sig=self.the_sig,
            args=self.the_args,
        )

        if block:
            ## NOTE: @yusef feel free to switch back to this method if you want:
            #print('CONTRACT DEPLOYED, WAITING FOR CONFIRMATION')
            #wait_for_confirmation(self.c, contract_tx)

            print('BLOCKING FOR RECEIPT..')
            while True:
                receipt = self.c.eth_getTransactionReceipt(
                    contract_tx)  ## blocks to ensure transaction is mined
                if receipt:
                    break
                sleep(self.blocking_sleep_time)
            print('GOT RECEIPT')
        else:
            self.pending_transactions[contract_tx] = (callback,
                                                      self.latest_block_num)

        self.contract_address = str(self.c.get_contract_address(contract_tx))
        self.is_deployed = True
        print('DEPLOYED', self.contract_address)
        return self.contract_address

    def loop_once(self):
        assert self.is_deployed, 'Must deploy contract first.'

        had_any_events = False

        if self.c.eth_syncing():
            print('BLOCKCHAIN_STILL_SYNCING')
            return False

        if self.events_callback is not False:
            had_any_events = self.poll_incoming()

        had_any_events = self.poll_outgoing() or had_any_events

        num_fails = 0

        while self.send_transaction_queue.qsize():
            print('TRY_TO_SEND')
            tries, args, kw = self.send_transaction_queue.get()
            try:
                self._send_transaction(*args, **kw)
            except Exception as e:
                print('FAILED_TO_SEND', e, tries, args, kw)
                sleep(1)  ## TODO
                self.send_transaction_queue.put((tries + 1, args, kw))
                break

        return had_any_events

    def check_for_reorg(
        self,
        block_num,
    ):
        """ Check for reorg since last check, and reorgs during our reorg rewinding... """
        print('START check_for_reorg', block_num)

        return
        block_num = ethereum.utils.parse_int_or_hex(block_num)

        while True:

            cur_num = block_num
            had_reorg = False

            while True:
                if cur_num == self.starting_block_num:
                    break

                assert cur_num >= self.starting_block_num, (
                    cur_num, self.starting_block_num)

                ## Get info for prev and current:

                for x_block_num in [block_num, block_num - 1]:
                    if x_block_num not in self.block_details:
                        rh = self.c.eth_getBlockByNumber(x_block_num)

                        ## Strip down to just a couple fields:
                        block_h = {
                            'timestamp':
                            ethereum.utils.parse_int_or_hex(rh['timestamp']),
                            'hash':
                            rh['hash'],
                            'parentHash':
                            rh['parentHash'],
                            'blockNumber':
                            x_block_num,
                        }
                        self.block_details[x_block_num] = block_h

                ## Check for reorg:

                block_h = self.block_details[block_num]

                if block_h['parentHash'] != self.block_details[
                        block_h['blockNumber'] - 1]['hash']:
                    print('!!! REORG', block_num, '->', cur_num)
                    cur_num -= 1
                    self.latest_done_block = cur_num
                    had_reorg = True
                    continue
                break

            ## Rewind state if had_reorg:

            if had_reorg and (self.reorg_callback is not False):
                self.reorg_callback(cur_num)
                self.last_incoming_block = cur_num - 1

            ## If had_reorg, loop again - to detect another reorg that occured while we tracked down the reorg...

            if not had_reorg:
                break

        return had_reorg

    def poll_incoming(self, chunk_size=50):
        """
        https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newfilter

        - track buffer of events from old blocks
        - track pointer to last processed block
        """

        assert self.is_deployed, 'Must deploy contract first.'

        #self.latest_block_num = self.c.eth_blockNumber()

        from_block = self.last_incoming_block + 1

        params = {
            'from_block': fixed_int_to_hex(from_block),
            'to_block': 'latest',  #fixed_int_to_hex(from_block + chunk_size),
            'address': self.contract_address,
        }

        print('eth_newFilter', 'from_block:', from_block, 'params:', params)

        self.the_filter = str(self.c.eth_newFilter(**params))

        num_blocks = len(self.msgs)

        xx_msgs = self.c.eth_getFilterLogs(self.the_filter)

        for msg in xx_msgs:
            msg['blockNumber'] = ethereum.utils.parse_int_or_hex(
                msg['blockNumber'])
            if msg['blockNumber'] not in self.msgs:
                self.msgs[msg['blockNumber']] = []
            self.msgs[msg['blockNumber']].append(msg)

        if num_blocks == len(self.msgs):
            ## Nothing new
            assert not len(xx_msgs), len(xx_msgs)
            return False

        for do_state, state_num_blocks in self.confirm_states.items():

            longest_confirm_state = max(self.confirm_states.values())
            newest_block_num = max(max(self.msgs), self.last_incoming_block)

            ## Oldest to newest:

            for nn in xrange(
                    max(1, self.last_incoming_block - state_num_blocks),
                    newest_block_num + 1,
            ):

                if self.check_for_reorg(nn):
                    ## Just wait for next call to poll_incoming() before resuming.
                    return False

                if nn in self.msgs:
                    for msg in self.msgs[nn]:
                        print('EMIT', do_state, nn, msg['data'])
                        self.events_callback(msg=msg,
                                             receipt=False,
                                             received_via=do_state)

            ## Clear out old buffer:

            for nn in self.msgs.keys():
                if nn < newest_block_num - longest_confirm_state - 1:
                    del self.msgs[nn]

        self.last_incoming_block = newest_block_num

        return True

        if False:
            ## START CHECKS

            if do_state not in self.done_transactions:
                self.done_transactions[do_state] = set()
                self.done_block_nums[do_state] = set()

            msg_block_num = ethereum.utils.parse_int_or_hex(msg['blockNumber'])

            if cm == 0:
                assert msg_block_num not in self.done_block_nums[do_state], (
                    'Seen block twice?',
                    msg_block_num,
                )
                self.done_block_nums[do_state].add(msg_block_num)

            if do_state in self.prev_block_num:
                assert msg_block_num >= self.prev_block_num[do_state], (
                    'REORG?',
                    msg_block_num,
                    self.prev_block_num[do_state],
                )
            self.prev_block_num[do_state] = msg_block_num

            assert msg['transactionHash'] not in self.done_transactions[
                do_state], (
                    'Seen transaction twice?',
                    msg_block_num,
                    msg['transactionHash'],
                )
            self.done_transactions[do_state].add(msg['transactionHash'])

            ## END CHECKS

        return had_any_events

    def _start_contract_thread(
        self,
        terminate_on_exception=False,
    ):
        while True:
            try:
                had_any_events = self.loop_once()
            except Exception as e:
                print('-----LOOP_ONCE_EXCEPTION', e)
                #exit(-1)
                raise

                if terminate_on_exception:
                    raise
                continue

            if not had_any_events:
                print('NO_NEW_EVENTS')

            sleep(self.contract_thread_sleep_time)

    def start_contract_thread(
        self,
        start_in_foreground=False,
        terminate_on_exception=False,
    ):
        """
        Start ContractWrapper loop_once() in background thread, which (in that thread!) calls back to self.process_event()
        """
        if start_in_foreground:
            self._start_contract_thread(
                terminate_on_exception=terminate_on_exception)
        else:
            self.t = Thread(
                target=self._start_contract_thread,
                args=(terminate_on_exception, ),
            )
            self.t.daemon = True
            self.t.start()

    def send_transaction(self, *args, **kw):
        assert len(args) <= 2
        if kw.get('block'):
            self.send_transaction(*args, **kw)
        else:
            self.send_transaction_queue.put((0, args, kw))

    def _send_transaction(
        self,
        args_sig,
        args,
        callback=False,
        send_from=False,
        block=False,
        gas_limit=False,
        gas_price=100,
        value=100000000000,
    ):
        """
        1) Attempt to send transaction.
        2) Get first confirmation via transaction receipt.
        3) Re-check receipt again after N blocks pass.
        
        https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendtransaction
        """

        assert self.is_deployed, 'Must deploy contract first.'

        print('SEND_TRANSACTION:', args_sig, args)

        if send_from is False:
            send_from = self.c.eth_coinbase()

        send_to = self.contract_address

        print('====TRANSACTION')
        print('send_from', send_from)
        print('send_to', send_to)
        print('args_sig', args_sig)
        print('args', args)
        #print ('gas', gas_limit)

        gas_limit = 1000000
        gas_price = self.c.DEFAULT_GAS_PRICE
        value = web3.utils.currency.to_wei(1, 'ether')

        data = self.c._encode_function(args_sig, args)
        data_hex = '0x' + data.encode('hex')

        tx = self.c.eth_sendTransaction(
            from_address=send_from,
            to_address=send_to,
            data=data_hex,
            gas=gas_limit,
            gas_price=gas_price,
            value=value,
        )

        if block:
            print('BLOCKING FOR RECEIPT..')
            while True:
                receipt = self.c.eth_getTransactionReceipt(
                    tx)  ## blocks to ensure transaction is mined
                if receipt:
                    break
                sleep(self.blocking_sleep_time)
            print('GOT RECEIPT')
            #print ('GOT_RECEIPT', receipt)
            #if receipt['blockNumber']:
            #    self.latest_block_num = max(ethereum.utils.parse_int_or_hex(receipt['blockNumber']), self.latest_block_num)
        else:
            self.pending_transactions[tx] = (callback, self.latest_block_num)

        self.latest_block_num = self.c.eth_blockNumber()

        return tx

    def poll_outgoing(self):
        """
        Confirm outgoing transactions.
        """

        assert self.is_deployed, 'Must deploy contract first.'

        had_any_events = False
        if self.pending_transactions:
            had_any_events = True

        for tx, (callback,
                 attempt_block_num) in self.pending_transactions.items():

            ## Compare against the block_number where it attempted to be included:

            if (attempt_block_num <= self.latest_block_num -
                    self.confirm_states['BLOCKCHAIN_CONFIRMED']):
                continue

            receipt = self.c.eth_getTransactionReceipt(tx)

            if receipt is not None and 'blockNumber' in receipt:
                actual_block_number = ethereum.utils.parse_int_or_hex(
                    receipt['blockNumber'])
            else:
                ## TODO: wasn't confirmed after a long time.
                actual_block_number = False

            ## Now compare against the block_number where it was actually included:

            if (actual_block_number is not False) and (
                    actual_block_number >= self.latest_block_num -
                    self.confirm_states['BLOCKCHAIN_CONFIRMED']):
                if callback is not False:
                    callback(receipt)
                del self.pending_transactions[tx]

        return had_any_events

    def read_transaction(self, args_sig, value):
        rr = self.c.call(self.c.eth_coinbase(), self.contract_address,
                         args_sig, value)
        return rr

    def sign(self, user_address, value):
        rr = self.c.eth_sign(self.c.eth_coinbase(), self.contract_address,
                             user_address, value)
        return rr
Exemple #3
0
class EthDeploy:
    def __init__(self, protocol, host, port, gas, gas_price, contract_dir,
                 optimize, account, private_key_path):
        # establish rpc connection
        self.json_rpc = EthJsonRpc(protocol=protocol, host=host, port=port)
        self._from = None
        self.private_key = None
        # set sending account
        if account:
            self._from = self.add_0x(account)
        elif private_key_path:
            with open(private_key_path, 'r') as private_key_file:
                self.private_key = private_key_file.read().strip()
            self._from = self.add_0x(
                encode(privtoaddr(decode(self.private_key, 'hex')), 'hex'))
        else:
            accounts = self.json_rpc.eth_accounts()['result']
            if len(accounts) == 0:
                raise ValueError('No account unlocked')
            self._from = self.add_0x(accounts[0])
        # account address in right format
        if not self.is_address(self._from):
            raise ValueError('Account address is wrong')
        self.optimize = optimize
        self.contract_dir = contract_dir
        self.gas = gas
        self.gas_price = gas_price
        # references dict maps labels to addresses
        self.references = {}
        # abis dict maps addresses to abis
        self.abis = {}
        # total consumed gas
        self.total_gas = 0
        self.log('Instructions are sent from address: {}'.format(self._from))
        balance = self.hex2int(
            self.json_rpc.eth_getBalance(self._from)['result'])
        self.log('Address balance: {} Ether / {} Wei'.format(
            balance / 10.0**18, balance))

    def is_address(self, string):
        return len(self.add_0x(string)) == 42

    @staticmethod
    def hex2int(_hex):
        return int(_hex, 16)

    @staticmethod
    def add_0x(string):
        if not string.startswith('0x'):
            return '0x' + string
        return string

    @staticmethod
    def strip_0x(string):
        if string.startswith('0x'):
            return string[2:]
        return string

    @staticmethod
    def log(string):
        logger.info(string)

    def format_reference(self, string):
        return self.add_0x(string) if self.is_address(string) else string

    def log_transaction_receipt(self, transaction_receipt):
        gas_used = self.hex2int(transaction_receipt['gasUsed'])
        self.total_gas += gas_used
        self.log(
            'Transaction receipt: {} block number, {} gas used, {} cumulative gas used'
            .format(self.hex2int(transaction_receipt['blockNumber']), gas_used,
                    self.hex2int(transaction_receipt['cumulativeGasUsed'])))

    def get_transaction_receipt(self, transaction_hash):
        return self.json_rpc.eth_getTransactionReceipt(
            transaction_hash)['result']

    def wait_for_transaction_receipt(self, transaction_hash):
        while self.get_transaction_receipt(transaction_hash) is None:
            self.log(
                'Waiting for transaction receipt {}'.format(transaction_hash))
            time.sleep(5)
        return self.get_transaction_receipt(transaction_hash)

    def replace_references(self, a):
        if isinstance(a, list):
            return [self.replace_references(i) for i in a]
        else:
            return self.references[a] if isinstance(
                a, basestring) and a in self.references else a

    def get_nonce(self):
        transaction_count = self.json_rpc.eth_getTransactionCount(
            self._from, default_block='pending')['result']
        return self.hex2int(self.strip_0x(transaction_count))

    def get_raw_transaction(self, to='', value=0, data=''):
        nonce = self.get_nonce()
        tx = Transaction(nonce, self.gas_price, self.gas, to, value,
                         decode(data, 'hex'))
        tx.sign(decode(self.private_key, 'hex'))
        return self.add_0x(encode(rlp.encode(tx), 'hex'))

    def compile_code(self, path):
        # create list of valid paths
        absolute_path = self.contract_dir if self.contract_dir.startswith(
            '/') else '{}/{}'.format(os.getcwd(), self.contract_dir)
        sub_dirs = [x[0] for x in os.walk(absolute_path)]
        extra_args = ' '.join(
            ['{}={}'.format(d.split('/')[-1], d) for d in sub_dirs])
        # compile code
        combined = _solidity.compile_last_contract(path,
                                                   libraries=self.references,
                                                   combined='bin,abi',
                                                   optimize=self.optimize,
                                                   extra_args=extra_args)
        bytecode = combined['bin_hex']
        abi = combined['abi']
        return bytecode, abi

    def deploy(self, _from, file_path, libraries, value, params, label):
        # replace library placeholders
        if libraries:
            for library_name, library_address in libraries.items():
                self.references[library_name] = self.replace_references(
                    self.strip_0x(library_address))
        if self.contract_dir:
            file_path = '{}/{}'.format(self.contract_dir, file_path)
        bytecode, abi = self.compile_code(file_path)
        if not label:
            label = file_path.split("/")[-1].split(".")[0]
        if params:
            translator = ContractTranslator(abi)
            # replace constructor placeholders
            params = [self.replace_references(p) for p in params]
            bytecode += encode(translator.encode_constructor_arguments(params),
                               'hex')
        # deploy contract
        self.log('Deployment transaction for {} sent'.format(
            label if label else 'unknown'))
        tx_response = None
        if self.private_key:
            raw_tx = self.get_raw_transaction(value=value, data=bytecode)
            while tx_response is None or 'error' in tx_response:
                if tx_response and 'error' in tx_response:
                    self.log('Deploy failed with error {}'.format(
                        tx_response['error']['message']))
                    time.sleep(5)
                tx_response = self.json_rpc.eth_sendRawTransaction(raw_tx)
        else:
            while tx_response is None or 'error' in tx_response:
                if tx_response and 'error' in tx_response:
                    self.log('Deploy failed with error {}'.format(
                        tx_response['error']['message']))
                    time.sleep(5)
                tx_response = self.json_rpc.eth_sendTransaction(
                    self.add_0x(_from if _from else self._from),
                    value=value,
                    data=self.add_0x(bytecode),
                    gas=self.gas,
                    gas_price=self.gas_price)
        transaction_receipt = self.wait_for_transaction_receipt(
            self.add_0x(tx_response['result']))
        contract_address = self.strip_0x(
            transaction_receipt['contractAddress'])
        self.references[label] = contract_address
        self.abis[contract_address] = abi
        self.log('Contract {} created at address {}'.format(
            label if label else 'unknown', self.add_0x(contract_address)))
        self.log_transaction_receipt(transaction_receipt)

    def send_transaction(self, _from, to, value, name, params, abi):
        reference = to
        to = self.replace_references(to)
        data = ''
        if name or abi:
            if not name:
                name = abi['name']
            abi = self.abis[to] if to in self.abis else [abi]
            translator = ContractTranslator(abi)
            data = encode(
                translator.encode(name, self.replace_references(params)),
                "hex")
        self.log('Transaction to {}{} sent'.format(
            self.format_reference(reference),
            ' calling {} function'.format(name) if name else ''))
        tx_response = None
        if self.private_key:
            raw_tx = self.get_raw_transaction(to=to, value=value, data=data)
            while tx_response is None or 'error' in tx_response:
                if tx_response and 'error' in tx_response:
                    self.log('Transaction failed with error {}'.format(
                        tx_response['error']['message']))
                    time.sleep(5)
                tx_response = self.json_rpc.eth_sendRawTransaction(raw_tx)
        else:
            while tx_response is None or 'error' in tx_response:
                if tx_response and 'error' in tx_response:
                    self.log('Transaction failed with error {}'.format(
                        tx_response['error']['message']))
                    time.sleep(5)
                tx_response = self.json_rpc.eth_sendTransaction(
                    self.add_0x(_from if _from else self._from),
                    to_address=self.add_0x(to),
                    value=value,
                    data=self.add_0x(data),
                    gas=self.gas,
                    gas_price=self.gas_price)
        transaction_hash = tx_response['result']
        transaction_receipt = self.wait_for_transaction_receipt(
            self.add_0x(transaction_hash))
        self.log('Transaction to {}{} successful'.format(
            self.format_reference(reference),
            ' calling {} function'.format(name) if name else ''))
        self.log_transaction_receipt(transaction_receipt)

    def call(self, _from, to, value, name, params, label, assertion, abi):
        reference = to
        to = self.replace_references(to)
        if not name:
            name = abi['name']
        abi = self.abis[to] if to in self.abis else [abi]
        translator = ContractTranslator(abi)
        data = encode(translator.encode(name, self.replace_references(params)),
                      'hex')
        response = self.json_rpc.eth_call(
            self.add_0x(to),
            from_address=self.add_0x(_from if _from else self._from),
            value=value,
            data=self.add_0x(data),
            gas=self.gas,
            gas_price=self.gas_price)
        result = translator.decode(
            name, decode(self.strip_0x(response['result']), 'hex'))
        result = result if len(result) > 1 else result[0]
        if label:
            self.references[label] = result
        if assertion:
            expected_result = self.replace_references(assertion)
            if isinstance(expected_result, int) or isinstance(
                    expected_result, long):
                assert result == expected_result
            else:
                assert result.lower() == self.strip_0x(expected_result.lower())
            self.log('Assertion of {} at {} successful'.format(
                name, self.format_reference(reference)))
        else:
            self.log('Call to {} calling function {} successful'.format(
                self.format_reference(reference), name))

    def process(self, f):
        # read instructions file
        with open(f, 'r') as instructions_file:
            instructions = json.load(instructions_file)
        for i in instructions:
            if i['type'] == 'abi':
                for address in i['addresses']:
                    self.abis[self.strip_0x(address)] = i['abi']
            if i['type'] == 'deployment':
                self.deploy(i['from'] if 'from' in i else None,
                            i['file'] if 'file' in i else None,
                            i['libraries'] if 'libraries' in i else None,
                            i['value'] if 'value' in i else 0,
                            i['params'] if 'params' in i else (),
                            i['label'] if 'label' in i else None)
            elif i["type"] == "transaction":
                self.send_transaction(
                    i['from'] if 'from' in i else None,
                    i['to'] if 'to' in i else None,
                    i['value'] if 'value' in i else 0,
                    i['name'] if 'name' in i else None,
                    i['params'] if 'params' in i else (),
                    i['abi'] if 'abi' in i else None,
                )
            elif i["type"] == "call":
                self.call(
                    i['from'] if 'from' in i else None,
                    i['to'] if 'to' in i else None,
                    i['value'] if 'value' in i else 0,
                    i['name'] if 'name' in i else None,
                    i['params'] if 'params' in i else (),
                    i['label'] if 'label' in i else None,
                    i['assertion'] if 'assertion' in i else None,
                    i['abi'] if 'abi' in i else None,
                )
        self.log('-' * 96)
        self.log('Summary: {} gas used, {} Ether / {} Wei spent on gas'.format(
            self.total_gas, self.total_gas * self.gas_price / 10.0**18,
            self.total_gas * self.gas_price))
        for reference, value in self.references.items():
            self.log('{} references {}'.format(
                reference,
                self.add_0x(value) if isinstance(value, unicode) else value))
        self.log('-' * 96)
Exemple #4
0
class EthereumBlockchain:
    def __init__(self,
                 the_code = False,
                 the_sig = None,
                 the_args = None,
                 the_address = False,
                 rpc_host = DEFAULT_RPC_HOST,
                 rpc_port = DEFAULT_RPC_PORT,
                 background_thread_sleep_time = 1.0,
                 ):
        
        self.con = EthJsonRpc(rpc_host, rpc_port)
        
        self.the_code = the_code
        self.the_sig = the_sig
        self.the_args = the_args
        
        self.contract_address = the_address
        
        assert self.the_code or self.contract_address
        
        self.loop_once_started = False
        
        self.sig_to_topic_id_cache = {}
        
        self.send_transaction_queue = Queue()
        
        self.background_thread_sleep_time = background_thread_sleep_time

        self.pending_transactions = {}  ## {tx:callback}
        
        self.is_deployed = False
        
        if the_address:
            assert self.check_anything_deployed(the_address), ('NOTHING DEPLOYED AT SPECIFIED ADDRESS:', the_address)
            self.is_deployed = True
        elif the_code:
            if auto_deploy:
                self.deploy()

        
    #def setup_create_pending_transaction(func):
    #    self._create_pending_transaction = func
    
    #def setup_logic_callback(func):
    #    self._logic_callback = func
    
    def event_sig_to_topic_id(self, sig):
        """ Compute ethereum topic_ids from function signatures. """
        if sig in self.sig_to_topic_id_cache:
            return self.sig_to_topic_id_cache[sig]
        name = sig[:sig.find('(')]
        types = [x.strip().split()[0] for x in sig[sig.find('(')+1:sig.find(')')].split(',')]
        topic_id = ethereum.utils.int_to_hex(ethereum.abi.event_id(name,types))
        self.sig_to_topic_id_cache[sig] = topic_id
        return topic_id

    def setup_event_callbacks(self,
                              log_handlers,
                              pending_handlers,
                              ):
        self.log_handlers = log_handlers
        self.log_handlers_hashed = {((x == 'DEFAULT') and 'DEFAULT' or self.event_sig_to_topic_id(x)):y
                                    for x,y
                                    in log_handlers.items()}
        self.pending_handlers = pending_handlers
    
    def logic_callback(self, msg, *args, **kw):
        default_func = self.log_handlers_hashed.get('DEFAULT', False)
        
        if 'topics' not in msg:
            assert default_func is not False, ('Unknown topic_id and no DEFAULT handler.')
            print ('PROXY logic_callback()', '->', default_func, kw)
            default_func(msg, *args, **kw)
            return
        
        for topic in msg['topics']:
            func = self.log_handlers_hashed.get(topic, default_func)
            print ('PROXY logic_callback()', topic, '->', func)
            assert func is not False, ('Unknown topic_id and no DEFAULT handler.', topic, kw)
            func(msg, *args, **kw)
    
    def simulate_pending(self,
                         args_sig,
                         args,
                         *aa, **bb):
        """ 
        See: https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI#events 
        """
        ## TODO: support indexed topics?
        
        func = self.pending_handlers.get(args_sig, self.pending_handlers.get('DEFAULT', False))
        
        print ('Proxy: simulate_pending()', args_sig, '->', func)
        
        return func(args_sig, args, *aa, **bb)

    def get_block_by_hash_callback(self, block_hash):
        """
        Get block by blockHash.
        
        https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getblockbyhash
        """
        print ('bcc.get_block_by_hash_callback()', block_hash)

        rh = self.con.eth_getBlockByHash(block_hash)
        
        for k in ['number', 'timestamp']:
            rh[k] = ethereum.utils.parse_int_or_hex(rh[k])
        
        return rh
        
    
    def get_logs_by_block_num_callback(self, block_num):
        """
        Get event logs for a particular block num. It's OK if the block_num has an unexpected hash, 
        that'll be taken care of by caller.
        
        https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getlogs
        """
        print ('bcc.get_logs_by_block_num_callback()', block_num)
        
        the_filter = self.con.eth_newFilter(from_block =  fixed_int_to_hex(block_num),
                                            to_block = fixed_int_to_hex(block_num),
                                            address = self.contract_address,
                                            )
        
        rr =  self.con.eth_getFilterLogs(str(the_filter))

        rr2 = []
        for msg in rr:
            #assert 'topics' in msg, list(sorted(msg.keys()))
            got_num = ethereum.utils.parse_int_or_hex(msg['blockNumber'])
            if got_num != block_num:
                continue
            msg['data'] = solidity_string_decode(msg['data'])
            msg['blockNumber'] = got_num
            msg["logIndex"] = ethereum.utils.parse_int_or_hex(msg['logIndex'])
            msg["transactionIndex"] = ethereum.utils.parse_int_or_hex(msg['transactionIndex'])
            #msg_data = loads_compact(msg['data'])
            #payload_decoded = loads_compact(msg_data['payload'])
            rr2.append(msg)
        rr = rr2
        
        return rr

    def get_latest_block_number(self):
        print ('bcc.get_latest_block_number()')
        bn = self.con.eth_blockNumber()
        return bn
    
    def get_latest_block_callback(self):
        """
        Returns the single latest block. Missing intermediate blocks will be automatically looked up by caller.
        """
        print ('bcc.get_latest_block_callback()')
        bn = self.get_latest_block_number()
        block = self.con.eth_getBlockByNumber(bn)
        return block

                
    def check_anything_deployed(self, address):
        """ Basic sanity check, checks if ANY code is deployed at provided address. """
        print ('bcc.check_anything_deployed()', address)
        if self.con.eth_getCode(address) == '0x0':
            return False
        return True
            
    def deploy(self,
               the_sig = False,
               the_args = False,
               block = False,
               deploy_from = False,
               callback = False,
               ):
        """ Deploy contract. Optional args_sig and args used to pass arguments to contract constructor."""
        print ('bcc.deploy()')

        if the_sig is not False:
            self.contract_sig = the_sig
        
        if the_args is not False:
            self.contract_args = the_args

        assert self.the_code

        if deploy_from is False:
            deploy_from = self.con.eth_coinbase()
        
        print ('DEPLOYING_CONTRACT...', 'deploy_from:', deploy_from, 'the_sig:', the_sig, 'the_args:', the_args)        
        # get contract address
        xx = self.con.eth_compileSolidity(self.the_code)
        #print ('GOT',xx)
        
        compiled = None
        
        try:
            compiled = xx['code']
        except KeyError:
            # geth seems to like putting the compiler output into an inner dict keyed by input filename,
            # e.g {'CCCoinToken.sol': {'code': '...', 'etc': '...'}
            for k, v in xx.iteritems():
                if isinstance(v, dict) and 'code' in v:
                    compiled = v['code']
                    break
        
        assert compiled
        
        contract_tx = self.con.create_contract(from_ = deploy_from,
                                               code = compiled,
                                               gas = 3000000,
                                               sig = self.contract_sig,
                                               args = self.contract_args,
                                               )

        if block:
            ## NOTE: @yusef feel free to switch back to this method if you want:
            #print('CONTRACT DEPLOYED, WAITING FOR CONFIRMATION')
            #wait_for_confirmation(self.c, contract_tx)
            
            print ('BLOCKING FOR RECEIPT..')
            while True:
                receipt = self.con.eth_getTransactionReceipt(contract_tx) ## blocks to ensure transaction is mined
                if receipt:
                    break
                sleep(self.blocking_sleep_time)
            print ('GOT RECEIPT')
        else:
            self.pending_transactions[contract_tx] = callback
        
        self.contract_address = str(self.con.get_contract_address(contract_tx))
        self.is_deployed = True
        print ('DEPLOYED', self.contract_address)
        return self.contract_address

    def send_transaction(self, *args, **kw):
        """
        1) If possible create simulated outputs of transactions, to use as pending state.
        2) Queue the transaction for blockchain commit.
        
        Used for e.g.:
        - addLog(bytes)
        - mintTokens(address, uint, uint, uint, uint, uint, uint)
        - withdrawTok(bytes)
        - lockupTok(bytes)
        """
        print ('bcc.send_transaction()')

        assert len(args) <= 2
        #assert self.loop_once_started, 'loop_once() not started?'

        ## Potentially slow blocking call to commit it to the blockchain:

        if kw.get('block'):
            ## Send transaction in blocking mode, and grab actual event logs that are committed:

            rh = self.inner_send_transaction(*args, **kw)
            pending_logs = rh['pending_logs']
            is_pending = False
            
        else:
            ## Run callbacks, return simulated event logs where possible:

            self.send_transaction_queue.put((0, args, kw))
            pending_logs = self.simulate_pending(*args, **kw)
            is_pending = True
        
        ## Run logic_callback() against pending transactions:
        
        for log in pending_logs:
            print ('CALLING', 'is_pending:', is_pending, 'is_noop:', log.get('is_noop', False))
                                
            self.logic_callback(log,
                                is_pending = is_pending,
                                is_noop = log.get('is_noop', False)
                                )

        return pending_logs
            
    def inner_send_transaction(self,
                               args_sig,
                               args,
                               callback = False,
                               send_from = False,
                               block = False,
                               gas_limit = False,
                               gas_price = 100,
                               value = 100000000000,
                               ):
        """
        1) Attempt to send transaction.
        2) Get first confirmation via transaction receipt.
        3) Re-check receipt again after N blocks pass.
        
        https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sendtransaction
        """
        print ('bcc.inner_send_transaction()')

        assert self.is_deployed, 'Must deploy contract first.'

        print ('SEND_TRANSACTION:', args_sig, args)

        if send_from is False:
            send_from = self.con.eth_coinbase()
        
        send_to = self.contract_address 

        print ('====TRANSACTION')
        print ('send_from', send_from)
        print ('send_to', send_to)
        print ('args_sig', args_sig)
        print ('args', args)
        #print ('gas', gas_limit)
        
        gas_limit = 1000000
        gas_price = self.con.DEFAULT_GAS_PRICE
        value = web3.utils.currency.to_wei(1,'ether')

        data = self.con._encode_function(args_sig, args)
        data_hex = '0x' + data.encode('hex')
        
        tx = self.con.eth_sendTransaction(from_address = send_from,
                                          to_address = send_to,
                                          data = data_hex,
                                          gas = gas_limit,
                                          gas_price = gas_price,
                                          value = value,
                                          )
        
        if block:
            print ('BLOCKING FOR RECEIPT..')
            while True:
                receipt = self.con.eth_getTransactionReceipt(tx) ## blocks to ensure transaction is mined
                if receipt:
                    break
                sleep(self.blocking_sleep_time)
            print ('GOT RECEIPT')
            #print ('GOT_RECEIPT', receipt)
            #if receipt['blockNumber']:
            #    self.latest_block_num = max(ethereum.utils.parse_int_or_hex(receipt['blockNumber']), self.latest_block_num)
        else:
            self.pending_transactions[tx] = callback
        
        #self.latest_block_num = self.con.eth_blockNumber()
        
        return {'tx':tx}

    def poll_outgoing_receipts(self):
        """
        Check for transaction receipts on transactions sent from this node.
        TODO - why not replace this with just watching for incoming transactions???
        """
        
        assert self.is_deployed, 'Must deploy contract first.'

        had_any_events = False
        if self.pending_transactions:
            had_any_events = True
        
        for tx, callback in self.pending_transactions.items():
            
            receipt = self.con.eth_getTransactionReceipt(tx)
            
            if receipt is not None and 'blockNumber' in receipt:
                actual_block_number = ethereum.utils.parse_int_or_hex(receipt['blockNumber'])
            else:
                ## TODO: wasn't confirmed after a long time.
                actual_block_number = False
            
            ## Now compare against the block_number where it was actually included:
            
            if actual_block_number is not False:
                if callback is not False:
                    callback(receipt)
                del self.pending_transactions[tx]
        
        return had_any_events
    
    
    def _start_background_thread(self,
                                 terminate_on_exception = False,
                                 ):
        last_event = False
        
        while True:
            try:
                had_any_events = self.loop_once_blockchain()
            except Exception as e:
                print ('-----LOOP_ONCE_EXCEPTION', e)
                #exit(-1)
                raise
                
                if terminate_on_exception:
                    raise
                continue
            
            if had_any_events:
                last_event = time()
            else:
                print ('NO_NEW_EVENTS', last_event and (time() - last_event))
            
            sleep(self.background_thread_sleep_time)
    
    def start_background_thread(self,
                                start_in_foreground = False,
                                terminate_on_exception = False,
                                ):
        """
        Start ContractWrapper loop_once() in background thread, which (in that thread!) calls back to self.process_event()
        """
        if start_in_foreground:
            self._start_background_thread(terminate_on_exception = terminate_on_exception)
        else:
            self.t = Thread(target = self._start_background_thread,
                            args = (terminate_on_exception,),
                            )
            self.t.daemon = True
            self.t.start()
    
            

    def loop_once_blockchain(self):
        ## Check for available write receipts:
        #self.poll_outgoing_receipts()

        self.loop_once_started = True
        
        ## Do write transactions transactions:
        
        while self.send_transaction_queue.qsize():
            print ('TRY_TO_SEND')
            tries, args, kw = self.send_transaction_queue.get()
            try:
                self.inner_send_transaction(*args, **kw)
            except Exception as e:
                print ('FAILED_TO_SEND', e, tries, args, kw)
                sleep(1) ## TODO
                self.send_transaction_queue.put((tries + 1, args, kw))
                break
Exemple #5
0
class Deploy:
    def __init__(self, protocol, host, port, add_dev_code, verify_code,
                 contract_dir, gas, gas_price, private_key):
        self.pp = PreProcessor()
        self.s = t.state()
        self.s.block.number = 1150000  # Homestead
        t.gas_limit = int(gas)
        self.json_rpc = EthJsonRpc(protocol=protocol, host=host, port=port)
        if private_key:
            self.user_address = '0x' + privtoaddr(
                private_key.decode('hex')).encode('hex')
        else:
            self.user_address = self.json_rpc.eth_coinbase()["result"]
        self.add_dev_code = add_dev_code == 'true'
        self.verify_code = verify_code == 'true'
        self.contract_dir = contract_dir
        self.gas = int(gas)
        self.gas_price = int(gas_price)
        self.private_key = private_key
        self.contract_addresses = {}
        self.contract_abis = {}

    def wait_for_transaction_receipt(self, transaction_hash):
        while self.json_rpc.eth_getTransactionReceipt(
                transaction_hash)['result'] is None:
            logging.info(
                'Waiting for transaction receipt {}'.format(transaction_hash))
            time.sleep(5)

    def replace_address(self, a):
        return self.contract_addresses[a] if isinstance(
            a, basestring) and a in self.contract_addresses else a

    def get_nonce(self):
        return int(
            self.json_rpc.eth_getTransactionCount(
                self.user_address)["result"][2:], 16)

    def get_raw_transaction(self, data, contract_address=''):
        nonce = self.get_nonce()
        tx = Transaction(nonce, self.gas_price, self.gas, contract_address, 0,
                         data.decode('hex'))
        tx.sign(self.private_key.decode('hex'))
        return rlp.encode(tx).encode('hex')

    def code_is_valid(self, contract_address, compiled_code):
        deployed_code = self.json_rpc.eth_getCode(contract_address)["result"]
        locally_deployed_code_address = self.s.evm(
            compiled_code.decode("hex")).encode("hex")
        locally_deployed_code = self.s.block.get_code(
            locally_deployed_code_address).encode("hex")
        return deployed_code == "0x" + locally_deployed_code

    @staticmethod
    def compile_code(code, language):
        combined = languages[language].combined(code)
        compiled_code = combined[-1][1]["bin_hex"]
        abi = combined[-1][1]["abi"]
        return compiled_code, abi

    @staticmethod
    def replace_library_placeholders(bytecode, addresses):
        if addresses:
            for library_name, library_address in addresses.iteritems():
                bytecode = bytecode.replace(
                    "__{}{}".format(library_name,
                                    "_" * (38 - len(library_name))),
                    library_address[2:])
        return bytecode

    def deploy_code(self, file_path, params, addresses):
        if addresses:
            addresses = dict([(k, self.replace_address(v))
                              for k, v in addresses.iteritems()])
        language = "solidity" if file_path.endswith(".sol") else "serpent"
        code = self.pp.process(file_path,
                               add_dev_code=self.add_dev_code,
                               contract_dir=self.contract_dir,
                               addresses=addresses)
        # compile code
        bytecode, abi = self.compile_code(code, language)
        # replace library placeholders
        bytecode = self.replace_library_placeholders(bytecode, addresses)
        if params:
            translator = ContractTranslator(abi)
            # replace constructor placeholders
            params = [self.replace_address(p) for p in params]
            bytecode += translator.encode_constructor_arguments(params).encode(
                "hex")
        logging.info(
            'Try to create contract with length {} based on code in file: {}'.
            format(len(bytecode), file_path))
        if self.private_key:
            raw_tx = self.get_raw_transaction(bytecode)
            tx_response = self.json_rpc.eth_sendRawTransaction("0x" + raw_tx)
            while "error" in tx_response:
                logging.info('Deploy failed with error {}. Retry!'.format(
                    tx_response['error']))
                time.sleep(5)
                tx_response = self.json_rpc.eth_sendRawTransaction("0x" +
                                                                   raw_tx)
        else:
            tx_response = self.json_rpc.eth_sendTransaction(
                self.user_address,
                data=bytecode,
                gas=self.gas,
                gas_price=self.gas_price)
            while "error" in tx_response:
                logging.info('Deploy failed with error {}. Retry!'.format(
                    tx_response['error']))
                time.sleep(5)
                tx_response = self.json_rpc.eth_sendTransaction(
                    self.user_address,
                    data=bytecode,
                    gas=self.gas,
                    gas_price=self.gas_price)
        transaction_hash = tx_response['result']
        self.wait_for_transaction_receipt(transaction_hash)
        contract_address = self.json_rpc.eth_getTransactionReceipt(
            transaction_hash)["result"]["contractAddress"]
        # Verify deployed code with locally deployed code
        if self.verify_code and not self.code_is_valid(contract_address,
                                                       bytecode):
            logging.info('Deploy of {} failed. Retry!'.format(file_path))
            self.deploy_code(file_path, params, addresses)
        contract_name = file_path.split("/")[-1].split(".")[0]
        self.contract_addresses[contract_name] = contract_address
        self.contract_abis[contract_name] = abi
        logging.info('Contract {} was created at address {}.'.format(
            file_path, contract_address))

    def send_transaction(self, contract, name, params):
        contract_address = self.replace_address(contract)
        contract_abi = self.contract_abis[contract]
        translator = ContractTranslator(contract_abi)
        data = translator.encode(name,
                                 [self.replace_address(p)
                                  for p in params]).encode("hex")
        logging.info('Try to send {} transaction to contract {}.'.format(
            name, contract))
        if self.private_key:
            raw_tx = self.get_raw_transaction(data, contract_address)
            tx_response = self.json_rpc.eth_sendRawTransaction("0x" + raw_tx)
            while 'error' in tx_response:
                logging.info('Transaction failed with error {}. Retry!'.format(
                    tx_response['error']))
                time.sleep(5)
                tx_response = self.json_rpc.eth_sendRawTransaction("0x" +
                                                                   raw_tx)
        else:
            tx_response = self.json_rpc.eth_sendTransaction(
                self.user_address,
                to_address=contract_address,
                data=data,
                gas=self.gas,
                gas_price=self.gas_price)
            while 'error' in tx_response:
                logging.info('Transaction failed with error {}. Retry!'.format(
                    tx_response['error']))
                time.sleep(5)
                tx_response = self.json_rpc.eth_sendTransaction(
                    self.user_address,
                    to_address=contract_address,
                    data=data,
                    gas=self.gas,
                    gas_price=self.gas_price)
        transaction_hash = tx_response['result']
        self.wait_for_transaction_receipt(transaction_hash)
        logging.info('Transaction {} for contract {} completed.'.format(
            name, contract))

    def assert_call(self, contract, name, params, return_value):
        contract_address = self.replace_address(contract)
        return_value = self.replace_address(return_value)
        contract_abi = self.contract_abis[contract]
        translator = ContractTranslator(contract_abi)
        data = translator.encode(name,
                                 [self.replace_address(p)
                                  for p in params]).encode("hex")
        logging.info('Try to assert return value of {} in contract {}.'.format(
            name, contract))
        bc_return_val = self.json_rpc.eth_call(to_address=contract_address,
                                               data=data)["result"]
        result_decoded = translator.decode(name,
                                           bc_return_val[2:].decode("hex"))
        result_decoded = result_decoded if len(
            result_decoded) > 1 else result_decoded[0]
        assert result_decoded == return_value
        logging.info(
            'Assertion successful for return value of {} in contract {}.'.
            format(name, contract))

    def process(self, f):
        with open(f) as data_file:
            instructions = json.load(data_file)
            logging.info('Your address: {}'.format(self.user_address))
            for instruction in instructions:
                logging.info('Your balance: {} Wei'.format(
                    int(
                        self.json_rpc.eth_getBalance(
                            self.user_address)['result'], 16)))
                if instruction["type"] == "deployment":
                    self.deploy_code(
                        instruction["file"],
                        instruction["params"]
                        if "params" in instruction else None,
                        instruction["addresses"]
                        if "addresses" in instruction else None,
                    )
                elif instruction["type"] == "transaction":
                    self.send_transaction(
                        instruction["contract"],
                        instruction["name"],
                        instruction["params"]
                        if "params" in instruction else [],
                    )
                elif instruction["type"] == "assertion":
                    self.assert_call(
                        instruction["contract"], instruction["name"],
                        instruction["params"] if "params" in instruction else
                        [], instruction["return"])
            for contract_name, contract_address in self.contract_addresses.iteritems(
            ):
                logging.info('Contract {} was created at address {}.'.format(
                    contract_name, contract_address))
Exemple #6
0
             #Reset password variables, for security reasons
             lcdClear()
             pwd = 0
             pwInput = [""] * pwdLen
             setCursor(0, 0)
             lcdPrint("Authenticated!")
             auth = True  #Authentication succesful
         except:
             #Possibly incorrect password
             lcdClear()
             setCursor(0, 0)
             lcdPrint("Nope...")
         if auth:
             try:
                 c.eth_sendTransaction(to_address=c.eth_accounts()[0],
                                       from_address=c.eth_accounts()[1],
                                       value=1000)
                 lcdClear()
                 lcd.setCursor(0, 0)
                 lcdPrint("Transaction")
                 lcd.setCursro(0, 1)
                 lcdPrint("Sucessful")
             except:
                 lcdClear()
                 setCursor(0, 0)
                 lcdPrint("Failed")
                 setCursor(0, 1)
                 lcdPrint("Insufficient balance")
             auth = False
     xPos = xPos % pwdLen
 sleep(0.07)
Exemple #7
0
def runWorker(ID, s, output):

    client = EthJsonRpc('10.64.83.200', 39000 + ID)
    obj = web3.Web3(web3.HTTPProvider('http://10.64.83.200:3900' + str(ID)))
    print(client.eth_accounts()[0])
    #print(client1.eth_accounts()[1])

    print("Worker %d initialized successfully!" % (ID, ))

    all_gas = []
    nu = 0  #iteration count
    itermax = s.admmopt.iterMaxlocal  #get maximum iteration
    flag = False
    new_gas = 0

    start_balance = obj.eth.getBalance(
        obj.toChecksumAddress(client.eth_accounts()[0]))

    j = 0
    s.admmopt.tau = 1
    last_block = obj.eth.blockNumber
    while (1):
        trans_by_block = obj.eth.getBlockTransactionCount(last_block - j)
        if (trans_by_block > 0):
            #dest = list(s.nbor.keys())
            #if(ID==1):getNextValues(ID,s,client,obj,last_block - j, trans_by_block)

            #s.update_z()
            #s.choose_max_rho()
            break

        j = j + 1

    prev_convegenceTable = []
    P_history = []
    Q_history = []
    start_time2 = time()

    while nu <= itermax and not flag:
        if s.recvmsg:
            s.update_z()
            s.choose_max_rho()

            #print(ID,"i have rho", s.var["rho"])

        start_time = time()
        result = s.pipslopf_solver()

        end_time = time()

        if result['eflag'] and nu % 20 == 0:
            print('Subproblem %d at iteration %d solved!' % (ID, nu))
            # print("Time for solving subproblem %d: %ssecs to %ssecs" % (ID, start_time, end_time))

        s.update_x()
        P_history.append(sum(s.var['Pg']))
        Q_history.append(sum(s.var['Qg']))

        if s.recvmsg:  # not the initialization
            s.update_y()
            s.update_rho()

            prev_convegenceTable = s.gapAll[s.ID - 1]

        # check convergence
        #if(nu>10):flag =
        flag = s.converge()
        s.recvmsg = {}  # clear the received messages

        #s.send()

        dest = s.nbor.keys()

        for k in dest:
            # prepare the message to be sent to neighbor k
            #tm.sleep(0.05)
            msg3 = message()
            msg3.config(s.ID, k, s.var, s.nbor[k].tlidx['int'], s.gapAll)
            data2 = json.dumps(msg3.__dict__, cls=MyEncoder)

            json_data = json.JSONEncoder().encode(data2)

            json_data = '0x' + json_data.encode("utf-8").hex()

            sampleDict = obj.txpool.content.pending

            new_gas = new_gas + 18000000000 * obj.eth.estimateGas({
                'to':
                obj.toChecksumAddress(
                    '0xa8085d8331f16a5b76690e665d9f5eaaaa85ee1c'),
                'data':
                json_data
            })

            client.eth_sendTransaction(
                from_address=client.eth_accounts()[0],
                to_address="0xa8085d8331f16a5b76690e665d9f5eaaaa85ee1c",
                gas=0xf4240,
                gas_price=18000000000,
                value=1,  # 2441406250
                data=json_data)

        txpooljson = obj.txpool.content.pending.__dict__

        recvmsg = {}

        twait = s.admmopt.pollWaitingtime
        dest = list(s.nbor.keys())
        recvFlag = [0] * s.region['nnbor']
        arrived = 0  # number of arrived neighbors
        pollround = 0
        while arrived < s.region['nwait'] and pollround < 5:
            #for i in range(len(dest)):
            #k = dest[i]
            #s.recvmsg[k] = recvmsg[k]
            #recvFlag[i] = 1

            for k in txpooljson.keys():

                txpooljson2 = txpooljson[k].__dict__
                last_nonce = max(txpooljson2, key=int)
                #print(ID,", last nonce",last_nonce)
                last_nonce_dict = txpooljson2[last_nonce].__dict__

                hexjson = last_nonce_dict['input'][2:]
                jsonstring = codecs.decode(hexjson, "hex").decode('utf-8')

                jsonvalues = json.JSONDecoder().decode(jsonstring)
                values_dict = json.loads(jsonvalues, cls=MyDecoder)

                temp_msg = message()
                if (values_dict['fID'] in s.nbor.keys()):
                    for last_nonce in range(int(max(txpooljson2, key=int)), 0,
                                            -1):
                        last_nonce_dict = txpooljson2[str(last_nonce)].__dict__

                        hexjson = last_nonce_dict['input'][2:]
                        jsonstring = codecs.decode(hexjson,
                                                   "hex").decode('utf-8')

                        jsonvalues = json.JSONDecoder().decode(jsonstring)
                        values_dict = json.loads(jsonvalues, cls=MyDecoder)
                        if (values_dict['tID'] == s.ID): break

                #print(ID,"last nonce=",last_nonce,"from",values_dict['fID'])
                temp_msg.fID = values_dict['fID']
                temp_msg.tID = values_dict['tID']
                temp_msg.fields['AVmd'] = numpy.asarray(
                    values_dict['fields']['AVmd'])
                temp_msg.fields['AVms'] = numpy.asarray(
                    values_dict['fields']['AVms'])
                temp_msg.fields['AVad'] = numpy.asarray(
                    values_dict['fields']['AVad'])
                temp_msg.fields['AVas'] = numpy.asarray(
                    values_dict['fields']['AVas'])
                temp_msg.fields['ymd'] = numpy.asarray(
                    values_dict['fields']['ymd'])
                temp_msg.fields['yms'] = numpy.asarray(
                    values_dict['fields']['yms'])
                temp_msg.fields['yad'] = numpy.asarray(
                    values_dict['fields']['yad'])
                temp_msg.fields['yas'] = numpy.asarray(
                    values_dict['fields']['yas'])
                temp_msg.fields['rho'] = values_dict['fields']['rho']
                temp_msg.fields['convergeTable'] = values_dict['fields'][
                    'convergeTable']

                if (temp_msg.tID == s.ID):
                    recvmsg[temp_msg.fID] = temp_msg
                    #recvFlag[i] = 1

                arrived = len(recvmsg)
                pollround += 1

        s.recvmsg = copy.deepcopy(recvmsg)

        all_gas.append(new_gas)
        nu += 1

    # record results
    print("Worker %d finished!" % (ID, ))

    for k in dest:

        starting_point = message2()
        starting_point.config(s.ID, k, s.var, s.nbor[k].tlidx['int'], s.gapAll)
        data2 = json.dumps(starting_point.__dict__, cls=MyEncoder)
        json_data = json.JSONEncoder().encode(data2)
        json_data = '0x' + json_data.encode("utf-8").hex()
        sampleDict = obj.txpool.content.pending

        client.eth_sendTransaction(
            from_address=client.eth_accounts()[0],
            to_address="0xa8085d8331f16a5b76690e665d9f5eaaaa85ee1c",
            gas=0xf4240,
            gas_price=18000000000,
            value=1,  # 2441406250
            data=json_data)

    print(starting_point.__dict__)

    x, f, info, lmbda, output2 = result["x"], result["f"], result[
        "eflag"], result["lmbda"], result["output"]
    nx = len(x)
    nb = s.region['nb']
    ng = s.region['ng']
    iv = s.idx['var']
    bus = s.region['bus']
    gen = s.region['gen']
    branch = s.region['branch']
    baseMVA = s.region['baseMVA']
    Ybus = s.region['Ybus']
    ridx = s.idx['rbus']['int']
    # idx ranges
    iVa = iv['iVa']
    iVm = iv['iVm']
    iPg = iv['iPg']
    iQg = iv['iQg']
    # grab Pg and Qg
    gen[:, PG] = x[iPg] * s.region["baseMVA"]
    gen[:, QG] = x[iQg] * s.region["baseMVA"]
    bus[:, PD] = bus[:, PD] * s.region["baseMVA"]
    bus[:, QD] = bus[:, QD] * s.region["baseMVA"]
    # reconstruct V
    Va, Vm = x[iVa], x[iVm]
    V = Vm * exp(1j * Va)

    #print(V)
    nl = shape(branch)[0]  ## number of branches
    bus[:, VA] = Va * 180 / pi
    bus[:, VM] = Vm

    if shape(branch)[1] < MU_ANGMAX + 1:
        branch = c_[branch, zeros((nl, MU_ANGMAX + 1 - shape(branch)[1]))]

    Ybus2, Yf, Yt = makeYbus(baseMVA, bus, branch)
    #print(Yf)
    ## compute branch flows
    Sf = V[branch[:, F_BUS].astype(int)] * conj(
        Yf * V)  ## cplx pwr at "from" bus, p["u"].
    St = V[branch[:, T_BUS].astype(int)] * conj(
        Yt * V)  ## cplx pwr at "to" bus, p["u"].

    branch[:, PF] = Sf.real * baseMVA
    branch[:, QF] = Sf.imag * baseMVA
    branch[:, PT] = St.real * baseMVA
    branch[:, QT] = St.imag * baseMVA

    #gen[:, VG] = Vm[ gen[:, GEN_BUS].astype(int) ]

    nlam = len(lmbda["eqnonlin"]) // 2
    lamP = zeros(nb)  #for non-included pf balances use 0 as multiplier
    lamQ = zeros(nb)
    lamP[s.idx['rbus']['int']] = lmbda["eqnonlin"][:nlam] / s.region["baseMVA"]
    lamQ[s.idx['rbus']['int']] = lmbda["eqnonlin"][nlam:nlam +
                                                   nlam] / s.region["baseMVA"]

    ong = find((gen[:, GEN_STATUS] > 0) & ~isload(gen))
    objValue1 = 0
    objValue2 = 0

    fd = stdout
    fd.write('\n REGION %d' % (s.ID))

    fd.write(
        '\nBus/Area  Voltage          Generation             Load        ')
    fd.write('  Lambda($/MVA-hr)')
    fd.write(
        '\n  #   Mag(pu) Ang(deg)   P (MW)   Q (MVAr)   P (MW)   Q (MVAr)')
    fd.write('     P        Q   ')
    fd.write(
        '\n----- ------- --------  --------  --------  --------  --------')
    fd.write('  -------  -------')
    for i in range(nb):
        for glob, loc in s.idx["mapping"].items():
            if loc == i:
                busid = glob + 1
                #bus[i,BUS_I]=glob+1
                pass
        fd.write('\n%5d/' % busid)
        fd.write('%d%7.3f%9.3f' % tuple(bus[i, [BUS_AREA, VM, VA]]))
        if bus[i, BUS_TYPE] == REF:
            fd.write('*')
        else:
            fd.write(' ')
        g = find((gen[:, GEN_STATUS] > 0) & (gen[:, GEN_BUS] == bus[i, BUS_I])
                 & ~isload(gen))
        ld = find((gen[:, GEN_STATUS] > 0) & (gen[:, GEN_BUS] == bus[i, BUS_I])
                  & isload(gen))
        if any(g + 1):
            fd.write('%9.2f%10.2f' % (sum(gen[g, PG]), sum(gen[g, QG])))
            objValue1 = objValue1 + (lamP[i]) * (sum(gen[g, PG]))
        else:
            fd.write('      -         -  ')
        if logical_or(bus[i, PD], bus[i, QD]) | any(ld + 1):
            if any(ld + 1):
                fd.write('%10.2f*%9.2f*' % (bus[i, PD] - sum(gen[ld, PG]),
                                            bus[i, QD] - sum(gen[ld, QG])))
                objValue2 = objValue2 + (lamP[i]) * (bus[i, PD] -
                                                     sum(gen[ld, PG]))
            else:
                fd.write('%10.2f%10.2f ' % tuple(bus[i, [PD, QD]]))
        else:
            fd.write('       -         -   ')

        fd.write('%9.3f' % lamP[i])

        if abs(lamQ[i]) > 1e-4:
            fd.write('%8.3f' % lamQ[i])
        else:
            fd.write('     -')
    fd.write(
        '\n                        --------  --------  --------  --------')
    nzld = find((bus[:, PD] != 0.0) | (bus[:, QD] != 0.0))
    onld = find((gen[:, GEN_STATUS] > 0) & isload(gen))

    fd.write('\n               Total: %9.2f %9.2f %9.2f %9.2f' %
             (sum(gen[ong, PG]), sum(gen[ong, QG]), sum(bus[nzld, PD]) -
              sum(gen[onld, PG]), sum(bus[nzld, QD]) - sum(gen[onld, QG])))
    fd.write('\n')

    print("Local iteration of worker %d is %d" % (ID, nu))
    # calculate local generation cost
    gencost = s.region['gencost']
    pg = s.var['Pg']
    """
	objValue21=0
	for i in range(ng):
		if(pg[i]>0):
			objValue1 = objValue1 - gencost[i,COST+1]* pg[i]
			print(gencost[i,COST+1]* pg[i])
		else:
			objValue21 = objValue21 + gencost[i,COST+1]* (-pg[i])
			print(gencost[i,COST+1]* (-pg[i]))
	objValue2 = objValue21 - objValue2
	objValue = objValue1 + objValue2
	"""

    objValue = dot(gencost[:, COST], pg**2) + dot(
        gencost[:, COST + 1], pg) + sum(gencost[:, COST + 2])
    print(objValue)

    varDual = {
        'ymd': s.var['ymd'],
        'yad': s.var['yad'],
        'yms': s.var['yms'],
        'yas': s.var['yas']
    }
    varPrimal = {
        'Vm': s.var['Vm'],
        'Va': s.var['Va'],
        'Pg': s.var['Pg'],
        'Qg': s.var['Qg']
    }
    Result = {
        'objValue': objValue,
        'varPrimal': varPrimal,
        'varDual': varDual,
        'localiter': nu,
        'primalgap': s.pb['primalgap'],
        'dualgap': s.pb['dualgap']
    }

    ng = s.region['ng']
    for i in range(ng):
        for glob, loc in s.idx["mapping"].items():
            if gen[i, GEN_BUS] == loc:
                gen[i, GEN_BUS] = glob + 1
                break

    for i in range(nb):
        for glob, loc in s.idx["mapping"].items():
            if loc == i:

                bus[i, BUS_I] = glob + 1

    nl = s.region['nl']
    for i in range(nl):
        for glob, loc in s.idx["mapping"].items():
            #print(glob, loc, branch[i, F_BUS])
            if branch[i, F_BUS] == loc:
                #print(branch[tl1,F_BUS])
                branch[i, F_BUS] = glob + 1
                break
    for i in range(nl):
        for glob, loc in s.idx["mapping"].items():
            #print(glob, loc, branch[i, F_BUS])
            if branch[i, T_BUS] == loc:
                #print(branch[tl1,F_BUS])
                branch[i, T_BUS] = glob + 1
                break

    success = flag
    reg_nb = find(bus[:, BUS_AREA] == ID)

    lamP = lamP[ix_(reg_nb, )]

    lamP2 = numpy.array(lamP)

    reg_bus = bus[ix_(reg_nb, )]
    print(reg_bus[:, BUS_I])
    reg_lam = numpy.array((reg_bus[:, BUS_I], lamP))

    print(reg_lam)

    ppc = {}
    ppc["bus"], ppc["gen"], ppc["branch"] = reg_bus, gen, branch

    ids1 = reg_bus[:, BUS_I]
    ids = numpy.array(ids1)
    #ppc["success"] = success
    #ppc=ext2int(ppc)
    P_history = [i * s.region["baseMVA"] for i in P_history]
    Q_history = [i * s.region["baseMVA"] for i in Q_history]

    #results = int2ext(ppc)
    """
	fig = plt.figure()
	curfig = fig.add_subplot(1, 2, 1)
	curfig.plot(P_history, color = 'red', linewidth = 2.5, label = 'P')
	curfig = fig.add_subplot(1, 2, 2)
	curfig.plot(Q_history, color = 'blue', linewidth = 2.5, label = 'Q')
	curfig.set_yscale('log')
	curfig.legend(loc='upper right')
	"""

    #plt.show()
    """
	
	print(all_gas)
	
	while( obj.txpool.inspect.pending.__dict__): pass
	end_time2 = time()
	final_balance = obj.eth.getBalance(obj.toChecksumAddress(client.eth_accounts()[0]))
	print("sasasa",ID, "    ",start_balance - final_balance , "Time ", end_time2 - start_time2)
	"""

    output.put((ID - 1, Result, ppc["bus"], ppc["gen"], ppc["branch"], success,
                lamP2, ids, P_history, Q_history))
    """