From b1cd8050835663f0d57862023fdbbcc814b4dcdd Mon Sep 17 00:00:00 2001 From: miiu Date: Wed, 7 Aug 2024 12:41:19 +0300 Subject: [PATCH] fix transaction status --- integrationtests/relayedTxV3_test.go | 274 +++++++++++++++++- .../relayed-tx-v3-with-events.json | 70 +++++ .../relayed-v3-execution-scr-on-dest.json | 58 ++++ .../relayed-v3-execution-source.json | 57 ++++ .../logsevents/informativeLogsProcessor.go | 5 + process/elasticproc/transactions/serialize.go | 4 + 6 files changed, 466 insertions(+), 2 deletions(-) create mode 100644 integrationtests/testdata/relayedTxV3/relayed-tx-v3-with-events.json create mode 100644 integrationtests/testdata/relayedTxV3/relayed-v3-execution-scr-on-dest.json create mode 100644 integrationtests/testdata/relayedTxV3/relayed-v3-execution-source.json diff --git a/integrationtests/relayedTxV3_test.go b/integrationtests/relayedTxV3_test.go index d492c753..e440c215 100644 --- a/integrationtests/relayedTxV3_test.go +++ b/integrationtests/relayedTxV3_test.go @@ -5,13 +5,16 @@ package integrationtests import ( "context" "encoding/hex" + "math/big" + "testing" + + "github.com/multiversx/mx-chain-core-go/core" dataBlock "github.com/multiversx/mx-chain-core-go/data/block" "github.com/multiversx/mx-chain-core-go/data/outport" + "github.com/multiversx/mx-chain-core-go/data/smartContractResult" "github.com/multiversx/mx-chain-core-go/data/transaction" indexerdata "github.com/multiversx/mx-chain-es-indexer-go/process/dataindexer" "github.com/stretchr/testify/require" - "math/big" - "testing" ) func TestRelayedTxV3(t *testing.T) { @@ -97,3 +100,270 @@ func TestRelayedTxV3(t *testing.T) { string(genericResponse.Docs[0].Source), ) } + +func TestRelayedTxV3WithSignalErrorAndCompletedEvent(t *testing.T) { + setLogLevelDebug() + + esClient, err := createESClient(esURL) + require.Nil(t, err) + + esProc, err := CreateElasticProcessor(esClient) + require.Nil(t, err) + + txHash := []byte("relayedTxV3WithSignalErrorAndCompletedEvent") + header := &dataBlock.Header{ + Round: 50, + TimeStamp: 5040, + } + + body := &dataBlock.Body{ + MiniBlocks: dataBlock.MiniBlockSlice{ + { + Type: dataBlock.TxBlock, + SenderShardID: 0, + ReceiverShardID: 0, + TxHashes: [][]byte{txHash}, + }, + }, + } + + initialTx := &transaction.Transaction{ + Nonce: 1000, + SndAddr: decodeAddress("erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a"), + RcvAddr: decodeAddress("erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a"), + GasLimit: 300_000, + GasPrice: 1000000000, + Value: big.NewInt(0), + InnerTransactions: []*transaction.Transaction{ + { + Nonce: 5, + SndAddr: decodeAddress("erd10ksryjr065ad5475jcg82pnjfg9j9qtszjsrp24anl6ym7cmeddshwnru8"), + RcvAddr: decodeAddress("erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r"), + GasLimit: 50_000, + GasPrice: 1000000000, + Value: big.NewInt(10000000000000000), + }, + { + Nonce: 3, + SndAddr: decodeAddress("erd10ksryjr065ad5475jcg82pnjfg9j9qtszjsrp24anl6ym7cmeddshwnru8"), + RcvAddr: decodeAddress("erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r"), + GasLimit: 50_000, + GasPrice: 1000000000, + Value: big.NewInt(10000000000000000), + }, + { + Nonce: 4, + SndAddr: decodeAddress("erd10ksryjr065ad5475jcg82pnjfg9j9qtszjsrp24anl6ym7cmeddshwnru8"), + RcvAddr: decodeAddress("erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r"), + GasLimit: 50_000, + GasPrice: 1000000000, + Value: big.NewInt(10000000000000000), + }, + }, + } + + txInfo := &outport.TxInfo{ + Transaction: initialTx, + FeeInfo: &outport.FeeInfo{ + GasUsed: 10556000, + Fee: big.NewInt(2257820000000000), + InitialPaidFee: big.NewInt(2306320000000000), + }, + ExecutionOrder: 0, + } + + pool := &outport.TransactionPool{ + Transactions: map[string]*outport.TxInfo{ + hex.EncodeToString(txHash): txInfo, + }, + Logs: []*outport.LogData{ + { + TxHash: hex.EncodeToString(txHash), + Log: &transaction.Log{ + Address: decodeAddress("erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a"), + Events: []*transaction.Event{ + { + Address: decodeAddress("erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a"), + Identifier: []byte(core.CompletedTxEventIdentifier), + Topics: [][]byte{[]byte("t1"), []byte("t2")}, + }, + nil, + }, + }, + }, + { + TxHash: hex.EncodeToString(txHash), + Log: &transaction.Log{ + Address: decodeAddress("erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a"), + Events: []*transaction.Event{ + { + Address: decodeAddress("erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a"), + Identifier: []byte(core.SignalErrorOperation), + Topics: [][]byte{[]byte("t1"), []byte("t2")}, + }, + nil, + }, + }, + }, + }, + } + err = esProc.SaveTransactions(createOutportBlockWithHeader(body, header, pool, nil, testNumOfShards)) + require.Nil(t, err) + + ids := []string{hex.EncodeToString(txHash)} + genericResponse := &GenericResponse{} + err = esClient.DoMultiGet(context.Background(), ids, indexerdata.TransactionsIndex, true, genericResponse) + require.Nil(t, err) + + require.JSONEq(t, + readExpectedResult("./testdata/relayedTxV3/relayed-tx-v3-with-events.json"), + string(genericResponse.Docs[0].Source), + ) +} + +func TestRelayedV3WithSCRCross(t *testing.T) { + setLogLevelDebug() + + esClient, err := createESClient(esURL) + require.Nil(t, err) + + esProc, err := CreateElasticProcessor(esClient) + require.Nil(t, err) + + txHash := []byte("relayedTxV3WithScrCross") + header := &dataBlock.Header{ + Round: 50, + TimeStamp: 5040, + } + + body := &dataBlock.Body{ + MiniBlocks: dataBlock.MiniBlockSlice{ + { + Type: dataBlock.TxBlock, + SenderShardID: 0, + ReceiverShardID: 0, + TxHashes: [][]byte{txHash}, + }, + }, + } + + initialTx := &transaction.Transaction{ + Nonce: 1000, + SndAddr: decodeAddress("erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a"), + RcvAddr: decodeAddress("erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a"), + GasLimit: 300_000, + GasPrice: 1000000000, + Value: big.NewInt(0), + InnerTransactions: []*transaction.Transaction{ + { + Nonce: 5, + SndAddr: decodeAddress("erd10ksryjr065ad5475jcg82pnjfg9j9qtszjsrp24anl6ym7cmeddshwnru8"), + RcvAddr: decodeAddress("erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r"), + GasLimit: 50_000, + GasPrice: 1000000000, + Value: big.NewInt(10000000000000000), + }, + { + Nonce: 3, + SndAddr: decodeAddress("erd10ksryjr065ad5475jcg82pnjfg9j9qtszjsrp24anl6ym7cmeddshwnru8"), + RcvAddr: decodeAddress("erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r"), + GasLimit: 50_000, + GasPrice: 1000000000, + Value: big.NewInt(10000000000000000), + }, + }, + } + + txInfo := &outport.TxInfo{ + Transaction: initialTx, + FeeInfo: &outport.FeeInfo{ + GasUsed: 10556000, + Fee: big.NewInt(2257820000000000), + InitialPaidFee: big.NewInt(2306320000000000), + }, + ExecutionOrder: 0, + } + + pool := &outport.TransactionPool{ + Transactions: map[string]*outport.TxInfo{ + hex.EncodeToString(txHash): txInfo, + }, + Logs: []*outport.LogData{ + { + TxHash: hex.EncodeToString(txHash), + Log: &transaction.Log{ + Address: decodeAddress("erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a"), + Events: []*transaction.Event{ + { + Address: decodeAddress("erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a"), + Identifier: []byte(core.CompletedTxEventIdentifier), + Topics: [][]byte{[]byte("t1"), []byte("t2")}, + }, + nil, + }, + }, + }, + }, + } + err = esProc.SaveTransactions(createOutportBlockWithHeader(body, header, pool, nil, testNumOfShards)) + require.Nil(t, err) + + ids := []string{hex.EncodeToString(txHash)} + genericResponse := &GenericResponse{} + err = esClient.DoMultiGet(context.Background(), ids, indexerdata.TransactionsIndex, true, genericResponse) + require.Nil(t, err) + + require.JSONEq(t, + readExpectedResult("./testdata/relayedTxV3/relayed-v3-execution-source.json"), + string(genericResponse.Docs[0].Source), + ) + + // execute scr on destination + header = &dataBlock.Header{ + Round: 60, + TimeStamp: 6040, + } + + scrInfo := &outport.SCRInfo{ + SmartContractResult: &smartContractResult.SmartContractResult{ + OriginalTxHash: txHash, + }, + FeeInfo: &outport.FeeInfo{ + Fee: big.NewInt(0), + InitialPaidFee: big.NewInt(0), + }, + ExecutionOrder: 0, + } + + pool = &outport.TransactionPool{ + SmartContractResults: map[string]*outport.SCRInfo{ + hex.EncodeToString([]byte("scr")): scrInfo, + }, + Logs: []*outport.LogData{ + { + TxHash: hex.EncodeToString([]byte("scr")), + Log: &transaction.Log{ + Address: decodeAddress("erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a"), + Events: []*transaction.Event{ + { + Address: decodeAddress("erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a"), + Identifier: []byte(core.SignalErrorOperation), + Topics: [][]byte{[]byte("t1"), []byte("t2")}, + }, + nil, + }, + }, + }, + }, + } + err = esProc.SaveTransactions(createOutportBlockWithHeader(body, header, pool, nil, testNumOfShards)) + require.Nil(t, err) + + err = esClient.DoMultiGet(context.Background(), ids, indexerdata.TransactionsIndex, true, genericResponse) + require.Nil(t, err) + + require.JSONEq(t, + readExpectedResult("./testdata/relayedTxV3/relayed-v3-execution-scr-on-dest.json"), + string(genericResponse.Docs[0].Source), + ) +} diff --git a/integrationtests/testdata/relayedTxV3/relayed-tx-v3-with-events.json b/integrationtests/testdata/relayedTxV3/relayed-tx-v3-with-events.json new file mode 100644 index 00000000..f60cafb2 --- /dev/null +++ b/integrationtests/testdata/relayedTxV3/relayed-tx-v3-with-events.json @@ -0,0 +1,70 @@ +{ + "miniBlockHash": "2b8a2e2b21d1cf1c5e3d782552810a07818e6b179dd196e901466bb588fc387a", + "nonce": 1000, + "round": 50, + "value": "0", + "valueNum": 0, + "receiver": "erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a", + "sender": "erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a", + "receiverShard": 0, + "senderShard": 0, + "gasPrice": 1000000000, + "gasLimit": 300000, + "gasUsed": 10556000, + "fee": "2257820000000000", + "feeNum": 0.00225782, + "initialPaidFee": "2306320000000000", + "data": null, + "signature": "", + "timestamp": 5040, + "status": "success", + "searchOrder": 0, + "hasOperations": true, + "hasLogs": true, + "receivers": [ + "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r", + "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r", + "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r" + ], + "receiversShardIDs": [ + 1, + 1, + 1 + ], + "operation": "transfer", + "isRelayed": true, + "errorEvent": true, + "completedEvent": true, + "innerTransactions": [ + { + "nonce": 5, + "value": "10000000000000000", + "receiver": "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r", + "sender": "erd10ksryjr065ad5475jcg82pnjfg9j9qtszjsrp24anl6ym7cmeddshwnru8", + "gasPrice": 1000000000, + "gasLimit": 50000, + "chainID": "", + "version": 0 + }, + { + "nonce": 3, + "value": "10000000000000000", + "receiver": "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r", + "sender": "erd10ksryjr065ad5475jcg82pnjfg9j9qtszjsrp24anl6ym7cmeddshwnru8", + "gasPrice": 1000000000, + "gasLimit": 50000, + "chainID": "", + "version": 0 + }, + { + "nonce": 4, + "value": "10000000000000000", + "receiver": "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r", + "sender": "erd10ksryjr065ad5475jcg82pnjfg9j9qtszjsrp24anl6ym7cmeddshwnru8", + "gasPrice": 1000000000, + "gasLimit": 50000, + "chainID": "", + "version": 0 + } + ] +} diff --git a/integrationtests/testdata/relayedTxV3/relayed-v3-execution-scr-on-dest.json b/integrationtests/testdata/relayedTxV3/relayed-v3-execution-scr-on-dest.json new file mode 100644 index 00000000..e525f876 --- /dev/null +++ b/integrationtests/testdata/relayedTxV3/relayed-v3-execution-scr-on-dest.json @@ -0,0 +1,58 @@ +{ + "miniBlockHash": "5fba08d48700058cf2789651a50ebaa35ee559ce51ee43a709943c6a4f763d25", + "nonce": 1000, + "round": 50, + "value": "0", + "valueNum": 0, + "receiver": "erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a", + "sender": "erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a", + "receiverShard": 0, + "senderShard": 0, + "gasPrice": 1000000000, + "gasLimit": 300000, + "gasUsed": 10556000, + "fee": "2257820000000000", + "feeNum": 0.00225782, + "initialPaidFee": "2306320000000000", + "data": null, + "signature": "", + "timestamp": 5040, + "status": "success", + "searchOrder": 0, + "hasOperations": true, + "hasLogs": true, + "receivers": [ + "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r", + "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r" + ], + "receiversShardIDs": [ + 1, + 1 + ], + "operation": "transfer", + "isRelayed": true, + "completedEvent": true, + "errorEvent": true, + "innerTransactions": [ + { + "nonce": 5, + "value": "10000000000000000", + "receiver": "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r", + "sender": "erd10ksryjr065ad5475jcg82pnjfg9j9qtszjsrp24anl6ym7cmeddshwnru8", + "gasPrice": 1000000000, + "gasLimit": 50000, + "chainID": "", + "version": 0 + }, + { + "nonce": 3, + "value": "10000000000000000", + "receiver": "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r", + "sender": "erd10ksryjr065ad5475jcg82pnjfg9j9qtszjsrp24anl6ym7cmeddshwnru8", + "gasPrice": 1000000000, + "gasLimit": 50000, + "chainID": "", + "version": 0 + } + ] +} diff --git a/integrationtests/testdata/relayedTxV3/relayed-v3-execution-source.json b/integrationtests/testdata/relayedTxV3/relayed-v3-execution-source.json new file mode 100644 index 00000000..e9d692b7 --- /dev/null +++ b/integrationtests/testdata/relayedTxV3/relayed-v3-execution-source.json @@ -0,0 +1,57 @@ +{ + "miniBlockHash": "5fba08d48700058cf2789651a50ebaa35ee559ce51ee43a709943c6a4f763d25", + "nonce": 1000, + "round": 50, + "value": "0", + "valueNum": 0, + "receiver": "erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a", + "sender": "erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a", + "receiverShard": 0, + "senderShard": 0, + "gasPrice": 1000000000, + "gasLimit": 300000, + "gasUsed": 10556000, + "fee": "2257820000000000", + "feeNum": 0.00225782, + "initialPaidFee": "2306320000000000", + "data": null, + "signature": "", + "timestamp": 5040, + "status": "success", + "searchOrder": 0, + "hasOperations": true, + "hasLogs": true, + "receivers": [ + "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r", + "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r" + ], + "receiversShardIDs": [ + 1, + 1 + ], + "operation": "transfer", + "isRelayed": true, + "completedEvent": true, + "innerTransactions": [ + { + "nonce": 5, + "value": "10000000000000000", + "receiver": "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r", + "sender": "erd10ksryjr065ad5475jcg82pnjfg9j9qtszjsrp24anl6ym7cmeddshwnru8", + "gasPrice": 1000000000, + "gasLimit": 50000, + "chainID": "", + "version": 0 + }, + { + "nonce": 3, + "value": "10000000000000000", + "receiver": "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r", + "sender": "erd10ksryjr065ad5475jcg82pnjfg9j9qtszjsrp24anl6ym7cmeddshwnru8", + "gasPrice": 1000000000, + "gasLimit": 50000, + "chainID": "", + "version": 0 + } + ] +} diff --git a/process/elasticproc/logsevents/informativeLogsProcessor.go b/process/elasticproc/logsevents/informativeLogsProcessor.go index 3e53cbd6..8058d412 100644 --- a/process/elasticproc/logsevents/informativeLogsProcessor.go +++ b/process/elasticproc/logsevents/informativeLogsProcessor.go @@ -49,6 +49,11 @@ func (ilp *informativeLogsProcessor) processEvent(args *argsProcessEvent) argOut } } + setSuccess := tx.CompletedEvent && tx.ErrorEvent + if setSuccess { + tx.Status = transaction.TxStatusSuccess.String() + } + return argOutputProcessEvent{ processed: true, } diff --git a/process/elasticproc/transactions/serialize.go b/process/elasticproc/transactions/serialize.go index 0c3a8803..e913c579 100644 --- a/process/elasticproc/transactions/serialize.go +++ b/process/elasticproc/transactions/serialize.go @@ -136,6 +136,10 @@ func serializeTxHashStatus(buffSlice *data.BufferSlice, txHashStatusInfo map[str if (params.statusInfo.errorEvent) { ctx._source.errorEvent = params.statusInfo.errorEvent; } + + if ((ctx._source.completedEvent) && (ctx._source.errorEvent)) { + ctx._source.status = 'success'; + } ` serializedData := []byte(fmt.Sprintf(`{"script": {"source": "%s","lang": "painless","params": {"statusInfo": %s}}, "upsert": %s }`, converters.FormatPainlessSource(codeToExecute), string(marshaledStatusInfo), string(marshaledTx))) err = buffSlice.PutData(metaData, serializedData)