diff --git a/api/groups/baseTransactionGroup.go b/api/groups/baseTransactionGroup.go index b22bee3e..d8fc64e0 100644 --- a/api/groups/baseTransactionGroup.go +++ b/api/groups/baseTransactionGroup.go @@ -36,6 +36,7 @@ func NewTransactionGroup(facadeHandler data.FacadeHandler) (*transactionGroup, e {Path: "/send-user-funds", Handler: tg.sendUserFunds, Method: http.MethodPost}, {Path: "/cost", Handler: tg.requestTransactionCost, Method: http.MethodPost}, {Path: "/:txhash/status", Handler: tg.getTransactionStatus, Method: http.MethodGet}, + {Path: "/:txhash/process-status", Handler: tg.getProcessedTransactionStatus, Method: http.MethodGet}, {Path: "/:txhash", Handler: tg.getTransaction, Method: http.MethodGet}, {Path: "/pool", Handler: tg.getTransactionsPool, Method: http.MethodGet}, } @@ -247,6 +248,22 @@ func (group *transactionGroup) getTransaction(c *gin.Context) { shared.RespondWith(c, http.StatusOK, gin.H{"transaction": tx}, "", data.ReturnCodeSuccess) } +func (group *transactionGroup) getProcessedTransactionStatus(c *gin.Context) { + txHash := c.Param("txhash") + if txHash == "" { + shared.RespondWith(c, http.StatusBadRequest, nil, errors.ErrTransactionHashMissing.Error(), data.ReturnCodeRequestError) + return + } + + status, err := group.facade.GetProcessedTransactionStatus(txHash) + if err != nil { + shared.RespondWith(c, http.StatusInternalServerError, nil, err.Error(), data.ReturnCodeInternalError) + return + } + + shared.RespondWith(c, http.StatusOK, gin.H{"transaction": status}, "", data.ReturnCodeSuccess) +} + func getTransactionByHashAndSenderAddress(c *gin.Context, ef TransactionFacadeHandler, txHash string, sndAddr string, withEvents bool) { tx, statusCode, err := ef.GetTransactionByHashAndSenderAddress(txHash, sndAddr, withEvents) if err != nil { diff --git a/api/groups/baseTransactionGroup_test.go b/api/groups/baseTransactionGroup_test.go index b23d75d1..7301ddad 100644 --- a/api/groups/baseTransactionGroup_test.go +++ b/api/groups/baseTransactionGroup_test.go @@ -71,6 +71,13 @@ type nonceGapsResp struct { Data nonceGaps } +type txProcessedStatusResp struct { + GeneralResponse + Data struct { + TransactionHash string `json:"transaction"` + } `json:"data"` +} + func TestNewTransactionGroup_WrongFacadeShouldErr(t *testing.T) { wrongFacade := &mock.WrongFacade{} group, err := groups.NewTransactionGroup(wrongFacade) @@ -741,3 +748,78 @@ func TestGetTransactionsPoolPoolNonceGapsForSender_ReturnsSuccessfully(t *testin assert.Equal(t, response.Error, "") assert.Equal(t, providedNonceGaps, &response.Data.NonceGaps) } + +func TestTransactionGroup_getProcessedTransactionStatus(t *testing.T) { + t.Parallel() + + expectedErr := errors.New("expected error") + hash := "hash" + t.Run("no tx hash provided, should error", func(t *testing.T) { + t.Parallel() + + transactionsGroup, err := groups.NewTransactionGroup(&mock.FacadeStub{}) + require.NoError(t, err) + ws := startProxyServer(transactionsGroup, transactionsPath) + + req, _ := http.NewRequest("GET", "/transaction//process-status", nil) + + resp := httptest.NewRecorder() + ws.ServeHTTP(resp, req) + + response := GeneralResponse{} + loadResponse(resp.Body, &response) + + assert.Equal(t, http.StatusBadRequest, resp.Code) + assert.Equal(t, apiErrors.ErrTransactionHashMissing.Error(), response.Error) + }) + t.Run("GetProcessedTransactionStatus errors, should error", func(t *testing.T) { + t.Parallel() + + facade := &mock.FacadeStub{ + GetProcessedTransactionStatusHandler: func(txHash string) (string, error) { + assert.Equal(t, hash, txHash) + return "", expectedErr + }, + } + transactionsGroup, err := groups.NewTransactionGroup(facade) + require.NoError(t, err) + ws := startProxyServer(transactionsGroup, transactionsPath) + + req, _ := http.NewRequest("GET", "/transaction/"+hash+"/process-status", nil) + + resp := httptest.NewRecorder() + ws.ServeHTTP(resp, req) + + response := GeneralResponse{} + loadResponse(resp.Body, &response) + + assert.Equal(t, http.StatusInternalServerError, resp.Code) + assert.Equal(t, expectedErr.Error(), response.Error) + }) + t.Run("should work", func(t *testing.T) { + t.Parallel() + + status := "status" + facade := &mock.FacadeStub{ + GetProcessedTransactionStatusHandler: func(txHash string) (string, error) { + assert.Equal(t, hash, txHash) + return status, nil + }, + } + transactionsGroup, err := groups.NewTransactionGroup(facade) + require.NoError(t, err) + ws := startProxyServer(transactionsGroup, transactionsPath) + + req, _ := http.NewRequest("GET", "/transaction/"+hash+"/process-status", nil) + + resp := httptest.NewRecorder() + ws.ServeHTTP(resp, req) + + response := txProcessedStatusResp{} + loadResponse(resp.Body, &response) + + assert.Equal(t, http.StatusOK, resp.Code) + assert.Empty(t, response.Error) + assert.Equal(t, status, response.Data.TransactionHash) + }) +} diff --git a/api/groups/interface.go b/api/groups/interface.go index abee0212..f893a4a0 100644 --- a/api/groups/interface.go +++ b/api/groups/interface.go @@ -97,6 +97,7 @@ type TransactionFacadeHandler interface { SendUserFunds(receiver string, value *big.Int) error TransactionCostRequest(tx *data.Transaction) (*data.TxCostResponseData, error) GetTransactionStatus(txHash string, sender string) (string, error) + GetProcessedTransactionStatus(txHash string) (string, error) GetTransaction(txHash string, withResults bool) (*transaction.ApiTransactionResult, error) GetTransactionByHashAndSenderAddress(txHash string, sndAddr string, withEvents bool) (*transaction.ApiTransactionResult, int, error) GetTransactionsPool(fields string) (*data.TransactionsPool, error) diff --git a/api/mock/facadeStub.go b/api/mock/facadeStub.go index 8bf1abae..0d85840f 100644 --- a/api/mock/facadeStub.go +++ b/api/mock/facadeStub.go @@ -38,6 +38,7 @@ type FacadeStub struct { ValidatorStatisticsHandler func() (map[string]*data.ValidatorApiResponse, error) TransactionCostRequestHandler func(tx *data.Transaction) (*data.TxCostResponseData, error) GetTransactionStatusHandler func(txHash string, sender string) (string, error) + GetProcessedTransactionStatusHandler func(txHash string) (string, error) GetConfigMetricsHandler func() (*data.GenericAPIResponse, error) GetNetworkMetricsHandler func(shardID uint32) (*data.GenericAPIResponse, error) GetAllIssuedESDTsHandler func(tokenType string) (*data.GenericAPIResponse, error) @@ -400,6 +401,11 @@ func (f *FacadeStub) GetTransactionStatus(txHash string, sender string) (string, return f.GetTransactionStatusHandler(txHash, sender) } +// GetProcessedTransactionStatus - +func (f *FacadeStub) GetProcessedTransactionStatus(txHash string) (string, error) { + return f.GetProcessedTransactionStatusHandler(txHash) +} + // SendUserFunds - func (f *FacadeStub) SendUserFunds(receiver string, value *big.Int) error { return f.SendUserFundsCalled(receiver, value) diff --git a/cmd/proxy/config/apiConfig/v1_0.toml b/cmd/proxy/config/apiConfig/v1_0.toml index 05d7f38a..d5220eb7 100644 --- a/cmd/proxy/config/apiConfig/v1_0.toml +++ b/cmd/proxy/config/apiConfig/v1_0.toml @@ -95,6 +95,7 @@ Routes = [ { Name = "/cost", Open = true, Secured = false, RateLimit = 0 }, { Name = "/:txhash", Open = true, Secured = false, RateLimit = 0 }, { Name = "/:txhash/status", Open = true, Secured = false, RateLimit = 0 }, + { Name = "/:txhash/process-status", Open = true, Secured = false, RateLimit = 0 }, { Name = "/pool", Open = true, Secured = false, RateLimit = 0 } ] diff --git a/cmd/proxy/config/apiConfig/v_next.toml b/cmd/proxy/config/apiConfig/v_next.toml index 37915aa0..41d9e348 100644 --- a/cmd/proxy/config/apiConfig/v_next.toml +++ b/cmd/proxy/config/apiConfig/v_next.toml @@ -95,6 +95,7 @@ Routes = [ { Name = "/cost", Open = true, Secured = false, RateLimit = 0 }, { Name = "/:txhash", Open = true, Secured = false, RateLimit = 0 }, { Name = "/:txhash/status", Open = true, Secured = false, RateLimit = 0 }, + { Name = "/:txhash/process-status", Open = true, Secured = false, RateLimit = 0 }, { Name = "/pool", Open = true, Secured = false, RateLimit = 0 } ] diff --git a/data/constants.go b/data/constants.go new file mode 100644 index 00000000..4f764451 --- /dev/null +++ b/data/constants.go @@ -0,0 +1,6 @@ +package data + +import "github.com/multiversx/mx-chain-core-go/data/transaction" + +// TxStatusUnknown defines the response that should be received from an observer when transaction status is unknown +const TxStatusUnknown transaction.TxStatus = "unknown" diff --git a/facade/baseFacade.go b/facade/baseFacade.go index fda4b57b..2612718c 100644 --- a/facade/baseFacade.go +++ b/facade/baseFacade.go @@ -216,6 +216,11 @@ func (epf *ProxyFacade) GetTransactionStatus(txHash string, sender string) (stri return epf.txProc.GetTransactionStatus(txHash, sender) } +// GetProcessedTransactionStatus should return transaction status after internal processing of the transaction results +func (epf *ProxyFacade) GetProcessedTransactionStatus(txHash string) (string, error) { + return epf.txProc.GetProcessedTransactionStatus(txHash) +} + // GetTransaction should return a transaction by hash func (epf *ProxyFacade) GetTransaction(txHash string, withResults bool) (*transaction.ApiTransactionResult, error) { return epf.txProc.GetTransaction(txHash, withResults) diff --git a/facade/interface.go b/facade/interface.go index 8e3d86c2..6c284e8d 100644 --- a/facade/interface.go +++ b/facade/interface.go @@ -41,6 +41,7 @@ type TransactionProcessor interface { TransactionCostRequest(tx *data.Transaction) (*data.TxCostResponseData, error) GetTransactionStatus(txHash string, sender string) (string, error) GetTransaction(txHash string, withEvents bool) (*transaction.ApiTransactionResult, error) + GetProcessedTransactionStatus(txHash string) (string, error) GetTransactionByHashAndSenderAddress(txHash string, sndAddr string, withEvents bool) (*transaction.ApiTransactionResult, int, error) ComputeTransactionHash(tx *data.Transaction) (string, error) GetTransactionsPool(fields string) (*data.TransactionsPool, error) diff --git a/facade/mock/transactionProcessorStub.go b/facade/mock/transactionProcessorStub.go index 70ace77e..488efc25 100644 --- a/facade/mock/transactionProcessorStub.go +++ b/facade/mock/transactionProcessorStub.go @@ -1,20 +1,24 @@ package mock import ( + "errors" "math/big" "github.com/multiversx/mx-chain-core-go/data/transaction" "github.com/multiversx/mx-chain-proxy-go/data" ) +var errNotImplemented = errors.New("not implemented") + // TransactionProcessorStub - type TransactionProcessorStub struct { SendTransactionCalled func(tx *data.Transaction) (int, string, error) SendMultipleTransactionsCalled func(txs []*data.Transaction) (data.MultipleTransactionsResponseData, error) SimulateTransactionCalled func(tx *data.Transaction, checkSignature bool) (*data.GenericAPIResponse, error) SendUserFundsCalled func(receiver string, value *big.Int) error - TransactionCostRequestHandler func(tx *data.Transaction) (*data.TxCostResponseData, error) - GetTransactionStatusHandler func(txHash string, sender string) (string, error) + TransactionCostRequestCalled func(tx *data.Transaction) (*data.TxCostResponseData, error) + GetTransactionStatusCalled func(txHash string, sender string) (string, error) + GetProcessedTransactionStatusCalled func(txHash string) (string, error) GetTransactionCalled func(txHash string, withEvents bool) (*transaction.ApiTransactionResult, error) GetTransactionByHashAndSenderAddressCalled func(txHash string, sndAddr string, withEvents bool) (*transaction.ApiTransactionResult, int, error) ComputeTransactionHashCalled func(tx *data.Transaction) (string, error) @@ -27,47 +31,92 @@ type TransactionProcessorStub struct { // SimulateTransaction - func (tps *TransactionProcessorStub) SimulateTransaction(tx *data.Transaction, checkSignature bool) (*data.GenericAPIResponse, error) { - return tps.SimulateTransactionCalled(tx, checkSignature) + if tps.SimulateTransactionCalled != nil { + return tps.SimulateTransactionCalled(tx, checkSignature) + } + + return nil, errNotImplemented } // SendTransaction - func (tps *TransactionProcessorStub) SendTransaction(tx *data.Transaction) (int, string, error) { - return tps.SendTransactionCalled(tx) + if tps.SendTransactionCalled != nil { + return tps.SendTransactionCalled(tx) + } + + return 0, "", errNotImplemented } // SendMultipleTransactions - func (tps *TransactionProcessorStub) SendMultipleTransactions(txs []*data.Transaction) (data.MultipleTransactionsResponseData, error) { - return tps.SendMultipleTransactionsCalled(txs) + if tps.SendMultipleTransactionsCalled != nil { + return tps.SendMultipleTransactionsCalled(txs) + } + + return data.MultipleTransactionsResponseData{}, errNotImplemented } // ComputeTransactionHash - func (tps *TransactionProcessorStub) ComputeTransactionHash(tx *data.Transaction) (string, error) { - return tps.ComputeTransactionHashCalled(tx) + if tps.ComputeTransactionHashCalled != nil { + return tps.ComputeTransactionHashCalled(tx) + } + + return "", errNotImplemented } // SendUserFunds - func (tps *TransactionProcessorStub) SendUserFunds(receiver string, value *big.Int) error { - return tps.SendUserFundsCalled(receiver, value) + if tps.SendUserFundsCalled != nil { + return tps.SendUserFundsCalled(receiver, value) + } + + return errNotImplemented } // GetTransactionStatus - func (tps *TransactionProcessorStub) GetTransactionStatus(txHash string, sender string) (string, error) { - return tps.GetTransactionStatusHandler(txHash, sender) + if tps.GetTransactionStatusCalled != nil { + return tps.GetTransactionStatusCalled(txHash, sender) + } + + return "", errNotImplemented +} + +// GetProcessedTransactionStatus - +func (tps *TransactionProcessorStub) GetProcessedTransactionStatus(txHash string) (string, error) { + if tps.GetProcessedTransactionStatusCalled != nil { + return tps.GetProcessedTransactionStatusCalled(txHash) + } + + return "", errNotImplemented } // GetTransaction - func (tps *TransactionProcessorStub) GetTransaction(txHash string, withEvents bool) (*transaction.ApiTransactionResult, error) { - return tps.GetTransactionCalled(txHash, withEvents) + if tps.GetTransactionCalled != nil { + return tps.GetTransactionCalled(txHash, withEvents) + } + + return nil, errNotImplemented } // GetTransactionByHashAndSenderAddress - func (tps *TransactionProcessorStub) GetTransactionByHashAndSenderAddress(txHash string, sndAddr string, withEvents bool) (*transaction.ApiTransactionResult, int, error) { - return tps.GetTransactionByHashAndSenderAddressCalled(txHash, sndAddr, withEvents) + if tps.GetTransactionByHashAndSenderAddressCalled != nil { + return tps.GetTransactionByHashAndSenderAddressCalled(txHash, sndAddr, withEvents) + } + + return nil, 0, errNotImplemented } // TransactionCostRequest - func (tps *TransactionProcessorStub) TransactionCostRequest(tx *data.Transaction) (*data.TxCostResponseData, error) { - return tps.TransactionCostRequestHandler(tx) + if tps.TransactionCostRequestCalled != nil { + return tps.TransactionCostRequestCalled(tx) + } + + return nil, errNotImplemented } // GetTransactionsPool - @@ -76,7 +125,7 @@ func (tps *TransactionProcessorStub) GetTransactionsPool(fields string) (*data.T return tps.GetTransactionsPoolCalled(fields) } - return nil, nil + return nil, errNotImplemented } // GetTransactionsPoolForShard - @@ -85,7 +134,7 @@ func (tps *TransactionProcessorStub) GetTransactionsPoolForShard(shardID uint32, return tps.GetTransactionsPoolForShardCalled(shardID, fields) } - return nil, nil + return nil, errNotImplemented } // GetTransactionsPoolForSender - @@ -94,7 +143,7 @@ func (tps *TransactionProcessorStub) GetTransactionsPoolForSender(sender, fields return tps.GetTransactionsPoolForSenderCalled(sender, fields) } - return nil, nil + return nil, errNotImplemented } // GetLastPoolNonceForSender - @@ -103,7 +152,7 @@ func (tps *TransactionProcessorStub) GetLastPoolNonceForSender(sender string) (u return tps.GetLastPoolNonceForSenderCalled(sender) } - return 0, nil + return 0, errNotImplemented } // GetTransactionsPoolNonceGapsForSender - @@ -112,5 +161,5 @@ func (tps *TransactionProcessorStub) GetTransactionsPoolNonceGapsForSender(sende return tps.GetTransactionsPoolNonceGapsForSenderCalled(sender) } - return nil, nil + return nil, errNotImplemented } diff --git a/process/export_test.go b/process/export_test.go index b45e49a7..0eec3804 100644 --- a/process/export_test.go +++ b/process/export_test.go @@ -3,6 +3,7 @@ package process import ( "time" + "github.com/multiversx/mx-chain-core-go/data/transaction" proxyData "github.com/multiversx/mx-chain-proxy-go/data" ) @@ -25,3 +26,8 @@ func ComputeTokenStorageKey(tokenID string, nonce uint64) string { func GetShortHashSize() int { return shortHashSize } + +// ComputeTransactionStatus - +func (tp *TransactionProcessor) ComputeTransactionStatus(tx *transaction.ApiTransactionResult, withResults bool) transaction.TxStatus { + return tp.computeTransactionStatus(tx, withResults) +} diff --git a/process/mock/loggerStub.go b/process/mock/loggerStub.go new file mode 100644 index 00000000..df3b18b1 --- /dev/null +++ b/process/mock/loggerStub.go @@ -0,0 +1,96 @@ +package mock + +import ( + logger "github.com/multiversx/mx-chain-logger-go" +) + +// LoggerStub - +type LoggerStub struct { + TraceCalled func(message string, args ...interface{}) + DebugCalled func(message string, args ...interface{}) + InfoCalled func(message string, args ...interface{}) + WarnCalled func(message string, args ...interface{}) + ErrorCalled func(message string, args ...interface{}) + LogIfErrorCalled func(err error, args ...interface{}) + LogCalled func(logLevel logger.LogLevel, message string, args ...interface{}) + LogLineCalled func(line *logger.LogLine) + SetLevelCalled func(logLevel logger.LogLevel) + GetLevelCalled func() logger.LogLevel +} + +// Trace - +func (stub *LoggerStub) Trace(message string, args ...interface{}) { + if stub.TraceCalled != nil { + stub.TraceCalled(message, args...) + } +} + +// Debug - +func (stub *LoggerStub) Debug(message string, args ...interface{}) { + if stub.DebugCalled != nil { + stub.DebugCalled(message, args...) + } +} + +// Info - +func (stub *LoggerStub) Info(message string, args ...interface{}) { + if stub.InfoCalled != nil { + stub.InfoCalled(message, args...) + } +} + +// Warn - +func (stub *LoggerStub) Warn(message string, args ...interface{}) { + if stub.WarnCalled != nil { + stub.WarnCalled(message, args...) + } +} + +// Error - +func (stub *LoggerStub) Error(message string, args ...interface{}) { + if stub.ErrorCalled != nil { + stub.ErrorCalled(message, args...) + } +} + +// LogIfError - +func (stub *LoggerStub) LogIfError(err error, args ...interface{}) { + if stub.LogIfErrorCalled != nil { + stub.LogIfErrorCalled(err, args...) + } +} + +// Log - +func (stub *LoggerStub) Log(logLevel logger.LogLevel, message string, args ...interface{}) { + if stub.LogCalled != nil { + stub.LogCalled(logLevel, message, args...) + } +} + +// LogLine - +func (stub *LoggerStub) LogLine(line *logger.LogLine) { + if stub.LogLineCalled != nil { + stub.LogLineCalled(line) + } +} + +// SetLevel - +func (stub *LoggerStub) SetLevel(logLevel logger.LogLevel) { + if stub.SetLevelCalled != nil { + stub.SetLevelCalled(logLevel) + } +} + +// GetLevel - +func (stub *LoggerStub) GetLevel() logger.LogLevel { + if stub.GetLevelCalled != nil { + return stub.GetLevelCalled() + } + + return logger.LogNone +} + +// IsInterfaceNil - +func (stub *LoggerStub) IsInterfaceNil() bool { + return stub == nil +} diff --git a/process/testdata/executingSCCall.json b/process/testdata/executingSCCall.json new file mode 100644 index 00000000..67e700f8 --- /dev/null +++ b/process/testdata/executingSCCall.json @@ -0,0 +1,165 @@ +{ + "transaction": { + "type": "normal", + "processingTypeOnSource": "SCInvoking", + "processingTypeOnDestination": "SCInvoking", + "hash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "notarizedAtSourceInMetaNonce": 1000, + "NotarizedAtSourceInMetaHash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "miniblockType": "TxBlock", + "miniblockHash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "smartContractResults": [ + { + "hash": "SCR-hash1", + "gasPrice": 1000000000, + "tokens": [ + "TKN-247875" + ], + "esdtValues": [ + "3715825415495382197" + ], + "receivers": [ + "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty" + ], + "receiversShardIDs": [ + 0 + ], + "operation": "MultiESDTNFTTransfer" + }, + { + "hash": "SCR-hash2", + "data": "@6f6b", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "operation": "transfer", + "isRefund": true + } + ], + "logs": { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "MultiESDTNFTTransfer", + "topics": [ + "WlBBWS0yNDc4NzU=" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "MultiESDTNFTTransfer", + "topics": [ + "RUZGT1JULWExMzUxMw==" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "MultiESDTNFTTransfer", + "topics": [ + "QUVSTy00NThiYmY=" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "MultiESDTNFTTransfer", + "topics": [ + "SVNFVC04NGU1NWU=" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "MultiESDTNFTTransfer", + "topics": [ + "QkhBVC1jMWZkZTM=" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "MultiESDTNFTTransfer", + "topics": [ + "VVRLLTJmODBlOQ==" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "MultiESDTNFTTransfer", + "topics": [ + "UVdULTQ2YWMwMQ==" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "MultiESDTNFTTransfer", + "topics": [ + "U0ZJVC1hZWJjOTA=" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "MultiESDTNFTTransfer", + "topics": [ + "Q1lCRVItNDg5YzFj" + ], + "data": null + } + ] + }, + "status": "success", + "operation": "transfer", + "function": "claimRewards", + "initiallyPaidFee": "1818670000000000", + "fee": "1682736380000000", + "chainID": "T", + "version": 1, + "options": 0 + }, + "scrs": [ + { + "type": "unsigned", + "hash": "SCR-hash1", + "gasUsed": 1256000, + "returnMessage": "", + "sourceShard": 2, + "destinationShard": 0, + "miniblockType": "SmartContractResultBlock", + "logs": { + "address": "erd1rjsy02mc73n2epsgm9u9j50pgwethrm9jfume40tk6gz89qmpdgqejt3pv", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "ESDTNFTTransfer", + "topics": [ + "Q09XLWNkNDYzZA==" + ], + "data": null + } + ] + }, + "status": "success", + "receiversShardIDs": [ + 0 + ], + "operation": "ESDTNFTTransfer", + "fee": "0", + "callType": "directCall", + "options": 0 + }, + { + "type": "unsigned", + "hash": "SCR-hash2", + "operation": "ESDTNFTTransfer", + "fee": "0", + "callType": "directCall", + "options": 0 + } + ] +} diff --git a/process/testdata/finishedFailedComplexScenario1.json b/process/testdata/finishedFailedComplexScenario1.json new file mode 100644 index 00000000..7d2aa9e7 --- /dev/null +++ b/process/testdata/finishedFailedComplexScenario1.json @@ -0,0 +1,230 @@ +{ + "transaction": { + "type": "normal", + "processingTypeOnSource": "BuiltInFunctionCall", + "processingTypeOnDestination": "SCInvoking", + "hash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "nonce": 19, + "gasPrice": 1000000000, + "gasLimit": 20000000, + "gasUsed": 20000000, + "sourceShard": 0, + "destinationShard": 0, + "miniblockType": "TxBlock", + "miniblockHash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "smartContractResults": [ + { + "hash": "SCR-hash1", + "nonce": 0, + "value": 0, + "data": "ESDTNFTTransfer@434f572d636434363364@080c@01@08011202000122e802088c101209436f772023363730381a2000000000000000000500799528645da9f81a3d56cf760b94870b04c377bba54f20a006324c68747470733a2f2f697066732e696f2f697066732f516d5038584c353657744e6e527657555848683157384d4c416a656b4d7959354a744d7735464337324c6633624b2f363730382e706e67324d68747470733a2f2f697066732e696f2f697066732f516d5038584c353657744e6e527657555848683157384d4c416a656b4d7959354a744d7735464337324c6633624b2f363730382e6a736f6e325368747470733a2f2f697066732e696f2f697066732f516d5038584c353657744e6e527657555848683157384d4c416a656b4d7959354a744d7735464337324c6633624b2f636f6c6c656374696f6e2e6a736f6e3a416d657461646174613a516d5038584c353657744e6e527657555848683157384d4c416a656b4d7959354a744d7735464337324c6633624b2f363730382e6a736f6e@616363657074476c6f62616c4f66666572@c3e5", + "gasLimit": 19508050, + "gasPrice": 1000000000, + "callType": 0, + "tokens": [ + "TKN-cd463d-080c" + ], + "esdtValues": [ + "1" + ], + "receivers": [ + "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty" + ], + "receiversShardIDs": [ + 2 + ], + "operation": "ESDTNFTTransfer", + "function": "call" + }, + { + "hash": "SCR-hash2", + "nonce": 0, + "value": 0, + "gasLimit": 0, + "gasPrice": 0, + "callType": 0, + "returnMessage": "ERROR", + "logs": { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "ESDTNFTTransfer", + "topics": [ + "Q09XLWNkNDYzZA==" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "completedTxEvent", + "topics": [ + "0yozTTuDGevfFN6XZXNkDXPfg42YTE5eUAWppT3ZX/Y=" + ], + "data": null + } + ] + }, + "tokens": [ + "TKN-cd463d-080c" + ], + "esdtValues": [ + "1" + ], + "receivers": [ + "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty" + ], + "receiversShardIDs": [ + 0 + ], + "operation": "ESDTNFTTransfer" + } + ], + "logs": { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "ESDTNFTTransfer", + "topics": [ + "Q09XLWNkNDYzZA==" + ], + "data": null + } + ] + }, + "status": "success", + "tokens": [ + "TKN-cd463d-080c" + ], + "esdtValues": [ + "1" + ], + "receivers": [ + "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty" + ], + "receiversShardIDs": [ + 2 + ], + "operation": "ESDTNFTTransfer", + "function": "call", + "initiallyPaidFee": "470765000000000", + "fee": "470765000000000", + "chainID": "1", + "version": 1, + "options": 0 + }, + "scrs": [ + { + "type": "unsigned", + "processingTypeOnSource": "BuiltInFunctionCall", + "processingTypeOnDestination": "SCInvoking", + "hash": "SCR-hash1", + "gasPrice": 1000000000, + "gasLimit": 19508050, + "gasUsed": 19508050, + "sourceShard": 0, + "destinationShard": 2, + "miniblockType": "SmartContractResultBlock", + "logs": { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "ESDTNFTTransfer", + "topics": [ + "Q09XLWNkNDYzZA==" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "signalError", + "topics": [ + "HKBHq3j0ZqyGCNl4WVHhQ7K7j2WSebzV67aQI5QbC1A=", + "VGhpcyBvZmZlciBpcyBhbHJlYWR5IHJlbW92ZWQh" + ], + "data": "RVNEVE5GVFRyYW5zZmVyQDQzNGY1NzJkNjM2NDM0MzYzMzY0QDA4MGNAMDFAMDgwMTEyMDIwMDAxMjJlODAyMDg4YzEwMTIwOTQzNmY3NzIwMjMzNjM3MzAzODFhMjAwMDAwMDAwMDAwMDAwMDAwMDUwMDc5OTUyODY0NWRhOWY4MWEzZDU2Y2Y3NjBiOTQ4NzBiMDRjMzc3YmJhNTRmMjBhMDA2MzI0YzY4NzQ3NDcwNzMzYTJmMmY2OTcwNjY3MzJlNjk2ZjJmNjk3MDY2NzMyZjUxNmQ1MDM4NTg0YzM1MzY1Nzc0NGU2ZTUyNzY1NzU1NTg0ODY4MzE1NzM4NGQ0YzQxNmE2NTZiNGQ3OTU5MzU0YTc0NGQ3NzM1NDY0MzM3MzI0YzY2MzM2MjRiMmYzNjM3MzAzODJlNzA2ZTY3MzI0ZDY4NzQ3NDcwNzMzYTJmMmY2OTcwNjY3MzJlNjk2ZjJmNjk3MDY2NzMyZjUxNmQ1MDM4NTg0YzM1MzY1Nzc0NGU2ZTUyNzY1NzU1NTg0ODY4MzE1NzM4NGQ0YzQxNmE2NTZiNGQ3OTU5MzU0YTc0NGQ3NzM1NDY0MzM3MzI0YzY2MzM2MjRiMmYzNjM3MzAzODJlNmE3MzZmNmUzMjUzNjg3NDc0NzA3MzNhMmYyZjY5NzA2NjczMmU2OTZmMmY2OTcwNjY3MzJmNTE2ZDUwMzg1ODRjMzUzNjU3NzQ0ZTZlNTI3NjU3NTU1ODQ4NjgzMTU3Mzg0ZDRjNDE2YTY1NmI0ZDc5NTkzNTRhNzQ0ZDc3MzU0NjQzMzczMjRjNjYzMzYyNGIyZjYzNmY2YzZjNjU2Mzc0Njk2ZjZlMmU2YTczNmY2ZTNhNDE2ZDY1NzQ2MTY0NjE3NDYxM2E1MTZkNTAzODU4NGMzNTM2NTc3NDRlNmU1Mjc2NTc1NTU4NDg2ODMxNTczODRkNGM0MTZhNjU2YjRkNzk1OTM1NGE3NDRkNzczNTQ2NDMzNzMyNGM2NjMzNjI0YjJmMzYzNzMwMzgyZTZhNzM2ZjZlQDc1NzM2NTcyMjA2NTcyNzI2Zjcy" + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "internalVMErrors", + "topics": [ + "AAAAAAAAAAAFANOyiCjWIFISTwfc1Q7TGwgl9g7uFSY=", + "YWNjZXB0R2xvYmFsT2ZmZXI=" + ], + "data": "CglydW50aW1lLmdvOjExNjggW2Vycm9yIHNpZ25hbGxlZCBieSBzbWFydGNvbnRyYWN0XSBbYWNjZXB0R2xvYmFsT2ZmZXJdCglydW50aW1lLmdvOjExNjggW2Vycm9yIHNpZ25hbGxlZCBieSBzbWFydGNvbnRyYWN0XSBbYWNjZXB0R2xvYmFsT2ZmZXJdCglydW50aW1lLmdvOjExNjUgW1RoaXMgb2ZmZXIgaXMgYWxyZWFkeSByZW1vdmVkIV0=" + } + ] + }, + "status": "success", + "tokens": [ + "TKN-cd463d-080c" + ], + "esdtValues": [ + "1" + ], + "receivers": [ + "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty" + ], + "receiversShardIDs": [ + 2 + ], + "operation": "ESDTNFTTransfer", + "function": "acceptGlobalOffer", + "fee": "182235500000000", + "callType": "directCall", + "options": 0 + }, + { + "type": "unsigned", + "processingTypeOnSource": "BuiltInFunctionCall", + "processingTypeOnDestination": "BuiltInFunctionCall", + "hash": "SCR-hash2", + "gasUsed": 1256000, + "data": "RVNEVE5GVFRyYW5zZmVyQDQzNGY1NzJkNjM2NDM0MzYzMzY0QDA4MGNAMDFAMDgwMTEyMDIwMDAxMjJlODAyMDg4YzEwMTIwOTQzNmY3NzIwMjMzNjM3MzAzODFhMjAwMDAwMDAwMDAwMDAwMDAwMDUwMDc5OTUyODY0NWRhOWY4MWEzZDU2Y2Y3NjBiOTQ4NzBiMDRjMzc3YmJhNTRmMjBhMDA2MzI0YzY4NzQ3NDcwNzMzYTJmMmY2OTcwNjY3MzJlNjk2ZjJmNjk3MDY2NzMyZjUxNmQ1MDM4NTg0YzM1MzY1Nzc0NGU2ZTUyNzY1NzU1NTg0ODY4MzE1NzM4NGQ0YzQxNmE2NTZiNGQ3OTU5MzU0YTc0NGQ3NzM1NDY0MzM3MzI0YzY2MzM2MjRiMmYzNjM3MzAzODJlNzA2ZTY3MzI0ZDY4NzQ3NDcwNzMzYTJmMmY2OTcwNjY3MzJlNjk2ZjJmNjk3MDY2NzMyZjUxNmQ1MDM4NTg0YzM1MzY1Nzc0NGU2ZTUyNzY1NzU1NTg0ODY4MzE1NzM4NGQ0YzQxNmE2NTZiNGQ3OTU5MzU0YTc0NGQ3NzM1NDY0MzM3MzI0YzY2MzM2MjRiMmYzNjM3MzAzODJlNmE3MzZmNmUzMjUzNjg3NDc0NzA3MzNhMmYyZjY5NzA2NjczMmU2OTZmMmY2OTcwNjY3MzJmNTE2ZDUwMzg1ODRjMzUzNjU3NzQ0ZTZlNTI3NjU3NTU1ODQ4NjgzMTU3Mzg0ZDRjNDE2YTY1NmI0ZDc5NTkzNTRhNzQ0ZDc3MzU0NjQzMzczMjRjNjYzMzYyNGIyZjYzNmY2YzZjNjU2Mzc0Njk2ZjZlMmU2YTczNmY2ZTNhNDE2ZDY1NzQ2MTY0NjE3NDYxM2E1MTZkNTAzODU4NGMzNTM2NTc3NDRlNmU1Mjc2NTc1NTU4NDg2ODMxNTczODRkNGM0MTZhNjU2YjRkNzk1OTM1NGE3NDRkNzczNTQ2NDMzNzMyNGM2NjMzNjI0YjJmMzYzNzMwMzgyZTZhNzM2ZjZlQDc1NzM2NTcyMjA2NTcyNzI2Zjcy", + "returnMessage": "ERROR", + "sourceShard": 2, + "destinationShard": 0, + "miniblockType": "SmartContractResultBlock", + "logs": { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "ESDTNFTTransfer", + "topics": [ + "Q09XLWNkNDYzZA==" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "completedTxEvent", + "topics": [ + "0yozTTuDGevfFN6XZXNkDXPfg42YTE5eUAWppT3ZX/Y=" + ], + "data": null + } + ] + }, + "status": "success", + "tokens": [ + "TKN-cd463d-080c" + ], + "esdtValues": [ + "1" + ], + "receivers": [ + "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty" + ], + "receiversShardIDs": [ + 0 + ], + "operation": "ESDTNFTTransfer", + "fee": "0", + "callType": "directCall", + "options": 0 + } + ] +} diff --git a/process/testdata/finishedFailedComplexScenario2.json b/process/testdata/finishedFailedComplexScenario2.json new file mode 100644 index 00000000..3d1328a6 --- /dev/null +++ b/process/testdata/finishedFailedComplexScenario2.json @@ -0,0 +1,204 @@ +{ + "transaction": { + "type": "normal", + "processingTypeOnSource": "SCInvoking", + "processingTypeOnDestination": "SCInvoking", + "hash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "gasPrice": 1000000000, + "gasLimit": 75000000, + "gasUsed": 75000000, + "data": "aXNzdWVUb2tlbkA0RDc5NTQ2NTczNzQ0RTY2NzQ2NEA1NDQ1NTM1NDRFNDY1NA==", + "smartContractResults": [ + { + "hash": "SCR-hash1", + "nonce": 0, + "value": 5000000000000000000, + "receiver": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "sender": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "data": "issueNonFungible@4d79546573744e667464", + "gasPrice": 1000000000, + "callType": 1, + "operation": "transfer", + "function": "issueNonFungible" + }, + { + "hash": "SCR-hash2", + "nonce": 0, + "value": 5000000000000000000, + "data": "@04@63616c6c56616c7565206e6f7420657175616c732077697468206261736549737375696e67436f7374", + "gasPrice": 1000000000, + "callType": 2, + "returnMessage": "callValue not equals with baseIssuingCost", + "logs": { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "transferValueOnly", + "topics": [ + "AAAAAAAAAAAFAO35sGZxo0ZbVHvE2+fsC6LrtfskrNw=" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "completedTxEvent", + "topics": [ + "Nugi510SGIVupLRZnynNrPWGvz5kgYpnWWdNS4102a8=" + ], + "data": null + } + ] + }, + "operation": "transfer" + }, + { + "hash": "SCR-hash3", + "nonce": 0, + "value": 5000000000000000000, + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "originalSender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "operation": "transfer" + }, + { + "hash": "SCR-hash4", + "nonce": 1, + "value": 27898530000000, + "data": "@6f6b", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "operation": "transfer", + "isRefund": true + } + ], + "logs": { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "transferValueOnly", + "topics": [ + "AAAAAAAAAAAFAO35sGZxo0ZbVHvE2+fsC6LrtfskrNw=", + "AAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAC//8=", + "RWORgkT0AAA=" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "writeLog", + "topics": [ + "qfaoGqfadnipWFWCnaJeOiknm8PQtEqI8lHBatO+rNw=" + ], + "data": "QDZmNmI=" + } + ] + }, + "status": "success", + "operation": "transfer", + "function": "issueToken", + "initiallyPaidFee": "867810000000000", + "fee": "867810000000000", + "chainID": "T", + "version": 1, + "options": 0 + }, + "scrs": [ + { + "type": "unsigned", + "processingTypeOnSource": "SCInvoking", + "processingTypeOnDestination": "SCInvoking", + "hash": "SCR-hash1", + "value": "5000000000000000000", + "gasLimit": 71452435, + "gasUsed": 71452435, + "sourceShard": 0, + "destinationShard": 4294967295, + "logs": { + "address": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "events": [ + { + "address": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "identifier": "signalError", + "topics": [ + "AAAAAAAAAAAFAO35sGZxo0ZbVHvE2+fsC6LrtfskrNw=" + ] + } + ] + }, + "status": "success", + "operation": "transfer", + "function": "issueNonFungible", + "fee": "710199350000000", + "callType": "asynchronousCall", + "options": 0 + }, + { + "type": "unsigned", + "processingTypeOnSource": "SCInvoking", + "processingTypeOnDestination": "SCInvoking", + "hash": "SCR-hash2", + "nonce": 0, + "gasLimit": 5828600, + "logs": { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "transferValueOnly", + "topics": [ + "AAAAAAAAAAAFAO35sGZxo0ZbVHvE2+fsC6LrtfskrNw=" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "completedTxEvent", + "topics": [ + "Nugi510SGIVupLRZnynNrPWGvz5kgYpnWWdNS4102a8=" + ], + "data": null + } + ] + }, + "status": "success", + "operation": "transfer", + "fee": "0", + "callType": "asynchronousCallBack", + "options": 0 + }, + { + "type": "unsigned", + "processingTypeOnSource": "MoveBalance", + "processingTypeOnDestination": "MoveBalance", + "hash": "SCR-hash3", + "nonce": 0, + "sourceShard": 0, + "destinationShard": 0, + "miniblockType": "SmartContractResultBlock", + "status": "success", + "operation": "transfer", + "fee": "0", + "callType": "directCall", + "options": 0 + }, + { + "type": "unsigned", + "processingTypeOnSource": "MoveBalance", + "processingTypeOnDestination": "MoveBalance", + "hash": "SCR-hash4", + "nonce": 1, + "gasUsed": 57500, + "data": "QDZmNmI=", + "status": "success", + "operation": "transfer", + "fee": "0", + "isRefund": true, + "callType": "directCall", + "options": 0 + } + ] +} diff --git a/process/testdata/finishedFailedComplexScenario3.json b/process/testdata/finishedFailedComplexScenario3.json new file mode 100644 index 00000000..db5f210c --- /dev/null +++ b/process/testdata/finishedFailedComplexScenario3.json @@ -0,0 +1,237 @@ +{ + "transaction": { + "type": "normal", + "processingTypeOnSource": "SCInvoking", + "processingTypeOnDestination": "SCInvoking", + "hash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "gasLimit": 75000000, + "gasUsed": 75000000, + "data": "aXNzdWVUb2tlbkA0RDc5NTQ2NTczNzQ0RTY2NzQ2NEA1NDQ1NTM1NDRFNDY1NA==", + "smartContractResults": [ + { + "hash": "SCR-hash1", + "nonce": 0, + "value": 50000000000000000, + "data": "issueNonFungible@4d79546573744e667464@544553544e4654@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4368616e67654f776e6572@66616c7365@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@74727565@58f638", + "gasLimit": 71450835, + "gasPrice": 1000000000, + "callType": 1, + "operation": "transfer", + "function": "issueNonFungible" + }, + { + "hash": "SCR-hash2", + "nonce": 0, + "value": 0, + "data": "@00@544553544e46542d643964353463", + "gasLimit": 21450835, + "gasPrice": 1000000000, + "callType": 2, + "logs": { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "signalError", + "topics": [ + "AAAAAAAAAAAFAO35sGZxo0ZbVHvE2+fsC6LrtfskrNw=", + "c3RvcmFnZSBkZWNvZGUgZXJyb3I6IGlucHV0IHRvbyBzaG9ydA==" + ], + "data": "QDc1NzM2NTcyMjA2NTcyNzI2Zjcy" + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "internalVMErrors", + "topics": [ + "AAAAAAAAAAAFAO35sGZxo0ZbVHvE2+fsC6LrtfskrNw=", + "Y2FsbEJhY2s=" + ], + "data": "CglydW50aW1lLmdvOjExNzIgW2Vycm9yIHNpZ25hbGxlZCBieSBzbWFydGNvbnRyYWN0XSBbY2FsbEJhY2tdCglydW50aW1lLmdvOjExNzIgW2Vycm9yIHNpZ25hbGxlZCBieSBzbWFydGNvbnRyYWN0XSBbY2FsbEJhY2tdCglydW50aW1lLmdvOjExNjkgW3N0b3JhZ2UgZGVjb2RlIGVycm9yOiBpbnB1dCB0b28gc2hvcnRd" + } + ] + }, + "operation": "transfer" + }, + { + "hash": "SCR-hash3", + "nonce": 0, + "value": 0, + "receiver": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqq2m3f0f", + "data": "ESDTSetBurnRoleForAll@544553544e46542d643964353463", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "logs": { + "address": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqq2m3f0f", + "events": [ + { + "address": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqq2m3f0f", + "identifier": "completedTxEvent", + "topics": [ + "wKBOwHdmkwlfOX1V9tL1ocCqdnUxqRB9pHnp42I1jDM=" + ], + "data": null + } + ] + }, + "operation": "transfer" + } + ], + "logs": { + "address": "erd1qqqqqqqqqqqqqpgqahumqen35dr9k4rmcnd70mqt5t4mt7ey4nwqwjme9g", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "transferValueOnly", + "topics": [ + "AAAAAAAAAAAFAO35sGZxo0ZbVHvE2+fsC6LrtfskrNw=" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "writeLog", + "topics": [ + "qfaoGqfadnipWFWCnaJeOiknm8PQtEqI8lHBatO+rNw=" + ], + "data": "QDZmNmI=" + } + ] + }, + "status": "success", + "operation": "transfer", + "function": "issueToken", + "initiallyPaidFee": "867810000000000", + "fee": "867810000000000", + "chainID": "T", + "version": 1, + "options": 0 + }, + "scrs": [ + { + "type": "unsigned", + "processingTypeOnSource": "SCInvoking", + "processingTypeOnDestination": "SCInvoking", + "hash": "SCR-hash1", + "nonce": 0, + "round": 2098204, + "epoch": 1747, + "value": "50000000000000000", + "receiver": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "gasPrice": 1000000000, + "gasLimit": 71450835, + "gasUsed": 432500, + "data": "aXNzdWVOb25GdW5naWJsZUA0ZDc5NTQ2NTczNzQ0ZTY2NzQ2NEA1NDQ1NTM1NDRlNDY1NEA2MzYxNmU0NjcyNjU2NTdhNjVANzQ3Mjc1NjVANjM2MTZlNTc2OTcwNjVANzQ3Mjc1NjVANjM2MTZlNTA2MTc1NzM2NUA3NDcyNzU2NUA2MzYxNmU0MzY4NjE2ZTY3NjU0Zjc3NmU2NTcyQDY2NjE2YzczNjVANjM2MTZlNTU3MDY3NzI2MTY0NjVANjY2MTZjNzM2NUA2MzYxNmU0MTY0NjQ1MzcwNjU2MzY5NjE2YzUyNmY2YzY1NzNANzQ3Mjc1NjVANThmNjM4", + "sourceShard": 0, + "destinationShard": 4294967295, + "miniblockType": "SmartContractResultBlock", + "logs": { + "address": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "upgradeProperties", + "topics": [ + "VEVTVE5GVC1kOWQ1NGM=" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "issueNonFungible", + "topics": [ + "VEVTVE5GVC1kOWQ1NGM=" + ], + "data": null + } + ] + }, + "status": "success", + "operation": "transfer", + "function": "issueNonFungible", + "fee": "0", + "callType": "asynchronousCall", + "options": 0 + }, + { + "type": "unsigned", + "processingTypeOnSource": "SCInvoking", + "processingTypeOnDestination": "SCInvoking", + "hash": "SCR-hash2", + "nonce": 0, + "round": 2098206, + "epoch": 1747, + "value": "0", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "gasPrice": 1000000000, + "gasLimit": 21450835, + "gasUsed": 21450835, + "data": "QDAwQDU0NDU1MzU0NGU0NjU0MmQ2NDM5NjQzNTM0NjM=", + "sourceShard": 4294967295, + "destinationShard": 0, + "miniblockType": "SmartContractResultBlock", + "logs": { + "address": "erd1qqqqqqqqqqqqqpgqahumqen35dr9k4rmcnd70mqt5t4mt7ey4nwqwjme9g", + "events": [ + { + "address": "erd1qqqqqqqqqqqqqpgqahumqen35dr9k4rmcnd70mqt5t4mt7ey4nwqwjme9g", + "identifier": "signalError", + "topics": [ + "AAAAAAAAAAAFAO35sGZxo0ZbVHvE2+fsC6LrtfskrNw=", + "c3RvcmFnZSBkZWNvZGUgZXJyb3I6IGlucHV0IHRvbyBzaG9ydA==" + ], + "data": "QDc1NzM2NTcyMjA2NTcyNzI2Zjcy" + }, + { + "address": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "identifier": "internalVMErrors", + "topics": [ + "AAAAAAAAAAAFAO35sGZxo0ZbVHvE2+fsC6LrtfskrNw=", + "Y2FsbEJhY2s=" + ], + "data": "CglydW50aW1lLmdvOjExNzIgW2Vycm9yIHNpZ25hbGxlZCBieSBzbWFydGNvbnRyYWN0XSBbY2FsbEJhY2tdCglydW50aW1lLmdvOjExNzIgW2Vycm9yIHNpZ25hbGxlZCBieSBzbWFydGNvbnRyYWN0XSBbY2FsbEJhY2tdCglydW50aW1lLmdvOjExNjkgW3N0b3JhZ2UgZGVjb2RlIGVycm9yOiBpbnB1dCB0b28gc2hvcnRd" + } + ] + }, + "status": "success", + "operation": "transfer", + "fee": "213528350000000", + "callType": "asynchronousCallBack", + "options": 0 + }, + { + "type": "unsigned", + "processingTypeOnSource": "BuiltInFunctionCall", + "processingTypeOnDestination": "BuiltInFunctionCall", + "hash": "SCR-hash3", + "nonce": 0, + "receiver": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqq2m3f0f", + "sender": "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "gasPrice": 1000000000, + "gasUsed": 125000, + "data": "RVNEVFNldEJ1cm5Sb2xlRm9yQWxsQDU0NDU1MzU0NGU0NjU0MmQ2NDM5NjQzNTM0NjM=", + "sourceShard": 4294967295, + "destinationShard": 0, + "blockNonce": 2095246, + "miniblockType": "SmartContractResultBlock", + "logs": { + "address": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqq2m3f0f", + "events": [ + { + "address": "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqq2m3f0f", + "identifier": "completedTxEvent", + "topics": [ + "wKBOwHdmkwlfOX1V9tL1ocCqdnUxqRB9pHnp42I1jDM=" + ], + "data": null + } + ] + }, + "status": "success", + "operation": "transfer", + "fee": "0", + "callType": "directCall", + "options": 0 + } + ] +} diff --git a/process/testdata/finishedFailedRelayedTxUnexecutable.json b/process/testdata/finishedFailedRelayedTxUnexecutable.json new file mode 100644 index 00000000..f583492c --- /dev/null +++ b/process/testdata/finishedFailedRelayedTxUnexecutable.json @@ -0,0 +1,69 @@ +{ + "transaction": { + "type": "normal", + "processingTypeOnSource": "RelayedTx", + "processingTypeOnDestination": "RelayedTx", + "hash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "gasLimit": 1843000, + "gasUsed": 1843000, + "data": "cmVsYXllZFR4QDdiMjI2ZTZmNmU2MzY1MjIzYTMyMzIyYzIyNzM2NTZlNjQ2NTcyMjIzYTIyNjY0ZDcxNTE0NTY5Njg2NzRhMzE2ODcwNGMzNjUyNzc0NTZjNTg1NzZlNmEzMjQ2Mzc0ZTZlNjgzMzY5Nzg1MTU5N2EzOTYzNTc1OTZlNGY0YjQ0NGQzZDIyMmMyMjcyNjU2MzY1Njk3NjY1NzIyMjNhMjI2NjRkNzE1MTQ1Njk2ODY3NGEzMTY4NzA0YzM2NTI3NzQ1NmM1ODU3NmU2YTMyNDYzNzRlNmU2ODMzNjk3ODUxNTk3YTM5NjM1NzU5NmU0ZjRiNDQ0ZDNkMjIyYzIyNzY2MTZjNzU2NTIyM2EzMDJjMjI2NzYxNzM1MDcyNjk2MzY1MjIzYTMxMzAzMDMwMzAzMDMwMzAzMDMwMmMyMjY3NjE3MzRjNjk2ZDY5NzQyMjNhMzUzMDMwMzAzMDMwMmMyMjY0NjE3NDYxMjIzYTIyNTUzMjU2MzA1MjMzNTY2ODYzNmQ1MjcwNTk1NzM1NDE0ZDQ0NDU3YTRmNTQ1MTMzNGQ2ZDU2NmQ1YTZhNTkzNDRmNDQ1OTMzNGU3YTQ2Njg0ZjU0Njc3OTVhNmE0ZDc3NGY0NDRlNmI1OTU0NTY2YjRlNDQ0OTc4NWE2YTQ5MzA1OTdhNDkzNTRkNTQ2Nzc4NWE1NDU5N2E0ZjQ0NjczNDRkNmE0OTM0NWE0NzRkMzQ0ZDU3NGU2ODRlNmE0MjZiNGU2YTZjNmM0ZDU1NDI2ODU5NmQ0YTY4MjIyYzIyNzM2OTY3NmU2MTc0NzU3MjY1MjIzYTIyNDU3ODcyNmU0Yjc5MmY0ZjRlMzg2MzZiMzM1NTU1MmY1MTM2NTI0YzRjNTg3MzM3NGIzODQ1MmYzNjRmNTU1MzZhNmMzNjRkNjk1ODZmMmYzMjYxNDE3YTRhMzI2Mzc4NDQ2YzdhNGY1NTc3NTU0MjZjNGM0YzRmMmI3MDJiNmM0NDM0MmI3NDQ2NmU2ZTZjNTY0ODRmNzQ1YTQ2NGU2ZjQ3NjM3NTZjNDM0MTNkM2QyMjJjMjI2MzY4NjE2OTZlNDk0NDIyM2EyMjU2NDEzZDNkMjIyYzIyNzY2NTcyNzM2OTZmNmUyMjNhMzE3ZA==", + "signature": "8fadce4b8512f5ecfb1e957f08949eea841f7266c7f5cbb7eb3c13d9168738f385fca5d9c0e75ce15323868b9b8e8f36b49a01e07e28e07c16859ecf22eb3a06", + "smartContractResults": [ + { + "hash": "SCR-hash1", + "nonce": 15, + "value": 0, + "receiver": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "sender": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "gasLimit": 0, + "gasPrice": 0, + "callType": 0, + "returnMessage": "lower nonce in transaction", + "operation": "transfer" + } + ], + "logs":{ + "address":"erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "events":[ + { + "address":"erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier":"signalError", + "topics":null, + "data":null + } + ] + }, + "status": "success", + "receivers": [ + "erd10n9fqy3gvqn4s6f053cpy4wknc7ctmxeu80zc5rr8aw9nzww9qesj03tma" + ], + "receiversShardIDs": [ + 1 + ], + "operation": "transfer", + "initiallyPaidFee": "1348000000000000", + "fee": "1348000000000000", + "isRelayed": true, + "chainID": "T", + "version": 1, + "options": 0 + }, + "scrs": [ + { + "type": "unsigned", + "processingTypeOnSource": "MoveBalance", + "processingTypeOnDestination": "MoveBalance", + "hash": "SCR-hash1", + "receiver": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "sender": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "returnMessage": "lower nonce in transaction", + "sourceShard": 1, + "destinationShard": 1, + "status": "success", + "operation": "transfer", + "fee": "0", + "callType": "directCall", + "options": 0 + } + ] +} diff --git a/process/testdata/finishedFailedRelayedTxWithSCCall.json b/process/testdata/finishedFailedRelayedTxWithSCCall.json new file mode 100644 index 00000000..b95eef31 --- /dev/null +++ b/process/testdata/finishedFailedRelayedTxWithSCCall.json @@ -0,0 +1,75 @@ +{ + "transaction": { + "type": "normal", + "processingTypeOnSource": "RelayedTx", + "processingTypeOnDestination": "RelayedTx", + "hash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "gasPrice": 1000000000, + "gasLimit": 21421000, + "gasUsed": 21421000, + "data": "cmVsYXllZFR4QDdiMjI2ZTZmNmU2MzY1MjIzYTMxMzIzOTM3MzIzMDJjMjI3MzY1NmU2NDY1NzIyMjNhMjI1MzY0MzIzNTU5MzE0YzQyNDU3MTU0Njg2MjU1Mzg2ODc5NDc1ODc3NTU2Zjc3NGY0NjJmNGQ1MDQxMzI2ZjU4NGI2NzMzMzA2YzUzNGI0Yjc1N2E0OTNkMjIyYzIyNzI2NTYzNjU2OTc2NjU3MjIyM2EyMjQxNDE0MTQxNDE0MTQxNDE0MTQxNDE0NjQxNGI1OTMzNzM0ZjJiNzU2YjRmNjQ2ZDQ1NjY0MjRkNjk2OTU4Nzc2NzMxNmQ0NDU4NTk1NzQ3NjgzMzZmM2QyMjJjMjI3NjYxNmM3NTY1MjIzYTMwMmMyMjY3NjE3MzUwNzI2OTYzNjUyMjNhMzEzMDMwMzAzMDMwMzAzMDMwMzAyYzIyNjc2MTczNGM2OTZkNjk3NDIyM2EzMjMwMzAzMDMwMzAzMDMwMmMyMjY0NjE3NDYxMjIzYTIyNTkzMjM5NzU1YTZkNmM3OTYyNTU0NjMwNjQ0NzU2N2E2NDQ3NDYzMDYxNTczOTc1NTE0NDUyNmI1OTU0NTI2ZDVhNTc1YTZkNGQ2YTRkNzc0ZjU3NWE2ZDRkNmE2MzM0NWE1NDYzNzk1YTQ0NjczNDRlNmE2NzM1NGQ2ZDU1Nzg0ZTU0NDU3ODRlNDQ0MTc3NGU0NzQ1MzA0ZTZhNGU2YTU5NmQ0NTMzNGQ2YTUyNmM0ZDdhNTk3NzVhNTQ2Yjc4NTkzMjQ5MzI0ZjQ0NDkzNDU5NmE0YTY5NGU2YTQ2NDE0ZDdhNTE3YTRlNDQ0ZDc4NGQ3YTY3N2E0ZDdhNGQzNTIyMmMyMjYzNjg2MTY5NmU0OTQ0MjIzYTIyNGQ1MTNkM2QyMjJjMjI3NjY1NzI3MzY5NmY2ZTIyM2EzMTJjMjI3MzY5Njc2ZTYxNzQ3NTcyNjUyMjNhMjI0ZDJmNGQ1OTU3Nzc1ODRmMzA2YzM5NGI3NDM5NzU0YTU2NjI0ZTQxNTk0NjQ0Njc0MjcxNmI2MjcxNGM2NzY0NDQzMDY0NDgzNDY3NmE2MTRkNGM2Yzc2MmIzMjYxNjU3ODZmNTI0YzM4Nzc3YTM5NTE1MDczNzQ2MjQxMmIzNjM0NjYyYjJiNzI3YTU5NTQ2MzQxNzA2OTRkMzk1OTU0NGE3OTM5NTM0MjUxM2QzZDIyN2Q=", + "smartContractResults": [ + { + "hash": "SCR-hash1", + "nonce": 129720, + "value": 0, + "receiver": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "sender": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "data": "@75736572206572726f72", + "gasLimit": 0, + "gasPrice": 0, + "callType": 0, + "returnMessage": "must be called after saveAttestation", + "operation": "transfer" + } + ], + "logs": { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "signalError", + "topics": [ + "Sd25Y1LBEqThbU8hyGXwUowOF/MPA2oXKg30lSKKuzI=" + ], + "data": "QDc1NzM2NTcyMjA2NTcyNzI2Zjcy" + } + ] + }, + "status": "success", + "receivers": [ + "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty" + ], + "receiversShardIDs": [ + 2 + ], + "operation": "transfer", + "function": "confirmAttestation", + "initiallyPaidFee": "1621000000000000", + "fee": "1621000000000000", + "isRelayed": true, + "chainID": "1", + "version": 1, + "options": 0 + }, + "scrs": [ + { + "type": "unsigned", + "processingTypeOnSource": "MoveBalance", + "processingTypeOnDestination": "MoveBalance", + "hash": "SCR-hash1", + "receiver": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "sender": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "gasUsed": 81500, + "data": "QDc1NzM2NTcyMjA2NTcyNzI2Zjcy", + "returnMessage": "must be called after saveAttestation", + "sourceShard": 2, + "destinationShard": 2, + "status": "success", + "operation": "transfer", + "fee": "0", + "callType": "directCall", + "options": 0 + } + ] +} diff --git a/process/testdata/finishedFailedSCCall.json b/process/testdata/finishedFailedSCCall.json new file mode 100644 index 00000000..89c1ec9f --- /dev/null +++ b/process/testdata/finishedFailedSCCall.json @@ -0,0 +1,65 @@ +{ + "transaction": { + "type": "normal", + "processingTypeOnSource": "BuiltInFunctionCall", + "processingTypeOnDestination": "SCInvoking", + "hash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "blockHash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "notarizedAtSourceInMetaNonce": 2000, + "NotarizedAtSourceInMetaHash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "notarizedAtDestinationInMetaNonce": 2000, + "notarizedAtDestinationInMetaHash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "miniblockType": "TxBlock", + "miniblockHash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "hyperblockHash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "logs": { + "address": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "ESDTNFTTransfer", + "topics": [ + "V0FSUC05YWIzMjI=" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "signalError", + "topics": [ + "PcsDekGLvCoXOQRSrs9OWLbpCiUYjTapCfGPuKVbdl8=" + ], + "data": "QDY1Nzg2NTYzNzU3NDY5NmY2ZTIwNjY2MTY5NmM2NTY0" + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "internalVMErrors", + "topics": [ + "AAAAAAAAAAAFAAfCb7p+cp8llHG2CSInNKwxoB1Qdl8=" + ], + "data": "" + } + ] + }, + "status": "success", + "tokens": [ + "TKN-9ab322-01" + ], + "esdtValues": [ + "1" + ], + "receivers": [ + "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty" + ], + "receiversShardIDs": [ + 1 + ], + "operation": "ESDTNFTTransfer", + "function": "call", + "initiallyPaidFee": "407005000000000", + "fee": "407005000000000", + "chainID": "T", + "version": 1, + "options": 0 + } +} diff --git a/process/testdata/finishedInvalidBuiltinFunction.json b/process/testdata/finishedInvalidBuiltinFunction.json new file mode 100644 index 00000000..2fb04d4a --- /dev/null +++ b/process/testdata/finishedInvalidBuiltinFunction.json @@ -0,0 +1,56 @@ +{ + "transaction": { + "type": "invalid", + "processingTypeOnSource": "BuiltInFunctionCall", + "processingTypeOnDestination": "BuiltInFunctionCall", + "hash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "value": "0", + "receiver": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "sender": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "gasPrice": 1000000000, + "gasLimit": 550000000, + "gasUsed": 550000000, + "data": "TXVsdGlFU0RUTkZUVHJhbnNmZXJAN2EwMTY3ZGY3NmY1ZjllNzBkNjRjMjEwNjAxYTQ2NWE4Y2I0ZGE5YTQ0YjkwY2FkZDY4ZDA0YWIwNTIwYmQ3Y0AwM0A1NjRjNTMyZDMxMzE2NDMwNjQzMEAwNEAwMUA1NjRjNTMyZDMxMzE2NDMwNjQzMEAwNUAwMUA1NjRjNTMyZDMxMzE2NDMwNjQzMEAwNkAwMUA2NzY1NzQ1NTZjNzQ2OTZkNjE3NDY1NDE2ZTczNzc2NTcy", + "signature": "ea1865ccf6d7cbc7312703ab3bd5fd780d286029c03d20cec5f0784ae1a04ab9556e1451be04a8a0e4cec03eaab16e782788a49fae9ef2b09f43f3d683235c07", + "sourceShard": 0, + "destinationShard": 0, + "logs": { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "signalError", + "topics": [ + "geQz5PeDGewXN9wviXwiSXnafo8GYO6dOYXGHRviLjw=" + ], + "data": "QDZlNjU3NzIwNGU0NjU0MjA2NDYxNzQ2MTIwNmY2ZTIwNzM2NTZlNjQ2NTcyMjA2NjZmNzIyMDc0NmY2YjY1NmUyMDU2NGM1MzJkMzEzMTY0MzA2NDMw" + } + ] + }, + "status": "invalid", + "tokens": [ + "TKN-11d0d0-04", + "TKN-11d0d0-05", + "TKN-11d0d0-06" + ], + "esdtValues": [ + "1", + "1", + "1" + ], + "receivers": [ + "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty" + ], + "receiversShardIDs": [ + 0, + 0, + 0 + ], + "operation": "MultiESDTNFTTransfer", + "initiallyPaidFee": "5852440000000000", + "fee": "5852440000000000", + "options": 0 + } +} diff --git a/process/testdata/finishedOKMoveBalance.json b/process/testdata/finishedOKMoveBalance.json new file mode 100644 index 00000000..97c179cd --- /dev/null +++ b/process/testdata/finishedOKMoveBalance.json @@ -0,0 +1,29 @@ +{ + "transaction": { + "type": "normal", + "processingTypeOnSource": "MoveBalance", + "processingTypeOnDestination": "MoveBalance", + "hash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "value": "1500000000000000000", + "receiver": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "sender": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "gasPrice": 1000000000, + "gasLimit": 50000, + "gasUsed": 50000, + "sourceShard": 2, + "destinationShard": 1, + "notarizedAtSourceInMetaNonce": 3000, + "NotarizedAtSourceInMetaHash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "notarizedAtDestinationInMetaNonce": 3000, + "notarizedAtDestinationInMetaHash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "miniblockType": "TxBlock", + "miniblockHash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "status": "success", + "operation": "transfer", + "initiallyPaidFee": "50000000000000", + "fee": "50000000000000", + "chainID": "T", + "version": 1, + "options": 0 + } +} diff --git a/process/testdata/finishedOKRelayedTxWithSCCall.json b/process/testdata/finishedOKRelayedTxWithSCCall.json new file mode 100644 index 00000000..e9ebbc52 --- /dev/null +++ b/process/testdata/finishedOKRelayedTxWithSCCall.json @@ -0,0 +1,144 @@ +{ + "transaction": { + "type": "normal", + "processingTypeOnSource": "RelayedTx", + "processingTypeOnDestination": "RelayedTx", + "hash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "value": "0", + "receiver": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "sender": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "gasPrice": 1000000000, + "gasLimit": 21421000, + "gasUsed": 4970467, + "data": "cmVsYXllZFR4QDdiMjI2ZTZmNmU2MzY1MjIzYTMxMzUzMDMxMzkzMjJjMjI3MzY1NmU2NDY1NzIyMjNhMjI1MzY0MzIzNTU5MzE0YzQyNDU3MTU0Njg2MjU1Mzg2ODc5NDc1ODc3NTU2Zjc3NGY0NjJmNGQ1MDQxMzI2ZjU4NGI2NzMzMzA2YzUzNGI0Yjc1N2E0OTNkMjIyYzIyNzI2NTYzNjU2OTc2NjU3MjIyM2EyMjQxNDE0MTQxNDE0MTQxNDE0MTQxNDE0NjQxNGI1OTMzNzM0ZjJiNzU2YjRmNjQ2ZDQ1NjY0MjRkNjk2OTU4Nzc2NzMxNmQ0NDU4NTk1NzQ3NjgzMzZmM2QyMjJjMjI3NjYxNmM3NTY1MjIzYTMwMmMyMjY3NjE3MzUwNzI2OTYzNjUyMjNhMzEzMDMwMzAzMDMwMzAzMDMwMzAyYzIyNjc2MTczNGM2OTZkNjk3NDIyM2EzMjMwMzAzMDMwMzAzMDMwMmMyMjY0NjE3NDYxMjIzYTIyNTkzMjM5NzU1YTZkNmM3OTYyNTU0NjMwNjQ0NzU2N2E2NDQ3NDYzMDYxNTczOTc1NTE0NDYzMzI0ZDZhNDEzMzVhNmE1OTM0NGU3YTY3MzQ0ZTQ3NGQ3NzRlN2E1NTMzNGQ0NzU5MzM0ZDdhNmI3ODU5NmQ0ZDc3NWE0NDUxN2E0ZDZhNmIzMDRlMzI1NTc4NWE1NDZjNjk0ZDQ0NTk3OTU5NTc0OTMzNTk2YTQxNzg0ZDQ0NGE2YjVhNTQ2YjM0NGY0NDU1MzE0ZDU0NGE2YzU5N2E0NjZhNGQ1NzUyNDE0ZDdhNjc3YTRmNTQ0ZDc5NGQ3YTQ5N2E0ZjU0NGQzMzIyMmMyMjYzNjg2MTY5NmU0OTQ0MjIzYTIyNGQ1MTNkM2QyMjJjMjI3NjY1NzI3MzY5NmY2ZTIyM2EzMTJjMjI3MzY5Njc2ZTYxNzQ3NTcyNjUyMjNhMjI1NDZmN2E3MzM4NzU1MDUyNmI3NDRlNzA0ZDY4NTE0MzQ1NmI1NTY2MzE0ODcyMzg2MTRmNmQ0NTY1Nzc1MDRkNGY2NDc3Njc2OTUyNTI0ZDcyNmY2ODRhMzc0NzUwNmQzNDM5N2EzMDUyMzg3OTU0MzE1YTUxNTA1MTQ5NzA0YzM3NzMyZjZhMzM0NzY1NTk3MTY3NTI3MTJmMzg2ZDRjNjM0ODcxNjM0MzY3M2QzZDIyN2Q=", + "smartContractResults": [ + { + "hash": "SCR-hash1", + "value": 0, + "receiver": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "sender": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "relayerAddress": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "relayedValue": 0, + "data": "confirmAttestation@76207f687884c07570f7391bc0d432947e1e9b062ab7b0102de9885512ec1c1d@383932323937", + "gasLimit": 19806000, + "gasPrice": 1000000000, + "callType": 0, + "logs": { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "writeLog", + "topics": [ + "Sd25Y1LBEqThbU8hyGXwUowOF/MPA2oXKg30lSKKuzI=" + ], + "data": "QDZmNmI=" + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "completedTxEvent", + "topics": [ + "bFkDfjsUiF9492s6DfAw94qorDy0qK6MhXi1m6/NAms=" + ], + "data": null + } + ] + }, + "operation": "transfer", + "function": "confirmAttestation" + }, + { + "hash": "SCR-hash2", + "value": 164505330000000, + "receiver": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "sender": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "returnMessage": "gas refund for relayer", + "operation": "transfer", + "isRefund": true + } + ], + "status": "success", + "receivers": [ + "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty" + ], + "receiversShardIDs": [ + 2 + ], + "operation": "transfer", + "function": "confirmAttestation", + "initiallyPaidFee": "1621000000000000", + "fee": "1456494670000000", + "isRelayed": true, + "chainID": "1", + "version": 1, + "options": 0 + }, + "scrs": [ + { + "type": "unsigned", + "processingTypeOnSource": "SCInvoking", + "processingTypeOnDestination": "SCInvoking", + "hash": "SCR-hash1", + "receiver": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "sender": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "gasPrice": 1000000000, + "gasLimit": 19806000, + "gasUsed": 19806000, + "data": "Y29uZmlybUF0dGVzdGF0aW9uQDc2MjA3ZjY4Nzg4NGMwNzU3MGY3MzkxYmMwZDQzMjk0N2UxZTliMDYyYWI3YjAxMDJkZTk4ODU1MTJlYzFjMWRAMzgzOTMyMzIzOTM3", + "sourceShard": 2, + "destinationShard": 2, + "logs": { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "writeLog", + "topics": [ + "Sd25Y1LBEqThbU8hyGXwUowOF/MPA2oXKg30lSKKuzI=" + ], + "data": "QDZmNmI=" + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "completedTxEvent", + "topics": [ + "bFkDfjsUiF9492s6DfAw94qorDy0qK6MhXi1m6/NAms=" + ], + "data": null + } + ] + }, + "status": "success", + "operation": "transfer", + "function": "confirmAttestation", + "fee": "198060000000000", + "callType": "directCall", + "relayerAddress": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "relayedValue": "0", + "options": 0 + }, + { + "type": "unsigned", + "processingTypeOnSource": "MoveBalance", + "processingTypeOnDestination": "MoveBalance", + "hash": "SCR-hash2", + "value": "164505330000000", + "receiver": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "sender": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "gasPrice": 1000000000, + "gasUsed": 50000, + "returnMessage": "gas refund for relayer", + "sourceShard": 2, + "destinationShard": 2, + "status": "success", + "operation": "transfer", + "fee": "0", + "isRefund": true, + "callType": "directCall", + "options": 0 + } + ] +} diff --git a/process/testdata/finishedOKSCCall.json b/process/testdata/finishedOKSCCall.json new file mode 100644 index 00000000..6b5555ab --- /dev/null +++ b/process/testdata/finishedOKSCCall.json @@ -0,0 +1,161 @@ +{ + "transaction": { + "type": "normal", + "processingTypeOnSource": "BuiltInFunctionCall", + "processingTypeOnDestination": "SCInvoking", + "hash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "value": "0", + "receiver": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "sender": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "data": "", + "sourceShard": 1, + "destinationShard": 1, + "notarizedAtSourceInMetaNonce": 4000, + "NotarizedAtSourceInMetaHash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "notarizedAtDestinationInMetaNonce": 4000, + "notarizedAtDestinationInMetaHash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "miniblockType": "TxBlock", + "miniblockHash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "smartContractResults": [ + { + "hash": "SCR-hash1", + "data": "call", + "gasLimit": 9245500, + "gasPrice": 1000000000, + "callType": 0, + "operation": "transfer", + "function": "call" + }, + { + "hash": "SCR-hash2", + "data": "", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "tokens": [ + "TKN-4ab1d4-069854" + ], + "esdtValues": [ + "24005495464671959870870" + ], + "receivers": [ + "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty" + ], + "receiversShardIDs": [ + 1 + ], + "operation": "ESDTNFTTransfer" + }, + { + "hash": "SCR-hash3", + "nonce": 2064, + "value": 19440250000000, + "data": "@6f6b@00", + "gasLimit": 0, + "gasPrice": 1000000000, + "callType": 0, + "operation": "transfer", + "isRefund": true + } + ], + "logs": { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "MultiESDTNFTTransfer", + "topics": [ + "UklERS03ZDE4ZTk=" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "MultiESDTNFTTransfer", + "topics": [ + "U1JJREUtNGFiMWQ0" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "ESDTNFTCreate", + "topics": [ + "U1JJREUtNGFiMWQ0" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "ESDTNFTBurn", + "topics": [ + "U1JJREUtNGFiMWQ0" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "ESDTNFTTransfer", + "topics": [ + "U1JJREUtNGFiMWQ0" + ], + "data": null + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "stakeFarm", + "topics": [ + "ZW50ZXJfZmFybQ==" + ], + "data": "" + }, + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "completedTxEvent", + "topics": [ + "g7AzrmRz5JrxEAon3ulthhbnf8+auxoCULhB0Spu0nA=" + ], + "data": null + } + ] + }, + "status": "success", + "tokens": [ + "TKN-7d18e9", + "MIIU-4ab1d4-0695ed" + ], + "esdtValues": [ + "1000000000000000000000", + "23005495464671959870870" + ], + "receivers": [ + "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty" + ], + "receiversShardIDs": [ + 1, + 1 + ], + "operation": "MultiESDTNFTTransfer", + "function": "call", + "initiallyPaidFee": "450955000000000", + "fee": "431514750000000", + "chainID": "T", + "version": 1, + "options": 0 + }, + "scrs": [ + { + "type": "unsigned", + "hash": "SCR-hash1" + }, + { + "type": "unsigned", + "hash": "SCR-hash2" + }, + { + "type": "unsigned", + "hash": "SCR-hash3" + } + ] +} diff --git a/process/testdata/finishedOKSCDeploy.json b/process/testdata/finishedOKSCDeploy.json new file mode 100644 index 00000000..e4d39edd --- /dev/null +++ b/process/testdata/finishedOKSCDeploy.json @@ -0,0 +1,46 @@ +{ + "transaction": { + "type": "normal", + "processingTypeOnSource": "SCDeployment", + "processingTypeOnDestination": "SCDeployment", + "hash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "value": "0", + "receiver": "erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu", + "sender": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "gasPrice": 1000000000, + "gasLimit": 550000000, + "gasUsed": 550000000, + "data": "MDA2MTczNmQwMTAwMDAwMDAxMTUwNDYwMDM3ZjdmN2UwMTdmNjAwMjdmN2YwMTdlNjAwMTdlMDA2MDAwMDAwMjQyMDMwMzY1NmU3NjExNjk2ZTc0MzYzNDczNzQ2ZjcyNjE2NzY1NTM3NDZmNzI2NTAwMDAwMzY1NmU3NjEwNjk2ZTc0MzYzNDczNzQ2ZjcyNjE2NzY1NGM2ZjYxNjQwMDAxMDM2NTZlNzYwYjY5NmU3NDM2MzQ2NjY5NmU2OTczNjgwMDAyMDMwNDAzMDMwMzAzMDQwNTAxNzAwMTAxMDEwNTAzMDEwMDAyMDYwODAxN2YwMTQxYTA4ODA0MGIwNzJhMDQwNjZkNjU2ZDZmNzI3OTAyMDAwODYzNjE2YzZjNDI2MTYzNmIwMDAzMDY2MzYxNmM2YzRkNjUwMDA0MDk2ZTc1NmQ0MzYxNmM2YzY1NjQwMDA1MGEzZTAzMDIwMDBiMjIwMDQxODA4ODgwODAwMDQxMjA0MTgwODg4MDgwMDA0MTIwMTA4MTgwODA4MDAwNDIwMTdjMTA4MDgwODA4MDAwMWEwYjE2MDA0MTgwODg4MDgwMDA0MTIwMTA4MTgwODA4MDAwMTA4MjgwODA4MDAwMGIwYjI3MDEwMDQxODAwODBiMjAyYTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDJhQDA1MDBAMDUwMA==", + "signature": "3e83a487b13bc46e9a80f67a552f878c21fe6ffb8c0a172b9807f2ddc3d8598a50a8569fc56c630b0e01af384962e201981beaa949b7a09a64d68ffb4aba2407", + "sourceShard": 0, + "destinationShard": 0, + "logs": { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "events": [ + { + "address": "erd1adfmxhyczrl2t97yx92v5nywqyse0c7qh4xs0p4artg2utnu90pspgvqty", + "identifier": "SCDeploy", + "topics": [ + "AAAAAAAAAAAFAI/gqaFAmqjqwl6V7SHtxjqOsCioLjw=" + ], + "data": null + }, + { + "address": "erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu", + "identifier": "writeLog", + "topics": [ + "geQz5PeDGewXN9wviXwiSXnafo8GYO6dOYXGHRviLjw=" + ], + "data": "QDZmNmI=" + } + ] + }, + "status": "success", + "operation": "scDeploy", + "initiallyPaidFee": "6384070000000000", + "fee": "6384070000000000", + "chainID": "1", + "version": 1, + "options": 0 + } +} diff --git a/process/testdata/pendingNewMoveBalance.json b/process/testdata/pendingNewMoveBalance.json new file mode 100644 index 00000000..e0e88223 --- /dev/null +++ b/process/testdata/pendingNewMoveBalance.json @@ -0,0 +1,23 @@ +{ + "transaction": { + "type": "normal", + "processingTypeOnSource": "MoveBalance", + "processingTypeOnDestination": "MoveBalance", + "hash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "value": "1500000000000000000", + "gasPrice": 1000000000, + "gasLimit": 50000, + "gasUsed": 50000, + "sourceShard": 2, + "destinationShard": 1, + "miniblockType": "TxBlock", + "miniblockHash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "status": "pending", + "operation": "transfer", + "initiallyPaidFee": "50000000000000", + "fee": "50000000000000", + "chainID": "T", + "version": 1, + "options": 0 + } +} diff --git a/process/testdata/pendingNewSCCall.json b/process/testdata/pendingNewSCCall.json new file mode 100644 index 00000000..c824e4e4 --- /dev/null +++ b/process/testdata/pendingNewSCCall.json @@ -0,0 +1,25 @@ +{ + "transaction": { + "type": "normal", + "processingTypeOnSource": "MoveBalance", + "processingTypeOnDestination": "SCInvoking", + "hash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "value": "0", + "gasPrice": 1000000000, + "gasLimit": 40000000, + "gasUsed": 1433000, + "data": "", + "sourceShard": 0, + "destinationShard": 1, + "miniblockType": "TxBlock", + "miniblockHash": "a4823050d2396540b17bd9290523973763142c9f655bb26cd9e33f359b6d73ad", + "status": "pending", + "operation": "transfer", + "function": "call", + "initiallyPaidFee": "1818670000000000", + "fee": "1433000000000000", + "chainID": "T", + "version": 1, + "options": 0 + } +} diff --git a/process/transactionProcessor.go b/process/transactionProcessor.go index 0ffae029..317e7949 100644 --- a/process/transactionProcessor.go +++ b/process/transactionProcessor.go @@ -30,16 +30,15 @@ const TransactionSimulatePath = "/transaction/simulate" // MultipleTransactionsPath defines the multiple transactions send path of the node const MultipleTransactionsPath = "/transaction/send-multiple" -// UnknownStatusTx defines the response that should be received from an observer when transaction status is unknown -const UnknownStatusTx = "unknown" - const ( - withResultsParam = "?withResults=true" - checkSignatureFalse = "?checkSignature=false" - bySenderParam = "&by-sender=" - fieldsParam = "?fields=" - lastNonceParam = "?last-nonce=true" - nonceGapsParam = "?nonce-gaps=true" + withResultsParam = "?withResults=true" + checkSignatureFalse = "?checkSignature=false" + bySenderParam = "&by-sender=" + fieldsParam = "?fields=" + lastNonceParam = "?last-nonce=true" + nonceGapsParam = "?nonce-gaps=true" + internalVMErrorsEventIdentifier = "internalVMErrors" // TODO export this in mx-chain-core-go, remove unexported definitions from mx-chain-vm's + moveBalanceDescriptor = "MoveBalance" ) type requestType int @@ -350,6 +349,7 @@ func (tp *TransactionProcessor) GetTransaction(txHash string, withResults bool) tx.HyperblockNonce = tx.NotarizedAtDestinationInMetaNonce tx.HyperblockHash = tx.NotarizedAtDestinationInMetaHash + return tx, nil } @@ -357,9 +357,9 @@ func (tp *TransactionProcessor) GetTransaction(txHash string, withResults bool) func (tp *TransactionProcessor) GetTransactionByHashAndSenderAddress( txHash string, sndAddr string, - withEvents bool, + withResults bool, ) (*transaction.ApiTransactionResult, int, error) { - tx, err := tp.getTxWithSenderAddr(txHash, sndAddr, withEvents) + tx, err := tp.getTxWithSenderAddr(txHash, sndAddr, withResults) if err != nil { return nil, http.StatusNotFound, err } @@ -388,22 +388,145 @@ func (tp *TransactionProcessor) getShardByAddress(address string) (uint32, error // GetTransactionStatus returns the status of a transaction func (tp *TransactionProcessor) GetTransactionStatus(txHash string, sender string) (string, error) { - if sender != "" { - tx, err := tp.getTxWithSenderAddr(txHash, sender, false) - if err != nil { - return UnknownStatusTx, err - } + tx, err := tp.getTransaction(txHash, sender, false) + if err != nil { + return string(data.TxStatusUnknown), err + } - return string(tx.Status), nil + return string(tx.Status), nil +} + +func (tp *TransactionProcessor) getTransaction(txHash string, sender string, withResults bool) (*transaction.ApiTransactionResult, error) { + if sender != "" { + return tp.getTxWithSenderAddr(txHash, sender, withResults) } // get status of transaction from random observers - tx, err := tp.getTxFromObservers(txHash, requestTypeObservers, false) + return tp.getTxFromObservers(txHash, requestTypeObservers, withResults) +} + +// GetProcessedTransactionStatus returns the status of a transaction after local processing +func (tp *TransactionProcessor) GetProcessedTransactionStatus(txHash string) (string, error) { + const withResults = true + tx, err := tp.getTxFromObservers(txHash, requestTypeObservers, withResults) if err != nil { - return UnknownStatusTx, errors.ErrTransactionNotFound + return string(data.TxStatusUnknown), err } - return string(tx.Status), nil + return string(tp.computeTransactionStatus(tx, withResults)), nil +} + +func (tp *TransactionProcessor) computeTransactionStatus(tx *transaction.ApiTransactionResult, withResults bool) transaction.TxStatus { + if !withResults { + return data.TxStatusUnknown + } + + if tx.Status == transaction.TxStatusInvalid { + return transaction.TxStatusFail + } + if tx.Status != transaction.TxStatusSuccess { + return tx.Status + } + + if checkIfMoveBalanceNotarized(tx) { + return tx.Status + } + + txLogsOnFirstLevel := []*transaction.ApiLogs{tx.Logs} + if checkIfFailed(txLogsOnFirstLevel) { + return transaction.TxStatusFail + } + + allLogs, err := tp.gatherAllLogs(tx) + if err != nil { + log.Warn("error in TransactionProcessor.computeTransactionStatus", "error", err) + return data.TxStatusUnknown + } + if checkIfFailed(allLogs) { + return transaction.TxStatusFail + } + + if checkIfCompleted(allLogs) { + return transaction.TxStatusSuccess + } + + return transaction.TxStatusPending +} + +func checkIfFailed(logs []*transaction.ApiLogs) bool { + if findIdentifierInLogs(logs, internalVMErrorsEventIdentifier) || + findIdentifierInLogs(logs, core.SignalErrorOperation) { + return true + } + + return false +} + +func checkIfCompleted(logs []*transaction.ApiLogs) bool { + if findIdentifierInLogs(logs, core.CompletedTxEventIdentifier) || + findIdentifierInLogs(logs, core.SCDeployIdentifier) { + return true + } + + return false +} + +func checkIfMoveBalanceNotarized(tx *transaction.ApiTransactionResult) bool { + isNotarized := tx.NotarizedAtSourceInMetaNonce > 0 && tx.NotarizedAtDestinationInMetaNonce > 0 + if !isNotarized { + return false + } + isMoveBalance := tx.ProcessingTypeOnSource == moveBalanceDescriptor && tx.ProcessingTypeOnDestination == moveBalanceDescriptor + if !isMoveBalance { + return false + } + + return true +} + +func findIdentifierInLogs(logs []*transaction.ApiLogs, identifier string) bool { + if len(logs) == 0 { + return false + } + + for _, logInstance := range logs { + if logInstance == nil { + continue + } + + found := findIdentifierInSingleLog(logInstance, identifier) + if found { + return true + } + } + + return false +} + +func findIdentifierInSingleLog(log *transaction.ApiLogs, identifier string) bool { + for _, event := range log.Events { + if event.Identifier == identifier { + return true + } + } + + return false +} + +func (tp *TransactionProcessor) gatherAllLogs(tx *transaction.ApiTransactionResult) ([]*transaction.ApiLogs, error) { + const withResults = true + allLogs := []*transaction.ApiLogs{tx.Logs} + + for _, scrFromTx := range tx.SmartContractResults { + scr, err := tp.GetTransaction(scrFromTx.Hash, withResults) + if err != nil { + return nil, fmt.Errorf("%w for scr hash %s", err, scrFromTx.Hash) + } + + allLogs = append(allLogs, scr.Logs) + } + + return allLogs, nil } func (tp *TransactionProcessor) getTxFromObservers(txHash string, reqType requestType, withResults bool) (*transaction.ApiTransactionResult, error) { @@ -492,14 +615,14 @@ func (tp *TransactionProcessor) alterTxWithScResultsFromSourceIfNeeded(txHash st return tx } -func (tp *TransactionProcessor) getTxWithSenderAddr(txHash, sender string, withEvents bool) (*transaction.ApiTransactionResult, error) { +func (tp *TransactionProcessor) getTxWithSenderAddr(txHash, sender string, withResults bool) (*transaction.ApiTransactionResult, error) { observers, sndShardID, err := tp.getShardObserversForSender(sender, requestTypeFullHistoryNodes) if err != nil { return nil, err } for _, observer := range observers { - getTxResponse, ok, _ := tp.getTxFromObserver(observer, txHash, withEvents) + getTxResponse, ok, _ := tp.getTxFromObserver(observer, txHash, withResults) if !ok { continue } @@ -516,9 +639,9 @@ func (tp *TransactionProcessor) getTxWithSenderAddr(txHash, sender string, withE return &getTxResponse.Data.Transaction, nil } - txFromDstShard, ok := tp.getTxFromDestShard(txHash, rcvShardID, withEvents) + txFromDstShard, ok := tp.getTxFromDestShard(txHash, rcvShardID, withResults) if ok { - alteredTxFromDest := tp.mergeScResultsFromSourceAndDestIfNeeded(&getTxResponse.Data.Transaction, txFromDstShard, withEvents) + alteredTxFromDest := tp.mergeScResultsFromSourceAndDestIfNeeded(&getTxResponse.Data.Transaction, txFromDstShard, withResults) return alteredTxFromDest, nil } diff --git a/process/transactionProcessor_test.go b/process/transactionProcessor_test.go index 2b8a5b7d..5d39bd3e 100644 --- a/process/transactionProcessor_test.go +++ b/process/transactionProcessor_test.go @@ -3,7 +3,10 @@ package process_test import ( "bytes" "encoding/hex" + "encoding/json" "errors" + "fmt" + "io/ioutil" "math/big" "net/http" "strings" @@ -33,6 +36,65 @@ var funcNewTxCostHandler = func() (process.TransactionCostHandler, error) { } var logsMerger, _ = logsevents.NewLogsMerger(hasher, &marshal.JsonMarshalizer{}) +var testPubkeyConverter, _ = pubkeyConverter.NewBech32PubkeyConverter(32, &mock.LoggerStub{}) + +type scenarioData struct { + Transaction *transaction.ApiTransactionResult `json:"transaction"` + SCRs []*transaction.ApiTransactionResult `json:"scrs"` +} + +func loadJsonIntoTxAndScrs(tb testing.TB, path string) *scenarioData { + scenarioDataInstance := &scenarioData{} + buff, err := ioutil.ReadFile(path) + require.Nil(tb, err) + + err = json.Unmarshal(buff, scenarioDataInstance) + require.Nil(tb, err) + + return scenarioDataInstance +} + +func createTestProcessorFromScenarioData(testData *scenarioData) *process.TransactionProcessor { + processorStub := &mock.ProcessorStub{ + GetShardIDsCalled: func() []uint32 { + return []uint32{0} // force everything intra-shard for test setup simplicity + }, + ComputeShardIdCalled: func(addressBuff []byte) (uint32, error) { + return 0, nil + }, + GetObserversCalled: func(shardId uint32) ([]*data.NodeData, error) { + return []*data.NodeData{ + { + Address: "test", + ShardId: 0, + }, + }, nil + }, + CallGetRestEndPointCalled: func(address string, path string, value interface{}) (int, error) { + for _, scr := range testData.SCRs { + if strings.Contains(path, scr.Hash) { + response := value.(*data.GetTransactionResponse) + response.Data.Transaction = *scr + return http.StatusOK, nil + } + } + + return http.StatusInternalServerError, fmt.Errorf("not found") + }, + } + + tp, _ := process.NewTransactionProcessor( + processorStub, + testPubkeyConverter, + hasher, + marshalizer, + funcNewTxCostHandler, + logsMerger, + false, + ) + + return tp +} func TestNewTransactionProcessor_NilCoreProcessorShouldErr(t *testing.T) { t.Parallel() @@ -766,7 +828,7 @@ func TestTransactionProcessor_GetTransactionStatusWithSenderInvaidSender(t *test txStatus, err := tp.GetTransactionStatus(string(hash0), "blablabla") assert.Error(t, err) - assert.Equal(t, process.UnknownStatusTx, txStatus) + assert.Equal(t, string(data.TxStatusUnknown), txStatus) } func TestTransactionProcessor_GetTransactionStatusWithSenderAddressIntraShard(t *testing.T) { @@ -1192,9 +1254,21 @@ func TestTransactionProcessor_GetTransactionWithEventsFirstFromDstShardAndAfterS return nil, nil }, CallGetRestEndPointCalled: func(address string, path string, value interface{}) (i int, err error) { - if address == addrObs1 { - responseGetTx := value.(*data.GetTransactionResponse) + responseGetTx := value.(*data.GetTransactionResponse) + if strings.Contains(path, scHash1) { + responseGetTx.Data.Transaction.Hash = scHash1 + return http.StatusOK, nil + } + if strings.Contains(path, scHash2) { + responseGetTx.Data.Transaction.Hash = scHash2 + return http.StatusOK, nil + } + if strings.Contains(path, scHash3) { + responseGetTx.Data.Transaction.Hash = scHash3 + return http.StatusOK, nil + } + if address == addrObs1 { responseGetTx.Data.Transaction = transaction.ApiTransactionResult{ Sender: sndrShard0, Receiver: rcvShard1, @@ -1204,11 +1278,10 @@ func TestTransactionProcessor_GetTransactionWithEventsFirstFromDstShardAndAfterS SmartContractResults: []*transaction.ApiSmartContractResult{ scRes1, scRes2, }, + Status: transaction.TxStatusSuccess, } return http.StatusOK, nil } else if address == addrObs0 { - responseGetTx := value.(*data.GetTransactionResponse) - responseGetTx.Data.Transaction = transaction.ApiTransactionResult{ Nonce: expectedNonce, SourceShard: 0, @@ -1216,6 +1289,7 @@ func TestTransactionProcessor_GetTransactionWithEventsFirstFromDstShardAndAfterS SmartContractResults: []*transaction.ApiSmartContractResult{ scRes2, scRes3, }, + Status: transaction.TxStatusSuccess, } return http.StatusOK, nil } @@ -1686,3 +1760,201 @@ func TestTransactionProcessor_GetTransactionPool(t *testing.T) { assert.Equal(t, providedGaps, nonceGaps.Gaps) }) } + +func TestTransactionProcessor_computeTransactionStatus(t *testing.T) { + t.Parallel() + + t.Run("no results should return unknown", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/pendingNewMoveBalance.json") + tp := createTestProcessorFromScenarioData(testData) + status := tp.ComputeTransactionStatus(testData.Transaction, false) + require.Equal(t, data.TxStatusUnknown, status) + }) + withResults := true + t.Run("Move balance", func(t *testing.T) { + t.Run("pending", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/pendingNewMoveBalance.json") + tp := createTestProcessorFromScenarioData(testData) + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, transaction.TxStatusPending, status) + }) + t.Run("executed", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedOKMoveBalance.json") + tp := createTestProcessorFromScenarioData(testData) + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, transaction.TxStatusSuccess, status) + }) + }) + t.Run("SC calls", func(t *testing.T) { + t.Run("pending new", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/pendingNewSCCall.json") + tp := createTestProcessorFromScenarioData(testData) + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, transaction.TxStatusPending, status) + }) + t.Run("executing", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/executingSCCall.json") + tp := createTestProcessorFromScenarioData(testData) + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, transaction.TxStatusPending, status) + }) + t.Run("tx ok", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedOKSCCall.json") + tp := createTestProcessorFromScenarioData(testData) + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, transaction.TxStatusSuccess, status) + }) + t.Run("tx ok but with nil logs", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedOKSCCall.json") + tp := createTestProcessorFromScenarioData(testData) + testData.Transaction.Logs = nil + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, transaction.TxStatusPending, status) + }) + t.Run("tx failed", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedFailedSCCall.json") + tp := createTestProcessorFromScenarioData(testData) + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, transaction.TxStatusFail, status) + }) + }) + t.Run("SC deploy", func(t *testing.T) { + t.Run("tx ok", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedOKSCDeploy.json") + tp := createTestProcessorFromScenarioData(testData) + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, transaction.TxStatusSuccess, status) + }) + }) + t.Run("complex scenarios with failed async calls", func(t *testing.T) { + t.Run("scenario 1: tx failed with ESDTs and SC calls", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedFailedComplexScenario1.json") + tp := createTestProcessorFromScenarioData(testData) + + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, transaction.TxStatusFail, status) + }) + t.Run("scenario 2: tx failed with ESDTs and SC calls", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedFailedComplexScenario2.json") + tp := createTestProcessorFromScenarioData(testData) + + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, transaction.TxStatusFail, status) + }) + t.Run("scenario 3: tx failed with ESDTs and SC calls", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedFailedComplexScenario3.json") + tp := createTestProcessorFromScenarioData(testData) + + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, transaction.TxStatusFail, status) + }) + }) + t.Run("relayed transaction", func(t *testing.T) { + t.Run("failed relayed transaction un-executable", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedFailedRelayedTxUnexecutable.json") + tp := createTestProcessorFromScenarioData(testData) + + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, transaction.TxStatusFail, status) + }) + t.Run("failed relayed transaction with SC call", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedFailedRelayedTxWithSCCall.json") + tp := createTestProcessorFromScenarioData(testData) + + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, transaction.TxStatusFail, status) + }) + t.Run("tx ok", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedOKRelayedTxWithSCCall.json") + tp := createTestProcessorFromScenarioData(testData) + + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, transaction.TxStatusSuccess, status) + }) + }) + t.Run("invalid transaction", func(t *testing.T) { + t.Parallel() + + testData := loadJsonIntoTxAndScrs(t, "./testdata/finishedInvalidBuiltinFunction.json") + tp := createTestProcessorFromScenarioData(testData) + + status := tp.ComputeTransactionStatus(testData.Transaction, withResults) + require.Equal(t, transaction.TxStatusFail, status) + }) +} + +func TestTransactionProcessor_GetProcessedTransactionStatus(t *testing.T) { + t.Parallel() + + hash0 := []byte("hash0") + providedShardId := uint32(0) + observerAddress := "observer address" + tp, _ := process.NewTransactionProcessor( + &mock.ProcessorStub{ + ComputeShardIdCalled: func(addressBuff []byte) (uint32, error) { + return providedShardId, nil + }, + GetObserversCalled: func(shardId uint32) ([]*data.NodeData, error) { + require.Equal(t, providedShardId, shardId) + return []*data.NodeData{ + { + Address: observerAddress, + ShardId: providedShardId, + }, + }, nil + }, + GetShardIDsCalled: func() []uint32 { + return []uint32{providedShardId} + }, + CallGetRestEndPointCalled: func(address string, path string, value interface{}) (i int, err error) { + assert.Contains(t, path, string(hash0)) + + txResponse := value.(*data.GetTransactionResponse) + txResponse.Data.Transaction.Nonce = 0 + txResponse.Data.Transaction.Status = transaction.TxStatusSuccess + + return http.StatusOK, nil + }, + }, + &mock.PubKeyConverterMock{}, + hasher, + marshalizer, + funcNewTxCostHandler, + logsMerger, + true, + ) + + status, err := tp.GetProcessedTransactionStatus(string(hash0)) + assert.Nil(t, err) + assert.Equal(t, string(transaction.TxStatusPending), status) // not a move balance tx with missing finish markers +}