mirror of https://github.com/nucypher/nucypher.git
Introduce dynamic multi-chain support; enforce condition chain ID as an int.
parent
89743cde87
commit
d2dcdb9230
|
@ -16,7 +16,7 @@
|
|||
"""
|
||||
|
||||
import re
|
||||
from typing import Any, List, Optional, Tuple, Union, Dict
|
||||
from typing import Any, List, Optional, Tuple, Dict
|
||||
|
||||
from eth_typing import ChecksumAddress
|
||||
from eth_utils import to_checksum_address
|
||||
|
@ -32,26 +32,20 @@ from nucypher.policy.conditions.base import ReencryptionCondition
|
|||
from nucypher.policy.conditions.context import get_context_value, is_context_variable
|
||||
from nucypher.policy.conditions.lingo import ReturnValueTest
|
||||
|
||||
# TODO: Move this method to a util function
|
||||
__CHAINS = {
|
||||
60: 'ethereum', # TODO: make a few edits for now
|
||||
131277322940537: 'testerchain', # TODO: this one can be moved to a pytest fixture / setup logic
|
||||
**PUBLIC_CHAINS,
|
||||
|
||||
# Permitted blockchains for condition evaluation
|
||||
_CONDITION_CHAINS = {
|
||||
1: "Ethereum", # TODO: 60 ?
|
||||
5: "Goerli",
|
||||
# 6: "Kotti",
|
||||
# 42: "Kovan",
|
||||
# 77: "Sokol",
|
||||
# 100: "xDai",
|
||||
137: "Polygon/Mainnet",
|
||||
80001: "Polygon/Mumbai"
|
||||
}
|
||||
|
||||
|
||||
def _resolve_chain(chain: Union[str, int]) -> Tuple[str, int]:
|
||||
"""Returns the name *and* chain ID given only a name *or* chain ID"""
|
||||
for pair in __CHAINS.items():
|
||||
if chain in pair:
|
||||
chain_id, chain_name = pair
|
||||
return chain_name, chain_id
|
||||
else:
|
||||
raise ReencryptionCondition.InvalidCondition(
|
||||
f"{chain} is not a known blockchain."
|
||||
)
|
||||
|
||||
|
||||
def _resolve_abi(standard_contract_type: str, method: str, function_abi: List) -> List:
|
||||
"""Resolves the contract an/or function ABI from a standard contract name"""
|
||||
if not (function_abi or standard_contract_type):
|
||||
|
@ -84,7 +78,7 @@ def camel_case_to_snake(data: str) -> str:
|
|||
|
||||
|
||||
def _resolve_any_context_variables(
|
||||
parameters: List[Any], return_value_test: ReturnValueTest, **context
|
||||
parameters: List[Any], return_value_test: ReturnValueTest, **context
|
||||
):
|
||||
processed_parameters = []
|
||||
for p in parameters:
|
||||
|
@ -102,6 +96,13 @@ def _resolve_any_context_variables(
|
|||
return processed_parameters, processed_return_value_test
|
||||
|
||||
|
||||
def _validate_chain(chain: int):
|
||||
if not isinstance(chain, int):
|
||||
raise ValueError(f'"chain" must be a the integer of a chain ID (got "{chain}").')
|
||||
if chain not in _CONDITION_CHAINS:
|
||||
raise RPCCondition.InvalidCondition(f'chain ID {chain} is not a permitted blockchain for condition evaluation.')
|
||||
|
||||
|
||||
class RPCCondition(ReencryptionCondition):
|
||||
ALLOWED_METHODS = (
|
||||
|
||||
|
@ -117,42 +118,38 @@ class RPCCondition(ReencryptionCondition):
|
|||
|
||||
class Schema(CamelCaseSchema):
|
||||
name = fields.Str()
|
||||
chain = fields.Str()
|
||||
method = fields.Str()
|
||||
chain = fields.Int(required=True)
|
||||
method = fields.Str(required=True)
|
||||
parameters = fields.List(fields.Field, attribute='parameters', required=False)
|
||||
return_value_test = fields.Nested(ReturnValueTest.ReturnValueTestSchema())
|
||||
return_value_test = fields.Nested(ReturnValueTest.ReturnValueTestSchema(), required=True)
|
||||
|
||||
@post_load
|
||||
def make(self, data, **kwargs):
|
||||
return RPCCondition(**data)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
r = f'{self.__class__.__name__}(function={self.method}, chain={self.chain_name})'
|
||||
r = f'{self.__class__.__name__}(function={self.method}, chain={self.chain})'
|
||||
return r
|
||||
|
||||
def __init__(self,
|
||||
chain: str,
|
||||
chain: int,
|
||||
method: str,
|
||||
return_value_test: ReturnValueTest,
|
||||
parameters: Optional[List[Any]] = None
|
||||
):
|
||||
|
||||
# Validate input
|
||||
# _validate_parameters(parameters=parameters)
|
||||
# TODO: Additional validation (function is valid for ABI, RVT validity, standard contract name validity, etc.)
|
||||
_validate_chain(chain=chain)
|
||||
|
||||
# internal
|
||||
self.chain_name, self.chain_id = _resolve_chain(chain=chain)
|
||||
self.chain = chain
|
||||
self.method = self.validate_method(method=method)
|
||||
|
||||
# test
|
||||
self.parameters = parameters # input
|
||||
self.return_value_test = return_value_test # output
|
||||
|
||||
@property
|
||||
def chain(self) -> str:
|
||||
return self.chain_name
|
||||
|
||||
def validate_method(self, method):
|
||||
if method not in self.ALLOWED_METHODS:
|
||||
raise ReencryptionCondition.InvalidCondition(
|
||||
|
@ -167,11 +164,11 @@ class RPCCondition(ReencryptionCondition):
|
|||
def _configure_provider(self, providers: Dict[int, BaseProvider]):
|
||||
"""Binds the condition's contract function to a blockchian provider for evaluation"""
|
||||
try:
|
||||
provider = providers[self.chain_id]
|
||||
provider = providers[self.chain]
|
||||
except KeyError:
|
||||
# TODO Use a custom exception class, and catch bubble it up to include info about the node
|
||||
# QUESTION Are nodes required to provide connections to all providers?
|
||||
raise Exception(f'This node does not have a connection to chain {self.chain_id}')
|
||||
raise Exception(f'This node does not have a connection to chain {self.chain}')
|
||||
|
||||
# Instantiate a local web3 instance
|
||||
self.w3 = Web3(provider)
|
||||
|
@ -179,9 +176,9 @@ class RPCCondition(ReencryptionCondition):
|
|||
# This next block validates that the actual web3 provider is *actually*
|
||||
# connected to the condition's chain ID by reading its RPC endpoint.
|
||||
provider_chain = self.w3.eth.chain_id
|
||||
if provider_chain != self.chain_id:
|
||||
if provider_chain != self.chain:
|
||||
raise ReencryptionCondition.InvalidCondition(
|
||||
f"This condition can only be evaluated on {self.chain_id} but the provider's "
|
||||
f"This condition can only be evaluated on {self.chain} but the provider's "
|
||||
f"connection is to chain {provider_chain}"
|
||||
)
|
||||
return provider
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
|
@ -32,18 +33,26 @@ from nucypher.blockchain.eth.sol.compile.compile import multiversion_compile
|
|||
from nucypher.blockchain.eth.sol.compile.types import SourceBundle
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
from nucypher.policy.conditions.context import USER_ADDRESS_CONTEXT
|
||||
from nucypher.policy.conditions.evm import ContractCondition, RPCCondition
|
||||
from nucypher.policy.conditions.evm import ContractCondition, RPCCondition, _CONDITION_CHAINS
|
||||
from nucypher.policy.conditions.lingo import AND, OR, ConditionLingo, ReturnValueTest
|
||||
from nucypher.policy.conditions.time import TimeCondition
|
||||
from tests.constants import TESTERCHAIN_CHAIN_ID
|
||||
|
||||
VECTORS_FILE = Path(tests.__file__).parent / "data" / "test_conditions.json"
|
||||
|
||||
|
||||
with open(VECTORS_FILE, 'r') as file:
|
||||
VECTORS = json.loads(file.read())
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_condition_blockchains(mocker):
|
||||
mocker.patch.dict(_CONDITION_CHAINS, {131277322940537: 'testerchain'})
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def ERC1155_balance_condition_data():
|
||||
VECTORS['ERC1155_balance']['chain'] = TESTERCHAIN_CHAIN_ID
|
||||
data = json.dumps(VECTORS['ERC1155_balance'])
|
||||
return data
|
||||
|
||||
|
@ -57,6 +66,7 @@ def ERC1155_balance_condition(ERC1155_balance_condition_data):
|
|||
|
||||
@pytest.fixture()
|
||||
def ERC20_balance_condition_data():
|
||||
VECTORS['ERC20_balance']['chain'] = TESTERCHAIN_CHAIN_ID
|
||||
data = json.dumps(VECTORS['ERC20_balance'])
|
||||
return data
|
||||
|
||||
|
@ -72,7 +82,7 @@ def ERC20_balance_condition(ERC20_balance_condition_data):
|
|||
def rpc_condition():
|
||||
condition = RPCCondition(
|
||||
method="eth_getBalance",
|
||||
chain="testerchain",
|
||||
chain=TESTERCHAIN_CHAIN_ID,
|
||||
return_value_test=ReturnValueTest("==", Web3.to_wei(1_000_000, "ether")),
|
||||
parameters=[USER_ADDRESS_CONTEXT],
|
||||
)
|
||||
|
@ -86,7 +96,7 @@ def erc20_evm_condition(test_registry, agency):
|
|||
contract_address=token.contract.address,
|
||||
method="balanceOf",
|
||||
standard_contract_type="ERC20",
|
||||
chain="testerchain",
|
||||
chain=TESTERCHAIN_CHAIN_ID,
|
||||
return_value_test=ReturnValueTest("==", 0),
|
||||
parameters=[USER_ADDRESS_CONTEXT],
|
||||
)
|
||||
|
@ -94,13 +104,13 @@ def erc20_evm_condition(test_registry, agency):
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def custom_context_variable_erc20_condition(test_registry, agency):
|
||||
def custom_context_variable_erc20_condition(test_registry, agency, testerchain):
|
||||
token = ContractAgency.get_agent(NucypherTokenAgent, registry=test_registry)
|
||||
condition = ContractCondition(
|
||||
contract_address=token.contract.address,
|
||||
method="balanceOf",
|
||||
standard_contract_type="ERC20",
|
||||
chain="testerchain",
|
||||
chain=TESTERCHAIN_CHAIN_ID,
|
||||
return_value_test=ReturnValueTest("==", 0),
|
||||
parameters=[":addressToUse"],
|
||||
)
|
||||
|
@ -136,7 +146,7 @@ def erc721_evm_condition_owner(erc721_contract):
|
|||
contract_address=erc721_contract.address,
|
||||
method="ownerOf",
|
||||
standard_contract_type="ERC721",
|
||||
chain="testerchain",
|
||||
chain=TESTERCHAIN_CHAIN_ID,
|
||||
return_value_test=ReturnValueTest("==", ":userAddress"),
|
||||
parameters=[
|
||||
":tokenId",
|
||||
|
@ -151,7 +161,7 @@ def erc721_evm_condition_balanceof(erc721_contract):
|
|||
contract_address=erc721_contract.address,
|
||||
method="balanceOf",
|
||||
standard_contract_type="ERC721",
|
||||
chain="testerchain",
|
||||
chain=TESTERCHAIN_CHAIN_ID,
|
||||
return_value_test=ReturnValueTest(">", 0),
|
||||
parameters=[
|
||||
":userAddress",
|
||||
|
@ -168,7 +178,7 @@ def subscription_manager_is_active_policy_condition(test_registry, agency):
|
|||
contract_address=subscription_manager.contract.address,
|
||||
function_abi=subscription_manager.contract.abi,
|
||||
method="isPolicyActive",
|
||||
chain="testerchain",
|
||||
chain=TESTERCHAIN_CHAIN_ID,
|
||||
return_value_test=ReturnValueTest("==", True),
|
||||
parameters=[":hrac"],
|
||||
)
|
||||
|
@ -186,7 +196,7 @@ def subscription_manager_get_policy_zeroized_policy_struct_condition(
|
|||
contract_address=subscription_manager.contract.address,
|
||||
function_abi=subscription_manager.contract.abi,
|
||||
method="getPolicy",
|
||||
chain="testerchain",
|
||||
chain=TESTERCHAIN_CHAIN_ID,
|
||||
return_value_test=ReturnValueTest("==", ":expectedPolicyStruct"),
|
||||
parameters=[":hrac"],
|
||||
)
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
You should have received a copy of the GNU Affero General Public License
|
||||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
|
||||
import copy
|
||||
import json
|
||||
import os
|
||||
|
@ -31,8 +33,16 @@ from nucypher.policy.conditions.context import (
|
|||
)
|
||||
from nucypher.policy.conditions.evm import RPCCondition, get_context_value
|
||||
from nucypher.policy.conditions.lingo import ConditionLingo, ReturnValueTest
|
||||
from tests.constants import TESTERCHAIN_CHAIN_ID
|
||||
from tests.integration.characters.test_bob_handles_frags import _make_message_kits
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def condition_providers(testerchain):
|
||||
providers = {testerchain.client.chain_id: testerchain.provider}
|
||||
return providers
|
||||
|
||||
|
||||
VALID_USER_ADDRESS_CONTEXT = {
|
||||
USER_ADDRESS_CONTEXT: {
|
||||
"signature": "0x488a7acefdc6d098eedf73cdfd379777c0f4a4023a660d350d3bf309a51dd4251abaad9cdd11b71c400cfb4625c14ca142f72b39165bd980c8da1ea32892ff071c",
|
||||
|
@ -77,11 +87,11 @@ def _dont_validate_user_address(context_variable: str, **context):
|
|||
|
||||
|
||||
def test_required_context_variable(
|
||||
testerchain, custom_context_variable_erc20_condition
|
||||
testerchain, custom_context_variable_erc20_condition, condition_providers
|
||||
):
|
||||
with pytest.raises(RequiredContextVariable):
|
||||
custom_context_variable_erc20_condition.verify(
|
||||
provider=testerchain.provider
|
||||
providers=condition_providers
|
||||
) # no context
|
||||
|
||||
|
||||
|
@ -142,10 +152,10 @@ def test_user_address_context_variable_verification(testerchain):
|
|||
"nucypher.policy.conditions.evm.get_context_value",
|
||||
side_effect=_dont_validate_user_address,
|
||||
)
|
||||
def test_rpc_condition_evaluation(get_context_value_mock, testerchain, rpc_condition):
|
||||
def test_rpc_condition_evaluation(get_context_value_mock, testerchain, rpc_condition, condition_providers):
|
||||
context = {USER_ADDRESS_CONTEXT: {"address": testerchain.unassigned_accounts[0]}}
|
||||
condition_result, call_result = rpc_condition.verify(
|
||||
provider=testerchain.provider, **context
|
||||
providers=condition_providers, **context
|
||||
)
|
||||
assert condition_result is True
|
||||
assert call_result == Web3.to_wei(
|
||||
|
@ -158,7 +168,7 @@ def test_rpc_condition_evaluation(get_context_value_mock, testerchain, rpc_condi
|
|||
side_effect=_dont_validate_user_address,
|
||||
)
|
||||
def test_rpc_condition_evaluation_with_context_var_in_return_value_test(
|
||||
get_context_value_mock, testerchain
|
||||
get_context_value_mock, testerchain, condition_providers
|
||||
):
|
||||
account, *other_accounts = testerchain.client.accounts
|
||||
balance = testerchain.client.get_balance(account)
|
||||
|
@ -166,7 +176,7 @@ def test_rpc_condition_evaluation_with_context_var_in_return_value_test(
|
|||
# we have balance stored, use for rpc condition with context variable
|
||||
rpc_condition = RPCCondition(
|
||||
method="eth_getBalance",
|
||||
chain="testerchain",
|
||||
chain=TESTERCHAIN_CHAIN_ID,
|
||||
return_value_test=ReturnValueTest(
|
||||
"==", ":balanceContextVar"
|
||||
), # user-defined context var
|
||||
|
@ -177,7 +187,7 @@ def test_rpc_condition_evaluation_with_context_var_in_return_value_test(
|
|||
":balanceContextVar": balance,
|
||||
}
|
||||
condition_result, call_result = rpc_condition.verify(
|
||||
provider=testerchain.provider, **context
|
||||
providers=condition_providers, **context
|
||||
)
|
||||
assert condition_result is True
|
||||
assert call_result == balance
|
||||
|
@ -186,7 +196,7 @@ def test_rpc_condition_evaluation_with_context_var_in_return_value_test(
|
|||
invalid_balance = balance + 1
|
||||
context[":balanceContextVar"] = invalid_balance
|
||||
condition_result, call_result = rpc_condition.verify(
|
||||
provider=testerchain.provider, **context
|
||||
providers={testerchain.client.chain_id: testerchain.provider}, **context
|
||||
)
|
||||
assert condition_result is False
|
||||
assert call_result != invalid_balance
|
||||
|
@ -197,33 +207,33 @@ def test_rpc_condition_evaluation_with_context_var_in_return_value_test(
|
|||
side_effect=_dont_validate_user_address,
|
||||
)
|
||||
def test_erc20_evm_condition_evaluation(
|
||||
get_context_value_mock, testerchain, erc20_evm_condition
|
||||
get_context_value_mock, testerchain, erc20_evm_condition, condition_providers
|
||||
):
|
||||
context = {USER_ADDRESS_CONTEXT: {"address": testerchain.unassigned_accounts[0]}}
|
||||
condition_result, call_result = erc20_evm_condition.verify(
|
||||
provider=testerchain.provider, **context
|
||||
providers=condition_providers, **context
|
||||
)
|
||||
assert condition_result is True
|
||||
|
||||
context[USER_ADDRESS_CONTEXT]["address"] = testerchain.etherbase_account
|
||||
condition_result, call_result = erc20_evm_condition.verify(
|
||||
provider=testerchain.provider, **context
|
||||
providers=condition_providers, **context
|
||||
)
|
||||
assert condition_result is False
|
||||
|
||||
|
||||
def test_erc20_evm_condition_evaluation_with_custom_context_variable(
|
||||
testerchain, custom_context_variable_erc20_condition
|
||||
testerchain, custom_context_variable_erc20_condition, condition_providers
|
||||
):
|
||||
context = {":addressToUse": testerchain.unassigned_accounts[0]}
|
||||
condition_result, call_result = custom_context_variable_erc20_condition.verify(
|
||||
provider=testerchain.provider, **context
|
||||
providers=condition_providers, **context
|
||||
)
|
||||
assert condition_result is True
|
||||
|
||||
context[":addressToUse"] = testerchain.etherbase_account
|
||||
condition_result, call_result = custom_context_variable_erc20_condition.verify(
|
||||
provider=testerchain.provider, **context
|
||||
providers=condition_providers, **context
|
||||
)
|
||||
assert condition_result is False
|
||||
|
||||
|
@ -233,7 +243,7 @@ def test_erc20_evm_condition_evaluation_with_custom_context_variable(
|
|||
side_effect=_dont_validate_user_address,
|
||||
)
|
||||
def test_erc721_evm_condition_owner_evaluation(
|
||||
get_context_value_mock, testerchain, test_registry, erc721_evm_condition_owner
|
||||
get_context_value_mock, testerchain, test_registry, erc721_evm_condition_owner, condition_providers
|
||||
):
|
||||
account, *other_accounts = testerchain.client.accounts
|
||||
# valid owner of nft
|
||||
|
@ -242,7 +252,7 @@ def test_erc721_evm_condition_owner_evaluation(
|
|||
":tokenId": 1, # valid token id
|
||||
}
|
||||
condition_result, call_result = erc721_evm_condition_owner.verify(
|
||||
provider=testerchain.provider, **context
|
||||
providers=condition_providers, **context
|
||||
)
|
||||
assert condition_result is True
|
||||
assert call_result == account
|
||||
|
@ -251,7 +261,7 @@ def test_erc721_evm_condition_owner_evaluation(
|
|||
with pytest.raises(RPCCondition.RPCExecutionFailed):
|
||||
context[":tokenId"] = 255
|
||||
_, _ = erc721_evm_condition_owner.verify(
|
||||
provider=testerchain.provider, **context
|
||||
providers=condition_providers, **context
|
||||
)
|
||||
|
||||
# invalid owner of nft
|
||||
|
@ -261,7 +271,7 @@ def test_erc721_evm_condition_owner_evaluation(
|
|||
":tokenId": 1, # valid token id
|
||||
}
|
||||
condition_result, call_result = erc721_evm_condition_owner.verify(
|
||||
provider=testerchain.provider, **context
|
||||
providers=condition_providers, **context
|
||||
)
|
||||
assert condition_result is False
|
||||
assert call_result != other_account
|
||||
|
@ -272,12 +282,12 @@ def test_erc721_evm_condition_owner_evaluation(
|
|||
side_effect=_dont_validate_user_address,
|
||||
)
|
||||
def test_erc721_evm_condition_balanceof_evaluation(
|
||||
get_context_value_mock, testerchain, test_registry, erc721_evm_condition_balanceof
|
||||
get_context_value_mock, testerchain, test_registry, erc721_evm_condition_balanceof, condition_providers
|
||||
):
|
||||
account, *other_accounts = testerchain.client.accounts
|
||||
context = {USER_ADDRESS_CONTEXT: {"address": account}} # owner of NFT
|
||||
condition_result, call_result = erc721_evm_condition_balanceof.verify(
|
||||
provider=testerchain.provider, **context
|
||||
providers=condition_providers, **context
|
||||
)
|
||||
assert condition_result is True
|
||||
|
||||
|
@ -285,7 +295,7 @@ def test_erc721_evm_condition_balanceof_evaluation(
|
|||
other_account = other_accounts[0] # not an owner of NFT
|
||||
context = {USER_ADDRESS_CONTEXT: {"address": other_account}}
|
||||
condition_result, call_result = erc721_evm_condition_balanceof.verify(
|
||||
provider=testerchain.provider, **context
|
||||
providers=condition_providers, **context
|
||||
)
|
||||
assert not condition_result
|
||||
|
||||
|
@ -294,12 +304,13 @@ def test_subscription_manager_is_active_policy_condition_evaluation(
|
|||
testerchain,
|
||||
enacted_blockchain_policy,
|
||||
subscription_manager_is_active_policy_condition,
|
||||
condition_providers
|
||||
):
|
||||
context = {
|
||||
":hrac": bytes(enacted_blockchain_policy.hrac)
|
||||
} # user-defined context var
|
||||
condition_result, call_result = subscription_manager_is_active_policy_condition.verify(
|
||||
provider=testerchain.provider, **context
|
||||
providers=condition_providers, **context
|
||||
)
|
||||
assert call_result
|
||||
assert condition_result is True
|
||||
|
@ -307,7 +318,7 @@ def test_subscription_manager_is_active_policy_condition_evaluation(
|
|||
# non-active policy hrac
|
||||
context[":hrac"] = os.urandom(16)
|
||||
condition_result, call_result = subscription_manager_is_active_policy_condition.verify(
|
||||
provider=testerchain.provider, **context
|
||||
providers=condition_providers, **context
|
||||
)
|
||||
assert not call_result
|
||||
assert not condition_result
|
||||
|
@ -317,6 +328,7 @@ def test_subscription_manager_get_policy_policy_struct_condition_evaluation(
|
|||
testerchain,
|
||||
enacted_blockchain_policy,
|
||||
subscription_manager_get_policy_zeroized_policy_struct_condition,
|
||||
condition_providers
|
||||
):
|
||||
|
||||
# zeroized policy struct
|
||||
|
@ -332,7 +344,7 @@ def test_subscription_manager_get_policy_policy_struct_condition_evaluation(
|
|||
":expectedPolicyStruct": zeroized_policy_struct,
|
||||
} # user-defined context vars
|
||||
condition_result, call_result = subscription_manager_get_policy_zeroized_policy_struct_condition.verify(
|
||||
provider=testerchain.provider, **context
|
||||
providers=condition_providers, **context
|
||||
)
|
||||
assert call_result != zeroized_policy_struct
|
||||
assert not condition_result # not zeroized policy
|
||||
|
@ -340,15 +352,15 @@ def test_subscription_manager_get_policy_policy_struct_condition_evaluation(
|
|||
# unknown policy hrac
|
||||
context[":hrac"] = os.urandom(16)
|
||||
condition_result, call_result = subscription_manager_get_policy_zeroized_policy_struct_condition.verify(
|
||||
provider=testerchain.provider, **context
|
||||
providers=condition_providers, **context
|
||||
)
|
||||
assert call_result == zeroized_policy_struct
|
||||
assert condition_result is True # zeroized policy was indeed returned
|
||||
|
||||
|
||||
def test_time_condition_evaluation(testerchain, timelock_condition):
|
||||
def test_time_condition_evaluation(testerchain, timelock_condition, condition_providers):
|
||||
condition_result, call_result = timelock_condition.verify(
|
||||
provider=testerchain.provider
|
||||
providers=condition_providers
|
||||
)
|
||||
assert condition_result is True
|
||||
|
||||
|
@ -376,9 +388,11 @@ def test_onchain_conditions_lingo_evaluation(
|
|||
get_context_value_mock,
|
||||
testerchain,
|
||||
lingo,
|
||||
condition_providers
|
||||
|
||||
):
|
||||
context = {USER_ADDRESS_CONTEXT: {"address": testerchain.etherbase_account}}
|
||||
result = lingo.eval(provider=testerchain.provider, **context)
|
||||
result = lingo.eval(providers=condition_providers, **context)
|
||||
assert result is True
|
||||
|
||||
|
||||
|
@ -387,7 +401,7 @@ def test_single_retrieve_with_onchain_conditions(enacted_blockchain_policy, bloc
|
|||
conditions = [
|
||||
{'returnValueTest': {'value': '0', 'comparator': '>'}, 'method': 'timelock'},
|
||||
{'operator': 'and'},
|
||||
{"chain": "testerchain",
|
||||
{"chain": TESTERCHAIN_CHAIN_ID,
|
||||
"method": "eth_getBalance",
|
||||
"parameters": [
|
||||
blockchain_bob.checksum_address,
|
||||
|
|
|
@ -143,3 +143,4 @@ CLI_TEST_ENV = {NUCYPHER_ENVVAR_KEYSTORE_PASSWORD: INSECURE_DEVELOPMENT_PASSWORD
|
|||
|
||||
CLI_ENV = {NUCYPHER_ENVVAR_KEYSTORE_PASSWORD: INSECURE_DEVELOPMENT_PASSWORD,
|
||||
NUCYPHER_ENVVAR_OPERATOR_ETH_PASSWORD: INSECURE_DEVELOPMENT_PASSWORD}
|
||||
TESTERCHAIN_CHAIN_ID = 131277322940537
|
||||
|
|
|
@ -60,6 +60,7 @@ from nucypher.config.characters import (
|
|||
UrsulaConfiguration,
|
||||
)
|
||||
from nucypher.config.constants import TEMPORARY_DOMAIN
|
||||
from nucypher.policy.payment import SubscriptionManagerPayment
|
||||
from nucypher.utilities.emitters import StdoutEmitter
|
||||
from nucypher.crypto.keystore import Keystore
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
|
@ -621,7 +622,12 @@ def staking_providers(testerchain, agency, test_registry, threshold_staking):
|
|||
operator_address=operator_address,
|
||||
domain=TEMPORARY_DOMAIN,
|
||||
registry=test_registry,
|
||||
transacting_power=operator_power)
|
||||
transacting_power=operator_power,
|
||||
payment_method=SubscriptionManagerPayment(
|
||||
eth_provider=testerchain.eth_provider_uri,
|
||||
network=TEMPORARY_DOMAIN,
|
||||
registry=test_registry)
|
||||
)
|
||||
operator.confirm_address() # assume we always need a "pre-confirmed" operator for now.
|
||||
|
||||
# track
|
||||
|
|
|
@ -23,9 +23,10 @@ from web3 import Web3
|
|||
|
||||
import tests
|
||||
from nucypher.policy.conditions.context import USER_ADDRESS_CONTEXT
|
||||
from nucypher.policy.conditions.evm import ContractCondition, RPCCondition
|
||||
from nucypher.policy.conditions.evm import ContractCondition, RPCCondition, _CONDITION_CHAINS
|
||||
from nucypher.policy.conditions.lingo import AND, OR, ConditionLingo, ReturnValueTest
|
||||
from nucypher.policy.conditions.time import TimeCondition
|
||||
from tests.constants import TESTERCHAIN_CHAIN_ID
|
||||
|
||||
VECTORS_FILE = Path(tests.__file__).parent / "data" / "test_conditions.json"
|
||||
|
||||
|
@ -33,10 +34,16 @@ with open(VECTORS_FILE, 'r') as file:
|
|||
VECTORS = json.loads(file.read())
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_condition_blockchains(mocker):
|
||||
mocker.patch.dict(_CONDITION_CHAINS, {131277322940537: 'testerchain'})
|
||||
|
||||
|
||||
# ERC1155
|
||||
|
||||
@pytest.fixture()
|
||||
def ERC1155_balance_condition_data():
|
||||
VECTORS['ERC1155_balance']['chain'] = TESTERCHAIN_CHAIN_ID
|
||||
data = json.dumps(VECTORS['ERC1155_balance'])
|
||||
return data
|
||||
|
||||
|
@ -52,6 +59,7 @@ def ERC1155_balance_condition(ERC1155_balance_condition_data):
|
|||
|
||||
@pytest.fixture()
|
||||
def ERC20_balance_condition_data():
|
||||
VECTORS['ERC20_balance']['chain'] = TESTERCHAIN_CHAIN_ID
|
||||
data = json.dumps(VECTORS['ERC20_balance'])
|
||||
return data
|
||||
|
||||
|
@ -67,7 +75,7 @@ def ERC20_balance_condition(ERC20_balance_condition_data):
|
|||
def rpc_condition():
|
||||
condition = RPCCondition(
|
||||
method="eth_getBalance",
|
||||
chain="testerchain",
|
||||
chain=TESTERCHAIN_CHAIN_ID,
|
||||
return_value_test=ReturnValueTest("==", Web3.to_wei(1_000_000, "ether")),
|
||||
parameters=[USER_ADDRESS_CONTEXT],
|
||||
)
|
||||
|
@ -80,7 +88,7 @@ def erc20_evm_condition(test_registry):
|
|||
contract_address="0xaDD9D957170dF6F33982001E4c22eCCdd5539118",
|
||||
method="balanceOf",
|
||||
standard_contract_type="ERC20",
|
||||
chain="testerchain",
|
||||
chain=TESTERCHAIN_CHAIN_ID,
|
||||
return_value_test=ReturnValueTest("==", 0),
|
||||
parameters=[
|
||||
USER_ADDRESS_CONTEXT,
|
||||
|
@ -95,7 +103,7 @@ def erc721_evm_condition(test_registry):
|
|||
contract_address="0xaDD9D957170dF6F33982001E4c22eCCdd5539118",
|
||||
method="ownerOf",
|
||||
standard_contract_type="ERC721",
|
||||
chain="testerchain",
|
||||
chain=TESTERCHAIN_CHAIN_ID,
|
||||
return_value_test=ReturnValueTest("==", ":userAddress"),
|
||||
parameters=[
|
||||
5954,
|
||||
|
@ -104,28 +112,6 @@ def erc721_evm_condition(test_registry):
|
|||
return condition
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sm_condition(test_registry):
|
||||
zeroized_policy_struct = (
|
||||
"0x0000000000000000000000000000000000000000",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"0x0000000000000000000000000000000000000000",
|
||||
)
|
||||
condition = ContractCondition(
|
||||
contract_address="0xaDD9D957170dF6F33982001E4c22eCCdd5539118",
|
||||
method="getPolicy",
|
||||
chain="testerchain",
|
||||
function_abi=ABI,
|
||||
return_value_test=ReturnValueTest("!=", zeroized_policy_struct),
|
||||
parameters=[
|
||||
':hrac',
|
||||
]
|
||||
)
|
||||
return condition
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def timelock_condition():
|
||||
condition = TimeCondition(
|
||||
|
|
|
@ -20,6 +20,7 @@ from nucypher.policy.conditions.base import ReencryptionCondition
|
|||
from nucypher.policy.conditions.evm import ContractCondition, RPCCondition
|
||||
from nucypher.policy.conditions.lingo import ReturnValueTest
|
||||
from nucypher.policy.conditions.time import TimeCondition
|
||||
from tests.constants import TESTERCHAIN_CHAIN_ID
|
||||
|
||||
|
||||
def test_invalid_time_condition():
|
||||
|
@ -35,7 +36,7 @@ def test_invalid_rpc_condition():
|
|||
with pytest.raises(ReencryptionCondition.InvalidCondition):
|
||||
_ = RPCCondition(
|
||||
method="no_eth_prefix_eth_getBalance",
|
||||
chain="testerchain",
|
||||
chain=TESTERCHAIN_CHAIN_ID,
|
||||
return_value_test=ReturnValueTest("==", 0),
|
||||
parameters=["0xaDD9D957170dF6F33982001E4c22eCCdd5539118"],
|
||||
)
|
||||
|
@ -44,16 +45,16 @@ def test_invalid_rpc_condition():
|
|||
with pytest.raises(RPCCondition.InvalidCondition):
|
||||
_ = RPCCondition(
|
||||
method="eth_randoMethod",
|
||||
chain="testerchain",
|
||||
chain=TESTERCHAIN_CHAIN_ID,
|
||||
return_value_test=ReturnValueTest("==", 0),
|
||||
parameters=["0xaDD9D957170dF6F33982001E4c22eCCdd5539118"],
|
||||
)
|
||||
|
||||
# invalid chain id
|
||||
# unsupported chain id
|
||||
with pytest.raises(RPCCondition.InvalidCondition):
|
||||
_ = RPCCondition(
|
||||
method="eth_getBalance",
|
||||
chain="90210", # Beverly Hills Chain :)
|
||||
chain=90210, # Beverly Hills Chain :)
|
||||
return_value_test=ReturnValueTest("==", 0),
|
||||
parameters=["0xaDD9D957170dF6F33982001E4c22eCCdd5539118"],
|
||||
)
|
||||
|
@ -65,7 +66,7 @@ def test_invalid_contract_condition():
|
|||
_ = ContractCondition(
|
||||
contract_address="0xaDD9D957170dF6F33982001E4c22eCCdd5539118",
|
||||
method="getPolicy",
|
||||
chain="testerchain",
|
||||
chain=TESTERCHAIN_CHAIN_ID,
|
||||
return_value_test=ReturnValueTest('!=', 0),
|
||||
parameters=[
|
||||
':hrac',
|
||||
|
@ -77,7 +78,7 @@ def test_invalid_contract_condition():
|
|||
_ = ContractCondition(
|
||||
contract_address="0xaDD9D957170dF6F33982001E4c22eCCdd5539118",
|
||||
method="getPolicy",
|
||||
chain="testerchain",
|
||||
chain=TESTERCHAIN_CHAIN_ID,
|
||||
standard_contract_type="ERC90210", # Beverly Hills contract type :)
|
||||
return_value_test=ReturnValueTest('!=', 0),
|
||||
parameters=[
|
||||
|
@ -90,7 +91,7 @@ def test_invalid_contract_condition():
|
|||
_ = ContractCondition(
|
||||
contract_address="0xaDD9D957170dF6F33982001E4c22eCCdd5539118",
|
||||
method="getPolicy",
|
||||
chain="testerchain",
|
||||
chain=TESTERCHAIN_CHAIN_ID,
|
||||
function_abi=["rando ABI"],
|
||||
return_value_test=ReturnValueTest('!=', 0),
|
||||
parameters=[
|
||||
|
|
Loading…
Reference in New Issue