Merge pull request #2560 from KPrasch/wake-up

Alternate finnegans wake demo for Lynx testnet + API Refinements
pull/2569/head
KPrasch 2021-02-15 08:35:39 -08:00 committed by GitHub
commit fcccf7789b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 583 additions and 250 deletions

View File

@ -31,6 +31,10 @@ without revealing data keys to intermediary entities.
+------+-----------+----------------------------------------------------------------------------------------------+
There are two version of the example, one federated example using a local federated network
and another example using the nucypher application development tesnet on Goerli: "Lynx".
Install NuCypher
----------------
@ -45,32 +49,34 @@ Acquire the ``nucypher`` application code and install the dependencies:
(nucypher-venv)$ cd nucypher
(nucypher-venv)$ pip install -e .
Federated Demo
--------------
Run a fleet of federated Ursulas
--------------------------------
Run the local fleet of federated Ursulas in a separate terminal.
This provides a network of 12 federated Ursulas.
First run the local federated network:
.. code::
(nucypher)$ python examples/run_demo_ursula_fleet.py
python ../run_demo_ursula_fleet.py
Download the Book Text
----------------------
For your convenience we have provided a bash script to acquire the "Finnegan's Wake" text. However,
feel free to use any text of your choice, as long you you edit the demo code accordingly.
To run the script from the ``examples/finnegans_wake_demo`` directory:
Then run the demo:
.. code::
(nucypher)$ ./download_finnegans_wake.sh
python finnegans-wake-demo-federated.py
Run the Demo
---------------
Testnet Demo
------------
After acquiring a text file to re-encrypt, execute the demo from the ``examples/finnegans_wake_demo`` by running:
First, configure the demo. Be sure tat alice's address has some Goerli ETH.
.. code::
(nucypher)$ python finnegans-wake-demo.py
export DEMO_PROVIDER_URI=<GOERLI RPC ENDPOINT>
export DEMO_ALICE_ETH_ADDRESS=<ETH ADDRESS>
export DEMO_SIGNER_URI=keystore://<PATH TO KEYSTORE>
Then run the demo:
.. code::
python finnegans-wake-demo-testnet.py

View File

@ -1,4 +1,4 @@
# Ursula exchange example over live network
# Finnegan's Wake Demo
This illustrates Alice sharing data with Bob over the NuCypher network using proxy re-encryption,
without revealing private keys to intermediary entities.
@ -11,14 +11,25 @@ without revealing private keys to intermediary entities.
5. Bob receives and reconstructs the Enrico from Policy public key and Enrico public key
6. Bob retrieves the original message from Enrico and MessageKit
There are two version of the example, one federated example using a local network
and another example using the nucypher application development tesnet: Lynx.
### Run a fleet of federated Ursulas
### Federated Demo
First run the local federated network:
`python ../run_demo_ursula_fleet.py`
Then run the demo:
`python finnegans-wake-demo-federated.py`
### Download the Book!
`./download_finnegans_wake.sh`
### Testnet Demo
First, configure the demo. Be sure tat alice's address has some Goerli ETH.
```bash
export DEMO_PROVIDER_URI=<GOERLI RPC ENDPOINT>
export DEMO_ALICE_ETH_ADDRESS=<ETH ADDRESS>
export DEMO_SIGNER_URI=keystore://<PATH TO KEYSTORE>
```
### Run
`python finnegans-wake-demo.py`
Then run the demo:
`python finnegans-wake-demo-testnet.py`

View File

@ -1,5 +0,0 @@
#!/usr/bin/env bash
echo "Downloading Finnegan's Wake Text..."
wget "https://github.com/nucypher/nucypher/files/1765576/finnegans-wake.txt" -O ./finnegans-wake.txt
echo "Successfully downloaded. To run the demo execute 'python finnegans-wake-demo.py'"

View File

