Пример #1
0
class ETHUtils:
    def __init__(self, account, web3_http_provider, ens_contract, erc20_token=None, abi=None):
        http_provider = HTTPProvider(web3_http_provider)
        self.ens = ENS(http_provider,  addr=ens_contract)
        self.web3 = Web3(http_provider, ens=self.ens)

        from web3.middleware import geth_poa_middleware
        # inject the poa compatibility middleware to the innermost layer
        self.web3.middleware_stack.inject(geth_poa_middleware, layer=0)
        self.ens.web3.middleware_stack.inject(geth_poa_middleware, layer=0)

        if erc20_token is not None and abi is not None:
            token_address = self.ens.address(erc20_token)
            self.erc20 = self.web3.eth.contract(token_address, abi=abi)
            self.erc20_balance_delimiter = (10 ** self.erc20.functions.decimals().call())

        self.__account = account

    @property
    def erc20Contract(self):
        return self.erc20

    @property
    def getCurrentBlockNumber(self):
        return self.web3.eth.blockNumber

    def getAddressByName(self, name):
        return self.ens.address(name)

    def getAccountTransactionCount(self):
        return self.web3.eth.getTransactionCount(self.__account.address)

    def signTransaction(self, tx):
        return self.__account.signTransaction(tx)

    def sendRawTransaction(self, raw_tx):
        return self.web3.eth.sendRawTransaction(raw_tx)

    def signAndSendTransaction(self, tx):
        signed_tx = self.signTransaction(tx=tx)
        return self.sendRawTransaction(raw_tx=signed_tx.rawTransaction)

    def getTransaction(self, tx_hash):
        return self.web3.eth.getTransaction(tx_hash)

    def getBalance(self, account):
        return self.web3.fromWei(self.web3.eth.getBalance(account), 'ether')

    def getTokenBalance(self, account):
        return self.erc20.functions.balanceOf(account).call() / self.erc20_balance_delimiter

    def getAllowance(self, account, address):
        return self.erc20.functions.allowance(account, address).call()
Пример #2
0
class Node:
    def __init__(self):
        rospy.init_node('erc20_node', anonymous=True)

        http_provider = HTTPProvider(rospy.get_param('~web3_http_provider'))
        self.ens = ENS(http_provider,
                       addr=rospy.get_param('~ens_contract', None))
        self.web3 = Web3(http_provider, ens=self.ens)

        from web3.middleware import geth_poa_middleware
        # inject the poa compatibility middleware to the innermost layer
        self.web3.middleware_stack.inject(geth_poa_middleware, layer=0)
        self.ens.web3.middleware_stack.inject(geth_poa_middleware, layer=0)

        token_address = self.ens.address(rospy.get_param('~token_contract'))
        self.erc20 = self.web3.eth.contract(token_address, abi=ABI)

        self.transfer = rospy.Publisher('event/transfer',
                                        TransferEvent,
                                        queue_size=10)
        self.approval = rospy.Publisher('event/approval',
                                        ApprovalEvent,
                                        queue_size=10)

        rospy.Service(
            'transfer', Transfer, lambda m: TransferResponse(
                self.erc20.functions.transfer(m.to.address, int(m.value.uint256
                                                                )).transact()))

        rospy.Service(
            'transfer_from', TransferFrom, lambda m: TransferFromResponse(
                self.erc20.functions
                .transferFrom(m.owner.address, m.to.address,
                              int(m.value.uint256)).transact()))

        rospy.Service(
            'approve', Approve, lambda m: ApproveResponse(
                self.erc20.functions.approve(m.spender.address,
                                             int(m.value.uint256)).transact()))

        rospy.Service(
            'accounts', Accounts, lambda m: AccountsResponse(
                list(map(strToAddress, self.web3.eth.accounts))))

    def spin(self):
        transfer_filter = self.erc20.eventFilter('Transfer')
        approval_filter = self.erc20.eventFilter('Approval')

        def filter_thread():
            for e in transfer_filter.get_new_entries():
                self.transfer.publish(transferEvent(e['args']))

            for e in approval_filter.get_new_entries():
                self.approval.publish(approvalEvent(e['args']))

            Timer(1, filter_thread).start()

        filter_thread()

        rospy.spin()
Пример #3
0
class Signer:
    def __init__(self):
        '''
            Lighthouse signer initialisation.
        '''
        rospy.init_node('robonomics_signer')

        ens_contract = rospy.get_param('~ens_contract', None)
        web3_http_provider = rospy.get_param('~web3_http_provider')
        http_provider = HTTPProvider(web3_http_provider)

        self.ens = ENS(http_provider, addr=ens_contract)
        self.web3 = Web3(http_provider, ens=self.ens)

        from web3.middleware import geth_poa_middleware
        # inject the poa compatibility middleware to the innermost layer
        self.web3.middleware_stack.inject(geth_poa_middleware, layer=0)
        self.ens.web3.middleware_stack.inject(geth_poa_middleware, layer=0)

        __factory_contract_abi = rospy.get_param('~factory_contract_abi')
        __factory_contract = rospy.get_param('~factory_contract')
        self.factory = None

        __keyfile = rospy.get_param('~keyfile')
        __keyfile_password_file = rospy.get_param('~keyfile_password_file')

        __keyfile_helper = eth_keyfile_helper.KeyfileHelper(
            __keyfile, keyfile_password_file=__keyfile_password_file)
        self.__account = __keyfile_helper.get_local_account_from_keyfile()

        self.signed_demand = rospy.Publisher('sending/demand',
                                             Demand,
                                             queue_size=10)
        self.signed_offer = rospy.Publisher('sending/offer',
                                            Offer,
                                            queue_size=10)
        self.signed_result = rospy.Publisher('sending/result',
                                             Result,
                                             queue_size=10)

        self.__factory_initialization_lock = Lock()

        def get_initialized_factory():
            if self.factory is None:
                try:
                    factory_abi = json.loads(__factory_contract_abi)
                    factory_address = self.ens.address(__factory_contract)
                    try:
                        self.__factory_initialization_lock.acquire()
                        if self.factory is None:
                            self.factory = self.web3.eth.contract(
                                factory_address, abi=factory_abi)
                    finally:
                        self.__factory_initialization_lock.release()

                    return self.factory
                except StaleBlockchain as e:
                    rospy.logwarn(
                        "Failed to initialize factory cause exception: %s", e)
            else:
                return self.factory

        def get_nonce_by_address(address):
            try:
                nonce = get_initialized_factory().call().nonceOf(
                    address.address)
                return UInt256(nonce)
            except Exception as e:
                rospy.logerr(
                    "Failed to get nonce by address %s with exception: %s",
                    address.address, e)
                try:
                    self.__factory_initialization_lock.acquire()
                    self.factory = None
                finally:
                    self.__factory_initialization_lock.release()

        def sign_demand(msg):
            msg.sender = Address(self.__account.address)

            if messageValidator.isDemandFieldsCorrect(msg):
                msg = robonomicsMessageUtils.convert_msg_ens_names_to_addresses(
                    msg, web3=self.web3)
                current_nonce = get_nonce_by_address(msg.sender)
                message_hash = robonomicsMessageUtils.demand_hash(
                    msg, current_nonce)
                signed_hash = self.__account.signHash(
                    defunct_hash_message(message_hash))
                msg.signature = signed_hash.signature
                msg.nonce = UInt256(uint256=str(current_nonce.uint256))
                rospy.loginfo('askhash: %s signature: %s',
                              binascii.hexlify(message_hash),
                              binascii.hexlify(msg.signature))
                self.signed_demand.publish(msg)
            else:
                rospy.logerr(
                    "Signing demand error: msg %s is not valid Demand message",
                    msg)

        rospy.Subscriber('signing/demand', Demand, sign_demand)

        def sign_offer(msg):
            msg.sender = Address(self.__account.address)

            if messageValidator.isOfferFieldsCorrect(msg):
                msg = robonomicsMessageUtils.convert_msg_ens_names_to_addresses(
                    msg, web3=self.web3)
                current_nonce = get_nonce_by_address(msg.sender)
                message_hash = robonomicsMessageUtils.offer_hash(
                    msg, current_nonce)
                signed_hash = self.__account.signHash(
                    defunct_hash_message(message_hash))
                msg.signature = signed_hash.signature
                msg.nonce = UInt256(uint256=str(current_nonce.uint256))
                rospy.loginfo('bidhash: %s signature: %s',
                              binascii.hexlify(message_hash),
                              binascii.hexlify(msg.signature))
                self.signed_offer.publish(msg)
            else:
                rospy.logerr(
                    "Signing offer error: msg %s is not valid Offer message",
                    msg)

        rospy.Subscriber('signing/offer', Offer, sign_offer)

        def sign_result(msg):
            if messageValidator.isResultFieldsCorrect(msg):
                msg = robonomicsMessageUtils.convert_msg_ens_names_to_addresses(
                    msg, web3=self.web3)
                message_hash = robonomicsMessageUtils.result_hash(msg)
                signed_hash = self.__account.signHash(
                    defunct_hash_message(message_hash))
                msg.signature = signed_hash.signature
                rospy.loginfo('reshash: %s signature: %s',
                              binascii.hexlify(message_hash),
                              binascii.hexlify(msg.signature))
                self.signed_result.publish(msg)
            else:
                rospy.logerr(
                    "Signing result error: msg %s is not valid Result message")

        rospy.Subscriber('signing/result', Result, sign_result)

    def spin(self):
        '''
            Waiting for the new messages.
        '''
        rospy.spin()
