diff --git a/services/horizon/internal/db2/history/main.go b/services/horizon/internal/db2/history/main.go index deae0ae223..e582c9abc5 100644 --- a/services/horizon/internal/db2/history/main.go +++ b/services/horizon/internal/db2/history/main.go @@ -39,6 +39,10 @@ const ( // account flags, either clearing or setting. EffectAccountFlagsUpdated EffectType = 6 // from set_options + // EffectAccountInflationDestinationUpdated effects occur when an account changes its + // inflation destination. + EffectAccountInflationDestinationUpdated EffectType = 7 // from set_options + // signer effects // EffectSignerCreated occurs when an account gains a signer diff --git a/services/horizon/internal/ingest/session.go b/services/horizon/internal/ingest/session.go index c28ceb592c..0076b3ef86 100644 --- a/services/horizon/internal/ingest/session.go +++ b/services/horizon/internal/ingest/session.go @@ -4,6 +4,7 @@ import ( "context" "encoding/base64" "fmt" + "reflect" "time" "github.com/stellar/go/clients/stellarcore" @@ -201,6 +202,14 @@ func (is *Session) ingestEffects() { effects.Add(source, history.EffectAccountFlagsUpdated, flagDetails) } + if op.InflationDest != nil { + effects.Add(source, history.EffectAccountInflationDestinationUpdated, + map[string]interface{}{ + "inflation_destination": op.InflationDest.Address(), + }, + ) + } + is.ingestSignerEffects(effects, op) case xdr.OperationTypeChangeTrust: @@ -397,6 +406,7 @@ func (is *Session) ingestSignerEffects(effects *EffectIngestion, op xdr.SetOptio // HACK (scott) 2017-11-27: Prevent crashes when BeforeAndAfter fails to // correctly work. if be == nil || ae == nil { + // TODO (scott) 2018-03-02: log some info to help us track down the crash, doofus return } @@ -406,6 +416,11 @@ func (is *Session) ingestSignerEffects(effects *EffectIngestion, op xdr.SetOptio before := beforeAccount.SignerSummary() after := afterAccount.SignerSummary() + // if before and after are the same, the signers have not changed + if reflect.DeepEqual(before, after) { + return + } + for addy := range before { weight, ok := after[addy] if !ok { diff --git a/services/horizon/internal/ingest/session_test.go b/services/horizon/internal/ingest/session_test.go new file mode 100644 index 0000000000..56f49eb61d --- /dev/null +++ b/services/horizon/internal/ingest/session_test.go @@ -0,0 +1,46 @@ +package ingest + +import ( + "testing" + + "github.com/stellar/go/services/horizon/internal/db2/history" + "github.com/stellar/go/services/horizon/internal/test" +) + +func Test_ingestSignerEffects(t *testing.T) { + tt := test.Start(t).ScenarioWithoutHorizon("set_options") + defer tt.Finish() + + s := ingest(tt) + tt.Require.NoError(s.Err) + + q := &history.Q{Session: tt.HorizonSession()} + + // Regression: https://github.com/stellar/horizon/issues/390 doesn't produce a signer effect when + // inflation has changed + var effects []history.Effect + err := q.Effects().ForLedger(3).Select(&effects) + tt.Require.NoError(err) + + if tt.Assert.Len(effects, 1) { + tt.Assert.NotEqual(history.EffectSignerUpdated, effects[0].Type) + } +} + +func Test_ingestOperationEffects(t *testing.T) { + tt := test.Start(t).ScenarioWithoutHorizon("set_options") + defer tt.Finish() + + s := ingest(tt) + tt.Require.NoError(s.Err) + + // ensure inflation destination change is correctly recorded + q := &history.Q{Session: tt.HorizonSession()} + var effects []history.Effect + err := q.Effects().ForLedger(3).Select(&effects) + tt.Require.NoError(err) + + if tt.Assert.Len(effects, 1) { + tt.Assert.Equal(history.EffectAccountInflationDestinationUpdated, effects[0].Type) + } +} diff --git a/services/horizon/internal/resource/effects/main.go b/services/horizon/internal/resource/effects/main.go index 7f13c33205..0b462d04bd 100644 --- a/services/horizon/internal/resource/effects/main.go +++ b/services/horizon/internal/resource/effects/main.go @@ -2,34 +2,35 @@ package effects import ( "github.com/stellar/go/services/horizon/internal/db2/history" - "github.com/stellar/go/services/horizon/internal/resource/base" "github.com/stellar/go/services/horizon/internal/render/hal" + "github.com/stellar/go/services/horizon/internal/resource/base" "golang.org/x/net/context" ) var TypeNames = map[history.EffectType]string{ - history.EffectAccountCreated: "account_created", - history.EffectAccountRemoved: "account_removed", - history.EffectAccountCredited: "account_credited", - history.EffectAccountDebited: "account_debited", - history.EffectAccountThresholdsUpdated: "account_thresholds_updated", - history.EffectAccountHomeDomainUpdated: "account_home_domain_updated", - history.EffectAccountFlagsUpdated: "account_flags_updated", - history.EffectSignerCreated: "signer_created", - history.EffectSignerRemoved: "signer_removed", - history.EffectSignerUpdated: "signer_updated", - history.EffectTrustlineCreated: "trustline_created", - history.EffectTrustlineRemoved: "trustline_removed", - history.EffectTrustlineUpdated: "trustline_updated", - history.EffectTrustlineAuthorized: "trustline_authorized", - history.EffectTrustlineDeauthorized: "trustline_deauthorized", - history.EffectOfferCreated: "offer_created", - history.EffectOfferRemoved: "offer_removed", - history.EffectOfferUpdated: "offer_updated", - history.EffectTrade: "trade", - history.EffectDataCreated: "data_created", - history.EffectDataRemoved: "data_removed", - history.EffectDataUpdated: "data_updated", + history.EffectAccountCreated: "account_created", + history.EffectAccountRemoved: "account_removed", + history.EffectAccountCredited: "account_credited", + history.EffectAccountDebited: "account_debited", + history.EffectAccountThresholdsUpdated: "account_thresholds_updated", + history.EffectAccountHomeDomainUpdated: "account_home_domain_updated", + history.EffectAccountFlagsUpdated: "account_flags_updated", + history.EffectAccountInflationDestinationUpdated: "account_inflation_destination_updated", + history.EffectSignerCreated: "signer_created", + history.EffectSignerRemoved: "signer_removed", + history.EffectSignerUpdated: "signer_updated", + history.EffectTrustlineCreated: "trustline_created", + history.EffectTrustlineRemoved: "trustline_removed", + history.EffectTrustlineUpdated: "trustline_updated", + history.EffectTrustlineAuthorized: "trustline_authorized", + history.EffectTrustlineDeauthorized: "trustline_deauthorized", + history.EffectOfferCreated: "offer_created", + history.EffectOfferRemoved: "offer_removed", + history.EffectOfferUpdated: "offer_updated", + history.EffectTrade: "trade", + history.EffectDataCreated: "data_created", + history.EffectDataRemoved: "data_removed", + history.EffectDataUpdated: "data_updated", } // New creates a new effect resource from the provided database representation