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

Force epoch change chain simulator master #6246

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
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
5 changes: 5 additions & 0 deletions api/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ var ErrTxGenerationFailed = errors.New("transaction generation failed")
// ErrValidationEmptyTxHash signals that an empty tx hash was provided
var ErrValidationEmptyTxHash = errors.New("TxHash is empty")

var ErrValidationEmptySCRHash = errors.New("SCRHash is empty")

// ErrInvalidBlockNonce signals that an invalid block nonce was provided
var ErrInvalidBlockNonce = errors.New("invalid block nonce")

Expand All @@ -79,6 +81,9 @@ var ErrValidationEmptyBlockHash = errors.New("block hash is empty")
// ErrGetTransaction signals an error happening when trying to fetch a transaction
var ErrGetTransaction = errors.New("getting transaction failed")

// ErrGetSmartContractResults signals an error happening when trying to fetch smart contract results
var ErrGetSmartContractResults = errors.New("getting smart contract results failed")

// ErrGetBlock signals an error happening when trying to fetch a block
var ErrGetBlock = errors.New("getting block failed")

Expand Down
66 changes: 66 additions & 0 deletions api/groups/transactionGroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ const (
simulateTransactionEndpoint = "/transaction/simulate"
sendMultipleTransactionsEndpoint = "/transaction/send-multiple"
getTransactionEndpoint = "/transaction/:hash"
getScrsByTxHashEndpoint = "/transaction/scrs-by-tx-hash/:txhash"
sendTransactionPath = "/send"
simulateTransactionPath = "/simulate"
costPath = "/cost"
sendMultiplePath = "/send-multiple"
getTransactionPath = "/:txhash"
getScrsByTxHashPath = "/scrs-by-tx-hash/:txhash"
getTransactionsPool = "/pool"

queryParamWithResults = "withResults"
Expand All @@ -39,6 +41,7 @@ const (
queryParamFields = "fields"
queryParamLastNonce = "last-nonce"
queryParamNonceGaps = "nonce-gaps"
queryParameterScrHash = "scrHash"
)

// transactionFacadeHandler defines the methods to be implemented by a facade for transaction requests
Expand All @@ -49,6 +52,7 @@ type transactionFacadeHandler interface {
SendBulkTransactions([]*transaction.Transaction) (uint64, error)
SimulateTransactionExecution(tx *transaction.Transaction) (*txSimData.SimulationResultsWithVMOutput, error)
GetTransaction(hash string, withResults bool) (*transaction.ApiTransactionResult, error)
GetSCRsByTxHash(txHash string, scrHash string) ([]*transaction.ApiSmartContractResult, error)
GetTransactionsPool(fields string) (*common.TransactionsPoolAPIResponse, error)
GetTransactionsPoolForSender(sender, fields string) (*common.TransactionsPoolForSenderApiResponse, error)
GetLastPoolNonceForSender(sender string) (uint64, error)
Expand Down Expand Up @@ -137,6 +141,17 @@ func NewTransactionGroup(facade transactionFacadeHandler) (*transactionGroup, er
},
},
},
{
Path: getScrsByTxHashPath,
Method: http.MethodGet,
Handler: tg.getScrsByTxHash,
AdditionalMiddlewares: []shared.AdditionalMiddleware{
{
Middleware: middleware.CreateEndpointThrottlerFromFacade(getScrsByTxHashEndpoint, facade),
Position: shared.Before,
},
},
},
}
tg.endpoints = endpoints

Expand Down Expand Up @@ -430,6 +445,57 @@ func (tg *transactionGroup) sendMultipleTransactions(c *gin.Context) {
)
}

func (tg *transactionGroup) getScrsByTxHash(c *gin.Context) {
txhash := c.Param("txhash")
if txhash == "" {
c.JSON(
http.StatusBadRequest,
shared.GenericAPIResponse{
Data: nil,
Error: fmt.Sprintf("%s: %s", errors.ErrValidation.Error(), errors.ErrValidationEmptyTxHash.Error()),
Code: shared.ReturnCodeRequestError,
},
)
return
}
scrHashStr := c.Request.URL.Query().Get(queryParameterScrHash)
if scrHashStr == "" {
c.JSON(
http.StatusBadRequest,
shared.GenericAPIResponse{
Data: nil,
Error: fmt.Sprintf("%s: %s", errors.ErrValidation.Error(), errors.ErrValidationEmptySCRHash.Error()),
Code: shared.ReturnCodeRequestError,
},
)
return
}

start := time.Now()
scrs, err := tg.getFacade().GetSCRsByTxHash(txhash, scrHashStr)
if err != nil {
c.JSON(
http.StatusInternalServerError,
shared.GenericAPIResponse{
Data: nil,
Error: fmt.Sprintf("%s: %s", errors.ErrGetSmartContractResults.Error(), err.Error()),
Code: shared.ReturnCodeInternalError,
},
)
return
}
logging.LogAPIActionDurationIfNeeded(start, "API call: GetSCRsByTxHash")

c.JSON(
http.StatusOK,
shared.GenericAPIResponse{
Data: gin.H{"scrs": scrs},
Error: "",
Code: shared.ReturnCodeSuccess,
},
)
}