Пример #4
0
class Listener:
    def __init__(self):
        '''
            Robonomics liability tracking node initialisation.
        '''
        rospy.init_node('robonomics_liability_listener')

        web3_http_provider = rospy.get_param('~web3_http_provider')
        http_provider = HTTPProvider(web3_http_provider)

        web3_ws_provider = rospy.get_param('~web3_ws_provider')
        ws_provider = WebsocketProvider(web3_ws_provider)

        ens_contract = rospy.get_param('~ens_contract', None)

        self.ens = ENS(http_provider, addr=ens_contract)
        self.web3 = Web3(http_provider, ens=self.ens)

        self.web3ws = Web3(ws_provider, ens=self.ens)

        from web3.middleware import geth_poa_middleware
        # inject the poa compatibility middleware to the innermost layer
        self.web3.middleware_stack.inject(geth_poa_middleware, layer=0)
        self.ens.web3.middleware_stack.inject(geth_poa_middleware, layer=0)

        self.poll_interval = rospy.get_param('~poll_interval', 5)

        self.liability = rospy.Publisher('incoming', Liability, queue_size=10)

        self.create_liability_filter()

        self.liability_abi = json.loads(
            rospy.get_param('~liability_contract_abi'))

        self.liability_finalization_checker = finalization_checker.FinalizationChecker(
            self.liability_abi,
            web3_http_provider=web3_http_provider,
            ens_contract=ens_contract)
        self.finalized = rospy.Publisher('finalized', String, queue_size=10)

        self.liabilities_queue = PersistentQueue(
            'robonomics_liability_listener.queue')

        self.result = rospy.Publisher('infochan/eth/signing/result',
                                      Result,
                                      queue_size=10)

        self.persistence_contains_liability = rospy.ServiceProxy(
            'persistence/exists', PersistenceContainsLiability)

        def liability_finalize(msg):
            rospy.logdebug("liability_finalize: msg is: %s", msg)
            is_finalized = False
            while is_finalized is not True:
                self.result.publish(msg)
                time.sleep(30)
                # TODO: move sleep time to rop parameter with 30 seconds by default
                is_finalized = self.liability_finalization_checker.finalized(
                    msg.liability.address)
            self.finalized.publish(msg.liability.address)

        rospy.Subscriber('result', Result, liability_finalize)

    def create_liability_filter(self):
        try:
            factory_abi = json.loads(rospy.get_param('~factory_contract_abi'))
            factory_address = self.ens.address(
                rospy.get_param('~factory_contract'))
            factory = self.web3ws.eth.contract(factory_address,
                                               abi=factory_abi)
            self.liability_filter = factory.eventFilter('NewLiability')
        except Exception as e:
            rospy.logwarn(
                "Failed to create liability filter with exception: \"%s\"", e)

    def liability_read(self, address):
        '''
            Read liability from blockchain to message.
        '''
        c = self.web3.eth.contract(address, abi=self.liability_abi)
        msg = Liability()
        msg.address.address = address
        msg.model.multihash = multihash.decode(
            c.call().model()).encode('base58').decode()
        msg.objective.multihash = multihash.decode(
            c.call().objective()).encode('base58').decode()
        msg.promisee.address = c.call().promisee()
        msg.promisor.address = c.call().promisor()
        msg.lighthouse.address = c.call().lighthouse()
        msg.token.address = c.call().token()
        msg.cost.uint256 = str(c.call().cost())
        msg.validator.address = c.call().validator()
        msg.validatorFee.uint256 = str(c.call().validatorFee())
        rospy.logdebug('New liability readed: %s', msg)
        return msg

    def spin(self):
        '''
            Waiting for the new liabilities.
        '''
        def liability_filter_thread():
            try:
                for entry in self.liability_filter.get_new_entries():
                    liability_address = entry['args']['liability']
                    self.liabilities_queue.push(liability_address)
                    rospy.loginfo(
                        "New liability added to persistence queue: %s",
                        liability_address)
            except Exception as e:
                rospy.logerr('listener liability filter exception: %s', e)
                self.create_liability_filter()
            Timer(self.poll_interval, liability_filter_thread).start()

        def liabilities_queue_handler():
            entry = self.liabilities_queue.peek()
            if entry is not None:
                try:
                    rospy.wait_for_service(
                        self.persistence_contains_liability.resolved_name)
                    liability_already_in_persistence = self.persistence_contains_liability(
                        entry)

                    # TODO: verify that liability for my saved in persistence before pop them from liabilities_queue
                    if not liability_already_in_persistence.exists:
                        self.liability.publish(self.liability_read(entry))

                    self.liabilities_queue.pop()
                    rospy.loginfo("Liability read successfully: %s", entry)
                except Exception as e:
                    rospy.logerr('Liability %s read exception: %s', entry, e)
            Timer(self.poll_interval, liabilities_queue_handler).start()

        liability_filter_thread()
        liabilities_queue_handler()
        rospy.spin()
