Fixes #1765 - Deprecates Seeder Contract.

pull/1885/head
Kieran Prasch 2020-04-14 11:33:15 -07:00
parent cc83797f47
commit c7541df6a8
No known key found for this signature in database
GPG Key ID: 199AB839D4125A62
9 changed files with 6 additions and 207 deletions

View File

@ -59,7 +59,6 @@ from nucypher.blockchain.eth.deployers import (
AdjudicatorDeployer, AdjudicatorDeployer,
BaseContractDeployer, BaseContractDeployer,
WorklockDeployer, WorklockDeployer,
SeederDeployer,
MultiSigDeployer MultiSigDeployer
) )
from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface, BlockchainInterfaceFactory from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface, BlockchainInterfaceFactory
@ -180,7 +179,6 @@ class ContractAdministrator(NucypherTokenActor):
aux_deployer_classes = ( aux_deployer_classes = (
WorklockDeployer, WorklockDeployer,
MultiSigDeployer, MultiSigDeployer,
SeederDeployer
) )
# For ownership relinquishment series. # For ownership relinquishment series.

View File

@ -16,16 +16,14 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
""" """
import importlib import importlib
import math
import random import random
from typing import Generator, List, Tuple, Union from typing import Generator, List, Tuple, Union
import math
from constant_sorrow.constants import NO_CONTRACT_AVAILABLE from constant_sorrow.constants import NO_CONTRACT_AVAILABLE
from eth_utils.address import to_checksum_address from eth_utils.address import to_checksum_address
from eth_tester.exceptions import TransactionFailed
from twisted.logger import Logger from twisted.logger import Logger
from web3.contract import Contract from web3.contract import Contract
from web3.exceptions import BadFunctionCallOutput
from nucypher.blockchain.eth.constants import ( from nucypher.blockchain.eth.constants import (
DISPATCHER_CONTRACT_NAME, DISPATCHER_CONTRACT_NAME,
@ -37,12 +35,12 @@ from nucypher.blockchain.eth.constants import (
ADJUDICATOR_CONTRACT_NAME, ADJUDICATOR_CONTRACT_NAME,
NUCYPHER_TOKEN_CONTRACT_NAME, NUCYPHER_TOKEN_CONTRACT_NAME,
MULTISIG_CONTRACT_NAME, MULTISIG_CONTRACT_NAME,
SEEDER_CONTRACT_NAME,
ETH_ADDRESS_BYTE_LENGTH, ETH_ADDRESS_BYTE_LENGTH,
NULL_ADDRESS) NULL_ADDRESS
)
from nucypher.blockchain.eth.decorators import validate_checksum_address from nucypher.blockchain.eth.decorators import validate_checksum_address
from nucypher.blockchain.eth.events import ContractEvents from nucypher.blockchain.eth.events import ContractEvents
from nucypher.blockchain.eth.interfaces import BlockchainInterface, BlockchainInterfaceFactory from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
from nucypher.blockchain.eth.registry import AllocationRegistry, BaseContractRegistry from nucypher.blockchain.eth.registry import AllocationRegistry, BaseContractRegistry
from nucypher.blockchain.eth.utils import epoch_to_period from nucypher.blockchain.eth.utils import epoch_to_period
from nucypher.crypto.api import sha256_digest from nucypher.crypto.api import sha256_digest
@ -1236,37 +1234,6 @@ class WorkLockAgent(EthereumContractAgent):
return parameters return parameters
class SeederAgent(EthereumContractAgent):
registry_contract_name = SEEDER_CONTRACT_NAME
def enroll(self, sender_address: str, seed_address: str, ip: str, port: int) -> dict:
# TODO: Protection for over-enrollment
contract_function = self.contract.functions.enroll(seed_address, ip, port)
receipt = self.blockchain.send_transaction(contract_function=contract_function,
sender_address=sender_address)
return receipt
def refresh(self, sender_address: str, ip: str, port: int) -> dict:
contract_function = self.contract.functions.refresh(ip, port)
receipt = self.blockchain.send_transaction(contract_function=contract_function,
sender_address=sender_address)
return receipt
def get_entries(self) -> int:
length = self.contract.functions.getSeedArrayLength().call()
return length
def dump(self) -> list:
total = self.get_entries()
entries = list()
for index in range(total):
ip = self.contract.functions.seedArray(index).call()
entry = self.contract.functions.seeds(ip).call()
entries.append(entry)
return entries
class MultiSigAgent(EthereumContractAgent): class MultiSigAgent(EthereumContractAgent):
registry_contract_name = MULTISIG_CONTRACT_NAME registry_contract_name = MULTISIG_CONTRACT_NAME
@ -1363,4 +1330,3 @@ class MultiSigAgent(EthereumContractAgent):
contract_function = self.contract.functions.execute(v, r, s, destination, value, data) contract_function = self.contract.functions.execute(v, r, s, destination, value, data)
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=sender_address) receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=sender_address)
return receipt return receipt

