Skip to content

Commit

Permalink
Merge pull request #53 from multiversx/force-epoch-change-endpoint
Browse files Browse the repository at this point in the history
Force epoch change endpoint
  • Loading branch information
miiu96 authored Jul 11, 2024
2 parents 3d8c1ff + f4adab0 commit 96a8a9f
Show file tree
Hide file tree
Showing 17 changed files with 285 additions and 43 deletions.
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,53 @@ This endpoint initiates the generation of blocks for each shard until the target
}
```

### `POST /simulator/generate-blocks-until-transcation-processed/:txHash`

This endpoint initiates the generation of blocks for each shard until the status of the provided transaction hash is processed.

##### Request
- **Method:** POST
- **Path:** `/simulator/generate-blocks-until-transcation-processed/:txHash`
- **Parameters:**
- `txHash` (path parameter): The hash of the targeted transaction.

##### Response
- **Status Codes:**
- `200 OK`: Blocks generated successfully, transaction was processed.
- `400 Bad Request`: Invalid request parameters.

#### Response Body
```json
{
"data": {},
"error": "",
"code": "successful"
}
```

### `POST /simulator/force-epoch-change`

This endpoint will trigger the chain to move in the next epoch. (this endpoint will generate a few block till next epoch is reached)

##### Request
- **Method:** POST
- **Path:** `/simulator/force-epoch-change`
- **URL parameter** `targetEpoch` Specifies the epoch the chain simulator needs to reach.

##### Response
- **Status Codes:**
- `200 OK`: Next epoch reached.
- `400 Bad Request`: Invalid request parameters.

#### Response Body
```json
{
"data": {},
"error": "",
"code": "successful"
}
```

### `GET /simulator/initial-wallets`

This endpoint returns the initial wallets (address and private key hex encoded).
Expand Down
1 change: 1 addition & 0 deletions cmd/chainsimulator/config/nodeOverrideDefault.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# System overrides, DO NOT EDIT THIS FILE
OverridableConfigTomlValues = [
{ File = "enableEpochs.toml", Path = "EnableEpochs.StakeLimitsEnableEpoch", Value = "1000000" }, # disable stake limits
{ File = "systemSmartContractsConfig.toml", Path = "ESDTSystemSCConfig.BaseIssuingCost", Value = "50000000000000000" }, # (0.05 EGLD)
]
6 changes: 4 additions & 2 deletions cmd/chainsimulator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ func startChainSimulator(ctx *cli.Context) error {

time.Sleep(time.Second)

proxyInstance, err := creator.CreateProxy(creator.ArgsProxy{
outputProxy, err := creator.CreateProxy(creator.ArgsProxy{
Config: outputProxyConfigs.Config,
NodeHandler: metaNode,
PathToConfig: outputProxyConfigs.PathToTempConfig,
Expand All @@ -247,7 +247,9 @@ func startChainSimulator(ctx *cli.Context) error {
return err
}

simulatorFacade, err := facade.NewSimulatorFacade(simulator)
proxyInstance := outputProxy.ProxyHandler

simulatorFacade, err := facade.NewSimulatorFacade(simulator, outputProxy.ProxyTransactionHandler)
if err != nil {
return err
}
Expand Down
5 changes: 3 additions & 2 deletions examples/esdt/issue-fungible.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

SIMULATOR_URL = "http://localhost:8085"
GENERATE_BLOCKS_URL = f"{SIMULATOR_URL}/simulator/generate-blocks"
GENERATE_BLOCKS_UNTIL_TX_PROCESSED = f"{SIMULATOR_URL}/simulator/generate-blocks-until-transaction-processed"


def main():
Expand Down Expand Up @@ -47,7 +48,7 @@ def main():
)

# set issue cost and nonce
tx.amount = 5000000000000000000
tx.amount = 50000000000000000 #0.05 EGLD
tx.nonce = provider.get_account(address).nonce

# sign transaction
Expand All @@ -61,7 +62,7 @@ def main():
time.sleep(1)

# execute 5 block ( transaction needs to be executed on source, block on source has to be finalized...)
provider.do_post(f"{GENERATE_BLOCKS_URL}/5", {})
provider.do_post(f"{GENERATE_BLOCKS_UNTIL_TX_PROCESSED}/{tx_hash}", {})

# get transaction with status
tx_from_network = provider.get_transaction(tx_hash, with_process_status=True)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.20
require (
github.com/gin-gonic/gin v1.9.1
github.com/multiversx/mx-chain-core-go v1.2.20
github.com/multiversx/mx-chain-go v1.7.12
github.com/multiversx/mx-chain-go v1.7.14-0.20240628141005-afa6d78f5601
github.com/multiversx/mx-chain-logger-go v1.0.14
github.com/multiversx/mx-chain-proxy-go v1.1.48
github.com/pelletier/go-toml v1.9.3
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -401,8 +401,8 @@ github.com/multiversx/mx-chain-crypto-go v1.2.11 h1:MNPJoiTJA5/tedYrI0N22OorbsKD
github.com/multiversx/mx-chain-crypto-go v1.2.11/go.mod h1:pcZutPdfLiAFytzCU3LxU3s8cXkvpNqquyitFSfoF3o=
github.com/multiversx/mx-chain-es-indexer-go v1.4.21 h1:rzxXCkgOsqj67GRYtqzKuf9XgHwnZLTZhU90Ck3VbrE=
github.com/multiversx/mx-chain-es-indexer-go v1.4.21/go.mod h1:V9xxOBkfV7GjN4K5SODaOetoGVpQm4snibMVPCjL0Kk=
github.com/multiversx/mx-chain-go v1.7.12 h1:cQ3g5sFZEcQmIRwi/wt+K/3d5nIwCMQRC1ZnJDRuRY4=
github.com/multiversx/mx-chain-go v1.7.12/go.mod h1:HwklJGQfMpv/yyF4oLpxjwdKCawspv1JjdgezlWBpRQ=
github.com/multiversx/mx-chain-go v1.7.14-0.20240628141005-afa6d78f5601 h1:IEQH9ST6hzaSPKJ0739RDbwMNncHxhMZpetZvXKYmcY=
github.com/multiversx/mx-chain-go v1.7.14-0.20240628141005-afa6d78f5601/go.mod h1:HwklJGQfMpv/yyF4oLpxjwdKCawspv1JjdgezlWBpRQ=
github.com/multiversx/mx-chain-logger-go v1.0.14 h1:PRMpAvXE7Nec2d//QNmbYfKVHMomOKmcN4UXurQWX9o=
github.com/multiversx/mx-chain-logger-go v1.0.14/go.mod h1:bDfHSdwqIimn7Gp8w+SH5KlDuGzJ//nlyEANAaTSc3o=
github.com/multiversx/mx-chain-proxy-go v1.1.48 h1:gmunv+2oimIN8ejlVAN7eWP7mt38So1WvsyiR3+94SU=
Expand Down
5 changes: 3 additions & 2 deletions pkg/facade/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package facade
import "errors"

var (
errNilSimulatorHandler = errors.New("nil simulator handler ")
errInvalidNumOfBlocks = errors.New("num of blocks must be greater than zero")
errNilSimulatorHandler = errors.New("nil simulator handler ")
errInvalidNumOfBlocks = errors.New("num of blocks must be greater than zero")
errNilProxyTransactionsHandler = errors.New("nil proxy transactions handler ")
)
13 changes: 12 additions & 1 deletion pkg/facade/interface.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package facade

import "github.com/multiversx/mx-chain-go/node/chainSimulator/dtos"
import (
"github.com/multiversx/mx-chain-go/node/chainSimulator/dtos"
"github.com/multiversx/mx-chain-go/node/chainSimulator/process"
"github.com/multiversx/mx-chain-proxy-go/data"
)

// SimulatorHandler defines what a simulator handler should be able to do
type SimulatorHandler interface {
Expand All @@ -13,5 +17,12 @@ type SimulatorHandler interface {
GenerateBlocksUntilEpochIsReached(targetEpoch int32) error
ForceResetValidatorStatisticsCache() error
GetRestAPIInterfaces() map[uint32]string
ForceChangeOfEpoch() error
GetNodeHandler(shardID uint32) process.NodeHandler
IsInterfaceNil() bool
}

// ProxyTransactionsHandler defines what a proxy transaction handler should be able to do
type ProxyTransactionsHandler interface {
GetProcessedTransactionStatus(txHash string) (*data.ProcessStatusResponse, error)
}
74 changes: 70 additions & 4 deletions pkg/facade/simulatorFacade.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,40 @@ package facade
import (
"encoding/base64"
"encoding/hex"
"errors"
"fmt"
"github.com/multiversx/mx-chain-core-go/data/transaction"
"strconv"
"strings"

"github.com/multiversx/mx-chain-core-go/core"
"github.com/multiversx/mx-chain-core-go/core/check"
"github.com/multiversx/mx-chain-go/node/chainSimulator/dtos"
dtoc "github.com/multiversx/mx-chain-simulator-go/pkg/dtos"
)

const errMsgAccountNotFound = "account was not found"
const (
errMsgAccountNotFound = "account was not found"
maxNumOfBlockToGenerateUntilTxProcessed = 10
)

type simulatorFacade struct {
simulator SimulatorHandler
simulator SimulatorHandler
transactionHandler ProxyTransactionsHandler
}

// NewSimulatorFacade will create a new instance of simulatorFacade
func NewSimulatorFacade(simulator SimulatorHandler) (*simulatorFacade, error) {
func NewSimulatorFacade(simulator SimulatorHandler, transactionHandler ProxyTransactionsHandler) (*simulatorFacade, error) {
if check.IfNil(simulator) {
return nil, errNilSimulatorHandler
}
if check.IfNilReflect(transactionHandler) {
return nil, errNilProxyTransactionsHandler
}

return &simulatorFacade{
simulator: simulator,
simulator: simulator,
transactionHandler: transactionHandler,
}, nil
}

Expand Down Expand Up @@ -114,6 +125,29 @@ func (sf *simulatorFacade) ForceUpdateValidatorStatistics() error {
return sf.simulator.ForceResetValidatorStatisticsCache()
}

// ForceChangeOfEpoch will force change the current epoch
func (sf *simulatorFacade) ForceChangeOfEpoch(targetEpoch uint32) error {
if targetEpoch == 0 {
return sf.simulator.ForceChangeOfEpoch()
}

currentEpoch := sf.getCurrentEpoch()
if currentEpoch >= targetEpoch {
return fmt.Errorf("target epoch must be greater than current epoch, current epoch: %d target epoch: %d", currentEpoch, targetEpoch)
}

for currentEpoch < targetEpoch {
err := sf.simulator.ForceChangeOfEpoch()
if err != nil {
return err
}

currentEpoch = sf.getCurrentEpoch()
}

return nil
}

// GetObserversInfo will return information about the observers
func (sf *simulatorFacade) GetObserversInfo() (map[uint32]*dtoc.ObserverInfo, error) {
restApiInterface := sf.simulator.GetRestAPIInterfaces()
Expand All @@ -138,6 +172,38 @@ func (sf *simulatorFacade) GetObserversInfo() (map[uint32]*dtoc.ObserverInfo, er
return response, nil
}

// GenerateBlocksUntilTransactionIsProcessed generate blocks until the status of the provided transaction hash is processed
func (sf *simulatorFacade) GenerateBlocksUntilTransactionIsProcessed(txHash string) error {
txStatusInfo, err := sf.transactionHandler.GetProcessedTransactionStatus(txHash)
if err != nil {
return err
}

count := 0
for txStatusInfo.Status == transaction.TxStatusPending.String() {
err = sf.GenerateBlocks(1)
if err != nil {
return err
}

txStatusInfo, err = sf.transactionHandler.GetProcessedTransactionStatus(txHash)
if err != nil {
return err
}

count++
if count > maxNumOfBlockToGenerateUntilTxProcessed {
return errors.New("something went wrong, transaction is still in pending")
}
}

return nil
}

func (sf *simulatorFacade) getCurrentEpoch() uint32 {
return sf.simulator.GetNodeHandler(core.MetachainShardId).GetProcessComponents().EpochStartTrigger().Epoch()
}

// IsInterfaceNil returns true if there is no value under the interface
func (sf *simulatorFacade) IsInterfaceNil() bool {
return sf == nil
Expand Down
26 changes: 13 additions & 13 deletions pkg/facade/simulatorFacade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ func TestNewSimulatorFacade(t *testing.T) {
t.Run("nil simulator should error", func(t *testing.T) {
t.Parallel()

facade, err := NewSimulatorFacade(nil)
facade, err := NewSimulatorFacade(nil, &testscommon.TransactionHandlerMock{})
require.Equal(t, errNilSimulatorHandler, err)
require.Nil(t, facade)
})
t.Run("should work", func(t *testing.T) {
t.Parallel()

facade, err := NewSimulatorFacade(&testscommon.SimulatorHandlerMock{})
facade, err := NewSimulatorFacade(&testscommon.SimulatorHandlerMock{}, &testscommon.TransactionHandlerMock{})
require.NoError(t, err)
require.NotNil(t, facade)
})
Expand All @@ -36,7 +36,7 @@ func TestSimulatorFacade_IsInterfaceNil(t *testing.T) {
var facade *simulatorFacade
require.True(t, facade.IsInterfaceNil())

facade, _ = NewSimulatorFacade(&testscommon.SimulatorHandlerMock{})
facade, _ = NewSimulatorFacade(&testscommon.SimulatorHandlerMock{}, &testscommon.TransactionHandlerMock{})
require.False(t, facade.IsInterfaceNil())
}

Expand All @@ -49,7 +49,7 @@ func TestSimulatorFacade_GenerateBlocks(t *testing.T) {
cnt++
return nil
},
})
}, &testscommon.TransactionHandlerMock{})
require.NoError(t, err)

err = facade.GenerateBlocks(0)
Expand All @@ -70,7 +70,7 @@ func TestSimulatorFacade_GetInitialWalletKeys(t *testing.T) {
wasCalled = true
return providedInitialWalletKeys
},
})
}, &testscommon.TransactionHandlerMock{})
require.NoError(t, err)

walletKeys := facade.GetInitialWalletKeys()
Expand All @@ -92,7 +92,7 @@ func TestSimulatorFacade_SetKeyValueForAddress(t *testing.T) {

return nil
},
})
}, &testscommon.TransactionHandlerMock{})
require.NoError(t, err)

err = facade.SetKeyValueForAddress(providedAddress, providedKeyValue)
Expand All @@ -112,7 +112,7 @@ func TestSimulatorFacade_SetStateMultiple(t *testing.T) {

return nil
},
})
}, &testscommon.TransactionHandlerMock{})
require.NoError(t, err)

err = facade.SetStateMultiple(providedStateSlice, true)
Expand All @@ -133,7 +133,7 @@ func TestSimulatorFacade_GenerateBlocksUntilEpochIsReached(t *testing.T) {
},
}

facade, _ := NewSimulatorFacade(simulator)
facade, _ := NewSimulatorFacade(simulator, &testscommon.TransactionHandlerMock{})
err := facade.GenerateBlocksUntilEpochIsReached(testEpoch)
assert.Nil(t, err)
assert.True(t, generateBlocksCalled)
Expand All @@ -156,7 +156,7 @@ func TestSimulatorFacade_AddValidatorKeys(t *testing.T) {

return nil
},
})
}, &testscommon.TransactionHandlerMock{})
require.NoError(t, err)

err = facade.AddValidatorKeys(providedValidators)
Expand All @@ -176,7 +176,7 @@ func TestSimulatorFacade_AddValidatorKeys(t *testing.T) {

return nil
},
})
}, &testscommon.TransactionHandlerMock{})
require.NoError(t, err)

err = facade.AddValidatorKeys(providedValidators)
Expand Down Expand Up @@ -205,7 +205,7 @@ func TestSimulatorFacade_AddValidatorKeys(t *testing.T) {

return nil
},
})
}, &testscommon.TransactionHandlerMock{})
require.NoError(t, err)

err = facade.AddValidatorKeys(providedValidators)
Expand All @@ -225,7 +225,7 @@ func TestSimulatorFacade_ForceUpdateValidatorStatistics(t *testing.T) {
},
}

facade, _ := NewSimulatorFacade(simulator)
facade, _ := NewSimulatorFacade(simulator, &testscommon.TransactionHandlerMock{})
err := facade.ForceUpdateValidatorStatistics()
assert.Nil(t, err)
assert.True(t, forceResetCalled)
Expand All @@ -243,7 +243,7 @@ func TestSimulatorFacade_GetObserversInfo(t *testing.T) {
},
}

facade, _ := NewSimulatorFacade(simulator)
facade, _ := NewSimulatorFacade(simulator, &testscommon.TransactionHandlerMock{})
response, err := facade.GetObserversInfo()
require.NoError(t, err)
require.Equal(t, map[uint32]*dtoc.ObserverInfo{
Expand Down
Loading

0 comments on commit 96a8a9f

Please sign in to comment.