@ -15,40 +15,30 @@
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import os
import sys
import datetime
import maya
from umbral.keys import UmbralPublicKey
import os
import sys
from pathlib import Path
from nucypher.characters.lawful import Alice, Bob, Ursula
from nucypher.characters.lawful import Enrico as Enrico
from nucypher.config.constants import TEMPORARY_DOMAIN
from nucypher.network.middleware import RestMiddleware
from nucypher.crypto.powers import SigningPower, DecryptingPower
from nucypher.utilities.logging import GlobalLoggerSettings
######################
# Boring setup stuff #
######################
# Execute the download script (download_finnegans_wake.sh) to retrieve the book
BOOK_PATH = os.path.join('.', 'finnegans-wake.txt')
# Change this value to to perform more or less total re-encryptions
# in order to avoid processing the entire book's text. (it's long)
NUMBER_OF_LINES_TO_REENCRYPT = 25
BOOK_PATH = Path(os.getenv('FINNEGANS_WAKE_PATH') or 'finnegans-wake-excerpt.txt')
# Twisted Logger
GlobalLoggerSettings.set_log_level(log_level_name='debug')
GlobalLoggerSettings.start_console_logging()
#######################################
# Finnegan's Wake on NuCypher Testnet #
# (will fail with bad connection) #####
#######################################
# if your ursulas are NOT running on your current host,
# run like this: python finnegans-wake-demo.py 172.28.1.3:11500
# otherwise the default will be fine.
@ -61,55 +51,60 @@ except IndexError:
##############################################
# Ursula, the Untrusted Re-Encryption Proxy #
##############################################
ursula = Ursula.from_seed_and_stake_info(seed_uri=SEEDNODE_URI,
federated_only=True,
minimum_stake=0)
ursula = Ursula.from_seed_and_stake_info(seed_uri=SEEDNODE_URI, federated_only=True)
# Here are our Policy details.
policy_end_datetime = maya.now() + datetime.timedelta(days=5)
policy_end_datetime = maya.now() + datetime.timedelta(days=1)
m, n = 2, 3
label = b"secret/files/and/stuff"
#####################
# Bob the BUIDLer ##
#####################
# First there was Bob.
bob = Bob(federated_only=True, domain=TEMPORARY_DOMAIN, known_nodes=[ursula])
# Bob gives his public keys to alice.
verifying_key = bob.public_keys(SigningPower)
encrypting_key = bob.public_keys(DecryptingPower)
######################################
# Alice, the Authority of the Policy #
######################################
ALICE = Alice(network_middleware=RestMiddleware(),
domain=TEMPORARY_DOMAIN,
known_nodes=[ursula],
learn_on_same_thread=True,
federated_only=True)
alice = Alice(federated_only=True, domain=TEMPORARY_DOMAIN, known_nodes=[ursula])
# Start node discovery and wait until 8 nodes are known in case
# the fleet isn't fully spun up yet, as sometimes happens on CI.
alice.start_learning_loop(now=True)
alice.block_until_number_of_known_nodes_is(8, timeout=30, learn_on_this_thread=True)
# Alice can get the public key even before creating the policy.
# From this moment on, any Data Source that knows the public key
# can encrypt data originally intended for Alice, but that can be shared with
# any Bob that Alice grants access.
policy_pubkey = ALICE.get_policy_encrypting_key_from_label(label)
policy_public_key = alice.get_policy_encrypting_key_from_label(label)
BOB = Bob(known_nodes=[ursula],
domain=TEMPORARY_DOMAIN,
network_middleware=RestMiddleware(),
federated_only=True,
start_learning_now=True,
learn_on_same_thread=True)
# Alice grant access to Bob. She already knows Bob's public keys from a side-channel.
remote_bob = Bob.from_public_keys(encrypting_key=encrypting_key, verifying_key=verifying_key)
policy = alice.grant(remote_bob, label, m=m, n=n, expiration=policy_end_datetime)
ALICE.start_learning_loop(now=True)
ALICE.block_until_number_of_known_nodes_is(8, timeout=30, learn_on_this_thread=True) # In case the fleet isn't fully spun up yet, as sometimes happens on CI.
policy = ALICE.grant(BOB,
label,
m=m, n=n,
expiration=policy_end_datetime)
assert policy.public_key == policy_pubkey
assert policy.public_key == policy_public_key
policy.treasure_map_publisher.block_until_complete()
# Alice puts her public key somewhere for Bob to find later...
alices_pubkey_bytes_saved_for_posterity = bytes(ALICE.stamp)
alice_verifying_key = bytes(alice.stamp)
# ...and then disappears from the internet.
ALICE.disenchant()
del ALICE
#
# Note that local characters (alice and bob), as opposed to objects representing
# remote characters constructed from public data (remote_alice and remote_bob)
# run a learning loop in a background thread and need to be stopped explicitly.
alice.disenchant()
del alice
#####################
# some time passes. #
@ -123,16 +118,16 @@ del ALICE
# Bob the BUIDLer ##
#####################
BOB.join_policy(label, alices_pubkey_bytes_saved_for_posterity)
bob.join_policy(label, alice_verifying_key)
# Now that Bob has joined the Policy, let's show how Enrico the Encryptor
# can share data with the members of this Policy and then how Bob retrieves it.
# In order to avoid re-encrypting the entire book in this demo, we only read some lines.
with open(BOOK_PATH, 'rb') as file:
finnegans_wake = file.readlines()[:NUMBER_OF_LINES_TO_REENCRYPT]
finnegans_wake = file.readlines()
print()
print("**************James Joyce's Finnegan's Wake**************")
print("**************James Joyce's Finnegan's Wake (Excerpt)**************")
print()
print("---------------------------------------------------------")
@ -141,7 +136,8 @@ for counter, plaintext in enumerate(finnegans_wake):
#########################
# Enrico, the Encryptor #
#########################
enrico = Enrico(policy_encrypting_key=policy_pubkey)
enrico = Enrico(policy_encrypting_key=policy_public_key)
# In this case, the plaintext is a
# single passage from James Joyce's Finnegan's Wake.
@ -155,20 +151,14 @@ for counter, plaintext in enumerate(finnegans_wake):
# Back to Bob #
###############
enrico_as_understood_by_bob = Enrico.from_public_keys(
verifying_key=data_source_public_key,
policy_encrypting_key=policy_pubkey
)
# Now Bob can retrieve the original message.
alice_pubkey_restored_from_ancient_scroll = UmbralPublicKey.from_bytes(alices_pubkey_bytes_saved_for_posterity)
delivered_cleartexts = BOB.retrieve(single_passage_ciphertext,
enrico=enrico_as_understood_by_bob,
alice_verifying_key=alice_pubkey_restored_from_ancient_scroll,
delivered_cleartexts = bob.retrieve(single_passage_ciphertext,
policy_encrypting_key=policy_public_key,
alice_verifying_key=alice_verifying_key,
label=label)
# We show that indeed this is the passage originally encrypted by Enrico.
assert plaintext == delivered_cleartexts[0]
print("Retrieved: {}".format(delivered_cleartexts[0]))
BOB.disenchant()
bob.disenchant()

View File

@ -0,0 +1,164 @@
"""
This file is part of nucypher.
nucypher is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
nucypher is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
from getpass import getpass
import datetime
import maya
import os
from pathlib import Path
from web3.main import Web3
from nucypher.blockchain.eth.signers.base import Signer
from nucypher.characters.lawful import Alice, Bob, Ursula
from nucypher.characters.lawful import Enrico as Enrico
from nucypher.crypto.powers import SigningPower, DecryptingPower
from nucypher.utilities.ethereum import connect_web3_provider
from nucypher.utilities.logging import GlobalLoggerSettings
######################
# Boring setup stuff #
######################
GlobalLoggerSettings.set_log_level(log_level_name='debug')
GlobalLoggerSettings.start_console_logging()
BOOK_PATH = Path('finnegans-wake-excerpt.txt')
try:
# Replace with ethereum RPC endpoint
PROVIDER_URI = os.environ['DEMO_PROVIDER_URI']
# Replace with wallet filepath.
WALLET_FILEPATH = os.environ['DEMO_WALLET_FILEPATH']
SIGNER_URI = f'keystore://{WALLET_FILEPATH}'
# Replace with alice's ethereum address
ALICE_ADDRESS = os.environ['DEMO_ALICE_ADDRESS']
except KeyError:
raise RuntimeError('Missing environment variables to run demo.')
####################
# NuCypher Network #
####################
TESTNET = 'lynx'
#####################
# Bob the BUIDLer ##
#####################
# Then, there was bob. Bob learns about the
# rest of the network from the seednode.
bob = Bob(domain=TESTNET)
# Bob puts his public keys somewhere alice can find them.
verifying_key = bob.public_keys(SigningPower)
encrypting_key = bob.public_keys(DecryptingPower)
######################################
# Alice, the Authority of the Policy #
######################################
# Connect to the ethereum provider.
connect_web3_provider(provider_uri=PROVIDER_URI)
# Setup and unlock alice's ethereum wallet.
# WARNING: Never give your mainnet password or mnemonic phrase to anyone.
# Do not use mainnet keys, create a dedicated software wallet to use for this demo.
wallet = Signer.from_signer_uri(SIGNER_URI)
password = os.environ.get('DEMO_ALICE_PASSWORD') or getpass(f"Enter password to unlock {ALICE_ADDRESS[:8]}: ")
wallet.unlock_account(account=ALICE_ADDRESS, password=password)
# This is Alice.
alice = Alice(checksum_address=ALICE_ADDRESS, signer=wallet, domain=TESTNET)
# Alice puts her public key somewhere for Bob to find later...
alice_verifying_key = bytes(alice.stamp)
# Alice can get the policy's public key even before creating the policy.
label = b"secret/files/42"
policy_public_key = alice.get_policy_encrypting_key_from_label(label)
# From this moment on, anyone that knows the public key
# can encrypt data originally intended for Alice, but that
# can be shared with any Bob that Alice grants access.
# Alice already knows Bob's public keys from a side-channel.
remote_bob = Bob.from_public_keys(encrypting_key=encrypting_key, verifying_key=verifying_key)
# These are the policy details for bob.
# In this example bob will be granted access for 1 day,
# trusting 2 of 3 nodes paying each of them 50 gwei per period.
expiration = maya.now() + datetime.timedelta(days=1)
rate = Web3.toWei(50, 'gwei')
m, n = 2, 3
# Alice grants access to Bob...
alice.grant(remote_bob, label, m=m, n=n, rate=rate, expiration=expiration)
# ...and then disappears from the internet.
#
# Note that local characters (alice and bob), as opposed to objects representing
# remote characters constructed from public data (remote_alice and remote_bob)
# run node discovery in a background thread and must be stopped explicitly.
alice.disenchant()
del alice
#########################
# Enrico, the Encryptor #
#########################
# Now that Bob has access to the policy, let's show how Enrico the Encryptor
# can share data with the members of this Policy and then how Bob retrieves it.
with open(BOOK_PATH, 'rb') as file:
finnegans_wake = file.readlines()
print("\n**************James Joyce's Finnegan's Wake (Excerpt)**************\n")
for counter, plaintext in enumerate(finnegans_wake):
# Enrico knows the policy's public key from a side-channel.
enrico = Enrico(policy_encrypting_key=policy_public_key)
# In this case, the plaintext is a single passage from James Joyce's Finnegan's Wake.
# The matter of whether encryption makes the passage more or less readable
# is left to the reader to determine. Many data sources (Enricos) can
# encrypt fot the policy's public key.
ciphertext, _signature = enrico.encrypt_message(plaintext)
enrico_public_key = bytes(enrico.stamp)
del enrico
###############
# Back to Bob #
###############
# Now Bob can retrieve the original message by requesting re-encryption from nodes.
cleartexts = bob.retrieve(ciphertext,
label=label,
policy_encrypting_key=policy_public_key,
alice_verifying_key=alice_verifying_key)
# We show that indeed this is the passage originally encrypted by Enrico.
assert plaintext == cleartexts[0]
bob.disenchant()

View File

@ -0,0 +1,22 @@
Poof! There's puff for ye, begor, and planxty of it, all abound
me breadth! Glor galore and glory be! As broad as its lung and
as long as a line ! The valiantine vaux of Venerable Val Vous-
dem. If my jaws must brass away like the due drops on my lay.
And the topnoted delivery you'd expected be me invoice! Theo
Dunnohoo's warning from Daddy O'Dowd. Whoo.^ What I'm
wondering to myselfwhose for there's a strong tendency, to put
it mildly, by making me the medium. I feel spirts of itchery out-
ching out from all over me and only for the sludgehummer's
force in my hand to hold them the darkens alone knows what' 11
who'll be saying of next. However. Now, before my upperotic
rogister, something nice. Now.^ Dear Sister, in perfect leave again I
say take a brokerly advice and keep it to yourself that we, Jaun, first
of our name here now make all receptacles of, free of price. Easy,
my dear, if they tingle you either say nothing or nod. No cheeka-
cheek with chipperchapper, you and your last mashboy and the
padre in the pulpbox enumerating you his nostrums. Be vacillant
over those vigilant who would leave you to belave black on white.
Close in for psychical hijiniks as well but fight shy of mugpunters.
I'd burn the books that grieve you and light an allassundrian bom-
pyre that would suffragate Tome Plyfire or Zolfanerole. Perousse
instate your Weekly Standerd^ our verile organ that is ethelred by all ^'^

View File

@ -0,0 +1,2 @@
Sister demo for Finnegan's wake for use on lynx/goerli testnet.
Alice and Bob API cleanup compelled by EthDenver 2021.

View File

@ -213,9 +213,8 @@ class ContractAdministrator(NucypherTokenActor):
def __init__(self,
registry: BaseContractRegistry,
deployer_address: str = None,
client_password: str = None,
signer: Signer = None,
is_transacting: bool = True, # FIXME: Workaround to be able to build MultiSig TXs
is_transacting: bool = True,
economics: BaseEconomics = None):
"""
Note: super() is not called here to avoid setting the token agent. TODO: call super but use "bare mode" without token agent. #1510
@ -232,10 +231,10 @@ class ContractAdministrator(NucypherTokenActor):
# Powers
if is_transacting:
self.deployer_power = TransactingPower(signer=signer,
password=client_password,
account=deployer_address,
cache=True)
if not signer:
raise ValueError('signer is required to make a transacting ContractAdministrator.')
self.deployer_power = TransactingPower(signer=signer, account=deployer_address)
self.transacting_power = self.deployer_power
self.transacting_power.activate()
else:
@ -253,7 +252,7 @@ class ContractAdministrator(NucypherTokenActor):
def recruit_sidekick(self, sidekick_address: str, sidekick_password: str):
self.sidekick_power = TransactingPower(account=sidekick_address, password=sidekick_password, cache=True)
if self.sidekick_power.is_device:
raise ValueError("Holy Wallet! Sidekicks can only be SW accounts")
raise ValueError("Holy Wallet! Sidekicks can only be SW accounts.")
self.sidekick_address = sidekick_address
def activate_deployer(self, refresh: bool = True):
@ -404,15 +403,16 @@ class Trustee(MultiSigActor):
def __init__(self,
checksum_address: str,
client_password: str = None,
is_transacting: bool,
signer: Optional[Signer] = None,
*args, **kwargs):
super().__init__(checksum_address=checksum_address, *args, **kwargs)
self.authorizations = dict()
self.executive_addresses = tuple(
self.multisig_agent.owners) # TODO: Investigate unresolved reference to .owners (linter)
if client_password: # TODO: Consider an is_transacting parameter
self.transacting_power = TransactingPower(password=client_password,
account=checksum_address)
self.executive_addresses = tuple(self.multisig_agent.owners)
if is_transacting:
if not signer:
raise ValueError('signer is required to create a transacting Trustee.')
self.transacting_power = TransactingPower(account=checksum_address, signer=signer)
self.transacting_power.activate()
def add_authorization(self, authorization, proposal: Proposal) -> str:
@ -495,7 +495,6 @@ class Executive(MultiSigActor):
def __init__(self,
checksum_address: str,
signer: Signer = None,
client_password: str = None,
*args, **kwargs):
super().__init__(checksum_address=checksum_address, *args, **kwargs)
@ -504,9 +503,7 @@ class Executive(MultiSigActor):
f"Current owners are {self.multisig_agent.owners}")
self.signer = signer
if signer:
self.transacting_power = TransactingPower(signer=signer,
password=client_password,
account=checksum_address)
self.transacting_power = TransactingPower(signer=signer, account=checksum_address)
self.transacting_power.activate()
def authorize_proposal(self, proposal) -> Authorization:
@ -1645,7 +1642,6 @@ class Bidder(NucypherTokenActor):
checksum_address: str,
transacting: bool = True,
signer: Signer = None,
client_password: str = None,
*args, **kwargs):
super().__init__(checksum_address=checksum_address, *args, **kwargs)
@ -1655,9 +1651,9 @@ class Bidder(NucypherTokenActor):
self.economics = EconomicsFactory.get_economics(registry=self.registry)
if transacting:
self.transacting_power = TransactingPower(signer=signer,
password=client_password,
account=checksum_address)
if not signer:
raise ValueError('signer is required to init a transacting Bidder.')
self.transacting_power = TransactingPower(signer=signer, account=checksum_address)
self.transacting_power.activate()
self._all_bonus_bidders = None
@ -1908,14 +1904,11 @@ class DaoActor(BaseActor):
checksum_address: ChecksumAddress,
registry=None,
signer: Signer = None,
client_password: str = None,
transacting: bool = True):
super().__init__(registry=registry, domain=network, checksum_address=checksum_address)
self.dao_registry = DAORegistry(network=network)
if transacting: # TODO: This logic is repeated in Bidder and possible others.
self.transacting_power = TransactingPower(signer=signer,
password=client_password,
account=checksum_address)
self.transacting_power = TransactingPower(signer=signer, account=checksum_address)
self.transacting_power.activate()

