Installation Guide, General documentation cleanup, grammar corrections, structure, expansion of existing documentation port

pull/682/head
Kieran Prasch 2019-01-22 21:58:41 -08:00 committed by Kieran Prasch
parent 0aacd4e703
commit 91de2f0329
No known key found for this signature in database
GPG Key ID: 199AB839D4125A62
9 changed files with 303 additions and 206 deletions

View File

@ -14,6 +14,7 @@ About
:maxdepth: 1
architecture/contracts
architecture/upgradeable_proxy_contracts
Guides

View File

@ -1,99 +1,111 @@
NuCypher Ethereum Contracts
===========================
# NuCypher Ethereum Contracts
* `NuCypherToken` contract is the ERC20 token contract with additional function - burn own tokens (only for owners)
* `MinersEscrow` contract holds Ursula's stake, stores information about Ursulas activity and assigns a reward for participating in NuCypher network. The `Issuer` contract is part of the `MinersEscrow` and uses only to split code
* `PolicyManager` contract holds policies fee and distributes fee by periods
* `Upgradeable` is base contract for upgrading (<nucypher.blockchain.eth/project/contracts/proxy/README.MD>)
* `Dispatcher` contract is used as proxy to other contracts. This provides upgrading of the `MinersEscrow` and `PolicyManager` contracts
* `UserEscrow` contract locks tokens for some time. Tokens will be unlocked after specified time and all tokens can be used as a stake in the `MinersEscrow` contract
Deployment
----------
## Contract Listing
* The first place is the contract `NuCypherToken` with all future supply tokens
* Next `MinersEscrow` should be deployed with its dispatcher
* Similarly `PolicyManager` is deployed with own dispatcher
* Transfer reward tokens to the `MinersEscrow` contract. This tokens is reward for mining. The remaining tokens are initial supply
* Run the `initialize()` method to initialize the `MinersEscrow` contract
* Set the address of the `PolicyManager` contract in the `MinersEscrow` by using the `setPolicyManager(address)`
* Pre-deposit tokens to the `MinersEscrow` if necessary:
* `NuCypherToken` ERC20 token contract with additional function - burn own tokens (only for owners)
* `MinersEscrow` Holds Ursula's stake, stores information about Ursulas activity and assigns a reward for participating in NuCypher network. The `Issuer` contract is part of the `MinersEscrow` and uses only to split code
* `PolicyManager` Holds policies fee and distributes fee by periods
* `Upgradeable` Base contract for upgrading (<nucypher.blockchain.eth/project/contracts/proxy/README.MD>)
* `Dispatcher` Proxy to other contracts. This provides upgrading of the `MinersEscrow` and `PolicyManager` contracts
* `UserEscrow` Locks tokens for predetermined time. Tokens will be unlocked after specified time and all tokens can be used as a stake in the `MinersEscrow` contract
## Deployment Procedure
1. Deployment `NuCypherToken` with all future supply tokens
2. Deploy `MinersEscrow` with a dispatcher targeting it
3. Deploy `PolicyManager` with it's own dispatcher, also targeting it
4. Transfer reward tokens to the `MinersEscrow` contract. These tokens are future mining rewards, and initial supply
5. Run the `initialize()` method to initialize the `MinersEscrow` contract
6. Set the address of the `PolicyManager` contract in the `MinersEscrow` by using the `setPolicyManager(address)`
7. Pre-deposit tokens to the `MinersEscrow` if necessary:
* Approve the transfer tokens for the `MinersEscrow` contract using the `approve(address, uint)` method. The parameters are the address of `MinersEscrow` and the amount of tokens for a miner or group of miner;
* Deposit tokens to the `MinersEscrow` contract using the `preDeposit(address[], uint[], uint[])` method. The parameters are the addresses of token miner, the amount of token for each miner and the periods during which tokens will be locked for each miner
* `UserEscrowLibraryLinker`, `UserEscrowProxy` TBD
* Pre-deposit tokens to the `UserEscrow` if necessary:
8. `UserEscrowLibraryLinker`, `UserEscrowProxy` TBD
9. Pre-deposit tokens to the `UserEscrow` if necessary:
* Create new instance of the `UserEscrow` contract
* Transfer ownership of the instance of the `UserEscrow` contract to the user
* Approve the transfer tokens for the `UserEscrow`
* Deposit tokens by the `initialDeposit(uint256, uint256)` method
Upgrade
-------
Smart contracts in Ethereum are not really changeable.
So fixing bugs and upgrading logic is to change the contract (address) and save the previous storage values.
The `Dispatcher` contract is used for this purpose - the fallback function in contract will execute on any request,
redirect request to the target address (delegatecall) and return result value (using some opcodes).
A target contract should be inherited from the `Upgradeable` contract in addition to the use of the `Dispatcher`.
The `Upgradeable` contract include 2 abstract methods that need to be implemented:
`verifyState(address)` method which checks that new version has correct storage;
`finishUpgrade(address)` method which should copy initialization data from library storage to the dispatcher storage;
## Alice's Contract Interaction
### Alice Authors a Blockchain Policy
Alice
-----
Alice uses the net of miners to deploy policies.
In order to take advantage of network Alice should choose miners and deploy policies with fees for that miners.
Alice can choose miners by herself or by `findCumSum(uint256, uint256, uint256)` method of the contract `MinersEscrow`.
The parameters are the start index (if the method is not called the first time), delta of the step and minimum number of periods during which tokens are locked.
Alice uses a network of Ursula miners to deploy policies.
In order to take advantage of the network, Alice chooses miners and deploys policies with fees for those miners.
Alice can choose miners by herself ("handpicked") or by using `findCumSum(uint256, uint256, uint256)` method of the contract `MinersEscrow` ("sampling").
`findCumSum` parameters are:
* The start index (if the method is not called the first time)
* The delta of the step
* minimum number of periods during which tokens are locked.
This method will return only active miners.
In order to place fee for policy Alice should call method `createPolicy(bytes20, uint256, uint256, address[])` of the contract `PolicyManager`
by specifying the miners addresses, the policy id (off-chain generation), duration in periods, first period reward.
In order to place the fee for a policy, Alice calls the method `PolicyManager.createPolicy(bytes20, uint256, uint256, address[])`;
By specifying a miner address, the policy ID (off-chain generation), the policy duration in periods, and the first period's reward.
Payment should be added in transaction in ETH and the amount is `firstReward * miners.length + rewardRate * periods * miners.length`.
Reward rate must be equal or more than minimum reward for each miner in the list. First period reward can not be refundable and it can be zero.
Reward rate must be equal to or more than minimum reward for each miner in the list. The first period's reward is not refundable, and can be zero.
In case Alice wants to cancel policy then she calls the `revokePolicy(bytes20)` or `revokeArrangement(bytes20, address)` methods of the contract `PolicyManager`.
While executing those methods Alice get all fee for future periods and for periods when the miners were inactive.
Also Alice can refund ETH for inactive miners periods without revoking policy by using methods `refund(bytes20)` or `refund(bytes20, address)` of the contract `PolicyManager`.
### Alice Revokes a Blockchain Policy
When Alice wants to revoke a policy, she calls the `PolicyManager.revokePolicy(bytes20)` or `PolicyManager.revokeArrangement(bytes20, address)`.
Execution of these methods results in Alice getting all fees for future periods, and also for periods when the miners were inactive.
Alice can refund ETH for any inactive miners periods without revoking the policy by using methods `PolicyManager.refund(bytes20)` or `PolicyManager.refund(bytes20, address)`.
Ursula
------
## Ursula's Contract Interaction
### Ursula Locks Tokens
In order to become a participant of the network, a miner stakes tokens in the `MinersEscrow` contract.
The miner allows the (mining) contract to perform a transaction using the `approve(address, uint256)` method in the token contract
(ERC20 contracts allow to delegrate access to another address).
After that, the miner transfers some quantity of tokens (method `deposit(uint256, uint256)`), locking them at the same time.
Another way to do it is using the `approveAndCall(address, uint256, bytes)` method in the token contract.
The parameters are the address of the `MinersEscrow` contract, the amount of staked tokens and the periods for locking which are serialized into an array of bytes.
The miner allows the (mining) contract to perform a transaction using the `MinersEscrow.approve(address, uint256)` method
(ERC20 contracts allow access delegation to another address).
When staking tokens, the miner sets the number of periods while tokens will be locked, but it should be no less than some minimal locking time (30 periods).
In order to unlock tokens, the miner should be active during the time of locking (confirm activity).
Each stake is the amount of tokens and the duration in periods.
The miner can add new stake by the `deposit(uint256, uint256)` or `lock(uint256, uint256)` methods.
Also the miner can split stake into two parts: one with the same duration and other with an extended duration.
For this purpose, the `divideStake(uint256, uint256, uint256, uint256)` method is used.
After that, the miner transfers some quantity of tokens (`MinersEscrow.deposit(uint256, uint256)`), locking them at the same time.
Alternately the `NucypherToken.approveAndCall(address, uint256, bytes)` method can be used.
The parameters are:
* The address of the `MinersEscrow` contract,
* The amount of staked tokens
* The periods for locking (which are serialized into an array of bytes).
When staking tokens, the miner sets the number of periods the tokens will be locked, but it must be no less than some minimal locking time (30 periods).
In order to unlock tokens, the miner must be active during the time of locking (and confirm activity each period).
Each stake is represented by the amount of tokens locked, and the stake's duration in periods.
The miner can add a new stake using `MinersEscrow.deposit(uint256, uint256)` or `MinersEscrow.lock(uint256, uint256)` methods.
The miner can split stake into two parts: one with the same duration and other with an extended duration.
For this purpose, the `MinersEscrow.divideStake(uint256, uint256, uint256, uint256)` method is used.
The first two parameters are used to identify the stake to divide and the others two for the extended part of the stake.
When calculating locked tokens (`getLockedTokens(address, uint256)` method), all stakes that are active during the specified period are summed up.
When calculating locked tokens (`MinersEscrow.getLockedTokens(address, uint256)` method), all stakes that are active during the specified period are summed.
In order to confirm activity every period, the miner should call `confirmActivity()` in the process of which activity for the next period is registered.
Also the method `confirmActivity` is called every time when methods `deposit(uint256, uint256)` or `lock(uint256, uint256)` are called.
### Ursula Confirms Activity
In order to confirm activity every period, miners call `MinersEscrow.confirmActivity()` wherein activities for the next period are registered.
The method `MinersEscrow.confirmActivity` is called every time the methods `MinersEscrow.deposit(uint256, uint256)` or `MinersEscrow.lock(uint256, uint256)` is called.
The miner gets a reward for every confirmed period.
After the period of activity has passed, the miner could call `mint()` method which computes and transfers tokens to the miner's account.
Also, the `lock(uint256, uint256)` and `confirmActivity()` methods include the `mint()` method.
The reward depends on the fraction of locked tokens for the period (only those who confirmed activity are accounted for)
### Ursula Generates Staking Rewards
After the period of activity has passed, the miner may call `MinersEscrow.mint()` method which computes and transfers tokens to the miner's account.
Also note, calls to `MinersEscrow.lock(uint256, uint256)` and `MinersEscrow.confirmActivity()` are included the `MinersEscrow.mint()` method.
The reward value depends on the fraction of locked tokens for the period (only those who confirmed activity are accounted for)
Also, the reward depends on the number of periods during which the tokens will be locked: if the tokens will be locked in half a year, the coefficient is 1.5.
Minimal coefficient is 1 (when tokens will get unlocked in the next period), and maximum is 2 (when the time is 1 year or more).
The reward is calculated separately for each stakes that are active during the mining period and all rewards are summed up.
The order of calling `mint` by miners (e.g. who calls first, second etc) doesn't matter.
All reward the miner can get by using the `witdraw(uint256)` method. Only non-locked tokens can be withdrawn.
### Ursula Generates Policy Rewards
Also the miner gets rewards for policies deployed.
Computation of the reward happens every time `mint()` is called by the `updateReward(address, uint256)` method.
In order to take the reward, the miner needs to call method `withdraw()` of the contract `PolicyManager`.
The miner can set a minimum reward rate for a policy. For that, the miner should call the `setMinRewardRate(uint256)` method.
### NuCypher Partner Ursula Staking
Some users will have locked but not staked tokens.
In that case, a instance of the `UserEscrow` contract will hold their tokens (method `initialDeposit(uint256, uint256)`).
In that case, an instance of the `UserEscrow` contract will hold their tokens (method `initialDeposit(uint256, uint256)`).
All tokens will be unlocked after specified time and the user can get them by method `withdraw(uint256)`.
When the user wants to become a miner - he uses the `UserEscrow` contract as a proxy for the `MinersEscrow` and `PolicyManager` contracts.