// getTransaction returns transaction details for a given txhash
func (tg *transactionGroup) getTransaction(c *gin.Context) {
txhash := c.Param("txhash")
Expand Down
71 changes: 71 additions & 0 deletions api/groups/transactionGroup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,76 @@ func TestTransactionGroup_sendTransaction(t *testing.T) {
})
}

func TestTransactionsGroup_getSCRsByTxHash(t *testing.T) {
t.Parallel()

t.Run("get SCRsByTxHash empty scr hash should error", func(t *testing.T) {
facade := &mock.FacadeStub{}

transactionGroup, err := groups.NewTransactionGroup(facade)
require.NoError(t, err)

ws := startWebServer(transactionGroup, "transaction", getTransactionRoutesConfig())

req, _ := http.NewRequest(http.MethodGet, "/transaction/scrs-by-tx-hash/txHash", bytes.NewBuffer([]byte{}))
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

txResp := shared.GenericAPIResponse{}
loadResponse(resp.Body, &txResp)

assert.Equal(t, http.StatusBadRequest, resp.Code)
assert.True(t, strings.Contains(txResp.Error, apiErrors.ErrValidationEmptySCRHash.Error()))
assert.Empty(t, txResp.Data)
})
t.Run("get scrs facade error", func(t *testing.T) {
localErr := fmt.Errorf("error")
facade := &mock.FacadeStub{
GetSCRsByTxHashCalled: func(txHash string, scrHash string) ([]*dataTx.ApiSmartContractResult, error) {
return nil, localErr
},
}

transactionGroup, err := groups.NewTransactionGroup(facade)
require.NoError(t, err)

ws := startWebServer(transactionGroup, "transaction", getTransactionRoutesConfig())

req, _ := http.NewRequest(http.MethodGet, "/transaction/scrs-by-tx-hash/txhash?scrHash=hash", bytes.NewBuffer([]byte{}))
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

txResp := shared.GenericAPIResponse{}
loadResponse(resp.Body, &txResp)

assert.Equal(t, http.StatusInternalServerError, resp.Code)
assert.True(t, strings.Contains(txResp.Error, localErr.Error()))
assert.Empty(t, txResp.Data)
})
t.Run("get scrs should work", func(t *testing.T) {
facade := &mock.FacadeStub{
GetSCRsByTxHashCalled: func(txHash string, scrHash string) ([]*dataTx.ApiSmartContractResult, error) {
return []*dataTx.ApiSmartContractResult{}, nil
},
}

transactionGroup, err := groups.NewTransactionGroup(facade)
require.NoError(t, err)

ws := startWebServer(transactionGroup, "transaction", getTransactionRoutesConfig())

req, _ := http.NewRequest(http.MethodGet, "/transaction/scrs-by-tx-hash/txhash?scrHash=hash", bytes.NewBuffer([]byte{}))
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

txResp := shared.GenericAPIResponse{}
loadResponse(resp.Body, &txResp)

assert.Equal(t, http.StatusOK, resp.Code)
assert.Equal(t, "", txResp.Error)
})
}

func TestTransactionGroup_sendMultipleTransactions(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -1122,6 +1192,7 @@ func getTransactionRoutesConfig() config.ApiRoutesConfig {
{Name: "/:txhash", Open: true},
{Name: "/:txhash/status", Open: true},
{Name: "/simulate", Open: true},
{Name: "/scrs-by-tx-hash/:txhash", Open: true},
},
},
},
Expand Down
10 changes: 10 additions & 0 deletions api/mock/facadeStub.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,16 @@ type FacadeStub struct {
GetWaitingEpochsLeftForPublicKeyCalled func(publicKey string) (uint32, error)
P2PPrometheusMetricsEnabledCalled func() bool
AuctionListHandler func() ([]*common.AuctionListValidatorAPIResponse, error)
GetSCRsByTxHashCalled func(txHash string, scrHash string) ([]*transaction.ApiSmartContractResult, error)
}

