Skip to content

sui_v0.32.0_1681453353_ci

@longbowlu longbowlu tagged this 14 Apr 04:05
## Description 

Adds a `coin_index` table in the fullnode indexes. Keyed by <SuiAddress,
CoinTypeStr, ObjectID>, valued by `CoinInfo`:
```
pub struct CoinInfo {
    pub version: SequenceNumber,
    pub digest: ObjectDigest,
    pub balance: u64,
    pub previous_transaction: TransactionDigest,
}
```
In this way, when a user asks about balance(s) or (coins), we can
sequentially read these small-sized entries and perform cheap
aggregation, even when the number of coins is huge.

This PR applies to get balances(s) and get (coins).

**The meat is in `authority.rs`, `indexes.rs` and `coin_api.rs`.**

## authority.rs
Return coin objects from `AuthorityState::commit_certificate`. 
We look at `inner_temporary_store.written` and
`inner_temporary_store.objects` and grab the `Object` info if they are
coins. Why do we need this? Two reasons:
a. if an object is deleted, we can no longer get the content from the
object table after the commit, then no way to know its coin type at that
point. But to delete an entry in the coin index, we need to know its
coin type.
b. it's much cheaper to grab them here compared to fetching them from
the db later, especially when the number of coins is big which is the
problem we tried to avoid initially.

## indexes.rs
In the post processing job, we leverage the coin info returned from
`commit_certificate` and `object_index_changes` which is used to update
the ownership table. It works in the following way.
1. to delete old entries for object that is deleted or
transferred/wrapped, we iterate over
`object_index_changes.deleted_owners`, which only has objects owned by
AccountOwner before the tx but not dynamic fields. For each item, we see
if it's in the input objects from inner_temporary_store. If so, then
it's a coin, and we get its coin type from the `Object` value and delete
the entry in coin_index.
2. to upsert new entries for object that is created, transferred or
unwrapped, we iterate over `object_index_changes.new_owners` which only
has objects owned by AccountOwner after the tx but not dynamic fields.
For each item, we see if it's in the written objects from
inner_temporary_store. If so, then it's a coin and we construct the new
entry from the `Object` and insert it to coin_index.

To query a user's all balances or a balance of a certain coin type, we
skip to right key, and iterate until the key is no longer valid.

## coin_api.rs
As sanity checks, in the initial commit of this PR, the get all balance
and get balance api calls both the new and old implementation and
`assert_eq!` them to check correctness.


## Test Plan 

production deployments + extensive e2e tests

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes
Assets 2
Loading