Exemple #1
0
def test_getters():
    minimal_code = \
    """
    pragma solidity ^0.4.6;
    contract Test {
      uint256 public the_var = 5;
    }
    """
    from ethjsonrpc import EthJsonRpc
    c = EthJsonRpc('127.0.0.1', 9999)
    xx = c.eth_compileSolidity(minimal_code)
    compiled = xx['code']
    contract_tx = c.create_contract(
        c.eth_coinbase(),
        compiled,
        gas=3000000,
    )
    contract_address = str(c.get_contract_address(contract_tx))

    rr = c.call(
        address=contract_address,
        sig='the_var()',
        args=[],
        result_types=['uint256'],
    )

    assert rr[0] == 5, rr
    print('PASSED')
class AddressToUrlTestCase(unittest.TestCase):

    def setUp(self):
        with open('compiled.evm') as f:
            compiled = f.read().rstrip()
        self.c = EthJsonRpc()
        self.c._call('evm_reset')
        self.cb = self.c.eth_coinbase()
        self.contract_addr = self.AddressToUrl(self.cb, compiled)

    def tearDown(self):
        pass

    def test_set(self):
        url = 'http://www.yahoo.com'
        self.set_url(self.cb, self.contract_addr, url)

        result = self.get_url(self.contract_addr, self.cb[2:])
        self.assertEqual(url, result)

    def test_set_clear(self):
        url = 'http://www.yahoo.com'
        self.set_url(self.cb, self.contract_addr, url)

        result = self.get_url(self.contract_addr, self.cb[2:])
        self.assertEqual(url, result)

        self.set_url(self.cb, self.contract_addr, '')

        result = self.get_url(self.contract_addr, self.cb[2:])
        self.assertEqual('', result)

    def test_get(self):
        result = self.get_url(self.contract_addr, self.cb[2:])
        self.assertEqual('', result)

################################################################################

    def AddressToUrl(self, sender, compiled):
        '''
        constructor
        '''
        sig = 'AddressToUrl()'
        args = []
        tx = self.c.create_contract(sender, compiled, 300000, sig, args)
        return self.c.get_contract_address(tx)

    def set_url(self, sender, contract_addr, ip):
        sig = 'set_url(string)'
        args = [ip]
        self.c.call_with_transaction(sender, contract_addr, sig, args)

    def get_url(self, contract_addr, addr):
        sig = 'get_url(address)'
        args = [addr]
        result_types = ['string']
        return self.c.call(contract_addr, sig, args, result_types)[0]
Exemple #3
0
class AddressToUrlTestCase(unittest.TestCase):
    def setUp(self):
        with open('compiled.evm') as f:
            compiled = f.read().rstrip()
        self.c = EthJsonRpc()
        self.c._call('evm_reset')
        self.cb = self.c.eth_coinbase()
        self.contract_addr = self.AddressToUrl(self.cb, compiled)

    def tearDown(self):
        pass

    def test_set(self):
        url = 'http://www.yahoo.com'
        self.set_url(self.cb, self.contract_addr, url)

        result = self.get_url(self.contract_addr, self.cb[2:])
        self.assertEqual(url, result)

    def test_set_clear(self):
        url = 'http://www.yahoo.com'
        self.set_url(self.cb, self.contract_addr, url)

        result = self.get_url(self.contract_addr, self.cb[2:])
        self.assertEqual(url, result)

        self.set_url(self.cb, self.contract_addr, '')

        result = self.get_url(self.contract_addr, self.cb[2:])
        self.assertEqual('', result)

    def test_get(self):
        result = self.get_url(self.contract_addr, self.cb[2:])
        self.assertEqual('', result)


################################################################################

    def AddressToUrl(self, sender, compiled):
        '''
        constructor
        '''
        sig = 'AddressToUrl()'
        args = []
        tx = self.c.create_contract(sender, compiled, 300000, sig, args)
        return self.c.get_contract_address(tx)

    def set_url(self, sender, contract_addr, ip):
        sig = 'set_url(string)'
        args = [ip]
        self.c.call_with_transaction(sender, contract_addr, sig, args)

    def get_url(self, contract_addr, addr):
        sig = 'get_url(address)'
        args = [addr]
        result_types = ['string']
        return self.c.call(contract_addr, sig, args, result_types)[0]