View File

@ -1,105 +1,69 @@
# Upgradeable Contracts
# Nucypher's Approaches to Upgradeable Contracts
Smart contracts in Ethereum are not really changeable. Even it can not be deleted - contract still exists in blockchain after `selfdestruct` (only storage cleared).
So fixing bugs and upgrading logic is to change contract (address) and save previous storage values.
Simple way for this is to create new contract, then copy storage there and destruct (mark as deleted) old contract.
But in this case client should change address for requested contract and also while migration will be active two versions of contract.
More convenient way is to use proxy contract with interface where each method redirect to the target contract.
It's good option because client uses one address most of the time but also have some minus - when we should add some methods then need to change proxy address too.
Another way is using fallback function in proxy contract - this function will execute on any request, redirect request to target and return result value (using some opcodes).
Almost like previous option, but this proxy doesn't have interface methods, only fallback function, so no need to change proxy address if we should change methods.
This way is not ideal and has some restrictions (here only major):
Smart contracts in Ethereum are not really changeable.
Even if it can be deleted - the contract still exists in blockchain after `selfdestruct`, and only the storage cleared.
In order to fix bugs and provide upgrade logic it is possible to change the contract (address) and save the original contract's storage values.
* Sending Ether from client's account to contract uses fallback function. Such transaction could consume only 2300 gas (http://solidity.readthedocs.io/en/develop/contracts.html#fallback-function)
* Proxy contract (Dispatcher) holds storage (not in the contract itself). While upgrading storage values should be the same or equivalent (see below)
## Sources
## Approach A
One simple way to achieve this is to create new contract, copy the original storage values to the new contract, then self-destruct (mark as deleted) the old contract.
When this happens, the client changes the address used for a requested contract.
*Note: (There will be two deployed versions of the contract during storage migration)*
## Approach B
Another way is using a fallback function in the proxy contract - this function will execute on any request, redirecting the request to the target and returning the resulting value (using opcodes).
This is similar to the previous option, but this proxy doesn't have interface methods, only a fallback function, so there is no need to change the proxy address if contract methods are changed.
This approach is not ideal, and has some restrictions:
* Sending Ether from client's account to contract uses the fallback function - Such transaction can only consume 2300 gas (http://solidity.readthedocs.io/en/develop/contracts.html#fallback-function)
* Proxy contracts (Dispatcher) hold storage (not in the contract itself). While upgrading storage, values must be the same or equivalent (see below).
## Approach C
A more convenient way is to use a proxy contract with an interface where each method redirects to the *target* contract.
This option is advantageous because the client uses one address most of the time but also has it's own methods.
*Note: If updates to the proxy contract's methods are made, then the client will need to change proxy address also.*
More examples:
* https://github.com/maraoz/solidity-proxy - good realization of using libraries (not contracts) but too complex and some ideas is obsolete after Byzantium hard fork
* https://github.com/willjgriff/solidity-playground - most of the upgradeable code taken from this repository
* https://github.com/0v1se/contracts-upgradeable - almost the same but also have code for verifying upgrade
## Interaction scheme
![Interaction scheme](../.static/img/Dispatcher.png)
* Dispatcher - proxy contract that redirects requests to the target address.
Also it clearly holds own values (owner and target address) and stores the values of the target contract but not explicitly.
Client should use result contract or interface ABI while sending request to the Dispatcher address.
Owner can change target address by using Dispatcher ABI.
Dispatcher contract uses `delegatecall` for redirecting requests, so msg.sender remains client address and uses storage from dispatcher when executing method in target contract.
If target address is not set or target contract is not exists result may be unpredictable, because `delegatecall` will return true.
It also holds it's own values (owner and target address) and stores the values of the target contract, but not explicitly.
The client should use the resulting contract or interface ABI while sending request to the `Dispatcher` address.
The contract's owner can change the target address by using the `Dispatcher`'s ABI.
The `Dispatcher` contract uses `delegatecall` for redirecting requests, so `msg.sender` remains as the client address
and uses the dispatcher's storage when executing methods in the target contract.
*WARNING: If target address is not set, or the target contract does not exist, results may be unpredictable because `delegatecall` will return `true`.*
* Contract - upgradeable contract, each version must have the same ordering of storage values.
New versions of the contract can expand values, but must contain all the old values (containing values from dispatcher **first**).
This contract is like a library because it's storage is not used.
If a client sends a request to the contract directly to it's deployed address without using the dispatcher,
then the request may execute (without exception) using the wrong target address.
* Contract - upgradeable contract, each version should have same order of storage values.
New versions of contract can expand values, but must contain all old values (first of all should contain values from dispatcher).
This contract is like library because it's storage is not used.
If client send request to the contract without using dispatcher then request could be executed without exception
but using wrong target address (should be dispatcher address) and wrong storage (should be dispatcher storage).
## Development
* Use Upgradeable as base contract for all contracts that will be used with Dispatcher
* Implement `verifyState(address)` method which checks that new version has correct storage
* Implement `finishUpgrade(address)` method which should copy initialization data from library storage to the dispatcher storage
* Use `Upgradeable` as base contract for all contracts that will be used with `Dispatcher`
* Implement `verifyState(address)` method which checks that a new version has correct storage values
* Implement `finishUpgrade(address)` method which copies initialization data from library storage to the dispatcher's storage
* Each upgrade should include tests which check storage equivalence
## Desired Properties
## Sources
* Nodes decide which update should occur;
* Nodes can rollback contract if new version has bugs.
### Approaches
* "Hard-fork"
![Hard-fork](../.static/img/Hard-fork.png)
Each version is a new contract with separate address and storage.
Nodes should change contract address that they use.
- Advantages:
- Code is simpler, no special requirements;
- Each node can choose which contract to use.
- Disadvantages:
- There are two versions of contract while updating, so contracts should work together.
Also we can add another contract (Government) for voting and migration between versions.
* [Dispatcher](README.MD) (proxy)
![Dispatcher](../.static/img/Dispatcher2.png)
Using proxy contract that holds storage and library address.
Updating is changing only one library address in proxy contract.
- Advantages:
- Instant update without changing address for nodes.
- Disadvantages:
- Certain rules for updating the contract storage,
better to write additional methods for testing contract storage;
- A voting contract (Government) is required for a legitimate upgrade.
### Implementation
* "Hard-fork"
* Soft updating with two contracts
![Hard-fork-impl1](../.static/img/Hard-fork2.png)
Updating contracts should contain methods for transfer data (amount of locked tokens, balance etc.).
For example, change manager address from old to new in Wallet contract.
Also both version should interact for correct mining
(all locked blocks will be sum from old and new versions in the current period).
For rollback will be enough to move data from the new version back to the previous.
In some moment, new version have to disable previous contract and move remaining data to the new version.
* Full update from one contract to another
![Hard-fork-impl2](../.static/img/Hard-fork3.png)
All nodes vote for updating using additional contract.
After the end of voting old contract should be blocked and new version is activated (or created).
And then data will be copied from old version to new, for example, by new contract.
Rollback is almost the same: new version is paused,
data is moved back to the old version and old version is activated.
So main task is the addition of methods for obtaining data for old and new versions.
* Dispatcher
![Dispatcher-impl](../.static/img/Dispatcher3.png)
After voting Government contract changes library address in proxy.
Rollback is changing address back from the new library to the old.
Main goal is create right voting and check storage while setting new address.
More examples:
* https://github.com/maraoz/solidity-proxy - Realization of using libraries (not contracts) but too complex and some ideas is obsolete after Byzantium hard fork
* https://github.com/willjgriff/solidity-playground - Most of the upgradeable proxy contract code taken from this repository
* https://github.com/0v1se/contracts-upgradeable - Source code for verifying upgrade