View File

@ -355,11 +355,6 @@ class KeystoreSigner(Signer):
Decrypt the signing material from the key metadata file and cache it on
the keystore instance is decryption is successful.
"""
if not password:
# It is possible that password is None here passed from the above layer
# causing Account.decrypt to crash, expecting a value for password.
raise self.AccessDenied('No password supplied to unlock account.')
if not self.__signers.get(account):
try:
key_metadata = self.__keys[account]
@ -368,6 +363,12 @@ class KeystoreSigner(Signer):
try:
signing_key = Account.from_key(Account.decrypt(key_metadata, password))
self.__signers[account] = signing_key
except TypeError:
if not password:
# It is possible that password is None here passed from the above layer
# causing Account.decrypt to crash, expecting a value for password.
raise self.AccessDenied('No password supplied to unlock account.')
raise
except ValueError as e:
raise self.AccessDenied("Invalid or incorrect signer password.") from e
return True

View File

@ -116,8 +116,6 @@ class Alice(Character, BlockchainPolicyAuthor):
# Ownership
checksum_address: str = None,
client_password: str = None,
cache_password: bool = False,
# M of N
m: int = None,
@ -164,10 +162,8 @@ class Alice(Character, BlockchainPolicyAuthor):
if is_me and not federated_only: # TODO: #289
blockchain = BlockchainInterfaceFactory.get_interface(provider_uri=self.provider_uri)
self.transacting_power = TransactingPower(account=self.checksum_address,
password=client_password,
cache=cache_password,
signer=signer or Web3Signer(blockchain.client))
signer = signer or Web3Signer(blockchain.client) # fallback to web3 provider by default for Alice.
self.transacting_power = TransactingPower(account=self.checksum_address, signer=signer)
self._crypto_power.consume_power_up(self.transacting_power)
BlockchainPolicyAuthor.__init__(self,
@ -176,11 +172,12 @@ class Alice(Character, BlockchainPolicyAuthor):
duration_periods=duration_periods,
checksum_address=checksum_address)
if is_me and controller:
self.make_cli_controller()
self.log = Logger(self.__class__.__name__)
self.log.info(self.banner)
if is_me:
if controller:
self.make_cli_controller()
self.log.info(self.banner)
self.active_policies = dict()
self.revocation_kits = dict()
@ -493,8 +490,18 @@ class Bob(Character):
def __init__(self, evidence: List):
self.evidence = evidence
def __init__(self, treasure_maps: Optional[Dict] = None, controller: bool = True, *args, **kwargs) -> None:
Character.__init__(self, known_node_class=Ursula, *args, **kwargs)
def __init__(self,
is_me: bool = True,
treasure_maps: Optional[Dict] = None,
controller: bool = True,
verify_node_bonding: bool = False,
*args, **kwargs) -> None:
Character.__init__(self,
is_me=is_me,
known_node_class=Ursula,
verify_node_bonding=verify_node_bonding,
*args, **kwargs)
if controller:
self.make_cli_controller()
@ -507,7 +514,8 @@ class Bob(Character):
self._completed_work_orders = WorkOrderHistory()
self.log = Logger(self.__class__.__name__)
self.log.info(self.banner)
if is_me:
self.log.info(self.banner)
def get_card(self) -> 'Card':
from nucypher.policy.identity import Card
@ -801,15 +809,23 @@ class Bob(Character):
return True, cfrags
def retrieve(self,
# Policy
*message_kits: UmbralMessageKit,
alice_verifying_key: UmbralPublicKey,
alice_verifying_key: Union[UmbralPublicKey, bytes],
label: bytes,
# Source Authentication
enrico: "Enrico" = None,
policy_encrypting_key: UmbralPublicKey = None,
# Retrieval Behaviour
retain_cfrags: bool = False,
use_attached_cfrags: bool = False,
use_precedent_work_orders: bool = False,
policy_encrypting_key: UmbralPublicKey = None,
treasure_map: Union['TreasureMap', bytes] = None):
treasure_map: Union['TreasureMap', bytes] = None
) -> List[bytes]:
# Try our best to get an UmbralPublicKey from input
alice_verifying_key = UmbralPublicKey.from_bytes(bytes(alice_verifying_key))
@ -833,7 +849,12 @@ class Bob(Character):
# self.treasure_maps[treasure_map.public_id()] = treasure_map # TODO: Can we?
else:
map_id = self.construct_map_id(alice_verifying_key, label)
treasure_map = self.treasure_maps[map_id]
try:
treasure_map = self.treasure_maps[map_id]
except KeyError:
# If the treasure map is not known, join the policy as part of retrieval.
self.join_policy(label=label, alice_verifying_key=alice_verifying_key)
treasure_map = self.treasure_maps[map_id]
_unknown_ursulas, _known_ursulas, m = self.follow_treasure_map(treasure_map=treasure_map, block=True)
@ -842,8 +863,7 @@ class Bob(Character):
# Normalization
for message in message_kits:
message.ensure_correct_sender(enrico=enrico,
policy_encrypting_key=policy_encrypting_key)
message.ensure_correct_sender(enrico=enrico, policy_encrypting_key=policy_encrypting_key)
# Sanity check: If we're not using attached cfrags, we don't want a Capsule which has them.
if not use_attached_cfrags and any(len(message.capsule) > 0 for message in message_kits):
@ -1450,6 +1470,18 @@ class Ursula(Teacher, Character, Worker):
seed_uri = f'{seednode_metadata.checksum_address}@{seednode_metadata.rest_host}:{seednode_metadata.rest_port}'
return cls.from_seed_and_stake_info(seed_uri=seed_uri, *args, **kwargs)
@classmethod
def seednode_for_network(cls, network: str) -> 'Ursula':
"""Returns a default seednode ursula for a given network."""
try:
url = RestMiddleware.TEACHER_NODES[network][0]
except KeyError:
raise ValueError(f'"{network}" is not a known network.')
except IndexError:
raise ValueError(f'No default seednodes available for "{network}".')
ursula = cls.from_seed_and_stake_info(seed_uri=url)
return ursula
@classmethod
def from_teacher_uri(cls,
federated_only: bool,
@ -1503,7 +1535,7 @@ class Ursula(Teacher, Character, Worker):
#
# Parse node URI
host, port, checksum_address = parse_node_uri(seed_uri)
host, port, staker_address = parse_node_uri(seed_uri)
# Fetch the hosts TLS certificate and read the common name
try:
@ -1529,19 +1561,18 @@ class Ursula(Teacher, Character, Worker):
)
# Check the node's stake (optional)
if minimum_stake > 0 and not federated_only:
if minimum_stake > 0 and staker_address and not federated_only:
staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=registry)
seednode_stake = staking_agent.get_locked_tokens(staker_address=checksum_address)
seednode_stake = staking_agent.get_locked_tokens(staker_address=staker_address)
if seednode_stake < minimum_stake:
raise Learner.NotATeacher(
f"{checksum_address} is staking less than the specified minimum stake value ({minimum_stake}).")
raise Learner.NotATeacher(f"{staker_address} is staking less than the specified minimum stake value ({minimum_stake}).")
# OK - everyone get out
temp_node_storage.forget()
return potential_seed_node
@classmethod
def payload_splitter(cls, splittable, partial=False):
def payload_splitter(cls, splittable, partial: bool = False):
splitter = BytestringKwargifier(
_receiver=cls.from_processed_bytes,
_partial_receiver=NodeSprout,
@ -1549,7 +1580,10 @@ class Ursula(Teacher, Character, Worker):
domain=VariableLengthBytestring,
timestamp=(int, 4, {'byteorder': 'big'}),
interface_signature=Signature,
decentralized_identity_evidence=VariableLengthBytestring, # FIXME: Fixed length doesn't work with federated. It was LENGTH_ECDSA_SIGNATURE_WITH_RECOVERY,
# FIXME: Fixed length doesn't work with federated. It was LENGTH_ECDSA_SIGNATURE_WITH_RECOVERY,
decentralized_identity_evidence=VariableLengthBytestring,
verifying_key=(UmbralPublicKey, PUBLIC_KEY_LENGTH),
encrypting_key=(UmbralPublicKey, PUBLIC_KEY_LENGTH),
certificate=(load_pem_x509_certificate, VariableLengthBytestring, {"backend": default_backend()}),
@ -1736,19 +1770,25 @@ class Enrico(Character):
_interface_class = EnricoInterface
_default_crypto_powerups = [SigningPower]
def __init__(self, policy_encrypting_key=None, controller: bool = True, *args, **kwargs):
def __init__(self,
is_me: bool = True,
policy_encrypting_key: Optional[UmbralPublicKey] = None,
controller: bool = True,
*args, **kwargs):
self._policy_pubkey = policy_encrypting_key
# Enrico never uses the blockchain, hence federated_only)
# Enrico never uses the blockchain (hence federated_only)
kwargs['federated_only'] = True
kwargs['known_node_class'] = None
super().__init__(*args, **kwargs)
super().__init__(is_me=is_me, *args, **kwargs)
if controller:
self.make_cli_controller()
self.log = Logger(f'{self.__class__.__name__}-{bytes(self.public_keys(SigningPower)).hex()[:6]}')
self.log.info(self.banner.format(policy_encrypting_key))
if is_me:
self.log.info(self.banner.format(policy_encrypting_key))
def encrypt_message(self, plaintext: bytes) -> Tuple[UmbralMessageKit, Signature]:
# TODO: #2107 Rename to "encrypt"

View File

@ -15,16 +15,17 @@ You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
from copy import copy
import tempfile
from eth_tester.exceptions import ValidationError
from unittest.mock import patch
from eth_tester.exceptions import ValidationError
from nucypher.blockchain.eth.signers.software import Web3Signer
from nucypher.characters.lawful import Alice, Ursula
from nucypher.config.constants import TEMPORARY_DOMAIN
from nucypher.crypto.api import encrypt_and_sign
from nucypher.crypto.constants import HRAC_LENGTH
from nucypher.crypto.powers import CryptoPower, SigningPower, DecryptingPower, TransactingPower
from nucypher.exceptions import DevelopmentInstallationRequired
from nucypher.policy.collections import SignedTreasureMap
@ -70,8 +71,9 @@ class Vladimir(Ursula):
if claim_signing_key:
crypto_power.consume_power_up(SigningPower(public_key=target_ursula.stamp.as_umbral_pubkey()))
blockchain = target_ursula.policy_agent.blockchain
if attach_transacting_key:
cls.attach_transacting_key(blockchain=target_ursula.policy_agent.blockchain)
cls.attach_transacting_key(blockchain=blockchain)
db_filepath = tempfile.mkdtemp(prefix='Vladimir')
@ -87,6 +89,7 @@ class Vladimir(Ursula):
network_middleware=cls.network_middleware,
checksum_address=cls.fraud_address,
worker_address=cls.fraud_address,
signer=Web3Signer(blockchain.client),
######### Asshole.
timestamp=target_ursula._timestamp,
interface_signature=target_ursula._interface_signature,

View File

@ -281,7 +281,6 @@ class AliceCharacterOptions:
unlock_keyring=not config.dev_mode,
teacher_uri=self.teacher_uri,
min_stake=self.min_stake,
client_password=client_password,
start_learning_now=load_seednodes,
lonely=self.config_options.lonely)
return ALICE

View File

@ -92,7 +92,6 @@ class DaoOptions: # TODO: This class is essentially the same that WorkLock opti
actor = EmergencyResponseManager(checksum_address=self.participant_address, # bomberos
network=self.network,
registry=registry,
client_password=client_password,
signer=signer,
transacting=transacting)
return actor

View File

@ -200,15 +200,14 @@ class ActorOptions:
click.confirm(CONFIRM_SELECTED_ACCOUNT.format(address=deployer_address), abort=True)
is_clef = ClefSigner.is_valid_clef_uri(self.signer_uri)
eth_password_is_needed = not self.hw_wallet and not deployer_interface.client.is_local and not is_clef
if eth_password_is_needed:
password_required = not self.hw_wallet and not deployer_interface.client.is_local and not is_clef
if password_required:
password = get_client_password(checksum_address=deployer_address)
# Produce Actor
testnet = deployer_interface.client.chain_name != PUBLIC_CHAINS[1] # Mainnet
signer = Signer.from_signer_uri(self.signer_uri, testnet=testnet) if self.signer_uri else None
ADMINISTRATOR = ContractAdministrator(registry=local_registry,
client_password=password,
deployer_address=deployer_address,
is_transacting=is_transacting,
signer=signer)

View File

@ -161,7 +161,7 @@ class FelixCharacterOptions:
envvar=NUCYPHER_ENVVAR_WORKER_ETH_PASSWORD)
# Produce Felix
FELIX = felix_config.produce(domain=self.config_options.domain, client_password=client_password)
FELIX = felix_config.produce(domain=self.config_options.domain)
FELIX.make_web_app() # attach web application, but dont start service
return FELIX

View File

@ -110,8 +110,7 @@ class MultiSigOptions:
client_password = get_client_password(checksum_address=self.checksum_address)
executive = Executive(checksum_address=self.checksum_address,
registry=registry,
signer=ClefSigner(self.signer_uri),
client_password=client_password)
signer=ClefSigner(self.signer_uri))
return executive
def create_executive(self, registry) -> Executive: # TODO: Reconsider this method: Executives don't transact, just sign.
@ -125,7 +124,7 @@ class MultiSigOptions:
is_clef = ClefSigner.is_valid_clef_uri(self.signer_uri)
if transacting and not self.hw_wallet and not is_clef:
client_password = get_client_password(checksum_address=self.checksum_address)
trustee = Trustee(checksum_address=self.checksum_address, registry=registry, client_password=client_password)
trustee = Trustee(checksum_address=self.checksum_address, registry=registry)
return trustee
def create_trustee(self, registry) -> Trustee:

View File

@ -264,11 +264,11 @@ class UrsulaCharacterOptions:
try:
URSULA = make_cli_character(character_config=ursula_config,
emitter=emitter,
client_password=client_password,
min_stake=self.min_stake,
teacher_uri=self.teacher_uri,
unlock_keyring=not self.config_options.dev,
lonely=self.config_options.lonely,
client_password=client_password,
start_learning_now=load_seednodes)
return ursula_config, URSULA

View File

@ -114,17 +114,19 @@ class WorkLockOptions:
def __create_bidder(self,
registry,
transacting: bool = True,
hw_wallet: bool = False) -> Bidder:
hw_wallet: bool = False
) -> Bidder:
client_password = None
is_clef = ClefSigner.is_valid_clef_uri(self.signer_uri)
if transacting and not is_clef and not hw_wallet:
client_password = get_client_password(checksum_address=self.bidder_address)
testnet = self.network != NetworksInventory.MAINNET
signer = Signer.from_signer_uri(self.signer_uri, testnet=testnet) if self.signer_uri else None
password_required = (not is_clef and not hw_wallet)
if signer and transacting and password_required:
client_password = get_client_password(checksum_address=self.bidder_address)
signer.unlock_account(account=self.bidder_address, password=client_password)
bidder = Bidder(checksum_address=self.bidder_address,
registry=registry,
client_password=client_password,
signer=signer,
transacting=transacting)
return bidder

View File

@ -55,7 +55,7 @@ def make_cli_character(character_config,
emitter,
unlock_keyring: bool = True,
teacher_uri: str = None,
min_stake: int = 0, # We not using this anymore? Where is it hooked up?
min_stake: int = 0,
**config_args) -> Character:
#
@ -79,11 +79,13 @@ def make_cli_character(character_config,
# Produce Character
if teacher_uri:
maybe_sage_node = character_config.known_node_class.from_teacher_uri(teacher_uri=teacher_uri,
min_stake=0, # TODO: Where to get this?
federated_only=character_config.federated_only,
network_middleware=character_config.network_middleware,
registry=character_config.registry)
maybe_sage_node = character_config.known_node_class.from_teacher_uri(
teacher_uri=teacher_uri,
min_stake=min_stake,
federated_only=character_config.federated_only,
network_middleware=character_config.network_middleware,
registry=character_config.registry
)
sage_nodes.append(maybe_sage_node)
CHARACTER = character_config(known_nodes=sage_nodes,

View File

@ -112,7 +112,7 @@ class TransactingPower(CryptoPowerUp):
@validate_checksum_address
def __init__(self,
account: str,
signer: Signer = None,
signer: Signer,
password: str = None,
cache: bool = False):
"""
@ -121,9 +121,7 @@ class TransactingPower(CryptoPowerUp):
# Auth
if not signer:
# TODO: Consider making this required
blockchain = BlockchainInterfaceFactory.get_interface()
signer = Web3Signer(client=blockchain.client)
raise ValueError('signer is required to init a TransactingPower.')
self._signer = signer
self.__account = account
self.__password = password
@ -186,6 +184,8 @@ class TransactingPower(CryptoPowerUp):
def unlock_account(self, password: str = None, duration: int = None) -> bool:
"""Unlocks the account with provided or cached password."""
if self.is_unlocked:
return True
password = password or self.__password
result = self._signer.unlock_account(self.__account,
password=password,

View File

@ -237,7 +237,6 @@ class Learner:
self._discovery_canceller = DiscoveryCanceller()
if not node_storage:
# Fallback storage backend
node_storage = self.__DEFAULT_NODE_STORAGE(federated_only=self.federated_only)
self.node_storage = node_storage
if save_metadata and node_storage is NO_STORAGE_AVAILIBLE:
@ -415,7 +414,7 @@ class Learner:
try:
node.verify_node(force=force_verification_recheck,
network_middleware_client=self.network_middleware.client,
registry=registry) # composed on character subclass, determines operating mode
registry=registry)
except SSLError:
# TODO: Bucket this node as having bad TLS info - maybe it's an update that hasn't fully propagated? 567
return False