def main():
    #
    # create rpc interface
    #
    try:
        rpc = EthJsonRpc(RPC_HOST, RPC_PORT)
    except:
        print('unable to connect to rpc server at {}:{}'.format(
            RPC_HOST, RPC_PORT))
        sys.exit(-1)

    method = sys.argv[1]

    if method == "newContract":
        owner = sys.argv[2]
        partner = sys.argv[3]
        text = sys.argv[4]

        tx = rpc.call_with_transaction(owner,
                                       CONTRACT_STORAGE_ADDRESS,
                                       'createNewContract(string,string)',
                                       [partner, text],
                                       gas=GAS)
        print(format(tx))

    elif method == "contractData":
        trans_addr = sys.argv[2]
        trans = rpc.eth_getTransactionByHash(trans_addr)
        res = Decoder.decodeABI(trans['input'],
                                'createNewContract(string,string)',
                                ['string', 'string'])
        print(res)

    elif method == "newUser":
        address = sys.argv[2]
        dataString = sys.argv[3]

        tx = rpc.call_with_transaction(address,
                                       USER_STORAGE_ADDRESS,
                                       'setUserIdentityDocs(string)',
                                       [dataString],
                                       gas=GAS)

    elif method == "identification":
        account_addr = sys.argv[2]
        transactionHashes, identityDocuments = rpc.call(
            USER_STORAGE_ADDRESS, 'getUser(address)', [account_addr],
            ['string', 'string'])
        print(identityDocuments)

    elif method == "accounts":
        account_id = sys.argv[2]
        print(rpc.eth_accounts()[int(account_id)])

    else:
        print("method not recognized!")
Exemple #5
0
def main01():
    load_dotenv()
    eth_host = os.environ.get('ETH_HOST')
    eth_port = os.environ.get('ETH_PORT')
    contract_addr = os.environ.get('CONTRACT_ADDR')
    c = EthJsonRpc(eth_host, eth_port)
    # data = c.call(contract_addr, 'rooms(uint256)', [0], ['Room'])
    # print(data)

    data = c.call(contract_addr, 'name()', [], ['string'])
    print(decode(data, 'string'))