View File

@ -2,30 +2,28 @@
## Overview
This is an illustration of NuCypher Decentralized Key Management System (KMS) allowing Alice to share a
This demo is an example of a NuCypher decentralized network allowing Alice to share a
data with Bob using proxy re-encryption paradigm. This enables the private sharing of data between
participants in public consensus networks, without revealing data keys to intermediary entities.
1. Alice sets a Policy on the NuCypher network (2/3) and grants access to Bob
2. Label and Alice's key public key provided to Bob
4. Bob joins the policy by Label and Alice's public key
5. DataSource created for the policy
6. Each plaintext message gets encapsulated through the DataSource to messageKit
5. Bob receives and reconstructs the DataSource from Policy public key and DataSource public key
6. Bob retrieves the original message form DataSource and MessageKit
|Step | Character | Operation |
|-----|-----------|-------------------------------------------------------------------------------------------------|
| 1 | Alice | Alice sets a Policy on the NuCypher network (2/3) and grants access to Bob |
| 2 | Alice | Label and Alice's key public key provided to Bob |
| 4 | Bob | Bob joins the policy with Label and Alice's public key |
| 5 | Enrico | DataSource created for the policy |
| 6 | Enrico | Each plaintext message gets encapsulated through the DataSource to messageKit |
| 5 | Bob | Bob receives and reconstructs the DataSource from Policy public key and DataSource public key |
| 6 | Bob | Bob retrieves the original message form DataSource and MessageKit |
## Install Nucypher
```
git clone https://github.com/nucypher/nucypher.git # clone NuCypher repository
cd nucypher
git checkout federated # We need a federated branch which isn't using blockchain
pipenv install --dev --three --skip-lock --pre
pipenv shell
```
## Download the Book Text
## 1. Install Nucypher
Acquire the nucypher application code and install the dependencies;
For a full installation guide see the [NuCypher Installation Guide](../guides/installation_guide)
## 2. Download the Book Text
`./download_finnegans_wake.sh`
## Run the Demo
## 3. Run the Demo
`python3 finnegans-wake-concise-demo.py`