// GetSCRsByTxHash -
func (f *FacadeStub) GetSCRsByTxHash(txHash string, scrHash string) ([]*transaction.ApiSmartContractResult, error) {
if f.GetSCRsByTxHashCalled != nil {
return f.GetSCRsByTxHashCalled(txHash, scrHash)
}

return nil, nil
}

// GetTokenSupply -
Expand Down
1 change: 1 addition & 0 deletions api/shared/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ type FacadeHandler interface {
GetEligibleManagedKeys() ([]string, error)
GetWaitingManagedKeys() ([]string, error)
GetWaitingEpochsLeftForPublicKey(publicKey string) (uint32, error)
GetSCRsByTxHash(txHash string, scrHash string) ([]*transaction.ApiSmartContractResult, error)
P2PPrometheusMetricsEnabled() bool
IsInterfaceNil() bool
}
3 changes: 3 additions & 0 deletions cmd/node/config/api.toml
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@

# /transaction/:txhash will return the transaction in JSON format based on its hash
{ Name = "/:txhash", Open = true },

# /transaction/scrs-by-tx-hash/:txhash will return the smart contract results generated by the provided transaction hash
{ Name = "/scrs-by-tx-hash/:txhash", Open = true },
]

[APIPackages.block]
Expand Down
5 changes: 5 additions & 0 deletions facade/initial/initialNodeFacade.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,11 @@ func (inf *initialNodeFacade) IsDataTrieMigrated(_ string, _ api.AccountQueryOpt
return false, errNodeStarting
}

// GetSCRsByTxHash return a nil slice and error
func (inf *initialNodeFacade) GetSCRsByTxHash(_ string, _ string) ([]*transaction.ApiSmartContractResult, error) {
return nil, errNodeStarting
}

