Decompose signer from blockchain interfaces.

pull/2572/head
Kieran Prasch 2021-02-18 13:31:10 -08:00
parent b91359f3ba
commit ee3a7b5e03
1 changed files with 15 additions and 14 deletions

View File

@ -18,6 +18,7 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
import math import math
import os import os
import pprint import pprint
from eth.typing import TransactionDict
from typing import Callable, NamedTuple, Tuple, Union, Optional from typing import Callable, NamedTuple, Tuple, Union, Optional
from typing import List from typing import List
from urllib.parse import urlparse from urllib.parse import urlparse
@ -42,6 +43,8 @@ from constant_sorrow.constants import (
READ_ONLY_INTERFACE, READ_ONLY_INTERFACE,
UNKNOWN_TX_STATUS UNKNOWN_TX_STATUS
) )
from nucypher.crypto.powers import TransactingPower
from nucypher.blockchain.eth.clients import EthereumClient, POA_CHAINS, InfuraClient from nucypher.blockchain.eth.clients import EthereumClient, POA_CHAINS, InfuraClient
from nucypher.blockchain.eth.decorators import validate_checksum_address from nucypher.blockchain.eth.decorators import validate_checksum_address
from nucypher.blockchain.eth.providers import ( from nucypher.blockchain.eth.providers import (
@ -232,10 +235,9 @@ class BlockchainInterface:
self._provider = provider self._provider = provider
self.w3 = NO_BLOCKCHAIN_CONNECTION self.w3 = NO_BLOCKCHAIN_CONNECTION
self.client = NO_BLOCKCHAIN_CONNECTION self.client = NO_BLOCKCHAIN_CONNECTION
self.transacting_power = READ_ONLY_INTERFACE
self.is_light = light self.is_light = light
# FIXME: Not ready to give users total flexibility. Let's stick for the moment to known values. See #2447 # TODO: Not ready to give users total flexibility. Let's stick for the moment to known values. See #2447
if gas_strategy not in ('slow', 'medium', 'fast', 'free', None): # FIXME: What is 'None' doing here? if gas_strategy not in ('slow', 'medium', 'fast', 'free', None): # FIXME: What is 'None' doing here?
raise ValueError(f"'{gas_strategy}' is an invalid gas strategy") raise ValueError(f"'{gas_strategy}' is an invalid gas strategy")
self.gas_strategy = gas_strategy or self.DEFAULT_GAS_STRATEGY self.gas_strategy = gas_strategy or self.DEFAULT_GAS_STRATEGY
@ -526,7 +528,8 @@ class BlockchainInterface:
return transaction_dict return transaction_dict
def sign_and_broadcast_transaction(self, def sign_and_broadcast_transaction(self,
transaction_dict, transacting_power: TransactingPower,
transaction_dict: TransactionDict,
transaction_name: str = "", transaction_name: str = "",
confirmations: int = 0, confirmations: int = 0,
fire_and_forget: bool = False fire_and_forget: bool = False
@ -550,9 +553,6 @@ class BlockchainInterface:
else: else:
emitter = StdoutEmitter() emitter = StdoutEmitter()
if self.transacting_power is READ_ONLY_INTERFACE:
raise self.InterfaceError(str(READ_ONLY_INTERFACE))
# #
# Sign # Sign
# #
@ -563,11 +563,11 @@ class BlockchainInterface:
cost_wei = price * transaction_dict['gas'] cost_wei = price * transaction_dict['gas']
cost = Web3.fromWei(cost_wei, 'ether') cost = Web3.fromWei(cost_wei, 'ether')
if self.transacting_power.is_device: if transacting_power.is_device:
emitter.message(f'Confirm transaction {transaction_name} on hardware wallet... ' emitter.message(f'Confirm transaction {transaction_name} on hardware wallet... '
f'({cost} ETH @ {price_gwei} gwei)', f'({cost} ETH @ {price_gwei} gwei)',
color='yellow') color='yellow')
signed_raw_transaction = self.transacting_power.sign_transaction(transaction_dict) signed_raw_transaction = transacting_power.sign_transaction(transaction_dict)
# #
# Broadcast # Broadcast
@ -624,7 +624,7 @@ class BlockchainInterface:
@validate_checksum_address @validate_checksum_address
def send_transaction(self, def send_transaction(self,
contract_function: Union[ContractFunction, ContractConstructor], contract_function: Union[ContractFunction, ContractConstructor],
sender_address: str, transacting_power: TransactingPower,
payload: dict = None, payload: dict = None,
transaction_gas_limit: Optional[int] = None, transaction_gas_limit: Optional[int] = None,
gas_estimation_multiplier: Optional[float] = None, gas_estimation_multiplier: Optional[float] = None,
@ -642,7 +642,7 @@ class BlockchainInterface:
use_pending_nonce = None # TODO: #2385 use_pending_nonce = None # TODO: #2385
transaction = self.build_contract_transaction(contract_function=contract_function, transaction = self.build_contract_transaction(contract_function=contract_function,
sender_address=sender_address, sender_address=transacting_power.account,
payload=payload, payload=payload,
transaction_gas_limit=transaction_gas_limit, transaction_gas_limit=transaction_gas_limit,
gas_estimation_multiplier=gas_estimation_multiplier, gas_estimation_multiplier=gas_estimation_multiplier,
@ -654,7 +654,8 @@ class BlockchainInterface:
except AttributeError: except AttributeError:
transaction_name = 'DEPLOY' if isinstance(contract_function, ContractConstructor) else 'UNKNOWN' transaction_name = 'DEPLOY' if isinstance(contract_function, ContractConstructor) else 'UNKNOWN'
txhash_or_receipt = self.sign_and_broadcast_transaction(transaction_dict=transaction, txhash_or_receipt = self.sign_and_broadcast_transaction(transacting_power=transacting_power,
transaction_dict=transaction,
transaction_name=transaction_name, transaction_name=transaction_name,
confirmations=confirmations, confirmations=confirmations,
fire_and_forget=fire_and_forget) fire_and_forget=fire_and_forget)
@ -796,7 +797,7 @@ class BlockchainDeployerInterface(BlockchainInterface):
@validate_checksum_address @validate_checksum_address
def deploy_contract(self, def deploy_contract(self,
deployer_address: str, transacting_power: TransactingPower,
registry: BaseContractRegistry, registry: BaseContractRegistry,
contract_name: str, contract_name: str,
*constructor_args, *constructor_args,
@ -823,7 +824,7 @@ class BlockchainDeployerInterface(BlockchainInterface):
contract_factory = self.get_contract_factory(contract_name=contract_name, version=contract_version) contract_factory = self.get_contract_factory(contract_name=contract_name, version=contract_version)
self.log.info(f"Deploying contract {contract_name}:{contract_factory.version} with " self.log.info(f"Deploying contract {contract_name}:{contract_factory.version} with "
f"deployer address {deployer_address} " f"deployer address {transacting_power.account} "
f"and parameters {pprint_args}") f"and parameters {pprint_args}")
constructor_function = contract_factory.constructor(*constructor_args, **constructor_kwargs) constructor_function = contract_factory.constructor(*constructor_args, **constructor_kwargs)
@ -839,7 +840,7 @@ class BlockchainDeployerInterface(BlockchainInterface):
# #
receipt = self.send_transaction(contract_function=constructor_function, receipt = self.send_transaction(contract_function=constructor_function,
sender_address=deployer_address, transacting_power=transacting_power,
payload=deploy_transaction, payload=deploy_transaction,
confirmations=confirmations) confirmations=confirmations)