mirror of https://github.com/nucypher/nucypher.git
More general deployment modes: Meet Bare, Idle and Full
Idle = Deploy contract in 'idle' state, without activationpull/1738/head
parent
5968b519d8
commit
e55ccf2341
|
@ -28,6 +28,9 @@ import maya
|
|||
from constant_sorrow.constants import (
|
||||
WORKER_NOT_RUNNING,
|
||||
NO_WORKER_ASSIGNED,
|
||||
BARE,
|
||||
IDLE,
|
||||
FULL
|
||||
)
|
||||
from eth_tester.exceptions import TransactionFailed
|
||||
from eth_utils import keccak, is_checksum_address, to_checksum_address
|
||||
|
@ -265,7 +268,7 @@ class ContractAdministrator(NucypherTokenActor):
|
|||
contract_name: str,
|
||||
gas_limit: int = None,
|
||||
plaintext_secret: str = None,
|
||||
bare: bool = False,
|
||||
deployment_mode=FULL,
|
||||
ignore_deployed: bool = False,
|
||||
progress=None,
|
||||
confirmations: int = 0,
|
||||
|
@ -286,7 +289,7 @@ class ContractAdministrator(NucypherTokenActor):
|
|||
|
||||
self.transacting_power.activate() # Activate the TransactingPower in case too much time has passed
|
||||
if Deployer._upgradeable:
|
||||
is_initial_deployment = not bare
|
||||
is_initial_deployment = deployment_mode != BARE # i.e., we also deploy a dispatcher
|
||||
if is_initial_deployment and not plaintext_secret:
|
||||
raise ValueError("An upgrade secret must be passed to perform initial deployment of a Dispatcher.")
|
||||
secret_hash = None
|
||||
|
@ -294,14 +297,16 @@ class ContractAdministrator(NucypherTokenActor):
|
|||
secret_hash = keccak(bytes(plaintext_secret, encoding='utf-8'))
|
||||
receipts = deployer.deploy(secret_hash=secret_hash,
|
||||
gas_limit=gas_limit,
|
||||
initial_deployment=is_initial_deployment,
|
||||
progress=progress,
|
||||
ignore_deployed=ignore_deployed,
|
||||
confirmations=confirmations)
|
||||
confirmations=confirmations,
|
||||
deployment_mode=deployment_mode,
|
||||
**deployment_parameters)
|
||||
else:
|
||||
receipts = deployer.deploy(gas_limit=gas_limit,
|
||||
progress=progress,
|
||||
confirmations=confirmations,
|
||||
deployment_mode=deployment_mode,
|
||||
**deployment_parameters)
|
||||
return receipts, deployer
|
||||
|
||||
|
|
|
@ -19,7 +19,14 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
from collections import OrderedDict
|
||||
from typing import Tuple, Dict, List
|
||||
|
||||
from constant_sorrow.constants import CONTRACT_NOT_DEPLOYED, NO_DEPLOYER_CONFIGURED, NO_BENEFICIARY
|
||||
from constant_sorrow.constants import (
|
||||
CONTRACT_NOT_DEPLOYED,
|
||||
NO_DEPLOYER_CONFIGURED,
|
||||
NO_BENEFICIARY,
|
||||
BARE,
|
||||
IDLE,
|
||||
FULL
|
||||
)
|
||||
from web3 import Web3
|
||||
from web3.contract import Contract
|
||||
|
||||
|
@ -36,11 +43,11 @@ from nucypher.blockchain.eth.agents import (
|
|||
MultiSigAgent,
|
||||
ContractAgency
|
||||
)
|
||||
from nucypher.blockchain.eth.constants import DISPATCHER_CONTRACT_NAME, STAKING_INTERFACE_ROUTER_CONTRACT_NAME
|
||||
from nucypher.blockchain.eth.constants import DISPATCHER_CONTRACT_NAME
|
||||
from nucypher.blockchain.eth.decorators import validate_secret, validate_checksum_address
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
|
||||
from nucypher.blockchain.eth.interfaces import (
|
||||
BlockchainDeployerInterface,
|
||||
BlockchainInterfaceFactory,
|
||||
VersionedContract
|
||||
)
|
||||
from nucypher.blockchain.eth.registry import AllocationRegistry
|
||||
|
@ -59,6 +66,8 @@ class BaseContractDeployer:
|
|||
_ownable = NotImplemented
|
||||
_proxy_deployer = NotImplemented
|
||||
|
||||
can_be_idle = False
|
||||
|
||||
class ContractDeploymentError(Exception):
|
||||
pass
|
||||
|
||||
|
@ -493,7 +502,11 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
|
||||
agency = StakingEscrowAgent
|
||||
contract_name = agency.registry_contract_name
|
||||
deployment_steps = ('contract_deployment', 'dispatcher_deployment', 'approve_reward_transfer', 'initialize')
|
||||
|
||||
can_be_idle = True
|
||||
preparation_steps = ('contract_deployment', 'dispatcher_deployment')
|
||||
activation_steps = ('approve_reward_transfer', 'initialize')
|
||||
deployment_steps = preparation_steps + activation_steps
|
||||
_proxy_deployer = DispatcherDeployer
|
||||
|
||||
def __init__(self, test_mode: bool = False, *args, **kwargs):
|
||||
|
@ -535,7 +548,7 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
return the_escrow_contract, deploy_receipt
|
||||
|
||||
def deploy(self,
|
||||
initial_deployment: bool = True,
|
||||
deployment_mode=FULL,
|
||||
secret_hash: bytes = None,
|
||||
gas_limit: int = None,
|
||||
progress=None,
|
||||
|
@ -557,7 +570,10 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
Returns transaction receipts in a dict.
|
||||
"""
|
||||
|
||||
if initial_deployment and not secret_hash:
|
||||
if deployment_mode not in (BARE, IDLE, FULL):
|
||||
raise ValueError(f"Invalid deployment mode ({deployment_mode})")
|
||||
|
||||
if deployment_mode is not BARE and not secret_hash:
|
||||
raise ValueError(f"An upgrade secret hash is required to perform an initial"
|
||||
f" deployment series for {self.contract_name}.")
|
||||
|
||||
|
@ -576,10 +592,10 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
**overrides)
|
||||
|
||||
# This is the end of bare deployment.
|
||||
if not initial_deployment:
|
||||
if deployment_mode is BARE:
|
||||
self._contract = the_escrow_contract
|
||||
return self._finish_bare_deployment(deployment_receipt=deploy_receipt,
|
||||
progress=progress)
|
||||
receipts = self._finish_bare_deployment(deployment_receipt=deploy_receipt, progress=progress)
|
||||
return receipts
|
||||
|
||||
if progress:
|
||||
progress.update(1)
|
||||
|
@ -603,10 +619,27 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
target_contract=the_escrow_contract)
|
||||
|
||||
# Switch the contract for the wrapped one
|
||||
the_escrow_contract = wrapped_escrow_contract
|
||||
self._contract = wrapped_escrow_contract
|
||||
|
||||
# 3 - Approve transfer the reward supply tokens to StakingEscrow #
|
||||
approve_reward_function = self.token_contract.functions.approve(the_escrow_contract.address,
|
||||
preparation_receipts = dict(zip(self.preparation_steps, (deploy_receipt, dispatcher_deploy_receipt)))
|
||||
self.deployment_receipts = preparation_receipts
|
||||
|
||||
if deployment_mode is IDLE:
|
||||
# This is the end of deployment without activation: the contract is now idle, waiting for activation
|
||||
return preparation_receipts
|
||||
else: # deployment_mode is FULL
|
||||
activation_receipts = self.activate(gas_limit=gas_limit, progress=progress)
|
||||
self.deployment_receipts.update(activation_receipts)
|
||||
return self.deployment_receipts
|
||||
|
||||
def activate(self, gas_limit: int = None, progress=None):
|
||||
|
||||
origin_args = {}
|
||||
if gas_limit:
|
||||
origin_args.update({'gas': gas_limit}) # TODO: #842 - Gas Management
|
||||
|
||||
# 3 - Approve transferring the reward supply tokens to StakingEscrow #
|
||||
approve_reward_function = self.token_contract.functions.approve(self._contract.address,
|
||||
self.economics.erc20_reward_supply)
|
||||
|
||||
# TODO: Confirmations / Successful Transaction Indicator / Events ?? - #1193, #1194
|
||||
|
@ -617,22 +650,15 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
progress.update(1)
|
||||
|
||||
# 4 - Initialize the StakingEscrow contract
|
||||
init_function = the_escrow_contract.functions.initialize(self.economics.erc20_reward_supply)
|
||||
|
||||
init_function = self._contract.functions.initialize(self.economics.erc20_reward_supply)
|
||||
init_receipt = self.blockchain.send_transaction(contract_function=init_function,
|
||||
sender_address=self.deployer_address,
|
||||
payload=origin_args)
|
||||
if progress:
|
||||
progress.update(1)
|
||||
|
||||
# Gather the transaction receipts
|
||||
ordered_receipts = (deploy_receipt, dispatcher_deploy_receipt, approve_reward_receipt, init_receipt)
|
||||
deployment_receipts = dict(zip(self.deployment_steps, ordered_receipts))
|
||||
|
||||
# Set the contract and transaction receipts #
|
||||
self._contract = the_escrow_contract
|
||||
self.deployment_receipts = deployment_receipts
|
||||
return deployment_receipts
|
||||
activation_receipts = dict(zip(self.activation_steps, (approve_reward_receipt, init_receipt)))
|
||||
return activation_receipts
|
||||
|
||||
|
||||
class PolicyManagerDeployer(BaseContractDeployer, UpgradeableContractMixin, OwnableContractMixin):
|
||||
|
|
|
@ -19,6 +19,12 @@ import json
|
|||
import os
|
||||
|
||||
import click
|
||||
from constant_sorrow import constants
|
||||
from constant_sorrow.constants import (
|
||||
BARE,
|
||||
IDLE,
|
||||
FULL
|
||||
)
|
||||
|
||||
from nucypher.blockchain.eth.actors import ContractAdministrator, Trustee
|
||||
from nucypher.blockchain.eth.agents import NucypherTokenAgent, ContractAgency, MultiSigAgent
|
||||
|
@ -359,13 +365,19 @@ def rollback(general_config, actor_options):
|
|||
@deploy.command()
|
||||
@group_general_config
|
||||
@group_actor_options
|
||||
@click.option('--bare', help="Deploy a contract *only* without any additional operations.", is_flag=True)
|
||||
@click.option('--mode',
|
||||
help="Deploy a contract following all steps ('full'), up to idle status ('idle'), "
|
||||
"or just the bare contract ('bare'). Defaults to 'full'",
|
||||
type=click.Choice(['full', 'idle', 'bare']),
|
||||
#case_sensitive
|
||||
default='full'
|
||||
)
|
||||
@option_gas
|
||||
@option_ignore_deployed
|
||||
@click.option('--confirmations', help="Number of required block confirmations", type=click.IntRange(min=0))
|
||||
@click.option('--parameters', help="Filepath to a JSON file containing additional deployment parameters",
|
||||
type=EXISTING_READABLE_FILE)
|
||||
def contracts(general_config, actor_options, bare, gas, ignore_deployed, confirmations, parameters):
|
||||
def contracts(general_config, actor_options, mode, gas, ignore_deployed, confirmations, parameters):
|
||||
"""
|
||||
Compile and deploy contracts.
|
||||
"""
|
||||
|
@ -383,6 +395,7 @@ def contracts(general_config, actor_options, bare, gas, ignore_deployed, confirm
|
|||
# Deploy Single Contract (Amend Registry)
|
||||
#
|
||||
contract_name = actor_options.contract_name
|
||||
deployment_mode = constants.__getattr__(mode.upper()) # TODO: constant sorrow
|
||||
if contract_name:
|
||||
try:
|
||||
contract_deployer = ADMINISTRATOR.deployers[contract_name]
|
||||
|
@ -393,24 +406,24 @@ def contracts(general_config, actor_options, bare, gas, ignore_deployed, confirm
|
|||
|
||||
# Deploy
|
||||
emitter.echo(f"Deploying {contract_name}")
|
||||
if contract_deployer._upgradeable and not bare:
|
||||
if contract_deployer._upgradeable and deployment_mode is not BARE:
|
||||
# NOTE: Bare deployments do not engage the proxy contract
|
||||
secret = ADMINISTRATOR.collect_deployment_secret(deployer=contract_deployer)
|
||||
receipts, agent = ADMINISTRATOR.deploy_contract(contract_name=contract_name,
|
||||
plaintext_secret=secret,
|
||||
gas_limit=gas,
|
||||
bare=bare,
|
||||
deployment_mode=deployment_mode,
|
||||
ignore_deployed=ignore_deployed,
|
||||
confirmations=confirmations)
|
||||
confirmations=confirmations,
|
||||
deployment_parameters=deployment_parameters)
|
||||
else:
|
||||
# Non-Upgradeable or Bare
|
||||
receipts, agent = ADMINISTRATOR.deploy_contract(contract_name=contract_name,
|
||||
gas_limit=gas,
|
||||
bare=bare,
|
||||
deployment_mode=deployment_mode,
|
||||
ignore_deployed=ignore_deployed,
|
||||
confirmations=confirmations,
|
||||
deployment_parameters=deployment_parameters
|
||||
)
|
||||
deployment_parameters=deployment_parameters)
|
||||
|
||||
# Report
|
||||
paint_contract_deployment(contract_name=contract_name,
|
||||
|
@ -424,6 +437,9 @@ def contracts(general_config, actor_options, bare, gas, ignore_deployed, confirm
|
|||
#
|
||||
# Deploy Automated Series (Create Registry)
|
||||
#
|
||||
if deployment_mode is not FULL:
|
||||
raise click.BadOptionUsage(option_name='--mode',
|
||||
message="Only 'full' mode is supported when deploying all network contracts")
|
||||
|
||||
# Confirm filesystem registry writes.
|
||||
if os.path.isfile(local_registry.filepath):
|
||||
|
|
|
@ -111,7 +111,7 @@ def test_bare_contract_deployment_to_alternate_registry(click_runner, agency_loc
|
|||
|
||||
command = ('contracts',
|
||||
'--contract-name', StakingEscrowDeployer.contract_name,
|
||||
'--bare',
|
||||
'--mode', 'bare',
|
||||
'--provider', TEST_PROVIDER_URI,
|
||||
'--registry-infile', agency_local_registry.filepath,
|
||||
'--registry-outfile', ALTERNATE_REGISTRY_FILEPATH,
|
||||
|
|
Loading…
Reference in New Issue