Пример #5
0
class Listener:
    def __init__(self):
        '''
            Robonomics liability tracking node initialisation.
        '''
        rospy.init_node('robonomics_liability_listener')

        web3_http_provider = rospy.get_param('~web3_http_provider')
        http_provider = HTTPProvider(web3_http_provider)

        web3_ws_provider = rospy.get_param('~web3_ws_provider')
        ws_provider = WebsocketProvider(web3_ws_provider)

        ens_contract = rospy.get_param('~ens_contract', None)

        self.ens = ENS(http_provider, addr=ens_contract)
        self.web3 = Web3(http_provider, ens=self.ens)

        self.web3ws = Web3(ws_provider, ens=self.ens)

        from web3.middleware import geth_poa_middleware
        # inject the poa compatibility middleware to the innermost layer
        self.web3.middleware_stack.inject(geth_poa_middleware, layer=0)
        self.ens.web3.middleware_stack.inject(geth_poa_middleware, layer=0)

        self.poll_interval = rospy.get_param('~poll_interval', 5)

        self.liability = rospy.Publisher('incoming', Liability, queue_size=10)

        self.create_liability_filter()

        self.liability_abi = json.loads(
            rospy.get_param('~liability_contract_abi'))

        self.liability_finalization_checker = finalization_checker.FinalizationChecker(
            self.liability_abi,
            web3_http_provider=web3_http_provider,
            ens_contract=ens_contract)
        self.finalized = rospy.Publisher('finalized', String, queue_size=10)

        self.result_handler()

    def create_liability_filter(self):
        try:
            factory_abi = json.loads(rospy.get_param('~factory_contract_abi'))
            factory_address = self.ens.address(
                rospy.get_param('~factory_contract'))
            factory = self.web3ws.eth.contract(factory_address,
                                               abi=factory_abi)
            self.liability_filter = factory.eventFilter('NewLiability')
        except Exception as e:
            rospy.logwarn(
                "Failed to create liability filter with exception: \"%s\"", e)

    def result_handler(self):
        result = rospy.Publisher('infochan/eth/signing/result',
                                 Result,
                                 queue_size=10)

        def liability_finalize(msg):
            is_finalized = False
            while is_finalized is not True:
                result.publish(msg)
                time.sleep(30)
                # TODO: move sleep time to rop parameter with 30 seconds by default
                is_finalized = self.liability_finalization_checker.finalized(
                    msg.liability)
            self.finalized.publish(msg.liability)

        rospy.Subscriber('result', Result, liability_finalize)

    def liability_read(self, address):
        '''
            Read liability from blockchain to message.
        '''
        c = self.web3.eth.contract(address, abi=self.liability_abi)
        msg = Liability()

        model_mh = Multihash()
        model_mh.multihash = multihash.decode(
            c.call().model()).encode('base58').decode()

        objective_mh = Multihash()
        objective_mh.multihash = multihash.decode(
            c.call().objective()).encode('base58').decode()

        msg.address = address
        msg.model = model_mh
        msg.objective = objective_mh
        msg.promisee = c.call().promisee()
        msg.promisor = c.call().promisor()
        msg.lighthouse = c.call().lighthouse()
        msg.token = c.call().token()
        msg.cost = c.call().cost()
        msg.validator = c.call().validator()
        msg.validatorFee = c.call().validatorFee()
        rospy.logdebug('New liability readed: %s', msg)
        return msg

    def spin(self):
        '''
            Waiting for the new liabilities.
        '''
        def liability_filter_thread():
            try:
                # TODO: improve error logging
                for entry in self.liability_filter.get_new_entries():
                    self.liability.publish(
                        self.liability_read(entry['args']['liability']))
            except Exception as e:
                rospy.logerr('listener liability filter exception: %s', e)
                self.create_liability_filter()
            Timer(self.poll_interval, liability_filter_thread).start()

        liability_filter_thread()

        rospy.spin()
