|
| 1 | +# ADR 001: Storage Consolidation |
| 2 | + |
| 3 | +## Changelog |
| 4 | +* 10-12-2019: Initial Draft |
| 5 | +* 11-12-2019: Extra comments |
| 6 | + |
| 7 | +## Context |
| 8 | +Currently (not counting Tendermint's internal storage or wallets), two processes maintain their internal storage: |
| 9 | + |
| 10 | +* chain-abci: stores the node state, Merkle trie of staking states, transaction metadata (whether spent or not), |
| 11 | +validator tracking, etc. |
| 12 | +* tx-validation enclave (TVE): sealed transaction data (of valid obfuscated transactions that have outputs) |
| 13 | + |
| 14 | +The reason for having two processes is that SGX SDK compilation is different and needs Intel SGX SDK tooling |
| 15 | +(and the subsequent process execution requires Intel SGX PSW tooling, such as AESM service), |
| 16 | +so for the development convenience, the transaction validation code that needs to execute in an enclave |
| 17 | +is isolated. (For example, one can build and run chain-abci on any platform (e.g. macOS), |
| 18 | +and run the enclave parts inside a docker container or on a remote Linux host.) |
| 19 | +The inter-process communication is over a simple REQ-REP 0MQ socket. |
| 20 | + |
| 21 | +*Problem 1: These two storage locations need to be "in sync"*: |
| 22 | + |
| 23 | +when an obfuscated transaction arrives that spends some transaction outputs, chain-abci will do a basic validation and check if they are unspent and forward it to TVE (assuming its storage contains |
| 24 | +sealed transaction data of respective outputs). There is currently a naive check that TVE |
| 25 | +stores the latest app hash provided by chain-abci; and upon a startup, chain-abci cross-checks if TVE is in sync with it. This leads to various errors and annoyances that are usually resolved by removing all storage and syncing from scratch (in certain cases, there may be a better mechanism, but wasn't implemented). |
| 26 | + |
| 27 | +*Problem 2: Transaction querying*: |
| 28 | + |
| 29 | +As wallet / client-* may be lightweight client and not have access to TEE directly, it will connect to one remotely. |
| 30 | +For this purpose, there is transaction query enclave (TQE). See [this document](https://github.com/crypto-com/chain-docs/blob/master/plan.md#transaction-query-enclave-tqe-optional--for-client-infrastructure) for more details. |
| 31 | + |
| 32 | +There are two flows (over an attested secure channel): |
| 33 | + |
| 34 | +1. retrieving transactions: client submits transaction identifiers signed by its view key, and TQE replies with matching transaction data. For this workflow, TQE contacts TVE over REQ-REP 0MQ socket to retrieve data. |
| 35 | + |
| 36 | +2. submitting new transactions: client submits a new transaction, TQE forwards it to TVE that checks it (so that it doesn't obfuscate random / invalid data) and if it's valid, it encrypts it with the obfuscation key (currently compile-time mock, but planned to be periodically regenerated |
| 37 | +by another type of enclave) and returns the obfuscated transaction to TQE that forwards it to the client. |
| 38 | + |
| 39 | +In the first flow, TQE only talks to the TVE's application wrapper that handles the persistence -- it can unseal |
| 40 | +the transaction data, because the key policy is MRSIGNER. |
| 41 | + |
| 42 | +In the second flow, TVE holds the obfuscation key inside the enclave memory, so the payload goes to TVE. |
| 43 | +Currently, TVE cannot check everything, e.g. staked state or if a transaction output was spent or not |
| 44 | +-- in the future, it may internally have app hash components and at least require some lightweight proofs |
| 45 | +for these things. |
| 46 | + |
| 47 | +For the first flow, it's unnecessary for TQE to talk to TVE. For the second flow, it'll be desirable |
| 48 | +to do a more complete verification (currently there are a few hacks and workarounds). |
| 49 | + |
| 50 | +## Decision |
| 51 | +This will be a bit big change, so it can be done in several steps: |
| 52 | + |
| 53 | +1. separate out the storage functionality from chain-abci into chain-storage crate |
| 54 | + |
| 55 | +2. TBD: separate storage process? moving enclave app wrappers to chain-abci? |
| 56 | + |
| 57 | +3. change enclave-protocol for chain-abci/storage to add sealed transaction data, and TVE to return Ok(sealed transaction data) back to chain-abci/storage |
| 58 | + |
| 59 | +4. give TQE some way to talk to chain-abci/storage (TBD: another 0MQ socket or abci_query?) |
| 60 | + |
| 61 | +5. change the first flow of TQE to use that instead of talking to TVE |
| 62 | + |
| 63 | +6. TBD: change the second flow to go through chain-abci (it'd still need to forward to TVE) |
| 64 | + |
| 65 | +7. remove storage from TVE (as it should be all handled by chain-abci/storage) |
| 66 | + |
| 67 | +## Status |
| 68 | + |
| 69 | +Proposed |
| 70 | + |
| 71 | +## Consequences |
| 72 | + |
| 73 | +### Positive |
| 74 | + |
| 75 | +* Only one place to store transaction data -- no need to keep storage of two processes in sync |
| 76 | +* Decoupling state machine logic (chain-abci) from the storage |
| 77 | +* As the second TQE flow may demand a full validation / more storage needs, it should be easier directly talking to abci. |
| 78 | + |
| 79 | +### Negative |
| 80 | +* Perhaps higher latency in some flows |
| 81 | +* If storage runs as a service (a la Libra architecture, see below, where it is a GRPC process), it'll be an extra complexity in deployment. |
| 82 | +* If enclave app wrappers are moved to chain-abci, development setup may be trickier on non-Linux platforms. |
| 83 | + |
| 84 | +### Neutral |
| 85 | +* One more crate |
| 86 | +* Coupling TQE process to chain-abci or storage process |
| 87 | +* Storage space shared between chain-abci and "sub-abci" enclave applications: probably an extra column in RocksDB-like storage |
| 88 | + |
| 89 | +## References |
| 90 | + |
| 91 | +* moving app wrapers to chain-abci: https://github.com/crypto-com/chain/pull/665#discussion_r356377869 |
| 92 | +* https://github.com/libra/libra/tree/master/storage/storage-service |
0 commit comments