diff --git a/nucypher/blockchain/eth/actors.py b/nucypher/blockchain/eth/actors.py index e3682a007..db8f52ffc 100644 --- a/nucypher/blockchain/eth/actors.py +++ b/nucypher/blockchain/eth/actors.py @@ -40,13 +40,13 @@ class NucypherTokenActor: self.token_agent = token_agent if token_agent is not None else NucypherTokenAgent() if not kwargs.get("public_address"): - self.ether_address = ether_address if ether_address is not None else constants.UNKNOWN_ACTOR + self._ether_address = ether_address if ether_address is not None else constants.UNKNOWN_ACTOR self._transaction_cache = list() # track transactions transmitted def __repr__(self): class_name = self.__class__.__name__ r = "{}(address='{}')" - r = r.format(class_name, self.ether_address) + r = r.format(class_name, self._ether_address) return r @classmethod @@ -57,13 +57,13 @@ class NucypherTokenActor: @property def eth_balance(self): """Return this actors's current ETH balance""" - balance = self.token_agent.blockchain.interface.w3.eth.getBalance(self.ether_address) + balance = self.token_agent.blockchain.interface.w3.eth.getBalance(self._ether_address) return balance @property def token_balance(self): """Return this actors's current token balance""" - balance = self.token_agent.get_balance(address=self.ether_address) + balance = self.token_agent.get_balance(address=self._ether_address) return balance @@ -108,11 +108,11 @@ class Miner(NucypherTokenActor): @property def locked_tokens(self, ): """Returns the amount of tokens this miner has locked.""" - return self.miner_agent.get_locked_tokens(node_address=self.ether_address) + return self.miner_agent.get_locked_tokens(node_address=self._ether_address) @property def stakes(self): - stakes_reader = self.miner_agent.get_all_stakes(miner_address=self.ether_address) + stakes_reader = self.miner_agent.get_all_stakes(miner_address=self._ether_address) return stakes_reader @only_me @@ -123,11 +123,11 @@ class Miner(NucypherTokenActor): approve_txhash = self.token_agent.approve_transfer(amount=amount, target_address=self.miner_agent.contract_address, - sender_address=self.ether_address) + sender_address=self._ether_address) deposit_txhash = self.miner_agent.deposit_tokens(amount=amount, lock_periods=lock_periods, - sender_address=self.ether_address) + sender_address=self._ether_address) return approve_txhash, deposit_txhash @@ -150,7 +150,7 @@ class Miner(NucypherTokenActor): raise ValueError("Pass the number of lock periods or an expiration MayaDT; not both.") _first_period, last_period, locked_value = self.miner_agent.get_stake_info( - miner_address=self.ether_address, stake_index=stake_index) + miner_address=self._ether_address, stake_index=stake_index) if expiration: additional_periods = datetime_to_period(datetime=expiration) - last_period @@ -164,7 +164,7 @@ class Miner(NucypherTokenActor): validate_stake_amount(amount=target_value) validate_stake_amount(amount=locked_value-target_value) - tx = self.miner_agent.divide_stake(miner_address=self.ether_address, + tx = self.miner_agent.divide_stake(miner_address=self._ether_address, stake_index=stake_index, target_value=target_value, periods=additional_periods) @@ -225,7 +225,7 @@ class Miner(NucypherTokenActor): def confirm_activity(self) -> str: """Miner rewarded for every confirmed period""" - txhash = self.miner_agent.confirm_activity(node_address=self.ether_address) + txhash = self.miner_agent.confirm_activity(node_address=self._ether_address) self._transaction_cache.append((datetime.utcnow(), txhash)) return txhash @@ -234,7 +234,7 @@ class Miner(NucypherTokenActor): def mint(self) -> Tuple[str, str]: """Computes and transfers tokens to the miner's account""" - mint_txhash = self.miner_agent.mint(node_address=self.ether_address) + mint_txhash = self.miner_agent.mint(node_address=self._ether_address) self._transaction_cache.append((datetime.utcnow(), mint_txhash)) return mint_txhash @@ -243,7 +243,7 @@ class Miner(NucypherTokenActor): def collect_policy_reward(self, policy_manager): """Collect rewarded ETH""" - policy_reward_txhash = policy_manager.collect_policy_reward(collector_address=self.ether_address) + policy_reward_txhash = policy_manager.collect_policy_reward(collector_address=self._ether_address) self._transaction_cache.append((datetime.utcnow(), policy_reward_txhash)) return policy_reward_txhash @@ -252,7 +252,7 @@ class Miner(NucypherTokenActor): def collect_staking_reward(self) -> str: """Withdraw tokens rewarded for staking.""" - collection_txhash = self.miner_agent.collect_staking_reward(collector_address=self.ether_address) + collection_txhash = self.miner_agent.collect_staking_reward(collector_address=self._ether_address) self._transaction_cache.append((datetime.utcnow(), collection_txhash)) return collection_txhash diff --git a/nucypher/blockchain/eth/policies.py b/nucypher/blockchain/eth/policies.py index 7866d1b4d..d598473f0 100644 --- a/nucypher/blockchain/eth/policies.py +++ b/nucypher/blockchain/eth/policies.py @@ -59,9 +59,9 @@ class BlockchainArrangement(Arrangement): return r def publish(self) -> str: - payload = {'from': self.author.ether_address, 'value': self.value} + payload = {'from': self.author._ether_address, 'value': self.value} - txhash = self.policy_agent.contract.functions.createPolicy(self.id, self.miner.ether_address, + txhash = self.policy_agent.contract.functions.createPolicy(self.id, self.miner._ether_address, self.lock_periods).transact(payload) self.policy_agent.blockchain.wait_for_receipt(txhash) diff --git a/nucypher/characters.py b/nucypher/characters.py index 2582f0876..07f52b1cd 100644 --- a/nucypher/characters.py +++ b/nucypher/characters.py @@ -7,7 +7,7 @@ from logging import getLogger from typing import Dict, ClassVar, Set from typing import Union, List -import binascii + import kademlia import msgpack from kademlia.network import Server @@ -16,6 +16,7 @@ from twisted.internet import task from bytestring_splitter import BytestringSplitter, VariableLengthBytestring from constant_sorrow import constants, default_constant_splitter +from eth_keys import KeyAPI as EthKeyAPI from eth_utils import to_checksum_address, to_canonical_address from nucypher.blockchain.eth.actors import PolicyAuthor, Miner from nucypher.blockchain.eth.agents import MinerAgent @@ -59,7 +60,7 @@ class Character: always_be_learning=True, known_nodes: Set = (), config: CharacterConfiguration = None, - public_address: bytes = None, + canonical_public_address: bytes = None, *args, **kwargs): """ :param attach_dht_server: Whether to attach a Server when this Character is @@ -87,8 +88,9 @@ class Character: self.federated_only = federated_only self._known_nodes = {} - if public_address is not None: - self.public_address = public_address + if canonical_public_address is not None: + self.canonical_public_address = canonical_public_address + self._checksum_address = None self.log = getLogger("characters") @@ -115,7 +117,6 @@ class Character: for node in known_nodes: self.remember_node(node) - try: signing_power = self._crypto_power.power_ups(SigningPower) self._stamp = signing_power.get_signature_stamp() @@ -198,7 +199,7 @@ class Character: ## def remember_node(self, node): - self._known_nodes[node.public_address] = node + self._known_nodes[node.canonical_public_address] = node def start_learning(self): d = self._learning_task.start(10, now=True) @@ -252,8 +253,8 @@ class Character: if self._node_ids_to_learn_about_immediately: self.learn_about_nodes_now() - def learn_about_specific_node(self, ether_address: str): - self._node_ids_to_learn_about_immediately.add(ether_address) # hmmmm + def learn_about_specific_nodes(self, canonical_addresses: Set): + self._node_ids_to_learn_about_immediately.update(canonical_addresses) # hmmmm self.learn_about_nodes_now() def learn_from_teacher_node(self, rest_address: str = None, port: int = None): @@ -443,20 +444,43 @@ class Character: return power_up.public_key() @property - def public_address(self): + def canonical_public_address(self): + return to_canonical_address(self.checksum_public_address) + + @canonical_public_address.setter + def canonical_public_address(self, address_bytes): + self._ether_address = to_checksum_address(address_bytes) + + @property + def ether_address(self): + raise NotImplementedError + + @property + def checksum_public_address(self): + if not self._checksum_address: + self._set_checksum_address() + return self._checksum_address + + def _set_checksum_address(self): if self.federated_only: verifying_key = self.public_key(SigningPower) uncompressed_bytes = verifying_key.to_bytes(is_compressed=False) - hash_of_signing_key = keccak_digest(uncompressed_bytes) - public_address = hash_of_signing_key[:PUBLIC_ADDRESS_LENGTH] + without_prefix = uncompressed_bytes[1:] + verifying_key_as_eth_key = EthKeyAPI.PublicKey(without_prefix) + public_address = verifying_key_as_eth_key.to_checksum_address() else: - public_address = to_canonical_address(self.ether_address) + try: + public_address = to_checksum_address(self._ether_address) + except NotImplementedError: + raise TypeError("You can't use a plain Character in federated mode - you need to implement ether_address.") - return public_address + self._checksum_address = public_address - @public_address.setter - def public_address(self, address_bytes): - self.ether_address = to_checksum_address(address_bytes) + def __repr__(self): + class_name = self.__class__.__name__ + r = "{} {}" + r = r.format(class_name, self.checksum_public_address[12:]) + return r class Alice(Character, PolicyAuthor):