View File

@ -1,15 +1,24 @@
# NuCypher's Heartbeat Demo
# Heartbeat Demo
![Heartbeat Demo](https://user-images.githubusercontent.com/2564234/49080419-dda35680-f243-11e8-90d7-6f649d80e03d.png)
## Overview
Alicia has a Heart Monitor device that measures her heart rate and outputs this data in encrypted form. Since she thinks that she may want to share this data in the future, she uses NuCypher to create a _policy public key_ for the Heart Monitor to use, so she can read and delegate access to the encrypted data as she sees fit. The Heart Monitor uses this public key to produce a file with some amount of encrypted heart rate measurements; this file is uploaded to some storage service (e.g., IPFS, S3, whatever).
Alicia has a Heart Monitor device that measures her heart rate and outputs this data in encrypted form.
Since Alicia knows that she may want to share this data in the future, she uses NuCypher to create
a _policy public key_ for her Heart Monitor to use, so she can read and delegate access to the encrypted
data as she sees fit.
At some moment, she wants to share this information with other people, such as her Doctor. Once she obtains her Doctor's public keys, she can create a policy in the NuCypher network granting access to him. After this, her Doctor can read the file with encrypted data (which was uploaded by the Heart Monitor) and request a re-encrypted ciphertext for each measurement, which can be opened with the Doctor's private key.
The Heart Monitor uses this public key to produce a file with some amount of encrypted heart rate measurements;
This file is uploaded to a storage layer (e.g., IPFS, S3, whatever).
This simple use case showcases many interesting and distinctive aspects of NuCypher:
At some moment, she wants to share this information with other people, such as her Doctor.
Once she obtains her Doctor's public keys, she can create a policy in the NuCypher network granting access to him.
After this, her Doctor can read the file with encrypted data (which was uploaded by the Heart Monitor) and
request a re-encrypted ciphertext for each measurement, which can be opened with the Doctor's private key.
This simple example showcases many interesting and distinctive aspects of NuCypher:
- Alicia can create policy public keys **before knowing** who can be the potential consumers.
- Alicia, or anyone knowing the policy public key (e.g., the Heart Monitor), can produce encrypted data that belongs to the policy. Again, this can happen before granting access to any consumer.
- As a consequence of the previous point, Data Sources, like the Heart Monitor, are completely unaware of the recipients. In their mind, they are producing data **for Alicia**.
@ -17,21 +26,29 @@ This simple use case showcases many interesting and distinctive aspects of NuCyp
- Alicia only interacts with the NuCypher network for granting access to the Doctor. After this, she can even disappear from the face of the Earth.
- The Doctor never interacts with Alicia or the Heart Monitor: he only needs the encrypted data and some policy metadata.
## Install Nucypher
Acquire the nucypher application code and install the dependencies;
For a full installation guide see the [NuCypher Installation Guide](../guides/installation_guide)
## Run the Demo
Assuming you already have `nucypher` installed (specifically, the `federated` branch), running the demo only involves running the `alicia.py` and `doctor.py` scripts. You should run `alicia.py` first:
Assuming you already have `nucypher` installed with the `demos` extra, running the Heartbeat demo only involves running the `alicia.py` and `doctor.py` scripts; Run `alicia.py` first:
```sh
(nucypher)$ python alicia.py <seednode_url>
```
This will create a temporal directory called `alicia-files` that contains the data for making Alicia persistent (i.e., her private keys). Apart from that, it will also generate data and keys for the demo. What's left is running the `doctor.py` script:
```sh
(nucypher)$ python doctor.py <seednode_url>
```
This script will read the data generated in the previous step and retrieve re-encrypted ciphertexts by means of the NuCypher network. The result is printed in the console:
```
```bash
Creating the Doctor ...
Doctor = ⇀Maroon Snowman DarkSlateGray Bishop↽ (0xA36bcd5c5Cfa0C1119ea5E53621720a0C1a610F5)
The Doctor joins policy for label 'heart-data-❤️-e917d959'

View File

@ -1,9 +1,57 @@
# Local Development Fleet Testing
## Run a Lonely Ursula
## Overview
## Run a Fleet of Ursulas
*Note: Currently only "Federated Only" mode is supported for local fleets*
## Run an Entry-Point Ursula
All Demo Ursulas:
* Run on `localhost`
* In `--federated-only` mode
* On the `TEMPORARY_DOMIAN` (Implied by `--dev`)
* Using temporary resources (files, database, etc.)
## Running A Local Fleet
### 1. Install Nucypher
Acquire the nucypher application code and install the dependencies;
For a full installation guide see the [NuCypher Installation Guide](../guides/installation_guide)
### 2. Run a Lonely Ursula
The first step is to launch to first Ursula on the network by running:
`$ python run_lonely_demo_ursula.py`
This will start an Ursula node:
* With seednode discovery disabled
* On port `11500`
### 3. Run a Local Fleet of Ursulas
Next, launch subsequent Ursulas, informing them of the first Ursula:
`$ python run_demo_ursula_fleet.py`
This will run 5 temporary Ursulas:
* All specify the lonely Ursula as a seednode
* Run on ports `11501` through `11506`
### 4. Run an Entry-Point Ursula (Optional)
While the local fleet is running, you may want an entry-point to introspect the code in a debugger.
For this we provide the optional script `run_single_demo_ursula.py` for your convenience.
`$ python run_single_demo_ursula.py`
This will run a single temporary Ursulas:
* Specifies a random fleet node as a teacher
* On a random available port
## Connecting the the Local Fleet
Alternately, you can connect any node run from the CLI by specifying one of the nodes
in the local fleet as a teacher, the same network domain, and the same operating mode:
`nucypher ursula run --dev --teacher-uri localhost:11501`

View File

@ -23,7 +23,7 @@ If you encounter issues, wed love to hear your feedback in our #staking chann
### Stage A | Install The Nucypher Environment
1) Install Python and Git
1. Install Python and Git
If you dont already have them, install Python and git.
As of November 2018, we are working with Python 3.6, 3.7, and 3.8.
@ -31,7 +31,7 @@ As of November 2018, we are working with Python 3.6, 3.7, and 3.8.
Official Python Website: https://www.python.org/downloads/
Git Install Guide: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
2) Create Virtual Environment
2. Create Virtual Environment
Create a system directory for the nucypher application code

