Skip to content

Commit

Permalink
Add unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
urvisavla committed Jan 17, 2025
1 parent fe6e1cc commit 40f1a57
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 27 deletions.
57 changes: 30 additions & 27 deletions services/horizon/internal/ingest/processors/operations_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -1047,40 +1047,15 @@ func (operation *transactionOperationWrapper) Participants() ([]xdr.AccountId, e
case xdr.OperationTypeLiquidityPoolWithdraw:
// the only direct participant is the source_account
case xdr.OperationTypeInvokeHostFunction:
changes, err := operation.transaction.GetOperationChanges(operation.index)
if err != nil {
return participants, err
}

for _, change := range changes {
if change.Type == xdr.LedgerEntryTypeAccount || change.Type == xdr.LedgerEntryTypeTrustline {
var data xdr.LedgerEntryData
switch {
case change.Post != nil:
data = change.Post.Data
case change.Pre != nil:
data = change.Pre.Data
default:
log.Errorf("Change Type %s with no pre or post", change.Type.String())
continue
}

switch change.Type {
case xdr.LedgerEntryTypeAccount:
participants = append(participants, data.MustAccount().AccountId)
case xdr.LedgerEntryTypeTrustline:
participants = append(participants, data.MustTrustLine().AccountId)
}
}
}

diagnosticEvents, err := operation.transaction.GetDiagnosticEvents()
if err != nil {
return participants, err
}

for _, contractEvent := range filterEvents(diagnosticEvents) {
if sacEvent, err := contractevents.NewStellarAssetContractEvent(&contractEvent, operation.network); err == nil {

Check failure on line 1056 in services/horizon/internal/ingest/processors/operations_processor.go

View workflow job for this annotation

GitHub Actions / check (ubuntu-22.04, 1.23)

declaration of "err" shadows declaration at line 1050
// 'to' and 'from' fields in these events can be either a Contract address or an Account address. We're
// only interested in account addresses and will skip Contract addresses.
switch sacEvent.GetType() {
case contractevents.EventTypeTransfer:
transferEvt := sacEvent.(*contractevents.TransferEvent)
Expand Down Expand Up @@ -1109,6 +1084,34 @@ func (operation *transactionOperationWrapper) Participants() ([]xdr.AccountId, e
}
}

// The SAC events above should be sufficient to identify the participating accounts. However,
// to be thorough, we will also iterate through the operation Changes to ensure no participants are missed.
changes, err := operation.transaction.GetOperationChanges(operation.index)
if err != nil {
return participants, err
}

for _, change := range changes {
if change.Type == xdr.LedgerEntryTypeAccount || change.Type == xdr.LedgerEntryTypeTrustline {
var data xdr.LedgerEntryData
switch {
case change.Post != nil:
data = change.Post.Data
case change.Pre != nil:
data = change.Pre.Data
default:
log.Errorf("Change Type %s with no pre or post", change.Type.String())
continue
}

switch change.Type {
case xdr.LedgerEntryTypeAccount:
participants = append(participants, data.MustAccount().AccountId)
case xdr.LedgerEntryTypeTrustline:
participants = append(participants, data.MustTrustLine().AccountId)
}
}
}
case xdr.OperationTypeExtendFootprintTtl:
// the only direct participant is the source_account
case xdr.OperationTypeRestoreFootprint:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
package processors

import (
"math/big"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"

"github.com/stellar/go/keypair"
"github.com/stellar/go/protocols/horizon/base"
"github.com/stellar/go/strkey"
"github.com/stellar/go/support/contractevents"

"github.com/stellar/go/ingest"
"github.com/stellar/go/services/horizon/internal/db2/history"
Expand Down Expand Up @@ -2285,3 +2289,110 @@ func TestDetailsCoversAllOperationTypes(t *testing.T) {
_, err := operation.Details()
assert.ErrorContains(t, err, "unknown operation type: ")
}

func TestTestInvokeHostFnOperationParticipants(t *testing.T) {
sourceAddress := "GAUJETIZVEP2NRYLUESJ3LS66NVCEGMON4UDCBCSBEVPIID773P2W6AY"
source := xdr.MustMuxedAddress(sourceAddress)

randomIssuer := keypair.MustRandom()
randomAsset := xdr.MustNewCreditAsset("TESTING", randomIssuer.Address())
passphrase := "passphrase"
randomAccount := keypair.MustRandom().Address()

burnEvtAcc := keypair.MustRandom().Address()
mintEvtAcc := keypair.MustRandom().Address()
clawbkEvtAcc := keypair.MustRandom().Address()
transferEvtFromAcc := keypair.MustRandom().Address()
transferEvtToAcc := keypair.MustRandom().Address()

transferContractEvent := contractevents.GenerateEvent(contractevents.EventTypeTransfer, transferEvtFromAcc, transferEvtToAcc, "", randomAsset, big.NewInt(10000000), passphrase)
mintContractEvent := contractevents.GenerateEvent(contractevents.EventTypeMint, "", mintEvtAcc, randomAccount, randomAsset, big.NewInt(10000000), passphrase)
burnContractEvent := contractevents.GenerateEvent(contractevents.EventTypeBurn, burnEvtAcc, "", randomAccount, randomAsset, big.NewInt(10000000), passphrase)
clawbackContractEvent := contractevents.GenerateEvent(contractevents.EventTypeClawback, clawbkEvtAcc, "", randomAccount, randomAsset, big.NewInt(10000000), passphrase)

tx1 := ingest.LedgerTransaction{
UnsafeMeta: xdr.TransactionMeta{
V: 3,
V3: &xdr.TransactionMetaV3{
SorobanMeta: &xdr.SorobanTransactionMeta{
Events: []xdr.ContractEvent{
transferContractEvent,
burnContractEvent,
mintContractEvent,
clawbackContractEvent,
},
},
},
},
}

wrapper1 := transactionOperationWrapper{
transaction: tx1,
operation: xdr.Operation{
SourceAccount: &source,
Body: xdr.OperationBody{
Type: xdr.OperationTypeInvokeHostFunction,
},
},
network: passphrase,
}

participants, err := wrapper1.Participants()
assert.NoError(t, err)
assert.ElementsMatch(t,
[]xdr.AccountId{
xdr.MustAddress(source.Address()),
xdr.MustAddress(mintEvtAcc),
xdr.MustAddress(burnEvtAcc),
xdr.MustAddress(clawbkEvtAcc),
xdr.MustAddress(transferEvtFromAcc),
xdr.MustAddress(transferEvtToAcc),
},
participants,
)

contractId := [32]byte{}
zeroContractStrKey, err := strkey.Encode(strkey.VersionByteContract, contractId[:])
assert.NoError(t, err)

transferContractEvent = contractevents.GenerateEvent(contractevents.EventTypeTransfer, zeroContractStrKey, zeroContractStrKey, "", randomAsset, big.NewInt(10000000), passphrase)
mintContractEvent = contractevents.GenerateEvent(contractevents.EventTypeMint, "", zeroContractStrKey, randomAccount, randomAsset, big.NewInt(10000000), passphrase)
burnContractEvent = contractevents.GenerateEvent(contractevents.EventTypeBurn, zeroContractStrKey, "", randomAccount, randomAsset, big.NewInt(10000000), passphrase)
clawbackContractEvent = contractevents.GenerateEvent(contractevents.EventTypeClawback, zeroContractStrKey, "", randomAccount, randomAsset, big.NewInt(10000000), passphrase)

tx2 := ingest.LedgerTransaction{
UnsafeMeta: xdr.TransactionMeta{
V: 3,
V3: &xdr.TransactionMetaV3{
SorobanMeta: &xdr.SorobanTransactionMeta{
Events: []xdr.ContractEvent{
transferContractEvent,
burnContractEvent,
mintContractEvent,
clawbackContractEvent,
},
},
},
},
}

wrapper2 := transactionOperationWrapper{
transaction: tx2,
operation: xdr.Operation{
SourceAccount: &source,
Body: xdr.OperationBody{
Type: xdr.OperationTypeInvokeHostFunction,
},
},
network: passphrase,
}

participants, err = wrapper2.Participants()
assert.NoError(t, err)
assert.ElementsMatch(t,
[]xdr.AccountId{
xdr.MustAddress(source.Address()),
},
participants,
)
}

0 comments on commit 40f1a57

Please sign in to comment.