Пример #6
0
class TestExecutor(unittest.TestCase):
    def __init__(self, *args):
        rospy.init_node(NAME)
        super(TestExecutor, self).__init__(*args)

        ipfs_provider = urlparse(
            rospy.get_param('~ipfs_http_provider')).netloc.split(':')
        self.ipfs = ipfsapi.connect(ipfs_provider[0], int(ipfs_provider[1]))

        self.test_token = rospy.get_param('~test_token')
        self.test_bid_publisher = rospy.Publisher(
            '/liability/test_executor/o/eth/signing/offer',
            Offer,
            queue_size=10)
        self.test_ask_publisher = rospy.Publisher(
            '/liability/test_executor/d/eth/signing/demand',
            Demand,
            queue_size=10)

        web3_http_provider = rospy.get_param('~web3_http_provider')
        http_provider = HTTPProvider(web3_http_provider)
        ens_contract = rospy.get_param('~ens_contract', None)

        self.ens = ENS(http_provider, addr=ens_contract)
        self.web3 = Web3(http_provider, ens=self.ens)

        from web3.middleware import geth_poa_middleware
        # inject the poa compatibility middleware to the innermost layer
        self.web3.middleware_stack.inject(geth_poa_middleware, layer=0)
        self.ens.web3.middleware_stack.inject(geth_poa_middleware, layer=0)
        self.lighthouse_address = self.ens.address(
            rospy.get_param('~lighthouse_contract'))

        self.test_start_time = time.time()

        self.success = False
        self.ready_liability = None

        self.test_objective = self.create_test_objective()
        rospy.logwarn("TEST EXECUTOR: CURRENT OBJECTIVE is %s",
                      self.test_objective)

    def create_test_objective(self):
        with TemporaryDirectory() as tmpdir:
            os.chdir(tmpdir)
            test_objective_bag = rosbag.Bag('output.bag', 'w')
            email_data = String(data='test@mail')
            droneid_data = String(data='test_drone_000')

            test_objective_bag.write('/agent/objective/droneid', droneid_data,
                                     rospy.Time().now())
            test_objective_bag.write('/agent/objective/email', email_data,
                                     rospy.Time().now())

            test_objective_bag.close()

            ipfs_objective = self.ipfs.add(test_objective_bag.filename)
            rospy.logwarn("TEST_EXECUTOR: ADD TEST OBJECTIVE TO IPFS is %s",
                          ipfs_objective)
            return ipfs_objective['Hash']

    def ready_liability_handler(self, msg):
        self.ready_liability = msg
        rospy.logwarn("EXECUTOR: READY LIABILITY address is %s",
                      self.ready_liability.address.address)

    def result_handler(self, msg):
        rospy.logwarn("EXECUTOR: liability: %s result %s", msg.liability,
                      msg.result)

        if self.ready_liability is not None \
                and self.ready_liability.address.address == msg.liability.address \
                and self.check_rosbag_is_new_and_has_messages(msg):
            self.success = True

    def check_rosbag_is_new_and_has_messages(self, msg):
        with TemporaryDirectory() as tmpdir:
            os.chdir(tmpdir)
            self.ipfs.get(msg.result.multihash)
            bag = rosbag.Bag(msg.result.multihash, 'r')
            bag_topics = bag.get_type_and_topic_info()

            bag_topics_dict = {}
            for topic, topic_info in bag_topics[1].items():
                bag_topics_dict[topic] = topic_info[1]
                rospy.loginfo(
                    "rosbag contains %s messages of type %s in topic %s",
                    topic_info[1], topic_info[0], topic)
            rospy.loginfo("ROSBAG: result has %s msgs",
                          bag.get_message_count())
            rospy.loginfo("ROSBAG: result has start time %s",
                          bag.get_start_time())
            return bag.get_message_count() == 2 and \
                   bag.get_start_time() > self.test_start_time and \
                   '/liability/eth_{0}/agent/objective/droneid'.format(self.ready_liability.address.address) in bag_topics_dict and \
                   '/liability/eth_{0}/agent/objective/email'.format(self.ready_liability.address.address) in bag_topics_dict

    def test_executor(self):
        rospy.Subscriber('liability/ready', Liability,
                         self.ready_liability_handler)
        rospy.Subscriber('liability/result', Result, self.result_handler)

        time.sleep(15)
        rospy.logwarn("test_executor: publish test offer")
        self.test_bid_publisher.publish(self.get_test_bid())
        rospy.logwarn("test_executor: publish test demand")
        self.test_ask_publisher.publish(self.get_test_ask())

        while self.ready_liability is None:
            time.sleep(0.1)

        start_service_proxy = rospy.ServiceProxy('/liability/start',
                                                 StartLiability)
        start_service_proxy(self.ready_liability.address.address)

        time.sleep(5)

        finish_service_proxy = rospy.ServiceProxy('/liability/finish',
                                                  FinishLiability)
        finish_service_proxy(self.ready_liability.address.address, True)

        while not rospy.is_shutdown() and not self.success:
            time.sleep(0.1)
        self.assert_(self.success)

    def get_test_bid(self):
        bidDict = {
            "model": "QmaRmbJtyfMDBfkDETTPAxKUUcSqZKXWwFKKoZ318nrPku",
            "objective": self.test_objective,
            "token": self.test_token,
            "cost": 0,
            "validator": '0x0000000000000000000000000000000000000000',
            "lighthouse": self.lighthouse_address,
            "lighthouseFee": 0,
            "deadline": 9999999,
            "sender": "",
            "signature": ""
        }
        return messageValidator.dict2bid(bidDict)

    def get_test_ask(self):
        askDict = {
            "model": "QmaRmbJtyfMDBfkDETTPAxKUUcSqZKXWwFKKoZ318nrPku",
            "objective": self.test_objective,
            "token": self.test_token,
            "cost": "0",
            "lighthouse": self.lighthouse_address,
            "validator": "0x0000000000000000000000000000000000000000",
            "validatorFee": 0,
            "deadline": 9999999,
            "sender": "",
            "signature": ""
        }
        return messageValidator.dict2ask(askDict)