View File

@ -1,41 +1,76 @@
# Installation Guide
## Pip Installation
`pip install nucypher`
## Standard Installation
## Pipenv Installation
We recommend installing nucypher with either `pip` or `pipenv`
### Standard Pip Installation
#### Create a Virtual Environment
```bash
$ virtualenv /your/path/nucypher-venv
...
```
Activate the newly created vrtual environment:
```bash
$ source /your/path/nucypher-venv
...
$(nucypher-venv)
```
#### Install Application Code with Pip
```bash
$(nucypher-venv) pip install nucypher
```
### Standard Pipenv Installation
See full documentation for pipenv here: [Pipenv Documentation](https://pipenv.readthedocs.io/en/latest/)
```bash
$ pipenv install nucypher
```
`pipenv install nucypher`
## Development Installation
### Acquire NuCypher Codebase
```
git clone https://github.com/nucypher/nucypher.git # clone NuCypher repository
cd nucypher
```bash
$ git clone https://github.com/nucypher/nucypher.git
...
$ cd nucypher
```
### Pipenv
After acquiring a local copy of the application code, you will need to
install the project dependencies, we recommend using either `pip` or `pipenv`
```
pipenv install --dev --three --skip-lock --pre
pipenv shell
### Pipenv Development Installation Method
```bash
$ pipenv install --dev --three --skip-lock --pre
...
$ pipenv shell
$(nucypher) pipenv run install-solc
...
```
### Pip
### Pip Development Installation Method
```
pip install -e .[testing]
```bash
$ pip install -e .[testing]
$ ./scripts/install_solc.sh
```
## System Service Installation
1. Use this template to create a file named ursula.service and place it in */etc/systemd/system/*.
`/etc/systemd/system/ursula.service`
```
[Unit]
Description="Run 'Ursula', a NuCypher Staking Node."
@ -44,15 +79,22 @@ Description="Run 'Ursula', a NuCypher Staking Node."
User=<YOUR USER>
Type=simple
Environment="NUCYPHER_KEYRING_PASSPHRASE=<YOUR PASSPHRASE>"
ExecStart=<VIRTUALENV PATH>/bin/nucypher ursula run --teacher-uri https://paris-load-balancer-14b0a87b7ff37a14.elb.eu-west-3.amazonaws.com
ExecStart=<VIRTUALENV PATH>/bin/nucypher ursula run --teacher-uri <SEEDNODE_URI>
[Install]
WantedBy=multi-user.target
```
Replace the following values with your own:
* `<YOUR_USER>` - The host system's username to run the process with
* `<YOUR_PASSWORD>` - Ursula's keyring password
* `<VIRTUALENV_PATH>` - The absolute path to the python virtual environment containing the `nucypher` executable
* `<SEEDNODE_URI>` - A seednode URI of a node on the network you are connecting to
2. Enable Ursula System Service
```
```bash
$ sudo systemctl enable ursula
...
```
@ -61,20 +103,20 @@ $ sudo systemctl enable ursula
To start Ursula services using systemd
```
```bash
$ sudo systemctl start ursula
...
```
4. Check Ursula service status
```
```bash
$ sudo systemctl status ursula
...
```
5. To restart your node service
`$ sudo systemctl restart ursula`
Updating Nucypher Application Code
```bash
$ sudo systemctl restart ursula
```

View File

@ -2,13 +2,28 @@
## Install NuCypher
`$ pip install nucypher`
```bash
$ pip install nucypher
```
## Run a Federated-Only Development Ursula
`$ nucypher ursula run --dev --federated-only`
```bash
$ nucypher ursula run --dev --federated-only
```
## Run a Geth-Connected Development Ursula
`$ geth --dev`
`$ nucypher ursula run --dev --provider-uri /tmp/geth.ipc`
Run a local geth node in development mode:
```bash
$ geth --dev
```
Run a local development Ursula connected to the geth node
```bash
$ nucypher ursula run --dev --provider-uri /tmp/geth.ipc --checksum-address <GETH_ADDRESS>
```
Replace `<GETH_ADDRESS>` with the geth node's public checksum address.