mirror of https://github.com/nucypher/nucypher.git
commit
65f6fcdb17
|
@ -21,22 +21,15 @@ from datetime import datetime
|
|||
from decimal import Decimal
|
||||
from json import JSONDecodeError
|
||||
from typing import Tuple, List, Dict, Union
|
||||
from eth_utils import keccak
|
||||
|
||||
import maya
|
||||
from constant_sorrow.constants import (
|
||||
CONTRACT_NOT_DEPLOYED,
|
||||
NO_DEPLOYER_ADDRESS,
|
||||
EMPTY_STAKING_SLOT,
|
||||
UNKNOWN_STAKES,
|
||||
NOT_STAKING,
|
||||
NO_STAKES,
|
||||
STRANGER_STAKER,
|
||||
NO_STAKING_DEVICE,
|
||||
STRANGER_WORKER,
|
||||
WORKER_NOT_RUNNING
|
||||
)
|
||||
from eth_tester.exceptions import TransactionFailed
|
||||
from eth_utils import keccak
|
||||
from twisted.logger import Logger
|
||||
|
||||
from nucypher.blockchain.economics import TokenEconomics
|
||||
|
@ -47,7 +40,6 @@ from nucypher.blockchain.eth.agents import (
|
|||
AdjudicatorAgent,
|
||||
EthereumContractAgent
|
||||
)
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainInterface
|
||||
from nucypher.blockchain.eth.deployers import (
|
||||
NucypherTokenDeployer,
|
||||
StakingEscrowDeployer,
|
||||
|
@ -57,10 +49,12 @@ from nucypher.blockchain.eth.deployers import (
|
|||
AdjudicatorDeployer,
|
||||
ContractDeployer)
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainInterface
|
||||
from nucypher.blockchain.eth.registry import AllocationRegistry
|
||||
from nucypher.blockchain.eth.token import NU, Stake, StakeTracker
|
||||
from nucypher.blockchain.eth.utils import datetime_to_period, calculate_period_duration
|
||||
from nucypher.config.constants import DEFAULT_CONFIG_ROOT
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
|
||||
|
||||
def only_me(func):
|
||||
|
@ -146,6 +140,7 @@ class Deployer(NucypherTokenActor):
|
|||
def __init__(self,
|
||||
blockchain: BlockchainInterface,
|
||||
deployer_address: str = None,
|
||||
client_password: str = None,
|
||||
bare: bool = True
|
||||
) -> None:
|
||||
|
||||
|
@ -162,6 +157,11 @@ class Deployer(NucypherTokenActor):
|
|||
|
||||
self.user_escrow_deployers = dict()
|
||||
self.deployers = {d.contract_name: d for d in self.deployer_classes}
|
||||
|
||||
blockchain.transacting_power = TransactingPower(blockchain=blockchain,
|
||||
account=deployer_address,
|
||||
password=client_password)
|
||||
blockchain.transacting_power.activate()
|
||||
self.log = Logger("Deployment-Actor")
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -170,12 +170,6 @@ class Deployer(NucypherTokenActor):
|
|||
deployer_address=self.deployer_address)
|
||||
return r
|
||||
|
||||
@classmethod
|
||||
def from_blockchain(cls, provider_uri: str, registry=None, *args, **kwargs):
|
||||
blockchain = BlockchainInterface.connect(provider_uri=provider_uri, registry=registry)
|
||||
instance = cls(blockchain=blockchain, *args, **kwargs)
|
||||
return instance
|
||||
|
||||
@property
|
||||
def deployer_address(self):
|
||||
return self.blockchain.deployer_address
|
||||
|
|
|
@ -118,7 +118,7 @@ class NucypherTokenAgent(EthereumContractAgent, metaclass=Agency):
|
|||
"""Approve the transfer of token from the sender address to the target address."""
|
||||
payload = {'gas': 500_000} # TODO #413: gas needed for use with geth.
|
||||
contract_function = self.contract.functions.approve(target_address, amount)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function,
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function,
|
||||
payload=payload,
|
||||
sender_address=sender_address)
|
||||
return receipt
|
||||
|
@ -126,7 +126,7 @@ class NucypherTokenAgent(EthereumContractAgent, metaclass=Agency):
|
|||
def transfer(self, amount: int, target_address: str, sender_address: str):
|
||||
self.approve_transfer(amount=amount, target_address=target_address, sender_address=sender_address)
|
||||
contract_function = self.contract.functions.transfer(target_address, amount)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=sender_address)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=sender_address)
|
||||
return receipt
|
||||
|
||||
|
||||
|
@ -186,13 +186,13 @@ class StakingEscrowAgent(EthereumContractAgent, metaclass=Agency):
|
|||
def deposit_tokens(self, amount: int, lock_periods: int, sender_address: str):
|
||||
"""Send tokens to the escrow from the staker's address"""
|
||||
contract_function = self.contract.functions.deposit(amount, lock_periods)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function,
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function,
|
||||
sender_address=sender_address)
|
||||
return receipt
|
||||
|
||||
def divide_stake(self, staker_address: str, stake_index: int, target_value: int, periods: int):
|
||||
contract_function = self.contract.functions.divideStake(stake_index, target_value, periods)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=staker_address)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=staker_address)
|
||||
return receipt
|
||||
|
||||
def get_last_active_period(self, address: str) -> int:
|
||||
|
@ -209,7 +209,7 @@ class StakingEscrowAgent(EthereumContractAgent, metaclass=Agency):
|
|||
|
||||
def set_worker(self, staker_address: str, worker_address: str):
|
||||
contract_function = self.contract.functions.setWorker(worker_address)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=staker_address)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=staker_address)
|
||||
return receipt
|
||||
|
||||
def release_worker(self, staker_address: str):
|
||||
|
@ -220,7 +220,7 @@ class StakingEscrowAgent(EthereumContractAgent, metaclass=Agency):
|
|||
For each period that the worker confirms activity, the staker is rewarded.
|
||||
"""
|
||||
contract_function = self.contract.functions.confirmActivity()
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=worker_address)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=worker_address)
|
||||
return receipt
|
||||
|
||||
def mint(self, staker_address: str):
|
||||
|
@ -230,7 +230,7 @@ class StakingEscrowAgent(EthereumContractAgent, metaclass=Agency):
|
|||
when you intend to withdraw 100% of tokens.
|
||||
"""
|
||||
contract_function = self.contract.functions.mint()
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=staker_address)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=staker_address)
|
||||
return receipt
|
||||
|
||||
@validate_checksum_address
|
||||
|
@ -252,7 +252,7 @@ class StakingEscrowAgent(EthereumContractAgent, metaclass=Agency):
|
|||
"""Withdraw tokens"""
|
||||
payload = {'gas': 500_000} # TODO: #842 Gas Management
|
||||
contract_function = self.contract.functions.withdraw(amount)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function,
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function,
|
||||
payload=payload,
|
||||
sender_address=staker_address)
|
||||
return receipt
|
||||
|
@ -322,7 +322,7 @@ class PolicyAgent(EthereumContractAgent, metaclass=Agency):
|
|||
|
||||
payload = {'value': value}
|
||||
contract_function = self.contract.functions.createPolicy(policy_id, periods, initial_reward, node_addresses)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function,
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function,
|
||||
payload=payload,
|
||||
sender_address=author_address)
|
||||
return receipt
|
||||
|
@ -335,13 +335,13 @@ class PolicyAgent(EthereumContractAgent, metaclass=Agency):
|
|||
def revoke_policy(self, policy_id: bytes, author_address: str):
|
||||
"""Revoke by arrangement ID; Only the policy's author_address can revoke the policy."""
|
||||
contract_function = self.contract.functions.revokePolicy(policy_id)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=author_address)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=author_address)
|
||||
return receipt
|
||||
|
||||
def collect_policy_reward(self, collector_address: str, staker_address: str):
|
||||
"""Collect rewarded ETH"""
|
||||
contract_function = self.contract.functions.withdraw(collector_address)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=staker_address)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=staker_address)
|
||||
return receipt
|
||||
|
||||
def fetch_policy_arrangements(self, policy_id):
|
||||
|
@ -352,17 +352,17 @@ class PolicyAgent(EthereumContractAgent, metaclass=Agency):
|
|||
|
||||
def revoke_arrangement(self, policy_id: str, node_address: str, author_address: str):
|
||||
contract_function = self.contract.functions.revokeArrangement(policy_id, node_address)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=author_address)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=author_address)
|
||||
return receipt
|
||||
|
||||
def calculate_refund(self, policy_id: str, author_address: str):
|
||||
contract_function = self.contract.functions.calculateRefundValue(policy_id)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=author_address)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=author_address)
|
||||
return receipt
|
||||
|
||||
def collect_refund(self, policy_id: str, author_address: str):
|
||||
contract_function = self.contract.functions.refund(policy_id)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=author_address)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=author_address)
|
||||
return receipt
|
||||
|
||||
|
||||
|
@ -455,47 +455,47 @@ class UserEscrowAgent(EthereumContractAgent):
|
|||
|
||||
def lock(self, amount: int, periods: int):
|
||||
contract_function = self.__proxy_contract.functions.lock(amount, periods)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=self.__beneficiary)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=self.__beneficiary)
|
||||
return receipt
|
||||
|
||||
def withdraw_tokens(self, value: int):
|
||||
contract_function = self.principal_contract.functions.withdrawTokens(value)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=self.__beneficiary)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=self.__beneficiary)
|
||||
return receipt
|
||||
|
||||
def withdraw_eth(self):
|
||||
contract_function = self.principal_contract.functions.withdrawETH()
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=self.__beneficiary)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=self.__beneficiary)
|
||||
return receipt
|
||||
|
||||
def deposit_as_staker(self, value: int, periods: int):
|
||||
contract_function = self.__proxy_contract.functions.depositAsStaker(value, periods)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=self.__beneficiary)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=self.__beneficiary)
|
||||
return receipt
|
||||
|
||||
def withdraw_as_staker(self, value: int):
|
||||
contract_function = self.__proxy_contract.functions.withdrawAsStaker(value)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=self.__beneficiary)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=self.__beneficiary)
|
||||
return receipt
|
||||
|
||||
def set_worker(self, worker_address: str):
|
||||
contract_function = self.__proxy_contract.functions.setWorker(worker_address)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=self.__beneficiary)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=self.__beneficiary)
|
||||
return receipt
|
||||
|
||||
def mint(self):
|
||||
contract_function = self.__proxy_contract.functions.mint()
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=self.__beneficiary)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=self.__beneficiary)
|
||||
return receipt
|
||||
|
||||
def collect_policy_reward(self):
|
||||
contract_function = self.__proxy_contract.functions.withdrawPolicyReward()
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=self.__beneficiary)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=self.__beneficiary)
|
||||
return receipt
|
||||
|
||||
def set_min_reward_rate(self, rate: int):
|
||||
contract_function = self.__proxy_contract.functions.setMinRewardRate(rate)
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function, sender_address=self.__beneficiary)
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=self.__beneficiary)
|
||||
return receipt
|
||||
|
||||
|
||||
|
@ -513,7 +513,7 @@ class AdjudicatorAgent(EthereumContractAgent, metaclass=Agency):
|
|||
"""
|
||||
payload = {'gas': 500_000} # TODO #413: gas needed for use with geth.
|
||||
contract_function = self.contract.functions.evaluateCFrag(*evidence.evaluation_arguments())
|
||||
receipt = self.blockchain.send_transaction(transaction_function=contract_function,
|
||||
receipt = self.blockchain.send_transaction(contract_function=contract_function,
|
||||
sender_address=sender_address,
|
||||
payload=payload)
|
||||
return receipt
|
||||
|
|
|
@ -6,6 +6,7 @@ from typing import Union
|
|||
|
||||
import maya
|
||||
from constant_sorrow.constants import NOT_RUNNING, UNKNOWN_DEVELOPMENT_CHAIN_ID
|
||||
from cytoolz.dicttoolz import dissoc
|
||||
from eth_account import Account
|
||||
from eth_account.messages import encode_defunct
|
||||
from eth_utils import to_canonical_address
|
||||
|
@ -59,7 +60,7 @@ LOCAL_CHAINS = {1337: "GethDev",
|
|||
5777: "Ganache/TestRPC"}
|
||||
|
||||
|
||||
class Web3Client(object):
|
||||
class Web3Client:
|
||||
|
||||
is_local = False
|
||||
|
||||
|
@ -151,6 +152,10 @@ class Web3Client(object):
|
|||
def syncing(self) -> Union[bool, dict]:
|
||||
return self.w3.eth.syncing
|
||||
|
||||
def lock_account(self, address):
|
||||
if not self.is_local:
|
||||
return self.lock_account(address=address)
|
||||
|
||||
def unlock_account(self, address, password) -> bool:
|
||||
if not self.is_local:
|
||||
return self.unlock_account(address, password)
|
||||
|
@ -195,6 +200,9 @@ class Web3Client(object):
|
|||
receipt = self.w3.eth.waitForTransactionReceipt(transaction_hash, timeout=timeout)
|
||||
return receipt
|
||||
|
||||
def sign_transaction(self, transaction: dict):
|
||||
raise NotImplementedError
|
||||
|
||||
def get_transaction(self, transaction_hash) -> str:
|
||||
return self.w3.eth.getTransaction(transaction_hash)
|
||||
|
||||
|
@ -264,6 +272,19 @@ class GethClient(Web3Client):
|
|||
def unlock_account(self, address, password):
|
||||
return self.w3.geth.personal.unlockAccount(address, password)
|
||||
|
||||
def sign_transaction(self, transaction: dict) -> bytes:
|
||||
|
||||
# Do not include a 'to' field for contract creation.
|
||||
if transaction['to'] == b'':
|
||||
transaction = dissoc(transaction, 'to')
|
||||
|
||||
# Sign
|
||||
result = self.w3.eth.signTransaction(transaction=transaction)
|
||||
|
||||
# Return RLP bytes
|
||||
rlp_encoded_transaction = result.raw
|
||||
return rlp_encoded_transaction
|
||||
|
||||
|
||||
class ParityClient(Web3Client):
|
||||
|
||||
|
@ -293,15 +314,18 @@ class EthereumTesterClient(Web3Client):
|
|||
|
||||
is_local = True
|
||||
|
||||
def unlock_account(self, address, password):
|
||||
return True
|
||||
def unlock_account(self, address, password) -> bool:
|
||||
"""Returns True if the testing backend keyring has control of the given address."""
|
||||
address = to_canonical_address(address)
|
||||
keystore = self.w3.provider.ethereum_tester.backend._key_lookup
|
||||
return address in keystore
|
||||
|
||||
def sync(self, *args, **kwargs):
|
||||
return True
|
||||
|
||||
def sign_transaction(self, account: str, transaction: dict):
|
||||
def sign_transaction(self, transaction: dict):
|
||||
# Get signing key of test account
|
||||
address = to_canonical_address(account)
|
||||
address = to_canonical_address(transaction['from'])
|
||||
signing_key = self.w3.provider.ethereum_tester.backend._key_lookup[address]._raw_key
|
||||
|
||||
# Sign using a local private key
|
||||
|
|
|
@ -204,7 +204,7 @@ class DispatcherDeployer(ContractDeployer):
|
|||
|
||||
origin_args = {'from': self.deployer_address, 'gasPrice': self.blockchain.client.gas_price} # TODO: Gas management
|
||||
upgrade_function = self._contract.functions.upgrade(new_target, existing_secret_plaintext, new_secret_hash)
|
||||
upgrade_receipt = self.blockchain.send_transaction(transaction_function=upgrade_function,
|
||||
upgrade_receipt = self.blockchain.send_transaction(contract_function=upgrade_function,
|
||||
sender_address=self.deployer_address,
|
||||
payload=origin_args)
|
||||
return upgrade_receipt
|
||||
|
@ -212,7 +212,7 @@ class DispatcherDeployer(ContractDeployer):
|
|||
def rollback(self, existing_secret_plaintext: bytes, new_secret_hash: bytes) -> dict:
|
||||
origin_args = {'from': self.deployer_address, 'gasPrice': self.blockchain.client.gas_price} # TODO: Gas management
|
||||
rollback_function = self._contract.functions.rollback(existing_secret_plaintext, new_secret_hash)
|
||||
rollback_receipt = self.blockchain.send_transaction(transaction_function=rollback_function,
|
||||
rollback_receipt = self.blockchain.send_transaction(contract_function=rollback_function,
|
||||
sender_address=self.deployer_address,
|
||||
payload=origin_args)
|
||||
return rollback_receipt
|
||||
|
@ -294,7 +294,7 @@ class StakingEscrowDeployer(ContractDeployer):
|
|||
reward_function = self.token_agent.contract.functions.transfer(the_escrow_contract.address,
|
||||
self.__economics.erc20_reward_supply)
|
||||
|
||||
reward_receipt = self.blockchain.send_transaction(transaction_function=reward_function,
|
||||
reward_receipt = self.blockchain.send_transaction(contract_function=reward_function,
|
||||
sender_address=self.deployer_address,
|
||||
payload=origin_args)
|
||||
|
||||
|
@ -304,7 +304,7 @@ class StakingEscrowDeployer(ContractDeployer):
|
|||
# 4 - Initialize the Staker Escrow contract
|
||||
init_function = the_escrow_contract.functions.initialize()
|
||||
|
||||
init_receipt = self.blockchain.send_transaction(transaction_function=init_function,
|
||||
init_receipt = self.blockchain.send_transaction(contract_function=init_function,
|
||||
sender_address=self.deployer_address,
|
||||
payload=origin_args)
|
||||
|
||||
|
@ -418,7 +418,7 @@ class PolicyManagerDeployer(ContractDeployer):
|
|||
if gas_limit:
|
||||
tx_args.update({'gas': gas_limit})
|
||||
set_policy_manager_function = self.staking_agent.contract.functions.setPolicyManager(policy_manager_contract.address)
|
||||
set_policy_manager_receipt = self.blockchain.send_transaction(transaction_function=set_policy_manager_function,
|
||||
set_policy_manager_receipt = self.blockchain.send_transaction(contract_function=set_policy_manager_function,
|
||||
sender_address=self.deployer_address,
|
||||
payload=tx_args)
|
||||
|
||||
|
@ -505,7 +505,7 @@ class LibraryLinkerDeployer(ContractDeployer):
|
|||
|
||||
origin_args = {'from': self.deployer_address} # TODO: Gas management
|
||||
retarget_function = self._contract.functions.upgrade(new_target, existing_secret_plaintext, new_secret_hash)
|
||||
retarget_receipt = self.blockchain.send_transaction(transaction_function=retarget_function,
|
||||
retarget_receipt = self.blockchain.send_transaction(contract_function=retarget_function,
|
||||
sender_address=self.deployer_address,
|
||||
payload=origin_args)
|
||||
return retarget_receipt
|
||||
|
@ -636,7 +636,7 @@ class UserEscrowDeployer(ContractDeployer):
|
|||
# TODO: #413, #842 - Gas Management
|
||||
payload = {'from': self.deployer_address, 'gas': 500_000, 'gasPrice': self.blockchain.client.gas_price}
|
||||
transfer_owner_function = self.contract.functions.transferOwnership(beneficiary_address)
|
||||
transfer_owner_receipt = self.blockchain.send_transaction(transaction_function=transfer_owner_function,
|
||||
transfer_owner_receipt = self.blockchain.send_transaction(contract_function=transfer_owner_function,
|
||||
payload=payload,
|
||||
sender_address=self.deployer_address)
|
||||
self.__beneficiary_address = beneficiary_address
|
||||
|
@ -657,7 +657,7 @@ class UserEscrowDeployer(ContractDeployer):
|
|||
'gasPrice': self.blockchain.client.gas_price,
|
||||
'gas': 200_000}
|
||||
deposit_function = self.contract.functions.initialDeposit(value, duration)
|
||||
deposit_receipt = self.blockchain.send_transaction(transaction_function=deposit_function,
|
||||
deposit_receipt = self.blockchain.send_transaction(contract_function=deposit_function,
|
||||
sender_address=self.deployer_address,
|
||||
payload=args)
|
||||
|
||||
|
@ -748,7 +748,7 @@ class AdjudicatorDeployer(ContractDeployer):
|
|||
if gas_limit:
|
||||
tx_args.update({'gas': gas_limit})
|
||||
set_adjudicator_function = self.staking_agent.contract.functions.setAdjudicator(adjudicator_contract.address)
|
||||
set_adjudicator_receipt = self.blockchain.send_transaction(transaction_function=set_adjudicator_function,
|
||||
set_adjudicator_receipt = self.blockchain.send_transaction(contract_function=set_adjudicator_function,
|
||||
sender_address=self.deployer_address,
|
||||
payload=tx_args)
|
||||
|
||||
|
|
|
@ -31,10 +31,12 @@ from constant_sorrow.constants import (
|
|||
READ_ONLY_INTERFACE
|
||||
)
|
||||
from eth_tester import EthereumTester
|
||||
from eth_utils import to_checksum_address, to_canonical_address
|
||||
from twisted.logger import Logger
|
||||
from web3 import Web3, WebsocketProvider, HTTPProvider, IPCProvider
|
||||
from web3.contract import Contract, ConciseContract, ContractFunction
|
||||
from web3.exceptions import TimeExhausted
|
||||
from web3.contract import ConciseContract
|
||||
from web3.contract import Contract, ContractFunction, ContractConstructor
|
||||
from web3.exceptions import TimeExhausted, ValidationError
|
||||
from web3.middleware import geth_poa_middleware
|
||||
|
||||
from nucypher.blockchain.eth.clients import Web3Client, NuCypherGethProcess
|
||||
|
@ -49,7 +51,7 @@ from nucypher.blockchain.eth.providers import (
|
|||
)
|
||||
from nucypher.blockchain.eth.registry import EthereumContractRegistry
|
||||
from nucypher.blockchain.eth.sol.compile import SolidityCompiler
|
||||
from nucypher.crypto.powers import BlockchainPower
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
|
||||
Web3Providers = Union[IPCProvider, WebsocketProvider, HTTPProvider, EthereumTester]
|
||||
|
||||
|
@ -83,13 +85,11 @@ class BlockchainInterface:
|
|||
|
||||
def __init__(self,
|
||||
poa: bool = True,
|
||||
sync_now: bool = True,
|
||||
provider_process: NuCypherGethProcess = NO_PROVIDER_PROCESS,
|
||||
provider_uri: str = NO_BLOCKCHAIN_CONNECTION,
|
||||
transacting_power: BlockchainPower = READ_ONLY_INTERFACE,
|
||||
transacting_power: TransactingPower = READ_ONLY_INTERFACE,
|
||||
provider: Web3Providers = NO_BLOCKCHAIN_CONNECTION,
|
||||
registry: EthereumContractRegistry = None,
|
||||
fetch_registry: bool = True):
|
||||
registry: EthereumContractRegistry = None):
|
||||
|
||||
"""
|
||||
A blockchain "network interface"; The circumflex wraps entirely around the bounds of
|
||||
|
@ -164,11 +164,6 @@ class BlockchainInterface:
|
|||
self.transacting_power = transacting_power
|
||||
self.registry = registry
|
||||
|
||||
self.connect(provider=provider,
|
||||
provider_uri=provider_uri,
|
||||
fetch_registry=fetch_registry,
|
||||
sync_now=sync_now)
|
||||
|
||||
BlockchainInterface._instance = self
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -188,6 +183,8 @@ class BlockchainInterface:
|
|||
"""
|
||||
https://web3py.readthedocs.io/en/stable/__provider.html#examples-using-automated-detection
|
||||
"""
|
||||
if self.client is NO_BLOCKCHAIN_CONNECTION:
|
||||
return False
|
||||
return self.client.is_connected
|
||||
|
||||
def disconnect(self):
|
||||
|
@ -208,21 +205,18 @@ class BlockchainInterface:
|
|||
self.log.debug('Injecting POA middleware at layer 0')
|
||||
self.client.inject_middleware(geth_poa_middleware, layer=0)
|
||||
|
||||
def connect(self,
|
||||
provider: Web3Providers = None,
|
||||
provider_uri: str = None,
|
||||
fetch_registry: bool = True,
|
||||
sync_now: bool = True):
|
||||
def connect(self, fetch_registry: bool = True, sync_now: bool = True):
|
||||
|
||||
# Spawn child process
|
||||
if self._provider_process:
|
||||
self._provider_process.start()
|
||||
provider_uri = self._provider_process.provider_uri(scheme='file')
|
||||
else:
|
||||
self.log.info(f"Using external Web3 Provider '{provider_uri}'")
|
||||
provider_uri = self.provider_uri
|
||||
self.log.info(f"Using external Web3 Provider '{self.provider_uri}'")
|
||||
|
||||
# Attach Provider
|
||||
self._attach_provider(provider=provider, provider_uri=provider_uri)
|
||||
self._attach_provider(provider=self._provider, provider_uri=provider_uri)
|
||||
self.log.info("Connecting to {}".format(self.provider_uri))
|
||||
if self._provider is NO_BLOCKCHAIN_CONNECTION:
|
||||
raise self.NoProvider("There are no configured blockchain providers")
|
||||
|
@ -291,7 +285,7 @@ class BlockchainInterface:
|
|||
self._provider = provider
|
||||
|
||||
def send_transaction(self,
|
||||
transaction_function: ContractFunction,
|
||||
contract_function: ContractFunction,
|
||||
sender_address: str,
|
||||
payload: dict = None,
|
||||
) -> dict:
|
||||
|
@ -312,7 +306,21 @@ class BlockchainInterface:
|
|||
'from': sender_address,
|
||||
'gasPrice': self.client.w3.eth.gasPrice})
|
||||
|
||||
unsigned_transaction = transaction_function.buildTransaction(payload)
|
||||
# Get interface name
|
||||
try:
|
||||
transaction_name = contract_function.fn_name.upper()
|
||||
except AttributeError:
|
||||
if isinstance(contract_function, ContractConstructor):
|
||||
transaction_name = 'DEPLOY'
|
||||
else:
|
||||
transaction_name = 'UNKNOWN'
|
||||
|
||||
# Build transaction payload
|
||||
try:
|
||||
unsigned_transaction = contract_function.buildTransaction(payload)
|
||||
except ValidationError:
|
||||
# TODO: Handle validation failures for gas limits, invalid fields, etc.
|
||||
raise
|
||||
|
||||
#
|
||||
# Broadcast
|
||||
|
@ -320,11 +328,15 @@ class BlockchainInterface:
|
|||
|
||||
signed_raw_transaction = self.transacting_power.sign_transaction(unsigned_transaction)
|
||||
txhash = self.client.send_raw_transaction(signed_raw_transaction)
|
||||
self.log.debug(f"[TX-{transaction_name}] | {to_checksum_address(payload['from'])}")
|
||||
|
||||
try:
|
||||
receipt = self.client.wait_for_receipt(txhash, timeout=self.TIMEOUT)
|
||||
except TimeExhausted:
|
||||
# TODO: Handle transaction timeout
|
||||
raise
|
||||
else:
|
||||
self.log.debug(f"[RECEIPT-{transaction_name}] | {receipt['transactionHash'].hex()}")
|
||||
|
||||
#
|
||||
# Confirm
|
||||
|
@ -427,9 +439,13 @@ class BlockchainDeployerInterface(BlockchainInterface):
|
|||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.compiler = compiler or SolidityCompiler()
|
||||
self._setup_solidity(compiler=self.compiler)
|
||||
self.__deployer_address = deployer_address or NO_DEPLOYER_CONFIGURED
|
||||
|
||||
def connect(self, *args, **kwargs):
|
||||
super().connect(*args, **kwargs)
|
||||
self._setup_solidity(compiler=self.compiler)
|
||||
return self.is_connected
|
||||
|
||||
@property
|
||||
def deployer_address(self):
|
||||
return self.__deployer_address
|
||||
|
@ -488,7 +504,7 @@ class BlockchainDeployerInterface(BlockchainInterface):
|
|||
# Transmit the deployment tx #
|
||||
#
|
||||
|
||||
receipt = self.send_transaction(transaction_function=transaction_function,
|
||||
receipt = self.send_transaction(contract_function=transaction_function,
|
||||
sender_address=self.deployer_address,
|
||||
payload=deploy_transaction)
|
||||
|
||||
|
|
|
@ -285,7 +285,7 @@ class BlockchainPolicy(Policy):
|
|||
|
||||
# Transact
|
||||
contract_function = self.author.policy_agent.contract.functions.createPolicy(*policy_args)
|
||||
receipt = self.author.blockchain.send_transaction(transaction_function=contract_function,
|
||||
receipt = self.author.blockchain.send_transaction(contract_function=contract_function,
|
||||
sender_address=self.author.checksum_address,
|
||||
payload=payload)
|
||||
txhash = receipt['transactionHash']
|
||||
|
|
|
@ -176,10 +176,12 @@ class Character(Learner):
|
|||
# Decentralized
|
||||
#
|
||||
if not federated_only:
|
||||
if not blockchain and is_me:
|
||||
raise ValueError('No blockchain interface provided to run decentralized mode.')
|
||||
if not checksum_address:
|
||||
raise ValueError("No checksum_address provided while running in a non-federated mode.")
|
||||
raise ValueError("No checksum_address provided to run in decentralized mode.")
|
||||
else:
|
||||
self._checksum_address = checksum_address # TODO: Check that this matches BlockchainPower
|
||||
self._checksum_address = checksum_address # TODO: Check that this matches TransactingPower
|
||||
#
|
||||
# Federated
|
||||
#
|
||||
|
@ -304,7 +306,7 @@ class Character(Learner):
|
|||
except TypeError:
|
||||
umbral_key = public_key
|
||||
|
||||
crypto_power.consume_power_up(power_up(pubkey=umbral_key))
|
||||
crypto_power.consume_power_up(power_up(public_key=umbral_key))
|
||||
|
||||
return cls(is_me=False, federated_only=federated_only, crypto_power=crypto_power, *args, **kwargs)
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ from nucypher.blockchain.eth.token import NU
|
|||
from nucypher.characters.banners import MOE_BANNER, FELIX_BANNER, NU_BANNER
|
||||
from nucypher.characters.base import Character
|
||||
from nucypher.config.constants import TEMPLATES_DIR
|
||||
from nucypher.crypto.powers import SigningPower, BlockchainPower
|
||||
from nucypher.crypto.powers import SigningPower, TransactingPower
|
||||
from nucypher.keystore.threading import ThreadedSession
|
||||
from nucypher.network.nodes import FleetStateTracker
|
||||
|
||||
|
@ -161,6 +161,7 @@ class Felix(Character, NucypherTokenActor):
|
|||
db_filepath: str,
|
||||
rest_host: str,
|
||||
rest_port: int,
|
||||
client_password: str = None,
|
||||
crash_on_error: bool = False,
|
||||
economics: TokenEconomics = None,
|
||||
distribute_ether: bool = True,
|
||||
|
@ -182,9 +183,10 @@ class Felix(Character, NucypherTokenActor):
|
|||
self.db_engine = create_engine(f'sqlite:///{self.db_filepath}', convert_unicode=True)
|
||||
|
||||
# Blockchain
|
||||
blockchain_power = BlockchainPower(blockchain=self.blockchain, account=self.checksum_address)
|
||||
self._crypto_power.consume_power_up(blockchain_power)
|
||||
# blockchain_power.unlock_account(password=None) # TODO: TransactingPower
|
||||
transacting_power = TransactingPower(blockchain=self.blockchain,
|
||||
password=client_password,
|
||||
account=self.checksum_address)
|
||||
self._crypto_power.consume_power_up(transacting_power)
|
||||
|
||||
self.token_agent = NucypherTokenAgent(blockchain=self.blockchain)
|
||||
self.reserved_addresses = [self.checksum_address, BlockchainInterface.NULL_ADDRESS]
|
||||
|
|
|
@ -28,8 +28,7 @@ import requests
|
|||
from bytestring_splitter import BytestringKwargifier, BytestringSplittingError
|
||||
from bytestring_splitter import BytestringSplitter, VariableLengthBytestring
|
||||
from constant_sorrow import constants
|
||||
from constant_sorrow.constants import FEDERATED_POLICY, STRANGER_ALICE
|
||||
from constant_sorrow.constants import INCLUDED_IN_BYTESTRING, PUBLIC_ONLY
|
||||
from constant_sorrow.constants import INCLUDED_IN_BYTESTRING, PUBLIC_ONLY, FEDERATED_POLICY, STRANGER_ALICE
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurve
|
||||
from cryptography.hazmat.primitives.serialization import Encoding
|
||||
|
@ -60,7 +59,7 @@ from nucypher.config.storages import NodeStorage, ForgetfulNodeStorage
|
|||
from nucypher.crypto.api import keccak_digest, encrypt_and_sign
|
||||
from nucypher.crypto.constants import PUBLIC_KEY_LENGTH, PUBLIC_ADDRESS_LENGTH
|
||||
from nucypher.crypto.kits import UmbralMessageKit
|
||||
from nucypher.crypto.powers import SigningPower, DecryptingPower, DelegatingPower, BlockchainPower, PowerUpError
|
||||
from nucypher.crypto.powers import SigningPower, DecryptingPower, DelegatingPower, TransactingPower, PowerUpError
|
||||
from nucypher.crypto.signing import InvalidSignature
|
||||
from nucypher.keystore.keypairs import HostingKeypair
|
||||
from nucypher.network.exceptions import NodeSeemsToBeDown
|
||||
|
@ -90,6 +89,7 @@ class Alice(Character, PolicyAuthor):
|
|||
network_middleware=None,
|
||||
controller=True,
|
||||
policy_agent=None,
|
||||
client_password: str = None,
|
||||
*args, **kwargs) -> None:
|
||||
|
||||
#
|
||||
|
@ -119,16 +119,16 @@ class Alice(Character, PolicyAuthor):
|
|||
*args, **kwargs)
|
||||
|
||||
if is_me and not federated_only: # TODO: #289
|
||||
transacting_power = TransactingPower(account=self.checksum_address,
|
||||
password=client_password,
|
||||
blockchain=self.blockchain)
|
||||
self._crypto_power.consume_power_up(transacting_power)
|
||||
|
||||
PolicyAuthor.__init__(self,
|
||||
blockchain=self.blockchain,
|
||||
policy_agent=policy_agent,
|
||||
checksum_address=checksum_address)
|
||||
|
||||
# TODO: #1092 - TransactingPower
|
||||
blockchain_power = BlockchainPower(blockchain=self.blockchain, account=self.checksum_address)
|
||||
self._crypto_power.consume_power_up(blockchain_power)
|
||||
self.blockchain.transacting_power = blockchain_power # TODO: Embed in Powerups
|
||||
|
||||
if is_me and controller:
|
||||
self.controller = self._controller_class(alice=self)
|
||||
|
||||
|
@ -842,6 +842,7 @@ class Ursula(Teacher, Character, Worker):
|
|||
checksum_address: str = None, # Staker address
|
||||
worker_address: str = None,
|
||||
stake_tracker: StakeTracker = None,
|
||||
client_password: str = None,
|
||||
|
||||
# Character
|
||||
password: str = None,
|
||||
|
@ -888,6 +889,16 @@ class Ursula(Teacher, Character, Worker):
|
|||
# Ursula is a Decentralized Worker
|
||||
#
|
||||
if not federated_only:
|
||||
|
||||
# Access staking node via node's transacting keys
|
||||
transacting_power = TransactingPower(account=worker_address,
|
||||
password=client_password,
|
||||
blockchain=self.blockchain)
|
||||
self._crypto_power.consume_power_up(transacting_power)
|
||||
|
||||
# Use blockchain power to substantiate stamp
|
||||
self.substantiate_stamp(client_password=password)
|
||||
|
||||
Worker.__init__(self,
|
||||
is_me=is_me,
|
||||
blockchain=self.blockchain,
|
||||
|
@ -895,17 +906,10 @@ class Ursula(Teacher, Character, Worker):
|
|||
worker_address=worker_address,
|
||||
stake_tracker=stake_tracker)
|
||||
|
||||
# Access to worker's ETH client via node's transacting keys
|
||||
# TODO: #1092 - TransactingPower
|
||||
blockchain_power = BlockchainPower(blockchain=self.blockchain, account=worker_address)
|
||||
self._crypto_power.consume_power_up(blockchain_power)
|
||||
self.blockchain.transacting_power = blockchain_power # TODO: Embed in powerups
|
||||
self.substantiate_stamp(client_password=password) # TODO: Use PowerUp / Derive from keyring
|
||||
|
||||
#
|
||||
# ProxyRESTServer and TLSHostingPower # TODO: Maybe we want _power_ups to be public after all?
|
||||
# ProxyRESTServer and TLSHostingPower #
|
||||
#
|
||||
if not crypto_power or (TLSHostingPower not in crypto_power._power_ups):
|
||||
if not crypto_power or (TLSHostingPower not in crypto_power):
|
||||
|
||||
#
|
||||
# Ephemeral Self-Ursula
|
||||
|
@ -966,15 +970,16 @@ class Ursula(Teacher, Character, Worker):
|
|||
certificate = self._crypto_power.power_ups(TLSHostingPower).keypair.certificate
|
||||
Teacher.__init__(self,
|
||||
password=password,
|
||||
worker_address=worker_address,
|
||||
domains=domains,
|
||||
certificate=certificate,
|
||||
certificate_filepath=certificate_filepath,
|
||||
interface_signature=interface_signature,
|
||||
timestamp=timestamp,
|
||||
decentralized_identity_evidence=decentralized_identity_evidence,
|
||||
|
||||
# TODO: #1091 When is_me and not federated_only, the stamp is substantiated twice
|
||||
worker_address=worker_address,
|
||||
substantiate_immediately=is_me and not federated_only,
|
||||
# FIXME: When is_me and not federated_only, the stamp is substantiated twice
|
||||
)
|
||||
|
||||
#
|
||||
|
|
|
@ -23,7 +23,8 @@ from typing import List
|
|||
|
||||
import click
|
||||
import requests
|
||||
from constant_sorrow.constants import NO_BLOCKCHAIN_CONNECTION
|
||||
from constant_sorrow.constants import NO_BLOCKCHAIN_CONNECTION, NO_PASSWORD
|
||||
from nacl.exceptions import CryptoError
|
||||
from twisted.logger import Logger
|
||||
|
||||
from nucypher.blockchain.eth.clients import NuCypherGethGoerliProcess
|
||||
|
@ -32,6 +33,7 @@ from nucypher.characters.lawful import Ursula
|
|||
from nucypher.cli.config import NucypherClickConfig
|
||||
from nucypher.cli.types import IPV4_ADDRESS
|
||||
from nucypher.config.constants import DEFAULT_CONFIG_ROOT, USER_LOG_DIR
|
||||
from nucypher.config.node import CharacterConfiguration
|
||||
from nucypher.network.middleware import RestMiddleware
|
||||
from nucypher.network.teachers import TEACHER_NODES
|
||||
|
||||
|
@ -67,6 +69,27 @@ class UnknownIPAddress(RuntimeError):
|
|||
pass
|
||||
|
||||
|
||||
def get_password(confirm: bool = False) -> str:
|
||||
keyring_password = os.environ.get("NUCYPHER_KEYRING_PASSWORD", NO_PASSWORD)
|
||||
if keyring_password is NO_PASSWORD: # Collect password, prefer env var
|
||||
prompt = "Enter keyring password"
|
||||
keyring_password = click.prompt(prompt, confirmation_prompt=confirm, hide_input=True)
|
||||
return keyring_password
|
||||
|
||||
|
||||
def unlock_nucypher_keyring(password: str, character_configuration: CharacterConfiguration):
|
||||
console_emitter(message='Decrypting NuCypher keyring...', color='yellow')
|
||||
if character_configuration.dev_mode:
|
||||
return True # Dev accounts are always unlocked
|
||||
|
||||
# NuCypher
|
||||
try:
|
||||
character_configuration.attach_keyring()
|
||||
character_configuration.keyring.unlock(password=password) # Takes ~3 seconds, ~1GB Ram
|
||||
except CryptoError:
|
||||
raise character_configuration.keyring.AuthenticationFailed
|
||||
|
||||
|
||||
def load_seednodes(min_stake: int,
|
||||
federated_only: bool,
|
||||
network_domains: set,
|
||||
|
@ -104,25 +127,6 @@ def load_seednodes(min_stake: int,
|
|||
return teacher_nodes
|
||||
|
||||
|
||||
def destroy_configuration_root(config_root=None, force=False, logs: bool = False) -> str:
|
||||
"""CAUTION: This will destroy *all* nucypher configuration files from the configuration root"""
|
||||
|
||||
config_root = config_root or DEFAULT_CONFIG_ROOT
|
||||
|
||||
if not force:
|
||||
click.confirm(DESTRUCTION.format(config_root), abort=True) # ABORT
|
||||
|
||||
if os.path.isdir(config_root):
|
||||
shutil.rmtree(config_root, ignore_errors=force) # config
|
||||
else:
|
||||
console_emitter(message=f'No NuCypher configuration root directory found at \'{config_root}\'')
|
||||
|
||||
if logs:
|
||||
shutil.rmtree(USER_LOG_DIR, ignore_errors=force) # logs
|
||||
|
||||
return config_root
|
||||
|
||||
|
||||
def get_external_ip_from_centralized_source() -> str:
|
||||
ip_request = requests.get('https://ifconfig.me/')
|
||||
if ip_request.status_code == 200:
|
||||
|
@ -226,7 +230,6 @@ def make_cli_character(character_config,
|
|||
dev: bool = False,
|
||||
teacher_uri: str = None,
|
||||
min_stake: int = 0,
|
||||
sync: bool = True,
|
||||
**config_args):
|
||||
|
||||
#
|
||||
|
@ -235,13 +238,13 @@ def make_cli_character(character_config,
|
|||
|
||||
# Handle Blockchain
|
||||
if not character_config.federated_only:
|
||||
click_config.connect_to_blockchain(character_configuration=character_config, sync_now=sync)
|
||||
character_config.get_blockchain_interface()
|
||||
|
||||
# Handle Keyring
|
||||
if not dev:
|
||||
character_config.attach_keyring()
|
||||
click_config.unlock_keyring(character_configuration=character_config,
|
||||
password=click_config.get_password(confirm=False))
|
||||
unlock_nucypher_keyring(character_configuration=character_config,
|
||||
password=get_password(confirm=False))
|
||||
|
||||
# Handle Teachers
|
||||
teacher_nodes = None
|
||||
|
@ -250,7 +253,7 @@ def make_cli_character(character_config,
|
|||
min_stake=min_stake,
|
||||
federated_only=character_config.federated_only,
|
||||
network_domains=character_config.domains,
|
||||
network_middleware=click_config.middleware)
|
||||
network_middleware=character_config.network_middleware)
|
||||
|
||||
#
|
||||
# Character Init
|
||||
|
@ -258,19 +261,20 @@ def make_cli_character(character_config,
|
|||
|
||||
# Produce Character
|
||||
CHARACTER = character_config(known_nodes=teacher_nodes,
|
||||
network_middleware=click_config.middleware,
|
||||
network_middleware=character_config.network_middleware,
|
||||
**config_args)
|
||||
|
||||
#
|
||||
# Post-Init
|
||||
#
|
||||
|
||||
# TODO: Move to character configuration
|
||||
# Switch to character control emitter
|
||||
if click_config.json_ipc:
|
||||
CHARACTER.controller.emitter = JSONRPCStdoutEmitter(quiet=click_config.quiet)
|
||||
|
||||
# Federated
|
||||
if character_config.federated_only:
|
||||
click_config.emit(message="WARNING: Running in Federated mode", color='yellow')
|
||||
console_emitter(message="WARNING: Running in Federated mode", color='yellow')
|
||||
|
||||
return CHARACTER
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
import click
|
||||
from constant_sorrow.constants import NO_BLOCKCHAIN_CONNECTION
|
||||
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainInterface
|
||||
from nucypher.blockchain.eth.registry import EthereumContractRegistry
|
||||
from nucypher.characters.banners import ALICE_BANNER
|
||||
from nucypher.cli import actions, painting
|
||||
from nucypher.cli import types
|
||||
from nucypher.cli import actions, painting, types
|
||||
from nucypher.cli.actions import get_password
|
||||
from nucypher.cli.config import nucypher_click_config
|
||||
from nucypher.cli.types import NETWORK_PORT, EXISTING_READABLE_FILE, EIP55_CHECKSUM_ADDRESS
|
||||
from nucypher.config.characters import AliceConfiguration
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
|
||||
|
||||
@click.command()
|
||||
|
@ -24,6 +27,7 @@ from nucypher.config.characters import AliceConfiguration
|
|||
@click.option('--config-file', help="Path to configuration file", type=EXISTING_READABLE_FILE)
|
||||
@click.option('--provider-uri', help="Blockchain provider's URI", type=click.STRING)
|
||||
@click.option('--sync/--no-sync', default=True)
|
||||
@click.option('--device/--no-device', default=False)
|
||||
@click.option('--geth', '-G', help="Run using the built-in geth node", is_flag=True)
|
||||
@click.option('--poa', help="Inject POA middleware", is_flag=True, default=None)
|
||||
@click.option('--no-registry', help="Skip importing the default contract registry", is_flag=True)
|
||||
|
@ -68,6 +72,7 @@ def alice(click_config,
|
|||
poa,
|
||||
no_registry,
|
||||
registry_filepath,
|
||||
device,
|
||||
|
||||
# Alice
|
||||
bob_encrypting_key,
|
||||
|
@ -79,7 +84,7 @@ def alice(click_config,
|
|||
rate,
|
||||
duration,
|
||||
expiration,
|
||||
message_kit
|
||||
message_kit,
|
||||
|
||||
):
|
||||
|
||||
|
@ -117,7 +122,7 @@ def alice(click_config,
|
|||
if not config_root: # Flag
|
||||
config_root = click_config.config_file # Envvar
|
||||
|
||||
new_alice_config = AliceConfiguration.generate(password=click_config.get_password(confirm=True),
|
||||
new_alice_config = AliceConfiguration.generate(password=get_password(confirm=True),
|
||||
config_root=config_root,
|
||||
checksum_address=pay_with,
|
||||
domains={network} if network else None,
|
||||
|
@ -168,13 +173,12 @@ def alice(click_config,
|
|||
except FileNotFoundError:
|
||||
return actions.handle_missing_configuration_file(character_config_class=AliceConfiguration,
|
||||
config_file=config_file)
|
||||
|
||||
|
||||
ALICE = actions.make_cli_character(character_config=alice_config,
|
||||
click_config=click_config,
|
||||
dev=dev,
|
||||
teacher_uri=teacher_uri,
|
||||
min_stake=min_stake,
|
||||
sync=sync)
|
||||
min_stake=min_stake)
|
||||
|
||||
#
|
||||
# Admin Actions
|
||||
|
|
|
@ -2,6 +2,7 @@ import click
|
|||
|
||||
from nucypher.characters.banners import BOB_BANNER
|
||||
from nucypher.cli import actions, painting
|
||||
from nucypher.cli.actions import get_password
|
||||
from nucypher.cli.config import nucypher_click_config
|
||||
from nucypher.cli.types import NETWORK_PORT, EXISTING_READABLE_FILE, EIP55_CHECKSUM_ADDRESS
|
||||
from nucypher.config.characters import BobConfiguration
|
||||
|
@ -78,7 +79,7 @@ def bob(click_config,
|
|||
if not config_root: # Flag
|
||||
config_root = click_config.config_file # Envvar
|
||||
|
||||
new_bob_config = BobConfiguration.generate(password=click_config.get_password(confirm=True),
|
||||
new_bob_config = BobConfiguration.generate(password=get_password(confirm=True),
|
||||
config_root=config_root or DEFAULT_CONFIG_ROOT,
|
||||
checksum_address=pay_with,
|
||||
domains={network} if network else None,
|
||||
|
|
|
@ -3,9 +3,9 @@ import os
|
|||
import click
|
||||
from constant_sorrow.constants import NO_BLOCKCHAIN_CONNECTION
|
||||
|
||||
from nucypher.blockchain.eth.clients import NuCypherGethDevnetProcess
|
||||
from nucypher.characters.banners import FELIX_BANNER
|
||||
from nucypher.cli import actions, painting
|
||||
from nucypher.cli.actions import get_password, unlock_nucypher_keyring
|
||||
from nucypher.cli.config import nucypher_click_config
|
||||
from nucypher.cli.types import NETWORK_PORT, EXISTING_READABLE_FILE, EIP55_CHECKSUM_ADDRESS
|
||||
from nucypher.config.characters import FelixConfiguration
|
||||
|
@ -72,11 +72,8 @@ def felix(click_config,
|
|||
if not config_root: # Flag
|
||||
config_root = DEFAULT_CONFIG_ROOT # Envvar or init-only default
|
||||
|
||||
# Acquire Keyring Password
|
||||
new_password = click_config.get_password(confirm=True)
|
||||
|
||||
try:
|
||||
new_felix_config = FelixConfiguration.generate(password=new_password,
|
||||
new_felix_config = FelixConfiguration.generate(password=get_password(confirm=True),
|
||||
config_root=config_root,
|
||||
rest_host=host,
|
||||
rest_port=discovery_port,
|
||||
|
@ -123,12 +120,10 @@ def felix(click_config,
|
|||
try:
|
||||
|
||||
# Connect to Blockchain
|
||||
felix_config.connect_to_blockchain()
|
||||
felix_config.get_blockchain_interface()
|
||||
|
||||
# Authenticate
|
||||
password = click_config.get_password(confirm=False)
|
||||
click_config.unlock_keyring(character_configuration=felix_config,
|
||||
password=password)
|
||||
unlock_nucypher_keyring(character_configuration=felix_config, password=get_password(confirm=False))
|
||||
|
||||
# Produce Teacher Ursulas
|
||||
teacher_nodes = actions.load_seednodes(teacher_uris=[teacher_uri] if teacher_uri else None,
|
||||
|
|
|
@ -18,16 +18,13 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
|
||||
import click
|
||||
import socket
|
||||
|
||||
from constant_sorrow.constants import NO_BLOCKCHAIN_CONNECTION
|
||||
from twisted.internet import stdio
|
||||
|
||||
from nucypher.blockchain.eth.clients import NuCypherGethDevnetProcess, NuCypherGethGoerliProcess
|
||||
from nucypher.blockchain.eth.token import NU
|
||||
from nucypher.characters.banners import URSULA_BANNER
|
||||
from nucypher.cli import actions, painting
|
||||
from nucypher.cli.actions import UnknownIPAddress
|
||||
from nucypher.cli.actions import get_password
|
||||
from nucypher.cli.config import nucypher_click_config
|
||||
from nucypher.cli.processes import UrsulaCommandProtocol
|
||||
from nucypher.cli.types import (
|
||||
|
@ -36,8 +33,7 @@ from nucypher.cli.types import (
|
|||
EXISTING_READABLE_FILE,
|
||||
STAKE_DURATION,
|
||||
STAKE_EXTENSION,
|
||||
STAKE_VALUE,
|
||||
IPV4_ADDRESS)
|
||||
STAKE_VALUE)
|
||||
from nucypher.config.characters import UrsulaConfiguration
|
||||
from nucypher.utilities.sandbox.constants import (
|
||||
TEMPORARY_DOMAIN,
|
||||
|
@ -66,9 +62,9 @@ from nucypher.utilities.sandbox.constants import (
|
|||
@click.option('--config-file', help="Path to configuration file", type=EXISTING_READABLE_FILE)
|
||||
@click.option('--poa', help="Inject POA middleware", is_flag=True, default=None)
|
||||
@click.option('--sync/--no-sync', default=True)
|
||||
@click.option('--device/--no-device', default=False)
|
||||
@click.option('--geth', '-G', help="Run using the built-in geth node", is_flag=True)
|
||||
@click.option('--provider-uri', help="Blockchain provider's URI", type=click.STRING)
|
||||
@click.option('--recompile-solidity', help="Compile solidity from source when making a web3 connection", is_flag=True)
|
||||
@click.option('--no-registry', help="Skip importing the default contract registry", is_flag=True)
|
||||
@click.option('--registry-filepath', help="Custom contract registry filepath", type=EXISTING_READABLE_FILE)
|
||||
@click.option('--value', help="Token value of stake", type=click.INT)
|
||||
|
@ -98,7 +94,6 @@ def ursula(click_config,
|
|||
config_file,
|
||||
provider_uri,
|
||||
geth,
|
||||
recompile_solidity,
|
||||
no_registry,
|
||||
registry_filepath,
|
||||
value,
|
||||
|
@ -107,6 +102,7 @@ def ursula(click_config,
|
|||
list_,
|
||||
divide,
|
||||
sync,
|
||||
device,
|
||||
interactive,
|
||||
|
||||
) -> None:
|
||||
|
@ -178,9 +174,7 @@ def ursula(click_config,
|
|||
if not rest_host:
|
||||
rest_host = actions.determine_external_ip_address(force=force)
|
||||
|
||||
new_password = click_config.get_password(confirm=True)
|
||||
|
||||
ursula_config = UrsulaConfiguration.generate(password=new_password,
|
||||
ursula_config = UrsulaConfiguration.generate(password=get_password(confirm=True),
|
||||
config_root=config_root,
|
||||
rest_host=rest_host,
|
||||
rest_port=rest_port,
|
||||
|
@ -248,14 +242,12 @@ def ursula(click_config,
|
|||
raise click.BadOptionUsage(option_name='--dev', message=message)
|
||||
return actions.destroy_configuration(character_config=ursula_config, force=force)
|
||||
|
||||
|
||||
#
|
||||
# Make Ursula
|
||||
#
|
||||
|
||||
URSULA = actions.make_cli_character(character_config=ursula_config,
|
||||
click_config=click_config,
|
||||
sync=sync,
|
||||
min_stake=min_stake,
|
||||
teacher_uri=teacher_uri,
|
||||
dev=dev,
|
||||
|
|
|
@ -21,13 +21,10 @@ import collections
|
|||
import os
|
||||
|
||||
import click
|
||||
from constant_sorrow.constants import NO_PASSWORD, NO_BLOCKCHAIN_CONNECTION
|
||||
from nacl.exceptions import CryptoError
|
||||
from twisted.logger import Logger
|
||||
from twisted.logger import globalLogPublisher
|
||||
|
||||
from nucypher.config.constants import NUCYPHER_SENTRY_ENDPOINT
|
||||
from nucypher.config.node import CharacterConfiguration
|
||||
from nucypher.utilities.logging import (
|
||||
logToSentry,
|
||||
getTextFileObserver,
|
||||
|
@ -68,53 +65,6 @@ class NucypherClickConfig:
|
|||
self.quiet = False
|
||||
self.log = Logger(self.__class__.__name__)
|
||||
|
||||
# Auth
|
||||
self.__keyring_password = NO_PASSWORD
|
||||
|
||||
# Blockchain
|
||||
self.accounts = NO_BLOCKCHAIN_CONNECTION
|
||||
self.blockchain = NO_BLOCKCHAIN_CONNECTION
|
||||
|
||||
def connect_to_blockchain(self, character_configuration, sync_now: bool = True):
|
||||
character_configuration.connect_to_blockchain(sync_now=sync_now)
|
||||
character_configuration.connect_to_contracts()
|
||||
self.blockchain = character_configuration.blockchain
|
||||
self.accounts = self.blockchain.client.accounts
|
||||
|
||||
def get_password(self, confirm: bool = False) -> str:
|
||||
keyring_password = os.environ.get("NUCYPHER_KEYRING_PASSWORD", NO_PASSWORD)
|
||||
|
||||
if keyring_password is NO_PASSWORD: # Collect password, prefer env var
|
||||
prompt = "Enter keyring password"
|
||||
keyring_password = click.prompt(prompt, confirmation_prompt=confirm, hide_input=True)
|
||||
|
||||
self.__keyring_password = keyring_password
|
||||
return self.__keyring_password
|
||||
|
||||
def unlock_keyring(self,
|
||||
password: str,
|
||||
character_configuration: CharacterConfiguration,
|
||||
unlock_wallet: bool = True):
|
||||
|
||||
if not self.quiet:
|
||||
self.emit(message='Decrypting NuCypher keyring...', color='yellow')
|
||||
|
||||
if character_configuration.dev_mode:
|
||||
return True # Dev accounts are always unlocked
|
||||
|
||||
# NuCypher
|
||||
try:
|
||||
character_configuration.attach_keyring()
|
||||
character_configuration.keyring.unlock(password=password) # Takes ~3 seconds, ~1GB Ram
|
||||
except CryptoError:
|
||||
raise character_configuration.keyring.AuthenticationFailed
|
||||
|
||||
# Ethereum Client # TODO : Integrate with Powers API
|
||||
if not character_configuration.federated_only and unlock_wallet:
|
||||
self.emit(message='Decrypting Ethereum Node Keyring...', color='yellow')
|
||||
character_configuration.blockchain.client.unlock_account(address=character_configuration.checksum_address,
|
||||
password=password)
|
||||
|
||||
@classmethod
|
||||
def attach_emitter(cls, emitter) -> None:
|
||||
cls.__emitter = emitter
|
||||
|
@ -129,9 +79,6 @@ class NucypherDeployerClickConfig(NucypherClickConfig):
|
|||
__secrets = ('staker_secret', 'policy_secret', 'escrow_proxy_secret', 'adjudicator_secret')
|
||||
Secrets = collections.namedtuple('Secrets', __secrets)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def collect_deployment_secrets(self) -> Secrets:
|
||||
|
||||
# Deployment Environment Variables
|
||||
|
@ -159,10 +106,10 @@ class NucypherDeployerClickConfig(NucypherClickConfig):
|
|||
hide_input=True,
|
||||
confirmation_prompt=True)
|
||||
|
||||
secrets = self.Secrets(staker_secret=self.staking_escrow_deployment_secret, # type: str
|
||||
policy_secret=self.policy_manager_deployment_secret, # type: str
|
||||
escrow_proxy_secret=self.user_escrow_proxy_deployment_secret, # type: str
|
||||
adjudicator_secret=self.adjudicator_deployment_secret # type: str
|
||||
secrets = self.Secrets(staker_secret=self.staking_escrow_deployment_secret, # type: str
|
||||
policy_secret=self.policy_manager_deployment_secret, # type: str
|
||||
escrow_proxy_secret=self.user_escrow_proxy_deployment_secret, # type: str
|
||||
adjudicator_secret=self.adjudicator_deployment_secret # type: str
|
||||
)
|
||||
return secrets
|
||||
|
||||
|
|
|
@ -19,19 +19,18 @@ import time
|
|||
|
||||
import click
|
||||
import maya
|
||||
from web3.exceptions import TimeExhausted
|
||||
|
||||
from nucypher.blockchain.eth.actors import Deployer
|
||||
from nucypher.blockchain.eth.agents import NucypherTokenAgent
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainInterface, BlockchainDeployerInterface
|
||||
from nucypher.blockchain.eth.clients import NuCypherGethDevnetProcess
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface
|
||||
from nucypher.blockchain.eth.registry import EthereumContractRegistry
|
||||
from nucypher.blockchain.eth.sol.compile import SolidityCompiler
|
||||
from nucypher.characters.banners import NU_BANNER
|
||||
from nucypher.cli.actions import get_password
|
||||
from nucypher.cli.config import nucypher_deployer_config
|
||||
from nucypher.cli.types import EIP55_CHECKSUM_ADDRESS, EXISTING_READABLE_FILE
|
||||
from nucypher.config.constants import DEFAULT_CONFIG_ROOT
|
||||
from nucypher.crypto.powers import BlockchainPower
|
||||
|
||||
|
||||
@click.command()
|
||||
|
@ -42,6 +41,7 @@ from nucypher.crypto.powers import BlockchainPower
|
|||
@click.option('--provider-uri', help="Blockchain provider's URI", type=click.STRING)
|
||||
@click.option('--geth', '-G', help="Run using the built-in geth node", is_flag=True)
|
||||
@click.option('--sync/--no-sync', default=True)
|
||||
@click.option('--device/--no-device', default=False) # TODO: Make True by default.
|
||||
@click.option('--enode', help="An ethereum bootnode enode address to start learning from", type=click.STRING)
|
||||
@click.option('--config-root', help="Custom configuration directory", type=click.Path())
|
||||
@click.option('--contract-name', help="Deploy a single contract by name", type=click.STRING)
|
||||
|
@ -70,6 +70,7 @@ def deploy(click_config,
|
|||
recipient_address,
|
||||
config_root,
|
||||
sync,
|
||||
device,
|
||||
force):
|
||||
"""Manage contract and registry deployment"""
|
||||
|
||||
|
@ -104,9 +105,9 @@ def deploy(click_config,
|
|||
blockchain = BlockchainDeployerInterface(provider_uri=provider_uri,
|
||||
poa=poa,
|
||||
registry=registry,
|
||||
compiler=SolidityCompiler(),
|
||||
fetch_registry=False,
|
||||
sync_now=sync)
|
||||
compiler=SolidityCompiler())
|
||||
|
||||
blockchain.connect(fetch_registry=False, sync_now=sync)
|
||||
|
||||
#
|
||||
# Deployment Actor
|
||||
|
@ -123,9 +124,13 @@ def deploy(click_config,
|
|||
if not force:
|
||||
click.confirm("Selected {} - Continue?".format(deployer_address), abort=True)
|
||||
|
||||
# TODO: Integrate with Deployer Actor (Character)
|
||||
blockchain.transacting_power = BlockchainPower(blockchain=blockchain, account=deployer_address)
|
||||
deployer = Deployer(blockchain=blockchain, deployer_address=deployer_address)
|
||||
password = None
|
||||
if not device and not blockchain.client.is_local:
|
||||
password = get_password(confirm=False)
|
||||
|
||||
deployer = Deployer(blockchain=blockchain,
|
||||
client_password=password,
|
||||
deployer_address=deployer_address)
|
||||
|
||||
# Verify ETH Balance
|
||||
click.secho(f"\n\nDeployer ETH balance: {deployer.eth_balance}")
|
||||
|
@ -133,11 +138,6 @@ def deploy(click_config,
|
|||
click.secho("Deployer address has no ETH.", fg='red', bold=True)
|
||||
raise click.Abort()
|
||||
|
||||
if not blockchain.client.is_local:
|
||||
# (~ dev mode; Assume accounts are already unlocked)
|
||||
password = click.prompt("Enter ETH node password", hide_input=True)
|
||||
blockchain.client.unlockAccount(deployer_address, password)
|
||||
|
||||
# Add ETH Bootnode or Peer
|
||||
if enode:
|
||||
if geth:
|
||||
|
@ -297,12 +297,6 @@ def deploy(click_config,
|
|||
txhash = token_agent.transfer(amount=amount, sender_address=token_agent.contract_address, target_address=recipient_address)
|
||||
click.secho(f"OK | {txhash}")
|
||||
|
||||
elif action == "destroy-registry":
|
||||
registry_filepath = deployer.blockchain.registry.filepath
|
||||
click.confirm(f"Are you absolutely sure you want to destroy the contract registry at {registry_filepath}?", abort=True)
|
||||
os.remove(registry_filepath)
|
||||
click.secho(f"Successfully destroyed {registry_filepath}", fg='red')
|
||||
|
||||
else:
|
||||
raise click.BadArgumentUsage(message=f"Unknown action '{action}'")
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@ def status(click_config, config_file):
|
|||
#
|
||||
ursula_config = UrsulaConfiguration.from_configuration_file(filepath=config_file)
|
||||
if not ursula_config.federated_only:
|
||||
ursula_config.connect_to_blockchain(provider_uri=ursula_config.provider_uri)
|
||||
ursula_config.connect_to_contracts()
|
||||
ursula_config.get_blockchain_interface(provider_uri=ursula_config.provider_uri)
|
||||
ursula_config.acquire_agency()
|
||||
|
||||
# Contracts
|
||||
paint_contract_status(ursula_config=ursula_config, click_config=click_config)
|
||||
|
|
|
@ -22,6 +22,7 @@ import stat
|
|||
from json import JSONDecodeError
|
||||
from typing import ClassVar, Tuple, Callable, Union, Dict, List
|
||||
|
||||
from constant_sorrow.constants import FEDERATED_ADDRESS
|
||||
from constant_sorrow.constants import KEYRING_LOCKED
|
||||
from cryptography import x509
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
|
@ -34,13 +35,12 @@ from cryptography.hazmat.primitives.serialization import Encoding
|
|||
from cryptography.x509 import Certificate
|
||||
from eth_account import Account
|
||||
from eth_keys import KeyAPI as EthKeyAPI
|
||||
from eth_utils import to_checksum_address, is_checksum_address
|
||||
from eth_utils import to_checksum_address
|
||||
from nacl.exceptions import CryptoError
|
||||
from nacl.secret import SecretBox
|
||||
from twisted.logger import Logger
|
||||
from umbral.keys import UmbralPrivateKey, UmbralPublicKey, UmbralKeyingMaterial, derive_key_from_password
|
||||
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainInterface
|
||||
from nucypher.config.constants import DEFAULT_CONFIG_ROOT
|
||||
from nucypher.crypto.api import generate_self_signed_certificate
|
||||
from nucypher.crypto.constants import BLAKE2B
|
||||
|
@ -49,10 +49,8 @@ from nucypher.crypto.powers import (
|
|||
DecryptingPower,
|
||||
KeyPairBasedPower,
|
||||
DerivedKeyBasedPower,
|
||||
BlockchainPower
|
||||
TransactingPower
|
||||
)
|
||||
|
||||
from constant_sorrow.constants import FEDERATED_ADDRESS
|
||||
from nucypher.network.server import TLSHostingPower
|
||||
|
||||
FILE_ENCODING = 'utf-8'
|
||||
|
@ -499,10 +497,6 @@ class NucypherKeyring:
|
|||
keying_material = SecretBox(wrap_key).decrypt(key_data['key'])
|
||||
new_cryptopower = power_class(keying_material=keying_material)
|
||||
|
||||
elif power_class is BlockchainPower:
|
||||
# new_cryptopower = power_class(account=self.checksum_address)
|
||||
pass # TODO: Needs refactoring with TransactingPower
|
||||
|
||||
else:
|
||||
failure_message = "{} is an invalid type for deriving a CryptoPower.".format(power_class.__name__)
|
||||
raise ValueError(failure_message)
|
||||
|
@ -514,13 +508,12 @@ class NucypherKeyring:
|
|||
#
|
||||
@classmethod
|
||||
def generate(cls,
|
||||
checksum_address: str,
|
||||
password: str,
|
||||
encrypting: bool,
|
||||
rest: bool,
|
||||
host: str = None,
|
||||
curve: EllipticCurve = None,
|
||||
federated: bool = False,
|
||||
checksum_address: str = None,
|
||||
keyring_root: str = None,
|
||||
) -> 'NucypherKeyring':
|
||||
"""
|
||||
|
@ -550,14 +543,14 @@ class NucypherKeyring:
|
|||
|
||||
keyring_args = dict()
|
||||
|
||||
if checksum_address:
|
||||
if checksum_address is not FEDERATED_ADDRESS:
|
||||
# Addresses read from some node keyrings (clients) are *not* returned in checksum format.
|
||||
checksum_address = to_checksum_address(checksum_address)
|
||||
|
||||
if encrypting is True:
|
||||
signing_private_key, signing_public_key = _generate_signing_keys()
|
||||
|
||||
if federated and not checksum_address:
|
||||
if checksum_address is FEDERATED_ADDRESS:
|
||||
uncompressed_bytes = signing_public_key.to_bytes(is_compressed=False)
|
||||
without_prefix = uncompressed_bytes[1:]
|
||||
verifying_key_as_eth_key = EthKeyAPI.PublicKey(without_prefix)
|
||||
|
|
|
@ -26,7 +26,8 @@ from constant_sorrow.constants import (
|
|||
NO_BLOCKCHAIN_CONNECTION,
|
||||
LIVE_CONFIGURATION,
|
||||
NO_KEYRING_ATTACHED,
|
||||
DEVELOPMENT_CONFIGURATION
|
||||
DEVELOPMENT_CONFIGURATION,
|
||||
FEDERATED_ADDRESS
|
||||
)
|
||||
from twisted.logger import Logger
|
||||
from umbral.signing import Signature
|
||||
|
@ -126,7 +127,6 @@ class CharacterConfiguration(BaseConfiguration):
|
|||
self.provider_uri = provider_uri or self.DEFAULT_PROVIDER_URI
|
||||
self.provider_process = provider_process or NO_BLOCKCHAIN_CONNECTION
|
||||
self.blockchain = NO_BLOCKCHAIN_CONNECTION.bool_value(False)
|
||||
self.accounts = NO_BLOCKCHAIN_CONNECTION
|
||||
self.token_agent = NO_BLOCKCHAIN_CONNECTION
|
||||
self.staking_agent = NO_BLOCKCHAIN_CONNECTION
|
||||
self.policy_agent = NO_BLOCKCHAIN_CONNECTION
|
||||
|
@ -178,24 +178,15 @@ class CharacterConfiguration(BaseConfiguration):
|
|||
def dev_mode(self) -> bool:
|
||||
return self.__dev_mode
|
||||
|
||||
@property
|
||||
def known_nodes(self):
|
||||
return self.__fleet_state
|
||||
|
||||
def connect_to_blockchain(self, sync_now: bool = False) -> None:
|
||||
def get_blockchain_interface(self) -> None:
|
||||
if self.federated_only:
|
||||
raise CharacterConfiguration.ConfigurationError("Cannot connect to blockchain in federated mode")
|
||||
|
||||
self.blockchain = BlockchainInterface(provider_uri=self.provider_uri,
|
||||
poa=self.poa,
|
||||
fetch_registry=True,
|
||||
provider_process=self.provider_process,
|
||||
sync_now=sync_now)
|
||||
provider_process=self.provider_process)
|
||||
|
||||
# Read Ethereum Node Keyring
|
||||
self.accounts = self.blockchain.client.accounts
|
||||
|
||||
def connect_to_contracts(self) -> None:
|
||||
def acquire_agency(self) -> None:
|
||||
self.token_agent = NucypherTokenAgent(blockchain=self.blockchain)
|
||||
self.staking_agent = StakingEscrowAgent(blockchain=self.blockchain)
|
||||
self.policy_agent = PolicyAgent(blockchain=self.blockchain)
|
||||
|
@ -327,7 +318,7 @@ class CharacterConfiguration(BaseConfiguration):
|
|||
node_storage=self.node_storage,
|
||||
crypto_power_ups=self.derive_node_power_ups())
|
||||
if not self.federated_only:
|
||||
self.connect_to_blockchain()
|
||||
self.get_blockchain_interface()
|
||||
payload.update(blockchain=self.blockchain)
|
||||
return payload
|
||||
|
||||
|
@ -424,9 +415,11 @@ class CharacterConfiguration(BaseConfiguration):
|
|||
|
||||
def write_keyring(self, password: str, **generation_kwargs) -> NucypherKeyring:
|
||||
|
||||
# Note: It is assumed the blockchain is not yet available.
|
||||
if not self.federated_only:
|
||||
if self.federated_only:
|
||||
checksum_address = FEDERATED_ADDRESS
|
||||
|
||||
else:
|
||||
# Note: It is assumed the blockchain interface is not yet connected.
|
||||
if self.provider_process:
|
||||
|
||||
# Generate Geth's "datadir"
|
||||
|
@ -439,17 +432,14 @@ class CharacterConfiguration(BaseConfiguration):
|
|||
elif self.checksum_address not in self.provider_process.accounts():
|
||||
raise self.ConfigurationError(f'Unknown Account {self.checksum_address}')
|
||||
|
||||
# Determine etherbase (web3)
|
||||
elif not self.checksum_address:
|
||||
self.connect_to_blockchain()
|
||||
if not self.blockchain.client.accounts:
|
||||
raise self.ConfigurationError(f'Web3 provider "{self.provider_uri}" does not have any accounts')
|
||||
self.checksum_address = self.blockchain.client.etherbase
|
||||
raise self.ConfigurationError(f'No checksum address provided for decentralized configuration.')
|
||||
|
||||
checksum_address = self.checksum_address
|
||||
|
||||
self.keyring = NucypherKeyring.generate(password=password,
|
||||
keyring_root=self.keyring_root,
|
||||
checksum_address=self.checksum_address,
|
||||
federated=self.federated_only,
|
||||
checksum_address=checksum_address,
|
||||
**generation_kwargs)
|
||||
|
||||
self.checksum_address = self.keyring.account
|
||||
|
|
|
@ -14,16 +14,18 @@ GNU Affero General Public License for more details.
|
|||
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 inspect
|
||||
|
||||
from eth_keys.datatypes import PublicKey, Signature as EthSignature
|
||||
from eth_keys.exceptions import BadSignature
|
||||
from eth_utils import keccak
|
||||
|
||||
import inspect
|
||||
from typing import List, Tuple, Optional
|
||||
|
||||
from constant_sorrow.constants import NO_BLOCKCHAIN_CONNECTION
|
||||
from cytoolz.dicttoolz import dissoc
|
||||
from eth_account._utils.transactions import assert_valid_fields
|
||||
from hexbytes import HexBytes
|
||||
from umbral import pre
|
||||
from umbral.keys import UmbralPublicKey, UmbralPrivateKey, UmbralKeyingMaterial
|
||||
|
||||
from nucypher.crypto.signing import InvalidSignature
|
||||
from nucypher.keystore import keypairs
|
||||
from nucypher.keystore.keypairs import SigningKeypair, DecryptingKeypair
|
||||
|
||||
|
@ -40,25 +42,32 @@ class NoDecryptingPower(PowerUpError):
|
|||
pass
|
||||
|
||||
|
||||
class NoBlockchainPower(PowerUpError):
|
||||
class NoTransactingPower(PowerUpError):
|
||||
pass
|
||||
|
||||
|
||||
class CryptoPower(object):
|
||||
def __init__(self, power_ups: list = None) -> None:
|
||||
self._power_ups = {} # type: dict
|
||||
self.__power_ups = {} # type: dict
|
||||
# TODO: The keys here will actually be IDs for looking up in a KeyStore.
|
||||
self.public_keys = {} # type: dict
|
||||
|
||||
if power_ups is not None:
|
||||
for power_up in power_ups:
|
||||
self.consume_power_up(power_up)
|
||||
else:
|
||||
power_ups = [] # default
|
||||
|
||||
def consume_power_up(self, power_up):
|
||||
def __contains__(self, item):
|
||||
try:
|
||||
self.power_ups(item)
|
||||
except PowerUpError:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def consume_power_up(self, power_up, *args, **kwargs):
|
||||
if isinstance(power_up, CryptoPowerUp):
|
||||
power_up_class = power_up.__class__
|
||||
power_up.activate(*args, **kwargs)
|
||||
power_up_instance = power_up
|
||||
elif CryptoPowerUp in inspect.getmro(power_up):
|
||||
power_up_class = power_up
|
||||
|
@ -67,69 +76,115 @@ class CryptoPower(object):
|
|||
raise TypeError(
|
||||
("power_up must be a subclass of CryptoPowerUp or an instance "
|
||||
"of a CryptoPowerUp subclass."))
|
||||
self._power_ups[power_up_class] = power_up_instance
|
||||
self.__power_ups[power_up_class] = power_up_instance
|
||||
|
||||
if power_up.confers_public_key:
|
||||
self.public_keys[power_up_class] = power_up_instance.public_key()
|
||||
|
||||
def power_ups(self, power_up_class):
|
||||
try:
|
||||
return self._power_ups[power_up_class]
|
||||
return self.__power_ups[power_up_class]
|
||||
except KeyError:
|
||||
raise power_up_class.not_found_error
|
||||
|
||||
|
||||
class CryptoPowerUp(object):
|
||||
class CryptoPowerUp:
|
||||
"""
|
||||
Gives you MORE CryptoPower!
|
||||
"""
|
||||
confers_public_key = False
|
||||
|
||||
def activate(self, *args, **kwargs):
|
||||
return
|
||||
|
||||
class BlockchainPower(CryptoPowerUp):
|
||||
|
||||
class TransactingPower(CryptoPowerUp):
|
||||
"""
|
||||
Allows for transacting on a Blockchain via web3 backend.
|
||||
"""
|
||||
not_found_error = NoBlockchainPower
|
||||
not_found_error = NoTransactingPower
|
||||
|
||||
def __init__(self, blockchain: 'Blockchain', account: str, device = None) -> None:
|
||||
class NoBlockchainConnection(PowerUpError):
|
||||
pass
|
||||
|
||||
class AccountLocked(PowerUpError):
|
||||
pass
|
||||
|
||||
class InvalidSigningRequest(PowerUpError):
|
||||
pass
|
||||
|
||||
def __init__(self,
|
||||
blockchain,
|
||||
account: str,
|
||||
password: str = None):
|
||||
"""
|
||||
Instantiates a BlockchainPower for the given account id.
|
||||
Instantiates a TransactingPower for the given checksum_address.
|
||||
"""
|
||||
self.blockchain = blockchain
|
||||
self.account = account
|
||||
self.device = device
|
||||
self.is_unlocked = False
|
||||
if blockchain.is_connected:
|
||||
self.client = blockchain.client
|
||||
else:
|
||||
self.client = NO_BLOCKCHAIN_CONNECTION
|
||||
|
||||
def unlock_account(self, password: str):
|
||||
"""
|
||||
Unlocks the account for the specified duration. If no duration is
|
||||
provided, it will remain unlocked indefinitely.
|
||||
"""
|
||||
self.is_unlocked = self.blockchain.client.unlock_account(self.account, password)
|
||||
if not self.is_unlocked:
|
||||
raise PowerUpError("Failed to unlock account {}".format(self.account))
|
||||
self.account = account
|
||||
self.device = True if not password else False
|
||||
self.__password = password
|
||||
self.__unlocked = False
|
||||
|
||||
def __del__(self):
|
||||
self.lock_account()
|
||||
|
||||
@property
|
||||
def is_unlocked(self) -> bool:
|
||||
return self.__unlocked
|
||||
|
||||
@property
|
||||
def is_active(self) -> bool:
|
||||
"""Returns True if the blockchain currently has this transacting power attached."""
|
||||
return self.blockchain.transacting_power == self
|
||||
|
||||
def activate(self, password: str = None):
|
||||
"""Be Consumed"""
|
||||
self.blockchain.connect()
|
||||
self.client = self.blockchain.client # Connect
|
||||
self.unlock_account(password=password or self.__password)
|
||||
self.blockchain.transacting_power = self # Attach
|
||||
self.__password = None # Discard
|
||||
|
||||
def lock_account(self):
|
||||
if self.device:
|
||||
# TODO: Force Disconnect Devices
|
||||
pass
|
||||
else:
|
||||
_result = self.client.lock_account(address=self.account)
|
||||
self.__unlocked = False
|
||||
|
||||
def unlock_account(self, password: str = None):
|
||||
if self.device:
|
||||
unlocked = True
|
||||
else:
|
||||
if self.client is NO_BLOCKCHAIN_CONNECTION:
|
||||
raise self.NoBlockchainConnection
|
||||
unlocked = self.client.unlock_account(address=self.account, password=password)
|
||||
self.__unlocked = unlocked
|
||||
|
||||
def sign_message(self, message: bytes) -> bytes:
|
||||
"""
|
||||
Signs the message with the private key of the BlockchainPower.
|
||||
Signs the message with the private key of the TransactingPower.
|
||||
"""
|
||||
if not self.is_unlocked:
|
||||
raise PowerUpError("Account is not unlocked.")
|
||||
signature = self.blockchain.client.sign_message(account=self.account, message=message)
|
||||
raise self.AccountLocked("Failed to unlock account {}".format(self.account))
|
||||
signature = self.client.sign_message(account=self.account, message=message)
|
||||
return signature
|
||||
|
||||
def sign_transaction(self, unsigned_transaction: dict):
|
||||
if self.device:
|
||||
# TODO: Implement TrustedDevice
|
||||
raise NotImplementedError
|
||||
|
||||
# This check is also performed client-side.
|
||||
sender_address = unsigned_transaction['from']
|
||||
if sender_address != self.account:
|
||||
raise PowerUpError(f"'from' field must match account {self.account}, but it was {sender_address}")
|
||||
signed_transaction = self.blockchain.client.sign_transaction(transaction=unsigned_transaction, account=self.account)
|
||||
return signed_transaction
|
||||
def sign_transaction(self, unsigned_transaction: dict) -> HexBytes:
|
||||
"""
|
||||
Signs the transaction with the private key of the TransactingPower.
|
||||
"""
|
||||
if not self.is_unlocked:
|
||||
raise self.AccountLocked("Failed to unlock account {}".format(self.account))
|
||||
signed_raw_transaction = self.blockchain.client.sign_transaction(transaction=unsigned_transaction)
|
||||
return signed_raw_transaction
|
||||
|
||||
|
||||
class KeyPairBasedPower(CryptoPowerUp):
|
||||
|
@ -138,25 +193,24 @@ class KeyPairBasedPower(CryptoPowerUp):
|
|||
_default_private_key_class = UmbralPrivateKey
|
||||
|
||||
def __init__(self,
|
||||
pubkey: UmbralPublicKey = None,
|
||||
public_key: UmbralPublicKey = None,
|
||||
keypair: keypairs.Keypair = None,
|
||||
) -> None:
|
||||
if keypair and pubkey:
|
||||
raise ValueError(
|
||||
"Pass keypair or pubkey_bytes (or neither), but not both.")
|
||||
if keypair and public_key:
|
||||
raise ValueError("Pass keypair or pubkey_bytes (or neither), but not both.")
|
||||
elif keypair:
|
||||
self.keypair = keypair
|
||||
else:
|
||||
# They didn't pass a keypair; we'll make one with the bytes or
|
||||
# UmbralPublicKey if they provided such a thing.
|
||||
if pubkey:
|
||||
if public_key:
|
||||
try:
|
||||
public_key = pubkey.as_umbral_pubkey()
|
||||
public_key = public_key.as_umbral_pubkey()
|
||||
except AttributeError:
|
||||
try:
|
||||
public_key = UmbralPublicKey.from_bytes(pubkey)
|
||||
public_key = UmbralPublicKey.from_bytes(public_key)
|
||||
except TypeError:
|
||||
public_key = pubkey
|
||||
public_key = public_key
|
||||
self.keypair = self._keypair_class(
|
||||
public_key=public_key)
|
||||
else:
|
||||
|
@ -168,10 +222,8 @@ class KeyPairBasedPower(CryptoPowerUp):
|
|||
try:
|
||||
return getattr(self.keypair, item)
|
||||
except AttributeError:
|
||||
raise PowerUpError(
|
||||
"This {} has a keypair, {}, which doesn't provide {}.".format(self.__class__,
|
||||
self.keypair.__class__,
|
||||
item))
|
||||
message = f"This {self.__class__} has a keypair, {self.keypair.__class__}, which doesn't provide {item}."
|
||||
raise PowerUpError(message)
|
||||
else:
|
||||
raise PowerUpError("This {} doesn't provide {}.".format(self.__class__, item))
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ from nucypher.blockchain.eth.interfaces import BlockchainInterface
|
|||
from nucypher.config.constants import SeednodeMetadata
|
||||
from nucypher.config.storages import ForgetfulNodeStorage
|
||||
from nucypher.crypto.api import keccak_digest, verify_eip_191, recover_address_eip_191
|
||||
from nucypher.crypto.powers import BlockchainPower, SigningPower, DecryptingPower, NoSigningPower
|
||||
from nucypher.crypto.powers import TransactingPower, SigningPower, DecryptingPower, NoSigningPower
|
||||
from nucypher.crypto.signing import signature_splitter
|
||||
from nucypher.network import LEARNING_LOOP_VERSION
|
||||
from nucypher.network.exceptions import NodeSeemsToBeDown
|
||||
|
@ -915,7 +915,7 @@ class Teacher:
|
|||
self.__worker_address = None
|
||||
|
||||
if substantiate_immediately:
|
||||
# TODO: #1091
|
||||
# TODO: #1091 When is_me and not federated_only, the stamp is substantiated twice
|
||||
self.substantiate_stamp(client_password=password)
|
||||
|
||||
class InvalidNode(SuspiciousActivity):
|
||||
|
@ -1149,13 +1149,12 @@ class Teacher:
|
|||
signature=self.decentralized_identity_evidence)
|
||||
return self.__worker_address
|
||||
|
||||
def substantiate_stamp(self, client_password: str):
|
||||
# TODO: #1092 - TransactingPower
|
||||
blockchain_power = self._crypto_power.power_ups(BlockchainPower)
|
||||
blockchain_power.unlock_account(password=client_password) # TODO: #349
|
||||
signature = blockchain_power.sign_message(message=bytes(self.stamp))
|
||||
def substantiate_stamp(self, client_password: str = None):
|
||||
transacting_power = self._crypto_power.power_ups(TransactingPower)
|
||||
transacting_power.unlock_account(password=client_password) # TODO: #349
|
||||
signature = transacting_power.sign_message(message=bytes(self.stamp))
|
||||
self.__decentralized_identity_evidence = signature
|
||||
self.__worker_address = blockchain_power.account
|
||||
self.__worker_address = transacting_power.account
|
||||
|
||||
#
|
||||
# Interface
|
||||
|
|
|
@ -32,7 +32,7 @@ from nucypher.blockchain.eth.sol.compile import SolidityCompiler
|
|||
from nucypher.blockchain.eth.token import NU
|
||||
from nucypher.blockchain.eth.utils import epoch_to_period
|
||||
from nucypher.config.constants import BASE_DIR
|
||||
from nucypher.crypto.powers import BlockchainPower
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
from nucypher.utilities.sandbox.constants import (
|
||||
NUMBER_OF_ETH_TEST_ACCOUNTS,
|
||||
NUMBER_OF_STAKERS_IN_BLOCKCHAIN_TESTS,
|
||||
|
@ -52,7 +52,7 @@ def token_airdrop(token_agent, amount: NU, origin: str, addresses: List[str]):
|
|||
args = {'from': origin, 'gasPrice': token_agent.blockchain.client.gas_price}
|
||||
for address in addresses:
|
||||
contract_function = token_agent.contract.functions.transfer(address, int(amount))
|
||||
_receipt = token_agent.blockchain.send_transaction(transaction_function=contract_function,
|
||||
_receipt = token_agent.blockchain.send_transaction(contract_function=contract_function,
|
||||
sender_address=origin,
|
||||
payload=args)
|
||||
yield _receipt
|
||||
|
@ -110,12 +110,13 @@ class TesterBlockchain(BlockchainDeployerInterface):
|
|||
*args, **kwargs)
|
||||
|
||||
self.log = Logger("test-blockchain")
|
||||
self.connect()
|
||||
|
||||
# Generate additional ethereum accounts for testing
|
||||
population = test_accounts
|
||||
enough_accounts = len(self.w3.eth.accounts) >= population
|
||||
enough_accounts = len(self.client.accounts) >= population
|
||||
if not enough_accounts:
|
||||
accounts_to_make = population - len(self.w3.eth.accounts)
|
||||
accounts_to_make = population - len(self.client.accounts)
|
||||
self.__generate_insecure_unlocked_accounts(quantity=accounts_to_make)
|
||||
assert test_accounts == len(self.w3.eth.accounts)
|
||||
|
||||
|
@ -212,8 +213,10 @@ class TesterBlockchain(BlockchainDeployerInterface):
|
|||
"""For use with metric testing scripts"""
|
||||
|
||||
testerchain = cls(compiler=SolidityCompiler())
|
||||
power = BlockchainPower(blockchain=testerchain, account=testerchain.client.etherbase)
|
||||
power.unlock_account(password=INSECURE_DEVELOPMENT_PASSWORD)
|
||||
power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=testerchain.etherbase_account)
|
||||
power.activate()
|
||||
testerchain.transacting_power = power
|
||||
|
||||
origin = testerchain.client.etherbase
|
||||
|
|
|
@ -23,11 +23,12 @@ from nucypher.blockchain.eth.interfaces import BlockchainInterface
|
|||
from nucypher.blockchain.eth.token import StakeTracker
|
||||
from nucypher.characters.lawful import Ursula
|
||||
from nucypher.config.characters import UrsulaConfiguration
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
from nucypher.utilities.sandbox.constants import (
|
||||
MOCK_KNOWN_URSULAS_CACHE,
|
||||
MOCK_URSULA_STARTING_PORT,
|
||||
NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK,
|
||||
MOCK_URSULA_DB_FILEPATH)
|
||||
MOCK_URSULA_DB_FILEPATH, INSECURE_DEVELOPMENT_PASSWORD)
|
||||
|
||||
|
||||
def make_federated_ursulas(ursula_config: UrsulaConfiguration,
|
||||
|
|
|
@ -15,7 +15,8 @@ def test_geth_EIP_191_client_signature_integration(geth_dev_node):
|
|||
pytest.skip("Do not run Geth nodes in CI")
|
||||
|
||||
# Start a geth process
|
||||
blockchain = BlockchainInterface(provider_process=geth_dev_node, sync_now=False)
|
||||
blockchain = BlockchainInterface(provider_process=geth_dev_node)
|
||||
blockchain.connect(fetch_registry=False, sync_now=False)
|
||||
|
||||
# Sign a message (RPC) and verify it.
|
||||
etherbase = blockchain.client.accounts[0]
|
||||
|
|
|
@ -86,7 +86,9 @@ class GanacheClientTestInterface(BlockchainInterfaceTestBase):
|
|||
|
||||
|
||||
def test_geth_web3_client():
|
||||
interface = GethClientTestBlockchain(provider_uri='file:///ipc.geth', sync_now=False)
|
||||
interface = GethClientTestBlockchain(provider_uri='file:///ipc.geth')
|
||||
interface.connect(fetch_registry=False, sync_now=False)
|
||||
|
||||
assert isinstance(interface.client, GethClient)
|
||||
assert interface.client.node_technology == 'Geth'
|
||||
assert interface.client.node_version == 'v1.4.11-stable-fed692f6'
|
||||
|
@ -98,7 +100,9 @@ def test_geth_web3_client():
|
|||
|
||||
|
||||
def test_parity_web3_client():
|
||||
interface = ParityClientTestInterface(provider_uri='file:///ipc.parity', sync_now=False)
|
||||
interface = ParityClientTestInterface(provider_uri='file:///ipc.parity')
|
||||
interface.connect(fetch_registry=False, sync_now=False)
|
||||
|
||||
assert isinstance(interface.client, ParityClient)
|
||||
assert interface.client.node_technology == 'Parity-Ethereum'
|
||||
assert interface.client.node_version == 'v2.5.1-beta-e0141f8-20190510'
|
||||
|
@ -107,7 +111,9 @@ def test_parity_web3_client():
|
|||
|
||||
|
||||
def test_ganache_web3_client():
|
||||
interface = GanacheClientTestInterface(provider_uri='http://ganache:8445', sync_now=False)
|
||||
interface = GanacheClientTestInterface(provider_uri='http://ganache:8445')
|
||||
interface.connect(fetch_registry=False, sync_now=False)
|
||||
|
||||
assert isinstance(interface.client, GanacheClient)
|
||||
assert interface.client.node_technology == 'EthereumJS TestRPC'
|
||||
assert interface.client.node_version == 'v2.1.5'
|
||||
|
|
|
@ -21,13 +21,17 @@ import pytest
|
|||
from web3.contract import Contract
|
||||
|
||||
from nucypher.blockchain.eth.deployers import DispatcherDeployer
|
||||
from nucypher.crypto.powers import BlockchainPower
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
from nucypher.utilities.sandbox.constants import INSECURE_DEVELOPMENT_PASSWORD
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def escrow(testerchain):
|
||||
# Mock Powerup consumption (Deployer)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=testerchain.etherbase_account)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=testerchain.etherbase_account)
|
||||
testerchain.transacting_power.activate()
|
||||
escrow, _ = testerchain.deploy_contract('StakingEscrowForAdjudicatorMock')
|
||||
return escrow
|
||||
|
||||
|
|
|
@ -22,10 +22,9 @@ import pytest
|
|||
from web3.auto import w3
|
||||
|
||||
from nucypher.blockchain.eth.actors import Deployer
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface
|
||||
from nucypher.blockchain.eth.registry import InMemoryEthereumContractRegistry, InMemoryAllocationRegistry
|
||||
from nucypher.blockchain.eth.registry import InMemoryAllocationRegistry
|
||||
from nucypher.blockchain.eth.sol.compile import SolidityCompiler
|
||||
from nucypher.crypto.powers import BlockchainPower
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
# Prevents TesterBlockchain to be picked up by py.test as a test class
|
||||
from nucypher.utilities.sandbox.blockchain import TesterBlockchain as _TesterBlockchain
|
||||
from nucypher.utilities.sandbox.constants import (
|
||||
|
@ -35,7 +34,8 @@ from nucypher.utilities.sandbox.constants import (
|
|||
POLICY_MANAGER_DEPLOYMENT_SECRET,
|
||||
STAKING_ESCROW_DEPLOYMENT_SECRET,
|
||||
NUMBER_OF_ALLOCATIONS_IN_TESTS,
|
||||
TEST_PROVIDER_URI)
|
||||
INSECURE_DEVELOPMENT_PASSWORD
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.slow()
|
||||
|
@ -48,7 +48,10 @@ def test_rapid_deployment(token_economics):
|
|||
compiler=compiler)
|
||||
|
||||
# TODO: #1092 - TransactingPower
|
||||
blockchain.transacting_power = BlockchainPower(blockchain=blockchain, account=blockchain.etherbase_account)
|
||||
blockchain.transacting_power = TransactingPower(blockchain=blockchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=blockchain.etherbase_account)
|
||||
blockchain.transacting_power.activate()
|
||||
deployer_address = blockchain.etherbase_account
|
||||
|
||||
deployer = Deployer(blockchain=blockchain, deployer_address=deployer_address)
|
||||
|
|
|
@ -20,9 +20,9 @@ import pytest
|
|||
|
||||
from nucypher.blockchain.eth.actors import Staker
|
||||
from nucypher.blockchain.eth.token import NU, Stake
|
||||
from nucypher.crypto.powers import BlockchainPower
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
from nucypher.utilities.sandbox.blockchain import token_airdrop
|
||||
from nucypher.utilities.sandbox.constants import DEVELOPMENT_TOKEN_AIRDROP_AMOUNT
|
||||
from nucypher.utilities.sandbox.constants import DEVELOPMENT_TOKEN_AIRDROP_AMOUNT, INSECURE_DEVELOPMENT_PASSWORD
|
||||
from nucypher.utilities.sandbox.ursula import make_decentralized_ursulas
|
||||
|
||||
|
||||
|
@ -43,7 +43,10 @@ def test_staker_locking_tokens(testerchain, agency, staker, token_economics):
|
|||
token_agent, staking_agent, policy_agent = agency
|
||||
|
||||
# Mock Powerup consumption (Ursula-Staker)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=staker.checksum_address)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=staker.checksum_address)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
assert NU(token_economics.minimum_allowed_locked, 'NuNit') < staker.token_balance, "Insufficient staker balance"
|
||||
|
||||
|
@ -106,8 +109,11 @@ def test_staker_collects_staking_reward(testerchain, staker, blockchain_ursulas,
|
|||
initial_balance = staker.token_balance
|
||||
assert token_agent.get_balance(staker.checksum_address) == initial_balance
|
||||
|
||||
# Mock Powerup consumption (Staker)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=staker.checksum_address)
|
||||
# Mock Powerup consumption (Ursula-Worker)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=staker.checksum_address)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
staker.initialize_stake(amount=NU(token_economics.minimum_allowed_locked, 'NuNit'), # Lock the minimum amount of tokens
|
||||
lock_periods=int(token_economics.minimum_locked_periods)) # ... for the fewest number of periods
|
||||
|
@ -131,8 +137,11 @@ def test_staker_collects_staking_reward(testerchain, staker, blockchain_ursulas,
|
|||
# ...wait more...
|
||||
testerchain.time_travel(periods=2)
|
||||
|
||||
# Mock Powerup consumption (Staker)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=staker.checksum_address)
|
||||
# Mock Powerup consumption (Ursula-Worker)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=staker.checksum_address)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
# Profit!
|
||||
staker.collect_staking_reward()
|
||||
|
|
|
@ -25,8 +25,9 @@ from nucypher.blockchain.eth.actors import NucypherTokenActor, Staker
|
|||
from nucypher.blockchain.eth.agents import AdjudicatorAgent
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainInterface
|
||||
from nucypher.blockchain.eth.token import NU
|
||||
from nucypher.crypto.powers import BlockchainPower
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
from nucypher.crypto.signing import SignatureStamp
|
||||
from nucypher.utilities.sandbox.constants import INSECURE_DEVELOPMENT_PASSWORD
|
||||
|
||||
|
||||
def mock_ursula(testerchain, account):
|
||||
|
@ -58,7 +59,10 @@ def test_adjudicator_slashes(agency,
|
|||
locked_tokens = token_economics.minimum_allowed_locked * 5
|
||||
|
||||
# Mock Powerup consumption (Deployer)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=testerchain.etherbase_account)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=testerchain.etherbase_account)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
# The staker receives an initial amount of tokens
|
||||
_txhash = token_agent.transfer(amount=locked_tokens,
|
||||
|
@ -66,7 +70,10 @@ def test_adjudicator_slashes(agency,
|
|||
sender_address=testerchain.etherbase_account)
|
||||
|
||||
# Mock Powerup consumption (Staker)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=staker_account)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=staker_account)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
# Deposit: The staker deposits tokens in the StakingEscrow contract.
|
||||
staker = Staker(checksum_address=staker_account, is_me=True, blockchain=testerchain)
|
||||
|
@ -97,7 +104,11 @@ def test_adjudicator_slashes(agency,
|
|||
bobby_old_balance = bobby.token_balance
|
||||
|
||||
# Mock Powerup consumption (Bob)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=bob_account)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=bob_account)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
adjudicator_agent.evaluate_cfrag(evidence=evidence, sender_address=bob_account)
|
||||
|
||||
assert adjudicator_agent.was_this_evidence_evaluated(evidence)
|
||||
|
|
|
@ -20,7 +20,8 @@ import collections
|
|||
import pytest
|
||||
from eth_utils import is_checksum_address
|
||||
|
||||
from nucypher.crypto.powers import BlockchainPower
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
from nucypher.utilities.sandbox.constants import INSECURE_DEVELOPMENT_PASSWORD
|
||||
|
||||
MockPolicyMetadata = collections.namedtuple('MockPolicyMetadata', 'policy_id author addresses')
|
||||
|
||||
|
@ -50,7 +51,10 @@ def test_create_policy(testerchain, agency, token_economics):
|
|||
agent = policy_agent
|
||||
|
||||
# Mock Powerup consumption
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=testerchain.alice_account)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=testerchain.alice_account)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
policy_id = os.urandom(16)
|
||||
node_addresses = list(staking_agent.sample(quantity=3, duration=1))
|
||||
|
@ -111,13 +115,19 @@ def test_calculate_refund(testerchain, agency, policy_meta):
|
|||
worker = staking_agent.get_worker_from_staker(staker)
|
||||
|
||||
# Mock Powerup consumption (Ursula-Worker)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=worker)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=worker)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
testerchain.time_travel(hours=9)
|
||||
_receipt = staking_agent.confirm_activity(worker_address=worker)
|
||||
|
||||
# Mock Powerup consumption (Alice)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=testerchain.alice_account)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=testerchain.alice_account)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
receipt = agent.calculate_refund(policy_id=policy_meta.policy_id, author_address=policy_meta.author)
|
||||
assert receipt['status'] == 1, "Transaction Rejected"
|
||||
|
@ -144,7 +154,10 @@ def test_collect_policy_reward(testerchain, agency, policy_meta, token_economics
|
|||
worker = staking_agent.get_worker_from_staker(staker)
|
||||
|
||||
# Mock Powerup consumption (Ursula-Worker)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=worker)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=worker)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
old_eth_balance = token_agent.blockchain.client.get_balance(staker)
|
||||
|
||||
|
@ -153,7 +166,10 @@ def test_collect_policy_reward(testerchain, agency, policy_meta, token_economics
|
|||
testerchain.time_travel(periods=1)
|
||||
|
||||
# Mock Powerup consumption (Ursula-Staker)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=staker)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=staker)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
receipt = agent.collect_policy_reward(collector_address=staker, staker_address=staker)
|
||||
assert receipt['status'] == 1, "Transaction Rejected"
|
||||
|
|
|
@ -22,7 +22,8 @@ from eth_utils.address import to_checksum_address, is_address
|
|||
|
||||
from nucypher.blockchain.eth.agents import StakingEscrowAgent
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainInterface
|
||||
from nucypher.crypto.powers import BlockchainPower
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
from nucypher.utilities.sandbox.constants import INSECURE_DEVELOPMENT_PASSWORD
|
||||
|
||||
|
||||
@pytest.mark.slow()
|
||||
|
@ -34,7 +35,10 @@ def test_deposit_tokens(testerchain, agency, token_economics):
|
|||
staker_account = testerchain.unassigned_accounts[0]
|
||||
|
||||
# Mock Powerup consumption (Deployer)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=testerchain.etherbase_account)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=testerchain.etherbase_account)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
balance = token_agent.get_balance(address=staker_account)
|
||||
assert balance == 0
|
||||
|
@ -45,7 +49,10 @@ def test_deposit_tokens(testerchain, agency, token_economics):
|
|||
sender_address=testerchain.etherbase_account)
|
||||
|
||||
# Mock Powerup consumption (Ursula-Staker)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=staker_account)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=staker_account)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
#
|
||||
# Deposit: The staker deposits tokens in the StakingEscrow contract.
|
||||
|
@ -165,7 +172,10 @@ def test_confirm_activity(agency, testerchain):
|
|||
staker_account, worker_account, *other = testerchain.unassigned_accounts
|
||||
|
||||
# Mock Powerup consumption (Ursula-Worker)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=worker_account)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=worker_account)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
receipt = staking_agent.confirm_activity(worker_address=worker_account)
|
||||
assert receipt['status'] == 1, "Transaction Rejected"
|
||||
|
@ -219,7 +229,10 @@ def test_collect_staking_reward(agency, testerchain):
|
|||
testerchain.time_travel(periods=2)
|
||||
|
||||
# Mock Powerup consumption (Ursula-Staker)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=staker_account)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=staker_account)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
# Mint
|
||||
_receipt = staking_agent.mint(staker_address=staker_account)
|
||||
|
|
|
@ -19,7 +19,8 @@ from eth_tester.exceptions import TransactionFailed
|
|||
|
||||
from nucypher.blockchain.eth.agents import NucypherTokenAgent
|
||||
from nucypher.blockchain.eth.deployers import NucypherTokenDeployer, DispatcherDeployer
|
||||
from nucypher.crypto.powers import BlockchainPower
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
from nucypher.utilities.sandbox.constants import INSECURE_DEVELOPMENT_PASSWORD
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
|
@ -67,7 +68,10 @@ def test_approve_transfer(agent, token_economics):
|
|||
deployer, someone, *everybody_else = testerchain.client.accounts
|
||||
|
||||
# Mock Powerup consumption
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=someone)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=someone)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
# Approve
|
||||
receipt = agent.approve_transfer(amount=token_economics.minimum_allowed_locked,
|
||||
|
@ -83,7 +87,10 @@ def test_transfer(agent, token_economics):
|
|||
origin, someone, *everybody_else = testerchain.client.accounts
|
||||
|
||||
# Mock Powerup consumption (Deployer)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=origin)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=origin)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
old_balance = agent.get_balance(someone)
|
||||
receipt = agent.transfer(amount=token_economics.minimum_allowed_locked,
|
||||
|
|
|
@ -25,7 +25,8 @@ from nucypher.blockchain.eth.agents import UserEscrowAgent
|
|||
from nucypher.blockchain.eth.interfaces import BlockchainInterface
|
||||
from nucypher.blockchain.eth.deployers import UserEscrowDeployer, UserEscrowProxyDeployer, DispatcherDeployer
|
||||
from nucypher.blockchain.eth.registry import InMemoryAllocationRegistry
|
||||
from nucypher.crypto.powers import BlockchainPower
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
from nucypher.utilities.sandbox.constants import INSECURE_DEVELOPMENT_PASSWORD
|
||||
|
||||
TEST_DURATION = 60*60
|
||||
TEST_ALLOCATION_REGISTRY = InMemoryAllocationRegistry()
|
||||
|
@ -56,7 +57,10 @@ def agent(testerchain, proxy_deployer, allocation_value) -> UserEscrowAgent:
|
|||
deployer_address, beneficiary_address, *everybody_else = testerchain.client.accounts
|
||||
|
||||
# Mock Powerup consumption (Deployer)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=deployer_address)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=deployer_address)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
# Escrow
|
||||
escrow_deployer = UserEscrowDeployer(deployer_address=deployer_address,
|
||||
|
@ -141,7 +145,10 @@ def test_deposit_and_withdraw_as_staker(testerchain, agent, agency, allocation_v
|
|||
assert token_agent.get_balance(address=agent.contract_address) == allocation_value
|
||||
|
||||
# Mock Powerup consumption (Beneficiary)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=agent.beneficiary)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=agent.beneficiary)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
# Move the tokens to the StakingEscrow
|
||||
receipt = agent.deposit_as_staker(value=token_economics.minimum_allowed_locked, periods=token_economics.minimum_locked_periods)
|
||||
|
@ -159,7 +166,10 @@ def test_deposit_and_withdraw_as_staker(testerchain, agent, agency, allocation_v
|
|||
assert staking_agent.get_locked_tokens(staker_address=agent.contract_address, periods=token_economics.minimum_locked_periods+1) == 0
|
||||
|
||||
# Mock Powerup consumption (Beneficiary-Worker)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=worker)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=worker)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
for _ in range(token_economics.minimum_locked_periods):
|
||||
staking_agent.confirm_activity(worker_address=worker)
|
||||
|
@ -167,7 +177,10 @@ def test_deposit_and_withdraw_as_staker(testerchain, agent, agency, allocation_v
|
|||
testerchain.time_travel(periods=1)
|
||||
|
||||
# Mock Powerup consumption (Beneficiary)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=agent.beneficiary)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=agent.beneficiary)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
agent.mint()
|
||||
|
||||
|
@ -190,7 +203,10 @@ def test_collect_policy_reward(testerchain, agent, agency, token_economics):
|
|||
deployer_address, beneficiary_address, author, ursula, *everybody_else = testerchain.client.accounts
|
||||
|
||||
# Mock Powerup consumption (Beneficiary)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=agent.beneficiary)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=agent.beneficiary)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
_txhash = agent.deposit_as_staker(value=token_economics.minimum_allowed_locked, periods=token_economics.minimum_locked_periods)
|
||||
|
||||
|
@ -201,7 +217,10 @@ def test_collect_policy_reward(testerchain, agent, agency, token_economics):
|
|||
testerchain.time_travel(periods=1)
|
||||
|
||||
# Mock Powerup consumption (Alice)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=author)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=author)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
_txhash = policy_agent.create_policy(policy_id=os.urandom(16),
|
||||
author_address=author,
|
||||
|
@ -211,7 +230,10 @@ def test_collect_policy_reward(testerchain, agent, agency, token_economics):
|
|||
node_addresses=[agent.contract_address])
|
||||
|
||||
# Mock Powerup consumption (Beneficiary-Worker)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=worker)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=worker)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
_txhash = staking_agent.confirm_activity(worker_address=worker)
|
||||
testerchain.time_travel(periods=2)
|
||||
|
@ -220,7 +242,10 @@ def test_collect_policy_reward(testerchain, agent, agency, token_economics):
|
|||
old_balance = testerchain.client.get_balance(account=agent.beneficiary)
|
||||
|
||||
# Mock Powerup consumption (Beneficiary)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=agent.beneficiary)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=agent.beneficiary)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
txhash = agent.collect_policy_reward()
|
||||
assert txhash # TODO
|
||||
|
@ -232,7 +257,10 @@ def test_withdraw_tokens(testerchain, agent, agency, allocation_value):
|
|||
deployer_address, beneficiary_address, *everybody_else = testerchain.client.accounts
|
||||
|
||||
# Mock Powerup consumption (Beneficiary)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=agent.beneficiary)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=agent.beneficiary)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
assert token_agent.get_balance(address=agent.contract_address) == agent.unvested_tokens
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
|
|
|
@ -14,11 +14,13 @@ GNU Affero General Public License for more details.
|
|||
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 eth_utils
|
||||
import pytest
|
||||
|
||||
|
||||
import pytest
|
||||
from constant_sorrow import constants
|
||||
from cryptography.exceptions import InvalidSignature
|
||||
from eth_account._utils.transactions import Transaction
|
||||
from eth_utils import to_checksum_address
|
||||
|
||||
from nucypher.characters.lawful import Alice, Character, Bob
|
||||
from nucypher.characters.lawful import Enrico
|
||||
|
@ -27,8 +29,8 @@ from nucypher.crypto.api import verify_eip_191
|
|||
from nucypher.crypto.powers import (CryptoPower,
|
||||
SigningPower,
|
||||
NoSigningPower,
|
||||
BlockchainPower,
|
||||
PowerUpError)
|
||||
TransactingPower)
|
||||
from nucypher.utilities.sandbox.constants import INSECURE_DEVELOPMENT_PASSWORD
|
||||
|
||||
"""
|
||||
Chapter 1: SIGNING
|
||||
|
@ -116,39 +118,51 @@ def test_anybody_can_verify():
|
|||
assert cleartext is constants.NO_DECRYPTION_PERFORMED
|
||||
|
||||
|
||||
def test_character_blockchain_power(testerchain, agency):
|
||||
# TODO: Handle multiple providers
|
||||
eth_address = testerchain.client.accounts[0]
|
||||
canonical_address = eth_utils.to_canonical_address(eth_address)
|
||||
sig_privkey = testerchain.provider.ethereum_tester.backend._key_lookup[canonical_address]
|
||||
def test_character_transacting_power_signing(testerchain, agency):
|
||||
|
||||
# Pretend to be a character.
|
||||
eth_address = testerchain.etherbase_account
|
||||
signer = Character(is_me=True, blockchain=testerchain, checksum_address=eth_address)
|
||||
signer._crypto_power.consume_power_up(BlockchainPower(blockchain=testerchain, account=eth_address))
|
||||
|
||||
# Due to testing backend, the account is already unlocked.
|
||||
power = signer._crypto_power.power_ups(BlockchainPower)
|
||||
power.is_unlocked = True
|
||||
# power.unlock_account('this-is-not-a-secure-password')
|
||||
# Manually consume the power up
|
||||
transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=eth_address)
|
||||
|
||||
data_to_sign = b'What does Ursula look like?!?'
|
||||
sig = power.sign_message(message=data_to_sign)
|
||||
assert testerchain.transacting_power != transacting_power
|
||||
signer._crypto_power.consume_power_up(transacting_power)
|
||||
|
||||
is_verified = verify_eip_191(address=eth_address, message=data_to_sign, signature=sig)
|
||||
# Retrieve the power up
|
||||
power = signer._crypto_power.power_ups(TransactingPower)
|
||||
|
||||
assert power == transacting_power
|
||||
assert testerchain.transacting_power == power
|
||||
|
||||
assert power.is_active is True
|
||||
assert power.is_unlocked is True
|
||||
assert testerchain.transacting_power.is_unlocked is True
|
||||
|
||||
# Sign Message
|
||||
data_to_sign = b'Premium Select Luxury Pencil Holder'
|
||||
signature = power.sign_message(message=data_to_sign)
|
||||
is_verified = verify_eip_191(address=eth_address, message=data_to_sign, signature=signature)
|
||||
assert is_verified is True
|
||||
|
||||
# Test a bad address/pubkey pair
|
||||
is_verified = verify_eip_191(address=testerchain.client.accounts[1],
|
||||
message=data_to_sign,
|
||||
signature=sig)
|
||||
assert is_verified is False
|
||||
# Sign Transaction
|
||||
transaction_dict = {'nonce': testerchain.client.w3.eth.getTransactionCount(eth_address),
|
||||
'gasPrice': testerchain.client.w3.eth.gasPrice,
|
||||
'gas': 100000,
|
||||
'from': eth_address,
|
||||
'to': testerchain.unassigned_accounts[1],
|
||||
'value': 1,
|
||||
'data': b''}
|
||||
|
||||
# Test a signature without unlocking the account
|
||||
power.is_unlocked = False
|
||||
with pytest.raises(PowerUpError):
|
||||
power.sign_message(message=b'test')
|
||||
signed_transaction = power.sign_transaction(unsigned_transaction=transaction_dict)
|
||||
|
||||
# Test lockAccount call
|
||||
del power
|
||||
# Demonstrate that the transaction is valid RLP encoded.
|
||||
restored_transaction = Transaction.from_bytes(serialized_bytes=signed_transaction)
|
||||
restored_dict = restored_transaction.as_dict()
|
||||
assert to_checksum_address(restored_dict['to']) == transaction_dict['to']
|
||||
|
||||
|
||||
"""
|
||||
|
@ -174,7 +188,7 @@ def test_anybody_can_encrypt():
|
|||
def test_node_deployer(federated_ursulas):
|
||||
for ursula in federated_ursulas:
|
||||
deployer = ursula.get_deployer()
|
||||
assert deployer.options['https_port'] == ursula.rest_interface.port
|
||||
assert deployer.options['https_port'] == ursula.rest_information()[0].port
|
||||
assert deployer.application == ursula.rest_app
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ def test_alice_control_starts_with_mocked_keyring(click_runner, mocker):
|
|||
|
||||
user_input = '{password}\n{password}\n'.format(password=INSECURE_DEVELOPMENT_PASSWORD)
|
||||
result = click_runner.invoke(nucypher_cli, init_args, input=user_input)
|
||||
assert result.exit_code == 0
|
||||
assert result.exit_code == 0, result.exception
|
||||
|
||||
|
||||
def test_initialize_alice_with_custom_configuration_root(custom_filepath, click_runner):
|
||||
|
|
|
@ -73,6 +73,7 @@ class MockSideChannel:
|
|||
@pt.inlineCallbacks
|
||||
@pytest.mark.parametrize('federated', (True, False))
|
||||
def test_cli_lifecycle(click_runner,
|
||||
testerchain,
|
||||
random_policy_label,
|
||||
federated_ursulas,
|
||||
blockchain_ursulas,
|
||||
|
@ -108,7 +109,8 @@ def test_cli_lifecycle(click_runner,
|
|||
if federated:
|
||||
alice_init_args += ('--federated-only', )
|
||||
else:
|
||||
alice_init_args += ('--provider-uri', TEST_PROVIDER_URI)
|
||||
alice_init_args += ('--provider-uri', TEST_PROVIDER_URI,
|
||||
'--pay-with', testerchain.alice_account)
|
||||
|
||||
alice_init_response = click_runner.invoke(nucypher_cli, alice_init_args, catch_exceptions=False, env=envvars)
|
||||
assert alice_init_response.exit_code == 0
|
||||
|
@ -137,7 +139,8 @@ def test_cli_lifecycle(click_runner,
|
|||
if federated:
|
||||
bob_init_args += ('--federated-only', )
|
||||
else:
|
||||
bob_init_args += ('--provider-uri', TEST_PROVIDER_URI)
|
||||
bob_init_args += ('--provider-uri', TEST_PROVIDER_URI,
|
||||
'--pay-with', testerchain.bob_account)
|
||||
|
||||
bob_init_response = click_runner.invoke(nucypher_cli, bob_init_args, catch_exceptions=False, env=envvars)
|
||||
assert bob_init_response.exit_code == 0
|
||||
|
|
|
@ -11,12 +11,12 @@ from nucypher.blockchain.eth.agents import (
|
|||
StakingEscrowAgent,
|
||||
UserEscrowAgent,
|
||||
PolicyAgent,
|
||||
Agency, AdjudicatorAgent)
|
||||
Agency)
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainInterface, BlockchainDeployerInterface
|
||||
from nucypher.blockchain.eth.registry import AllocationRegistry, EthereumContractRegistry
|
||||
from nucypher.blockchain.eth.registry import AllocationRegistry
|
||||
from nucypher.cli.deploy import deploy
|
||||
from nucypher.config.constants import DEFAULT_CONFIG_ROOT
|
||||
from nucypher.crypto.powers import BlockchainPower
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
# Prevents TesterBlockchain to be picked up by py.test as a test class
|
||||
from nucypher.utilities.sandbox.blockchain import TesterBlockchain as _TesterBlockchain
|
||||
from nucypher.utilities.sandbox.constants import (
|
||||
|
@ -44,7 +44,7 @@ def make_testerchain():
|
|||
|
||||
# Set the deployer address from a freshly created test account
|
||||
testerchain.deployer_address = testerchain.etherbase_account
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=testerchain.etherbase_account)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain, account=testerchain.etherbase_account)
|
||||
return testerchain
|
||||
|
||||
|
||||
|
@ -356,8 +356,7 @@ def test_nucypher_deploy_allocation_contracts(click_runner,
|
|||
|
||||
account_index = '0\n'
|
||||
yes = 'Y\n'
|
||||
node_password = f'{INSECURE_DEVELOPMENT_PASSWORD}\n'
|
||||
user_input = account_index + yes + node_password + yes
|
||||
user_input = account_index + yes + yes
|
||||
|
||||
result = click_runner.invoke(deploy,
|
||||
deploy_command,
|
||||
|
@ -379,24 +378,3 @@ def test_nucypher_deploy_allocation_contracts(click_runner,
|
|||
|
||||
# Destroy existing blockchain
|
||||
testerchain.disconnect()
|
||||
|
||||
|
||||
def test_destroy_registry(click_runner, mock_primary_registry_filepath):
|
||||
|
||||
# ... I changed my mind, destroy the registry!
|
||||
destroy_command = ('destroy-registry',
|
||||
'--registry-infile', mock_primary_registry_filepath,
|
||||
'--provider-uri', TEST_PROVIDER_URI,
|
||||
'--poa')
|
||||
|
||||
# TODO: #1036 - Providers and unlocking are not needed for this command
|
||||
account_index = '0\n'
|
||||
yes = 'Y\n'
|
||||
user_input = account_index + yes + yes
|
||||
|
||||
result = click_runner.invoke(deploy, destroy_command, input=user_input, catch_exceptions=False)
|
||||
assert result.exit_code == 0
|
||||
assert mock_primary_registry_filepath in result.output
|
||||
assert DEFAULT_CONFIG_ROOT not in result.output, 'WARNING: Deploy CLI tests are using default config root dir!'
|
||||
assert f'Successfully destroyed {mock_primary_registry_filepath}' in result.output
|
||||
assert not os.path.isfile(mock_primary_registry_filepath)
|
||||
|
|
|
@ -5,17 +5,18 @@ from umbral.signing import Signer
|
|||
|
||||
from nucypher.config.keyring import NucypherKeyring
|
||||
from nucypher.crypto.powers import DelegatingPower, DecryptingPower
|
||||
from nucypher.utilities.sandbox.constants import INSECURE_DEVELOPMENT_PASSWORD
|
||||
from constant_sorrow.constants import FEDERATED_ADDRESS
|
||||
|
||||
|
||||
def test_generate_alice_keyring(tmpdir):
|
||||
password = 'x' * 16
|
||||
|
||||
keyring = NucypherKeyring.generate(
|
||||
password=password,
|
||||
checksum_address=FEDERATED_ADDRESS,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
encrypting=True,
|
||||
rest=False,
|
||||
keyring_root=tmpdir,
|
||||
federated=True
|
||||
keyring_root=tmpdir
|
||||
)
|
||||
|
||||
enc_pubkey = keyring.encrypting_public_key
|
||||
|
@ -24,7 +25,7 @@ def test_generate_alice_keyring(tmpdir):
|
|||
with pytest.raises(NucypherKeyring.KeyringLocked):
|
||||
_dec_keypair = keyring.derive_crypto_power(DecryptingPower).keypair
|
||||
|
||||
keyring.unlock(password)
|
||||
keyring.unlock(password=INSECURE_DEVELOPMENT_PASSWORD)
|
||||
dec_keypair = keyring.derive_crypto_power(DecryptingPower).keypair
|
||||
|
||||
assert enc_pubkey == dec_keypair.pubkey
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
import pytest
|
||||
from eth_account._utils.transactions import Transaction
|
||||
from eth_utils import to_checksum_address
|
||||
|
||||
from nucypher.blockchain.eth.agents import NucypherTokenAgent
|
||||
from nucypher.crypto.api import verify_eip_191
|
||||
from nucypher.crypto.powers import (PowerUpError)
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
from nucypher.utilities.sandbox.constants import INSECURE_DEVELOPMENT_PASSWORD
|
||||
|
||||
|
||||
def test_transacting_power_sign_message(testerchain):
|
||||
|
||||
# Manually create a TransactingPower
|
||||
testerchain.connect()
|
||||
eth_address = testerchain.etherbase_account
|
||||
power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=eth_address)
|
||||
|
||||
# The default state of the account is locked.
|
||||
# Test a signature without unlocking the account
|
||||
with pytest.raises(PowerUpError):
|
||||
power.sign_message(message=b'test')
|
||||
|
||||
# Manually unlock
|
||||
power.unlock_account(password=INSECURE_DEVELOPMENT_PASSWORD)
|
||||
|
||||
# Sign
|
||||
data_to_sign = b'Premium Select Luxury Pencil Holder'
|
||||
signature = power.sign_message(message=data_to_sign)
|
||||
|
||||
# Verify
|
||||
is_verified = verify_eip_191(address=eth_address, message=data_to_sign, signature=signature)
|
||||
assert is_verified is True
|
||||
|
||||
# Test invalid address/pubkey pair
|
||||
is_verified = verify_eip_191(address=testerchain.client.accounts[1],
|
||||
message=data_to_sign,
|
||||
signature=signature)
|
||||
assert is_verified is False
|
||||
|
||||
# Test lockAccount call
|
||||
power.lock_account()
|
||||
|
||||
# Test a signature without unlocking the account
|
||||
with pytest.raises(PowerUpError):
|
||||
power.sign_message(message=b'test')
|
||||
|
||||
del power # Locks account
|
||||
|
||||
|
||||
def test_transacting_power_sign_transaction(testerchain):
|
||||
|
||||
eth_address = testerchain.unassigned_accounts[2]
|
||||
power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=eth_address)
|
||||
|
||||
assert power.is_active is False
|
||||
assert power.is_unlocked is False
|
||||
|
||||
transaction_dict = {'nonce': testerchain.client.w3.eth.getTransactionCount(eth_address),
|
||||
'gasPrice': testerchain.client.w3.eth.gasPrice,
|
||||
'gas': 100000,
|
||||
'from': eth_address,
|
||||
'to': testerchain.unassigned_accounts[1],
|
||||
'value': 1,
|
||||
'data': b''}
|
||||
|
||||
# The default state of the account is locked.
|
||||
# Test a signature without unlocking the account
|
||||
with pytest.raises(TransactingPower.AccountLocked):
|
||||
power.sign_transaction(unsigned_transaction=transaction_dict)
|
||||
|
||||
# Sign
|
||||
power.activate()
|
||||
assert power.is_active is True
|
||||
assert power.is_unlocked is True
|
||||
signed_transaction = power.sign_transaction(unsigned_transaction=transaction_dict)
|
||||
|
||||
# Demonstrate that the transaction is valid RLP encoded.
|
||||
from eth_account._utils.transactions import Transaction
|
||||
restored_transaction = Transaction.from_bytes(serialized_bytes=signed_transaction)
|
||||
restored_dict = restored_transaction.as_dict()
|
||||
assert to_checksum_address(restored_dict['to']) == transaction_dict['to']
|
||||
|
||||
# Try signing with missing transaction fields
|
||||
del transaction_dict['gas']
|
||||
del transaction_dict['nonce']
|
||||
with pytest.raises(TypeError):
|
||||
power.sign_transaction(unsigned_transaction=transaction_dict)
|
||||
|
||||
# Try signing with a re-locked account.
|
||||
power.lock_account()
|
||||
with pytest.raises(TransactingPower.AccountLocked):
|
||||
power.sign_transaction(unsigned_transaction=transaction_dict)
|
||||
|
||||
power.unlock_account(password=INSECURE_DEVELOPMENT_PASSWORD)
|
||||
assert power.is_unlocked is True
|
||||
|
||||
# Tear-Down Test
|
||||
power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=testerchain.etherbase_account)
|
||||
power.activate(password=INSECURE_DEVELOPMENT_PASSWORD)
|
||||
|
||||
|
||||
def test_transacting_power_sign_agent_transaction(testerchain, agency):
|
||||
|
||||
token_agent = NucypherTokenAgent(blockchain=testerchain)
|
||||
contract_function = token_agent.contract.functions.approve(testerchain.etherbase_account, 100)
|
||||
|
||||
payload = {'chainId': int(testerchain.client.chain_id),
|
||||
'nonce': testerchain.client.w3.eth.getTransactionCount(testerchain.etherbase_account),
|
||||
'from': testerchain.etherbase_account,
|
||||
'gasPrice': testerchain.client.gas_price}
|
||||
|
||||
unsigned_transaction = contract_function.buildTransaction(payload)
|
||||
|
||||
# Sign with Transacting Power
|
||||
transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=testerchain.etherbase_account)
|
||||
transacting_power.activate()
|
||||
signed_raw_transaction = transacting_power.sign_transaction(unsigned_transaction)
|
||||
|
||||
# Demonstrate that the transaction is valid RLP encoded.
|
||||
restored_transaction = Transaction.from_bytes(serialized_bytes=signed_raw_transaction)
|
||||
restored_dict = restored_transaction.as_dict()
|
||||
assert to_checksum_address(restored_dict['to']) == unsigned_transaction['to']
|
|
@ -39,15 +39,12 @@ from nucypher.blockchain.eth.deployers import (NucypherTokenDeployer,
|
|||
PolicyManagerDeployer,
|
||||
DispatcherDeployer,
|
||||
AdjudicatorDeployer)
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface
|
||||
from nucypher.blockchain.eth.registry import InMemoryEthereumContractRegistry
|
||||
from nucypher.blockchain.eth.sol.compile import SolidityCompiler
|
||||
from nucypher.blockchain.eth.token import NU
|
||||
from nucypher.characters.lawful import Enrico, Bob
|
||||
from nucypher.config.characters import UrsulaConfiguration, AliceConfiguration, BobConfiguration
|
||||
from nucypher.config.constants import BASE_DIR
|
||||
from nucypher.config.node import CharacterConfiguration
|
||||
from nucypher.crypto.powers import BlockchainPower
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
from nucypher.crypto.utils import canonical_address_from_umbral_key
|
||||
from nucypher.keystore import keystore
|
||||
from nucypher.keystore.db import Base
|
||||
|
@ -59,8 +56,8 @@ from nucypher.utilities.sandbox.constants import (DEVELOPMENT_ETH_AIRDROP_AMOUNT
|
|||
MOCK_URSULA_STARTING_PORT,
|
||||
NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK,
|
||||
TEMPORARY_DOMAIN,
|
||||
TEST_PROVIDER_URI
|
||||
)
|
||||
TEST_PROVIDER_URI,
|
||||
INSECURE_DEVELOPMENT_PASSWORD)
|
||||
from nucypher.utilities.sandbox.middleware import MockRestMiddleware
|
||||
from nucypher.utilities.sandbox.policy import generate_random_label
|
||||
from nucypher.utilities.sandbox.ursula import (make_decentralized_ursulas,
|
||||
|
@ -296,7 +293,6 @@ def capsule_side_channel(enacted_federated_policy):
|
|||
self.messages = []
|
||||
self()
|
||||
|
||||
|
||||
return _CapsuleSideChannel()
|
||||
|
||||
|
||||
|
@ -316,7 +312,7 @@ def federated_alice(alice_federated_test_config):
|
|||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def blockchain_alice(alice_blockchain_test_config):
|
||||
def blockchain_alice(alice_blockchain_test_config, testerchain):
|
||||
_alice = alice_blockchain_test_config.produce()
|
||||
return _alice
|
||||
|
||||
|
@ -328,7 +324,7 @@ def federated_bob(bob_federated_test_config):
|
|||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def blockchain_bob(bob_blockchain_test_config):
|
||||
def blockchain_bob(bob_blockchain_test_config, testerchain):
|
||||
_bob = bob_blockchain_test_config.produce()
|
||||
return _bob
|
||||
|
||||
|
@ -371,20 +367,21 @@ def testerchain():
|
|||
# Create the blockchain
|
||||
testerchain = TesterBlockchain(eth_airdrop=True, free_transactions=True)
|
||||
|
||||
# TODO: TransactingPower
|
||||
# Mock TransactingPower Consumption
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=testerchain.etherbase_account)
|
||||
# Mock TransactingPower Consumption (Deployer)
|
||||
testerchain.deployer_address = testerchain.etherbase_account
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=testerchain.deployer_address)
|
||||
testerchain.transacting_power.activate()
|
||||
|
||||
yield testerchain
|
||||
testerchain.disconnect()
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def agency(testerchain):
|
||||
"""
|
||||
Launch the big three contracts on provided chain,
|
||||
make agents for each and return them.
|
||||
"""
|
||||
"""Launch all Nucypher ethereum contracts"""
|
||||
|
||||
origin = testerchain.etherbase_account
|
||||
|
||||
token_deployer = NucypherTokenDeployer(blockchain=testerchain, deployer_address=origin)
|
||||
|
@ -399,18 +396,22 @@ def agency(testerchain):
|
|||
adjudicator_deployer = AdjudicatorDeployer(deployer_address=origin, blockchain=testerchain)
|
||||
adjudicator_deployer.deploy(secret_hash=os.urandom(DispatcherDeployer.DISPATCHER_SECRET_LENGTH))
|
||||
|
||||
token_agent = token_deployer.make_agent() # 1: Token
|
||||
staking_agent = staking_escrow_deployer.make_agent() # 2 Miner Escrow
|
||||
policy_agent = policy_manager_deployer.make_agent() # 3 Policy Agent
|
||||
adjudicator_agent = adjudicator_deployer.make_agent() # 4
|
||||
token_agent = token_deployer.make_agent() # 1 Token
|
||||
staking_agent = staking_escrow_deployer.make_agent() # 2 Miner Escrow
|
||||
policy_agent = policy_manager_deployer.make_agent() # 3 Policy Agent
|
||||
_adjudicator_agent = adjudicator_deployer.make_agent() # 4 Adjudicator
|
||||
|
||||
# TODO: Perhaps we should get rid of returning these agents here.
|
||||
# What's important is deploying and creating the first agent for each contract,
|
||||
# and since agents are singletons, in tests it's only necessary to call the agent
|
||||
# constructor again to receive the existing agent. For example:
|
||||
# constructor again to receive the existing agent.
|
||||
#
|
||||
# For example:
|
||||
# staking_agent = StakingEscrowAgent()
|
||||
#
|
||||
# This is more clear than how we currently obtain an agent instance in tests:
|
||||
# _, staking_agent, _ = agency
|
||||
#
|
||||
# Other advantages is that it's closer to how agents should be use (i.e., there
|
||||
# are no fixtures IRL) and it's more extensible (e.g., AdjudicatorAgent)
|
||||
|
||||
|
@ -425,13 +426,15 @@ def clear_out_agency():
|
|||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def stakers(agency, token_economics):
|
||||
def stakers(testerchain, agency, token_economics):
|
||||
token_agent, _staking_agent, _policy_agent = agency
|
||||
blockchain = token_agent.blockchain
|
||||
|
||||
# Mock Powerup consumption (Deployer)
|
||||
blockchain.transacting_power = BlockchainPower(blockchain=blockchain,
|
||||
account=blockchain.etherbase_account)
|
||||
blockchain.transacting_power = TransactingPower(blockchain=blockchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=blockchain.etherbase_account)
|
||||
blockchain.transacting_power.activate()
|
||||
|
||||
token_airdrop(origin=blockchain.etherbase_account,
|
||||
addresses=blockchain.stakers_accounts,
|
||||
|
@ -442,9 +445,11 @@ def stakers(agency, token_economics):
|
|||
for index, account in enumerate(blockchain.stakers_accounts):
|
||||
staker = Staker(is_me=True, checksum_address=account, blockchain=blockchain)
|
||||
|
||||
# Mock TransactingPower consumption (Ursula-Staker)
|
||||
staker.blockchain.transacting_power = BlockchainPower(blockchain=staker.blockchain,
|
||||
account=staker.checksum_address)
|
||||
# Mock TransactingPower consumption
|
||||
staker.blockchain.transacting_power = TransactingPower(blockchain=blockchain,
|
||||
password=INSECURE_DEVELOPMENT_PASSWORD,
|
||||
account=account)
|
||||
staker.blockchain.transacting_power.activate()
|
||||
|
||||
min_stake, balance = token_economics.minimum_allowed_locked, staker.token_balance
|
||||
amount = random.randint(min_stake, balance)
|
||||
|
@ -494,8 +499,8 @@ def idle_staker(testerchain, agency):
|
|||
idle_staker_account = testerchain.unassigned_accounts[-2]
|
||||
|
||||
# Mock Powerup consumption (Deployer)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
|
||||
account=testerchain.etherbase_account)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
account=testerchain.etherbase_account)
|
||||
|
||||
token_airdrop(origin=testerchain.etherbase_account,
|
||||
addresses=[idle_staker_account],
|
||||
|
|
|
@ -9,7 +9,7 @@ from bytestring_splitter import VariableLengthBytestring
|
|||
from constant_sorrow.constants import NOT_SIGNED
|
||||
|
||||
from nucypher.characters.base import Character
|
||||
from nucypher.crypto.powers import BlockchainPower
|
||||
from nucypher.crypto.powers import TransactingPower
|
||||
from nucypher.network.nicknames import nickname_from_seed
|
||||
from nucypher.network.nodes import FleetStateTracker
|
||||
from nucypher.utilities.sandbox.middleware import MockRestMiddleware
|
||||
|
@ -84,8 +84,8 @@ def test_invalid_workers_tolerance(testerchain,
|
|||
periods = token_economics.minimum_locked_periods
|
||||
|
||||
# Mock Powerup consumption (Staker)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
|
||||
account=idle_staker.checksum_address)
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
account=idle_staker.checksum_address)
|
||||
|
||||
idle_staker.initialize_stake(amount=amount, lock_periods=periods)
|
||||
|
||||
|
@ -122,7 +122,7 @@ def test_invalid_workers_tolerance(testerchain,
|
|||
# She withdraws up to the last penny (well, last nunit, actually).
|
||||
|
||||
# Mock Powerup consumption (Staker)
|
||||
testerchain.transacting_power = BlockchainPower(blockchain=testerchain,
|
||||
testerchain.transacting_power = TransactingPower(blockchain=testerchain,
|
||||
account=idle_staker.checksum_address)
|
||||
idle_staker.mint()
|
||||
testerchain.time_travel(periods=1)
|
||||
|
|
|
@ -24,9 +24,9 @@ import os
|
|||
import re
|
||||
import sys
|
||||
import time
|
||||
from mock import Mock
|
||||
from os.path import abspath, dirname
|
||||
|
||||
from mock import Mock
|
||||
from twisted.logger import globalLogPublisher, Logger, jsonFileLogObserver, ILogObserver
|
||||
from umbral.keys import UmbralPrivateKey
|
||||
from umbral.signing import Signer
|
||||
|
|
Loading…
Reference in New Issue