Skip to content

Commit

Permalink
services/horizon: CAP0018 Support (#2423)
Browse files Browse the repository at this point in the history
* Extend operation processor with authorized to mainliabilities details.

* Add EffectTrustlineAuthorizedToMaintainLiabilities.

* Add EffectTrustlineAuthorizedToMaintainLiabilities to protocol.

* Show both authorize and authorize_to_maintain_liabilities in in operation details.

* Add test for AllowTrust resource adapter.

* Update allow trust details.

* Add test for effect resource.

* Add is_authorized_to_maintain_liabilities to balance resource.

* Always show is_authorized_to_maintain_liabilities.

* Always show authorize_to_maintain_liabilities in operation allow trust.

* Include all flags in allow trust operation details.

* Update changelog.
  • Loading branch information
abuiles authored and tamirms committed Mar 31, 2020
1 parent bec3ae2 commit 88f97da
Show file tree
Hide file tree
Showing 16 changed files with 475 additions and 69 deletions.
62 changes: 37 additions & 25 deletions protocols/horizon/effects/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ const (
// it issues.
EffectTrustlineDeauthorized EffectType = 24 // from allow_trust

// EffectTrustlineAuthorizedToMaintainLiabilities occurs when an anchor has AUTH_REQUIRED flag set
// to true and it authorizes another account's trustline to maintain liabilities
EffectTrustlineAuthorizedToMaintainLiabilities EffectType = 25 // from allow_trust

// trading effects

// EffectOfferCreated occurs when an account offers to trade an asset
Expand Down Expand Up @@ -114,30 +118,31 @@ const (

// EffectTypeNames stores a map of effect type ID and names
var EffectTypeNames = map[EffectType]string{
EffectAccountCreated: "account_created",
EffectAccountRemoved: "account_removed",
EffectAccountCredited: "account_credited",
EffectAccountDebited: "account_debited",
EffectAccountThresholdsUpdated: "account_thresholds_updated",
EffectAccountHomeDomainUpdated: "account_home_domain_updated",
EffectAccountFlagsUpdated: "account_flags_updated",
EffectAccountInflationDestinationUpdated: "account_inflation_destination_updated",
EffectSignerCreated: "signer_created",
EffectSignerRemoved: "signer_removed",
EffectSignerUpdated: "signer_updated",
EffectTrustlineCreated: "trustline_created",
EffectTrustlineRemoved: "trustline_removed",
EffectTrustlineUpdated: "trustline_updated",
EffectTrustlineAuthorized: "trustline_authorized",
EffectTrustlineDeauthorized: "trustline_deauthorized",
EffectOfferCreated: "offer_created",
EffectOfferRemoved: "offer_removed",
EffectOfferUpdated: "offer_updated",
EffectTrade: "trade",
EffectDataCreated: "data_created",
EffectDataRemoved: "data_removed",
EffectDataUpdated: "data_updated",
EffectSequenceBumped: "sequence_bumped",
EffectAccountCreated: "account_created",
EffectAccountRemoved: "account_removed",
EffectAccountCredited: "account_credited",
EffectAccountDebited: "account_debited",
EffectAccountThresholdsUpdated: "account_thresholds_updated",
EffectAccountHomeDomainUpdated: "account_home_domain_updated",
EffectAccountFlagsUpdated: "account_flags_updated",
EffectAccountInflationDestinationUpdated: "account_inflation_destination_updated",
EffectSignerCreated: "signer_created",
EffectSignerRemoved: "signer_removed",
EffectSignerUpdated: "signer_updated",
EffectTrustlineCreated: "trustline_created",
EffectTrustlineRemoved: "trustline_removed",
EffectTrustlineUpdated: "trustline_updated",
EffectTrustlineAuthorized: "trustline_authorized",
EffectTrustlineAuthorizedToMaintainLiabilities: "trustline_authorized_to_maintain_liabilities",
EffectTrustlineDeauthorized: "trustline_deauthorized",
EffectOfferCreated: "offer_created",
EffectOfferRemoved: "offer_removed",
EffectOfferUpdated: "offer_updated",
EffectTrade: "trade",
EffectDataCreated: "data_created",
EffectDataRemoved: "data_removed",
EffectDataUpdated: "data_updated",
EffectSequenceBumped: "sequence_bumped",
}

// Base provides the common structure for any effect resource effect.
Expand Down Expand Up @@ -247,6 +252,13 @@ type TrustlineAuthorized struct {
AssetCode string `json:"asset_code,omitempty"`
}

type TrustlineAuthorizedToMaintainLiabilities struct {
Base
Trustor string `json:"trustor"`
AssetType string `json:"asset_type"`
AssetCode string `json:"asset_code,omitempty"`
}

type TrustlineDeauthorized struct {
Base
Trustor string `json:"trustor"`
Expand Down Expand Up @@ -397,7 +409,7 @@ func UnmarshalEffect(effectType string, dataString []byte) (effects Effect, err
return
}
effects = effect
case EffectTypeNames[EffectTrustlineAuthorized]:
case EffectTypeNames[EffectTrustlineAuthorized], EffectTypeNames[EffectTrustlineAuthorizedToMaintainLiabilities]:
var effect TrustlineAuthorized
if err = json.Unmarshal(dataString, &effect); err != nil {
return
Expand Down
13 changes: 7 additions & 6 deletions protocols/horizon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,12 +192,13 @@ func (res AssetStat) PagingToken() string {

// Balance represents an account's holdings for a single currency type
type Balance struct {
Balance string `json:"balance"`
Limit string `json:"limit,omitempty"`
BuyingLiabilities string `json:"buying_liabilities"`
SellingLiabilities string `json:"selling_liabilities"`
LastModifiedLedger uint32 `json:"last_modified_ledger,omitempty"`
IsAuthorized *bool `json:"is_authorized,omitempty"`
Balance string `json:"balance"`
Limit string `json:"limit,omitempty"`
BuyingLiabilities string `json:"buying_liabilities"`
SellingLiabilities string `json:"selling_liabilities"`
LastModifiedLedger uint32 `json:"last_modified_ledger,omitempty"`
IsAuthorized *bool `json:"is_authorized,omitempty"`
IsAuthorizedToMaintainLiabilities *bool `json:"is_authorized_to_maintain_liabilities,omitempty"`
base.Asset
}

Expand Down
7 changes: 4 additions & 3 deletions protocols/horizon/operations/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,10 @@ type ChangeTrust struct {
type AllowTrust struct {
Base
base.Asset
Trustee string `json:"trustee"`
Trustor string `json:"trustor"`
Authorize bool `json:"authorize"`
Trustee string `json:"trustee"`
Trustor string `json:"trustor"`
Authorize bool `json:"authorize"`
AuthorizeToMaintainLiabilities bool `json:"authorize_to_maintain_liabilities"`
}

// AccountMerge is the json resource representing a single operation whose type
Expand Down
59 changes: 58 additions & 1 deletion services/horizon/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,64 @@ file. This project adheres to [Semantic Versioning](http://semver.org/).
* Fix ask and bid price levels of GET /order_book when encountering non-canonical price values. The `limit` parameter is now respected and levels are coallesced properly. Also, `price_r` is now in canonical form.
* Remove duplicate indexes: index_history_transactions_on_id, index_history_ledgers_on_id, exp_asset_stats_by_code, and asset_by_code
* Remove asset_stats table which is no longer necessary

* Add support for CAP0018: Fine-Grained Control of Authorization ([#2423](https://github.com/stellar/go/pull/2423)).
- Add `is_authorized_to_maintain_liabilities` to `Balance`.
<pre>
"balances": [
{
"is_authorized": true,
<b>"is_authorized_to_maintain_liabilities": true,</b>
"balance": "27.1374422",
"limit": "922337203685.4775807",
"buying_liabilities": "0.0000000",
"selling_liabilities": "0.0000000",
"last_modified_ledger": 28893780,
"asset_type": "credit_alphanum4",
"asset_code": "USD",
"asset_issuer": "GBSTRUSD7IRX73RQZBL3RQUH6KS3O4NYFY3QCALDLZD77XMZOPWAVTUK"
},
{
"balance": "1.5000000",
"buying_liabilities": "0.0000000",
"selling_liabilities": "0.0000000",
"asset_type": "native"
}
]
</pre>
- Add `authorize_to_maintain_liabilities` to `AllowTrust` operation.
<pre>
{
"id": "124042211741474817",
"paging_token": "124042211741474817",
"transaction_successful": true,
"source_account": "GBSTRUSD7IRX73RQZBL3RQUH6KS3O4NYFY3QCALDLZD77XMZOPWAVTUK",
"type": "allow_trust",
"type_i": 7,
"created_at": "2020-03-27T03:40:10Z",
"transaction_hash": "a77d4ee5346d55fb8026cdcdad6e4b5e0c440c96b4627e3727f4ccfa6d199e94",
"asset_type": "credit_alphanum4",
"asset_code": "USD",
"asset_issuer": "GBSTRUSD7IRX73RQZBL3RQUH6KS3O4NYFY3QCALDLZD77XMZOPWAVTUK",
"trustee": "GBSTRUSD7IRX73RQZBL3RQUH6KS3O4NYFY3QCALDLZD77XMZOPWAVTUK",
"trustor": "GA332TXN6BX2DYKGYB7FW5BWV2JLQKERNX4T7EUJT4MHWOW2TSGC2SPM",
"authorize": true,
<b>"authorize_to_maintain_liabilities": true,</b>
}
</pre>
- Add effect `trustline_authorized_to_maintain_liabilities`.
<pre>
{
"id": "0124042211741474817-0000000001",
"paging_token": "124042211741474817-1",
"account": "GBSTRUSD7IRX73RQZBL3RQUH6KS3O4NYFY3QCALDLZD77XMZOPWAVTUK",
<b>"type": "trustline_authorized_to_maintain_liabilities",</b>
<b>"type_i": 25,</b>
"created_at": "2020-03-27T03:40:10Z",
"trustor": "GA332TXN6BX2DYKGYB7FW5BWV2JLQKERNX4T7EUJT4MHWOW2TSGC2SPM",
"asset_type": "credit_alphanum4",
"asset_code": "USD"
}
</pre>
## v1.0.1

### Fixed
Expand Down
4 changes: 4 additions & 0 deletions services/horizon/internal/db2/core/trustline.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ func (tl Trustline) IsAuthorized() bool {
return (tl.Flags & int32(xdr.TrustLineFlagsAuthorizedFlag)) != 0
}

func (tl Trustline) IsAuthorizedToMaintainLiabilities() bool {
return (tl.Flags & int32(xdr.TrustLineFlagsAuthorizedToMaintainLiabilitiesFlag)) != 0
}

// AssetsForAddress returns a list of assets and balances for those assets held by
// a given address.
func (q *Q) AssetsForAddress(addy string) ([]xdr.Asset, []xdr.Int64, error) {
Expand Down
4 changes: 4 additions & 0 deletions services/horizon/internal/db2/history/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ const (
// it issues.
EffectTrustlineDeauthorized EffectType = 24 // from allow_trust

// EffectTrustlineAuthorizedToMaintainLiabilities occurs when an anchor has AUTH_REQUIRED flag set
// to true and it authorizes another account's trustline to maintain liabilities
EffectTrustlineAuthorizedToMaintainLiabilities EffectType = 25 // from allow_trust

// trading effects

// EffectOfferCreated occurs when an account offers to trade an asset
Expand Down
6 changes: 6 additions & 0 deletions services/horizon/internal/db2/history/trust_lines.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ func (trustLine TrustLine) IsAuthorized() bool {
return xdr.TrustLineFlags(trustLine.Flags).IsAuthorized()
}

// IsAuthorizedToMaintainLiabilities returns true if issuer has authorized the account to maintain
// liabilities with its credit
func (trustLine TrustLine) IsAuthorizedToMaintainLiabilities() bool {
return xdr.TrustLineFlags(trustLine.Flags).IsAuthorizedToMaintainLiabilitiesFlag()
}

func (q *Q) CountTrustLines() (int, error) {
sql := sq.Select("count(*)").From("trust_lines")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -549,9 +549,16 @@ func (operation *transactionOperationWrapper) allowTrustEffects() []effect {
}
assetDetails(details, asset, "")

if xdr.TrustLineFlags(op.Authorize).IsAuthorized() {
switch {
case xdr.TrustLineFlags(op.Authorize).IsAuthorized():
effects.add(source.Address(), history.EffectTrustlineAuthorized, details)
} else {
case xdr.TrustLineFlags(op.Authorize).IsAuthorizedToMaintainLiabilitiesFlag():
effects.add(
source.Address(),
history.EffectTrustlineAuthorizedToMaintainLiabilities,
details,
)
default:
effects.add(source.Address(), history.EffectTrustlineDeauthorized, details)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1213,3 +1213,48 @@ func TestOperationRegressionAccountTrustItself(t *testing.T) {
tt.NoError(err)
tt.Equal([]effect{}, effects)
}

func TestOperationEffectsAllowTrustAuthorizedToMaintainLiabilities(t *testing.T) {
tt := assert.New(t)
asset := xdr.Asset{}
allowTrustAsset, err := asset.ToAllowTrustOpAsset("COP")
tt.NoError(err)
source := xdr.MustAddress("GDRW375MAYR46ODGF2WGANQC2RRZL7O246DYHHCGWTV2RE7IHE2QUQLD")
op := xdr.Operation{
SourceAccount: &source,
Body: xdr.OperationBody{
Type: xdr.OperationTypeAllowTrust,
AllowTrustOp: &xdr.AllowTrustOp{
Trustor: xdr.MustAddress("GDQNY3PBOJOKYZSRMK2S7LHHGWZIUISD4QORETLMXEWXBI7KFZZMKTL3"),
Asset: allowTrustAsset,
Authorize: xdr.Uint32(xdr.TrustLineFlagsAuthorizedToMaintainLiabilitiesFlag),
},
},
}

operation := transactionOperationWrapper{
index: 0,
transaction: io.LedgerTransaction{},
operation: op,
ledgerSequence: 1,
}

effects, err := operation.effects()
tt.NoError(err)

expected := []effect{
effect{
address: "GDRW375MAYR46ODGF2WGANQC2RRZL7O246DYHHCGWTV2RE7IHE2QUQLD",
operationID: 4294967297,
details: map[string]interface{}{
"asset_code": "COP",
"asset_issuer": "GDRW375MAYR46ODGF2WGANQC2RRZL7O246DYHHCGWTV2RE7IHE2QUQLD",
"asset_type": "credit_alphanum4",
"trustor": "GDQNY3PBOJOKYZSRMK2S7LHHGWZIUISD4QORETLMXEWXBI7KFZZMKTL3",
},
effectType: history.EffectTrustlineAuthorizedToMaintainLiabilities,
order: uint32(1),
},
}
tt.Equal(expected, effects)
}
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ func (operation *transactionOperationWrapper) Details() map[string]interface{} {
details["trustee"] = source.Address()
details["trustor"] = op.Trustor.Address()
details["authorize"] = xdr.TrustLineFlags(op.Authorize).IsAuthorized()
details["authorize_to_maintain_liabilities"] = xdr.TrustLineFlags(op.Authorize).IsAuthorized() || xdr.TrustLineFlags(op.Authorize).IsAuthorizedToMaintainLiabilitiesFlag()
case xdr.OperationTypeAccountMerge:
aid := operation.operation.Body.MustDestination()
details["account"] = source.Address()
Expand Down
Loading

0 comments on commit 88f97da

Please sign in to comment.