class TestExecutor(unittest.TestCase):
    def __init__(self, *args):
        rospy.init_node(NAME)
        super(TestExecutor, self).__init__(*args)

        ipfs_provider = urlparse(
            rospy.get_param('~ipfs_http_provider')).netloc.split(':')
        self.ipfs = ipfsapi.connect(ipfs_provider[0], int(ipfs_provider[1]))

        self.test_token = rospy.get_param('~test_token')
        self.test_bid_publisher = rospy.Publisher(
            '/liability/infochan/eth/signing/offer', Offer, queue_size=10)
        self.test_ask_publisher = rospy.Publisher(
            '/liability/infochan/eth/signing/demand', Demand, queue_size=10)

        web3_http_provider = rospy.get_param('~web3_http_provider')
        http_provider = HTTPProvider(web3_http_provider)
        ens_contract = rospy.get_param('~ens_contract', None)

        self.ens = ENS(http_provider, addr=ens_contract)
        self.web3 = Web3(http_provider, ens=self.ens)

        from web3.middleware import geth_poa_middleware
        # inject the poa compatibility middleware to the innermost layer
        self.web3.middleware_stack.inject(geth_poa_middleware, layer=0)
        self.ens.web3.middleware_stack.inject(geth_poa_middleware, layer=0)

        self.lighthouse_address = self.ens.address(
            rospy.get_param('~lighthouse_contract'))

        self.test_start_time = time.time()

        self.success = False
        self.ready_liability = None

    def ready_liability_handler(self, msg):
        self.ready_liability = msg
        rospy.loginfo("READY LIABILITY HANDLER: address is %s",
                      self.ready_liability.address)

    def result_handler(self, result):
        rospy.loginfo("RESULT HANDLER: liability: %s result %s",
                      result.liability, result.result)

        if self.ready_liability is not None \
                and self.ready_liability.address == result.liability \
                and self.check_rosbag_is_new_and_has_messages(result):
            self.success = True

    def check_rosbag_is_new_and_has_messages(self, result):
        with TemporaryDirectory() as tmpdir:
            os.chdir(tmpdir)
            self.ipfs.get(result.result.multihash)
            bag = rosbag.Bag(result.result.multihash, 'r')
            bag_topics = bag.get_type_and_topic_info()

            bag_topics_dict = {}
            for topic, topic_info in bag_topics[1].items():
                bag_topics_dict[topic] = topic_info[1]
                rospy.loginfo(
                    "rosbag contains %s messages of type %s in topic %s",
                    topic_info[1], topic_info[0], topic)
            rospy.loginfo("ROSBAG: result has %s msgs",
                          bag.get_message_count())
            rospy.loginfo("ROSBAG: result has start time %s",
                          bag.get_start_time())
            return bag.get_message_count() == 2 and \
                   bag.get_start_time() > self.test_start_time and \
                   '/liability/eth_{0}/agent/objective/droneid'.format(self.ready_liability.address) in bag_topics_dict and \
                   '/liability/eth_{0}/agent/objective/email'.format(self.ready_liability.address) in bag_topics_dict

    def test_executor(self):
        rospy.Subscriber('liability/ready', Liability,
                         self.ready_liability_handler)
        rospy.Subscriber('liability/result', Result, self.result_handler)

        time.sleep(15)
        rospy.logwarn("test_executor: publish test offer")
        self.test_bid_publisher.publish(self.get_test_bid())
        rospy.logwarn("test_executor: publish test demand")
        self.test_ask_publisher.publish(self.get_test_ask())

        while self.ready_liability is None:
            time.sleep(0.1)

        start_service_proxy = rospy.ServiceProxy('/liability/start',
                                                 StartLiability)
        start_service_proxy(self.ready_liability.address)

        time.sleep(5)

        finish_service_proxy = rospy.ServiceProxy('/liability/finish',
                                                  FinishLiability)
        finish_service_proxy(self.ready_liability.address, True)

        timeout_t = time.time() + 30.0
        while not rospy.is_shutdown(
        ) and not self.success and time.time() < timeout_t:
            time.sleep(0.1)
        self.assert_(self.success)

    def get_test_bid(self):
        bidDict = {
            "model": "QmaRmbJtyfMDBfkDETTPAxKUUcSqZKXWwFKKoZ318nrPku",
            "objective": "Qmb3H3tHZ1QutcrLq7WEtQWbEWjA11aPqVmeatMSrmFXvE",
            "token": self.test_token,
            "cost": 0,
            "validator": '0x0000000000000000000000000000000000000000',
            "lighthouse": self.lighthouse_address,
            "lighthouseFee": 0,
            "deadline": 9999999
        }
        bid = Offer()
        model_mh = Multihash()
        model_mh.multihash = bidDict['model']

        objective_mh = Multihash()
        objective_mh.multihash = bidDict['objective']

        bid.model = model_mh
        bid.objective = objective_mh
        bid.token = bidDict['token']
        bid.cost = bidDict['cost']
        bid.validator = bidDict['validator']
        bid.lighthouse = bidDict['lighthouse']
        bid.lighthouseFee = bidDict['lighthouseFee']
        bid.deadline = bidDict['deadline']
        return bid

    def get_test_ask(self):
        askDict = {
            "model": "QmaRmbJtyfMDBfkDETTPAxKUUcSqZKXWwFKKoZ318nrPku",
            "objective": "Qmb3H3tHZ1QutcrLq7WEtQWbEWjA11aPqVmeatMSrmFXvE",
            "token": self.test_token,
            "cost": 0,
            "lighthouse": self.lighthouse_address,
            "validator": "0x0000000000000000000000000000000000000000",
            "validatorFee": 0,
            "deadline": 9999999
        }
        ask = Demand()
        model_mh = Multihash()
        model_mh.multihash = askDict['model']

        objective_mh = Multihash()
        objective_mh.multihash = askDict['objective']

        ask.model = model_mh
        ask.objective = objective_mh

        ask.token = askDict['token']
        ask.cost = askDict['cost']
        ask.lighthouse = askDict['lighthouse']
        ask.validator = askDict['validator']
        ask.validatorFee = askDict['validatorFee']
        ask.deadline = askDict['deadline']
        return ask
