Skip to content

Commit

Permalink
Merge pull request humanprotocol#2 from hCaptcha/master
Browse files Browse the repository at this point in the history
Update fork
  • Loading branch information
uivlis authored Jul 10, 2020
2 parents 63373ac + c8622d3 commit d859754
Show file tree
Hide file tree
Showing 4 changed files with 369 additions and 39 deletions.
83 changes: 55 additions & 28 deletions hmt_escrow/eth_bridge.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
import os
import time
import unittest

from solcx import compile_files
from web3 import Web3, HTTPProvider, EthereumTesterProvider
Expand Down Expand Up @@ -63,29 +64,6 @@ def handle_transaction(txn_func, *args, **kwargs) -> AttributeDict:
signing, building, sending the transaction and returning a transaction
receipt.
>>> credentials = {
... "gas_payer": "0x1413862C2B7054CDbfdc181B83962CB0FC11fD92",
... "gas_payer_priv": "28e516f1e2f99e96a48a23cea1f94ee5f073403a1c68e818263f0eb898f1c8e5"
... }
>>> rep_oracle_pub_key = b"2dbc2c2c86052702e7c219339514b2e8bd4687ba1236c478ad41b43330b08488c12c8c1797aa181f3a4596a1bd8a0c18344ea44d6655f61fa73e56e743f79e0d"
>>> job = Job(credentials=credentials, escrow_manifest=manifest)
>>> job.launch(rep_oracle_pub_key)
True
>>> gas = 4712388
>>> hmt_amount = int(job.amount * 10**18)
>>> hmtoken_contract = get_hmtoken()
>>> txn_func = hmtoken_contract.functions.transfer
>>> func_args = [job.job_contract.address, hmt_amount]
>>> txn_info = {
... "gas_payer": job.gas_payer,
... "gas_payer_priv": job.gas_payer_priv,
... "gas": gas
... }
>>> txn_receipt = handle_transaction(txn_func, *func_args, **txn_info)
>>> type(txn_receipt)
<class 'web3.datastructures.AttributeDict'>
Args:
txn_func: the transaction function to be handled.
Expand Down Expand Up @@ -340,9 +318,58 @@ def set_pub_key_at_addr(pub_key: str) -> Dict[str, Any]:
return handle_transaction(txn_func, *func_args, **txn_info)


if __name__ == "__main__":
import doctest
from test_manifest import manifest
from job import Job
class EthBridgeTestCase(unittest.TestCase):
def setUp(self):
from job import Job

self.credentials = {
"gas_payer": "0x1413862C2B7054CDbfdc181B83962CB0FC11fD92",
"gas_payer_priv": "28e516f1e2f99e96a48a23cea1f94ee5f073403a1c68e818263f0eb898f1c8e5",
}
self.rep_oracle_pub_key = b"2dbc2c2c86052702e7c219339514b2e8bd4687ba1236c478ad41b43330b08488c12c8c1797aa181f3a4596a1bd8a0c18344ea44d6655f61fa73e56e743f79e0d"
self.job = Job(credentials=self.credentials, escrow_manifest=manifest)

def test_handle_transaction(self):
from web3.datastructures import AttributeDict as Web3AttributeDict

self.assertTrue(self.job.launch(self.rep_oracle_pub_key))
gas = 4712388
hmt_amount = int(self.job.amount * 10 ** 18)
hmtoken_contract = get_hmtoken()
txn_func = hmtoken_contract.functions.transfer
func_args = [self.job.job_contract.address, hmt_amount]
txn_info = {
"gas_payer": self.job.gas_payer,
"gas_payer_priv": self.job.gas_payer_priv,
"gas": gas,
}
txn_receipt = handle_transaction(txn_func, *func_args, **txn_info)
self.assertIs(type(txn_receipt), Web3AttributeDict)

def test_get_escrow(self):
self.job.launch(self.rep_oracle_pub_key)
self.assertIsNotNone(get_escrow(self.job.job_contract.address))

def test_get_factory(self):
self.assertIsNotNone(get_factory(self.job.factory_contract.address))

def test_get_pub_key_from_address(self):
with self.assertRaises(ValueError):
get_pub_key_from_addr("badaddress")
os.environ["GAS_PAYER"] = self.credentials["gas_payer"]
os.environ["GAS_PAYER_PRIV"] = self.credentials["gas_payer_priv"]
set_pub_key_at_addr(self.rep_oracle_pub_key)
self.assertEqual(
get_pub_key_from_addr(os.environ["GAS_PAYER"]), self.rep_oracle_pub_key
)

doctest.testmod(raise_on_error=True)
def test_set_pub_key_at_address(self):
os.environ["GAS_PAYER"] = self.credentials["gas_payer"]
os.environ["GAS_PAYER_PRIV"] = self.credentials["gas_payer_priv"]
self.assertIsNotNone(
set_pub_key_at_addr(self.rep_oracle_pub_key).transactionHash
)


if __name__ == "__main__":
unittest.main(exit=False)
261 changes: 256 additions & 5 deletions hmt_escrow/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os
import sys
import logging
import unittest

from decimal import Decimal
from enum import Enum
Expand Down Expand Up @@ -1249,7 +1250,6 @@ def _validate_credentials(
bool: returns True if the calculated and the given address match.
"""
addr_valid = False
gas_payer_addr = credentials["gas_payer"]
gas_payer_priv = credentials["gas_payer_priv"]

Expand Down Expand Up @@ -1502,8 +1502,259 @@ def _raffle_txn(
return txn_succeeded


if __name__ == "__main__":
import doctest
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_status(self):
self.assertTrue(self.job.launch(self.rep_oracle_pub_key))
self.assertEqual(status(self.job.job_contract, self.job.gas_payer), Status(1))

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.

# IMPORTANT, don't modify this so CI catches the doctest errors.
doctest.testmod()
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_abort(self):

# The escrow contract is in Paid state after the a 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)


if __name__ == "__main__":
unittest.main(exit=False)
Loading

0 comments on commit d859754

Please sign in to comment.