Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inner transactions in operations index #298

Open
wants to merge 10 commits into
base: rc/v1.7.next1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions data/scresult.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ type ScResult struct {
SenderAddressBytes []byte `json:"-"`
InitialTxGasUsed uint64 `json:"-"`
InitialTxFee string `json:"-"`
GasRefunded uint64 `json:"-"`
}
129 changes: 76 additions & 53 deletions data/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,59 @@ package data

import (
"time"

"github.com/multiversx/mx-chain-core-go/data/transaction"
)

// Transaction is a structure containing all the fields that need
// to be saved for a transaction. It has all the default fields
// plus some extra information for ease of search and filter
type Transaction struct {
MBHash string `json:"miniBlockHash"`
Nonce uint64 `json:"nonce"`
Round uint64 `json:"round"`
Value string `json:"value"`
ValueNum float64 `json:"valueNum"`
Receiver string `json:"receiver"`
Sender string `json:"sender"`
ReceiverShard uint32 `json:"receiverShard"`
SenderShard uint32 `json:"senderShard"`
GasPrice uint64 `json:"gasPrice"`
GasLimit uint64 `json:"gasLimit"`
GasUsed uint64 `json:"gasUsed"`
Fee string `json:"fee"`
FeeNum float64 `json:"feeNum"`
InitialPaidFee string `json:"initialPaidFee,omitempty"`
Data []byte `json:"data"`
Signature string `json:"signature"`
Timestamp time.Duration `json:"timestamp"`
Status string `json:"status"`
SearchOrder uint32 `json:"searchOrder"`
SenderUserName []byte `json:"senderUserName,omitempty"`
ReceiverUserName []byte `json:"receiverUserName,omitempty"`
HasSCR bool `json:"hasScResults,omitempty"`
IsScCall bool `json:"isScCall,omitempty"`
HasOperations bool `json:"hasOperations,omitempty"`
HasLogs bool `json:"hasLogs,omitempty"`
Tokens []string `json:"tokens,omitempty"`
ESDTValues []string `json:"esdtValues,omitempty"`
ESDTValuesNum []float64 `json:"esdtValuesNum,omitempty"`
Receivers []string `json:"receivers,omitempty"`
ReceiversShardIDs []uint32 `json:"receiversShardIDs,omitempty"`
Type string `json:"type,omitempty"`
Operation string `json:"operation,omitempty"`
Function string `json:"function,omitempty"`
IsRelayed bool `json:"isRelayed,omitempty"`
Version uint32 `json:"version,omitempty"`
GuardianAddress string `json:"guardian,omitempty"`
GuardianSignature string `json:"guardianSignature,omitempty"`
ErrorEvent bool `json:"errorEvent,omitempty"`
CompletedEvent bool `json:"completedEvent,omitempty"`
RelayedAddr string `json:"relayed,omitempty"`
InnerTransactions []*transaction.FrontendTransaction `json:"innerTransactions,omitempty"`
ExecutionOrder int `json:"-"`
SmartContractResults []*ScResult `json:"-"`
Hash string `json:"-"`
BlockHash string `json:"-"`
HadRefund bool `json:"-"`
MBHash string `json:"miniBlockHash"`
Nonce uint64 `json:"nonce"`
Round uint64 `json:"round"`
Value string `json:"value"`
ValueNum float64 `json:"valueNum"`
Receiver string `json:"receiver"`
Sender string `json:"sender"`
ReceiverShard uint32 `json:"receiverShard"`
SenderShard uint32 `json:"senderShard"`
GasPrice uint64 `json:"gasPrice"`
GasLimit uint64 `json:"gasLimit"`
GasUsed uint64 `json:"gasUsed"`
Fee string `json:"fee"`
FeeNum float64 `json:"feeNum"`
InitialPaidFee string `json:"initialPaidFee,omitempty"`
Data []byte `json:"data"`
Signature string `json:"signature"`
Timestamp time.Duration `json:"timestamp"`
Status string `json:"status"`
SearchOrder uint32 `json:"searchOrder"`
SenderUserName []byte `json:"senderUserName,omitempty"`
ReceiverUserName []byte `json:"receiverUserName,omitempty"`
HasSCR bool `json:"hasScResults,omitempty"`
IsScCall bool `json:"isScCall,omitempty"`
HasOperations bool `json:"hasOperations,omitempty"`
HasLogs bool `json:"hasLogs,omitempty"`
Tokens []string `json:"tokens,omitempty"`
ESDTValues []string `json:"esdtValues,omitempty"`
ESDTValuesNum []float64 `json:"esdtValuesNum,omitempty"`
Receivers []string `json:"receivers,omitempty"`
ReceiversShardIDs []uint32 `json:"receiversShardIDs,omitempty"`
Type string `json:"type,omitempty"`
Operation string `json:"operation,omitempty"`
Function string `json:"function,omitempty"`
IsRelayed bool `json:"isRelayed,omitempty"`
Version uint32 `json:"version,omitempty"`
GuardianAddress string `json:"guardian,omitempty"`
GuardianSignature string `json:"guardianSignature,omitempty"`
ErrorEvent bool `json:"errorEvent,omitempty"`
CompletedEvent bool `json:"completedEvent,omitempty"`
RelayedAddr string `json:"relayed,omitempty"`
InnerTransactions []*InnerTransaction `json:"innerTransactions,omitempty"`
ExecutionOrder int `json:"-"`
SmartContractResults []*ScResult `json:"-"`
Hash string `json:"-"`
BlockHash string `json:"-"`
HadRefund bool `json:"-"`
}

