Skip to content
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

Merged
merged 12 commits into from
Mar 16, 2023
2 changes: 2 additions & 0 deletions protocols/horizon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,13 @@ type AssetStat struct {
NumAccounts int32 `json:"num_accounts"`
NumClaimableBalances int32 `json:"num_claimable_balances"`
NumLiquidityPools int32 `json:"num_liquidity_pools"`
NumContracts int32 `json:"num_contracts"`
// 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"`
Copy link
Contributor

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

Copy link
Contributor

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?

Copy link
Contributor Author

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

Balances AssetStatBalances `json:"balances"`
Flags AccountFlags `json:"flags"`
}
Expand Down
5 changes: 5 additions & 0 deletions services/horizon/internal/actions/asset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ func TestAssetStats(t *testing.T) {
LiquidityPoolsAmount: "0.0000020",
Amount: "0.0000001",
NumAccounts: usdAssetStat.NumAccounts,
ContractsAmount: "0.0000000",
Asset: base.Asset{
Type: "credit_alphanum4",
Code: usdAssetStat.AssetCode,
Expand Down Expand Up @@ -202,6 +203,7 @@ func TestAssetStats(t *testing.T) {
},
ClaimableBalancesAmount: "0.0000000",
LiquidityPoolsAmount: "0.0000000",
ContractsAmount: "0.0000000",
Amount: "0.0000023",
NumAccounts: etherAssetStat.NumAccounts,
Asset: base.Asset{
Expand Down Expand Up @@ -248,6 +250,7 @@ func TestAssetStats(t *testing.T) {
ClaimableBalancesAmount: "0.0000000",
LiquidityPoolsAmount: "0.0000000",
Amount: "0.0000001",
ContractsAmount: "0.0000000",
NumAccounts: otherUSDAssetStat.NumAccounts,
Asset: base.Asset{
Type: "credit_alphanum4",
Expand Down Expand Up @@ -295,6 +298,7 @@ func TestAssetStats(t *testing.T) {
ClaimableBalancesAmount: "0.0000000",
LiquidityPoolsAmount: "0.0000000",
Amount: "0.0000111",
ContractsAmount: "0.0000000",
NumAccounts: eurAssetStat.NumAccounts,
Asset: base.Asset{
Type: "credit_alphanum4",
Expand Down Expand Up @@ -471,6 +475,7 @@ func TestAssetStatsIssuerDoesNotExist(t *testing.T) {
ClaimableBalancesAmount: "0.0000000",
LiquidityPoolsAmount: "0.0000000",
Amount: "0.0000001",
ContractsAmount: "0.0000000",
NumAccounts: usdAssetStat.NumAccounts,
Asset: base.Asset{
Type: "credit_alphanum4",
Expand Down
14 changes: 0 additions & 14 deletions services/horizon/internal/db2/history/asset_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,20 +126,6 @@ func (q *Q) GetAssetStatByContracts(ctx context.Context, contractIDs [][32]byte)
return assetStats, err
}

// CountContractIDs counts all rows in the asset stats table which have a contract id set.
// CountContractIDs is used by the state verification routine.
func (q *Q) CountContractIDs(ctx context.Context) (int, error) {
sql := sq.Select("count(*)").From("exp_asset_stats").
Where("contract_id IS NOT NULL")

var count int
if err := q.Get(ctx, &count, sql); err != nil {
return 0, errors.Wrap(err, "could not run select query")
}

return count, nil
}

func parseAssetStatsCursor(cursor string) (string, string, error) {
parts := strings.SplitN(cursor, "_", 3)
if len(parts) != 3 {
Expand Down
48 changes: 37 additions & 11 deletions services/horizon/internal/db2/history/asset_stats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ func TestAssetStatContracts(t *testing.T) {
test.ResetHorizonDB(t, tt.HorizonDB)
q := &Q{tt.HorizonSession()}

// asset stats is empty so count should be 0
count, err := q.CountContractIDs(tt.Ctx)
tt.Assert.NoError(err)
tt.Assert.Equal(0, count)

assetStats := []ExpAssetStat{
{
AssetType: xdr.AssetTypeAssetTypeNative,
Expand All @@ -30,13 +25,15 @@ func TestAssetStatContracts(t *testing.T) {
ClaimableBalances: 0,
LiquidityPools: 0,
Unauthorized: 0,
Contracts: 0,
},
Balances: ExpAssetStatBalances{
Authorized: "0",
AuthorizedToMaintainLiabilities: "0",
ClaimableBalances: "0",
LiquidityPools: "0",
Unauthorized: "0",
Contracts: "0",
},
Amount: "0",
NumAccounts: 0,
Expand All @@ -49,13 +46,15 @@ func TestAssetStatContracts(t *testing.T) {
Authorized: 1,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
Contracts: 7,
},
Balances: ExpAssetStatBalances{
Authorized: "23",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
ClaimableBalances: "4",
LiquidityPools: "5",
Contracts: "60",
},
Amount: "23",
NumAccounts: 1,
Expand All @@ -68,13 +67,15 @@ func TestAssetStatContracts(t *testing.T) {
Authorized: 2,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
Contracts: 8,
},
Balances: ExpAssetStatBalances{
Authorized: "1",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
ClaimableBalances: "4",
LiquidityPools: "5",
Contracts: "90",
},
Amount: "1",
NumAccounts: 2,
Expand All @@ -87,14 +88,10 @@ func TestAssetStatContracts(t *testing.T) {
}
tt.Assert.NoError(q.InsertAssetStats(tt.Ctx, assetStats, 1))

count, err = q.CountContractIDs(tt.Ctx)
tt.Assert.NoError(err)
tt.Assert.Equal(2, count)

contractID[0] = 0
for i := 0; i < 2; i++ {
var assetStat ExpAssetStat
assetStat, err = q.GetAssetStatByContract(tt.Ctx, contractID)
assetStat, err := q.GetAssetStatByContract(tt.Ctx, contractID)
tt.Assert.NoError(err)
tt.Assert.True(assetStat.Equals(assetStats[i]))
contractID[0]++
Expand Down Expand Up @@ -162,13 +159,15 @@ func TestInsertAssetStats(t *testing.T) {
Authorized: 2,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
Contracts: 0,
},
Balances: ExpAssetStatBalances{
Authorized: "1",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
ClaimableBalances: "4",
LiquidityPools: "5",
Contracts: "0",
},
Amount: "1",
NumAccounts: 2,
Expand All @@ -181,13 +180,15 @@ func TestInsertAssetStats(t *testing.T) {
Authorized: 1,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
Contracts: 0,
},
Balances: ExpAssetStatBalances{
Authorized: "23",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
ClaimableBalances: "4",
LiquidityPools: "5",
Contracts: "0",
},
Amount: "23",
NumAccounts: 1,
Expand Down Expand Up @@ -217,13 +218,15 @@ func TestInsertAssetStat(t *testing.T) {
Authorized: 2,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
Contracts: 0,
},
Balances: ExpAssetStatBalances{
Authorized: "1",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
ClaimableBalances: "4",
LiquidityPools: "5",
Contracts: "0",
},
Amount: "1",
NumAccounts: 2,
Expand All @@ -236,13 +239,15 @@ func TestInsertAssetStat(t *testing.T) {
Authorized: 1,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
Contracts: 0,
},
Balances: ExpAssetStatBalances{
Authorized: "23",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
ClaimableBalances: "4",
LiquidityPools: "5",
Contracts: "0",
},
Amount: "23",
NumAccounts: 1,
Expand Down Expand Up @@ -274,13 +279,15 @@ func TestInsertAssetStatAlreadyExistsError(t *testing.T) {
Authorized: 2,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
Contracts: 0,
},
Balances: ExpAssetStatBalances{
Authorized: "1",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
ClaimableBalances: "4",
LiquidityPools: "5",
Contracts: "0",
},
Amount: "1",
NumAccounts: 2,
Expand Down Expand Up @@ -321,13 +328,15 @@ func TestUpdateAssetStatDoesNotExistsError(t *testing.T) {
Authorized: 2,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
Contracts: 0,
},
Balances: ExpAssetStatBalances{
Authorized: "1",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
ClaimableBalances: "4",
LiquidityPools: "5",
Contracts: "0",
},
Amount: "1",
NumAccounts: 2,
Expand Down Expand Up @@ -356,13 +365,15 @@ func TestUpdateStat(t *testing.T) {
Authorized: 2,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
Contracts: 0,
},
Balances: ExpAssetStatBalances{
Authorized: "1",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
ClaimableBalances: "4",
LiquidityPools: "5",
Contracts: "0",
},
Amount: "1",
NumAccounts: 2,
Expand All @@ -377,15 +388,18 @@ func TestUpdateStat(t *testing.T) {
tt.Assert.Equal(got, assetStat)

assetStat.NumAccounts = 50
assetStat.Accounts.Contracts = 4
assetStat.Amount = "23"
assetStat.Balances.Contracts = "56"
assetStat.SetContractID([32]byte{23})

numChanged, err = q.UpdateAssetStat(tt.Ctx, assetStat)
tt.Assert.Nil(err)
tt.Assert.Equal(numChanged, int64(1))

got, err = q.GetAssetStat(tt.Ctx, assetStat.AssetType, assetStat.AssetCode, assetStat.AssetIssuer)
tt.Assert.NoError(err)
tt.Assert.Equal(got, assetStat)
tt.Assert.True(got.Equals(assetStat))
}

func TestGetAssetStatDoesNotExist(t *testing.T) {
Expand All @@ -402,13 +416,15 @@ func TestGetAssetStatDoesNotExist(t *testing.T) {
Authorized: 2,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
Contracts: 0,
},
Balances: ExpAssetStatBalances{
Authorized: "1",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
ClaimableBalances: "4",
LiquidityPools: "5",
Contracts: "0",
},
Amount: "1",
NumAccounts: 2,
Expand All @@ -433,13 +449,15 @@ func TestRemoveAssetStat(t *testing.T) {
Authorized: 2,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
Contracts: 0,
},
Balances: ExpAssetStatBalances{
Authorized: "1",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
ClaimableBalances: "4",
LiquidityPools: "5",
Contracts: "0",
},
Amount: "1",
NumAccounts: 2,
Expand Down Expand Up @@ -569,13 +587,15 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) {
Authorized: 2,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
Contracts: 0,
},
Balances: ExpAssetStatBalances{
Authorized: "1",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
ClaimableBalances: "0",
LiquidityPools: "0",
Contracts: "0",
},
Amount: "1",
NumAccounts: 2,
Expand All @@ -588,13 +608,15 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) {
Authorized: 1,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
Contracts: 0,
},
Balances: ExpAssetStatBalances{
Authorized: "23",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
ClaimableBalances: "0",
LiquidityPools: "0",
Contracts: "0",
},
Amount: "23",
NumAccounts: 1,
Expand All @@ -607,13 +629,15 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) {
Authorized: 2,
AuthorizedToMaintainLiabilities: 3,
Unauthorized: 4,
Contracts: 0,
},
Balances: ExpAssetStatBalances{
Authorized: "1",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
ClaimableBalances: "0",
LiquidityPools: "0",
Contracts: "0",
},
Amount: "1",
NumAccounts: 2,
Expand All @@ -626,13 +650,15 @@ func TestGetAssetStatsFiltersAndCursor(t *testing.T) {
Authorized: 3,
AuthorizedToMaintainLiabilities: 2,
Unauthorized: 4,
Contracts: 0,
},
Balances: ExpAssetStatBalances{
Authorized: "111",
AuthorizedToMaintainLiabilities: "2",
Unauthorized: "3",
ClaimableBalances: "1",
LiquidityPools: "2",
Contracts: "0",
},
Amount: "111",
NumAccounts: 3,
Expand Down
Loading