Пример #8
0
class Signer:
    def __init__(self):
        '''
            Lighthouse signer initialisation.
        '''
        rospy.init_node('robonomics_signer')

        ens_contract = rospy.get_param('~ens_contract', None)
        web3_http_provider = rospy.get_param('~web3_http_provider')
        http_provider = HTTPProvider(web3_http_provider)

        self.ens = ENS(http_provider, addr=ens_contract)
        self.web3 = Web3(http_provider, ens=self.ens)

        __factory_contract_abi = rospy.get_param('~factory_contract_abi')
        __factory_contract = rospy.get_param('~factory_contract')
        self.factory = None

        __keyfile = rospy.get_param('~keyfile')
        __keyfile_password_file = rospy.get_param('~keyfile_password_file')

        __keyfile_helper = eth_keyfile_helper.KeyfileHelper(__keyfile, keyfile_password_file=__keyfile_password_file)
        self.__account = __keyfile_helper.get_local_account_from_keyfile()

        self.signed_demand = rospy.Publisher('sending/demand', Demand, queue_size=10)
        self.signed_offer  = rospy.Publisher('sending/offer',  Offer, queue_size=10)
        self.signed_result = rospy.Publisher('sending/result', Result, queue_size=10)

        self.__factory_initialization_lock = Lock()

        def get_initialized_factory():
            if self.factory is None:
                try:
                    factory_abi = json.loads(__factory_contract_abi)
                    factory_address = self.ens.address(__factory_contract)
                    try:
                        self.__factory_initialization_lock.acquire()
                        if self.factory is None:
                            self.factory = self.web3.eth.contract(factory_address, abi=factory_abi)
                    finally:
                        self.__factory_initialization_lock.release()

                    return self.factory
                except StaleBlockchain as e:
                    rospy.logwarn("Failed to initialize factory cause exception: %s", e)
            else:
                return self.factory

        def get_nonce_by_address(address):
            try:
                nonce = get_initialized_factory().call().nonceOf(address.address)
                return UInt256(nonce)
            except Exception as e:
                rospy.logerr("Failed to get nonce by address %s with exception: %s", address.address, e)
                try:
                    self.__factory_initialization_lock.acquire()
                    self.factory = None
                finally:
                    self.__factory_initialization_lock.release()

        def sign_demand(msg):
            msg.sender = Address(self.__account.address)
            current_nonce = get_nonce_by_address(msg.sender)
            message_hash = robonomicsMessageUtils.demand_hash(msg, current_nonce)
            signed_hash = self.__account.signHash(defunct_hash_message(message_hash))
            msg.signature = signed_hash.signature
            rospy.loginfo('askhash: %s signature: %s', binascii.hexlify(message_hash), binascii.hexlify(msg.signature))
            self.signed_demand.publish(msg)
        rospy.Subscriber('signing/demand', Demand, sign_demand)

        def sign_offer(msg):
            msg.sender = Address(self.__account.address)
            current_nonce = get_nonce_by_address(msg.sender)
            message_hash = robonomicsMessageUtils.offer_hash(msg, current_nonce)
            signed_hash = self.__account.signHash(defunct_hash_message(message_hash))
            msg.signature = signed_hash.signature
            rospy.loginfo('bidhash: %s signature: %s', binascii.hexlify(message_hash), binascii.hexlify(msg.signature))
            self.signed_offer.publish(msg)
        rospy.Subscriber('signing/offer', Offer, sign_offer)

        def sign_result(msg):
            message_hash = robonomicsMessageUtils.result_hash(msg)
            signed_hash = self.__account.signHash(defunct_hash_message(message_hash))
            msg.signature = signed_hash.signature
            rospy.loginfo('reshash: %s signature: %s', binascii.hexlify(message_hash), binascii.hexlify(msg.signature))
            self.signed_result.publish(msg)
        rospy.Subscriber('signing/result', Result, sign_result)

    def spin(self):
        '''
            Waiting for the new messages.
        '''
        rospy.spin()
