Returning to a single-account BlockchainPower;TODO annotations for BlockchainPower.

pull/1029/head
Kieran Prasch 2019-06-19 18:31:00 -07:00 committed by David Núñez
parent e56245565b
commit 68b8a2735d
12 changed files with 58 additions and 43 deletions

View File

@ -59,7 +59,7 @@ class EthereumContractAgent:
pass pass
def __init__(self, def __init__(self,
blockchain: BlockchainInterface = None, blockchain: BlockchainInterface,
contract: Contract = None, contract: Contract = None,
transaction_gas: int = None transaction_gas: int = None
) -> None: ) -> None:

View File

@ -318,7 +318,7 @@ class BlockchainInterface:
# Broadcast # Broadcast
# #
signed_raw_transaction = self.transacting_power.sign_transaction(unsigned_transaction, sender_address) signed_raw_transaction = self.transacting_power.sign_transaction(unsigned_transaction)
txhash = self.client.w3.eth.sendRawTransaction(signed_raw_transaction) txhash = self.client.w3.eth.sendRawTransaction(signed_raw_transaction)
try: try:

View File

@ -182,9 +182,9 @@ class Felix(Character, NucypherTokenActor):
self.db_engine = create_engine(f'sqlite:///{self.db_filepath}', convert_unicode=True) self.db_engine = create_engine(f'sqlite:///{self.db_filepath}', convert_unicode=True)
# Blockchain # Blockchain
blockchain_power = BlockchainPower(client=self.blockchain.client) blockchain_power = BlockchainPower(blockchain=self.blockchain, account=self.checksum_address)
self._crypto_power.consume_power_up(blockchain_power) self._crypto_power.consume_power_up(blockchain_power)
# blockchain_power.unlock_account(account=self.checksum_address) # TODO # blockchain_power.unlock_account(password=None) # TODO: TransactingPower
self.token_agent = NucypherTokenAgent(blockchain=self.blockchain) self.token_agent = NucypherTokenAgent(blockchain=self.blockchain)
self.reserved_addresses = [self.checksum_address, BlockchainInterface.NULL_ADDRESS] self.reserved_addresses = [self.checksum_address, BlockchainInterface.NULL_ADDRESS]

View File

@ -124,9 +124,10 @@ class Alice(Character, PolicyAuthor):
policy_agent=policy_agent, policy_agent=policy_agent,
checksum_address=checksum_address) checksum_address=checksum_address)
blockchain_power = BlockchainPower(client=self.blockchain.client) # TODO: #1092 - TransactingPower
blockchain_power = BlockchainPower(blockchain=self.blockchain, account=self.checksum_address)
self._crypto_power.consume_power_up(blockchain_power) self._crypto_power.consume_power_up(blockchain_power)
self.blockchain.transacting_power = blockchain_power # TODO: #1092 self.blockchain.transacting_power = blockchain_power # TODO: Embed in Powerups
if is_me and controller: if is_me and controller:
self.controller = self._controller_class(alice=self) self.controller = self._controller_class(alice=self)
@ -839,7 +840,6 @@ class Ursula(Teacher, Character, Worker):
checksum_address: str = None, # Staker address checksum_address: str = None, # Staker address
worker_address: str = None, worker_address: str = None,
stake_tracker: StakeTracker = None, stake_tracker: StakeTracker = None,
staking_agent: StakingEscrowAgent = None,
# Character # Character
password: str = None, password: str = None,
@ -877,7 +877,9 @@ class Ursula(Teacher, Character, Worker):
# #
# Self-Ursula # Self-Ursula
# #
if is_me is True: # TODO: 340 # TODO: Better handle ephemeral staking self ursula <-- Is this still relevant?
if is_me is True: # TODO: #340
self._stored_treasure_maps = dict() self._stored_treasure_maps = dict()
# #
@ -892,13 +894,11 @@ class Ursula(Teacher, Character, Worker):
stake_tracker=stake_tracker) stake_tracker=stake_tracker)
# Access to worker's ETH client via node's transacting keys # Access to worker's ETH client via node's transacting keys
# TODO: Better handle ephemeral staking self ursula <-- Is this still relevant? # TODO: #1092 - TransactingPower
blockchain_power = BlockchainPower(client=self.blockchain.client) blockchain_power = BlockchainPower(blockchain=self.blockchain, account=worker_address)
self._crypto_power.consume_power_up(blockchain_power) self._crypto_power.consume_power_up(blockchain_power)
# TODO: #1092 self.blockchain.transacting_power = blockchain_power # TODO: Embed in powerups
self.substantiate_stamp(client_password=password) # TODO: Use PowerUp / Derive from keyring
# Use blockchain power to substantiate stamp
self.substantiate_stamp(client_password=password, checksum_address=worker_address) # TODO: Derive from keyring
# #
# ProxyRESTServer and TLSHostingPower # TODO: Maybe we want _power_ups to be public after all? # ProxyRESTServer and TLSHostingPower # TODO: Maybe we want _power_ups to be public after all?

View File

