diff --git a/ingest/ledger_transaction.go b/ingest/ledger_transaction.go index f582ff021f..1a348f9683 100644 --- a/ingest/ledger_transaction.go +++ b/ingest/ledger_transaction.go @@ -153,7 +153,7 @@ func operationChanges(ops []xdr.OperationMeta, index uint32) []Change { } // GetOperationEvents returns all contract events emitted by a given operation. -func (t *LedgerTransaction) GetOperationEvents(operationIndex uint32) ([]xdr.ContractEvent, error) { +func (t *LedgerTransaction) GetOperationEvents(operationIndex uint32) ([]xdr.DiagnosticEvent, error) { // Ignore operations meta if txInternalError https://github.com/stellar/go/issues/2111 if t.txInternalError() { return nil, nil @@ -167,18 +167,21 @@ func (t *LedgerTransaction) GetOperationEvents(operationIndex uint32) ([]xdr.Con case 3: diagnosticEventsByOperation := t.UnsafeMeta.MustV3().DiagnosticEvents if int(operationIndex) < len(diagnosticEventsByOperation) { - diagnosticEvents := diagnosticEventsByOperation[operationIndex].Events - events := make([]xdr.ContractEvent, len(diagnosticEvents)) - for i, d := range diagnosticEvents { - events[i] = d.Event - } - return events, nil + return diagnosticEventsByOperation[operationIndex].Events, nil } eventsByOperation := t.UnsafeMeta.MustV3().Events if int(operationIndex) >= len(eventsByOperation) { return nil, nil } - return eventsByOperation[operationIndex].Events, nil + events := eventsByOperation[operationIndex].Events + diagnosticEvents := make([]xdr.DiagnosticEvent, len(events)) + for i, event := range events { + diagnosticEvents[i] = xdr.DiagnosticEvent{ + InSuccessfulContractCall: true, + Event: event, + } + } + return diagnosticEvents, nil default: return nil, fmt.Errorf("unsupported TransactionMeta version: %v", t.UnsafeMeta.V) } diff --git a/ingest/ledger_transaction_test.go b/ingest/ledger_transaction_test.go index 719d9d4dd0..630a341022 100644 --- a/ingest/ledger_transaction_test.go +++ b/ingest/ledger_transaction_test.go @@ -70,7 +70,8 @@ func TestGetOperationEvents(t *testing.T) { events, err := tx.GetOperationEvents(0) assert.NoError(t, err) assert.Len(t, events, 1) - assert.Equal(t, *events[0].Body.V0.Data.U32, values[0]) + assert.True(t, events[0].InSuccessfulContractCall) + assert.Equal(t, *events[0].Event.Body.V0.Data.U32, values[0]) events, err = tx.GetOperationEvents(1) assert.NoError(t, err) @@ -79,8 +80,10 @@ func TestGetOperationEvents(t *testing.T) { events, err = tx.GetOperationEvents(2) assert.NoError(t, err) assert.Len(t, events, 2) - assert.Equal(t, *events[0].Body.V0.Data.U32, values[1]) - assert.Equal(t, *events[1].Body.V0.Data.U32, values[2]) + assert.True(t, events[0].InSuccessfulContractCall) + assert.Equal(t, *events[0].Event.Body.V0.Data.U32, values[1]) + assert.True(t, events[1].InSuccessfulContractCall) + assert.Equal(t, *events[1].Event.Body.V0.Data.U32, values[2]) events, err = tx.GetOperationEvents(3) assert.NoError(t, err) @@ -162,7 +165,8 @@ func TestGetDiagnosticEvents(t *testing.T) { events, err := tx.GetOperationEvents(0) assert.NoError(t, err) assert.Len(t, events, 1) - assert.Equal(t, *events[0].Body.V0.Data.U32, values[0]) + assert.False(t, events[0].InSuccessfulContractCall) + assert.Equal(t, *events[0].Event.Body.V0.Data.U32, values[0]) events, err = tx.GetOperationEvents(1) assert.NoError(t, err) @@ -171,8 +175,10 @@ func TestGetDiagnosticEvents(t *testing.T) { events, err = tx.GetOperationEvents(2) assert.NoError(t, err) assert.Len(t, events, 2) - assert.Equal(t, *events[0].Body.V0.Data.U32, values[1]) - assert.Equal(t, *events[1].Body.V0.Data.U32, values[2]) + assert.True(t, events[0].InSuccessfulContractCall) + assert.Equal(t, *events[0].Event.Body.V0.Data.U32, values[1]) + assert.True(t, events[1].InSuccessfulContractCall) + assert.Equal(t, *events[1].Event.Body.V0.Data.U32, values[2]) events, err = tx.GetOperationEvents(3) assert.NoError(t, err) diff --git a/services/horizon/internal/ingest/processors/effects_processor.go b/services/horizon/internal/ingest/processors/effects_processor.go index 096111decd..07135dc456 100644 --- a/services/horizon/internal/ingest/processors/effects_processor.go +++ b/services/horizon/internal/ingest/processors/effects_processor.go @@ -236,14 +236,14 @@ func (operation *transactionOperationWrapper) effects() ([]effect, error) { case xdr.OperationTypeInvokeHostFunction: // If there's an invokeHostFunction operation, there's definitely V3 // meta in the transaction, which means this error is real. - events, innerErr := operation.transaction.GetOperationEvents(operation.index) + diagnosticEvents, innerErr := operation.transaction.GetOperationEvents(operation.index) if innerErr != nil { return nil, innerErr } // For now, the only effects are related to the events themselves. // Possible add'l work: https://github.com/stellar/go/issues/4585 - err = wrapper.addInvokeHostFunctionEffects(events) + err = wrapper.addInvokeHostFunctionEffects(filterEvents(diagnosticEvents)) default: return nil, fmt.Errorf("unknown operation type: %s", op.Body.Type) @@ -274,6 +274,17 @@ func (operation *transactionOperationWrapper) effects() ([]effect, error) { return wrapper.effects, nil } +func filterEvents(diagnosticEvents []xdr.DiagnosticEvent) []xdr.ContractEvent { + var filtered []xdr.ContractEvent + for _, diagnosticEvent := range diagnosticEvents { + if !diagnosticEvent.InSuccessfulContractCall || diagnosticEvent.Event.Type != xdr.ContractEventTypeContract { + continue + } + filtered = append(filtered, diagnosticEvent.Event) + } + return filtered +} + type effectsWrapper struct { effects []effect operation *transactionOperationWrapper diff --git a/services/horizon/internal/ingest/processors/operations_processor.go b/services/horizon/internal/ingest/processors/operations_processor.go index ac52f9c068..2d669732ca 100644 --- a/services/horizon/internal/ingest/processors/operations_processor.go +++ b/services/horizon/internal/ingest/processors/operations_processor.go @@ -268,13 +268,13 @@ func (operation *transactionOperationWrapper) IsPayment() bool { case xdr.OperationTypeAccountMerge: return true case xdr.OperationTypeInvokeHostFunction: - events, err := operation.transaction.GetOperationEvents(0) + diagnosticEvents, err := operation.transaction.GetOperationEvents(operation.index) if err != nil { return false } // scan all the contract events for at least one SAC event, qualified to be a payment // in horizon - for _, contractEvent := range events { + for _, contractEvent := range filterEvents(diagnosticEvents) { if sacEvent, err := contractevents.NewStellarAssetContractEvent(&contractEvent, operation.network); err == nil { switch sacEvent.GetType() { case contractevents.EventTypeTransfer: @@ -719,14 +719,14 @@ func (operation *transactionOperationWrapper) Details() (map[string]interface{}, func (operation *transactionOperationWrapper) parseAssetBalanceChangesFromContractEvents() ([]map[string]interface{}, error) { balanceChanges := []map[string]interface{}{} - events, err := operation.transaction.GetOperationEvents(0) + diagnosticEvents, err := operation.transaction.GetOperationEvents(operation.index) if err != nil { // this operation in this context must be an InvokeHostFunctionOp, therefore V3Meta should be present // as it's in same soroban model, so if any err, it's real, return nil, err } - for _, contractEvent := range events { + for _, contractEvent := range filterEvents(diagnosticEvents) { // Parse the xdr contract event to contractevents.StellarAssetContractEvent model // has some convenience like to/from attributes are expressed in strkey format for accounts(G...) and contracts(C...)