View File

@ -30,7 +30,6 @@ PREALLOCATION_ESCROW_CONTRACT_NAME = 'PreallocationEscrow'
ADJUDICATOR_CONTRACT_NAME = 'Adjudicator' ADJUDICATOR_CONTRACT_NAME = 'Adjudicator'
WORKLOCK_CONTRACT_NAME = 'WorkLock' WORKLOCK_CONTRACT_NAME = 'WorkLock'
MULTISIG_CONTRACT_NAME = 'MultiSig' MULTISIG_CONTRACT_NAME = 'MultiSig'
SEEDER_CONTRACT_NAME = 'Seeder'
NUCYPHER_CONTRACT_NAMES = ( NUCYPHER_CONTRACT_NAMES = (
DISPATCHER_CONTRACT_NAME, DISPATCHER_CONTRACT_NAME,
@ -43,7 +42,6 @@ NUCYPHER_CONTRACT_NAMES = (
ADJUDICATOR_CONTRACT_NAME, ADJUDICATOR_CONTRACT_NAME,
WORKLOCK_CONTRACT_NAME, WORKLOCK_CONTRACT_NAME,
MULTISIG_CONTRACT_NAME, MULTISIG_CONTRACT_NAME,
SEEDER_CONTRACT_NAME
) )

View File

@ -39,7 +39,6 @@ from nucypher.blockchain.eth.agents import (
PreallocationEscrowAgent, PreallocationEscrowAgent,
AdjudicatorAgent, AdjudicatorAgent,
WorkLockAgent, WorkLockAgent,
SeederAgent,
MultiSigAgent, MultiSigAgent,
ContractAgency ContractAgency
) )
@ -1202,30 +1201,6 @@ class WorklockDeployer(BaseContractDeployer):
return approve_receipt, funding_receipt return approve_receipt, funding_receipt
class SeederDeployer(BaseContractDeployer, OwnableContractMixin):
agency = SeederAgent
contract_name = agency.registry_contract_name
deployment_steps = ('contract_deployment', )
_upgradeable = False
MAX_SEEDS = 10 # TODO: Move to economics?
def deploy(self, gas_limit: int = None, progress: int = None, **overrides) -> dict:
self.check_deployment_readiness()
constructor_args = (self.MAX_SEEDS,)
seeder_contract, receipt = self.blockchain.deploy_contract(self.deployer_address,
self.registry,
self.contract_name,
*constructor_args,
gas_limit=gas_limit)
self._contract = seeder_contract
if progress:
progress.update(1)
self.deployment_receipts.update({self.deployment_steps[0]: receipt})
return self.deployment_receipts
class MultiSigDeployer(BaseContractDeployer): class MultiSigDeployer(BaseContractDeployer):
agency = MultiSigAgent agency = MultiSigAgent

View File

@ -1,71 +0,0 @@
pragma solidity ^0.6.1;
import "zeppelin/ownership/Ownable.sol";
/**
* @notice Contract holds references to seed
* node interface information for bootstrapping the network.
*/
contract Seeder is Ownable {
struct SeedInfo {
string ip;
uint16 port;
}
mapping (address => SeedInfo) public seeds;
address[] public seedArray;
/**
* @param _maxSeeds The quantity of maximum seed nodes the contract can store
*/
constructor(uint256 _maxSeeds) public {
seedArray = new address[](_maxSeeds);
}
/**
* @notice Returns the length of the seed nodes array
*/
function getSeedArrayLength()
external view returns (uint256)
{
return seedArray.length;
}
/**
* @notice Write a new seed address and interface info to contract storage
* @param _ip IPv4 address of the seed node
* @param _port TCP port of the seed node
*/
function enroll(address _seed, string calldata _ip, uint16 _port) external onlyOwner {
seeds[_seed] = SeedInfo(_ip, _port);
uint256 i = 0;
for (; i < seedArray.length; i++) {
address currentSeed = seedArray[i];
if (currentSeed == address(0)) {
seedArray[i] = _seed;
break;
} else if (currentSeed == _seed) {
break;
}
}
require(i < seedArray.length,
'Not enough slots to enroll a new seed node');
}
/**
* @notice Seed updates itself.
* @param _ip Updated IPv4 address of the existing seed node
* @param _port Updated TCP port of the existing seed node
*/
function refresh(string calldata _ip, uint16 _port) external {
SeedInfo storage seed = seeds[msg.sender];
require(seed.port != 0);
seed.ip = _ip;
seed.port = _port;
}
}

