diff --git a/examples/heartbeat_demo/alicia.py b/examples/heartbeat_demo/alicia.py
index 6d18dc433..cf8061d74 100644
--- a/examples/heartbeat_demo/alicia.py
+++ b/examples/heartbeat_demo/alicia.py
@@ -16,78 +16,84 @@
"""
import base64
import datetime
-import sys
import json
import os
import shutil
+from getpass import getpass
from pathlib import Path
import maya
-from nucypher.characters.lawful import Bob, Ursula
-from nucypher.config.characters import AliceConfiguration
-from nucypher.config.constants import TEMPORARY_DOMAIN
+from nucypher.blockchain.eth.signers import Signer
+from nucypher.characters.lawful import Bob, Alice
+from nucypher.policy.payment import SubscriptionManagerPayment
+from nucypher.utilities.ethereum import connect_web3_provider
from nucypher.utilities.logging import GlobalLoggerSettings
-
######################
# Boring setup stuff #
######################
-
-# Twisted Logger
-
+LOG_LEVEL = 'info'
+GlobalLoggerSettings.set_log_level(log_level_name=LOG_LEVEL)
GlobalLoggerSettings.start_console_logging()
TEMP_ALICE_DIR = Path('/', 'tmp', 'heartbeat-demo-alice')
-
-
-# if your ursulas are NOT running on your current host,
-# run like this: python alicia.py 172.28.1.3:11500
-# otherwise the default will be fine.
+POLICY_FILENAME = "policy-metadata.json"
+shutil.rmtree(TEMP_ALICE_DIR, ignore_errors=True)
try:
- SEEDNODE_URI = sys.argv[1]
-except IndexError:
- SEEDNODE_URI = "localhost:11500"
-POLICY_FILENAME = "policy-metadata.json"
+ # Replace with ethereum RPC endpoint
+ L1_PROVIDER = os.environ['DEMO_L1_PROVIDER_URI']
+ L2_PROVIDER = os.environ['DEMO_L2_PROVIDER_URI']
+
+ # Replace with wallet filepath.
+ WALLET_FILEPATH = os.environ['DEMO_L2_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.')
+
+L1_NETWORK = 'mainnet' # 'ibex'
+L2_NETWORK = 'polygon' # 'mumbai'
#######################################
# Alicia, the Authority of the Policy #
#######################################
+connect_web3_provider(eth_provider_uri=L1_PROVIDER) # Connect to the ethereum provider.
+connect_web3_provider(eth_provider_uri=L2_PROVIDER) # Connect to the layer 2 provider.
-# We get a persistent Alice.
-# If we had an existing Alicia in disk, let's get it from there
-passphrase = "TEST_ALICIA_INSECURE_DEVELOPMENT_PASSWORD"
-# If anything fails, let's create Alicia from scratch
-# Remove previous demo files and create new ones
+# 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's wallet ({ALICE_ADDRESS[:8]}): ")
+wallet.unlock_account(account=ALICE_ADDRESS, password=password)
-shutil.rmtree(TEMP_ALICE_DIR, ignore_errors=True)
-
-ursula = Ursula.from_seed_and_stake_info(seed_uri=SEEDNODE_URI,
- federated_only=True,
- minimum_stake=0)
-
-alice_config = AliceConfiguration(
- config_root=TEMP_ALICE_DIR,
- domain=TEMPORARY_DOMAIN,
- known_nodes={ursula},
- start_learning_now=False,
- federated_only=True,
- learn_on_same_thread=True,
+# This is Alice's payment method.
+payment_method = SubscriptionManagerPayment(
+ network=L2_NETWORK,
+ eth_provider=L2_PROVIDER
)
-alice_config.initialize(password=passphrase)
+# This is Alicia.
+alicia = Alice(
+ checksum_address=ALICE_ADDRESS,
+ signer=wallet,
+ domain=L1_NETWORK,
+ eth_provider_uri=L1_PROVIDER,
+ payment_method=payment_method
+)
-alice_config.keystore.unlock(password=passphrase)
-alicia = alice_config.produce()
-
-# We will save Alicia's config to a file for later use
-alice_config_file = alice_config.to_configuration_file()
+# Alice puts her public key somewhere for Bob to find later...
+alice_verifying_key = alicia.stamp.as_umbral_pubkey()
# Let's get to learn about the NuCypher network
alicia.start_learning_loop(now=True)
diff --git a/examples/heartbeat_demo/doctor.py b/examples/heartbeat_demo/doctor.py
index e7eb2cd3c..7b66066b8 100644
--- a/examples/heartbeat_demo/doctor.py
+++ b/examples/heartbeat_demo/doctor.py
@@ -14,46 +14,31 @@
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see .
"""
+
+
import base64
import json
-from pathlib import Path
+import shutil
from timeit import default_timer as timer
import maya
import msgpack
-import shutil
-import sys
-
from nucypher_core import MessageKit, EncryptedTreasureMap
from nucypher_core.umbral import PublicKey
-from nucypher.characters.lawful import Bob, Enrico, Ursula
-from nucypher.config.constants import TEMPORARY_DOMAIN
+from nucypher.characters.lawful import Bob
from nucypher.crypto.keypairs import DecryptingKeypair, SigningKeypair
from nucypher.crypto.powers import DecryptingPower, SigningPower
from nucypher.network.middleware import RestMiddleware
from nucypher.utilities.logging import GlobalLoggerSettings
-GlobalLoggerSettings.start_console_logging()
-
######################
# Boring setup stuff #
######################
-try:
- SEEDNODE_URI = sys.argv[1]
-except IndexError:
- SEEDNODE_URI = "localhost:11500"
+GlobalLoggerSettings.start_console_logging()
-
-TEMP_DOCTOR_DIR = Path(__file__).parent.absolute() / "doctor-files"
-
-# Remove previous demo files and create new ones
-shutil.rmtree(TEMP_DOCTOR_DIR, ignore_errors=True)
-
-ursula = Ursula.from_seed_and_stake_info(seed_uri=SEEDNODE_URI,
- federated_only=True,
- minimum_stake=0)
+L1_NETWORK = 'mainnet' # 'ibex'
# To create a Bob, we need the doctor's private keys previously generated.
from doctor_keys import get_doctor_privkeys
@@ -69,13 +54,8 @@ power_ups = [enc_power, sig_power]
print("Creating the Doctor ...")
doctor = Bob(
- domain=TEMPORARY_DOMAIN,
- federated_only=True,
+ domain=L1_NETWORK,
crypto_power_ups=power_ups,
- start_learning_now=True,
- abort_on_learning_error=True,
- known_nodes=[ursula],
- save_metadata=False,
network_middleware=RestMiddleware(),
)
diff --git a/examples/heartbeat_demo/heartbeat_demo.md b/examples/heartbeat_demo/heartbeat_demo.md
index bde87ca22..ec24081c5 100644
--- a/examples/heartbeat_demo/heartbeat_demo.md
+++ b/examples/heartbeat_demo/heartbeat_demo.md
@@ -26,15 +26,31 @@ This simple use case showcases many interesting and distinctive aspects of NuCyp
- The Doctor never interacts with Alicia or the Heart Monitor:
he only needs the encrypted data and some policy metadata.
-### How to run the demo
+### Decentralized Network Demo
+
Ensure that you already have `nucypher` installed.
-Run a fleet of federated Ursulas in a separate terminal:
+First, configure the demo by making exporting environment variables
+with your provider and wallet details for ethereum and polygon.
-```sh
-(nucypher)$ python ../run_demo_ursula_fleet.py
+```bash
+export DEMO_L1_PROVIDER_URI=
+export DEMO_L2_PROVIDER_URI=
+export DEMO_L2_WALLET_FILEPATH=
+export DEMO_ALICE_ADDRESS=
```
-This will create a local network of federated Ursulas that will be used by the demo for re-encryption of data.
+
+Alternatively you can use the provided .env.template file by making a copy named .env
+and adding your provider and wallet details. To set the variables in your current session run:
+`export $(cat .env | xargs)`
+
+Optionally, you can change the network the demo is running on by changing the value of `L1_NETWORK` and `L2_NETWORK`.
+If you change these values be sure to also change `L1_PROVIDER_URI` and `L2_PROVIDER_URI` accordingly.
+
+Available options for `L1_NETOWRK` are `ibex` or `mainnet`.
+Available options for `L2_NETWORK` are `mumbai` or `mainnet`
+
+Ensure Alice's account has a bit of MATIC on polygon to pay for the policy.
Subsequently, running the demo only involves running the `alicia.py` and `doctor.py` scripts.
You should run `alicia.py` first: