예제 #1
0
    def test_complete_job(self):
        """Test case for complete_job

        Complete a given job
        """
        with open(f"{PAYOUTS_PATH}", "r") as payouts_file:
            data = payouts_file.read()
        payouts = [(address, Decimal(amount))
                   for (address, amount) in json.loads(data).items()]
        job = Job({
            "gas_payer": GAS_PAYER,
            "gas_payer_priv": GAS_PAYER_PRIV
        }, manifest, FACTORY_ADDRESS)
        job.launch(REP_ORACLE_PUB_KEY)
        job.setup()
        job.bulk_payout(payouts, {}, REP_ORACLE_PUB_KEY)
        query_string = [('address', job.job_contract.address),
                        ('gasPayer', GAS_PAYER),
                        ('gasPayerPrivate', GAS_PAYER_PRIV)]
        response = self.client.open('/job/complete',
                                    method='GET',
                                    query_string=query_string)
        self.assert200(response,
                       'Response body is: ' + response.data.decode('utf-8'))
        self.assertTrue(
            json.loads(response.data.decode('utf-8')).get("success", False))
예제 #2
0
def bulk_payout_job(body=None):  # noqa: E501
    """Performs a payout to multiple ethereum addresses.

    When the payout happens, final results are uploaded to S3 and contract's state is updated to Partial or Paid depending on contract's balance.

    :param body: 
    :type body: dict | bytes

    :rtype: BoolDataResponse
    """
    if connexion.request.is_json:
        body = BulkPayoutJobBody.from_dict(
            connexion.request.get_json())  # noqa: E501
        try:
            factory_addr = launcher(get_escrow(body.address), body.gas_payer)
        except Exception as e:
            return ErrorNotexistResponse(str(e)), 404
        try:
            req = Request(body.results_url)
            req.add_header(
                "User-Agent",
                "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.75 Safari/537.36"
            )
            req.add_header("X-Requested-With", "XMLHttpRequest")
            data = urlopen(req).read()
            results = json.loads(data)
        except Exception as e:
            return ErrorParameterResponse(str(e), "results_url"), 400
        try:
            req = Request(body.payouts_url)
            req.add_header(
                "User-Agent",
                "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.75 Safari/537.36"
            )
            req.add_header("X-Requested-With", "XMLHttpRequest")
            data = urlopen(req).read()
            payouts = [(address, Decimal(amount))
                       for (address, amount) in json.loads(data).items()]
        except Exception as e:
            return ErrorParameterResponse(str(e), "payouts_url"), 400
        try:
            job = Job(credentials={
                "gas_payer":
                body.gas_payer,
                "gas_payer_priv":
                body.gas_payer_private,
                "rep_oracle_priv_key":
                bytes(body.gas_payer_private.lstrip("0x"), encoding="utf-8")
            },
                      factory_addr=factory_addr,
                      escrow_addr=body.address)
        except Exception as e:
            return ErrorUnauthorizedResponse(str(e)), 401
        try:
            return BoolDataResponse(
                job.bulk_payout(payouts, results,
                                bytes(body.rep_oracle_pub,
                                      encoding="utf-8"))), 200
        except Exception as e:
            return ErrorParameterResponse(str(e), "rep_oracle_pub_key"), 400
예제 #3
0
    def test_job_bulk_payout_with_encryption_option(self):
        """Tests whether final results must be persisted in storage encrypted
        or plain.
        """
        job = Job(self.credentials, manifest)
        self.assertEqual(job.launch(self.rep_oracle_pub_key), True)
        self.assertEqual(job.setup(), True)

        payouts = [("0x852023fbb19050B8291a335E5A83Ac9701E7B4E6",
                    Decimal("100.0"))]

        final_results = {'results': 0}

        mock_upload = MagicMock(return_value=('hash', 'url'))

        # Testing option as: do not encrypt final results: encrypt_final_results=False
        with patch('hmt_escrow.job.upload', mock_upload):
            # Bulk payout with final results as plain (not encrypted)
            job.bulk_payout(payouts=payouts,
                            results=final_results,
                            pub_key=self.rep_oracle_pub_key,
                            encrypt_final_results=False)

            mock_upload.assert_called_once_with(
                msg=final_results,
                public_key=self.rep_oracle_pub_key,
                encrypt_data=False)
            mock_upload.reset_mock()

        # Testing option as: encrypt final results: encrypt_final_results=True
        with patch("hmt_escrow.job.upload", mock_upload):
            # Bulk payout with final results as plain (not encrypted)
            job.bulk_payout(payouts=payouts,
                            results={"results": 0},
                            pub_key=self.rep_oracle_pub_key,
                            encrypt_final_results=True)

            mock_upload.assert_called_once_with(
                msg=final_results,
                public_key=self.rep_oracle_pub_key,
                encrypt_data=True)