// GetManagedKeysCount returns 0
func (inf *initialNodeFacade) GetManagedKeysCount() int {
return 0
Expand Down
1 change: 1 addition & 0 deletions facade/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ type ApiResolver interface {
GetDirectStakedList(ctx context.Context) ([]*api.DirectStakedValue, error)
GetDelegatorsList(ctx context.Context) ([]*api.Delegator, error)
GetTransaction(hash string, withResults bool) (*transaction.ApiTransactionResult, error)
GetSCRsByTxHash(txHash string, scrHash string) ([]*transaction.ApiSmartContractResult, error)
GetTransactionsPool(fields string) (*common.TransactionsPoolAPIResponse, error)
GetTransactionsPoolForSender(sender, fields string) (*common.TransactionsPoolForSenderApiResponse, error)
GetLastPoolNonceForSender(sender string) (uint64, error)
Expand Down
10 changes: 10 additions & 0 deletions facade/mock/apiResolverStub.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ type ApiResolverStub struct {
GetEligibleManagedKeysCalled func() ([]string, error)
GetWaitingManagedKeysCalled func() ([]string, error)
GetWaitingEpochsLeftForPublicKeyCalled func(publicKey string) (uint32, error)
GetSCRsByTxHashCalled func(txHash string, scrHash string) ([]*transaction.ApiSmartContractResult, error)
}

// GetSCRsByTxHash -
func (ars *ApiResolverStub) GetSCRsByTxHash(txHash string, scrHash string) ([]*transaction.ApiSmartContractResult, error) {
if ars.GetSCRsByTxHashCalled != nil {
return ars.GetSCRsByTxHashCalled(txHash, scrHash)
}

return nil, nil
}

// GetTransaction -
Expand Down
5 changes: 5 additions & 0 deletions facade/nodeFacade.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,11 @@ func (nf *nodeFacade) GetTransaction(hash string, withResults bool) (*transactio
return nf.apiResolver.GetTransaction(hash, withResults)
}

// GetSCRsByTxHash will return a list of smart contract results based on a provided tx hash and smart contract result hash
func (nf *nodeFacade) GetSCRsByTxHash(txHash string, scrHash string) ([]*transaction.ApiSmartContractResult, error) {
return nf.apiResolver.GetSCRsByTxHash(txHash, scrHash)
}

// GetTransactionsPool will return a structure containing the transactions pool that is to be returned on API calls
func (nf *nodeFacade) GetTransactionsPool(fields string) (*common.TransactionsPoolAPIResponse, error) {
return nf.apiResolver.GetTransactionsPool(fields)
Expand Down
10 changes: 8 additions & 2 deletions integrationTests/chainSimulator/staking/jail/jail_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func testChainSimulatorJailAndUnJail(t *testing.T, targetEpoch int32, nodeStatus
numOfShards := uint32(3)

cs, err := chainSimulator.NewChainSimulator(chainSimulator.ArgsChainSimulator{
BypassTxSignatureCheck: false,
BypassTxSignatureCheck: true,
TempDir: t.TempDir(),
PathToInitialConfig: defaultPathToInitialConfig,
NumOfShards: numOfShards,
Expand Down Expand Up @@ -98,6 +98,9 @@ func testChainSimulatorJailAndUnJail(t *testing.T, targetEpoch int32, nodeStatus
walletAddress, err := cs.GenerateAndMintWalletAddress(core.AllShardId, mintValue)
require.Nil(t, err)

err = cs.GenerateBlocks(1)
require.Nil(t, err)

txDataField := fmt.Sprintf("stake@01@%s@%s", blsKeys[0], staking.MockBLSSignature)
txStake := staking.GenerateTransaction(walletAddress.Bytes, 0, vm.ValidatorSCAddress, staking.MinimumStakeValue, txDataField, staking.GasLimitForStakeOperation)
stakeTx, err := cs.SendTxAndGenerateBlockTilTxIsExecuted(txStake, staking.MaxNumOfBlockToGenerateWhenExecutingTx)
Expand Down Expand Up @@ -166,7 +169,7 @@ func TestChainSimulator_FromQueueToAuctionList(t *testing.T) {
numOfShards := uint32(3)

cs, err := chainSimulator.NewChainSimulator(chainSimulator.ArgsChainSimulator{
BypassTxSignatureCheck: false,
BypassTxSignatureCheck: true,
TempDir: t.TempDir(),
PathToInitialConfig: defaultPathToInitialConfig,
NumOfShards: numOfShards,
Expand Down Expand Up @@ -202,6 +205,9 @@ func TestChainSimulator_FromQueueToAuctionList(t *testing.T) {
walletAddress, err := cs.GenerateAndMintWalletAddress(core.AllShardId, mintValue)
require.Nil(t, err)

err = cs.GenerateBlocks(1)
require.Nil(t, err)

txDataField := fmt.Sprintf("stake@01@%s@%s", blsKeys[0], staking.MockBLSSignature)
txStake := staking.GenerateTransaction(walletAddress.Bytes, 0, vm.ValidatorSCAddress, staking.MinimumStakeValue, txDataField, staking.GasLimitForStakeOperation)
stakeTx, err := cs.SendTxAndGenerateBlockTilTxIsExecuted(txStake, staking.MaxNumOfBlockToGenerateWhenExecutingTx)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func testChainSimulatorSimpleStake(t *testing.T, targetEpoch int32, nodesStatus
numOfShards := uint32(3)

cs, err := chainSimulator.NewChainSimulator(chainSimulator.ArgsChainSimulator{
BypassTxSignatureCheck: false,
BypassTxSignatureCheck: true,
TempDir: t.TempDir(),
PathToInitialConfig: defaultPathToInitialConfig,
NumOfShards: numOfShards,
Expand Down Expand Up @@ -93,6 +93,9 @@ func testChainSimulatorSimpleStake(t *testing.T, targetEpoch int32, nodesStatus
wallet3, err := cs.GenerateAndMintWalletAddress(0, mintValue)
require.Nil(t, err)

err = cs.GenerateBlocks(1)
require.Nil(t, err)

_, blsKeys, err := chainSimulator.GenerateBlsPrivateKeys(3)
require.Nil(t, err)

Expand Down Expand Up @@ -158,7 +161,7 @@ func TestChainSimulator_StakingV4Step2APICalls(t *testing.T) {
stakingV4Step3Epoch := uint32(4)

cs, err := chainSimulator.NewChainSimulator(chainSimulator.ArgsChainSimulator{
BypassTxSignatureCheck: false,
BypassTxSignatureCheck: true,
TempDir: t.TempDir(),
PathToInitialConfig: defaultPathToInitialConfig,
NumOfShards: 3,
Expand Down Expand Up @@ -200,6 +203,9 @@ func TestChainSimulator_StakingV4Step2APICalls(t *testing.T) {
validatorOwner, err := cs.GenerateAndMintWalletAddress(core.AllShardId, mintValue)
require.Nil(t, err)

err = cs.GenerateBlocks(1)
require.Nil(t, err)

// Stake a new validator that should end up in auction in step 1
txDataField := fmt.Sprintf("stake@01@%s@%s", blsKeys[0], staking.MockBLSSignature)
txStake := staking.GenerateTransaction(validatorOwner.Bytes, 0, vm.ValidatorSCAddress, staking.MinimumStakeValue, txDataField, staking.GasLimitForStakeOperation)
Expand Down
Loading
Loading