Exemple #6
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
def main():
    #
    # receive contract addr
    #
    if len(sys.argv) != 3:
        print('Usage:\npython user.py <contract addr> <account addr>')
        sys.exit(-1)
    contract_addr = sys.argv[1]
    account_addr = sys.argv[2]

    #
    # create rpc interface
    #
    try:
        print('-' * 80)
        rpc = EthJsonRpc(RPC_HOST, RPC_PORT)
        print('client software: {}'.format(rpc.web3_clientVersion()))
        print('block: {}'.format(rpc.eth_blockNumber()))
        print('address: {}'.format(rpc.eth_coinbase()))
    except:
        print('unable to connect to rpc server at {}:{}'.format(
            RPC_HOST, RPC_PORT))
        sys.exit(-1)

    #
    # check contract is online
    #
    print('-' * 80)
    if rpc.eth_getCode(contract_addr) == '0x0':
        print('!!! contract code not available on blockchain !!!')
        sys.exit(-1)
    print('found contract on blockchain!')

    #
    # console
    #
    topics = []
    print('-' * 80)
    print('starting chat command line...')
    while True:
        #
        # simply read input
        #
        sys.stdout.write('>> ')
        command = sys.stdin.readline()

        #
        # quit?
        #
        if 'q' in command:
            sys.exit(0)

        #
        # show help
        #
        elif command == '\n' or 'help' in command:
            print('commands: help, send, status, topics, search, listen')

        #
        # compose new message
        #
        elif 'send' in command:
            print('-' * 80)
            print('[composing new message]')
            sys.stdout.write('message....: ')
            msg = sys.stdin.readline().strip()
            sys.stdout.write('image file.: ')
            img = sys.stdin.readline().strip()
            sys.stdout.write('custom tags: ')
            tag = sys.stdin.readline().strip()
            print('-' * 80)
            print('sending...')
            # loading image
            try:
                image = Image.open(img)
            except Exception as e:
                print('loading {} failed'.format(img))
                continue
            # prediction
            print('precessing image...')
            label = ImageClassifier.predict(img)
            if label is None:
                print('classification failed')
                continue
            print('label: {}'.format(label))
            tag += ' #' + label
            bs = ImageHelper.imgToBytes(image)
            tx = rpc.call_with_transaction(
                account_addr,
                contract_addr,
                'setNewUserState(string,bytes,string)', [msg, bs, tag],
                gas=GAS)
            print('done, transaction id: {}'.format(tx))

        #
        # get own last post
        #
        elif 'status' in command:
            print('-' * 80)
            print('[receiving last post]')
            userMessage, userImage, userTags = rpc.call(
                contract_addr, 'getUserState(address)', [account_addr],
                ['string', 'bytes', 'string'])
            if not userMessage:
                print('nothing posted yet')
                continue
            print('  content: {}'.format(userMessage))
            print('  tags...: {}'.format(userTags))
            ImageHelper.bytesToImg(userImage).show()

        #
        # set tag filters
        #
        elif 'topics' in command:
            topics = [t.strip() for t in command.split()[1:]]
            if len(topics) == 0:
                print('please provide actual topics after <topics> command')
                continue
            print('filter set for messages on topics: {}'.format(topics))

        #
        # search complete blockchain for messages with certain tags
        #
        elif 'search' in command:
            if len(topics) == 0:
                print('call topics first')
                continue
            curBlock = rpc.eth_blockNumber()
            for i in range(curBlock + 1):
                for trans in rpc.eth_getBlockByNumber(i)['transactions']:
                    res = Decoder.decodeABI(trans['input'])
                    if res is None:
                        continue
                    msg, code, tags = res
                    if all(t not in tags for t in topics):
                        continue
                    print('-' * 80)
                    print('message from user {} (block {}):'.format(
                        trans['from'], i))
                    print('  content: {}'.format(msg))
                    print('  tags...: {}'.format(tags))
                    ImageHelper.bytesToImg(code).show(title='{}'.format(tags))

        #
        # start listening for messages
        #
        elif 'listen' in command:
            if len(topics) == 0:
                print('call topics first')
                continue
            global LISTENING
            LISTENING = True
            curBlock = rpc.eth_blockNumber()
            while LISTENING:
                newBlock = rpc.eth_blockNumber()
                if newBlock > curBlock:
                    print('new block detected ({})'.format(newBlock))
                    curBlock = newBlock
                    for trans in rpc.eth_getBlockByNumber(
                            newBlock)['transactions']:
                        res = Decoder.decodeABI(trans['input'])
                        if res is None:
                            continue
                        msg, code, tags = res
                        if all(t not in tags for t in topics):
                            continue
                        print('-' * 80)
                        print('message from user {} (block {}):'.format(
                            trans['from'], newBlock))
                        print('  content: {}'.format(msg))
                        print('  tags...: {}'.format(tags))
                        ImageHelper.bytesToImg(code).show(
                            title='{}'.format(tags))
                time.sleep(1)

        #
        # default response
        #
        else:
            print('command not recognized')
Exemple #8
0
class Ipv4TestCase(unittest.TestCase):

    def setUp(self):
        with open('compiled.evm') as f:
            compiled = f.read().rstrip()
        self.c = EthJsonRpc()
        self.c._call('evm_reset')
        self.cb = self.c.eth_coinbase()
        self.contract_addr = self.AddressToIPv4(self.cb, compiled)

    def tearDown(self):
        pass