예제 #4
0
    def test_final_results_job(self):
        """Test case for final_results_job

        Retrieve the final results stored by the Recording Oracle
        """
        job = Job({
            "gas_payer": GAS_PAYER,
            "gas_payer_priv": GAS_PAYER_PRIV
        }, manifest, FACTORY_ADDRESS)
        job.launch(REP_ORACLE_PUB_KEY)
        job.setup()
        payouts = [("0x852023fbb19050B8291a335E5A83Ac9701E7B4E6",
                    Decimal('100.0'))]
        job.bulk_payout(payouts, {'results': 0}, REP_ORACLE_PUB_KEY)
        query_string = [('address', job.job_contract.address),
                        ('gasPayer', GAS_PAYER),
                        ('gasPayerPrivate', GAS_PAYER_PRIV),
                        ('repOraclePrivate', GAS_PAYER_PRIV.lstrip("0x"))]
        response = self.client.open('/job/finalResults',
                                    method='GET',
                                    query_string=query_string)
        self.assert200(response,
                       'Response body is: ' + response.data.decode('utf-8'))
예제 #5
0
class JobTestCase(unittest.TestCase):
    def setUp(self):
        self.credentials = {
            "gas_payer":
            "0x1413862C2B7054CDbfdc181B83962CB0FC11fD92",
            "gas_payer_priv":
            "28e516f1e2f99e96a48a23cea1f94ee5f073403a1c68e818263f0eb898f1c8e5",
        }
        self.rep_oracle_pub_key = b"2dbc2c2c86052702e7c219339514b2e8bd4687ba1236c478ad41b43330b08488c12c8c1797aa181f3a4596a1bd8a0c18344ea44d6655f61fa73e56e743f79e0d"
        self.job = Job(self.credentials, manifest)

    def test_lauch(self):
        """ Tests job launch """
        lauched = self.job.launch(self.rep_oracle_pub_key)
        self.assertEqual(lauched, True)

        next_status = status(self.job.job_contract, self.job.gas_payer)
        self.assertEqual(next_status, Status.Launched)

    def test_status(self):
        lauched = self.job.launch(self.rep_oracle_pub_key)
        self.assertEqual(lauched, True)

        next_status = status(self.job.job_contract, self.job.gas_payer)
        self.assertEqual(next_status, Status.Launched)

    def test_manifest_url(self):
        self.assertTrue(self.job.launch(self.rep_oracle_pub_key))
        self.assertTrue(self.job.setup())
        self.assertEqual(
            manifest_hash(self.job.job_contract, self.job.gas_payer),
            self.job.manifest_hash,
        )

    def test_job_init(self):
        # Creating a new Job instance initializes the critical attributes correctly.
        self.assertEqual(self.job.gas_payer, self.credentials["gas_payer"])
        self.assertEqual(self.job.gas_payer_priv,
                         self.credentials["gas_payer_priv"])
        self.assertEqual(self.job.serialized_manifest["oracle_stake"], "0.05")
        self.assertEqual(self.job.amount, Decimal("100.0"))

        # Initializing a new Job instance with a factory address succeeds.
        factory_addr = deploy_factory(**(self.credentials))
        self.job = Job(self.credentials, manifest, factory_addr)
        self.assertTrue(self.job.factory_contract.address, factory_addr)
        self.assertTrue(self.job.launch(self.rep_oracle_pub_key))
        self.assertTrue(self.job.setup())
        self.assertTrue(
            launcher(self.job.job_contract,
                     self.credentials["gas_payer"]).lower(),
            self.job.factory_contract.address.lower(),
        )

        # Initializing an existing Job instance with a factory and escrow address succeeds.
        self.credentials[
            "rep_oracle_priv_key"] = b"28e516f1e2f99e96a48a23cea1f94ee5f073403a1c68e818263f0eb898f1c8e5"
        escrow_addr = self.job.job_contract.address
        factory_addr = self.job.factory_contract.address
        manifest_url = self.job.manifest_url
        new_job = Job(
            credentials=self.credentials,
            factory_addr=factory_addr,
            escrow_addr=escrow_addr,
        )
        self.assertEqual(new_job.manifest_url, manifest_url)
        self.assertEqual(new_job.job_contract.address, escrow_addr)
        self.assertEqual(new_job.factory_contract.address, factory_addr)
        with self.assertRaises(AttributeError):
            new_job.launch(self.rep_oracle_pub_key)

    def test_job_launch(self):
        self.assertTrue(self.job.launch(self.rep_oracle_pub_key))
        self.assertEqual(self.job.status(), Status(1))
        multi_credentials = [
            (
                "0x61F9F0B31eacB420553da8BCC59DC617279731Ac",
                "486a0621e595dd7fcbe5608cbbeec8f5a8b5cabe7637f11eccfc7acd408c3a0e",
            ),
            (
                "0x6b7E3C31F34cF38d1DFC1D9A8A59482028395809",
                "f22d4fc42da79aa5ba839998a0a9f2c2c45f5e55ee7f1504e464d2c71ca199e1",
            ),
        ]
        self.job = Job(self.credentials,
                       manifest,
                       multi_credentials=multi_credentials)

        # Inject wrong credentials on purpose to test out raffling

        self.job.gas_payer_priv = (
            "657b6497a355a3982928d5515d48a84870f057c4d16923eb1d104c0afada9aa8")
        self.job.multi_credentials = [
            (
                "0x61F9F0B31eacB420553da8BCC59DC617279731Ac",
                "28e516f1e2f99e96a48a23cea1f94ee5f073403a1c68e818263f0eb898f1c8e5",
            ),
            (
                "0x6b7E3C31F34cF38d1DFC1D9A8A59482028395809",
                "f22d4fc42da79aa5ba839998a0a9f2c2c45f5e55ee7f1504e464d2c71ca199e1",
            ),
        ]
        self.assertTrue(self.job.launch(self.rep_oracle_pub_key))
        self.assertEqual(self.job.status(), Status(1))

        # Make sure we launched with raffled credentials

        self.assertEqual(self.job.gas_payer,
                         "0x6b7E3C31F34cF38d1DFC1D9A8A59482028395809")
        self.assertEqual(
            self.job.gas_payer_priv,
            "f22d4fc42da79aa5ba839998a0a9f2c2c45f5e55ee7f1504e464d2c71ca199e1",
        )

    def test_job_setup(self):
        # A Job can't be setup without deploying it first.

        self.assertFalse(self.job.setup())
        multi_credentials = [
            (
                "0x61F9F0B31eacB420553da8BCC59DC617279731Ac",
                "28e516f1e2f99e96a48a23cea1f94ee5f073403a1c68e818263f0eb898f1c8e5",
            ),
            (
                "0x6b7E3C31F34cF38d1DFC1D9A8A59482028395809",
                "f22d4fc42da79aa5ba839998a0a9f2c2c45f5e55ee7f1504e464d2c71ca199e1",
            ),
        ]
        self.job = Job(self.credentials,
                       manifest,
                       multi_credentials=multi_credentials)
        self.assertTrue(self.job.launch(self.rep_oracle_pub_key))
        self.assertTrue(self.job.setup())

    def test_job_add_trusted_handlers(self):
        # Make sure we se set our gas payer as a trusted handler by default.

        self.assertTrue(self.job.launch(self.rep_oracle_pub_key))
        self.assertTrue(
            is_trusted_handler(self.job.job_contract, self.job.gas_payer,
                               self.job.gas_payer))
        trusted_handlers = [
            "0x61F9F0B31eacB420553da8BCC59DC617279731Ac",
            "0xD979105297fB0eee83F7433fC09279cb5B94fFC6",
        ]
        self.assertTrue(self.job.add_trusted_handlers(trusted_handlers))
        self.assertTrue(
            is_trusted_handler(
                self.job.job_contract,
                "0x61F9F0B31eacB420553da8BCC59DC617279731Ac",
                self.job.gas_payer,
            ))
        self.assertTrue(
            is_trusted_handler(
                self.job.job_contract,
                "0xD979105297fB0eee83F7433fC09279cb5B94fFC6",
                self.job.gas_payer,
            ))

    def test_job_bulk_payout(self):
        self.assertTrue(self.job.launch(self.rep_oracle_pub_key))
        self.assertTrue(self.job.setup())
        payouts = [
            ("0x6b7E3C31F34cF38d1DFC1D9A8A59482028395809", Decimal("20.0")),
            ("0x852023fbb19050B8291a335E5A83Ac9701E7B4E6", Decimal("50.0")),
        ]
        self.assertTrue(
            self.job.bulk_payout(payouts, {}, self.rep_oracle_pub_key))

        # The escrow contract is still in Partial state as there's still balance left.

        self.assertEqual(self.job.balance(), 30000000000000000000)
        self.assertEqual(self.job.status(), Status(3))

        # Trying to pay more than the contract balance results in failure.

        payouts = [("0x9d689b8f50Fd2CAec716Cc5220bEd66E03F07B5f",
                    Decimal("40.0"))]
        self.assertFalse(
            self.job.bulk_payout(payouts, {}, self.rep_oracle_pub_key))

        # Paying the remaining amount empties the escrow and updates the status correctly.

        payouts = [("0x9d689b8f50Fd2CAec716Cc5220bEd66E03F07B5f",
                    Decimal("30.0"))]
        self.assertTrue(
            self.job.bulk_payout(payouts, {}, self.rep_oracle_pub_key))
        self.assertEqual(self.job.balance(), 0)
        self.assertEqual(self.job.status(), Status(4))

        multi_credentials = [
            (
                "0x61F9F0B31eacB420553da8BCC59DC617279731Ac",
                "486a0621e595dd7fcbe5608cbbeec8f5a8b5cabe7637f11eccfc7acd408c3a0e",
            ),
            (
                "0x6b7E3C31F34cF38d1DFC1D9A8A59482028395809",
                "f22d4fc42da79aa5ba839998a0a9f2c2c45f5e55ee7f1504e464d2c71ca199e1",
            ),
        ]
        self.job = Job(self.credentials,
                       manifest,
                       multi_credentials=multi_credentials)
        self.assertTrue(self.job.launch(self.rep_oracle_pub_key))
        self.assertTrue(self.job.setup())
        payouts = [
            ("0x6b7E3C31F34cF38d1DFC1D9A8A59482028395809", Decimal("20.0")),
            ("0x852023fbb19050B8291a335E5A83Ac9701E7B4E6", Decimal("50.0")),
        ]
        self.assertTrue(
            self.job.bulk_payout(payouts, {}, self.rep_oracle_pub_key))

    def test_job_bulk_payout_with_encryption_option(self):
        """Tests whether final results must be persisted in storage encrypted
        or plain.
        """
        job = Job(self.credentials, manifest)
        self.assertEqual(job.launch(self.rep_oracle_pub_key), True)
        self.assertEqual(job.setup(), True)

        payouts = [("0x852023fbb19050B8291a335E5A83Ac9701E7B4E6",
                    Decimal("100.0"))]

        final_results = {'results': 0}

        mock_upload = MagicMock(return_value=('hash', 'url'))

        # Testing option as: do not encrypt final results: encrypt_final_results=False
        with patch('hmt_escrow.job.upload', mock_upload):
            # Bulk payout with final results as plain (not encrypted)
            job.bulk_payout(payouts=payouts,
                            results=final_results,
                            pub_key=self.rep_oracle_pub_key,
                            encrypt_final_results=False)

            mock_upload.assert_called_once_with(
                msg=final_results,
                public_key=self.rep_oracle_pub_key,
                encrypt_data=False)
            mock_upload.reset_mock()

        # Testing option as: encrypt final results: encrypt_final_results=True
        with patch("hmt_escrow.job.upload", mock_upload):
            # Bulk payout with final results as plain (not encrypted)
            job.bulk_payout(payouts=payouts,
                            results={"results": 0},
                            pub_key=self.rep_oracle_pub_key,
                            encrypt_final_results=True)

            mock_upload.assert_called_once_with(
                msg=final_results,
                public_key=self.rep_oracle_pub_key,
                encrypt_data=True)

    def test_job_abort(self):
        """
        The escrow contract is in Paid state after the full bulk payout, and
            it can't be aborted.
        """

        self.assertTrue(self.job.launch(self.rep_oracle_pub_key))
        self.assertTrue(self.job.setup())
        payouts = [("0x852023fbb19050B8291a335E5A83Ac9701E7B4E6",
                    Decimal("100.0"))]
        self.assertTrue(
            self.job.bulk_payout(payouts, {"results": 0},
                                 self.rep_oracle_pub_key))
        self.assertFalse(self.job.abort())
        self.assertEqual(self.job.status(), Status(4))

        # Trusted handler should be able to abort an existing contract

        self.job = Job(self.credentials, manifest)
        self.assertTrue(self.job.launch(self.rep_oracle_pub_key))
        self.assertTrue(self.job.setup())
        trusted_handler = "0x6b7E3C31F34cF38d1DFC1D9A8A59482028395809"
        self.assertTrue(self.job.add_trusted_handlers([trusted_handler]))

        handler_credentials = {
            "gas_payer":
            "0x6b7E3C31F34cF38d1DFC1D9A8A59482028395809",
            "gas_payer_priv":
            "f22d4fc42da79aa5ba839998a0a9f2c2c45f5e55ee7f1504e464d2c71ca199e1",
            "rep_oracle_priv_key":
            b"28e516f1e2f99e96a48a23cea1f94ee5f073403a1c68e818263f0eb898f1c8e5",
        }
        access_job = Job(
            credentials=handler_credentials,
            factory_addr=self.job.factory_contract.address,
            escrow_addr=self.job.job_contract.address,
        )
        self.assertTrue(access_job.abort())

    def test_job_cancel(self):
        self.assertTrue(self.job.launch(self.rep_oracle_pub_key))
        self.assertTrue(self.job.setup())
        payouts = [("0x6b7E3C31F34cF38d1DFC1D9A8A59482028395809",
                    Decimal("20.0"))]
        self.assertTrue(
            self.job.bulk_payout(payouts, {}, self.rep_oracle_pub_key))
        self.assertEqual(self.job.status(), Status(3))

        # The escrow contract is in Paid state after the second payout and it can't be cancelled.

        payouts = [("0x852023fbb19050B8291a335E5A83Ac9701E7B4E6",
                    Decimal("80.0"))]
        self.assertTrue(
            self.job.bulk_payout(payouts, {"results": 0},
                                 self.rep_oracle_pub_key))
        self.assertFalse(self.job.cancel())
        self.assertEqual(self.job.status(), Status(4))

    def test_job_status(self):
        self.assertTrue(self.job.launch(self.rep_oracle_pub_key))
        self.assertEqual(self.job.status(), Status(1))

    def test_job_balance(self):
        self.assertTrue(self.job.launch(self.rep_oracle_pub_key))
        self.assertTrue(self.job.setup())
        self.assertEqual(self.job.balance(), 100000000000000000000)

    def test_launch_failure(self):
        """ Test _launch raises error on failure to create contract """

        handler_mock = MagicMock()
        handler_mock.side_effect = Exception("")

        e = None
        with self.assertRaises(Exception) as e:
            with patch("hmt_escrow.eth_bridge.handle_transaction",
                       handler_mock):
                self.job.launch(b"")

        self.assertIsNotNone(e)
        self.assertEqual(str(e.exception), "Unable to create escrow")

    def test__raffle_txn_retry(self):
        """ Test general retry logic """

        retries = 4
        delay = 0.01
        backoff = 2
        self.job.retry = Retry(retries=retries, delay=delay, backoff=backoff)

        txn_mock = MagicMock()
        handler_mock = MagicMock(side_effect=Exception)
        sleep_mock = MagicMock()

        with patch("hmt_escrow.eth_bridge.handle_transaction",
                   handler_mock), patch("hmt_escrow.eth_bridge.sleep",
                                        sleep_mock):
            success = self.job._raffle_txn(
                multi_creds=[("1", "11")],
                txn_func=txn_mock,
                txn_args=[],
                txn_event="Transfer",
            )

            self.assertFalse(success)

            self.assertEqual(
                handler_mock.call_args_list,
                [
                    call(txn_mock,
                         gas_payer="1",
                         gas_payer_priv="11",
                         gas=6700000) for i in range(5)
                ],
            )
            self.assertEqual(
                sleep_mock.call_args_list,
                [call(delay * backoff**i) for i in range(retries)],
            )

            sleep_mock.reset_mock()
            handler_mock.reset_mock()
            handler_mock.side_effect = Exception

            # no retries
            self.job.retry = Retry()

            success = self.job._raffle_txn(
                multi_creds=[("1", "11")],
                txn_func=txn_mock,
                txn_args=[],
                txn_event="Transfer",
            )

            self.assertFalse(success)
            self.assertEqual(
                handler_mock.call_args_list,
                [
                    call(txn_mock,
                         gas_payer="1",
                         gas_payer_priv="11",
                         gas=6700000)
                ],
            )
            self.assertEqual(sleep_mock.call_args_list, [])

    def test_get_hmt_balance(self):
        """ Test wallet HMT balance is OK """
        amount = utils.get_hmt_balance(
            "0x1413862C2B7054CDbfdc181B83962CB0FC11fD92",
            "0x56B532F1D090E4edb1c92F30d3087771AE6B6992",
            get_w3(),
        )
        print(amount)
        self.assertGreater(amount, 10000)