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

test: add stateful end to end test #2360

Merged
merged 9 commits into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from 7 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
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,10 @@ start-localnet: zetanode
@echo "--> Starting localnet"
cd contrib/localnet/ && $(DOCKER) compose -f docker-compose.yml -f docker-compose-setup-only.yml up -d

start-e2e-import-mainnet-test: zetanode
@echo "--> Starting e2e import-data test"
cd contrib/localnet/ && ./scripts/import-data.sh mainnet && $(DOCKER) compose -f docker-compose.yml -f docker-compose-import-data.yml up -d

stop-test:
cd contrib/localnet/ && $(DOCKER) compose down --remove-orphans

Expand Down
41 changes: 29 additions & 12 deletions cmd/zetacored/parse_genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ const MaxItemsForList = 10
// Copy represents a set of modules for which, the entire state is copied without any modifications
var Copy = map[string]bool{
slashingtypes.ModuleName: true,
govtypes.ModuleName: true,
crisistypes.ModuleName: true,
feemarkettypes.ModuleName: true,
paramstypes.ModuleName: true,
Expand All @@ -50,24 +49,37 @@ var Copy = map[string]bool{
vestingtypes.ModuleName: true,
fungibletypes.ModuleName: true,
emissionstypes.ModuleName: true,
authz.ModuleName: true,
}

// Skip represents a set of modules for which, the entire state is skipped and nothing gets imported
var Skip = map[string]bool{
evmtypes.ModuleName: true,
stakingtypes.ModuleName: true,
genutiltypes.ModuleName: true,
authtypes.ModuleName: true,
banktypes.ModuleName: true,
// Skipping evm this is done to reduce the size of the genesis file evm module uses the majority of the space due to smart contract data
evmtypes.ModuleName: true,
// Skipping staking as new validators would be created for the new chain
stakingtypes.ModuleName: true,
// Skipping genutil as new gentxs would be created
genutiltypes.ModuleName: true,
// Skipping auth as new accounts would be created for the new chain. This also needs to be done as we are skipping evm module
authtypes.ModuleName: true,
// Skipping bank module as it is not used when starting a new chain this is done to make sure the total supply invariant is maintained.
// This would need modification but might be possible to add in non evm based modules in the future
banktypes.ModuleName: true,
// Skipping distribution module as it is not used when starting a new chain , rewards are based on validators and delegators , and so rewards from a different chain do not hold any value
distributiontypes.ModuleName: true,
group.ModuleName: true,
// Skipping group module as it is not used when starting a new chain, new groups should be created based on the validator operator keys
group.ModuleName: true,
// Skipping authz as it is not used when starting a new chain, new grants should be created based on the validator hotkeys abd operator keys
authz.ModuleName: true,
// Skipping fungible module as new fungible tokens would be created and system contract would be deployed
fungibletypes.ModuleName: true,
// Skipping gov types as new parameters are set for the new chain
govtypes.ModuleName: true,
}

// Modify represents a set of modules for which, the state is modified before importing. Each Module should have a corresponding Modify function
var Modify = map[string]bool{
crosschaintypes.ModuleName: true,
observertypes.ModuleName: true,
crosschaintypes.ModuleName: true,
}

func CmdParseGenesisFile() *cobra.Command {
Expand All @@ -78,6 +90,10 @@ func CmdParseGenesisFile() *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
cdc := clientCtx.Codec
modifyEnabled, err := cmd.Flags().GetBool("modify")
if err != nil {
return err
}
genesisFilePath := filepath.Join(app.DefaultNodeHome, "config", "genesis.json")
if len(args) == 2 {
genesisFilePath = args[1]
Expand All @@ -90,7 +106,7 @@ func CmdParseGenesisFile() *cobra.Command {
if err != nil {
return err
}
err = ImportDataIntoFile(genDoc, importData, cdc)
err = ImportDataIntoFile(genDoc, importData, cdc, modifyEnabled)
if err != nil {
return err
}
Expand All @@ -103,10 +119,11 @@ func CmdParseGenesisFile() *cobra.Command {
return nil
},
}
cmd.PersistentFlags().Bool("modify", false, "Modify the genesis file before importing")
return cmd
}

func ImportDataIntoFile(genDoc *types.GenesisDoc, importFile *types.GenesisDoc, cdc codec.Codec) error {
func ImportDataIntoFile(genDoc *types.GenesisDoc, importFile *types.GenesisDoc, cdc codec.Codec, modifyEnabled bool) error {

appState, err := genutiltypes.GenesisStateFromGenDoc(*genDoc)
if err != nil {
Expand All @@ -124,7 +141,7 @@ func ImportDataIntoFile(genDoc *types.GenesisDoc, importFile *types.GenesisDoc,
if Copy[m] {
appState[m] = importAppState[m]
}
if Modify[m] {
if Modify[m] && modifyEnabled {
kingpinXD marked this conversation as resolved.
Show resolved Hide resolved
switch m {
case crosschaintypes.ModuleName:
err := ModifyCrosschainState(appState, importAppState, cdc)
Expand Down
103 changes: 73 additions & 30 deletions cmd/zetacored/parse_genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,43 +92,86 @@ func Test_ModifyObserverState(t *testing.T) {
}

func Test_ImportDataIntoFile(t *testing.T) {
setConfig(t)
cdc := keepertest.NewCodec()
genDoc := sample.GenDoc(t)
importGenDoc := ImportGenDoc(t, cdc, 100)
t.Run("successfully import data into file and modify data", func(t *testing.T) {
setConfig(t)
cdc := keepertest.NewCodec()
genDoc := sample.GenDoc(t)
importGenDoc := ImportGenDoc(t, cdc, 100)

err := zetacored.ImportDataIntoFile(genDoc, importGenDoc, cdc)
require.NoError(t, err)
err := zetacored.ImportDataIntoFile(genDoc, importGenDoc, cdc, true)
require.NoError(t, err)

appState, err := genutiltypes.GenesisStateFromGenDoc(*genDoc)
require.NoError(t, err)
appState, err := genutiltypes.GenesisStateFromGenDoc(*genDoc)
require.NoError(t, err)

// Crosschain module is in Modify list
crosschainStateAfterImport := crosschaintypes.GetGenesisStateFromAppState(cdc, appState)
require.Len(t, crosschainStateAfterImport.CrossChainTxs, zetacored.MaxItemsForList)
require.Len(t, crosschainStateAfterImport.InboundHashToCctxList, zetacored.MaxItemsForList)
require.Len(t, crosschainStateAfterImport.FinalizedInbounds, zetacored.MaxItemsForList)
// Crosschain module is in Modify list
crosschainStateAfterImport := crosschaintypes.GetGenesisStateFromAppState(cdc, appState)
require.Len(t, crosschainStateAfterImport.CrossChainTxs, zetacored.MaxItemsForList)
require.Len(t, crosschainStateAfterImport.InboundHashToCctxList, zetacored.MaxItemsForList)
require.Len(t, crosschainStateAfterImport.FinalizedInbounds, zetacored.MaxItemsForList)

// Bank module is in Skip list
var bankStateAfterImport banktypes.GenesisState
if appState[banktypes.ModuleName] != nil {
err := cdc.UnmarshalJSON(appState[banktypes.ModuleName], &bankStateAfterImport)
if err != nil {
panic(fmt.Sprintf("Failed to get genesis state from app state: %s", err.Error()))
// Bank module is in Skip list
var bankStateAfterImport banktypes.GenesisState
if appState[banktypes.ModuleName] != nil {
err := cdc.UnmarshalJSON(appState[banktypes.ModuleName], &bankStateAfterImport)
if err != nil {
panic(fmt.Sprintf("Failed to get genesis state from app state: %s", err.Error()))
}
}
}
// 4 balances were present in the original genesis state
require.Len(t, bankStateAfterImport.Balances, 4)
// 4 balances were present in the original genesis state
require.Len(t, bankStateAfterImport.Balances, 4)

// Emissions module is in Copy list
var emissionStateAfterImport emissionstypes.GenesisState
if appState[emissionstypes.ModuleName] != nil {
err := cdc.UnmarshalJSON(appState[emissionstypes.ModuleName], &emissionStateAfterImport)
if err != nil {
panic(fmt.Sprintf("Failed to get genesis state from app state: %s", err.Error()))
// Emissions module is in Copy list
var emissionStateAfterImport emissionstypes.GenesisState
if appState[emissionstypes.ModuleName] != nil {
err := cdc.UnmarshalJSON(appState[emissionstypes.ModuleName], &emissionStateAfterImport)
if err != nil {
panic(fmt.Sprintf("Failed to get genesis state from app state: %s", err.Error()))
}
}
}
require.Len(t, emissionStateAfterImport.WithdrawableEmissions, 100)
require.Len(t, emissionStateAfterImport.WithdrawableEmissions, 100)
})

t.Run("successfully import data into file without modifying data", func(t *testing.T) {
setConfig(t)
cdc := keepertest.NewCodec()
genDoc := sample.GenDoc(t)
importGenDoc := ImportGenDoc(t, cdc, 8)

err := zetacored.ImportDataIntoFile(genDoc, importGenDoc, cdc, false)
require.NoError(t, err)

appState, err := genutiltypes.GenesisStateFromGenDoc(*genDoc)
require.NoError(t, err)

// Crosschain module is in Modify list
crosschainStateAfterImport := crosschaintypes.GetGenesisStateFromAppState(cdc, appState)
require.Len(t, crosschainStateAfterImport.CrossChainTxs, 0)
require.Len(t, crosschainStateAfterImport.InboundHashToCctxList, 0)
require.Len(t, crosschainStateAfterImport.FinalizedInbounds, 0)

// Bank module is in Skip list
var bankStateAfterImport banktypes.GenesisState
if appState[banktypes.ModuleName] != nil {
err := cdc.UnmarshalJSON(appState[banktypes.ModuleName], &bankStateAfterImport)
if err != nil {
panic(fmt.Sprintf("Failed to get genesis state from app state: %s", err.Error()))
}
}
// 4 balances were present in the original genesis state
require.Len(t, bankStateAfterImport.Balances, 4)

// Emissions module is in Copy list
var emissionStateAfterImport emissionstypes.GenesisState
if appState[emissionstypes.ModuleName] != nil {
err := cdc.UnmarshalJSON(appState[emissionstypes.ModuleName], &emissionStateAfterImport)
if err != nil {
panic(fmt.Sprintf("Failed to get genesis state from app state: %s", err.Error()))
}
}
require.Len(t, emissionStateAfterImport.WithdrawableEmissions, 8)

})
}

func Test_GetGenDoc(t *testing.T) {
Expand Down
30 changes: 30 additions & 0 deletions contrib/localnet/docker-compose-import-data.yml
kingpinXD marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
version: "3"

# This docker-compose file configures the localnet environment
# it contains the following services:
# - ZetaChain with 2 nodes (zetacore0, zetacore1)
# - A observer set with 2 clients (zetaclient0, zetaclient1)
# - An Ethereum node (eth)
# - A Bitcoin node (bitcoin)
# - A Rosetta API (rosetta)
# - An orchestrator to manage interaction with the localnet (orchestrator)
services:
rosetta:
entrypoint: ["/root/start-rosetta.sh"]

zetacore0:
entrypoint: ["/root/start-zetacored.sh", "2","import-data"]
volumes:
- ~/genesis_export/:/root/genesis_data

zetacore1:
entrypoint: ["/root/start-zetacored.sh", "2","import-data"]

zetaclient0:
entrypoint: ["/root/start-zetaclientd.sh"]

zetaclient1:
entrypoint: ["/root/start-zetaclientd.sh"]

orchestrator:
entrypoint: ["/work/start-zetae2e.sh", "local"]
6 changes: 6 additions & 0 deletions contrib/localnet/orchestrator/start-zetae2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ while [ ! -f ~/.ssh/authorized_keys ]; do
sleep 1
done

# need to wait for zetacore0 to be up
while ! curl -s -o /dev/null zetacore0:26657/status ; do
echo "Waiting for zetacore0 rpc"
sleep 10
done

echo "waiting for geth RPC to start..."
sleep 2

Expand Down
15 changes: 15 additions & 0 deletions contrib/localnet/scripts/import-data.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
if [ $# -lt 1 ]
then
echo "Usage: import-data.sh [network]"
exit 1
fi

NETWORK=$1
echo "NETWORK: ${NETWORK}"
rm -rf ~/genesis_export/
mkdir ~/genesis_export/
echo "Download Latest State Export"
LATEST_EXPORT_URL=$(curl https://snapshots.zetachain.com/latest-state-export | jq -r ."${NETWORK}")
echo "LATEST EXPORT URL: ${LATEST_EXPORT_URL}"
wget -q ${LATEST_EXPORT_URL} -O ~/genesis_export/exported-genesis.json
14 changes: 14 additions & 0 deletions contrib/localnet/scripts/start-rosetta.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash

# This script is used to start the Rosetta API server for the Zetacore network.

echo "Waiting for network to start producing blocks"
CURRENT_HEIGHT=0
WAIT_HEIGHT=1
while [[ $CURRENT_HEIGHT -lt $WAIT_HEIGHT ]]
do
CURRENT_HEIGHT=$(curl -s zetacore0:26657/status | jq '.result.sync_info.latest_block_height' | tr -d '"')
sleep 5
done

zetacored rosetta --tendermint zetacore0:26657 --grpc zetacore0:9090 --network athens_101-1 --blockchain zetacore
9 changes: 9 additions & 0 deletions contrib/localnet/scripts/start-zetaclientd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ while [ ! -f ~/.ssh/authorized_keys ]; do
sleep 1
done



# need to wait for zetacore0 to be up
while ! curl -s -o /dev/null zetacore0:26657/status ; do
echo "Waiting for zetacore0 rpc"
sleep 10
done


# read HOTKEY_BACKEND env var for hotkey keyring backend and set default to test
BACKEND="test"
if [ "$HOTKEY_BACKEND" == "file" ]; then
Expand Down
8 changes: 8 additions & 0 deletions contrib/localnet/scripts/start-zetacored.sh
kingpinXD marked this conversation as resolved.
Show resolved Hide resolved
kingpinXD marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
# It initializes the nodes and creates the genesis.json file
# It also starts the nodes
# The number of nodes is passed as an first argument to the script
# The second argument is optional and can have the following value:
# - import-data: import data into the genesis file

/usr/sbin/sshd

Expand Down Expand Up @@ -71,6 +73,7 @@ then
exit 1
fi
NUMOFNODES=$1
OPTION=$2

# create keys
CHAINID="athens_101-1"
Expand Down Expand Up @@ -254,6 +257,11 @@ then
scp $NODE:~/.zetacored/config/gentx/* ~/.zetacored/config/gentx/z2gentx/
done

if [[ "$OPTION" == "import-data" || "$OPTION" == "import-data-upgrade" ]]; then
echo "Importing data"
zetacored parse-genesis-file /root/genesis_data/exported-genesis.json
fi

# 4. Collect all the gentx files in zetacore0 and create the final genesis.json
zetacored collect-gentxs
zetacored validate-genesis
Expand Down
Loading