Skip to content
This repository was archived by the owner on Jun 21, 2020. It is now read-only.

KM docs #288

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions enigma-principal/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
# Enigma Key Management Node

The Key Management node is part of the Enigma node software stack. The Key Management component is responsible for emitting random numbers from within an enclave into the Enigma contract. Currently, it uses a centralized design in order to maintain simplicity while testing and developing Core, but it will eventually move to a decentralized design matching the rest of the network.
The Key Management node is part of the Enigma node software stack.
The Key Management component is responsible for emitting random numbers from within
an enclave into the Enigma contract, which defines the seed for each epoch.
In addition, it handles the state keys, which encrypt the state of each secret contract
stored on each of the nodes and supplies the acquired keys to the chosen worker/node in
the epoch (according to the seed that defines the epoch and a worker selection algorithm)
for each of the secret contracts, on demand through the jsonRPC server.
Currently, it uses a centralized design in order to maintain simplicity while
testing and developing Core, but it will eventually move to a decentralized design
matching the rest of the network.

<img src="https://drone.enigma.co/api/badges/enigmampc/enigma-core/status.svg?branch=develop" />

Expand Down Expand Up @@ -32,7 +41,7 @@ The encryption method relies on a DH key exchange between the Principal node and

```sh
// Request
curl -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "id":1, "method":"get_state_keys", "params": {"data": "84a46461746181a75265717565737493dc0020cca7cc937b64ccb8cccacca5cc8f03721bccb6ccbacccf5c78cccb235fccebcce0cce70b1bcc84cccdcc99541461cca0cc8edc002016367accacccb67a4a017ccc8dcca8ccabcc95682ccccb390863780f7114ccddcca0cca0cce0ccc55644ccc7ccc4dc0020ccb1cce9cc9324505bccd32dcca0cce1ccf85dcccf5e19cca0cc9dccb0481ecc8a15ccf62c41cceb320304cca8cce927a269649c1363ccb3301c101f33cce1cc9a0524a67072656669789e456e69676d61204d657373616765a67075626b6579dc0040cce5ccbe28cc9dcc9a2eccbd08ccc0457a5f16ccdfcc9fccdc256c5d5f6c3514cccdcc95ccb47c11ccc4cccd3e31ccf0cce4ccefccc83ccc80cce8121c3939ccbb2561cc80ccec48ccbecca8ccc569ccd2cca3ccda6bcce415ccfa20cc9bcc98ccda", "workerSig": "43f19586b0a0ae626b9418fe8355888013be1c9b4263a4b3a27953de641991e936ed6c4076a2a383b3b001936bf0eb6e23c78fbec1ee36f19c6a9d24d75e9e081c"}}'
curl -X POST --data '{"jsonrpc": "2.0", "id": "1", "method": "getStateKeys", "params": ["84a46461746181a75265717565737493dc0020cca7cc937b64ccb8cccacca5cc8f03721bccb6ccbacccf5c78cccb235fccebcce0cce70b1bcc84cccdcc99541461cca0cc8edc002016367accacccb67a4a017ccc8dcca8ccabcc95682ccccb390863780f7114ccddcca0cca0cce0ccc55644ccc7ccc4dc0020ccb1cce9cc9324505bccd32dcca0cce1ccf85dcccf5e19cca0cc9dccb0481ecc8a15ccf62c41cceb320304cca8cce927a269649c1363ccb3301c101f33cce1cc9a0524a67072656669789e456e69676d61204d657373616765a67075626b6579dc0040cce5ccbe28cc9dcc9a2eccbd08ccc0457a5f16ccdfcc9fccdc256c5d5f6c3514cccdcc95ccb47c11ccc4cccd3e31ccf0cce4ccefccc83ccc80cce8121c3939ccbb2561cc80ccec48ccbecca8ccc569ccd2cca3ccda6bcce415ccfa20cc9bcc98ccda", "43f19586b0a0ae626b9418fe8355888013be1c9b4263a4b3a27953de641991e936ed6c4076a2a383b3b001936bf0eb6e23c78fbec1ee36f19c6a9d24d75e9e081c"]}' -H "Content-Type: application/json" http://127.0.0.1:3040/

// Result
{
Expand All @@ -44,6 +53,22 @@ curl -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "id":1, "method"
}
}
```

## getHealthCheck

Requests a health check to be done on the Key management node. needed by the kubernetes cluster to check that all components are alive and
returning reasonable data.
the method, checks if the connection with the enclave and the enigma contract on ethereum are alive and return the same data.

**Returns**

bool: True, if the registration key is the same in both components.
False, if either we weren't able to connect to one of the components or if the keys were different.

An example for a request will look like this:
```sh
curl -sb -o /dev/null -X POST -d '{"jsonrpc": "2.0", "id": "1", "method": "getHealthCheck", "params": []}' -H "Content-Type: application/json" 127.0.0.1:3040
```