// Receipt is a structure containing all the fields that need to be safe for a Receipt
Expand Down Expand Up @@ -91,8 +89,33 @@ type ResponseTransactionDB struct {

// FeeData is the structure that contains data about transaction fee and gas used
type FeeData struct {
FeeNum float64
Fee string
GasUsed uint64
Receiver string
FeeNum float64
Fee string
GasUsed uint64
Receiver string
GasRefunded uint64
}

// InnerTransaction is the structure that contains data about an inner transaction
type InnerTransaction struct {
ID string `json:"-"`
Hash string `json:"hash,omitempty"`
Type string `json:"type,omitempty"`
Nonce uint64 `json:"nonce"`
Value string `json:"value"`
Receiver string `json:"receiver"`
Sender string `json:"sender"`
SenderUsername []byte `json:"senderUsername,omitempty"`
ReceiverUsername []byte `json:"receiverUsername,omitempty"`
GasPrice uint64 `json:"gasPrice"`
GasLimit uint64 `json:"gasLimit"`
Data []byte `json:"data,omitempty"`
Signature string `json:"signature,omitempty"`
ChainID string `json:"chainID"`
Version uint32 `json:"version"`
Options uint32 `json:"options,omitempty"`
GuardianAddr string `json:"guardian,omitempty"`
GuardianSignature string `json:"guardianSignature,omitempty"`
Relayer string `json:"relayer,omitempty"`
RelayedTxHash string `json:"relayedTxHash,omitempty"`
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/gin-contrib/cors v1.4.0
github.com/gin-gonic/gin v1.9.1
github.com/multiversx/mx-chain-communication-go v1.1.0
github.com/multiversx/mx-chain-core-go v1.2.21
github.com/multiversx/mx-chain-core-go v1.2.23-0.20241018055916-203f32de05ad
github.com/multiversx/mx-chain-logger-go v1.0.15
github.com/multiversx/mx-chain-vm-common-go v1.5.13
github.com/prometheus/client_model v0.4.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,8 @@ github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/multiversx/mx-chain-communication-go v1.1.0 h1:J7bX6HoN3HiHY7cUeEjG8AJWgQDDPcY+OPDOsSUOkRE=
github.com/multiversx/mx-chain-communication-go v1.1.0/go.mod h1:WK6bP4pGEHGDDna/AYRIMtl6G9OA0NByI1Lw8PmOnRM=
github.com/multiversx/mx-chain-core-go v1.2.21 h1:+XVKznPTlUU5EFS1A8chtS8fStW60upRIyF4Pgml19I=
github.com/multiversx/mx-chain-core-go v1.2.21/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE=
github.com/multiversx/mx-chain-core-go v1.2.23-0.20241018055916-203f32de05ad h1:EFWFNts9am6Dp+tJxYiHfsepK4TF0J931mTEZ3Aireo=
github.com/multiversx/mx-chain-core-go v1.2.23-0.20241018055916-203f32de05ad/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE=
github.com/multiversx/mx-chain-crypto-go v1.2.12 h1:zWip7rpUS4CGthJxfKn5MZfMfYPjVjIiCID6uX5BSOk=
github.com/multiversx/mx-chain-logger-go v1.0.15 h1:HlNdK8etyJyL9NQ+6mIXyKPEBo+wRqOwi3n+m2QIHXc=
github.com/multiversx/mx-chain-logger-go v1.0.15/go.mod h1:t3PRKaWB1M+i6gUfD27KXgzLJJC+mAQiN+FLlL1yoGQ=
Expand Down
151 changes: 151 additions & 0 deletions integrationtests/relayedTxV3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,19 @@ func TestRelayedTxV3(t *testing.T) {
readExpectedResult("./testdata/relayedTxV3/relayed-tx-v3.json"),
string(genericResponse.Docs[0].Source),
)

ids = []string{"90cb33aad72cca66ec5f6caace6bdd7a8eb5b36b6d4e02b2712d264a9c53d7b8", "33e70412cb96952914955ad0497e0a4505dfbc795917c4488632f0a53bd05c2a"}
err = esClient.DoMultiGet(context.Background(), ids, indexerdata.OperationsIndex, true, genericResponse)
require.Nil(t, err)

require.JSONEq(t,
readExpectedResult("./testdata/relayedTxV3/innerTx1.json"),
string(genericResponse.Docs[0].Source),
)
require.JSONEq(t,
readExpectedResult("./testdata/relayedTxV3/innerTx2.json"),
string(genericResponse.Docs[1].Source),
)
}

func TestRelayedTxV3WithSignalErrorAndCompletedEvent(t *testing.T) {
Expand Down Expand Up @@ -367,3 +380,141 @@ func TestRelayedV3WithSCRCross(t *testing.T) {
string(genericResponse.Docs[0].Source),
)
}

func TestRelayedV3TransactionWithMultipleRefunds(t *testing.T) {
setLogLevelDebug()

esClient, err := createESClient(esURL)
require.Nil(t, err)

esProc, err := CreateElasticProcessor(esClient)
require.Nil(t, err)

txHash := []byte("relayedTxV3WithMultipleRefunds")
header := &dataBlock.Header{
Round: 50,
TimeStamp: 5040,
}

body := &dataBlock.Body{
MiniBlocks: dataBlock.MiniBlockSlice{
{
Type: dataBlock.TxBlock,
SenderShardID: 0,
ReceiverShardID: 0,
TxHashes: [][]byte{txHash},
},
},
}

initialTx := &transaction.Transaction{
Nonce: 1000,
SndAddr: decodeAddress("erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a"),
RcvAddr: decodeAddress("erd1ykqd64fxxpp4wsz0v7sjqem038wfpzlljhx4mhwx8w9lcxmdzcfszrp64a"),
GasLimit: 500_000_000,
GasPrice: 1000000000,
Value: big.NewInt(0),
InnerTransactions: []*transaction.Transaction{
{
Nonce: 5,
SndAddr: decodeAddress("erd10ksryjr065ad5475jcg82pnjfg9j9qtszjsrp24anl6ym7cmeddshwnru8"),
RcvAddr: decodeAddress("erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r"),
GasLimit: 60_000_000,
GasPrice: 1000000000,
Value: big.NewInt(10000000000000000),
Data: []byte("doSomething"),
},
{
Nonce: 3,
SndAddr: decodeAddress("erd10ksryjr065ad5475jcg82pnjfg9j9qtszjsrp24anl6ym7cmeddshwnru8"),
RcvAddr: decodeAddress("erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r"),
GasLimit: 60_000_000,
GasPrice: 1000000000,
Value: big.NewInt(10000000000000000),
Data: []byte("doSomething"),
},
},
}

txInfo := &outport.TxInfo{
Transaction: initialTx,
FeeInfo: &outport.FeeInfo{
GasUsed: 180_150_000,
Fee: big.NewInt(2864760000000000),
InitialPaidFee: big.NewInt(2864760000000000),
},
ExecutionOrder: 0,
}

pool := &outport.TransactionPool{
Transactions: map[string]*outport.TxInfo{
hex.EncodeToString(txHash): txInfo,
},
}
err = esProc.SaveTransactions(createOutportBlockWithHeader(body, header, pool, nil, testNumOfShards))
require.Nil(t, err)

ids := []string{hex.EncodeToString(txHash)}
genericResponse := &GenericResponse{}
err = esClient.DoMultiGet(context.Background(), ids, indexerdata.TransactionsIndex, true, genericResponse)
require.Nil(t, err)

require.JSONEq(t,
readExpectedResult("./testdata/relayedTxV3/relayed-v3-no-refund.json"),
string(genericResponse.Docs[0].Source),
)

// execute first SCR with refund
pool = &outport.TransactionPool{
SmartContractResults: map[string]*outport.SCRInfo{
"scrHash": {
SmartContractResult: &smartContractResult.SmartContractResult{
OriginalTxHash: txHash,
},
FeeInfo: &outport.FeeInfo{
GasRefunded: 9_692_000,
Fee: big.NewInt(96920000000000),
},
},
},
}
err = esProc.SaveTransactions(createOutportBlockWithHeader(body, header, pool, nil, testNumOfShards))
require.Nil(t, err)

ids = []string{hex.EncodeToString(txHash)}
genericResponse = &GenericResponse{}
err = esClient.DoMultiGet(context.Background(), ids, indexerdata.TransactionsIndex, true, genericResponse)
require.Nil(t, err)

require.JSONEq(t,
readExpectedResult("./testdata/relayedTxV3/relayed-v3-with-one-refund.json"),
string(genericResponse.Docs[0].Source),
)

// execute second SCR with refund
pool = &outport.TransactionPool{
SmartContractResults: map[string]*outport.SCRInfo{
"scrHash": {
SmartContractResult: &smartContractResult.SmartContractResult{
OriginalTxHash: txHash,
},
FeeInfo: &outport.FeeInfo{
GasRefunded: 9_692_000,
Fee: big.NewInt(96920000000000),
},
},
},
}
err = esProc.SaveTransactions(createOutportBlockWithHeader(body, header, pool, nil, testNumOfShards))
require.Nil(t, err)

ids = []string{hex.EncodeToString(txHash)}
genericResponse = &GenericResponse{}
err = esClient.DoMultiGet(context.Background(), ids, indexerdata.TransactionsIndex, true, genericResponse)
require.Nil(t, err)

require.JSONEq(t,
readExpectedResult("./testdata/relayedTxV3/relayed-v3-with-two-refunds.json"),
string(genericResponse.Docs[0].Source),
)
}
13 changes: 13 additions & 0 deletions integrationtests/testdata/relayedTxV3/innerTx1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"hash":"13b41efddcb2c01dbaba26ebc387a7f58a4ea0757a73420267818224f939e77a",
"type": "innerTx",
"nonce": 20,
"value": "1000",
"receiver": "erd14eyayfrvlrhzfrwg5zwleua25mkzgncggn35nvc6xhv5yxwml2es0f3dht",
"sender": "erd1k7j6ewjsla4zsgv8v6f6fe3dvrkgv3d0d9jerczw45hzedhyed8sh2u34u",
"gasPrice": 1000000000,
"gasLimit": 15406000,
"chainID": "",
"version": 0,
"relayedTxHash": "72656c6179656454785633"
}
13 changes: 13 additions & 0 deletions integrationtests/testdata/relayedTxV3/innerTx2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"hash":"f8b8b93e42afb737a59dd622af054e34d970663b09b90138e7dc2712565ca8db",
"type": "innerTx",
"nonce": 10,
"value": "0",
"receiver": "erd14eyayfrvlrhzfrwg5zwleua25mkzgncggn35nvc6xhv5yxwml2es0f3dht",
"sender": "erd1k7j6ewjsla4zsgv8v6f6fe3dvrkgv3d0d9jerczw45hzedhyed8sh2u34u",
"gasPrice": 1000000000,
"gasLimit": 15406000,
"chainID": "",
"version": 0,
"relayedTxHash": "72656c6179656454785633"
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"completedEvent": true,
"innerTransactions": [
{
"hash": "0521127b7d727e5d5e82ce963870ac16dde71f438b5dc2a64bd476ad3b8e96c2",
"nonce": 5,
"value": "10000000000000000",
"receiver": "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r",
Expand All @@ -47,6 +48,7 @@
"version": 0
},
{
"hash": "c4d7ee5288fb2f02789e36970a2b22d977870e506eb6df07e10aad12aaf67dbd",
"nonce": 3,
"value": "10000000000000000",
"receiver": "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r",
Expand All @@ -57,6 +59,7 @@
"version": 0
},
{
"hash": "5ab08906cd2d05abaca912fa450df5fb6f9cf64481f649d118f8fd14aa81b1be",
"nonce": 4,
"value": "10000000000000000",
"receiver": "erd1aduqqezzw0u3j7tywlq3mrl0yn4z6f6vytdju8gg0neq38fauyzsa5yy6r",
Expand Down
Loading
Loading