################################################################################

    def test_read(self):
        result = self.get_ip(self.contract_addr, self.cb[2:])
        unchained_ip = self.ip_from_chain(result)
        self.assertEqual('0.0.0.0', unchained_ip)

    def test_set_read(self):
        ip = u'192.168.1.1'
        chained_ip = self.ip_to_chain(ip)
        self.set_ip(self.cb, self.contract_addr, chained_ip)

        result = self.get_ip(self.contract_addr, self.cb[2:])
        unchained_ip = self.ip_from_chain(result)
        self.assertEqual(ip, unchained_ip)

    def test_set_delete_read(self):
        ip = u'192.168.1.1'
        chained_ip = self.ip_to_chain(ip)
        self.set_ip(self.cb, self.contract_addr, chained_ip)

        self.delete_ip(self.cb, self.contract_addr)

        result = self.get_ip(self.contract_addr, self.cb[2:])
        unchained_ip = self.ip_from_chain(result)
        self.assertEqual('0.0.0.0', unchained_ip)


################################################################################

    def ip_to_chain(self, ip):
        return int(IPv4Address(ip))

    def ip_from_chain(self, ip):
        return str(IPv4Address(ip))

################################################################################

    def AddressToIPv4(self, sender, compiled):
        '''
        constructor
        '''
        sig = 'AddressToIPv4()'
        args = []
        tx = self.c.create_contract(sender, compiled, sig, args)
        return self.c.get_contract_address(tx)

    def set_ip(self, sender, contract_addr, ip):
        sig = 'set_ip(uint32)'
        args = [ip]
        self.c.call_with_transaction(sender, contract_addr, sig, args)

    def delete_ip(self, sender, contract_addr):
        sig = 'delete_ip()'
        args = []
        self.c.call_with_transaction(sender, contract_addr, sig, args)

    def get_ip(self, contract_addr, addr):
        sig = 'get_ip(address)'
        args = [addr]
        result_types = ['uint32']
        return self.c.call(contract_addr, sig, args, result_types)[0]
Exemple #9
0
def main():
    #
    # create rpc interface
    #
    try:
        rpc = EthJsonRpc(RPC_HOST, RPC_PORT)
    except:
        print('unable to connect to rpc server at {}:{}'.format(
            RPC_HOST, RPC_PORT))
        sys.exit(-1)

    if sys.argv[1] == "contracts":
        transactionHashes, identityDocuments = rpc.call(
            USER_STORAGE_ADDRESS, 'getUser(address)',
            [0x866d9f0b315afa2dcf31be291882ae9a1965f86a], ['string', 'string'])
        print(transactionHashes)

    elif sys.argv[1] == "newContract":
        owner = sys.argv[2]
        partner = sys.argv[3]
        text = sys.argv[4]

        tx = rpc.call_with_transaction(owner,
                                       CONTRACT_STORAGE_ADDRESS,
                                       'createNewContract(string,string)',
                                       [partner, text],
                                       gas=GAS)
        print('done, transaction id: {}'.format(tx))

        transHash = format(tx)
        trans = rpc.eth_getTransactionByHash(transHash)
        res = Decoder.decodeABI(trans['input'],
                                'createNewContract(string,string)',
                                ['string', 'string'])
        print(res)

        transHashes = transHash  #rpc.call(USER_STORAGE_ADDRESS, 'getUserTransactions(address)', [owner], ['string'])
        #transHashes += "," + transHash;

        tx = rpc.call_with_transaction(owner,
                                       USER_STORAGE_ADDRESS,
                                       'setUserTransactions(string)',
                                       [transHashes],
                                       gas=GAS)

        trans = rpc.eth_getTransactionByHash(format(tx))
        res = Decoder.decodeABI(trans['input'], 'setUserTransactions(string)',
                                ['string'])
        print(res)

        transHashes = transHash  #rpc.call(USER_STORAGE_ADDRESS, 'getUserTransactions(address)', [partner], ['string'])
        #transHashes += "," + transHash;

        tx = rpc.call_with_transaction(partner,
                                       USER_STORAGE_ADDRESS,
                                       'setUserTransactions(string)',
                                       [transHashes],
                                       gas=GAS)

        print('done, transaction id: {}'.format(tx))

        trans = rpc.eth_getTransactionByHash(format(tx))
        res = Decoder.decodeABI(trans['input'], 'setUserTransactions(string)',
                                ['string'])
        print(res)

    owner = "0x866d9f0b315afa2dcf31be291882ae9a1965f86a"
    partner = "0x115908c9272fc6b915286de90e25a24862d69988"