## To see all of the options available once compiled cd into /bin and type
```
Expand Down
41 changes: 41 additions & 0 deletions enigma-principal/app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
## App Structure

this folder consists of all the untrusted KM functionality.

it's divided into 5 folders:

##cli

consists of the scripts called by `main.rs` in the rebooting of the KM and the handling of the
cli options.


##boot_network

Consists of the functionality the boots up the KM.
The `principal_manager` which creates the 2 threads which handle the functionality of the KM, which consist of
the watching blocks thread that is located in `principal_utils.rs` file which counts the number of blocks until the end of the epoch and is in charge of
evaluating a new random seed which will define the new epoch and the second thread which handles the json rpc server
which is located in the `keys_provider_http.rs` file.
`deploy_scripts` consists of other functionality which is used to run tests while running idle.

## common_u

consists of the joint methods to all of the untrusted functionality. In our case it consists only of the custom errors.

## epoch_u

Consists of all scripts which are in charge of handling the epoch data.
There are 3 structs which are provided:
`epoch_state`- holds all data which is needed on the untrusted side that defines an epoch which was created in the enclave.
`epoch_state_manager`- holds a `cap` amount of epochs which can be called upon by workers (cap is defined when booting the network- in the configurations).
`epoch_provider`- holds all what's needed in order to create a new epoch (the eid of the enclave and an enigma-contract object which can communicate with the contract on ethereum) and the epoch_state manager.

## esgx

all the ecall functionality that calls the trusted side.
`epoch_keeper_u.rs` consists of setting the worker params which creates the new epoch - evaluates a new seed, and stores all active workers with it,
to have all necessary data for running the worker selection algorithm and confirm the keys are given to the right worker.
`equote` - similar to the enigma-core, all the functionality that registers a worker and evaluates a key pair for the encalve.
`key_keeper_u.rs` consists of the functionality on the untrusted side which provides the worker with the state keys of the contracts that he is in charge of in the current (or in inside the cap)
epoch.
4 changes: 3 additions & 1 deletion enigma-principal/app/src/boot_network/principal_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ impl Sampler for PrincipalManager {
#[logfn(INFO)]
fn run<G: Into<U256>>(&self, path: PathBuf, reset_epoch: bool, gas_limit: G) -> Result<(), Error> {
let gas_limit: U256 = gas_limit.into();
// make sure the KM was registered
self.verify_identity_or_register(gas_limit)?;
// get enigma contract
// Start the WorkerParameterized Web3 log filter
Expand All @@ -322,11 +323,12 @@ impl Sampler for PrincipalManager {
let port = self.config.http_port;
let server_ep = Arc::clone(&epoch_provider);
thread::spawn(move || {
// brings up the JSON rpc server in a separate thread
let server = PrincipalHttpServer::new(server_ep, port);
server.start();
});

// watch blocks
// watch blocks in order to decide when to create a new epoch.
let polling_interval = self.config.polling_interval;
let epoch_size = self.config.epoch_size;
self.contract.watch_blocks(
Expand Down
3 changes: 3 additions & 0 deletions enigma-principal/app/src/cli/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub fn create_signer(eid: sgx_enclave_id_t, with_private_key: bool, private_key:
}
}

/// the starting point of the KM. called by main and is in charge of all functionality called by the cli app.
#[logfn(INFO)]
pub fn start(eid: sgx_enclave_id_t) -> Result<(), Error> {
let opt = cli::options::Opt::from_args();
Expand All @@ -49,6 +50,7 @@ pub fn start(eid: sgx_enclave_id_t) -> Result<(), Error> {
if opt.info {
cli::options::print_info(&signing_address, &ethereum_address);
} else if opt.sign_address {
// store the KM addresses and close the KM. needed for the integration tests.
path.push("principal-sign-addr.txt");
let mut file = File::create(&path)?;
let prefixed_signing_address = format!("0x{}", signing_address);
Expand Down Expand Up @@ -117,6 +119,7 @@ pub fn start(eid: sgx_enclave_id_t) -> Result<(), Error> {
let response = PrincipalHttpServer::get_state_keys(&epoch_provider, request)?;
println!("The getStateKeys response: {}", serde_json::to_string(&response)?);
} else {
// the actual functionality of the KM node
principal.run(path, false, gas_limit).unwrap();
}
if let Some(t) = join_handle {
Expand Down
2 changes: 2 additions & 0 deletions enigma-principal/enclave/src/epoch_keeper_t/epoch_t.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ impl Epoch {
.ok_or_else(|| SystemError(EnclaveSystemError::WorkerAuthError { err: "Worker selection returns nothing.".to_string() }))
}

/// creates the encoding agreed upon and which is aligned on both ends in order to encrypt/decrypt
/// the data while making sure it cannot be compromised in the process.
pub fn encode_for_hashing(&self) -> Bytes {
let mut encoding: Vec<u8> = Vec::new();

Expand Down
4 changes: 3 additions & 1 deletion enigma-principal/enclave/src/epoch_keeper_t/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ fn store_epoch(epoch: Epoch) -> Result<(), EnclaveError> {
let mut data = H256::from_uint(&nonce).0.to_vec();
data.extend(hash.to_vec());
let mut marker_doc: SealedDocumentStorage<EpochMarker> = SealedDocumentStorage {
version: 0x1234, // TODO: what's this?
version: 0x1234, // TODO: remove. not needed.
data: [0; 64],
};
// Length of the slice guaranteed to be 64
Expand Down Expand Up @@ -150,9 +150,11 @@ pub(crate) fn ecall_set_worker_params_internal(worker_params_rlp: &[u8], seed_in
};
*nonce_out = EpochNonce::from(nonce);
rsgx_read_rand(&mut rand_out[..])?;
// create a random seed
let seed = U256::from(rand_out.as_ref());
let epoch = Epoch { nonce, seed, worker_params };
debug_println!("Creating new epoch with nonce {:?} and seed: {:?}", nonce, seed);

store_epoch(epoch.clone())?;
epoch
}
Expand Down
1 change: 1 addition & 0 deletions enigma-principal/enclave/src/keys_keeper_t/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ fn new_state_keys(keys_map: &mut HashMap<ContractAddress, StateKey>,
Ok(results)
}

/// builds the key response in the way agreed upon in the ipc documents on the p2p repository
fn build_get_state_keys_response(sc_addrs: Vec<ContractAddress>) -> Result<Vec<(ContractAddress, StateKey)>, EnclaveError> {
let mut response_data: Vec<(ContractAddress, StateKey)> = Vec::new();
if sc_addrs.is_empty() {
Expand Down