common/types

This commit is contained in:
hinto.janai 2024-09-04 16:18:01 -04:00
parent 76d0cfbd87
commit 7a784459da
No known key found for this signature in database
GPG key ID: D47CE05FA175A499
3 changed files with 41 additions and 5 deletions

View file

@ -1 +1,9 @@
# 🟢 Common behavior
# Common behavior
The crates that build on-top of the database abstraction ([`cuprate_database`](https://doc.cuprate.org/cuprate_database))
share some common behavior including but not limited to:
- Defining their specific database tables and types
- Having an `ops` module
- Exposing a `tower::Service` API (backed by a threadpool) for public usage
This section provides more details on these behaviors.

View file

@ -1 +1,21 @@
# 🟢 Types
# Types
## POD types
Since [all types in the database are POD types](../db/serde.md), we must often
provide mappings between outside types and the types actually stored in the database.
A common case is mapping infallible types to and from [`bitflags`](https://docs.rs/bitflag) and/or their raw integer representation.
For example, the [`OutputFlag`](https://doc.cuprate.org/cuprate_blockchain/types/struct.OutputFlags.html) type or `bool` types.
As types like `enum`s, `bool`s and `char`s cannot be casted from an integer infallibly,
`bytemuck::Pod` cannot be implemented on it safely. Thus, we store some infallible version
of it inside the database with a custom type and map them when fetching the data.
## Lean types
Another reason why database crates define their own types is
to cut any unneeded data from the type.
Many of the types used in normal operation (e.g. [`cuprate_types::VerifiedBlockInformation`](https://doc.cuprate.org/cuprate_types/struct.VerifiedBlockInformation.html)) contain lots of extra pre-processed data for convenience.
This would be a waste to store in the database, so in this example, the much leaner
"raw" [`BlockInfo`](https://doc.cuprate.org/cuprate_blockchain/types/struct.BlockInfo.html)
type is stored.

View file

@ -1,7 +1,10 @@
# Multimap
Some of `cuprate_blockchain`'s tables differ from `monerod`'s tables, for example, the way multimap tables are done requires that the primary key is stored _for all_ entries, compared to `monerod` only needing to store it once.
`cuprate_database` does not currently have an abstraction for [multimap tables](https://en.wikipedia.org/wiki/Multimap).
All tables are single maps of keys to values.
This matters as this means some of `cuprate_blockchain`'s tables differ from `monerod`'s tables - the primary key is stored _for all_ entries, compared to `monerod` only needing to store it once:
For example:
```rust
// `monerod` only stores `amount: 1` once,
// `cuprated` stores it each time it appears.
@ -11,4 +14,9 @@ struct PreRctOutputId { amount: 1, amount_index: 1 }
This means `cuprated`'s database will be slightly larger than `monerod`'s.
The current method `cuprate_blockchain` uses will be "good enough" until usage shows that it must be optimized as multimap tables are tricky to implement across all backends.
The current method `cuprate_blockchain` uses will be "good enough" as the multimap
keys needed for now are fixed, e.g. pre-RCT outputs are no longer being produced.
This may need to change in the future when multimap is all but required, e.g. for FCMP++.
Until then, multimap tables are not implemented as they are tricky to implement across all backends.