View File

@ -14,6 +14,8 @@
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
from eth_typing import HexStr
from web3 import Web3
from web3._utils.abi import get_constructor_abi, merge_args_and_kwargs
@ -21,6 +23,7 @@ from web3._utils.contracts import encode_abi
from web3.contract import ContractConstructor
def to_bytes32(value=None, hexstr=None) -> bytes:
return Web3.toBytes(primitive=value, hexstr=hexstr).rjust(32, b'\0')
@ -58,3 +61,17 @@ def encode_constructor_arguments(web3: Web3,
else:
data = None
return data
def connect_web3_provider(provider_uri: str) -> None:
"""
Convenience function for connecting to an ethereum provider now.
This may be used to optimize the startup time of some applications by
establishing the connection eagarly.
"""
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
if not BlockchainInterfaceFactory.is_interface_initialized(provider_uri=provider_uri):
BlockchainInterfaceFactory.initialize_interface(provider_uri=provider_uri)
interface = BlockchainInterfaceFactory.get_interface(provider_uri=provider_uri)
interface.connect()

View File

@ -1,7 +1,6 @@
version: '3'
# USAGE
# docker-compose run nucypher-circle-dev bash download_finnegans_wake.sh
# docker-compose run nucypher-circle-dev python finnegans-wake-demo.py 172.29.1.3:11500
services:
@ -17,6 +16,8 @@ services:
networks:
nucypher_circle_net:
ipv4_address: 172.29.1.0
environment:
- FINNEGANS_WAKE_PATH=finnegans_wake_demo/finnegans-wake-excerpt.txt
circleursula1:
ports:
- 11500
@ -148,8 +149,6 @@ services:
ipv4_address: 172.29.1.12
container_name: circleursula12
networks:
nucypher_circle_net:
ipam:

View File

@ -1,7 +0,0 @@
#!/usr/bin/env bash
# runs in docker on circle ci
set -e
/code/examples/finnegans_wake_demo/download_finnegans_wake.sh
python /code/examples/finnegans_wake_demo/finnegans-wake-demo.py 172.29.1.3:11500

View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
# runs in docker on circle ci
set -e
python /code/examples/finnegans_wake_demo/finnegans-wake-demo-federated.py 172.29.1.3:11500

View File

@ -11,7 +11,7 @@ cd "${0%/*}"
echo "working in directory: $PWD"
# run some ursulas
docker-compose up -d
docker-compose up -d --build
# Wait to ensure Ursulas are up.
echo "War... watisit good for?"
@ -21,7 +21,7 @@ sleep 3
# Run demo
echo "Starting Demo"
echo "working in directory: $PWD"
docker-compose run nucypher-circle-dev bash /code/scripts/circle/download_and_run_finnegans_wake.sh
docker-compose run nucypher-circle-dev bash /code/scripts/circle/run_finnegans_wake.sh
# spit out logs
./logOutput.sh

View File

@ -20,6 +20,7 @@ import random
import pytest
from eth_tester.exceptions import TransactionFailed
from nucypher.blockchain.eth.signers.software import Web3Signer
from nucypher.blockchain.eth.actors import Bidder
from nucypher.blockchain.eth.agents import ContractAgency, StakingEscrowAgent, WorkLockAgent
from nucypher.blockchain.eth.constants import NULL_ADDRESS
@ -27,7 +28,7 @@ from nucypher.blockchain.eth.constants import NULL_ADDRESS
def test_create_bidder(testerchain, test_registry, agency, token_economics):
bidder_address = testerchain.unassigned_accounts[0]
bidder = Bidder(checksum_address=bidder_address, registry=test_registry)
bidder = Bidder(checksum_address=bidder_address, registry=test_registry, signer=Web3Signer(testerchain.client))
assert bidder.checksum_address == bidder_address
assert bidder.registry == test_registry
@ -48,7 +49,7 @@ def test_bidding(testerchain, agency, token_economics, test_registry):
for i, bid in enumerate(initial_bids):
bidder_address = testerchain.client.accounts[i]
bidder = Bidder(checksum_address=bidder_address, registry=test_registry)
bidder = Bidder(checksum_address=bidder_address, registry=test_registry, signer=Web3Signer(testerchain.client))
assert bidder.get_deposited_eth == 0
receipt = bidder.place_bid(value=bid)
@ -61,7 +62,7 @@ def test_cancel_bid(testerchain, agency, token_economics, test_registry):
testerchain.time_travel(seconds=token_economics.bidding_duration+1)
bidder_address = testerchain.client.accounts[1]
bidder = Bidder(checksum_address=bidder_address, registry=test_registry)
bidder = Bidder(checksum_address=bidder_address, registry=test_registry, signer=Web3Signer(testerchain.client))
assert bidder.get_deposited_eth # Bid
receipt = bidder.cancel_bid() # Cancel
assert receipt['status'] == 1
@ -74,14 +75,14 @@ def test_cancel_bid(testerchain, agency, token_economics, test_registry):
def test_get_remaining_work(testerchain, agency, token_economics, test_registry):
bidder_address = testerchain.client.accounts[0]
bidder = Bidder(checksum_address=bidder_address, registry=test_registry)
bidder = Bidder(checksum_address=bidder_address, registry=test_registry, signer=Web3Signer(testerchain.client))
remaining = bidder.remaining_work
assert remaining
def test_verify_correctness_before_refund(testerchain, agency, token_economics, test_registry):
bidder_address = testerchain.client.accounts[0]
bidder = Bidder(checksum_address=bidder_address, registry=test_registry)
bidder = Bidder(checksum_address=bidder_address, registry=test_registry, signer=Web3Signer(testerchain.client))
worklock_agent = ContractAgency.get_agent(WorkLockAgent, registry=test_registry)
with pytest.raises(Bidder.CancellationWindowIsOpen):
@ -99,7 +100,7 @@ def test_verify_correctness_before_refund(testerchain, agency, token_economics,
def test_force_refund(testerchain, agency, token_economics, test_registry):
bidder_address = testerchain.client.accounts[0]
bidder = Bidder(checksum_address=bidder_address, registry=test_registry)
bidder = Bidder(checksum_address=bidder_address, registry=test_registry, signer=Web3Signer(testerchain.client))
whales = bidder.get_whales()
# Simulate force refund
@ -110,7 +111,7 @@ def test_force_refund(testerchain, agency, token_economics, test_registry):
new_whales = bidder.get_whales()
bidder_address = testerchain.client.accounts[1]
bidder = Bidder(checksum_address=bidder_address, registry=test_registry)
bidder = Bidder(checksum_address=bidder_address, registry=test_registry, signer=Web3Signer(testerchain.client))
worklock_agent = ContractAgency.get_agent(WorkLockAgent, registry=test_registry)
receipt = bidder.force_refund()
@ -127,7 +128,7 @@ def test_force_refund(testerchain, agency, token_economics, test_registry):
def test_verify_correctness(testerchain, agency, token_economics, test_registry):
bidder_address = testerchain.client.accounts[0]
bidder = Bidder(checksum_address=bidder_address, registry=test_registry)
bidder = Bidder(checksum_address=bidder_address, registry=test_registry, signer=Web3Signer(testerchain.client))
worklock_agent = ContractAgency.get_agent(WorkLockAgent, registry=test_registry)
assert not worklock_agent.bidders_checked()
@ -143,7 +144,7 @@ def test_verify_correctness(testerchain, agency, token_economics, test_registry)
def test_withdraw_compensation(testerchain, agency, token_economics, test_registry):
bidder_address = testerchain.client.accounts[12]
bidder = Bidder(checksum_address=bidder_address, registry=test_registry)
bidder = Bidder(checksum_address=bidder_address, registry=test_registry, signer=Web3Signer(testerchain.client))
worklock_agent = ContractAgency.get_agent(WorkLockAgent, registry=test_registry)
assert worklock_agent.get_available_compensation(checksum_address=bidder_address) > 0
@ -154,7 +155,7 @@ def test_withdraw_compensation(testerchain, agency, token_economics, test_regist
def test_claim(testerchain, agency, token_economics, test_registry):
bidder_address = testerchain.client.accounts[11]
bidder = Bidder(checksum_address=bidder_address, registry=test_registry)
bidder = Bidder(checksum_address=bidder_address, registry=test_registry, signer=Web3Signer(testerchain.client))
staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=test_registry)
worklock_agent = ContractAgency.get_agent(WorkLockAgent, registry=test_registry)

View File

@ -21,6 +21,7 @@ import json
import pytest
import random
from nucypher.blockchain.eth.signers.software import Web3Signer
from nucypher.blockchain.eth.actors import ContractAdministrator
from nucypher.crypto.powers import TransactingPower
from tests.constants import INSECURE_DEVELOPMENT_PASSWORD, NUMBER_OF_ALLOCATIONS_IN_TESTS
@ -37,11 +38,14 @@ def test_rapid_deployment(token_economics, test_registry, tmpdir, get_random_che
# TODO: #1092 - TransactingPower
blockchain.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD,
signer=Web3Signer(blockchain.client),
account=blockchain.etherbase_account)
blockchain.transacting_power.activate()
deployer_address = blockchain.etherbase_account
administrator = ContractAdministrator(deployer_address=deployer_address, registry=test_registry)
administrator = ContractAdministrator(deployer_address=deployer_address,
signer=Web3Signer(blockchain.client),
registry=test_registry)
blockchain.bootstrap_network(registry=test_registry)
all_yall = blockchain.unassigned_accounts

View File

@ -15,11 +15,10 @@ You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import pytest
from unittest.mock import patch
from nucypher.blockchain.eth.signers.software import Web3Signer
from nucypher.blockchain.eth.actors import Trustee
from nucypher.blockchain.eth.agents import MultiSigAgent
from nucypher.blockchain.eth.deployers import MultiSigDeployer
@ -33,10 +32,13 @@ def test_trustee_proposes_multisig_management_operations(testerchain, test_regis
for step in multisig_deployer.deployment_steps:
assert receipts[step]['status'] == 1
multisig_agent = multisig_deployer.make_agent() # type: MultiSigAgent
multisig_agent = multisig_deployer.make_agent()
trustee_address = testerchain.unassigned_accounts[-1]
trustee = Trustee(checksum_address=trustee_address, registry=test_registry)
trustee = Trustee(checksum_address=trustee_address,
signer=Web3Signer(testerchain.client),
registry=test_registry,
is_transacting=True)
# Propose changing threshold
free_payload = {'nonce': 0, 'from': multisig_agent.contract_address, 'gasPrice': 0}

View File

@ -256,6 +256,8 @@ def test_staker_collects_staking_reward(testerchain,
ursula_decentralized_test_config):
token_agent, staking_agent, policy_agent = agency
testerchain.transacting_power.activate()
# Give more tokens to staker
token_airdrop(token_agent=token_agent,
origin=testerchain.etherbase_account,
@ -263,11 +265,8 @@ def test_staker_collects_staking_reward(testerchain,
amount=DEVELOPMENT_TOKEN_AIRDROP_AMOUNT)
mock_transacting_power_activation(account=staker.checksum_address, password=INSECURE_DEVELOPMENT_PASSWORD)
staker.initialize_stake(amount=NU(token_economics.minimum_allowed_locked, 'NuNit'),
# Lock the minimum amount of tokens
lock_periods=int(
token_economics.minimum_locked_periods)) # ... for the fewest number of periods
staker.initialize_stake(amount=NU(token_economics.minimum_allowed_locked, 'NuNit'), # Lock the minimum amount of tokens
lock_periods=int(token_economics.minimum_locked_periods)) # ... for the fewest number of periods
# Get an unused address for a new worker
worker_address = testerchain.unassigned_accounts[-1]

View File

@ -149,7 +149,6 @@ def test_set_min_fee_rate(testerchain, test_registry, agency, policy_meta):
assert policy_agent.get_min_fee_rate(staker) == minimum + 1
@pytest.mark.usefixtures('blockchain_ursulas')
def test_collect_policy_fee(testerchain, agency, policy_meta, token_economics, mock_transacting_power_activation):
token_agent, staking_agent, policy_agent = agency
@ -159,12 +158,10 @@ def test_collect_policy_fee(testerchain, agency, policy_meta, token_economics, m
worker = staking_agent.get_worker_from_staker(staker)
mock_transacting_power_activation(account=worker, password=INSECURE_DEVELOPMENT_PASSWORD)
old_eth_balance = token_agent.blockchain.client.get_balance(staker)
for _ in range(token_economics.minimum_locked_periods):
staking_agent.commit_to_next_period(worker_address=worker)
testerchain.time_travel(periods=1)
staking_agent.commit_to_next_period(worker_address=worker)
mock_transacting_power_activation(account=staker, password=INSECURE_DEVELOPMENT_PASSWORD)
receipt = agent.collect_policy_fee(collector_address=staker, staker_address=staker)

View File

@ -19,6 +19,7 @@ import pytest
from constant_sorrow import constants
from eth_tester.exceptions import TransactionFailed
from nucypher.blockchain.eth.signers.software import Web3Signer
from nucypher.blockchain.eth.actors import Staker
from nucypher.blockchain.eth.agents import ContractAgency, NucypherTokenAgent, StakingEscrowAgent
from nucypher.blockchain.eth.deployers import (AdjudicatorDeployer, BaseContractDeployer, NucypherTokenDeployer,
@ -131,7 +132,9 @@ def test_stake_in_idle_network(testerchain, token_economics, test_registry):
staker = Staker(is_me=True, checksum_address=account, registry=test_registry)
# Mock TransactingPower consumption
staker.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD, account=staker.checksum_address)
staker.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD,
signer=Web3Signer(testerchain.client),
account=staker.checksum_address)
staker.transacting_power.activate()
# Since StakingEscrow hasn't been activated yet, deposit should work but making a commitment must fail

View File

@ -18,6 +18,7 @@
from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface, BlockchainInterfaceFactory
from nucypher.blockchain.eth.registry import InMemoryContractRegistry
from nucypher.blockchain.eth.signers.software import Web3Signer
from nucypher.blockchain.eth.sol.compile.constants import TEST_MULTIVERSION_CONTRACTS
from nucypher.blockchain.eth.sol.compile.types import SourceBundle
from nucypher.crypto.powers import TransactingPower
@ -49,7 +50,9 @@ def test_deployer_interface_multiversion_contract():
BlockchainInterfaceFactory.register_interface(interface=blockchain_interface) # Lets this test run in isolation
origin = blockchain_interface.client.accounts[0]
blockchain_interface.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD, account=origin)
blockchain_interface.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD,
signer=Web3Signer(blockchain_interface.client),
account=origin)
blockchain_interface.transacting_power.activate()
# Searching both contract through raw data

View File

@ -20,10 +20,10 @@ import pytest
from nucypher.blockchain.eth.clients import EthereumClient
from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface
from nucypher.blockchain.eth.registry import InMemoryContractRegistry
from nucypher.blockchain.eth.signers.software import Web3Signer
from nucypher.blockchain.eth.sol.compile.compile import multiversion_compile
from nucypher.blockchain.eth.sol.compile.constants import TEST_MULTIVERSION_CONTRACTS, SOLIDITY_SOURCE_ROOT
from nucypher.blockchain.eth.sol.compile.types import SourceBundle
from nucypher.config.constants import NUCYPHER_TEST_DIR
from nucypher.crypto.powers import TransactingPower
from tests.constants import (
DEVELOPMENT_ETH_AIRDROP_AMOUNT,
@ -112,7 +112,9 @@ def test_multiversion_contract():
blockchain_interface._raw_contract_cache = compiled_contracts
origin = blockchain_interface.client.accounts[0]
blockchain_interface.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD, account=origin)
blockchain_interface.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD,
signer=Web3Signer(blockchain_interface.client),
account=origin)
blockchain_interface.transacting_power.activate()
# Searching both contract through raw data

View File

@ -15,10 +15,12 @@
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import pytest
from eth_account._utils.transactions import Transaction
from eth_utils import to_checksum_address
from nucypher.blockchain.eth.signers.software import Web3Signer
from nucypher.blockchain.eth.agents import NucypherTokenAgent
from nucypher.crypto.api import verify_eip_191
from nucypher.crypto.powers import TransactingPower
@ -33,6 +35,7 @@ def test_transacting_power_sign_message(testerchain):
# Manually create a TransactingPower
eth_address = testerchain.etherbase_account
power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD,
signer=Web3Signer(testerchain.client),
account=eth_address)
# The default state of the account is locked.
@ -69,6 +72,7 @@ def test_transacting_power_sign_transaction(testerchain):
eth_address = testerchain.unassigned_accounts[2]
power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD,
signer=Web3Signer(testerchain.client),
account=eth_address)
assert power.is_active is False
@ -116,6 +120,7 @@ def test_transacting_power_sign_transaction(testerchain):
# Tear-Down Test
power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD,
signer=Web3Signer(testerchain.client),
account=testerchain.etherbase_account)
power.activate(password=INSECURE_DEVELOPMENT_PASSWORD)
@ -134,6 +139,7 @@ def test_transacting_power_sign_agent_transaction(testerchain, agency, test_regi
# Sign with Transacting Power
transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD,
signer=Web3Signer(testerchain.client),
account=testerchain.etherbase_account)
transacting_power.activate()
signed_raw_transaction = transacting_power.sign_transaction(unsigned_transaction)

