UserEscrowProxyDeployer was incorrectly deploying a new Linker each time

New behavior is to look first for an existing Linker, and just in case it's not found, deploy it.
pull/1124/head
David Núñez 2019-07-01 12:07:38 +02:00 committed by Kieran Prasch
parent e7dba04989
commit cef7e17279
No known key found for this signature in database
GPG Key ID: 199AB839D4125A62
2 changed files with 49 additions and 27 deletions

View File

@ -29,8 +29,9 @@ from nucypher.blockchain.eth.agents import (
PolicyAgent, PolicyAgent,
UserEscrowAgent, UserEscrowAgent,
AdjudicatorAgent) AdjudicatorAgent)
from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface, BlockchainInterface
from nucypher.blockchain.eth.registry import AllocationRegistry from nucypher.blockchain.eth.registry import AllocationRegistry, EthereumContractRegistry
from nucypher.crypto.api import keccak_digest
class ContractDeployer: class ContractDeployer:
@ -39,7 +40,7 @@ class ContractDeployer:
contract_name = NotImplemented contract_name = NotImplemented
_interface_class = BlockchainDeployerInterface _interface_class = BlockchainDeployerInterface
_upgradeable = NotImplemented _upgradeable = NotImplemented
__proxy_deployer = NotImplemented __linker_deployer = NotImplemented
class ContractDeploymentError(Exception): class ContractDeploymentError(Exception):
pass pass
@ -500,6 +501,12 @@ class LibraryLinkerDeployer(ContractDeployer):
if new_target == self._contract.address: if new_target == self._contract.address:
raise self.ContractDeploymentError(f"{self.contract_name} {self._contract.address} cannot target itself.") raise self.ContractDeploymentError(f"{self.contract_name} {self._contract.address} cannot target itself.")
# TODO: Make this logic a decorator for retarget and upgrade
secret_hash = self._contract.functions.secretHash().call()
if secret_hash != keccak_digest(existing_secret_plaintext):
raise self.ContractDeploymentError(f"The secret for retargeting {self.contract_name} "
f"is not {existing_secret_plaintext}.")
origin_args = {'from': self.deployer_address} # TODO: Gas management origin_args = {'from': self.deployer_address} # TODO: Gas management
retarget_function = self._contract.functions.upgrade(new_target, existing_secret_plaintext, new_secret_hash) retarget_function = self._contract.functions.upgrade(new_target, existing_secret_plaintext, new_secret_hash)
retarget_receipt = self.blockchain.send_transaction(contract_function=retarget_function, retarget_receipt = self.blockchain.send_transaction(contract_function=retarget_function,
@ -511,7 +518,7 @@ class LibraryLinkerDeployer(ContractDeployer):
class UserEscrowProxyDeployer(ContractDeployer): class UserEscrowProxyDeployer(ContractDeployer):
contract_name = 'UserEscrowProxy' contract_name = 'UserEscrowProxy'
__proxy_deployer = LibraryLinkerDeployer __linker_deployer = LibraryLinkerDeployer
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@ -519,10 +526,11 @@ class UserEscrowProxyDeployer(ContractDeployer):
self.staking_agent = StakingEscrowAgent(blockchain=self.blockchain) self.staking_agent = StakingEscrowAgent(blockchain=self.blockchain)
self.policy_agent = PolicyAgent(blockchain=self.blockchain) self.policy_agent = PolicyAgent(blockchain=self.blockchain)
def __get_state_contract(self) -> str: def deploy(self, secret_hash: bytes, existing_secret_plaintext: bytes = None, gas_limit: int = None) -> dict:
return self.contract.functions.getStateContract() """
Deploys a new UserEscrowProxy contract, and retargets UserEscrowLibraryLinker to new contract.
def deploy(self, secret_hash: bytes, gas_limit: int = None) -> dict: In case UserEscrowLibraryLinker is not found, then it deploys it.
"""
deployment_receipts = dict() deployment_receipts = dict()
@ -535,19 +543,33 @@ class UserEscrowProxyDeployer(ContractDeployer):
self._contract = user_escrow_proxy_contract self._contract = user_escrow_proxy_contract
deployment_receipts['deployment'] = proxy_deployment_txhash deployment_receipts['deployment'] = proxy_deployment_txhash
# Proxy-Proxy # LibraryLinker
proxy_deployer = self.__proxy_deployer(blockchain=self.blockchain, try:
deployer_address=self.deployer_address, linker_contract = self.blockchain.get_contract_by_name(name=self.__linker_deployer.contract_name)
target_contract=user_escrow_proxy_contract) except (BlockchainInterface.UnknownContract, EthereumContractRegistry.UnknownContract): # TODO: Unify exceptions
linker_deployer = self.__linker_deployer(blockchain=self.blockchain,
deployer_address=self.deployer_address,
target_contract=user_escrow_proxy_contract)
_proxy_deployment_txhashes = proxy_deployer.deploy(secret_hash=secret_hash, gas_limit=gas_limit) linker_deployment_txhash = linker_deployer.deploy(secret_hash=secret_hash, gas_limit=gas_limit)
deployment_receipts['linker_deployment'] = linker_deployment_txhash
else:
# LibraryLinker.retarget
retarget = linker_contract.functions.upgrade(self._contract.address,
existing_secret_plaintext,
secret_hash)
retarget_receipt = self.blockchain.send_transaction(transaction_function=retarget,
# payload=payload,
sender_address=self.deployer_address)
deployment_receipts['linker_retarget'] = retarget_receipt
deployment_receipts['proxy_deployment'] = proxy_deployment_txhash
return deployment_receipts return deployment_receipts
@classmethod @classmethod
def get_latest_version(cls, blockchain) -> Contract: def get_latest_version(cls, blockchain) -> Contract:
contract = blockchain.get_contract_by_name(name=cls.contract_name, proxy_name=cls.__proxy_deployer.contract_name) contract = blockchain.get_contract_by_name(name=cls.contract_name,
proxy_name=cls.__linker_deployer.contract_name,
use_proxy_address=False)
return contract return contract
def upgrade(self, existing_secret_plaintext: bytes, new_secret_hash: bytes): def upgrade(self, existing_secret_plaintext: bytes, new_secret_hash: bytes):
@ -555,13 +577,13 @@ class UserEscrowProxyDeployer(ContractDeployer):
deployment_receipts = dict() deployment_receipts = dict()
existing_bare_contract = self.blockchain.get_contract_by_name(name=self.contract_name, existing_bare_contract = self.blockchain.get_contract_by_name(name=self.contract_name,
proxy_name=self.__proxy_deployer.contract_name, proxy_name=self.__linker_deployer.contract_name,
use_proxy_address=False) use_proxy_address=False)
# Proxy-Proxy # UserEscrowLibraryLinker
proxy_deployer = self.__proxy_deployer(blockchain=self.blockchain, linker_deployer = self.__linker_deployer(blockchain=self.blockchain,
deployer_address=self.deployer_address, deployer_address=self.deployer_address,
target_contract=existing_bare_contract, target_contract=existing_bare_contract,
bare=True) bare=True)
# Proxy # Proxy
proxy_args = (self.contract_name, proxy_args = (self.contract_name,
@ -573,17 +595,17 @@ class UserEscrowProxyDeployer(ContractDeployer):
self._contract = user_escrow_proxy_contract self._contract = user_escrow_proxy_contract
deployment_receipts['deployment'] = proxy_deployment_receipt deployment_receipts['deployment'] = proxy_deployment_receipt
proxy_deployer.retarget(new_target=user_escrow_proxy_contract.address, linker_receipt = linker_deployer.retarget(new_target=user_escrow_proxy_contract.address,
existing_secret_plaintext=existing_secret_plaintext, existing_secret_plaintext=existing_secret_plaintext,
new_secret_hash=new_secret_hash) new_secret_hash=new_secret_hash)
deployment_receipts['proxy_deployment'] = proxy_deployment_receipt deployment_receipts['linker_retarget'] = linker_receipt
return deployment_receipts return deployment_receipts
def rollback(self, existing_secret_plaintext: bytes, new_secret_hash: bytes): def rollback(self, existing_secret_plaintext: bytes, new_secret_hash: bytes):
existing_bare_contract = self.blockchain.get_contract_by_name(name=self.contract_name, existing_bare_contract = self.blockchain.get_contract_by_name(name=self.contract_name,
proxy_name=self.__proxy_deployer.contract_name, proxy_name=self.__linker_deployer.contract_name,
use_proxy_address=False) use_proxy_address=False)
dispatcher_deployer = DispatcherDeployer(blockchain=self.blockchain, dispatcher_deployer = DispatcherDeployer(blockchain=self.blockchain,

View File

@ -46,7 +46,7 @@ def proxy_deployer(testerchain, agency) -> UserEscrowAgent:
proxy_secret = os.urandom(DispatcherDeployer.DISPATCHER_SECRET_LENGTH) proxy_secret = os.urandom(DispatcherDeployer.DISPATCHER_SECRET_LENGTH)
proxy_deployer = UserEscrowProxyDeployer(deployer_address=deployer_address, blockchain=testerchain) proxy_deployer = UserEscrowProxyDeployer(deployer_address=deployer_address, blockchain=testerchain)
proxy_deployer.deploy( secret_hash=proxy_secret) proxy_deployer.deploy(secret_hash=proxy_secret)
yield proxy_deployer yield proxy_deployer