fix(design): update state RFC to put ordered list values in RocksDB keys (#3997)

* Update RFC to use BTreeSets for ordered lists

* Update to put value sets in the rocksdb key

* Clarify some workding

* Update type name
This commit is contained in:
teor 2022-03-31 09:42:09 +10:00 committed by GitHub
parent ce51ad060f
commit 98ec995d56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 20 additions and 10 deletions

View File

@ -612,9 +612,9 @@ We use the following rocksdb column families:
| `tx_loc_by_hash` | `transaction::Hash` | `TransactionLocation` | Never |
| *Transparent* | | | |
| `balance_by_transparent_addr` | `transparent::Address` | `Amount \|\| AddressLocation` | Update |
| `tx_by_transparent_addr_loc` | `AddressLocation` | `AtLeastOne<TransactionLocation>` | Append |
| `tx_by_transparent_addr_loc` | `AddressTransaction` | `()` | Never |
| `utxo_by_out_loc` | `OutputLocation` | `Output \|\| AddressLocation` | Delete |
| `utxo_by_transparent_addr_loc` | `AddressLocation` | `Vec<OutputLocation>` | Up/Del |
| `utxo_by_transparent_addr_loc` | `AddressUnspentOutput` | `()` | Delete |
| *Sprout* | | | |
| `sprout_nullifiers` | `sprout::Nullifier` | `()` | Never |
| `sprout_anchors` | `sprout::tree::Root` | `sprout::tree::NoteCommitmentTree` | Never |
@ -645,7 +645,10 @@ Block and Transaction Data:
- `AddressLocation`: the first `OutputLocation` used by a `transparent::Address`.
Always has the same value for each address, even if the first output is spent.
- `Utxo`: `Output`, derives extra fields from the `OutputLocation` key
- `AtLeastOne<T>` and `Vec<T>`: `[T; len()]` (for known-size `T`)
- `AddressUnspentOutput`: `AddressLocation \|\| OutputLocation`,
used instead of a `BTreeSet<OutputLocation>` value, to improve database performance
- `AddressTransaction`: `AddressLocation \|\| TransactionLocation`
used instead of a `BTreeSet<TransactionLocation>` value, to improve database performance
We use big-endian encoding for keys, to allow database index prefix searches.
@ -660,13 +663,15 @@ Derived Formats:
### Implementing consensus rules using rocksdb
[rocksdb-consensus-rules]: #rocksdb-consensus-rules
Each column family handles updates differently, based on its specific consensus rules:
Each column family handles value updates differently, based on its specific consensus rules:
- Never: Keys are never deleted, values are never updated. The value for each key is inserted once.
- Delete: Keys can be deleted, but values are never updated. The value for each key is inserted once.
- Code called by ReadStateService must ignore deleted keys, or use a read lock.
- TODO: should we prevent re-inserts of keys that have been deleted?
- Update: Keys are never deleted, but values can be updated.
- Code called by ReadStateService must accept old or new values, or use a read lock.
We can't do some kinds of value updates, because they cause RocksDB performance issues:
- Append: Keys are never deleted, existing values are never updated,
but sets of values can be extended with more entries.
- Code called by ReadStateService must accept truncated or extended sets, or use a read lock.
@ -675,6 +680,8 @@ Each column family handles updates differently, based on its specific consensus
accept truncated or extended sets, and accept old or new values.
Or it should use a read lock.
In general, avoid using large sets of values as RocksDB keys or values.
### RocksDB read locks
[rocksdb-read-locks]: #rocksdb-read-locks
@ -783,19 +790,22 @@ So they should not be used for consensus-critical checks.
address, which allows for efficient lookups.
- `utxo_by_transparent_addr_loc` stores unspent transparent output locations
by address. UTXO locations are appended by each block.
This list includes the `AddressLocation`, if it has not been spent.
by address. The address location and UTXO location are stored as a RocksDB key,
so they are in chain order, and get good database performance.
This column family includes also includes the original address location UTXO,
if it has not been spent.
- When a block write deletes a UTXO from `utxo_by_out_loc`,
that UTXO location should be deleted from `utxo_by_transparent_addr_loc`.
The `OutputLocations` are in order, so the deleted UTXO can be found using a
[binary search](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.binary_search).
The deleted UTXO can be removed efficiently, because the UTXO location is part of the key.
This is an index optimisation, which does not affect query results.
- `tx_by_transparent_addr_loc` stores transaction locations by address.
This list includes transactions containing spent UTXOs.
It also includes the `TransactionLocation` of the transaction for the `AddressLocation`.
(This duplicate data is small, and helps simplify the code.)
The address location and transaction location are stored as a RocksDB key,
so they are in chain order, and get good database performance.
This column family also includes the `TransactionLocation`
of the transaction for the `AddressLocation`.
- The `sprout_note_commitment_tree` stores the note commitment tree state
at the tip of the finalized state, for the specific pool. There is always