mirror of https://github.com/nucypher/nucypher.git
Removes minerIds and datastore
parent
e4253b6c5d
commit
2999110c16
|
@ -86,11 +86,6 @@ class Miner(NucypherTokenActor):
|
|||
|
||||
# Establish initial state
|
||||
self.is_me = is_me
|
||||
if self.ether_address is not constants.UNKNOWN_ACTOR:
|
||||
node_datastore = self.miner_agent._fetch_node_datastore(node_address=self.ether_address)
|
||||
else:
|
||||
node_datastore = constants.CONTRACT_DATASTORE_UNAVAILIBLE
|
||||
self.__node_datastore = node_datastore
|
||||
|
||||
@classmethod
|
||||
def from_config(cls, blockchain_config) -> 'Miner':
|
||||
|
@ -211,11 +206,9 @@ class Miner(NucypherTokenActor):
|
|||
if entire_balance is True:
|
||||
amount = self.token_balance
|
||||
|
||||
amount, lock_periods = int(amount), int(lock_periods) # Manual type checks below this point in the stack;
|
||||
staking_transactions = OrderedDict() # Time series of txhases
|
||||
|
||||
# Validate
|
||||
amount = self.blockchain.interface.w3.toInt(amount)
|
||||
assert self.__validate_stake(amount=amount, lock_periods=lock_periods)
|
||||
|
||||
# Transact
|
||||
|
|
|
@ -85,13 +85,6 @@ class MinerAgent(EthereumContractAgent):
|
|||
class NotEnoughMiners(Exception):
|
||||
pass
|
||||
|
||||
class MinerInfo(Enum):
|
||||
VALUE = 0
|
||||
DECIMALS = 1
|
||||
LAST_ACTIVE_PERIOD = 2
|
||||
CONFIRMED_PERIOD_1 = 3
|
||||
CONFIRMED_PERIOD_2 = 4
|
||||
|
||||
def __init__(self, token_agent: NucypherTokenAgent=None, *args, **kwargs):
|
||||
token_agent = token_agent if token_agent is not None else NucypherTokenAgent()
|
||||
super().__init__(blockchain=token_agent.blockchain, *args, **kwargs)
|
||||
|
@ -154,7 +147,7 @@ class MinerAgent(EthereumContractAgent):
|
|||
return txhash
|
||||
|
||||
def mint(self, node_address) -> Tuple[str, str]:
|
||||
"""Computes and transfers tokens to the miner's account"""
|
||||
"""Computes reward tokens for the miner's account"""
|
||||
|
||||
mint_txhash = self.contract.functions.mint().transact({'from': node_address})
|
||||
self.blockchain.wait_for_receipt(mint_txhash)
|
||||
|
@ -173,55 +166,20 @@ class MinerAgent(EthereumContractAgent):
|
|||
|
||||
return collection_txhash
|
||||
|
||||
# Node Datastore #
|
||||
|
||||
def _publish_datastore(self, node_address: str, data) -> str:
|
||||
"""Publish new data to the MinerEscrow contract as a public record associated with this miner."""
|
||||
|
||||
txhash = self.contract.functions.setMinerId(data).transact({'from': node_address})
|
||||
self.blockchain.wait_for_receipt(txhash)
|
||||
return txhash
|
||||
|
||||
def _get_datastore_entries(self, node_address: str) -> int:
|
||||
count_bytes = self.contract.functions.getMinerIdsLength(node_address).call()
|
||||
datastore_entries = self.blockchain.interface.w3.toInt(count_bytes)
|
||||
return datastore_entries
|
||||
|
||||
def _fetch_node_datastore(self, node_address):
|
||||
"""Cache a generator of all asosciated contract data for this miner."""
|
||||
|
||||
datastore_entries = self._get_datastore_entries(node_address=node_address)
|
||||
|
||||
def __node_datastore_reader():
|
||||
for index in range(datastore_entries):
|
||||
value = self.contract.functions.getMinerId(node_address, index).call()
|
||||
yield value
|
||||
|
||||
return __node_datastore_reader()
|
||||
|
||||
|
||||
#
|
||||
# Contract Utilities
|
||||
#
|
||||
def swarm(self, fetch_data: bool=False) -> Union[Generator[str, None, None], Generator[Tuple[str, bytes], None, None]]:
|
||||
def swarm(self) -> Union[Generator[str, None, None], Generator[Tuple[str, bytes], None, None]]:
|
||||
"""
|
||||
Returns an iterator of all miner addresses via cumulative sum, on-network.
|
||||
if fetch_data is true, tuples containing the address and the miners stored data are yielded.
|
||||
|
||||
Miner addresses are returned in the order in which they registered with the MinersEscrow contract's ledger
|
||||
|
||||
"""
|
||||
|
||||
for index in range(self.get_miner_population()):
|
||||
|
||||
miner_address = self.contract.functions.miners(index).call()
|
||||
validated_address = self.blockchain.interface.w3.toChecksumAddress(miner_address) # string address of next node
|
||||
|
||||
if fetch_data is True:
|
||||
stored_miner_data = self.contract.functions.getMinerIdsLength(miner_address).call()
|
||||
yield (validated_address, stored_miner_data)
|
||||
else:
|
||||
yield validated_address
|
||||
yield miner_address
|
||||
|
||||
def sample(self, quantity: int, duration: int, additional_ursulas: float=1.7, attempts: int=5) -> List[str]:
|
||||
"""
|
||||
|
|
|
@ -111,7 +111,7 @@ def datetime_to_period(datetime: maya.MayaDT) -> int:
|
|||
"""Converts a MayaDT instance to a period number."""
|
||||
|
||||
future_period = datetime._epoch // int(SECONDS_PER_PERIOD)
|
||||
return future_period
|
||||
return int(future_period)
|
||||
|
||||
|
||||
def calculate_period_duration(future_time: maya.MayaDT) -> int:
|
||||
|
|
|
@ -64,7 +64,6 @@ contract MinersEscrow is Issuer {
|
|||
uint256 lastActivePeriod;
|
||||
Downtime[] downtime;
|
||||
StakeInfo[] stakes;
|
||||
bytes[] minerIds;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -628,28 +627,6 @@ contract MinersEscrow is Issuer {
|
|||
policyManager = _policyManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Return the length of the miner ids array
|
||||
**/
|
||||
function getMinerIdsLength(address _miner) public view returns (uint256) {
|
||||
return minerInfo[_miner].minerIds.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Return the miner id
|
||||
**/
|
||||
function getMinerId(address _miner, uint256 _index) public view returns (bytes) {
|
||||
return minerInfo[_miner].minerIds[_index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Set the miner id
|
||||
**/
|
||||
function setMinerId(bytes _minerId) public {
|
||||
MinerInfo storage info = minerInfo[msg.sender];
|
||||
info.minerIds.push(_minerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Return the length of the miners array
|
||||
**/
|
||||
|
@ -737,18 +714,6 @@ contract MinersEscrow is Issuer {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get miner id bytes by delegatecall
|
||||
**/
|
||||
function delegateGetMinerId(address _target, string _signature, address _miner, uint256 _index)
|
||||
internal returns (bytes memory result)
|
||||
{
|
||||
bytes32 memoryAddress = delegateGetData(_target, _signature, 2, bytes32(_miner), bytes32(_index));
|
||||
assembly {
|
||||
result := add(memoryAddress, mload(memoryAddress))
|
||||
}
|
||||
}
|
||||
|
||||
function verifyState(address _testTarget) public onlyOwner {
|
||||
super.verifyState(_testTarget);
|
||||
require(uint256(delegateGet(_testTarget, "minLockedPeriods()")) ==
|
||||
|
@ -792,16 +757,6 @@ contract MinersEscrow is Issuer {
|
|||
stakeInfoToCheck.periods == stakeInfo.periods &&
|
||||
stakeInfoToCheck.lockedValue == stakeInfo.lockedValue);
|
||||
}
|
||||
|
||||
require(uint256(delegateGet(_testTarget, "getMinerIdsLength(address)", miner)) == info.minerIds.length);
|
||||
for (i = 0; i < info.minerIds.length && i < MAX_CHECKED_VALUES; i++) {
|
||||
// TODO try to optimize size
|
||||
bytes memory minerIdToCheck =
|
||||
delegateGetMinerId(_testTarget, "getMinerId(address,uint256)", minerAddress, i);
|
||||
bytes storage minerId = info.minerIds[i];
|
||||
require(minerIdToCheck.length == minerId.length &&
|
||||
keccak256(minerIdToCheck) == keccak256(minerId));
|
||||
}
|
||||
}
|
||||
|
||||
function finishUpgrade(address _target) public onlyOwner {
|
||||
|
|
|
@ -894,38 +894,6 @@ def test_pre_deposit(testerchain, token, escrow_contract):
|
|||
assert 250 == event_args['periods']
|
||||
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_miner_id(testerchain, token, escrow_contract):
|
||||
escrow = escrow_contract(5 * 10 ** 8)
|
||||
creator = testerchain.interface.w3.eth.accounts[0]
|
||||
miner = testerchain.interface.w3.eth.accounts[1]
|
||||
|
||||
# Initialize contract and miner
|
||||
tx = escrow.functions.initialize().transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = token.functions.transfer(miner, 1000).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
balance = token.functions.balanceOf(miner).call()
|
||||
tx = token.functions.approve(escrow.address, balance).transact({'from': miner})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = escrow.functions.deposit(balance, 2).transact({'from': miner})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Set miner ids
|
||||
miner_id = os.urandom(33)
|
||||
tx = escrow.functions.setMinerId(miner_id).transact({'from': miner})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert 1 == escrow.functions.getMinerIdsLength(miner).call()
|
||||
|
||||
assert miner_id == escrow.functions.getMinerId(miner, 0).call()
|
||||
miner_id = os.urandom(66)
|
||||
tx = escrow.functions.setMinerId(miner_id).transact({'from': miner})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert 2 == escrow.functions.getMinerIdsLength(miner).call()
|
||||
|
||||
assert miner_id == escrow.functions.getMinerId(miner, 1).call()
|
||||
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_verifying_state(testerchain, token):
|
||||
creator = testerchain.interface.w3.eth.accounts[0]
|
||||
|
@ -963,9 +931,6 @@ def test_verifying_state(testerchain, token):
|
|||
tx = token.functions.approve(contract.address, balance).transact({'from': miner})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = contract.functions.deposit(balance, 1000).transact({'from': miner})
|
||||
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = contract.functions.setMinerId(testerchain.interface.w3.toBytes(111)).transact({'from': miner})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
# Upgrade to the second version
|
||||
|
@ -976,8 +941,6 @@ def test_verifying_state(testerchain, token):
|
|||
assert 1500 == contract.functions.maxAllowableLockedTokens().call()
|
||||
assert policy_manager.address == contract.functions.policyManager().call()
|
||||
assert 2 == contract.functions.valueToCheck().call()
|
||||
assert 1 == testerchain.interface.w3.toInt(contract.functions.getMinerIdsLength(miner).call())
|
||||
assert 111 == testerchain.interface.w3.toInt(contract.functions.getMinerId(miner, 0).call())
|
||||
tx = contract.functions.setValueToCheck(3).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert 3 == contract.functions.valueToCheck().call()
|
||||
|
|
|
@ -21,26 +21,23 @@ class TestMiner:
|
|||
def test_miner_locking_tokens(self, testerchain, miner, mock_miner_agent):
|
||||
|
||||
testerchain.ether_airdrop(amount=10000)
|
||||
|
||||
assert constants.MIN_ALLOWED_LOCKED < miner.token_balance, "Insufficient miner balance"
|
||||
|
||||
now = maya.now()
|
||||
expiration = now.add(days=constants.MIN_LOCKED_PERIODS)
|
||||
|
||||
miner.stake(amount=constants.MIN_ALLOWED_LOCKED, # Lock the minimum amount of tokens
|
||||
expiration = maya.now().add(days=constants.MIN_LOCKED_PERIODS)
|
||||
miner.stake(amount=int(constants.MIN_ALLOWED_LOCKED), # Lock the minimum amount of tokens
|
||||
expiration=expiration)
|
||||
# lock_periods=constants.MIN_LOCKED_PERIODS) # ... for the fewest number of periods
|
||||
|
||||
# Verify that the escrow is "approved" to receive tokens
|
||||
assert mock_miner_agent.token_agent.contract.functions.allowance(miner.ether_address,
|
||||
mock_miner_agent.contract_address).call() == 0
|
||||
allowance = mock_miner_agent.token_agent.contract.functions.allowance(
|
||||
miner.ether_address,
|
||||
mock_miner_agent.contract_address).call()
|
||||
assert 0 == allowance
|
||||
|
||||
# Staking starts after one period
|
||||
assert mock_miner_agent.contract.functions.getLockedTokens(miner.ether_address).call() == 0
|
||||
|
||||
# Wait for it...
|
||||
testerchain.time_travel(periods=1)
|
||||
assert mock_miner_agent.contract.functions.getLockedTokens(miner.ether_address).call() == constants.MIN_ALLOWED_LOCKED
|
||||
locked_tokens = mock_miner_agent.contract.functions.getLockedTokens(miner.ether_address).call()
|
||||
assert 0 == locked_tokens
|
||||
locked_tokens = mock_miner_agent.contract.functions.getLockedTokens(miner.ether_address, 1).call()
|
||||
assert constants.MIN_ALLOWED_LOCKED == locked_tokens
|
||||
|
||||
@pytest.mark.usefixtures("mock_policy_agent")
|
||||
def test_miner_divides_stake(self, miner):
|
||||
|
@ -78,10 +75,10 @@ class TestMiner:
|
|||
|
||||
# Capture the current token balance of the miner
|
||||
initial_balance = miner.token_balance
|
||||
assert mock_token_agent.get_balance(miner.ether_address) == miner.token_balance
|
||||
assert mock_token_agent.get_balance(miner.ether_address) == initial_balance
|
||||
|
||||
miner.stake(amount=constants.MIN_ALLOWED_LOCKED, # Lock the minimum amount of tokens
|
||||
lock_periods=constants.MIN_LOCKED_PERIODS) # ... for the fewest number of periods
|
||||
miner.stake(amount=int(constants.MIN_ALLOWED_LOCKED), # Lock the minimum amount of tokens
|
||||
lock_periods=int(constants.MIN_LOCKED_PERIODS)) # ... for the fewest number of periods
|
||||
|
||||
# Have other address lock tokens
|
||||
_origin, ursula, *everybody_else = deployed_testerchain.interface.w3.eth.accounts
|
||||
|
|
|
@ -31,8 +31,9 @@ def test_get_swarm(mock_miner_agent):
|
|||
@pytest.mark.usefixtures("miners")
|
||||
def test_sample_miners(mock_miner_agent):
|
||||
|
||||
miners_population = mock_miner_agent.get_miner_population()
|
||||
with pytest.raises(MinerAgent.NotEnoughMiners):
|
||||
mock_miner_agent.sample(quantity=100) # Waay more than we have deployed
|
||||
mock_miner_agent.sample(quantity=miners_population + 1) # Way more than we have deployed
|
||||
|
||||
miners = mock_miner_agent.sample(quantity=3)
|
||||
assert len(miners) == 3 # Three..
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
import pytest
|
||||
|
||||
from nucypher.blockchain.eth.agents import NucypherTokenAgent, MinerAgent
|
||||
from nucypher.blockchain.eth.deployers import NucypherTokenDeployer, MinerEscrowDeployer, PolicyManagerDeployer
|
||||
from nucypher.blockchain.eth.interfaces import EthereumContractRegistrar
|
||||
|
||||
|
||||
def test_token_deployer_and_agent(testerchain):
|
||||
origin, *everybody_else = testerchain.interface.w3.eth.accounts
|
||||
|
||||
# Trying to get token from blockchain before it's been published fails
|
||||
with pytest.raises(EthereumContractRegistrar.UnknownContract):
|
||||
NucypherTokenAgent(blockchain=testerchain)
|
||||
|
||||
# The big day...
|
||||
deployer = NucypherTokenDeployer(blockchain=testerchain, deployer_address=origin)
|
||||
|
||||
# It's not armed
|
||||
with pytest.raises(NucypherTokenDeployer.ContractDeploymentError):
|
||||
deployer.deploy()
|
||||
|
||||
# Token must be armed before deploying to the blockchain
|
||||
deployer.arm()
|
||||
deployer.deploy()
|
||||
|
||||
# Create a token instance
|
||||
token_agent = deployer.make_agent()
|
||||
token_contract = testerchain.get_contract(token_agent.contract_address)
|
||||
expected_token_supply = token_contract.functions.totalSupply().call()
|
||||
assert expected_token_supply == token_agent.contract.functions.totalSupply().call()
|
||||
|
||||
# Retrieve the token from the blockchain
|
||||
same_token_agent = NucypherTokenAgent(blockchain=testerchain)
|
||||
|
||||
# Compare the contract address for equality
|
||||
assert token_agent.contract_address == same_token_agent.contract_address
|
||||
assert token_agent == same_token_agent # __eq__
|
||||
|
||||
|
||||
@pytest.mark.slow()
|
||||
def test_deploy_ethereum_contracts(testerchain):
|
||||
"""
|
||||
Launch all ethereum contracts:
|
||||
- NuCypherToken
|
||||
- PolicyManager
|
||||
- MinersEscrow
|
||||
- UserEscrow
|
||||
- Issuer
|
||||
"""
|
||||
origin, *everybody_else = testerchain.interface.w3.eth.accounts
|
||||
|
||||
token_deployer = NucypherTokenDeployer(blockchain=testerchain, deployer_address=origin)
|
||||
token_deployer.arm()
|
||||
token_deployer.deploy()
|
||||
|
||||
token_agent = NucypherTokenAgent(blockchain=testerchain)
|
||||
|
||||
miner_escrow_deployer = MinerEscrowDeployer(token_agent=token_agent, deployer_address=origin)
|
||||
miner_escrow_deployer.arm()
|
||||
miner_escrow_deployer.deploy()
|
||||
|
||||
miner_agent = MinerAgent(token_agent=token_agent)
|
||||
|
||||
policy_manager_contract = PolicyManagerDeployer(miner_agent=miner_agent, deployer_address=origin)
|
||||
policy_manager_contract.arm()
|
||||
policy_manager_contract.deploy()
|
||||
|
||||
# TODO: Assert
|
Loading…
Reference in New Issue