Exemple #10
0
def main():
    """
    Runs doorman and listens for incoming whispers on the configured node.
    When receiving a valid command, starts the configured script with the
    arguments address and command.
    """
    if len(sys.argv) < 2:
        config_filepath = "/etc/lokkit/doorman.yml"
    else:
        config_filepath = sys.argv[1]

    if not os.path.isfile(config_filepath):
        logger.error(
            'Error reading the config file "{}": The file does not exist'.
            format(config_filepath))
        _print_help()
        return 1

    logger.info("Reading config file: {}".format(config_filepath))
    config = _parse_config_file(config_filepath)
    if not config:
        logger.error(
            "Config file could not be parsed: {}".format(config_filepath))
        _print_help()
        return 1

    host = config['node_ip']
    port = config['node_rpc_port']
    rentable_addresses = config['rentable_addresses']
    script = config['script']
    symmetric_key_password = config['symmetric_key_password']

    logger.info('Connecting to {0}:{1}'.format(host, port))
    c = EthJsonRpc(host, port)

    try:
        logger.info('Node shh version: {0}'.format(c.shh_version()))
    except ConnectionError:
        logger.error('Could not connect to {0}:{1}'.format(host, port))
        return
    except:
        logger.error('Shh is not enabled on this node.')
        return

    # config
    topics = []
    logger.info('listening for whispers for {0} addresses'.format(
        len(rentable_addresses)))
    for rentable_address in rentable_addresses:
        try:
            description = c.call(rentable_address, 'description()', [],
                                 ['string'])[0]
            deposit = c.call(rentable_address, 'deposit()', [], ['uint256'])[0]
            location = c.call(rentable_address, 'location()', [],
                              ['string'])[0]
            costPerSecond = c.call(rentable_address, 'costPerSecond()', [],
                                   ['uint256'])[0]
            current_renter = c.call(rentable_address, 'currentRenter()', [],
                                    ['address'])[0]
            address_sha3 = c.web3_sha3(rentable_address)[:10]
            topics.append(address_sha3)
            logger.info('Configured rentable contract {0}\n\
        description: {1}\n\
        location: {2}\n\
        deposit: {3}\n\
        costPerSecond: {4}\n\
        current_renter: {5}\n\
        address sha3: {6}'.format(rentable_address, description, location,
                                  deposit, costPerSecond, current_renter,
                                  address_sha3))
        except AssertionError:
            logger.error(
                'Address {0} is not a Rentable'.format(rentable_address))
            return

    symmetric_key_address = c.shh_addSymmetricKeyFromPassword(
        symmetric_key_password)

    filter_id = c.shh_subscribe(type='sym',
                                key=symmetric_key_address,
                                sig=None,
                                minPow=None,
                                topics=topics)
    logger.info('Listen for incomming messages..')
    try:
        while True:
            messages = c.shh_getNewSubscriptionMessages(filter_id)
            for message in messages:
                logger.debug(
                    'Message details:\n  hash {0}\n  ttl {1}\n  payload: {2}\n  topic: {3}'
                    .format(message['hash'], message['ttl'],
                            message['payload'], message['topic']))

                payload = None
                try:
                    # payload contains digest and message
                    message_payload_string = message['payload'][2:].decode(
                        'hex')
                    payload = json.loads(message_payload_string,
                                         object_pairs_hook=OrderedDict)
                except:
                    logger.error(
                        'Error parsing whisper message payload: {0}'.format(
                            message['payload']))
                    continue

                signature = payload['digest']  # hex value starting with 0x....
                lokkit_message = payload['message']  # dict object
                logger.debug('signature: {0}\nlokkit_message {1}'.format(
                    signature, lokkit_message))

                # get ethereum address of the sender
                message_json = json.dumps(
                    lokkit_message,
                    separators=(',', ':'))  # separators: no whitespaces
                message_hex_string = '0x{0}'.format(message_json.encode('hex'))
                logger.debug(
                    'message_json_string {0}\nmessage_json_string_hex {1}'.
                    format(message_json, message_hex_string))

                signer = c.personal_ecRecover(message_hex_string, signature)
                key = lokkit_message['key']

                logger.info(
                    'command "{0}", rentableAddress "{1}", key "{2}"'.format(
                        lokkit_message['command'],
                        lokkit_message['rentableAddress'], key))
                logger.info(
                    'signing ethereum account (recovered) "{0}"'.format(
                        signer))

                current_renter = c.call(rentable_address, 'currentRenter()',
                                        [], ['address'])[0]
                logger.info(
                    'current renter (smart contract)      "0x{0}"'.format(
                        current_renter))

                if signer[2:] != current_renter:
                    logger.error(
                        'Refuse execution of command "{0}": requester ({1}) is not the current renter ({2}) of rentable "{3}"'
                        .format(lokkit_message['command'], signer,
                                current_renter,
                                lokkit_message['rentableAddress']))
                    continue

                if message['sig'] == '':
                    logger.error(
                        'The envelope was not signed by the sender. Signature with an asymmetric key is required.'
                    )
                    continue

                if key != message['sig']:
                    logger.error(
                        'Encrypted public key is not of the sender. Possible replay attack detected'
                    )
                    logger.error(key)
                    logger.error(message['sig'])
                    continue

                logger.info(
                    'Executing script "{0}" with argument "{1}" for rentable "{2}"'
                    .format(script, lokkit_message['command'],
                            lokkit_message['rentableAddress']))
                subprocess.call([script, lokkit_message['command']])

            sleep(1)
    except KeyboardInterrupt:
        pass
