diff --git a/integrationtests/nftTransferCrossShard_test.go b/integrationtests/nftTransferCrossShard_test.go index 45c961e7..544549fa 100644 --- a/integrationtests/nftTransferCrossShard_test.go +++ b/integrationtests/nftTransferCrossShard_test.go @@ -451,3 +451,154 @@ func TestNFTTransferCrossShardImportDBScenarioFirstIndexDestinationAfterSource(t string(genericResponse.Docs[0].Source), ) } + +func TestNFTTransferCrossShardImportDBScenarioFirstIndexDestinationAfterSourceSuccess(t *testing.T) { + setLogLevelDebug() + + esClient, err := createESClient(esURL) + require.Nil(t, err) + + esProc, err := CreateElasticProcessor(esClient) + require.Nil(t, err) + + txHash := []byte("nftTransferCross-success") + scrHash1 := []byte("scrHashCross1") + scrHash2 := []byte("scrHashCross2") + header := &dataBlock.Header{ + Round: 50, + TimeStamp: 5040, + } + + address1 := "erd1ure7ea247clj6yqjg80unz6xzjhlj2zwm4gtg6sudcmtsd2cw3xs74hasv" + address2 := "erd1qqqqqqqqqqqqqpgq57szwud2quysucrlq2e97ntdysdl7v4ejz3qn3njq4" + scr2 := &smartContractResult.SmartContractResult{ + Nonce: 0, + GasPrice: 1000000000, + SndAddr: decodeAddress(address1), + RcvAddr: decodeAddress(address2), + Data: []byte("ESDTNFTTransfer@434f4c4c454354494f4e2d323663313838@01@01@08011202000122e50108011204434f4f4c1a20e0f3ecf555f63f2d101241dfc98b4614aff9284edd50b46a1c6e36b83558744d20c4132a2e516d5a7961565631786a7866446255575a503178655a7676544d3156686f61346f594752444d706d4a727a52435a324368747470733a2f2f697066732e696f2f697066732f516d5a7961565631786a7866446255575a503178655a7676544d3156686f61346f594752444d706d4a727a52435a3a41746167733a436f6f6c3b6d657461646174613a516d5869417850396e535948515954546143357358717a4d32645856334142516145355241725932777a4e686179"), + PrevTxHash: txHash, + OriginalTxHash: txHash, + } + + // EXECUTE transfer on the destination shard + bodyDstShard := &dataBlock.Body{ + MiniBlocks: dataBlock.MiniBlockSlice{ + { + Type: dataBlock.SmartContractResultBlock, + SenderShardID: 0, + ReceiverShardID: 1, + TxHashes: [][]byte{scrHash2}, + }, + }, + } + scr3WithErrHash := []byte("scrWithError") + poolDstShard := &outport.TransactionPool{ + SmartContractResults: map[string]*outport.SCRInfo{ + hex.EncodeToString(scrHash2): {SmartContractResult: scr2, FeeInfo: &outport.FeeInfo{}}, + hex.EncodeToString(scr3WithErrHash): {SmartContractResult: &smartContractResult.SmartContractResult{ + SndAddr: decodeAddress(address2), + RcvAddr: decodeAddress(address1), + PrevTxHash: []byte("1546eb9970a6dc1710b6528274e75d5095c1349706f4ff70f52a1f58e1156316"), + OriginalTxHash: txHash, + Data: []byte("ESDTNFTTransfer@434f4c4c454354494f4e2d323663313838@01@01@08011202000122e50108011204434f4f4c1a20e0f3ecf555f63f2d101241dfc98b4614aff9284edd50b46a1c6e36b83558744d20c4132a2e516d5a7961565631786a7866446255575a503178655a7676544d3156686f61346f594752444d706d4a727a52435a324368747470733a2f2f697066732e696f2f697066732f516d5a7961565631786a7866446255575a503178655a7676544d3156686f61346f594752444d706d4a727a52435a3a41746167733a436f6f6c3b6d657461646174613a516d5869417850396e535948515954546143357358717a4d32645856334142516145355241725932777a4e686179@75736572206572726f72"), + }, FeeInfo: &outport.FeeInfo{}}, + }, + Logs: []*outport.LogData{ + { + TxHash: hex.EncodeToString(scr3WithErrHash), + Log: &transaction.Log{ + Address: decodeAddress(address1), + Events: []*transaction.Event{ + { + Address: decodeAddress(address1), + Identifier: []byte(core.CompletedTxEventIdentifier), + }, + }, + }, + }, + }, + } + + ids := []string{hex.EncodeToString(txHash)} + genericResponse := &GenericResponse{} + err = esProc.SaveTransactions(createOutportBlockWithHeader(bodyDstShard, header, poolDstShard, 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/nftTransferCrossShard/tx-nft-transfer-success-destination-first.json"), + string(genericResponse.Docs[0].Source), + ) + + // execute on source + + body := &dataBlock.Body{ + MiniBlocks: dataBlock.MiniBlockSlice{ + { + Type: dataBlock.TxBlock, + SenderShardID: 0, + ReceiverShardID: 0, + TxHashes: [][]byte{txHash}, + }, + { + Type: dataBlock.SmartContractResultBlock, + SenderShardID: 0, + ReceiverShardID: 1, + TxHashes: [][]byte{scrHash2}, + }, + }, + } + + tx := &transaction.Transaction{ + Nonce: 79, + SndAddr: decodeAddress(address1), + RcvAddr: decodeAddress(address1), + GasLimit: 5000000, + GasPrice: 1000000000, + Data: []byte("ESDTNFTTransfer@434f4c4c454354494f4e2d323663313838@01@01@00000000000000000500a7a02771aa07090e607f02b25f4d6d241bff32b990a2"), + Value: big.NewInt(0), + } + + txInfo := &outport.TxInfo{ + Transaction: tx, + FeeInfo: &outport.FeeInfo{ + GasUsed: 963500, + Fee: big.NewInt(238820000000000), + InitialPaidFee: big.NewInt(595490000000000), + }, + ExecutionOrder: 0, + } + + refundValueBig, _ := big.NewInt(0).SetString("40365000000000", 10) + pool := &outport.TransactionPool{ + Transactions: map[string]*outport.TxInfo{ + hex.EncodeToString(txHash): txInfo, + }, + SmartContractResults: map[string]*outport.SCRInfo{ + hex.EncodeToString(scrHash1): {SmartContractResult: &smartContractResult.SmartContractResult{ + Nonce: 80, + Value: refundValueBig, + GasPrice: 1000000000, + SndAddr: decodeAddress(address1), + RcvAddr: decodeAddress(address1), + Data: []byte("@6f6b"), + PrevTxHash: txHash, + OriginalTxHash: txHash, + }, FeeInfo: &outport.FeeInfo{}}, + hex.EncodeToString(scrHash2): {SmartContractResult: scr2, FeeInfo: &outport.FeeInfo{}}, + }, + } + 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/nftTransferCrossShard/tx-nft-transfer-success-source-second.json"), + string(genericResponse.Docs[0].Source), + ) +} diff --git a/integrationtests/testdata/nftTransferCrossShard/tx-nft-transfer-success-destination-first.json b/integrationtests/testdata/nftTransferCrossShard/tx-nft-transfer-success-destination-first.json new file mode 100644 index 00000000..5781ea71 --- /dev/null +++ b/integrationtests/testdata/nftTransferCrossShard/tx-nft-transfer-success-destination-first.json @@ -0,0 +1,22 @@ +{ + "miniBlockHash": "", + "nonce": 0, + "round": 0, + "value": "", + "valueNum": 0, + "receiver": "", + "sender": "", + "receiverShard": 0, + "senderShard": 0, + "gasPrice": 0, + "gasLimit": 0, + "gasUsed": 0, + "fee": "", + "feeNum": 0, + "data": null, + "signature": "", + "timestamp": 0, + "status": "", + "searchOrder": 0, + "completedEvent": true +} diff --git a/integrationtests/testdata/nftTransferCrossShard/tx-nft-transfer-success-source-second.json b/integrationtests/testdata/nftTransferCrossShard/tx-nft-transfer-success-source-second.json new file mode 100644 index 00000000..f30d8dee --- /dev/null +++ b/integrationtests/testdata/nftTransferCrossShard/tx-nft-transfer-success-source-second.json @@ -0,0 +1,40 @@ +{ + "receiversShardIDs": [ + 2 + ], + "data": "RVNEVE5GVFRyYW5zZmVyQDQzNGY0YzRjNDU0MzU0NDk0ZjRlMmQzMjM2NjMzMTM4MzhAMDFAMDFAMDAwMDAwMDAwMDAwMDAwMDA1MDBhN2EwMjc3MWFhMDcwOTBlNjA3ZjAyYjI1ZjRkNmQyNDFiZmYzMmI5OTBhMg==", + "signature": "", + "fee": "238820000000000", + "completedEvent": true, + "esdtValues": [ + "1" + ], + "initialPaidFee": "595490000000000", + "gasLimit": 5000000, + "esdtValuesNum": [ + 1e-18 + ], + "gasUsed": 963500, + "miniBlockHash": "091d7b3e7cd6ceed57ff5aa17a22bb8ffd6df009fc24d89faa7458452708ec69", + "receivers": [ + "erd1qqqqqqqqqqqqqpgq57szwud2quysucrlq2e97ntdysdl7v4ejz3qn3njq4" + ], + "senderShard": 0, + "tokens": [ + "COLLECTION-26c188-01" + ], + "value": "0", + "gasPrice": 1000000000, + "timestamp": 5040, + "receiver": "erd1ure7ea247clj6yqjg80unz6xzjhlj2zwm4gtg6sudcmtsd2cw3xs74hasv", + "valueNum": 0, + "feeNum": 0.00023882, + "nonce": 79, + "round": 50, + "hasScResults": true, + "sender": "erd1ure7ea247clj6yqjg80unz6xzjhlj2zwm4gtg6sudcmtsd2cw3xs74hasv", + "receiverShard": 0, + "operation": "ESDTNFTTransfer", + "status": "success", + "searchOrder": 0 +} diff --git a/process/elasticproc/logsevents/informativeLogsProcessor.go b/process/elasticproc/logsevents/informativeLogsProcessor.go index 3706f708..3e53cbd6 100644 --- a/process/elasticproc/logsevents/informativeLogsProcessor.go +++ b/process/elasticproc/logsevents/informativeLogsProcessor.go @@ -67,16 +67,16 @@ func processEventNoTx(args *argsProcessEvent) argOutputProcessEvent { case core.CompletedTxEventIdentifier: { record.CompletedEvent = true + args.txHashStatusInfoProc.addRecord(scr.OriginalTxHash, record) } case core.SignalErrorOperation, core.InternalVMErrorsOperation: { record.Status = transaction.TxStatusFail.String() record.ErrorEvent = true + args.txHashStatusInfoProc.addRecord(scr.OriginalTxHash, record) } } - args.txHashStatusInfoProc.addRecord(scr.OriginalTxHash, record) - return argOutputProcessEvent{ processed: true, } diff --git a/process/elasticproc/transactions/serialize.go b/process/elasticproc/transactions/serialize.go index 2cab3fc9..bb5db537 100644 --- a/process/elasticproc/transactions/serialize.go +++ b/process/elasticproc/transactions/serialize.go @@ -189,9 +189,18 @@ func prepareNFTESDTTransferOrMultiESDTTransfer(marshaledTx []byte) ([]byte, erro } else { def status = ctx._source.status; def errorEvent = ctx._source.errorEvent; + def completedEvent = ctx._source.completedEvent; + ctx._source = params.tx; - ctx._source.status = status; - ctx._source.errorEvent = errorEvent; + if (!status.isEmpty()) { + ctx._source.status = status; + } + if (errorEvent != null) { + ctx._source.errorEvent = errorEvent; + } + if (completedEvent != null) { + ctx._source.completedEvent = completedEvent; + } } ` serializedData := []byte(fmt.Sprintf(`{"scripted_upsert": true, "script":{"source":"%s","lang": "painless","params":{"tx": %s}},"upsert":{}}`,