mirror of https://github.com/nucypher/nucypher.git
Handle being consumed, validate 'from' field in RPC tx requests.
parent
dc22bdede0
commit
cda052b710
|
@ -176,8 +176,10 @@ class Character(Learner):
|
|||
# Decentralized
|
||||
#
|
||||
if not federated_only:
|
||||
if not blockchain:
|
||||
raise ValueError('No blockchain interface provided to run decentralized mode.')
|
||||
if not checksum_address:
|
||||
raise ValueError("No checksum_address provided while running in a non-federated mode.")
|
||||
raise ValueError("No checksum_address provided to run in decentralized mode.")
|
||||
else:
|
||||
self._checksum_address = checksum_address # TODO: Check that this matches TransactingPower
|
||||
#
|
||||
|
|
|
@ -895,11 +895,8 @@ class Ursula(Teacher, Character, Worker):
|
|||
if not federated_only:
|
||||
|
||||
# Access staking node via node's transacting keys
|
||||
transacting_power = TransactingPower(account=self.checksum_address,
|
||||
device=device,
|
||||
password=client_password, # FIXME: password from somewhere
|
||||
blockchain=self.blockchain)
|
||||
self._crypto_power.consume_power_up(transacting_power)
|
||||
transacting_power = TransactingPower(account=worker_address, device=device, blockchain=self.blockchain)
|
||||
self._crypto_power.consume_power_up(transacting_power, client_password)
|
||||
|
||||
# Use blockchain power to substantiate stamp
|
||||
self.substantiate_stamp(client_password=password)
|
||||
|
|
|
@ -127,27 +127,24 @@ class TransactingPower(CryptoPowerUp):
|
|||
def is_unlocked(self):
|
||||
return self.__unlocked
|
||||
|
||||
def activate(self, password: str):
|
||||
self.blockchain.connect()
|
||||
self.unlock_account(password=password)
|
||||
self.blockchain.transacting_power = self
|
||||
self.__password = None
|
||||
def activate(self, password: str = None):
|
||||
"""Be Consumed"""
|
||||
self.blockchain.connect() # Connect
|
||||
self.unlock_account(password=password) # Unlock
|
||||
self.blockchain.transacting_power = self # Attach
|
||||
self.__password = None # Discard
|
||||
|
||||
def lock_account(self):
|
||||
if self.client:
|
||||
self.client.lock_account(address=self.account)
|
||||
elif self.device:
|
||||
if self.device is not NO_STAKING_DEVICE:
|
||||
# TODO: Implement TrustedDevice
|
||||
raise NotImplementedError
|
||||
_result = self.device.lock()
|
||||
else:
|
||||
_result = self.client.lock_account(address=self.account)
|
||||
self.__unlocked = False
|
||||
|
||||
def unlock_account(self, password: str = None):
|
||||
"""
|
||||
Unlocks the account for the specified duration. If no duration is
|
||||
provided, it will remain unlocked indefinitely.
|
||||
"""
|
||||
|
||||
if self.device is not NO_STAKING_DEVICE:
|
||||
# TODO: Embed in TrustedDevice
|
||||
_hd_path = self.device.get_address_path(checksum_address=self.account)
|
||||
ping = 'PING|PONG'
|
||||
pong = self.device.client.ping(ping) # TODO: Use pin protection?
|
||||
|
@ -168,29 +165,34 @@ class TransactingPower(CryptoPowerUp):
|
|||
|
||||
# HW Signer
|
||||
if self.device is not NO_STAKING_DEVICE:
|
||||
# TODO: Use a common message signature type from clients and devices
|
||||
signature = self.device.sign_message(checksum_address=self.account, message=message)
|
||||
signature = signature.signature # TODO: Use a common type from clients and devices
|
||||
signature = signature.signature
|
||||
|
||||
# Web3 Signer
|
||||
else:
|
||||
signature = self.client.sign_message(account=self.account, message=message)
|
||||
|
||||
return signature
|
||||
|
||||
def sign_transaction(self, unsigned_transaction: dict) -> HexBytes:
|
||||
"""
|
||||
Signs the transaction with the private key of the TransactingPower.
|
||||
"""
|
||||
if not self.is_unlocked:
|
||||
raise PowerUpError("Failed to unlock account {}".format(self.account))
|
||||
|
||||
# Note: This check is also performed client-side.
|
||||
sender_address = unsigned_transaction['from']
|
||||
if sender_address != self.account:
|
||||
raise PowerUpError(f"'from' field must match key's {self.account}, but it was {sender_address}")
|
||||
|
||||
# HW Signer
|
||||
if self.device is not NO_STAKING_DEVICE:
|
||||
# TODO: Use a common tx_sign return type from clients and devices
|
||||
signed_raw_transaction = self.device.sign_eth_transaction(unsigned_transaction=unsigned_transaction,
|
||||
checksum_address=self.account)
|
||||
# Web3 Signer
|
||||
else:
|
||||
# Note: This check is also performed client-side.
|
||||
sender_address = unsigned_transaction['from']
|
||||
if sender_address != self.account:
|
||||
raise PowerUpError(f"'from' field must match key's {self.account}, but it was {sender_address}")
|
||||
signed_raw_transaction = self.blockchain.client.sign_transaction(transaction=unsigned_transaction,
|
||||
account=self.account)
|
||||
return signed_raw_transaction
|
||||
|
|
|
@ -29,6 +29,7 @@ from nucypher.crypto.powers import (CryptoPower,
|
|||
NoSigningPower,
|
||||
TransactingPower,
|
||||
PowerUpError)
|
||||
from nucypher.utilities.sandbox.constants import INSECURE_DEVELOPMENT_PASSWORD
|
||||
|
||||
"""
|
||||
Chapter 1: SIGNING
|
||||
|
@ -123,15 +124,17 @@ def test_character_client_transacting_power(testerchain, agency):
|
|||
sig_pubkey = sig_privkey.public_key
|
||||
|
||||
signer = Character(is_me=True, blockchain=testerchain, checksum_address=eth_address)
|
||||
signer._crypto_power.consume_power_up(TransactingPower(blockchain=testerchain, account=eth_address))
|
||||
|
||||
transacting_power = TransactingPower(blockchain=testerchain, account=eth_address)
|
||||
signer._crypto_power.consume_power_up(transacting_power)
|
||||
power = signer._crypto_power.power_ups(TransactingPower)
|
||||
|
||||
power.lock_account()
|
||||
|
||||
# Test a signature without unlocking the account
|
||||
with pytest.raises(PowerUpError):
|
||||
power.sign_message(message=b'test', checksum_address=eth_address)
|
||||
power.sign_message(message=b'test')
|
||||
|
||||
power.unlock_account(checksum_address=eth_address)
|
||||
power.unlock_account(password=INSECURE_DEVELOPMENT_PASSWORD)
|
||||
|
||||
data_to_sign = b'What does Ursula look like?!?'
|
||||
sig = power.sign_message(message=data_to_sign)
|
||||
|
@ -146,7 +149,7 @@ def test_character_client_transacting_power(testerchain, agency):
|
|||
assert is_verified is False
|
||||
|
||||
# Test lockAccount call
|
||||
power.lock_account(checksum_address=eth_address)
|
||||
power.lock_account()
|
||||
|
||||
# Test a signature without unlocking the account
|
||||
with pytest.raises(PowerUpError):
|
||||
|
|
Loading…
Reference in New Issue