@ -108,9 +108,6 @@ def deploy(click_config,
fetch_registry=False, fetch_registry=False,
sync_now=sync) sync_now=sync)
# TODO: Integrate with Deployer Actor (Character)
blockchain.transacting_power = BlockchainPower(client=blockchain.client)
# #
# Deployment Actor # Deployment Actor
# #
@ -125,6 +122,9 @@ def deploy(click_config,
# Verify Address # Verify Address
if not force: if not force:
click.confirm("Selected {} - Continue?".format(deployer_address), abort=True) click.confirm("Selected {} - Continue?".format(deployer_address), abort=True)
# TODO: Integrate with Deployer Actor (Character)
blockchain.transacting_power = BlockchainPower(blockchain=blockchain, account=deployer_address)
deployer = Deployer(blockchain=blockchain, deployer_address=deployer_address) deployer = Deployer(blockchain=blockchain, deployer_address=deployer_address)
# Verify ETH Balance # Verify ETH Balance

View File

@ -92,39 +92,44 @@ class BlockchainPower(CryptoPowerUp):
""" """
not_found_error = NoBlockchainPower not_found_error = NoBlockchainPower
def __init__(self, client=None, device=None) -> None: def __init__(self, blockchain: 'Blockchain', account: str, device = None) -> None:
""" """
Instantiates a BlockchainPower for the given account id. Instantiates a BlockchainPower for the given account id.
""" """
self.blockchain = blockchain
self.account = account
self.device = device self.device = device
self.client = client
self.is_unlocked = False self.is_unlocked = False
def unlock_account(self, account, password: str): def unlock_account(self, password: str):
""" """
Unlocks the account for the specified duration. If no duration is Unlocks the account for the specified duration. If no duration is
provided, it will remain unlocked indefinitely. provided, it will remain unlocked indefinitely.
""" """
self.is_unlocked = self.client.unlock_account(account, password) self.is_unlocked = self.blockchain.client.unlock_account(self.account, password)
if not self.is_unlocked: if not self.is_unlocked:
raise PowerUpError("Failed to unlock account {}".format(account)) raise PowerUpError("Failed to unlock account {}".format(self.account))
def sign_message(self, message: bytes, account: str) -> bytes: def sign_message(self, message: bytes) -> bytes:
""" """
Signs the message with the private key of the BlockchainPower. Signs the message with the private key of the BlockchainPower.
""" """
if not self.is_unlocked: if not self.is_unlocked:
raise PowerUpError("Account is not unlocked.") raise PowerUpError("Account is not unlocked.")
signature = self.client.sign_message(account, message) signature = self.blockchain.client.sign_message(account=self.account, message=message)
return signature return signature
def sign_transaction(self, unsigned_transaction: dict, sender_address: str): def sign_transaction(self, unsigned_transaction: dict):
if self.device: if self.device:
assert False # TODO: Implement TrustedDevice
elif self.client: raise NotImplementedError
signed_raw_transaction = self.client.sign_transaction(transaction=unsigned_transaction,
account=sender_address) sender_address = unsigned_transaction['from']
return signed_raw_transaction if sender_address != self.account:
raise PowerUpError(f"'from' field must match key's {self.account}, but it was {sender_address}")
signed_transaction = self.blockchain.client.sign_transaction(transaction=unsigned_transaction, account=self.account)
return signed_transaction
class KeyPairBasedPower(CryptoPowerUp): class KeyPairBasedPower(CryptoPowerUp):

View File

@ -913,7 +913,8 @@ class Teacher:
self.__worker_address = None self.__worker_address = None
if substantiate_immediately: if substantiate_immediately:
self.substantiate_stamp(client_password=password, checksum_address=worker_address) # TODO: #1091
self.substantiate_stamp(client_password=password)
class InvalidNode(SuspiciousActivity): class InvalidNode(SuspiciousActivity):
"""Raised when a node has an invalid characteristic - stamp, interface, or address.""" """Raised when a node has an invalid characteristic - stamp, interface, or address."""
@ -1146,12 +1147,13 @@ class Teacher:
signature=self.decentralized_identity_evidence) signature=self.decentralized_identity_evidence)
return self.__worker_address return self.__worker_address
def substantiate_stamp(self, client_password: str, checksum_address: str): def substantiate_stamp(self, client_password: str):
# TODO: #1092 - TransactingPower
blockchain_power = self._crypto_power.power_ups(BlockchainPower) blockchain_power = self._crypto_power.power_ups(BlockchainPower)
blockchain_power.unlock_account(password=client_password, account=checksum_address) # TODO: #349 blockchain_power.unlock_account(password=client_password) # TODO: #349
signature = blockchain_power.sign_message(message=bytes(self.stamp), account=checksum_address) signature = blockchain_power.sign_message(message=bytes(self.stamp))
self.__decentralized_identity_evidence = signature self.__decentralized_identity_evidence = signature
self.__worker_address = checksum_address self.__worker_address = blockchain_power.account
# #
# Interface # Interface

View File

@ -212,8 +212,8 @@ class TesterBlockchain(BlockchainDeployerInterface):
"""For use with metric testing scripts""" """For use with metric testing scripts"""
testerchain = cls(compiler=SolidityCompiler()) testerchain = cls(compiler=SolidityCompiler())
power = BlockchainPower(client=testerchain.client) power = BlockchainPower(blockchain=testerchain, account=testerchain.client.etherbase)
power.unlock_account(account=testerchain.client.etherbase, password=INSECURE_DEVELOPMENT_PASSWORD) power.unlock_account(password=INSECURE_DEVELOPMENT_PASSWORD)
testerchain.transacting_power = power testerchain.transacting_power = power
origin = testerchain.client.etherbase origin = testerchain.client.etherbase

View File

@ -47,7 +47,8 @@ def test_rapid_deployment(token_economics):
test_accounts=4, test_accounts=4,
compiler=compiler) compiler=compiler)
blockchain.transacting_power = BlockchainPower(client=blockchain.client) # TODO: #1092 - TransactingPower
blockchain.transacting_power = BlockchainPower(blockchain=blockchain, account=blockchain.etherbase_account)
deployer_address = blockchain.etherbase_account deployer_address = blockchain.etherbase_account
deployer = Deployer(blockchain=blockchain, deployer_address=deployer_address) deployer = Deployer(blockchain=blockchain, deployer_address=deployer_address)

View File

@ -123,7 +123,7 @@ def test_character_blockchain_power(testerchain, agency):
sig_privkey = testerchain.provider.ethereum_tester.backend._key_lookup[canonical_address] sig_privkey = testerchain.provider.ethereum_tester.backend._key_lookup[canonical_address]
signer = Character(is_me=True, blockchain=testerchain, checksum_address=eth_address) signer = Character(is_me=True, blockchain=testerchain, checksum_address=eth_address)
signer._crypto_power.consume_power_up(BlockchainPower(testerchain.client, eth_address)) signer._crypto_power.consume_power_up(BlockchainPower(blockchain=testerchain, account=eth_address))
# Due to testing backend, the account is already unlocked. # Due to testing backend, the account is already unlocked.
power = signer._crypto_power.power_ups(BlockchainPower) power = signer._crypto_power.power_ups(BlockchainPower)
@ -131,7 +131,7 @@ def test_character_blockchain_power(testerchain, agency):
# power.unlock_account('this-is-not-a-secure-password') # power.unlock_account('this-is-not-a-secure-password')
data_to_sign = b'What does Ursula look like?!?' data_to_sign = b'What does Ursula look like?!?'
sig = power.sign_message(message=data_to_sign, account=eth_address) sig = power.sign_message(message=data_to_sign)
is_verified = verify_eip_191(address=eth_address, message=data_to_sign, signature=sig) is_verified = verify_eip_191(address=eth_address, message=data_to_sign, signature=sig)
assert is_verified is True assert is_verified is True
@ -145,7 +145,7 @@ def test_character_blockchain_power(testerchain, agency):
# Test a signature without unlocking the account # Test a signature without unlocking the account
power.is_unlocked = False power.is_unlocked = False
with pytest.raises(PowerUpError): with pytest.raises(PowerUpError):
power.sign_message(message=b'test', account=eth_address) power.sign_message(message=b'test')
# Test lockAccount call # Test lockAccount call
del power del power

View File

@ -44,7 +44,7 @@ def make_testerchain():
# Set the deployer address from a freshly created test account # Set the deployer address from a freshly created test account
testerchain.deployer_address = testerchain.etherbase_account testerchain.deployer_address = testerchain.etherbase_account
testerchain.transacting_power = BlockchainPower(client=testerchain.client) testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=testerchain.etherbase_account)
return testerchain return testerchain

View File

@ -370,7 +370,10 @@ def testerchain():
""" """
# Create the blockchain # Create the blockchain
testerchain = TesterBlockchain(eth_airdrop=True, free_transactions=True) testerchain = TesterBlockchain(eth_airdrop=True, free_transactions=True)
testerchain.transacting_power = BlockchainPower(client=testerchain.client)
# TODO: TransactingPower
# Mock TransactingPower Consumption
testerchain.transacting_power = BlockchainPower(blockchain=testerchain, account=testerchain.etherbase_account)
testerchain.deployer_address = testerchain.etherbase_account testerchain.deployer_address = testerchain.etherbase_account
yield testerchain yield testerchain
testerchain.disconnect() testerchain.disconnect()
@ -426,6 +429,10 @@ def stakers(agency, token_economics):
for index, account in enumerate(blockchain.stakers_accounts): for index, account in enumerate(blockchain.stakers_accounts):
staker = Staker(is_me=True, checksum_address=account, blockchain=blockchain) staker = Staker(is_me=True, checksum_address=account, blockchain=blockchain)
# TODO: #1092 - TransactingPower
# Mock TransactingPower consumption
staker.blockchain.transacting_power = BlockchainPower(blockchain=staker.blockchain, account=staker.checksum_address)
min_stake, balance = token_economics.minimum_allowed_locked, staker.token_balance min_stake, balance = token_economics.minimum_allowed_locked, staker.token_balance
amount = random.randint(min_stake, balance) amount = random.randint(min_stake, balance)