View File

@ -48,6 +48,7 @@ def test_deploy_single_contract(click_runner, tempfile_path):
'--contract-name', NucypherTokenAgent.contract_name,
'--registry-infile', tempfile_path,
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--debug']
@ -106,6 +107,7 @@ def test_upgrade_contracts(click_runner, test_registry_source_manager, test_regi
cli_action = 'upgrade'
base_command = ('--registry-infile', registry_filepath,
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--confirmations', 1,
'--network', TEMPORARY_DOMAIN,
'--force' # skip registry preflight check for tests
@ -234,7 +236,9 @@ def test_rollback(click_runner, testerchain, registry_filepath, agency):
'--contract-name', contract_name,
'--registry-infile', registry_filepath,
'--network', TEMPORARY_DOMAIN,
'--provider', TEST_PROVIDER_URI)
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI
)
user_input = '0\n' + YES_ENTER
result = click_runner.invoke(deploy, command, input=user_input, catch_exceptions=False)

View File

@ -62,6 +62,7 @@ def test_set_range(click_runner, testerchain, agency_local_registry):
minimum, default, maximum = 10, 20, 30
status_command = ('set-range',
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--registry-infile', agency_local_registry.filepath,
'--minimum', minimum,
'--default', default,
@ -122,6 +123,7 @@ def test_transfer_ownership(click_runner, testerchain, agency_local_registry):
'--registry-infile', agency_local_registry.filepath,
'--contract-name', STAKING_ESCROW_CONTRACT_NAME,
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--target-address', maclane)
@ -146,6 +148,7 @@ def test_transfer_ownership(click_runner, testerchain, agency_local_registry):
'--contract-name', STAKING_ESCROW_CONTRACT_NAME,
'--registry-infile', agency_local_registry.filepath,
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--target-address', michwill)
@ -171,6 +174,7 @@ def test_transfer_ownership_staking_interface_router(click_runner, testerchain,
'--registry-infile', agency_local_registry.filepath,
'--contract-name', StakingInterfaceDeployer.contract_name,
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--target-address', maclane,
'--debug')
@ -200,6 +204,7 @@ def test_bare_contract_deployment_to_alternate_registry(click_runner, agency_loc
'--contract-name', StakingEscrowDeployer.contract_name,
'--mode', 'bare',
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--registry-infile', agency_local_registry.filepath,
'--registry-outfile', ALTERNATE_REGISTRY_FILEPATH,
'--network', TEMPORARY_DOMAIN,
@ -246,6 +251,7 @@ def test_manual_proxy_retargeting(monkeypatch, testerchain, click_runner, token_
'--contract-name', StakingEscrowDeployer.contract_name,
'--target-address', untargeted_deployment.address,
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--registry-infile', ALTERNATE_REGISTRY_FILEPATH,
'--confirmations', 4,
'--network', TEMPORARY_DOMAIN)
@ -275,6 +281,7 @@ def test_manual_deployment_of_idle_network(click_runner):
'--contract-name', NUCYPHER_TOKEN_CONTRACT_NAME,
'--provider', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--signer', TEST_PROVIDER_URI,
'--registry-infile', ALTERNATE_REGISTRY_FILEPATH_2)
result = click_runner.invoke(deploy, command, input=user_input, catch_exceptions=False)
@ -291,6 +298,7 @@ def test_manual_deployment_of_idle_network(click_runner):
'--contract-name', STAKING_ESCROW_CONTRACT_NAME,
'--mode', 'init',
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--registry-infile', ALTERNATE_REGISTRY_FILEPATH_2)
@ -304,6 +312,7 @@ def test_manual_deployment_of_idle_network(click_runner):
command = ('contracts',
'--contract-name', POLICY_MANAGER_CONTRACT_NAME,
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--registry-infile', ALTERNATE_REGISTRY_FILEPATH_2)
@ -317,6 +326,7 @@ def test_manual_deployment_of_idle_network(click_runner):
command = ('contracts',
'--contract-name', ADJUDICATOR_CONTRACT_NAME,
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--registry-infile', ALTERNATE_REGISTRY_FILEPATH_2)
@ -331,6 +341,7 @@ def test_manual_deployment_of_idle_network(click_runner):
'--contract-name', STAKING_ESCROW_CONTRACT_NAME,
'--mode', 'idle',
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--registry-infile', ALTERNATE_REGISTRY_FILEPATH_2)
@ -345,6 +356,7 @@ def test_manual_deployment_of_idle_network(click_runner):
'--contract-name', STAKING_ESCROW_CONTRACT_NAME,
'--activate',
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--registry-infile', ALTERNATE_REGISTRY_FILEPATH_2)

View File

@ -23,6 +23,7 @@ import pytest
from eth_utils import to_wei
from web3 import Web3
from nucypher.blockchain.eth.signers.software import Web3Signer
from nucypher.crypto.powers import TransactingPower
from nucypher.blockchain.eth.actors import Bidder, Staker
from nucypher.blockchain.eth.agents import (
@ -73,6 +74,7 @@ def test_bid(click_runner, testerchain, agency_local_registry, token_economics,
base_command = ('escrow',
'--registry-filepath', agency_local_registry.filepath,
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--force')
@ -107,6 +109,7 @@ def test_cancel_bid(click_runner, testerchain, agency_local_registry, token_econ
'--participant-address', bidder,
'--registry-filepath', agency_local_registry.filepath,
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--force')
@ -123,6 +126,7 @@ def test_cancel_bid(click_runner, testerchain, agency_local_registry, token_econ
'--participant-address', bidder,
'--registry-filepath', agency_local_registry.filepath,
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--force')
@ -146,6 +150,7 @@ def test_enable_claiming(click_runner, testerchain, agency_local_registry, token
'--participant-address', bidder,
'--registry-filepath', agency_local_registry.filepath,
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--force',
'--network', TEMPORARY_DOMAIN,
'--gas-limit', 100000)
@ -165,6 +170,7 @@ def test_claim(click_runner, testerchain, agency_local_registry, token_economics
'--participant-address', bidder,
'--registry-filepath', agency_local_registry.filepath,
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--force')
@ -178,6 +184,7 @@ def test_claim(click_runner, testerchain, agency_local_registry, token_economics
'--participant-address', whale,
'--registry-filepath', agency_local_registry.filepath,
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--force')
@ -201,6 +208,7 @@ def test_remaining_work(click_runner, testerchain, agency_local_registry, token_
'--participant-address', bidder,
'--registry-filepath', agency_local_registry.filepath,
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN)
result = click_runner.invoke(worklock, command, catch_exceptions=False)
@ -230,6 +238,7 @@ def test_refund(click_runner, testerchain, agency_local_registry, token_economic
worker = Ursula(is_me=True,
registry=agency_local_registry,
checksum_address=bidder,
signer=Web3Signer(testerchain.client),
worker_address=worker_address,
rest_host=MOCK_IP_ADDRESS,
rest_port=select_test_port(),
@ -255,6 +264,7 @@ def test_refund(click_runner, testerchain, agency_local_registry, token_economic
'--participant-address', bidder,
'--registry-filepath', agency_local_registry.filepath,
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--force')
@ -268,12 +278,15 @@ def test_refund(click_runner, testerchain, agency_local_registry, token_economic
def test_participant_status(click_runner, testerchain, agency_local_registry, token_economics):
bidder = Bidder(checksum_address=testerchain.client.accounts[2], registry=agency_local_registry)
bidder = Bidder(checksum_address=testerchain.client.accounts[2],
signer=Web3Signer(testerchain.client),
registry=agency_local_registry)
command = ('status',
'--registry-filepath', agency_local_registry.filepath,
'--participant-address', bidder.checksum_address,
'--provider', TEST_PROVIDER_URI,
'--signer', TEST_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN)
result = click_runner.invoke(worklock, command, catch_exceptions=False)

View File

@ -145,9 +145,9 @@ def test_ursula_and_local_keystore_signer_integration(click_runner,
# Produce an Ursula with a Keystore signer correctly derived from the signer URI, and don't do anything else!
mocker.patch.object(StakeList, 'refresh', autospec=True)
ursula = ursula_config.produce(client_password=password,
commit_now=False,
block_until_ready=False)
ursula = ursula_config.produce(commit_now=False, block_until_ready=False)
ursula.signer.unlock_account(account=worker_account.address, password=password)
try:
# Verify the keystore path is still preserved

View File

@ -16,32 +16,41 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import json
import random
import maya
import os
import pytest
import random
import tempfile
from web3 import Web3
from nucypher.blockchain.eth.actors import Staker
from nucypher.blockchain.eth.agents import (ContractAgency, NucypherTokenAgent, PreallocationEscrowAgent,
StakingEscrowAgent)
from nucypher.blockchain.eth.agents import (
ContractAgency,
NucypherTokenAgent,
PreallocationEscrowAgent,
StakingEscrowAgent
)
from nucypher.blockchain.eth.constants import NULL_ADDRESS
from nucypher.blockchain.eth.deployers import PreallocationEscrowDeployer
from nucypher.blockchain.eth.registry import InMemoryAllocationRegistry, IndividualAllocationRegistry
from nucypher.blockchain.eth.signers.software import Web3Signer
from nucypher.blockchain.eth.token import NU, Stake, StakeList
from nucypher.characters.lawful import Enrico, Ursula
from nucypher.cli.main import nucypher_cli
from nucypher.config.characters import UrsulaConfiguration
from nucypher.config.constants import TEMPORARY_DOMAIN
from nucypher.utilities.logging import Logger
from tests.constants import (FAKE_PASSWORD_CONFIRMED, INSECURE_DEVELOPMENT_PASSWORD,
MOCK_INDIVIDUAL_ALLOCATION_FILEPATH, MOCK_IP_ADDRESS,
ONE_YEAR_IN_SECONDS,
TEST_PROVIDER_URI)
from tests.constants import (
FAKE_PASSWORD_CONFIRMED,
INSECURE_DEVELOPMENT_PASSWORD,
MOCK_INDIVIDUAL_ALLOCATION_FILEPATH,
MOCK_IP_ADDRESS,
ONE_YEAR_IN_SECONDS,
TEST_PROVIDER_URI
)
from tests.utils.middleware import MockRestMiddleware
from tests.utils.ursula import MOCK_KNOWN_URSULAS_CACHE, MOCK_URSULA_STARTING_PORT, select_test_port
from tests.utils.ursula import MOCK_KNOWN_URSULAS_CACHE, select_test_port
#
@ -492,6 +501,7 @@ def test_collect_rewards_integration(click_runner,
ursula_port = select_test_port()
ursula = Ursula(is_me=True,
signer=Web3Signer(testerchain.client),
checksum_address=staker_address,
worker_address=worker_address,
registry=agency_local_registry,

View File

@ -15,18 +15,20 @@ You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import json
import os
import random
import tempfile
from unittest import mock
import maya
import os
import random
import tempfile
from web3 import Web3
from nucypher.blockchain.eth.actors import Staker
from nucypher.blockchain.eth.agents import ContractAgency, StakingEscrowAgent
from nucypher.blockchain.eth.constants import NULL_ADDRESS
from nucypher.blockchain.eth.signers.software import Web3Signer
from nucypher.blockchain.eth.token import NU, Stake
from nucypher.blockchain.eth.utils import prettify_eth_amount
from nucypher.characters.lawful import Enrico, Ursula
@ -35,11 +37,16 @@ from nucypher.cli.main import nucypher_cli
from nucypher.config.characters import StakeHolderConfiguration, UrsulaConfiguration
from nucypher.config.constants import TEMPORARY_DOMAIN
from nucypher.utilities.logging import Logger
from tests.constants import FAKE_PASSWORD_CONFIRMED, FEE_RATE_RANGE, INSECURE_DEVELOPMENT_PASSWORD, MOCK_IP_ADDRESS, \
TEST_PROVIDER_URI, YES_ENTER
from tests.constants import (
FAKE_PASSWORD_CONFIRMED,
FEE_RATE_RANGE,
INSECURE_DEVELOPMENT_PASSWORD,
MOCK_IP_ADDRESS,
TEST_PROVIDER_URI,
YES_ENTER
)
from tests.utils.middleware import MockRestMiddleware
from tests.utils.ursula import MOCK_KNOWN_URSULAS_CACHE, MOCK_URSULA_STARTING_PORT, select_test_port
from tests.utils.ursula import MOCK_KNOWN_URSULAS_CACHE, select_test_port
@mock.patch('nucypher.config.characters.StakeHolderConfiguration.default_filepath', return_value='/non/existent/file')
@ -562,6 +569,7 @@ def test_collect_rewards_integration(click_runner,
ursula_port = select_test_port()
ursula = Ursula(is_me=True,
checksum_address=staker_address,
signer=Web3Signer(testerchain.client),
worker_address=worker_address,
registry=agency_local_registry,
rest_host='127.0.0.1',

View File

@ -14,19 +14,26 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import contextlib
import os
from pathlib import Path
import requests
from constant_sorrow import constants
from pathlib import Path
from web3.exceptions import ValidationError
from nucypher.blockchain.eth.deployers import AdjudicatorDeployer, BaseContractDeployer, NucypherTokenDeployer, \
PolicyManagerDeployer, StakingEscrowDeployer, WorklockDeployer
from nucypher.blockchain.eth.deployers import (
AdjudicatorDeployer,
BaseContractDeployer,
NucypherTokenDeployer,
PolicyManagerDeployer,
StakingEscrowDeployer,
WorklockDeployer
)
from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface, BlockchainInterfaceFactory
from nucypher.blockchain.eth.registry import InMemoryContractRegistry
from nucypher.blockchain.eth.signers.software import Web3Signer
from nucypher.blockchain.eth.sol.compile.constants import SOLIDITY_SOURCE_ROOT
from nucypher.blockchain.eth.sol.compile.types import SourceBundle
from nucypher.crypto.powers import TransactingPower
@ -137,7 +144,9 @@ def test_upgradeability(temp_dir_path):
blockchain_interface.connect()
origin = blockchain_interface.client.accounts[0]
BlockchainInterfaceFactory.register_interface(interface=blockchain_interface)
blockchain_interface.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD, account=origin)
blockchain_interface.transacting_power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD,
signer=Web3Signer(blockchain_interface.client),
account=origin)
blockchain_interface.transacting_power.activate()
economics = make_token_economics(blockchain_interface)

View File

@ -171,12 +171,13 @@ def test_keystore_locking(mock_account, good_signer, unknown_address, mocker):
with pytest.raises(Signer.UnknownAccount):
good_signer.unlock_account(account=unknown_address, password=INSECURE_DEVELOPMENT_PASSWORD)
mocker.patch.dict(good_signer._KeystoreSigner__signers, {}, clear=True)
# Missing password
with pytest.raises(Signer.AccessDenied, match='No password supplied to unlock account.'):
good_signer.unlock_account(account=mock_account.address, password=None)
# Wrong password
mocker.patch.dict(good_signer._KeystoreSigner__signers, {}, clear=True)
with pytest.raises(Signer.AccessDenied, match="Invalid or incorrect signer password."):
good_signer.unlock_account(account=mock_account.address, password='imadeupthispassworditisverygood')

View File

@ -100,8 +100,9 @@ def test_ursula_init_with_local_keystore_signer(click_runner,
# Produce an ursula with a Keystore signer correctly derived from the signer URI, and dont do anything else!
mocker.patch.object(StakeList, 'refresh', autospec=True)
ursula = ursula_config.produce(client_password=password,
block_until_ready=False)
ursula = ursula_config.produce(block_until_ready=False)
ursula.signer.unlock_account(account=worker_account.address, password=password)
# Verify the keystore path is still preserved
assert isinstance(ursula.signer, KeystoreSigner)

View File

@ -24,6 +24,7 @@ import pytest
from eth_utils import to_wei
from web3 import Web3
from nucypher.blockchain.eth.signers.software import Web3Signer
from nucypher.blockchain.eth.actors import Bidder
from nucypher.blockchain.eth.interfaces import BlockchainInterface
from nucypher.blockchain.eth.utils import prettify_eth_amount
@ -51,7 +52,8 @@ from tests.mock.agents import MockContractAgent
@pytest.fixture()
def surrogate_bidder(mock_testerchain, test_registry, mock_worklock_agent):
address = mock_testerchain.etherbase_account
bidder = Bidder(checksum_address=address, registry=test_registry)
signer = Web3Signer(mock_testerchain.client)
bidder = Bidder(checksum_address=address, registry=test_registry, signer=signer)
return bidder
@ -80,9 +82,10 @@ def test_account_selection(click_runner, mocker, mock_testerchain, mock_worklock
command = ('cancel-escrow',
'--provider', MOCK_PROVIDER_URI,
'--signer', MOCK_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN)
user_input = '\n'.join((str(index), INSECURE_DEVELOPMENT_PASSWORD, YES))
user_input = '\n'.join((str(index), INSECURE_DEVELOPMENT_PASSWORD, YES, YES))
result = click_runner.invoke(worklock, command, input=user_input, catch_exceptions=False)
assert result.exit_code == 0
@ -103,6 +106,7 @@ def bidding_command(token_economics, surrogate_bidder):
'--participant-address', surrogate_bidder.checksum_address,
'--value', bid_value,
'--provider', MOCK_PROVIDER_URI,
'--signer', MOCK_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--force')
return command
@ -197,6 +201,7 @@ def test_valid_bid(click_runner,
'--participant-address', surrogate_bidder.checksum_address,
'--value', bid_value_in_eth,
'--provider', MOCK_PROVIDER_URI,
'--signer', MOCK_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--force')
@ -237,6 +242,7 @@ def test_cancel_bid(click_runner,
command = ('cancel-escrow',
'--participant-address', surrogate_bidder.checksum_address,
'--provider', MOCK_PROVIDER_URI,
'--signer', MOCK_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--force')
result = click_runner.invoke(worklock, command, input=INSECURE_DEVELOPMENT_PASSWORD, catch_exceptions=False)
@ -303,6 +309,7 @@ def test_enable_claiming(click_runner,
command = ('enable-claiming',
'--participant-address', surrogate_bidder.checksum_address,
'--provider', MOCK_PROVIDER_URI,
'--signer', MOCK_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN)
gas_limit_1 = 200000
@ -362,6 +369,7 @@ def test_initial_claim(click_runner,
command = ('claim',
'--participant-address', bidder_address,
'--provider', MOCK_PROVIDER_URI,
'--signer', MOCK_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN)
# First, let's test that if claiming is not available, command fails
@ -439,6 +447,7 @@ def test_already_claimed(click_runner,
command = ('claim',
'--participant-address', surrogate_bidder.checksum_address,
'--provider', MOCK_PROVIDER_URI,
'--signer', MOCK_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,
'--force')
@ -470,6 +479,7 @@ def test_remaining_work(click_runner,
command = ('remaining-work',
'--participant-address', surrogate_bidder.checksum_address,
'--provider', MOCK_PROVIDER_URI,
'--signer', MOCK_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN)
result = click_runner.invoke(worklock, command, catch_exceptions=False)
@ -496,6 +506,7 @@ def test_refund(click_runner,
command = ('refund',
'--participant-address', bidder_address,
'--provider', MOCK_PROVIDER_URI,
'--signer', MOCK_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN)
user_input = INSECURE_DEVELOPMENT_PASSWORD + '\n' + YES
@ -521,6 +532,7 @@ def test_participant_status(click_runner,
command = ('status',
'--participant-address', surrogate_bidder.checksum_address,
'--provider', MOCK_PROVIDER_URI,
'--signer', MOCK_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN)
result = click_runner.invoke(worklock, command, catch_exceptions=False)
@ -574,6 +586,7 @@ def test_interactive_new_bid(click_runner,
command = ('escrow',
'--participant-address', surrogate_bidder.checksum_address,
'--provider', MOCK_PROVIDER_URI,
'--signer', MOCK_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,)
user_input = "\n".join((INSECURE_DEVELOPMENT_PASSWORD, str(wrong_bid_in_eth), str(bid_value_in_eth), YES))
@ -624,6 +637,7 @@ def test_interactive_increase_bid(click_runner,
command = ('escrow',
'--participant-address', surrogate_bidder.checksum_address,
'--provider', MOCK_PROVIDER_URI,
'--signer', MOCK_PROVIDER_URI,
'--network', TEMPORARY_DOMAIN,)
user_input = "\n".join((INSECURE_DEVELOPMENT_PASSWORD, str(bid_value_in_eth), YES))

View File

@ -176,7 +176,8 @@ def make_alice(known_nodes: Optional[Set[Ursula]] = None):
alice_config.initialize(password=INSECURE_PASSWORD)
alice_config.keyring.unlock(password=INSECURE_PASSWORD)
alice = alice_config.produce(client_password=SIGNER_PASSWORD)
alice = alice_config.produce()
alice.signer.unlock_account(account=ALICE_ADDRESS, password=SIGNER_PASSWORD)
alice.start_learning_loop(now=True)
return alice

View File

@ -24,6 +24,7 @@ from hexbytes import HexBytes
from typing import List, Tuple, Union, Optional
from web3 import Web3
from nucypher.blockchain.eth.signers.software import Web3Signer
from nucypher.blockchain.economics import BaseEconomics, StandardTokenEconomics
from nucypher.blockchain.eth.actors import ContractAdministrator
from nucypher.blockchain.eth.deployers import StakingEscrowDeployer
@ -50,6 +51,9 @@ from constant_sorrow.constants import INIT
def token_airdrop(token_agent, amount: NU, origin: str, addresses: List[str]):
"""Airdrops tokens from creator address to all other addresses!"""
signer = Web3Signer(token_agent.blockchain.client)
signer.unlock_account(account=origin, password=INSECURE_DEVELOPMENT_PASSWORD)
def txs():
args = {'from': origin, 'gasPrice': token_agent.blockchain.client.gas_price}
for address in addresses:
@ -222,13 +226,11 @@ class TesterBlockchain(BlockchainDeployerInterface):
testerchain = cls()
if not BlockchainInterfaceFactory.is_interface_initialized(provider_uri=testerchain.provider_uri):
BlockchainInterfaceFactory.register_interface(interface=testerchain)
power = TransactingPower(password=INSECURE_DEVELOPMENT_PASSWORD, account=testerchain.etherbase_account)
power.activate()
testerchain.transacting_power = power
origin = testerchain.client.etherbase
admin = ContractAdministrator(deployer_address=origin,
registry=registry,
signer=Web3Signer(testerchain.client),
economics=economics or cls.DEFAULT_ECONOMICS)
gas_limit = None # TODO: Gas management - #842