diff --git a/nkms_eth/actors.py b/nkms_eth/actors.py index 377ea7ef0..54353c76b 100644 --- a/nkms_eth/actors.py +++ b/nkms_eth/actors.py @@ -200,34 +200,34 @@ class Miner(TokenActor): return staking_transactions - # TODO: Sidechain datastore - # def publish_data(self, miner_id) -> str: - # """Store a new Miner ID""" - # - # txhash = self.miner_agent.transact({'from': self.address}).setMinerId(miner_id) - # self._blockchain.wait_for_receipt(txhash) - # self._transactions[datetime.utcnow()] = txhash - # - # return txhash - # - # def fetch_miner_data(self) -> tuple: - # """Retrieve all stored Miner IDs on this miner""" - # - # count = self.miner_agent.read().getMinerInfo(self.miner_agent._deployer.MinerInfoField.MINER_IDS_LENGTH.value, - # self.address, - # 0).encode('latin-1') - # - # count = self._blockchain._chain.web3.toInt(count) - # - # miner_ids = list() - # for index in range(count): - # miner_id = self.miner_agent.read().getMinerInfo(self.miner_agent._deployer.MinerInfoField.MINER_ID.value, - # self.address, - # index) - # encoded_miner_id = miner_id.encode('latin-1') # TODO change when v4 of web3.py is released - # miner_ids.append(encoded_miner_id) - # - # return tuple(miner_ids) + def publish_data(self, data) -> str: + """Store new data""" + + txhash = self.miner_agent.transact({'from': self.address}).setMinerId(data) + self.blockchain.wait_for_receipt(txhash) + + self._transactions[datetime.utcnow()] = txhash + + return txhash + + def fetch_data(self) -> tuple: + """Retrieve all stored Miner IDs on this miner""" + + count_bytes = self.miner_agent.read().getMinerInfo(self.miner_agent._deployer.MinerInfoField.MINER_IDS_LENGTH.value, + self.address, + 0).encode('latin-1') # TODO change when v4 of web3.py is released + + count = self.blockchain._chain.web3.toInt(count_bytes) + + miner_ids = list() + for index in range(count): + miner_id = self.miner_agent.read().getMinerInfo(self.miner_agent._deployer.MinerInfoField.MINER_ID.value, + self.address, + index) + encoded_miner_id = miner_id.encode('latin-1') + miner_ids.append(encoded_miner_id) + + return tuple(miner_ids) class PolicyAuthor(TokenActor): @@ -239,40 +239,12 @@ class PolicyAuthor(TokenActor): self._arrangements = OrderedDict() # Track authored policies by id - def make_arrangement(self, miner: Miner, periods: int, rate: int, arrangement_id: bytes=None) -> 'BlockchainArrangement': - """ - Create a new arrangement to carry out a blockchain policy for the specified rate and time. - """ - - value = rate * periods - arrangement = BlockchainArrangement(author=self, - miner=miner, - value=value, - periods=periods) - - self._arrangements[arrangement.id] = {arrangement_id: arrangement} - return arrangement - - def get_arrangement(self, arrangement_id: bytes) -> BlockchainArrangement: - """Fetch a published arrangement from the blockchain""" - - blockchain_record = self.policy_agent.read().policies(arrangement_id) - author_address, miner_address, rate, start_block, end_block, downtime_index = blockchain_record - - duration = end_block - start_block - - miner = Miner(address=miner_address, miner_agent=self.policy_agent.miner_agent) - arrangement = BlockchainArrangement(author=self, miner=miner, periods=duration) - - arrangement.is_published = True - return arrangement - def revoke_arrangement(self, arrangement_id): """Get the arrangement from the cache and revoke it on the blockchain""" try: arrangement = self._arrangements[arrangement_id] except KeyError: - raise Exception('No such arrangement') #TODO + raise self.ActorError('No such arrangement') else: txhash = arrangement.revoke() return txhash diff --git a/nkms_eth/agents.py b/nkms_eth/agents.py index 12c0dc164..45b6d74f8 100644 --- a/nkms_eth/agents.py +++ b/nkms_eth/agents.py @@ -7,6 +7,10 @@ from nkms_eth.deployers import MinerEscrowDeployer, NuCypherKMSTokenDeployer, Po class EthereumContractAgent(ABC): + """ + Base class for ethereum contract wrapper types that interact with blockchain contract instances + """ + _principal_contract_name = NotImplemented class ContractNotDeployed(ContractDeployer.ContractDeploymentError): @@ -38,6 +42,16 @@ class EthereumContractAgent(ABC): return self.blockchain._chain.web3.eth.accounts[0] # TODO: make swappable def read(self): + """ + Returns an object that exposes the contract instance functions. + + This method is intended for use with method chaining, + results in zero state changes, and costs zero gas. + Useful as a dry-run before sending an actual transaction. + + See more on interacting with contract instances in the Populus docs: + http://populus.readthedocs.io/en/latest/dev_cycle.part-07.html#call-an-instance-function + """ return self._contract.call() def transact(self, payload: dict): diff --git a/nkms_eth/blockchain.py b/nkms_eth/blockchain.py index 6409f5031..5ff0bce13 100644 --- a/nkms_eth/blockchain.py +++ b/nkms_eth/blockchain.py @@ -78,7 +78,8 @@ class TheBlockchain(ABC): if timeout is None: timeout = self._default_timeout - self._chain.wait.for_receipt(txhash, timeout=timeout) + result = self._chain.wait.for_receipt(txhash, timeout=timeout) + return result # class TestRpcBlockchain: # diff --git a/nkms_eth/config.py b/nkms_eth/config.py index 382eb9d10..8c7be3182 100644 --- a/nkms_eth/config.py +++ b/nkms_eth/config.py @@ -63,7 +63,6 @@ class NuCypherMinerConfig: def null_address(self): return self._null_addr - @property def mining_coefficient(self): return self.__mining_coeff @@ -74,18 +73,19 @@ class NuCypherMinerConfig: class PopulusConfig: + __project_name = 'nucypher-kms' - def __init__(self, project_name='nucypher-kms', registrar_path=None): - self._python_project_name = project_name + def __init__(self, registrar_path=None): # This config is persistent and is created in user's .local directory if registrar_path is None: - registrar_path = join(appdirs.user_data_dir(self._python_project_name), 'registrar.json') + registrar_path = join(appdirs.user_data_dir(self.__project_name), 'registrar.json') self._registrar_path = registrar_path # Populus project config self._project_dir = join(dirname(abspath(nkms_eth.__file__)), 'project') self._populus_project = populus.Project(self._project_dir) + self.project.config['chains.mainnetrpc.contracts.backends.JSONFile.settings.file_path'] = self._registrar_path @property diff --git a/nkms_eth/deployers.py b/nkms_eth/deployers.py index cdb979908..63217e15f 100644 --- a/nkms_eth/deployers.py +++ b/nkms_eth/deployers.py @@ -1,13 +1,16 @@ from abc import ABC, abstractmethod -from typing import Tuple +from typing import Tuple, Dict + +from populus.contracts.contract import PopulusContract from nkms_eth.config import NuCypherMinerConfig, NuCypherTokenConfig from .blockchain import TheBlockchain -class ContractDeployer(ABC): +class ContractDeployer: _contract_name = NotImplemented + _arming_word = "I UNDERSTAND" class ContractDeploymentError(Exception): pass