Пример #9
0
def validate_name_has_address(ens: ENS, name: str) -> ChecksumAddress:
    addr = ens.address(name)
    if addr:
        return addr
    else:
        raise NameNotFound("Could not find address for name %r" % name)
Пример #10
0
class Listener:
    def __init__(self):
        '''
            Robonomics liability tracking node initialisation.
        '''
        rospy.init_node('robonomics_liability_listener')

        http_provider = HTTPProvider(rospy.get_param('~web3_http_provider'))
        self.ens = ENS(http_provider, addr=rospy.get_param('~ens_contract', None))
        self.web3 = Web3(http_provider, ens=self.ens)

        from web3.middleware import geth_poa_middleware
        # inject the poa compatibility middleware to the innermost layer
        self.web3.middleware_stack.inject(geth_poa_middleware, layer=0)
        self.ens.web3.middleware_stack.inject(geth_poa_middleware, layer=0)

        self.poll_interval = rospy.get_param('~poll_interval', 5)

        self.liability = rospy.Publisher('incoming', Liability, queue_size=10)

        factory_abi = json.loads(rospy.get_param('~factory_contract_abi'))
        factory_address = self.ens.address(rospy.get_param('~factory_contract'))
        self.factory = self.web3.eth.contract(factory_address, abi=factory_abi)

        self.liability_abi = json.loads(rospy.get_param('~liability_contract_abi'))

        self.result_handler()

    def result_handler(self):
        result = rospy.Publisher('infochan/signing/result', Result, queue_size=10)

        def liability_finalize(msg):
            c = self.web3.eth.contract(msg.liability, abi=self.liability_abi)
            def try_again():
                if not c.call().isFinalized():
                    result.publish(msg)
                    Timer(30, try_again).start()
            try_again()

        rospy.Subscriber('result', Result, liability_finalize)


    def liability_read(self, address):
        '''
            Read liability from blockchain to message.
        '''
        c = self.web3.eth.contract(address, abi=self.liability_abi)
        msg = Liability()
        msg.address = address
        msg.model = b58encode(c.call().model())
        msg.objective = b58encode(c.call().objective())
        msg.promisee = c.call().promisee()
        msg.promisor = c.call().promisor()
        msg.token = c.call().token()
        msg.cost = c.call().cost()
        msg.validator = c.call().validator()
        msg.validatorFee = c.call().validatorFee()
        rospy.logdebug('New liability readed: %s', msg)
        return msg

    def spin(self):
        '''
            Waiting for the new liabilities.
        '''
        liability_filter = self.factory.eventFilter('NewLiability')
        def liability_filter_thread():
            for entry in liability_filter.get_new_entries():
                self.liability.publish(self.liability_read(entry['args']['liability']))
            Timer(self.poll_interval, liability_filter_thread).start()
        liability_filter_thread()

        rospy.spin()