-
Notifications
You must be signed in to change notification settings - Fork 499
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
services/horizon: Include contract asset balances in asset stats #4805
services/horizon: Include contract asset balances in asset stats #4805
Conversation
// Action needed in release: horizon-v3.0.0: deprecated field | ||
Amount string `json:"amount"` | ||
Accounts AssetStatAccounts `json:"accounts"` | ||
ClaimableBalancesAmount string `json:"claimable_balances_amount"` | ||
LiquidityPoolsAmount string `json:"liquidity_pools_amount"` | ||
ContractsAmount string `json:"contracts_amount"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the total amount of assets in all the contracts? Then I would rename it to something like AllContractsAmount
or ContractsTotalAmount
or ContractsAmountSum
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is the amount of the given, specific asset that is stored w/in its SAC contract. Or does it go beyond the SAC, @tamirms?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@2opremio is correct that is the total amount held by all smart contracts. I agree that renaming it would be better but then it would be inconsistent with liquidity_pools_amount
and claimable_balances_amount
. We could rename all the fields but that would be a breaking change
// Action needed in release: horizon-v3.0.0: deprecated field | ||
Amount string `json:"amount"` | ||
Accounts AssetStatAccounts `json:"accounts"` | ||
ClaimableBalancesAmount string `json:"claimable_balances_amount"` | ||
LiquidityPoolsAmount string `json:"liquidity_pools_amount"` | ||
ContractsAmount string `json:"contracts_amount"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is the amount of the given, specific asset that is stored w/in its SAC contract. Or does it go beyond the SAC, @tamirms?
amount := amountObj.MustI128() | ||
// check if negative | ||
if ((amount.Hi >> 56) & 0x80) > 0 { | ||
return [32]byte{}, nil, false | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😳 is there a test for this? why 56?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we also check that Hi
or Lo
fits in an int64
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wondered similar, for balances,Hi
is just holding sign extension bits for Lo
as uint64
? just the most significant bit in Hi
could be checked?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
few comments.. but looks good.
services/horizon/internal/ingest/processors/asset_stats_processor.go
Outdated
Show resolved
Hide resolved
services/horizon/internal/ingest/processors/asset_stats_processor.go
Outdated
Show resolved
Hide resolved
if obj.Type != xdr.ScObjectTypeScoBytes { | ||
return nil | ||
} | ||
var err error | ||
assetIssuer, err = strkey.Encode(strkey.VersionByteAccountID, obj.MustBin()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is wrong :
if objMjustBin() is nil ,then you shoudl return nil.
however, if strkey.Encode
returns an error, you should return this error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the issuer byte array is invalid then this is an indication that it's not coming from the stellar asset contract which is why I return nil. But you're right that I should check that obj.MustBin() is not nill
services/horizon/internal/ingest/processors/asset_stats_processor.go
Outdated
Show resolved
Hide resolved
@stellar/horizon-committers PTAL I think I've addressed all the code review feedback |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure my approval is enough, other reviewers had some conversations in flight still, but wanted to check off, thanks for all clarifications.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
couple comments around subtleties in i128
but otherwise I think it LGTM!
return [32]byte{}, nil, false | ||
} | ||
amt := new(big.Int).Lsh(big.NewInt(int64(amount.Hi)), 64) | ||
amt.Add(amt, big.NewInt(int64(amount.Lo))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on my discussion on Slack here, I think int64(amount.Lo)
is not safe. You should do big.NewInt(0).SetUint64(amount.Lo)
, instead, because only the upper half contains info about the overall sign of amount
. Otherwise this will give you a negative value if amount > MaxInt64
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a great catch. I think there is a bug here. I will fix this and update the tests to catch this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in general, we should probably shove this into a library wrapper around Int128Parts
as these conversions/math can easily be a huge source of bugs down the line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made #4809 to track this for the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm, awesome work 👏
PR Checklist
PR Structure
otherwise).
services/friendbot
, orall
ordoc
if the changes are broad or impact manypackages.
Thoroughness
.md
files, etc... affected by this change). Take a look in the
docs
folder for a given service,like this one.
Release planning
needed with deprecations, added features, breaking changes, and DB schema changes.
semver, or if it's mainly a patch change. The PR is targeted at the next
release branch if it's not a patch change.
What
This PR a follow up to #4782 where we update asset stats ingestion to keep track of how many contracts hold an asset and the amount of an asset held by all contracts in total.
This is implemented by ingesting balance contract data ledger entries which are updated by the stellar asset contract. The balance contract data ledger entries are like trustlines but for contract holders of an asset.
Why
This PR is required to implement #4727
Known limitations
We cannot directly identify if a balance contract data ledger entry belongs to a genuine stellar asset contract. So we work around this by querying the asset stats table by contract id. If there is a row present then we know that the balance contract data ledger entry corresponds to the stellar asset contract. Otherwise, we ignore the ledger entry change in ingestion.
If the extra db load becomes a problem we could think about having a something like a bloom filter which we can use to discard ledger entries from non stellar asset contracts that mimic the stellar asset contract balance format.