View File

@ -47,7 +47,7 @@ DEFAULT_CONFIG_ROOT = os.getenv('NUCYPHER_CONFIG_ROOT', default=APP_DIR.user_dat
USER_LOG_DIR = os.getenv('NUCYPHER_USER_LOG_DIR', default=APP_DIR.user_log_dir) USER_LOG_DIR = os.getenv('NUCYPHER_USER_LOG_DIR', default=APP_DIR.user_log_dir)
# Static Seednodes (Not from seeder contract) # Static Seednodes
SeednodeMetadata = namedtuple('seednode', ['checksum_address', 'rest_host', 'rest_port']) SeednodeMetadata = namedtuple('seednode', ['checksum_address', 'rest_host', 'rest_port'])
SEEDNODES = tuple() SEEDNODES = tuple()

View File

@ -77,8 +77,6 @@ NUMBER_OF_URSULAS_IN_DEVELOPMENT_NETWORK = NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS
TEST_CONTRACTS_DIR = os.path.join(BASE_DIR, 'tests', 'blockchain', 'eth', 'contracts', 'contracts') TEST_CONTRACTS_DIR = os.path.join(BASE_DIR, 'tests', 'blockchain', 'eth', 'contracts', 'contracts')
MAX_TEST_SEEDER_ENTRIES = 20
ONE_YEAR_IN_SECONDS = ((60 * 60) * 24) * 365 ONE_YEAR_IN_SECONDS = ((60 * 60) * 24) * 365
DEVELOPMENT_TOKEN_AIRDROP_AMOUNT = NU(1_000_000, 'NU') DEVELOPMENT_TOKEN_AIRDROP_AMOUNT = NU(1_000_000, 'NU')

View File

@ -1,65 +0,0 @@
"""
This file is part of nucypher.
nucypher is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
nucypher is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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 pytest
from eth_tester.exceptions import TransactionFailed
from nucypher.blockchain.eth.constants import NULL_ADDRESS
from nucypher.utilities.sandbox.constants import (
MOCK_IP_ADDRESS,
MOCK_IP_ADDRESS_2,
MAX_TEST_SEEDER_ENTRIES,
MOCK_URSULA_STARTING_PORT
)
@pytest.mark.slow()
def test_seeder(testerchain, deploy_contract):
origin, seed_address, another_seed_address, *everyone_else = testerchain.client.accounts
seed = (MOCK_IP_ADDRESS, MOCK_URSULA_STARTING_PORT)
another_seed = (MOCK_IP_ADDRESS_2, MOCK_URSULA_STARTING_PORT + 1)
contract, _txhash = deploy_contract('Seeder', MAX_TEST_SEEDER_ENTRIES)
assert contract.functions.getSeedArrayLength().call() == MAX_TEST_SEEDER_ENTRIES
assert contract.functions.owner().call() == origin
with pytest.raises((TransactionFailed, ValueError)):
txhash = contract.functions.enroll(seed_address, *seed).transact({'from': seed_address})
testerchain.wait_for_receipt(txhash)
with pytest.raises((TransactionFailed, ValueError)):
txhash = contract.functions.refresh(*seed).transact({'from': seed_address})
testerchain.wait_for_receipt(txhash)
txhash = contract.functions.enroll(seed_address, *seed).transact({'from': origin})
testerchain.wait_for_receipt(txhash)
assert contract.functions.seeds(seed_address).call() == [*seed]
assert contract.functions.seedArray(0).call() == seed_address
assert contract.functions.seedArray(1).call() == NULL_ADDRESS
txhash = contract.functions.enroll(another_seed_address, *another_seed).transact({'from': origin})
testerchain.wait_for_receipt(txhash)
assert contract.functions.seeds(another_seed_address).call() == [*another_seed]
assert contract.functions.seedArray(0).call() == seed_address
assert contract.functions.seedArray(1).call() == another_seed_address
assert contract.functions.seedArray(2).call() == NULL_ADDRESS
txhash = contract.functions.refresh(*another_seed).transact({'from': seed_address})
testerchain.wait_for_receipt(txhash)
assert contract.functions.seedArray(0).call() == seed_address
assert contract.functions.seeds(seed_address).call() == [*another_seed]

View File

@ -113,7 +113,7 @@ def test_deploy_single_contract(click_runner, registry_filepath):
# Perform the Test # Perform the Test
command = ['contracts', command = ['contracts',
'--contract-name', 'Seeder', '--contract-name', 'NuCypherToken',
'--registry-infile', registry_filepath, '--registry-infile', registry_filepath,
'--provider', TEST_PROVIDER_URI, '--provider', TEST_PROVIDER_URI,
'--poa', '--poa',