nucypher/examples/pre/finnegans_wake_demo/finnegans-wake-demo-l2.py

180 lines
5.7 KiB
Python
Raw Normal View History

2022-01-11 21:54:58 +00:00
import datetime
import os
2022-03-02 21:23:35 +00:00
from getpass import getpass
2022-01-11 21:54:58 +00:00
from pathlib import Path
2022-03-02 21:23:35 +00:00
import maya
2022-01-11 21:54:58 +00:00
from nucypher.blockchain.eth.signers.base import Signer
2022-03-02 21:23:35 +00:00
from nucypher.characters.lawful import Alice, Bob
2022-01-11 21:54:58 +00:00
from nucypher.characters.lawful import Enrico as Enrico
from nucypher.crypto.powers import DecryptingPower, SigningPower
from nucypher.policy.payment import SubscriptionManagerPayment
2022-01-11 21:54:58 +00:00
from nucypher.utilities.ethereum import connect_web3_provider
from nucypher.utilities.logging import GlobalLoggerSettings
######################
# Boring setup stuff #
######################
LOG_LEVEL = "info"
GlobalLoggerSettings.set_log_level(log_level_name=LOG_LEVEL)
2022-01-11 21:54:58 +00:00
GlobalLoggerSettings.start_console_logging()
BOOK_PATH = Path("finnegans-wake-excerpt.txt")
2022-01-11 21:54:58 +00:00
try:
# Replace with ethereum RPC endpoint
L1_PROVIDER = os.environ["DEMO_L1_PROVIDER_URI"]
L2_PROVIDER = os.environ["DEMO_L2_PROVIDER_URI"]
2022-01-11 21:54:58 +00:00
# Replace with wallet filepath.
WALLET_FILEPATH = os.environ["DEMO_L2_WALLET_FILEPATH"]
SIGNER_URI = f"keystore://{WALLET_FILEPATH}"
2022-01-11 21:54:58 +00:00
# Replace with alice's ethereum address
ALICE_ADDRESS = os.environ["DEMO_ALICE_ADDRESS"]
2022-01-11 21:54:58 +00:00
except KeyError:
raise RuntimeError("Missing environment variables to run demo.")
2022-01-11 21:54:58 +00:00
print("\n************** Setup **************\n")
2022-01-11 21:54:58 +00:00
###########
# Network #
###########
2022-01-11 21:54:58 +00:00
TACO_NETWORK = "lynx"
2022-01-11 21:54:58 +00:00
#####################
# Bob the BUIDLer ##
#####################
# Then, there was bob. Bob learns about the
# rest of the network from the seednode.
bob = Bob(
domain=TACO_NETWORK,
eth_endpoint=L1_PROVIDER,
)
2022-01-11 21:54:58 +00:00
# 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(eth_provider_uri=L1_PROVIDER)
2022-04-04 22:00:15 +00:00
# Connect to the layer 2 provider.
connect_web3_provider(eth_provider_uri=L2_PROVIDER)
2022-01-11 21:54:58 +00:00
# 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]}): "
)
2022-01-11 21:54:58 +00:00
wallet.unlock_account(account=ALICE_ADDRESS, password=password)
# This is Alice's PRE payment method.
pre_payment_method = SubscriptionManagerPayment(
network=TACO_NETWORK, blockchain_endpoint=L2_PROVIDER
)
2022-01-11 21:54:58 +00:00
# This is Alice.
alice = Alice(
checksum_address=ALICE_ADDRESS,
signer=wallet,
domain=TACO_NETWORK,
eth_endpoint=L1_PROVIDER,
polygon_endpoint=L2_PROVIDER,
pre_payment_method=pre_payment_method,
2022-01-11 21:54:58 +00:00
)
# Alice puts her public key somewhere for Bob to find later...
2022-03-02 21:23:35 +00:00
alice_verifying_key = alice.stamp.as_umbral_pubkey()
2022-01-11 21:54:58 +00:00
print("\n************** Grant **************\n")
2022-01-11 21:54:58 +00:00
# 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.
2022-03-02 21:23:35 +00:00
remote_bob = Bob.from_public_keys(
encrypting_key=encrypting_key,
verifying_key=verifying_key,
eth_provider_uri=L1_PROVIDER,
2022-03-02 21:23:35 +00:00
)
2022-01-11 21:54:58 +00:00
# These are the policy details.
2022-01-11 21:54:58 +00:00
expiration = maya.now() + datetime.timedelta(days=1)
2022-03-24 20:17:34 +00:00
threshold, shares = 2, 3
price = alice.pre_payment_method.quote(expiration=expiration.epoch, shares=shares).value
2022-01-11 21:54:58 +00:00
# Alice grants access to Bob...
policy = alice.grant(
remote_bob,
label,
threshold=threshold,
shares=shares,
value=price,
expiration=expiration,
)
2022-01-11 21:54:58 +00:00
# ...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:
2022-01-11 21:54:58 +00:00
finnegans_wake = file.readlines()
print("\n************** Encrypt and Retrieve **************\n")
2022-01-11 21:54:58 +00:00
for counter, plaintext in enumerate(finnegans_wake):
# Enrico knows the policy's public key from a side-channel.
# In this demo a new enrico is being constructed for each line of text.
# This demonstrates how many individual encryptors may encrypt for a single policy.
# In other words -- Many data sources (Enricos) can encrypt for the policy's public key.
enrico = Enrico(encrypting_key=policy_public_key)
2022-01-11 21:54:58 +00:00
# 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.
message_kit = enrico.encrypt_for_pre(plaintext)
2022-01-11 21:54:58 +00:00
del enrico
###############
# Back to Bob #
###############
# Now Bob can retrieve the original message by requesting re-encryption from nodes.
cleartexts = bob.retrieve_and_decrypt(
[message_kit],
alice_verifying_key=alice_verifying_key,
encrypted_treasure_map=policy.treasure_map,
)
2022-01-11 21:54:58 +00:00
# We show that indeed this is the passage originally encrypted by Enrico.
assert plaintext == cleartexts[0]
2022-03-02 21:23:35 +00:00
print(cleartexts)
2022-01-11 21:54:58 +00:00
bob.disenchant()