Exemple #11
0
class LiteIDContract:
    def __init__(self, ip='127.0.0.1', port=8545, contract_id=None):
        self.connection = EthJsonRpc(ip, port)
        self.contract_id = contract_id
        self.abi_def = [{
            "constant":
            False,
            "inputs": [],
            "name":
            "dumpSaltedHashArray",
            "outputs": [{
                "name": "Hashes",
                "type": "bytes32[]"
            }, {
                "name": "Salts",
                "type": "bytes32[]"
            }, {
                "name": "Timestamps",
                "type": "uint256[]"
            }],
            "payable":
            False,
            "type":
            "function"
        }, {
            "constant":
            False,
            "inputs": [{
                "name": "Hash",
                "type": "bytes32"
            }, {
                "name": "Salt",
                "type": "bytes32"
            }],
            "name":
            "addHash",
            "outputs": [],
            "payable":
            False,
            "type":
            "function"
        }, {
            "inputs": [{
                "name": "Hash",
                "type": "bytes32"
            }, {
                "name": "Salt",
                "type": "bytes32"
            }],
            "payable":
            False,
            "type":
            "constructor"
        }]

    @staticmethod
    def _calculate_hash(data_to_hash):
        salt = SHA256.new()
        salt.update(bytes(random.getrandbits(256)))
        original_hash = SHA256.new()
        original_hash.update(data_to_hash)
        salted_hash = SHA256.new()
        salted_hash.update(original_hash.digest() + salt.digest())
        salt = salt.hexdigest().decode("hex")
        original_hash = original_hash.hexdigest().decode("hex")
        salted_hash = salted_hash.hexdigest().decode("hex")
        return salted_hash, salt, original_hash, data_to_hash

    def unlock_account(self, account, password):
        self.connection._call('personal_unlockAccount',
                              params=[account, password, 36000])

    def add_hash(self, data):
        if self.contract_id is None:
            raise IOError
        salted_hash, salt, original_hash, _ = self._calculate_hash(data)
        tx = self.connection.call_with_transaction(
            self.connection.eth_coinbase(), self.contract_id,
            'addHash(bytes32,bytes32)', [salted_hash, salt])
        print("Waiting for addHash to be mined")
        while self.connection.eth_getTransactionReceipt(tx) is None:
            time.sleep(1)
        return original_hash

    def create_contract(self, data):
        if not hasattr(self, 'byte_code'):
            contract_file = open(__file__[:-11] + '\LiteID-Contract.sol')
            code_data = self.connection.eth_compileSolidity(
                contract_file.read())
            self.byte_code = code_data['ID']['code']
            self.abi_def = code_data['ID']['info']['abiDefinition']
        salted_hash, salt, original_hash, _ = self._calculate_hash(data)
        tx_id = self.connection.create_contract(self.connection.eth_coinbase(),
                                                self.byte_code,
                                                300000,
                                                sig='addHash(bytes32,bytes32)',
                                                args=[salted_hash, salt])
        print("Waiting for contract to be mined")
        while self.connection.eth_getTransactionReceipt(tx_id) is None:
            time.sleep(1)
        self.contract_id = self.connection.eth_getTransactionReceipt(
            tx_id)['contractAddress']
        return self.contract_id

    def dump_hashes(self):
        return_types = list()
        for item in self.abi_def:
            try:
                if item['name'] == 'dumpSaltedHashArray':
                    for i in item['outputs']:
                        return_types.append(i['type'])
            except KeyError:
                pass
        return_types = ['bytes32[]', 'bytes32[]', 'uint256[]']
        return self.connection.call(self.contract_id, 'dumpSaltedHashArray()',
                                    [], return_types)
Exemple #12
0
import sys, os, time
#from solc import compile_source, compile_files, link_code
from ethjsonrpc import EthJsonRpc
import RPi.GPIO as GPIO
from telnetlib import theNULL

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)
GPIO.setup(17, GPIO.OUT)
GPIO.setup(27, GPIO.OUT)
GPIO.setup(22, GPIO.OUT)

relays = [4, 17, 27, 22]
results = [1]

c = EthJsonRpc('192.168.0.109', 8545)
#compiled = "6060604052341561000f57600080fd5b6102e38061001e6000396000f30060606040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806375d74f3914610051578063e7aab290146100df575b600080fd5b341561005c57600080fd5b61006461013c565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100a4578082015181840152602081019050610089565b50505050905090810190601f1680156100d15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156100ea57600080fd5b61013a600480803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919050506101e4565b005b6101446101fe565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156101da5780601f106101af576101008083540402835291602001916101da565b820191906000526020600020905b8154815290600101906020018083116101bd57829003601f168201915b5050505050905090565b80600090805190602001906101fa929190610212565b5050565b602060405190810160405280600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061025357805160ff1916838001178555610281565b82800160010185558215610281579182015b82811115610280578251825591602001919060010190610265565b5b50905061028e9190610292565b5090565b6102b491905b808211156102b0576000816000905550600101610298565b5090565b905600a165627a7a72305820a1b6671ab3bfba7a22ca49ff7a553d8902a18e098e285942773f570bbc6868b20029"
#contractTx = c.create_contract(c.eth_coinbase(), compiled, gas=300000)
#contractAddr = c.get_contract_address(contractTx)
contractAddr = '0xed4b68c46a5fc176e62fb66b2fe840dc4e5812a8'
while (True):
    time.sleep(5)
    for x in range(0, 4):
        #print(relays[x])
        results = c.call(contractAddr, 'getRelay(uint256)', [x],
                         ['uint256', 'uint256'])
        GPIO.output(relays[x], results[0])
        print(results)
        time.sleep(1)
Exemple #13
0
from ethjsonrpc import EthJsonRpc  # to use Parity-specific methods, import ParityEthJsonRpc

base_address = "0xbb1588c5debc2871cd8852c4bd6c6e4cb1d9fe15"
c = EthJsonRpc('127.0.0.1', 8545)
print(c.net_version())
print(c.web3_clientVersion())
print(c.net_listening())
print(c.net_peerCount())
print(c.eth_mining())
print(c.eth_gasPrice())

contract_addr = "0xc1bba31875a1a66eb4794e6e4dd07811fb58b5c5"
my_addr = str(c.eth_coinbase())
print my_addr
tx = c.call_with_transaction(my_addr, contract_addr, 'pushByte(string)',
                             ['Hello, world'])
print(tx)

results = c.call(contract_addr, 'getdata()', [], ['string'])
print(results)