From f369f47fa0f34e6ae25f6d3ad979ed8f913e506f Mon Sep 17 00:00:00 2001 From: Krishna Upadhyaya Date: Wed, 4 Aug 2021 13:30:05 +0530 Subject: [PATCH 01/16] Bridge nonce issue fix (#715) * new: add check to validate nonce in bridge stake update task * update: save last stake txn block in state instead of map in bridge * update: change variable name * update: used tx_query to fetch recent stake txn count * update: use helper package for query method * log: added more details to logger * update: added support for all staking txns * fix: update log message --- bridge/setu/processor/staking.go | 110 +++++++++++++++++++++++++++++++ bridge/setu/util/common.go | 24 +++++++ 2 files changed, 134 insertions(+) diff --git a/bridge/setu/processor/staking.go b/bridge/setu/processor/staking.go index 9ab3ace6..f1ee7a31 100644 --- a/bridge/setu/processor/staking.go +++ b/bridge/setu/processor/staking.go @@ -2,6 +2,8 @@ package processor import ( "encoding/json" + "fmt" + "time" "github.com/RichardKnop/machinery/v1/tasks" cliContext "github.com/cosmos/cosmos-sdk/client/context" @@ -15,6 +17,10 @@ import ( hmTypes "github.com/maticnetwork/heimdall/types" ) +const ( + defaultDelayDuration time.Duration = 10 * time.Second +) + // StakingProcessor - process staking related events type StakingProcessor struct { BaseProcessor @@ -93,6 +99,17 @@ func (sp *StakingProcessor) sendValidatorJoinToHeimdall(eventName string, logByt return tasks.NewErrRetryTaskLater("account doesn't exist", util.RetryTaskDelay) } + validNonce, nonceDelay, err := sp.checkValidNonce(event.ValidatorId.Uint64(), event.Nonce.Uint64()) + if err != nil { + sp.Logger.Error("Error while validating nonce for the validator", "error", err) + return err + } + + if !validNonce { + sp.Logger.Info("Ignoring task to send validator-join to heimdall as nonce is out of order") + return tasks.NewErrRetryTaskLater("Nonce out of order", defaultDelayDuration*time.Duration(nonceDelay)) + } + sp.Logger.Info( "✅ Received task to send validatorjoin to heimdall", "event", eventName, @@ -155,6 +172,17 @@ func (sp *StakingProcessor) sendUnstakeInitToHeimdall(eventName string, logBytes return nil } + validNonce, nonceDelay, err := sp.checkValidNonce(event.ValidatorId.Uint64(), event.Nonce.Uint64()) + if err != nil { + sp.Logger.Error("Error while validating nonce for the validator", "error", err) + return err + } + + if !validNonce { + sp.Logger.Info("Ignoring task to send unstake-init to heimdall as nonce is out of order") + return tasks.NewErrRetryTaskLater("Nonce out of order", defaultDelayDuration*time.Duration(nonceDelay)) + } + sp.Logger.Info( "✅ Received task to send unstake-init to heimdall", "event", eventName, @@ -211,6 +239,18 @@ func (sp *StakingProcessor) sendStakeUpdateToHeimdall(eventName string, logBytes ) return nil } + + validNonce, nonceDelay, err := sp.checkValidNonce(event.ValidatorId.Uint64(), event.Nonce.Uint64()) + if err != nil { + sp.Logger.Error("Error while validating nonce for the validator", "error", err) + return err + } + + if !validNonce { + sp.Logger.Info("Ignoring task to send stake-update to heimdall as nonce is out of order") + return tasks.NewErrRetryTaskLater("Nonce out of order", defaultDelayDuration*time.Duration(nonceDelay)) + } + sp.Logger.Info( "✅ Received task to send stake-update to heimdall", "event", eventName, @@ -272,6 +312,18 @@ func (sp *StakingProcessor) sendSignerChangeToHeimdall(eventName string, logByte ) return nil } + + validNonce, nonceDelay, err := sp.checkValidNonce(event.ValidatorId.Uint64(), event.Nonce.Uint64()) + if err != nil { + sp.Logger.Error("Error while validating nonce for the validator", "error", err) + return err + } + + if !validNonce { + sp.Logger.Info("Ignoring task to send signer-change to heimdall as nonce is out of order") + return tasks.NewErrRetryTaskLater("Nonce out of order", defaultDelayDuration*time.Duration(nonceDelay)) + } + sp.Logger.Info( "✅ Received task to send signer-change to heimdall", "event", eventName, @@ -333,3 +385,61 @@ func (sp *StakingProcessor) isOldTx(cliCtx cliContext.CLIContext, txHash string, return status, nil } + +func (sp *StakingProcessor) checkValidNonce(validatorId uint64, txnNonce uint64) (bool, uint64, error) { + currentNonce, currentHeight, err := util.GetValidatorNonce(sp.cliCtx, validatorId) + if err != nil { + sp.Logger.Error("Failed to fetch validator nonce and height data from API", "validatorId", validatorId) + return false, 0, err + } + + if currentNonce+1 != txnNonce { + sp.Logger.Error("Nonce for the given event not in order", "validatorId", validatorId, "currentNonce", currentNonce, "txnNonce", txnNonce) + return false, txnNonce - currentNonce, nil + } + + stakingTxnCount, err := queryTxCount(sp.cliCtx, validatorId, currentHeight) + if err != nil { + sp.Logger.Error("Failed to query stake txns by txquery for the given validator", "validatorId", validatorId) + return false, 0, err + } + + if stakingTxnCount != 0 { + sp.Logger.Info("Recent staking txn count for the given validator is not zero", "validatorId", validatorId, "currentNonce", currentNonce, "txnNonce", txnNonce, "currentHeight", currentHeight) + return false, 1, nil + } + + return true, 0, nil +} + +func queryTxCount(cliCtx cliContext.CLIContext, validatorId uint64, currentHeight int64) (int, error) { + const ( + defaultPage = 1 + defaultLimit = 30 // should be consistent with tendermint/tendermint/rpc/core/pipe.go:19 + ) + + stakingTxnMsgMap := map[string]string{ + "validator-stake-update": "stake-update", + "validator-join": "validator-join", + "signer-update": "signer-update", + "validator-exit": "validator-exit", + } + + for msg, action := range stakingTxnMsgMap { + events := []string{ + fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeyAction, msg), + fmt.Sprintf("%s.%s=%d", action, "validator-id", validatorId), + fmt.Sprintf("%s.%s>%d", "tx", "height", currentHeight-3), + } + + searchResult, err := helper.QueryTxsByEvents(cliCtx, events, defaultPage, defaultLimit) + if err != nil { + return 0, err + } + + if searchResult.TotalCount != 0 { + return searchResult.TotalCount, nil + } + } + return 0, nil +} diff --git a/bridge/setu/util/common.go b/bridge/setu/util/common.go index a4bf297d..cd5f22d2 100644 --- a/bridge/setu/util/common.go +++ b/bridge/setu/util/common.go @@ -382,3 +382,27 @@ func AppendPrefix(signerPubKey []byte) []byte { signerPubKey = append(prefix[:], signerPubKey[:]...) return signerPubKey } + +// GetValidatorNonce fethes validator nonce and height +func GetValidatorNonce(cliCtx cliContext.CLIContext, validatorID uint64) (uint64, int64, error) { + var validator hmtypes.Validator + + result, err := helper.FetchFromAPI(cliCtx, + helper.GetHeimdallServerEndpoint(fmt.Sprintf(ValidatorURL, strconv.FormatUint(validatorID, 10))), + ) + + if err != nil { + logger.Error("Error fetching validator data", "error", err) + return 0, 0, err + } + + err = json.Unmarshal(result.Result, &validator) + if err != nil { + logger.Error("error unmarshalling validator data", "error", err) + return 0, 0, err + } + + logger.Debug("Validator data recieved ", "validator", validator.String()) + + return validator.Nonce, result.Height, nil +} From d4d6499e9d7c4e757af42ebfb286ba898f7e1936 Mon Sep 17 00:00:00 2001 From: Krishna Upadhyaya Date: Wed, 4 Aug 2021 23:33:25 +0530 Subject: [PATCH 02/16] fix: check end block instead of latest which checkpoint (#718) --- helper/call.go | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/helper/call.go b/helper/call.go index bd926dd9..75613ee5 100644 --- a/helper/call.go +++ b/helper/call.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "errors" + "fmt" "math/big" "strings" @@ -705,21 +706,17 @@ func (c *ContractCaller) CurrentStateCounter(stateSenderInstance *statesender.St return result } -// CheckIfBlocksExist - check if latest block number is greater than end block +// CheckIfBlocksExist - check if the given block exists on local chain func (c *ContractCaller) CheckIfBlocksExist(end uint64) bool { - // Get Latest block number. - var latestBlock *ethTypes.Header + // Get block by number. + var block *ethTypes.Header - err := c.MaticChainRPC.Call(&latestBlock, "eth_getBlockByNumber", "latest", false) + err := c.MaticChainRPC.Call(&block, "eth_getBlockByNumber", fmt.Sprintf("0x%x", end), false) if err != nil { return false } - if end > latestBlock.Number.Uint64() { - return false - } - - return true + return end == block.Number.Uint64() } // From 2191326d21da3f3ff221dcf049cfaac961303018 Mon Sep 17 00:00:00 2001 From: Krishna Upadhyaya Date: Wed, 18 Aug 2021 15:03:12 +0530 Subject: [PATCH 03/16] add: check for max gas price in tx builder (#720) --- helper/config.go | 6 ++++++ helper/toml.go | 3 +++ helper/tx.go | 14 ++++++++++---- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/helper/config.go b/helper/config.go index 1ae88514..c10705c8 100644 --- a/helper/config.go +++ b/helper/config.go @@ -64,6 +64,8 @@ const ( DefaultMainchainGasLimit = uint64(5000000) + DefaultMainchainMaxGasPrice = 400000000000 // 400 Gwei + DefaultBorChainID string = "15001" secretFilePerm = 0600 @@ -94,6 +96,8 @@ type Configuration struct { MainchainGasLimit uint64 `mapstructure:"main_chain_gas_limit"` // gas limit to mainchain transaction. eg....submit checkpoint. + MainchainMaxGasPrice int64 `mapstructure:"main_chain_max_gas_price"` // max gas price to mainchain transaction. eg....submit checkpoint. + // config related to bridge CheckpointerPollInterval time.Duration `mapstructure:"checkpoint_poll_interval"` // Poll interval for checkpointer service to send new checkpoints or missing ACK SyncerPollInterval time.Duration `mapstructure:"syncer_poll_interval"` // Poll interval for syncher service to sync for changes on main chain @@ -214,6 +218,8 @@ func GetDefaultHeimdallConfig() Configuration { MainchainGasLimit: DefaultMainchainGasLimit, + MainchainMaxGasPrice: DefaultMainchainMaxGasPrice, + CheckpointerPollInterval: DefaultCheckpointerPollInterval, SyncerPollInterval: DefaultSyncerPollInterval, NoACKPollInterval: DefaultNoACKPollInterval, diff --git a/helper/toml.go b/helper/toml.go index 5e3b5307..26d8a975 100644 --- a/helper/toml.go +++ b/helper/toml.go @@ -42,6 +42,9 @@ span_poll_interval = "{{ .SpanPollInterval }}" #### gas limits #### main_chain_gas_limit = "{{ .MainchainGasLimit }}" +#### gas price #### +main_chain_max_gas_price = "{{ .MainchainMaxGasPrice }}" + ##### Timeout Config ##### no_ack_wait_time = "{{ .NoACKWaitTime }}" diff --git a/helper/tx.go b/helper/tx.go index de7f5854..4c800769 100644 --- a/helper/tx.go +++ b/helper/tx.go @@ -41,6 +41,14 @@ func GenerateAuthObj(client *ethclient.Client, address common.Address, data []by if err != nil { return } + + mainChainMaxGasPrice := GetConfig().MainchainMaxGasPrice + if gasprice.Cmp(big.NewInt(mainChainMaxGasPrice)) == 1 { + Logger.Error("Gas price is more than max gas price", "gasprice", gasprice) + err = fmt.Errorf("gas price is more than max_gas_price, gasprice = %v, maxGasPrice = %d", gasprice, mainChainMaxGasPrice) + return + } + // fetch nonce nonce, err := client.PendingNonceAt(context.Background(), fromAddress) if err != nil { @@ -72,8 +80,7 @@ func (c *ContractCaller) SendCheckpoint(signedData []byte, sigs [][3]*big.Int, r auth, err := GenerateAuthObj(GetMainClient(), rootChainAddress, data) if err != nil { Logger.Error("Unable to create auth object", "error", err) - Logger.Info("Setting custom gaslimit", "gaslimit", GetConfig().MainchainGasLimit) - auth.GasLimit = GetConfig().MainchainGasLimit + return err } s := make([]string, 0) @@ -106,8 +113,7 @@ func (c *ContractCaller) SendTick(signedData []byte, sigs []byte, slashManagerAd auth, err := GenerateAuthObj(GetMainClient(), slashManagerAddress, data) if err != nil { Logger.Error("Unable to create auth object", "error", err) - Logger.Info("Setting custom gaslimit", "gaslimit", GetConfig().MainchainGasLimit) - auth.GasLimit = GetConfig().MainchainGasLimit + return err } Logger.Info("Sending new tick", From 05f255eb4b00a8a18bca27cff166bb693a707377 Mon Sep 17 00:00:00 2001 From: Vamsi Reddy Date: Wed, 18 Aug 2021 15:03:33 +0530 Subject: [PATCH 04/16] Add min bor block confirmation check (#722) * Matic tx confirmation also to be checked by nodes apart from the proposer too. * chainmanager keeper params to be fetcher from the checkpoint keeper. Fix * fix test cases Co-authored-by: Krishna Upadhyaya --- checkpoint/handler_test.go | 3 ++- checkpoint/side_handler.go | 3 ++- checkpoint/side_handler_test.go | 7 ++++--- checkpoint/types/merkel.go | 4 ++-- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/checkpoint/handler_test.go b/checkpoint/handler_test.go index 6d4a2e9c..689eb024 100644 --- a/checkpoint/handler_test.go +++ b/checkpoint/handler_test.go @@ -8,6 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/maticnetwork/heimdall/app" + cmTypes "github.com/maticnetwork/heimdall/chainmanager/types" "github.com/maticnetwork/heimdall/checkpoint/types" errs "github.com/maticnetwork/heimdall/common" @@ -414,7 +415,7 @@ func (suite *HandlerTestSuite) SendCheckpoint(header hmTypes.Checkpoint) (res sd borChainId, ) - suite.contractCaller.On("CheckIfBlocksExist", header.EndBlock).Return(true) + suite.contractCaller.On("CheckIfBlocksExist", header.EndBlock+cmTypes.DefaultMaticchainTxConfirmations).Return(true) suite.contractCaller.On("GetRootHash", header.StartBlock, header.EndBlock, uint64(1024)).Return(header.RootHash.Bytes(), nil) // send checkpoint to handler diff --git a/checkpoint/side_handler.go b/checkpoint/side_handler.go index f0c86d2d..8f95d13d 100644 --- a/checkpoint/side_handler.go +++ b/checkpoint/side_handler.go @@ -36,12 +36,13 @@ func NewSideTxHandler(k Keeper, contractCaller helper.IContractCaller) hmTypes.S func SideHandleMsgCheckpoint(ctx sdk.Context, k Keeper, msg types.MsgCheckpoint, contractCaller helper.IContractCaller) (result abci.ResponseDeliverSideTx) { // get params params := k.GetParams(ctx) + maticTxConfirmations := k.ck.GetParams(ctx).MaticchainTxConfirmations // logger logger := k.Logger(ctx) // validate checkpoint - validCheckpoint, err := types.ValidateCheckpoint(msg.StartBlock, msg.EndBlock, msg.RootHash, params.MaxCheckpointLength, contractCaller) + validCheckpoint, err := types.ValidateCheckpoint(msg.StartBlock, msg.EndBlock, msg.RootHash, params.MaxCheckpointLength, contractCaller, maticTxConfirmations) if err != nil { logger.Error("Error validating checkpoint", "error", err, diff --git a/checkpoint/side_handler_test.go b/checkpoint/side_handler_test.go index c78f88d8..b6490fcf 100644 --- a/checkpoint/side_handler_test.go +++ b/checkpoint/side_handler_test.go @@ -8,6 +8,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/maticnetwork/heimdall/app" + cmTypes "github.com/maticnetwork/heimdall/chainmanager/types" "github.com/maticnetwork/heimdall/checkpoint" chSim "github.com/maticnetwork/heimdall/checkpoint/simulation" "github.com/maticnetwork/heimdall/checkpoint/types" @@ -88,7 +89,7 @@ func (suite *SideHandlerTestSuite) TestSideHandleMsgCheckpoint() { borChainId, ) - suite.contractCaller.On("CheckIfBlocksExist", header.EndBlock).Return(true) + suite.contractCaller.On("CheckIfBlocksExist", header.EndBlock+cmTypes.DefaultMaticchainTxConfirmations).Return(true) suite.contractCaller.On("GetRootHash", header.StartBlock, header.EndBlock, uint64(1024)).Return(header.RootHash.Bytes(), nil) result := suite.sideHandler(ctx, msgCheckpoint) @@ -111,7 +112,7 @@ func (suite *SideHandlerTestSuite) TestSideHandleMsgCheckpoint() { borChainId, ) - suite.contractCaller.On("CheckIfBlocksExist", header.EndBlock).Return(true) + suite.contractCaller.On("CheckIfBlocksExist", header.EndBlock+cmTypes.DefaultMaticchainTxConfirmations).Return(true) suite.contractCaller.On("GetRootHash", header.StartBlock, header.EndBlock, uint64(1024)).Return(nil, nil) result := suite.sideHandler(ctx, msgCheckpoint) @@ -137,7 +138,7 @@ func (suite *SideHandlerTestSuite) TestSideHandleMsgCheckpoint() { borChainId, ) - suite.contractCaller.On("CheckIfBlocksExist", header.EndBlock).Return(true) + suite.contractCaller.On("CheckIfBlocksExist", header.EndBlock+cmTypes.DefaultMaticchainTxConfirmations).Return(true) suite.contractCaller.On("GetRootHash", header.StartBlock, header.EndBlock, uint64(1024)).Return([]byte{1}, nil) result := suite.sideHandler(ctx, msgCheckpoint) diff --git a/checkpoint/types/merkel.go b/checkpoint/types/merkel.go index 382f8aca..45341d14 100644 --- a/checkpoint/types/merkel.go +++ b/checkpoint/types/merkel.go @@ -15,9 +15,9 @@ import ( ) // ValidateCheckpoint - Validates if checkpoint rootHash matches or not -func ValidateCheckpoint(start uint64, end uint64, rootHash hmTypes.HeimdallHash, checkpointLength uint64, contractCaller helper.IContractCaller) (bool, error) { +func ValidateCheckpoint(start uint64, end uint64, rootHash hmTypes.HeimdallHash, checkpointLength uint64, contractCaller helper.IContractCaller, confirmations uint64) (bool, error) { // Check if blocks exist locally - if !contractCaller.CheckIfBlocksExist(end) { + if !contractCaller.CheckIfBlocksExist(end + confirmations) { return false, errors.New("blocks not found locally") } From 9c1f70f720bcfe53d06c2ab541c71b6dc04511d3 Mon Sep 17 00:00:00 2001 From: Krishna Upadhyaya Date: Mon, 23 Aug 2021 13:15:11 +0530 Subject: [PATCH 05/16] Template for new selection algo height (#723) * add: template for heimdall-params.go * update: README * fix: add make process-template to github ci flow * add: support for local network in process-template * update: moved process-template to build and install * update: formatting --- Makefile | 16 +++++++- bor/keeper.go | 2 +- helper/heimdall-params.template.go | 62 ++++++++++++++++++++++++++++++ mainnet.toml | 1 + mumbai.toml | 1 + 5 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 helper/heimdall-params.template.go create mode 100644 mainnet.toml create mode 100644 mumbai.toml diff --git a/Makefile b/Makefile index 9a5df31a..ccf7c3a0 100644 --- a/Makefile +++ b/Makefile @@ -18,21 +18,33 @@ BUILD_FLAGS := -ldflags '$(ldflags)' clean: rm -rf build + rm -f helper/heimdall-params.go tests: # go test -v ./... go test -v ./app/ ./auth/ ./clerk/ ./sidechannel/ ./bank/ ./chainmanager/ ./topup/ ./checkpoint/ ./staking/ -cover -coverprofile=cover.out - +# make build Will generate for mainnet by default +# make build network=mainnet Will generate for mainnet +# make build network=mumbai Will generate for mumbai +# make build network=local Will generate for local with NewSelectionAlgoHeight = 0 +# make build network=anythingElse Will generate for mainnet by default build: clean + go run helper/heimdall-params.template.go $(network) mkdir -p build go build -o build/heimdalld ./cmd/heimdalld go build -o build/heimdallcli ./cmd/heimdallcli go build -o build/bridge bridge/bridge.go @echo "====================================================\n==================Build Successful==================\n====================================================" - + +# make install Will generate for mainnet by default +# make install network=mainnet Will generate for mainnet +# make install network=mumbai Will generate for mumbai +# make install network=local Will generate for local with NewSelectionAlgoHeight = 0 +# make install network=anythingElse Will generate for mainnet by default install: + go run helper/heimdall-params.template.go $(network) go install $(BUILD_FLAGS) ./cmd/heimdalld go install $(BUILD_FLAGS) ./cmd/heimdallcli go install $(BUILD_FLAGS) bridge/bridge.go diff --git a/bor/keeper.go b/bor/keeper.go index 7e8269cc..a7fb8b9f 100644 --- a/bor/keeper.go +++ b/bor/keeper.go @@ -232,7 +232,7 @@ func (k *Keeper) SelectNextProducers(ctx sdk.Context, seed common.Hash) (vals [] // TODO remove old selection algorigthm // select next producers using seed as blockheader hash fn := SelectNextProducers - if ctx.BlockHeight() < 375300 { + if ctx.BlockHeight() < helper.NewSelectionAlgoHeight { fn = XXXSelectNextProducers } diff --git a/helper/heimdall-params.template.go b/helper/heimdall-params.template.go new file mode 100644 index 00000000..00ad74b4 --- /dev/null +++ b/helper/heimdall-params.template.go @@ -0,0 +1,62 @@ +// The following directive is necessary to make the package coherent: + +// +build ignore + +// This program generate heimdall-params.go, It must be invoked from make file that purpose only. + +package main + +import ( + "fmt" + "log" + "os" + "text/template" + + "github.com/BurntSushi/toml" +) + +var packageTemplate = template.Must(template.New("").Parse(`package helper + +const NewSelectionAlgoHeight = {{ .BlockHeight }} +`)) + +var tomlConfig struct { + NewSelectionAlgoHeight int `toml:"new_selection_algo_height"` +} + +var networks = []string{ + "mainnet", + "mumbai", + "local", +} + +func main() { + var network = networks[0] + if len(os.Args) > 1 { + networkFile := os.Args[1] + for _, n := range networks { + if n == networkFile { + network = networkFile + } + } + } + + filePath := fmt.Sprintf("%s.toml", network) + toml.DecodeFile(filePath, &tomlConfig) + + f, err := os.Create("helper/heimdall-params.go") + chekcError(err) + defer f.Close() + + packageTemplate.Execute(f, struct { + BlockHeight int + }{ + BlockHeight: tomlConfig.NewSelectionAlgoHeight, + }) +} + +func chekcError(err error) { + if err != nil { + log.Fatal(err) + } +} diff --git a/mainnet.toml b/mainnet.toml new file mode 100644 index 00000000..b3e409a0 --- /dev/null +++ b/mainnet.toml @@ -0,0 +1 @@ +new_selection_algo_height = 375300 diff --git a/mumbai.toml b/mumbai.toml new file mode 100644 index 00000000..3af8d224 --- /dev/null +++ b/mumbai.toml @@ -0,0 +1 @@ +new_selection_algo_height = 282500 From 93b88e8f5cf0e79444fb13e888d06c7a9ca4719b Mon Sep 17 00:00:00 2001 From: Jaynti Kanani Date: Mon, 23 Aug 2021 13:08:16 +0400 Subject: [PATCH 06/16] Update linuxpackage.yml (#724) --- .github/workflows/linuxpackage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linuxpackage.yml b/.github/workflows/linuxpackage.yml index 99d28d58..6db7a355 100644 --- a/.github/workflows/linuxpackage.yml +++ b/.github/workflows/linuxpackage.yml @@ -21,7 +21,7 @@ jobs: ruby-version: 2.6 - name: Retrieve release version - run: echo "::set-env name=RELEASE_VERSION::${GITHUB_REF/refs\/tags\/v/}" + run: echo "RELEASE_VERSION=${GITHUB_REF/refs\/tags\/v/}" >> $GITHUB_ENV - name: Build package run: | From 9ceee1a78f274fbf2fefc4242f8773ed95cb180c Mon Sep 17 00:00:00 2001 From: Krishna Upadhyaya Date: Mon, 23 Aug 2021 22:29:07 +0530 Subject: [PATCH 07/16] Update: README (#725) * Update: README * fix README indentation --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 18cf3b2f..51e5b20c 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,16 @@ Make sure your have go1.11+ already installed ### Install ```bash -$ make install -``` - +$ make install network=mainnet +``` +#### Usage +``` +# make install Will generate for mainnet by default +# make install network=mainnet Will generate for mainnet +# make install network=mumbai Will generate for mumbai +# make install network=local Will generate for local with NewSelectionAlgoHeight = 0 +# make install network=anythingElse Will generate for mainnet by default +``` ### Run-heimdall ```bash $ heimdalld start From c5a1a066fbcfcee8aec363e73d1453825cb63c2d Mon Sep 17 00:00:00 2001 From: Arpit Temani Date: Wed, 6 Oct 2021 21:18:28 +0530 Subject: [PATCH 08/16] add checkpoint-adjust (#730) * add checkpoint-adjust * removed unnecessary params * add checkpoint buffer check * review comments fix * fix syntax * fix emit events * add testcases * Update side_handler.go * review comments * add test cases --- .gitignore | 1 + checkpoint/client/cli/flags.go | 1 + checkpoint/client/cli/tx.go | 86 ++++++++++++++++++++++-- checkpoint/handler.go | 40 +++++++++++ checkpoint/handler_test.go | 52 +++++++++++++++ checkpoint/side_handler.go | 114 ++++++++++++++++++++++++++++++++ checkpoint/side_handler_test.go | 92 ++++++++++++++++++++++++++ checkpoint/types/codec.go | 1 + checkpoint/types/events.go | 7 +- checkpoint/types/msg.go | 71 ++++++++++++++++++++ common/error.go | 10 +++ 11 files changed, 467 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 613d8e19..d8754500 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ logs .idea .vscode +helper/heimdall-params.go diff --git a/checkpoint/client/cli/flags.go b/checkpoint/client/cli/flags.go index 954256a7..a8f793d2 100644 --- a/checkpoint/client/cli/flags.go +++ b/checkpoint/client/cli/flags.go @@ -2,6 +2,7 @@ package cli const ( FlagProposerAddress = "proposer" + FlagFromAddress = "from" FlagStartBlock = "start-block" FlagEndBlock = "end-block" FlagRootHash = "root-hash" diff --git a/checkpoint/client/cli/tx.go b/checkpoint/client/cli/tx.go index 9c54303d..ebeadc01 100644 --- a/checkpoint/client/cli/tx.go +++ b/checkpoint/client/cli/tx.go @@ -39,11 +39,92 @@ func GetTxCmd(cdc *codec.Codec) *cobra.Command { SendCheckpointTx(cdc), SendCheckpointACKTx(cdc), SendCheckpointNoACKTx(cdc), + SendCheckpointAdjust(cdc), )..., ) return txCmd } +// SendCheckpointAdjust adjusts previous checkpoint transaction +func SendCheckpointAdjust(cdc *codec.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "checkpoint-adjust", + Short: "adjusts previous checkpoint transaction according to ethereum chain (details to be provided for checkpoint on ethereum chain)", + RunE: func(cmd *cobra.Command, args []string) error { + cliCtx := context.NewCLIContext().WithCodec(cdc) + + // header index + headerIndexStr := viper.GetString(FlagHeaderNumber) + if headerIndexStr == "" { + return fmt.Errorf("header number cannot be empty") + } + headerIndex, err := strconv.ParseUint(headerIndexStr, 10, 64) + if err != nil { + return err + } + + // get from + from := helper.GetFromAddress(cliCtx) + + // get proposer + proposer := hmTypes.HexToHeimdallAddress(viper.GetString(FlagProposerAddress)) + if proposer.Empty() { + return fmt.Errorf("proposer cannot be empty") + } + + // start block + startBlockStr := viper.GetString(FlagStartBlock) + if startBlockStr == "" { + return fmt.Errorf("start block cannot be empty") + } + startBlock, err := strconv.ParseUint(startBlockStr, 10, 64) + if err != nil { + return err + } + + // end block + endBlockStr := viper.GetString(FlagEndBlock) + if endBlockStr == "" { + return fmt.Errorf("end block cannot be empty") + } + endBlock, err := strconv.ParseUint(endBlockStr, 10, 64) + if err != nil { + return err + } + + // root hash + rootHashStr := viper.GetString(FlagRootHash) + if rootHashStr == "" { + return fmt.Errorf("root hash cannot be empty") + } + + msg := types.NewMsgCheckpointAdjust( + headerIndex, + startBlock, + endBlock, + proposer, + from, + hmTypes.HexToHeimdallHash(rootHashStr), + ) + + return helper.BroadcastMsgsWithCLI(cliCtx, []sdk.Msg{msg}) + }, + } + cmd.Flags().String(FlagHeaderNumber, "", "--header=") + cmd.Flags().StringP(FlagProposerAddress, "p", "", "--proposer=") + cmd.Flags().String(FlagStartBlock, "", "--start-block=") + cmd.Flags().String(FlagEndBlock, "", "--end-block=") + cmd.Flags().StringP(FlagRootHash, "r", "", "--root-hash=") + + cmd.MarkFlagRequired(FlagHeaderNumber) + cmd.MarkFlagRequired(FlagRootHash) + cmd.MarkFlagRequired(FlagProposerAddress) + cmd.MarkFlagRequired(FlagStartBlock) + cmd.MarkFlagRequired(FlagEndBlock) + + return cmd +} + // SendCheckpointTx send checkpoint transaction func SendCheckpointTx(cdc *codec.Codec) *cobra.Command { cmd := &cobra.Command{ @@ -103,31 +184,26 @@ func SendCheckpointTx(cdc *codec.Codec) *cobra.Command { } // start block - startBlockStr := viper.GetString(FlagStartBlock) if startBlockStr == "" { return fmt.Errorf("start block cannot be empty") } - startBlock, err := strconv.ParseUint(startBlockStr, 10, 64) if err != nil { return err } // end block - endBlockStr := viper.GetString(FlagEndBlock) if endBlockStr == "" { return fmt.Errorf("end block cannot be empty") } - endBlock, err := strconv.ParseUint(endBlockStr, 10, 64) if err != nil { return err } // root hash - rootHashStr := viper.GetString(FlagRootHash) if rootHashStr == "" { return fmt.Errorf("root hash cannot be empty") diff --git a/checkpoint/handler.go b/checkpoint/handler.go index 3211c95c..8448be5d 100644 --- a/checkpoint/handler.go +++ b/checkpoint/handler.go @@ -18,6 +18,8 @@ func NewHandler(k Keeper, contractCaller helper.IContractCaller) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { ctx = ctx.WithEventManager(sdk.NewEventManager()) switch msg := msg.(type) { + case types.MsgCheckpointAdjust: + return handleMsgCheckpointAdjust(ctx, msg, k, contractCaller) case types.MsgCheckpoint: return handleMsgCheckpoint(ctx, msg, k, contractCaller) case types.MsgCheckpointAck: @@ -30,6 +32,44 @@ func NewHandler(k Keeper, contractCaller helper.IContractCaller) sdk.Handler { } } +// handleMsgCheckpointAdjust adjusts checkpoint +func handleMsgCheckpointAdjust(ctx sdk.Context, msg types.MsgCheckpointAdjust, k Keeper, contractCaller helper.IContractCaller) sdk.Result { + logger := k.Logger(ctx) + + checkpointBuffer, err := k.GetCheckpointFromBuffer(ctx) + if checkpointBuffer != nil { + logger.Error("checkpoint buffer exists", "error", err) + return common.ErrCheckpointBufferFound(k.Codespace()).Result() + } + + checkpointObj, err := k.GetCheckpointByNumber(ctx, msg.HeaderIndex) + if err != nil { + logger.Error("Unable to get checkpoint from db", "error", err) + return common.ErrNoCheckpointFound(k.Codespace()).Result() + } + + if checkpointObj.EndBlock == msg.EndBlock && checkpointObj.StartBlock == msg.StartBlock && bytes.Equal(checkpointObj.RootHash.Bytes(), msg.RootHash.Bytes()) && bytes.Equal(checkpointObj.Proposer.Bytes(), msg.Proposer.Bytes()) { + logger.Error("Same Checkpoint in DB") + return common.ErrCheckpointAlreadyExists(k.Codespace()).Result() + } + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + types.EventTypeCheckpointAdjust, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(types.AttributeKeyHeaderIndex, strconv.FormatUint(msg.HeaderIndex, 10)), + sdk.NewAttribute(types.AttributeKeyStartBlock, strconv.FormatUint(msg.StartBlock, 10)), + sdk.NewAttribute(types.AttributeKeyEndBlock, strconv.FormatUint(msg.EndBlock, 10)), + sdk.NewAttribute(types.AttributeKeyProposer, msg.Proposer.String()), + sdk.NewAttribute(types.AttributeKeyRootHash, msg.RootHash.String()), + ), + }) + + return sdk.Result{ + Events: ctx.EventManager().Events(), + } +} + // handleMsgCheckpoint Validates checkpoint transaction func handleMsgCheckpoint(ctx sdk.Context, msg types.MsgCheckpoint, k Keeper, contractCaller helper.IContractCaller) sdk.Result { logger := k.Logger(ctx) diff --git a/checkpoint/handler_test.go b/checkpoint/handler_test.go index 689eb024..63b7898c 100644 --- a/checkpoint/handler_test.go +++ b/checkpoint/handler_test.go @@ -149,6 +149,58 @@ func (suite *HandlerTestSuite) TestHandleMsgCheckpoint() { }) } +func (suite *HandlerTestSuite) TestHandleMsgCheckpointAdjustCheckpointBuffer() { + t, app, ctx := suite.T(), suite.app, suite.ctx + keeper := app.CheckpointKeeper + + checkpoint := hmTypes.Checkpoint{ + Proposer: hmTypes.HexToHeimdallAddress("123"), + StartBlock: 0, + EndBlock: 256, + RootHash: hmTypes.HexToHeimdallHash("123"), + BorChainID: "testchainid", + TimeStamp: 1, + } + keeper.SetCheckpointBuffer(ctx, checkpoint) + + checkpointAdjust := types.MsgCheckpointAdjust{ + HeaderIndex: 1, + Proposer: hmTypes.HexToHeimdallAddress("456"), + StartBlock: 0, + EndBlock: 512, + RootHash: hmTypes.HexToHeimdallHash("456"), + } + + result := suite.handler(ctx, checkpointAdjust) + require.False(t, result.IsOK()) +} + +func (suite *HandlerTestSuite) TestHandleMsgCheckpointAdjustSameCheckpointAsMsg() { + t, app, ctx := suite.T(), suite.app, suite.ctx + keeper := app.CheckpointKeeper + + checkpoint := hmTypes.Checkpoint{ + Proposer: hmTypes.HexToHeimdallAddress("123"), + StartBlock: 0, + EndBlock: 256, + RootHash: hmTypes.HexToHeimdallHash("123"), + BorChainID: "testchainid", + TimeStamp: 1, + } + keeper.AddCheckpoint(ctx, 1, checkpoint) + + checkpointAdjust := types.MsgCheckpointAdjust{ + HeaderIndex: 1, + Proposer: hmTypes.HexToHeimdallAddress("123"), + StartBlock: 0, + EndBlock: 256, + RootHash: hmTypes.HexToHeimdallHash("123"), + } + + result := suite.handler(ctx, checkpointAdjust) + require.False(t, result.IsOK()) +} + func (suite *HandlerTestSuite) TestHandleMsgCheckpointAfterBufferTimeOut() { t, app, ctx := suite.T(), suite.app, suite.ctx keeper := app.CheckpointKeeper diff --git a/checkpoint/side_handler.go b/checkpoint/side_handler.go index 8f95d13d..fb227363 100644 --- a/checkpoint/side_handler.go +++ b/checkpoint/side_handler.go @@ -20,6 +20,8 @@ func NewSideTxHandler(k Keeper, contractCaller helper.IContractCaller) hmTypes.S ctx = ctx.WithEventManager(sdk.NewEventManager()) switch msg := msg.(type) { + case types.MsgCheckpointAdjust: + return SideHandleMsgCheckpointAdjust(ctx, k, msg, contractCaller) case types.MsgCheckpoint: return SideHandleMsgCheckpoint(ctx, k, msg, contractCaller) case types.MsgCheckpointAck: @@ -32,6 +34,50 @@ func NewSideTxHandler(k Keeper, contractCaller helper.IContractCaller) hmTypes.S } } +// SideHandleMsgCheckpointAdjust handles MsgCheckpointAdjust message for external call +func SideHandleMsgCheckpointAdjust(ctx sdk.Context, k Keeper, msg types.MsgCheckpointAdjust, contractCaller helper.IContractCaller) (result abci.ResponseDeliverSideTx) { + logger := k.Logger(ctx) + chainParams := k.ck.GetParams(ctx).ChainParams + params := k.GetParams(ctx) + + checkpointBuffer, err := k.GetCheckpointFromBuffer(ctx) + if checkpointBuffer != nil { + logger.Error("checkpoint buffer", "error", err) + return common.ErrorSideTx(k.Codespace(), common.CodeCheckpointBuffer) + } + + checkpointObj, err := k.GetCheckpointByNumber(ctx, msg.HeaderIndex) + if err != nil { + logger.Error("Unable to get checkpoint from db", "error", err) + return common.ErrorSideTx(k.Codespace(), common.CodeNoCheckpoint) + } + + rootChainInstance, err := contractCaller.GetRootChainInstance(chainParams.RootChainAddress.EthAddress()) + if err != nil { + logger.Error("Unable to fetch rootchain contract instance", "error", err) + return common.ErrorSideTx(k.Codespace(), common.CodeOldCheckpoint) + } + + root, start, end, _, proposer, err := contractCaller.GetHeaderInfo(msg.HeaderIndex, rootChainInstance, params.ChildBlockInterval) + if err != nil { + logger.Error("Unable to fetch checkpoint from rootchain", "error", err, "checkpointNumber", msg.HeaderIndex) + return common.ErrorSideTx(k.Codespace(), common.CodeNoCheckpoint) + } + + if checkpointObj.EndBlock == end && checkpointObj.StartBlock == start && bytes.Equal(checkpointObj.RootHash.Bytes(), root.Bytes()) && bytes.Equal(checkpointObj.Proposer.Bytes(), proposer.Bytes()) { + logger.Error("Same Checkpoint in DB") + return common.ErrorSideTx(k.Codespace(), common.CodeCheckpointAlreadyExists) + } + + if msg.EndBlock != end || msg.StartBlock != start || !bytes.Equal(msg.RootHash.Bytes(), root.Bytes()) || !bytes.Equal(msg.Proposer.Bytes(), proposer.Bytes()) { + logger.Error("Checkpoint on Rootchain is not same as msg") + return common.ErrorSideTx(k.Codespace(), common.CodeCheckpointAlreadyExists) + } + + result.Result = abci.SideTxResultType_Yes + return +} + // SideHandleMsgCheckpoint handles MsgCheckpoint message for external call func SideHandleMsgCheckpoint(ctx sdk.Context, k Keeper, msg types.MsgCheckpoint, contractCaller helper.IContractCaller) (result abci.ResponseDeliverSideTx) { // get params @@ -114,6 +160,8 @@ func NewPostTxHandler(k Keeper, contractCaller helper.IContractCaller) hmTypes.P ctx = ctx.WithEventManager(sdk.NewEventManager()) switch msg := msg.(type) { + case types.MsgCheckpointAdjust: + return PostHandleMsgCheckpointAdjust(ctx, k, msg, sideTxResult, contractCaller) case types.MsgCheckpoint: return PostHandleMsgCheckpoint(ctx, k, msg, sideTxResult) case types.MsgCheckpointAck: @@ -124,6 +172,72 @@ func NewPostTxHandler(k Keeper, contractCaller helper.IContractCaller) hmTypes.P } } +// PostHandleMsgCheckpointAdjust handles msg checkpoint adjust +func PostHandleMsgCheckpointAdjust(ctx sdk.Context, k Keeper, msg types.MsgCheckpointAdjust, sideTxResult abci.SideTxResultType, contractCaller helper.IContractCaller) sdk.Result { + logger := k.Logger(ctx) + + // Skip handler if checkpoint-adjust is not approved + if sideTxResult != abci.SideTxResultType_Yes { + logger.Debug("Skipping new checkpoint-adjust since side-tx didn't get yes votes", "checkpointNumber", msg.HeaderIndex) + return common.ErrBadBlockDetails(k.Codespace()).Result() + } + + checkpointBuffer, err := k.GetCheckpointFromBuffer(ctx) + if checkpointBuffer != nil { + logger.Error("checkpoint buffer exists", "error", err) + return common.ErrCheckpointBufferFound(k.Codespace()).Result() + } + + checkpointObj, err := k.GetCheckpointByNumber(ctx, msg.HeaderIndex) + if err != nil { + logger.Error("Unable to get checkpoint from db", "error", err) + return common.ErrNoCheckpointFound(k.Codespace()).Result() + } + + if checkpointObj.EndBlock == msg.EndBlock && checkpointObj.StartBlock == msg.StartBlock && bytes.Equal(checkpointObj.RootHash.Bytes(), msg.RootHash.Bytes()) && bytes.Equal(checkpointObj.Proposer.Bytes(), msg.Proposer.Bytes()) { + logger.Error("Same Checkpoint in DB") + return common.ErrCheckpointAlreadyExists(k.Codespace()).Result() + } + + logger.Info("Previous checkpoint details: EndBlock -", checkpointObj.EndBlock, ", RootHash -", msg.RootHash, " Proposer -", checkpointObj.Proposer) + + checkpointObj.EndBlock = msg.EndBlock + checkpointObj.RootHash = hmTypes.BytesToHeimdallHash(msg.RootHash.Bytes()) + checkpointObj.Proposer = msg.Proposer + + logger.Info("New checkpoint details: EndBlock -", checkpointObj.EndBlock, ", RootHash -", msg.RootHash, " Proposer -", checkpointObj.Proposer) + + // + // Update checkpoint state + // + + // Add checkpoint to store + if err := k.AddCheckpoint(ctx, msg.HeaderIndex, checkpointObj); err != nil { + logger.Error("Error while adding checkpoint into store", "checkpointNumber", msg.HeaderIndex) + return sdk.ErrInternal("Failed to add checkpoint into store").Result() + } + logger.Debug("Checkpoint updated to store", "checkpointNumber", msg.HeaderIndex) + + // Emit event for checkpoints + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + types.EventTypeCheckpointAck, + sdk.NewAttribute(sdk.AttributeKeyAction, msg.Type()), // action + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), // module name + sdk.NewAttribute(hmTypes.AttributeKeySideTxResult, sideTxResult.String()), // result + sdk.NewAttribute(types.AttributeKeyHeaderIndex, strconv.FormatUint(msg.HeaderIndex, 10)), + sdk.NewAttribute(types.AttributeKeyStartBlock, strconv.FormatUint(msg.StartBlock, 10)), + sdk.NewAttribute(types.AttributeKeyEndBlock, strconv.FormatUint(msg.EndBlock, 10)), + sdk.NewAttribute(types.AttributeKeyProposer, msg.Proposer.String()), + sdk.NewAttribute(types.AttributeKeyRootHash, msg.RootHash.String()), + ), + }) + + return sdk.Result{ + Events: ctx.EventManager().Events(), + } +} + // PostHandleMsgCheckpoint handles msg checkpoint func PostHandleMsgCheckpoint(ctx sdk.Context, k Keeper, msg types.MsgCheckpoint, sideTxResult abci.SideTxResultType) sdk.Result { logger := k.Logger(ctx) diff --git a/checkpoint/side_handler_test.go b/checkpoint/side_handler_test.go index b6490fcf..9f8bc0bc 100644 --- a/checkpoint/side_handler_test.go +++ b/checkpoint/side_handler_test.go @@ -7,6 +7,7 @@ import ( "time" sdk "github.com/cosmos/cosmos-sdk/types" + borCommon "github.com/maticnetwork/bor/common" "github.com/maticnetwork/heimdall/app" cmTypes "github.com/maticnetwork/heimdall/chainmanager/types" "github.com/maticnetwork/heimdall/checkpoint" @@ -65,6 +66,97 @@ func (suite *SideHandlerTestSuite) TestSideHandler() { } // test handler for message +func (suite *HandlerTestSuite) TestHandleMsgCheckpointAdjustSuccess() { + t, app, ctx := suite.T(), suite.app, suite.ctx + keeper := app.CheckpointKeeper + + checkpoint := hmTypes.Checkpoint{ + Proposer: hmTypes.HexToHeimdallAddress("123"), + StartBlock: 0, + EndBlock: 256, + RootHash: hmTypes.HexToHeimdallHash("123"), + BorChainID: "testchainid", + TimeStamp: 1, + } + keeper.AddCheckpoint(ctx, 1, checkpoint) + + checkpointAdjust := types.MsgCheckpointAdjust{ + HeaderIndex: 1, + Proposer: hmTypes.HexToHeimdallAddress("456"), + StartBlock: 0, + EndBlock: 512, + RootHash: hmTypes.HexToHeimdallHash("456"), + } + rootchainInstance := &rootchain.Rootchain{} + suite.contractCaller.On("GetRootChainInstance", mock.Anything).Return(rootchainInstance, nil) + suite.contractCaller.On("GetHeaderInfo", mock.Anything, mock.Anything, mock.Anything).Return(borCommon.HexToHash("456"), uint64(0), uint64(512), uint64(1), hmTypes.HexToHeimdallAddress("456"), nil) + + suite.handler(ctx, checkpointAdjust) + sideResult := suite.sideHandler(ctx, checkpointAdjust) + suite.postHandler(ctx, checkpointAdjust, sideResult.Result) + + responseCheckpoint, _ := keeper.GetCheckpointByNumber(ctx, 1) + require.Equal(t, responseCheckpoint.EndBlock, uint64(512)) + require.Equal(t, responseCheckpoint.Proposer, hmTypes.HexToHeimdallAddress("456")) + require.Equal(t, responseCheckpoint.RootHash, hmTypes.HexToHeimdallHash("456")) +} + +func (suite *HandlerTestSuite) TestHandleMsgCheckpointAdjustSameCheckpointAsRootChain() { + t, app, ctx := suite.T(), suite.app, suite.ctx + keeper := app.CheckpointKeeper + + checkpoint := hmTypes.Checkpoint{ + Proposer: hmTypes.HexToHeimdallAddress("123"), + StartBlock: 0, + EndBlock: 256, + RootHash: hmTypes.HexToHeimdallHash("123"), + BorChainID: "testchainid", + TimeStamp: 1, + } + keeper.AddCheckpoint(ctx, 1, checkpoint) + + checkpointAdjust := types.MsgCheckpointAdjust{ + HeaderIndex: 1, + Proposer: hmTypes.HexToHeimdallAddress("123"), + StartBlock: 0, + EndBlock: 256, + RootHash: hmTypes.HexToHeimdallHash("456"), + } + rootchainInstance := &rootchain.Rootchain{} + suite.contractCaller.On("GetRootChainInstance", mock.Anything).Return(rootchainInstance, nil) + suite.contractCaller.On("GetHeaderInfo", mock.Anything, mock.Anything, mock.Anything).Return(borCommon.HexToHash("123"), uint64(0), uint64(256), uint64(1), hmTypes.HexToHeimdallAddress("123"), nil) + + suite.handler(ctx, checkpointAdjust) + sideResult := suite.sideHandler(ctx, checkpointAdjust) + require.Equal(t, sideResult.Code, uint32(0x5e9)) +} + +func (suite *HandlerTestSuite) TestHandleMsgCheckpointAdjustSameCheckpointAsMsgSideHandler() { + t, app, ctx := suite.T(), suite.app, suite.ctx + keeper := app.CheckpointKeeper + + checkpoint := hmTypes.Checkpoint{ + Proposer: hmTypes.HexToHeimdallAddress("123"), + StartBlock: 0, + EndBlock: 256, + RootHash: hmTypes.HexToHeimdallHash("123"), + BorChainID: "testchainid", + TimeStamp: 1, + } + keeper.AddCheckpoint(ctx, 1, checkpoint) + + checkpointAdjust := types.MsgCheckpointAdjust{ + HeaderIndex: 1, + Proposer: hmTypes.HexToHeimdallAddress("123"), + StartBlock: 0, + EndBlock: 256, + RootHash: hmTypes.HexToHeimdallHash("123"), + } + + result := suite.sideHandler(ctx, checkpointAdjust) + require.Equal(t, result.Code, uint32(common.CodeCheckpointAlreadyExists)) +} + func (suite *SideHandlerTestSuite) TestSideHandleMsgCheckpoint() { t, app, ctx := suite.T(), suite.app, suite.ctx keeper := app.CheckpointKeeper diff --git a/checkpoint/types/codec.go b/checkpoint/types/codec.go index 30d36aed..e50680c0 100644 --- a/checkpoint/types/codec.go +++ b/checkpoint/types/codec.go @@ -8,6 +8,7 @@ func RegisterCodec(cdc *codec.Codec) { cdc.RegisterConcrete(MsgCheckpoint{}, "checkpoint/MsgCheckpoint", nil) cdc.RegisterConcrete(MsgCheckpointAck{}, "checkpoint/MsgCheckpointACK", nil) cdc.RegisterConcrete(MsgCheckpointNoAck{}, "checkpoint/MsgCheckpointNoACK", nil) + cdc.RegisterConcrete(MsgCheckpointAdjust{}, "checkpoint/MsgCheckpointAdjust", nil) } // ModuleCdc generic sealed codec to be used throughout module diff --git a/checkpoint/types/events.go b/checkpoint/types/events.go index e6de3fc1..f659768a 100644 --- a/checkpoint/types/events.go +++ b/checkpoint/types/events.go @@ -2,9 +2,10 @@ package types // Checkpoint tags var ( - EventTypeCheckpoint = "checkpoint" - EventTypeCheckpointAck = "checkpoint-ack" - EventTypeCheckpointNoAck = "checkpoint-noack" + EventTypeCheckpoint = "checkpoint" + EventTypeCheckpointAdjust = "checkpoint-adjust" + EventTypeCheckpointAck = "checkpoint-ack" + EventTypeCheckpointNoAck = "checkpoint-noack" AttributeKeyProposer = "proposer" AttributeKeyStartBlock = "start-block" diff --git a/checkpoint/types/msg.go b/checkpoint/types/msg.go index 93ac67c5..9f017752 100644 --- a/checkpoint/types/msg.go +++ b/checkpoint/types/msg.go @@ -18,6 +18,77 @@ import ( var _ sdk.Msg = &MsgCheckpoint{} +// MsgCheckpointAdjust represents checkpoint adjust +type MsgCheckpointAdjust struct { + HeaderIndex uint64 `json:"header_index"` + Proposer types.HeimdallAddress `json:"proposer"` + From types.HeimdallAddress `json:"from"` + StartBlock uint64 `json:"start_block"` + EndBlock uint64 `json:"end_block"` + RootHash types.HeimdallHash `json:"root_hash"` +} + +// NewMsgCheckpointAdjust adjust previous checkpoint +func NewMsgCheckpointAdjust( + headerIndex uint64, + startBlock uint64, + endBlock uint64, + proposer types.HeimdallAddress, + from types.HeimdallAddress, + rootHash types.HeimdallHash, +) MsgCheckpointAdjust { + return MsgCheckpointAdjust{ + HeaderIndex: headerIndex, + StartBlock: startBlock, + EndBlock: endBlock, + Proposer: proposer, + From: from, + RootHash: rootHash, + } +} + +func (msg MsgCheckpointAdjust) GetSignBytes() []byte { + b, err := ModuleCdc.MarshalJSON(msg) + if err != nil { + panic(err) + } + return sdk.MustSortJSON(b) +} + +// GetSigners returns address of the signer +func (msg MsgCheckpointAdjust) GetSigners() []sdk.AccAddress { + return []sdk.AccAddress{types.HeimdallAddressToAccAddress(msg.From)} +} + +func (msg MsgCheckpointAdjust) Route() string { + return RouterKey +} + +// Type returns message type +func (msg MsgCheckpointAdjust) Type() string { + return "checkpoint-adjust" +} + +func (msg MsgCheckpointAdjust) ValidateBasic() sdk.Error { + if bytes.Equal(msg.RootHash.Bytes(), helper.ZeroHash.Bytes()) { + return hmCommon.ErrInvalidMsg(hmCommon.DefaultCodespace, "Invalid rootHash %v", msg.RootHash.String()) + } + + if msg.Proposer.Empty() { + return hmCommon.ErrInvalidMsg(hmCommon.DefaultCodespace, "Invalid proposer %v", msg.Proposer.String()) + } + + if msg.StartBlock >= msg.EndBlock || msg.EndBlock == 0 { + return hmCommon.ErrInvalidMsg(hmCommon.DefaultCodespace, "Invalid startBlock %v or/and endBlock %v", msg.StartBlock, msg.EndBlock) + } + return nil +} + +// GetSideSignBytes returns side sign bytes +func (msg MsgCheckpointAdjust) GetSideSignBytes() []byte { + return nil +} + // MsgCheckpoint represents checkpoint type MsgCheckpoint struct { Proposer types.HeimdallAddress `json:"proposer"` diff --git a/common/error.go b/common/error.go index cbeb4f68..7a83a58a 100644 --- a/common/error.go +++ b/common/error.go @@ -30,6 +30,8 @@ const ( CodeOldCheckpoint CodeType = 1509 CodeDisCountinuousCheckpoint CodeType = 1510 CodeNoCheckpointBuffer CodeType = 1511 + CodeCheckpointBuffer CodeType = 1512 + CodeCheckpointAlreadyExists CodeType = 1513 CodeOldValidator CodeType = 2500 CodeNoValidator CodeType = 2501 @@ -125,10 +127,18 @@ func ErrNoCheckpointFound(codespace sdk.CodespaceType) sdk.Error { return newError(codespace, CodeNoCheckpoint, "Checkpoint Not Found") } +func ErrCheckpointAlreadyExists(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeCheckpointAlreadyExists, "Checkpoint Already Exists") +} + func ErrNoCheckpointBufferFound(codespace sdk.CodespaceType) sdk.Error { return newError(codespace, CodeNoCheckpointBuffer, "Checkpoint buffer not found") } +func ErrCheckpointBufferFound(codespace sdk.CodespaceType) sdk.Error { + return newError(codespace, CodeCheckpointBuffer, "Checkpoint buffer found") +} + func ErrInvalidNoACK(codespace sdk.CodespaceType) sdk.Error { return newError(codespace, CodeInvalidNoACK, "Invalid No ACK -- Waiting for last checkpoint ACK") } From fa8d34d0122901daf5c07c274f5e28c023e5467b Mon Sep 17 00:00:00 2001 From: Jaynti Kanani Date: Wed, 6 Oct 2021 21:48:31 +0400 Subject: [PATCH 09/16] fix: testcases for checkpoint side handler (#731) --- checkpoint/side_handler_test.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/checkpoint/side_handler_test.go b/checkpoint/side_handler_test.go index 9f8bc0bc..ffc2b9e4 100644 --- a/checkpoint/side_handler_test.go +++ b/checkpoint/side_handler_test.go @@ -128,10 +128,10 @@ func (suite *HandlerTestSuite) TestHandleMsgCheckpointAdjustSameCheckpointAsRoot suite.handler(ctx, checkpointAdjust) sideResult := suite.sideHandler(ctx, checkpointAdjust) - require.Equal(t, sideResult.Code, uint32(0x5e9)) + require.Equal(t, sideResult.Code, uint32(common.CodeCheckpointAlreadyExists)) } -func (suite *HandlerTestSuite) TestHandleMsgCheckpointAdjustSameCheckpointAsMsgSideHandler() { +func (suite *HandlerTestSuite) TestHandleMsgCheckpointAdjustNotSameCheckpointAsRootChain() { t, app, ctx := suite.T(), suite.app, suite.ctx keeper := app.CheckpointKeeper @@ -153,6 +153,10 @@ func (suite *HandlerTestSuite) TestHandleMsgCheckpointAdjustSameCheckpointAsMsgS RootHash: hmTypes.HexToHeimdallHash("123"), } + rootchainInstance := &rootchain.Rootchain{} + suite.contractCaller.On("GetRootChainInstance", mock.Anything).Return(rootchainInstance, nil) + suite.contractCaller.On("GetHeaderInfo", mock.Anything, mock.Anything, mock.Anything).Return(borCommon.HexToHash("222"), uint64(0), uint64(256), uint64(1), hmTypes.HexToHeimdallAddress("123"), nil) + result := suite.sideHandler(ctx, checkpointAdjust) require.Equal(t, result.Code, uint32(common.CodeCheckpointAlreadyExists)) } From 1cb873731ea9213556175204aaf4f134c491bd55 Mon Sep 17 00:00:00 2001 From: Krishna Upadhyaya Date: Wed, 27 Oct 2021 19:30:23 +0530 Subject: [PATCH 10/16] fix: Use default gas price in case of invalid value (#733) --- helper/tx.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/helper/tx.go b/helper/tx.go index 4c800769..af05da9f 100644 --- a/helper/tx.go +++ b/helper/tx.go @@ -43,6 +43,10 @@ func GenerateAuthObj(client *ethclient.Client, address common.Address, data []by } mainChainMaxGasPrice := GetConfig().MainchainMaxGasPrice + // Check if configured or not, Use default in case of invalid value + if mainChainMaxGasPrice <= 0 { + mainChainMaxGasPrice = DefaultMainchainMaxGasPrice + } if gasprice.Cmp(big.NewInt(mainChainMaxGasPrice)) == 1 { Logger.Error("Gas price is more than max gas price", "gasprice", gasprice) err = fmt.Errorf("gas price is more than max_gas_price, gasprice = %v, maxGasPrice = %d", gasprice, mainChainMaxGasPrice) From 7d03bfc52ad6e5bca8fed7e39d06c19ecc80ced1 Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 10 Jan 2022 17:55:43 +0800 Subject: [PATCH 11/16] fix: msg broadcast delay && checkpointSyncACk msg broadcast --- bridge/setu/broadcaster/broadcaster.go | 11 ++++++++ bridge/setu/processor/checkpointsync.go | 32 +++++++++++++--------- bridge/setu/util/common.go | 35 ++++++++++++++++--------- 3 files changed, 52 insertions(+), 26 deletions(-) diff --git a/bridge/setu/broadcaster/broadcaster.go b/bridge/setu/broadcaster/broadcaster.go index 377e1312..d2c06d81 100644 --- a/bridge/setu/broadcaster/broadcaster.go +++ b/bridge/setu/broadcaster/broadcaster.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "sync" + "time" "github.com/cosmos/cosmos-sdk/client" cliContext "github.com/cosmos/cosmos-sdk/client/context" @@ -56,6 +57,16 @@ func NewTxBroadcaster(cdc *codec.Codec) *TxBroadcaster { return &txBroadcaster } +func (tb *TxBroadcaster) BroadcastToHeimdallWithDelay(msg sdk.Msg, delay time.Duration) error { + eta := time.Now().Add(delay) + timeAfterTrigger := time.After(delay) + tb.logger.Info("Tx sent on heimdall ", "msg", msg.Type(), "currentTime", time.Now(), "delayTime", eta) + select { + case <-timeAfterTrigger: + return tb.BroadcastToHeimdall(msg) + } +} + // BroadcastToHeimdall broadcast to heimdall func (tb *TxBroadcaster) BroadcastToHeimdall(msg sdk.Msg) error { tb.heimdallMutex.Lock() diff --git a/bridge/setu/processor/checkpointsync.go b/bridge/setu/processor/checkpointsync.go index 3ed207fe..01b82d36 100644 --- a/bridge/setu/processor/checkpointsync.go +++ b/bridge/setu/processor/checkpointsync.go @@ -61,13 +61,15 @@ func (cp *CheckpointProcessor) handleCheckpointSync() { msg := checkpointTypes.NewMsgCheckpointSync(hmTypes.BytesToHeimdallAddress(helper.GetAddress()), proposer, nextCheckpointNumber, start, end, rootChain) // return broadcast to heimdall - if err := cp.txBroadcaster.BroadcastToHeimdall(msg); err != nil { - cp.Logger.Error("Error while broadcasting checkpoint-sync to heimdall", - "root", rootChain, "number", nextCheckpointNumber, "start", start, "end", end, "error", err) - continue + if isCurrentValidator, delay := util.CalculateTaskDelay(cp.cliCtx); isCurrentValidator { + if err := cp.txBroadcaster.BroadcastToHeimdallWithDelay(msg, delay); err != nil { + cp.Logger.Error("Error while broadcasting checkpoint-sync to heimdall", + "root", rootChain, "number", nextCheckpointNumber, "start", start, "end", end, "error", err) + continue + } + cp.Logger.Info("checkpoint sync transaction sent successfully", + "root", rootChain, "number", nextCheckpointNumber, "start", start, "end", end) } - cp.Logger.Info("checkpoint sync transaction sent successfully", - "root", rootChain, "number", nextCheckpointNumber, "start", start, "end", end) } } } @@ -183,13 +185,17 @@ func (cp *CheckpointProcessor) sendCheckpointSyncAckToHeimdall(eventName string, ) // fetch checkpoint sync buffer bufferedCheckpoint, err := util.GetBufferedCheckpointSync(cp.cliCtx, checkpointChain) - if err == nil { - bufferedTime := time.Unix(int64(bufferedCheckpoint.TimeStamp), 0) - currentTime := time.Now().UTC() - if currentTime.Sub(bufferedTime).Seconds() > checkpointParams.CheckpointBufferTime.Seconds()/5 { - cp.Logger.Debug("checkpoint sync buffer has expired, ignore this ack") - return nil - } + + if err != nil { + cp.Logger.Debug("checkpoint sync buffer has been cleared, this ack already submitted.") + return nil + } + + bufferedTime := time.Unix(int64(bufferedCheckpoint.TimeStamp), 0) + currentTime := time.Now().UTC() + if currentTime.Sub(bufferedTime).Seconds() > checkpointParams.CheckpointBufferTime.Seconds()/5 { + cp.Logger.Debug("checkpoint sync buffer has expired, ignore this ack") + return nil } // create msg checkpoint ack message diff --git a/bridge/setu/util/common.go b/bridge/setu/util/common.go index 7376fc9c..c5567838 100644 --- a/bridge/setu/util/common.go +++ b/bridge/setu/util/common.go @@ -143,34 +143,43 @@ func IsInProposerList(cliCtx cliContext.CLIContext, count uint64) (bool, error) // CalculateTaskDelay calculates delay required for current validator to propose the tx // It solves for multiple validators sending same transaction. func CalculateTaskDelay(cliCtx cliContext.CLIContext) (bool, time.Duration) { - // calculate validator position - valPosition := 0 - isCurrentValidator := false response, err := helper.FetchFromAPI(cliCtx, helper.GetHeimdallServerEndpoint(CurrentValidatorSetURL)) if err != nil { logger.Error("Unable to send request for current validatorset", "url", CurrentValidatorSetURL, "error", err) - return isCurrentValidator, 0 + return false, 0 } // unmarshall data from buffer var validatorSet hmtypes.ValidatorSet err = json.Unmarshal(response.Result, &validatorSet) if err != nil { logger.Error("Error unmarshalling current validatorset data ", "error", err) - return isCurrentValidator, 0 + return false, 0 } logger.Info("Fetched current validatorset list", "currentValidatorcount", len(validatorSet.Validators)) - for i, validator := range validatorSet.Validators { - if bytes.Equal(validator.Signer.Bytes(), helper.GetAddress()) { - valPosition = i + 1 - isCurrentValidator = true - break - } + + validators := validatorSet.Validators + proposer := validatorSet.GetProposer().Signer.Bytes() + localAddress := helper.GetAddress() + + proposerIndex, _ := validatorSet.GetByAddress(proposer) + localIndex, _ := validatorSet.GetByAddress(localAddress) + + if localIndex < 0 { + return false, 0 } + // temp index + tempIndex := localIndex + if tempIndex < proposerIndex { + tempIndex = tempIndex + len(validators) + } + + delay := tempIndex - proposerIndex + 1 + // calculate delay - taskDelay := time.Duration(valPosition) * TaskDelayBetweenEachVal - return isCurrentValidator, taskDelay + taskDelay := time.Duration(delay) * TaskDelayBetweenEachVal + return true, taskDelay } // IsCurrentProposer checks if we are current proposer From 23b64f5134fdf96732c4796f8905dd1ed9d946bf Mon Sep 17 00:00:00 2001 From: halibobo1205 Date: Mon, 10 Jan 2022 18:40:15 +0800 Subject: [PATCH 12/16] fix: change CalculateTaskDelay URL --- bridge/setu/util/common.go | 54 +++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/bridge/setu/util/common.go b/bridge/setu/util/common.go index c5567838..d387cd7f 100644 --- a/bridge/setu/util/common.go +++ b/bridge/setu/util/common.go @@ -63,7 +63,8 @@ const ( TaskDelayBetweenEachVal = 24 * time.Second RetryTaskDelay = 12 * time.Second - BridgeDBFlag = "bridge-db" + BridgeDBFlag = "bridge-db" + ProposersURLSizeLimit = 100 ) var logger log.Logger @@ -143,43 +144,36 @@ func IsInProposerList(cliCtx cliContext.CLIContext, count uint64) (bool, error) // CalculateTaskDelay calculates delay required for current validator to propose the tx // It solves for multiple validators sending same transaction. func CalculateTaskDelay(cliCtx cliContext.CLIContext) (bool, time.Duration) { - response, err := helper.FetchFromAPI(cliCtx, helper.GetHeimdallServerEndpoint(CurrentValidatorSetURL)) - if err != nil { - logger.Error("Unable to send request for current validatorset", "url", CurrentValidatorSetURL, "error", err) - return false, 0 - } - // unmarshall data from buffer - var validatorSet hmtypes.ValidatorSet - err = json.Unmarshal(response.Result, &validatorSet) + // calculate validator position + valPosition := 0 + isCurrentValidator := false + + proposersURL := fmt.Sprintf(ProposersURL, ProposersURLSizeLimit) + proposersResponse, err := helper.FetchFromAPI(cliCtx, helper.GetHeimdallServerEndpoint(proposersURL)) if err != nil { - logger.Error("Error unmarshalling current validatorset data ", "error", err) - return false, 0 + logger.Error("Unable to send request for proposers ", "url", proposersURL, "error", err) + return isCurrentValidator, 0 } - logger.Info("Fetched current validatorset list", "currentValidatorcount", len(validatorSet.Validators)) - - validators := validatorSet.Validators - proposer := validatorSet.GetProposer().Signer.Bytes() - localAddress := helper.GetAddress() - - proposerIndex, _ := validatorSet.GetByAddress(proposer) - localIndex, _ := validatorSet.GetByAddress(localAddress) - - if localIndex < 0 { - return false, 0 + var proposers []hmtypes.Validator + err = json.Unmarshal(proposersResponse.Result, &proposers) + if err != nil { + logger.Error("Error unmarshalling proposers data ", "error", err) + return isCurrentValidator, 0 } - // temp index - tempIndex := localIndex - if tempIndex < proposerIndex { - tempIndex = tempIndex + len(validators) + logger.Info("Fetched proposers ", "currentValidatorsCount", len(proposers)) + for i, validator := range proposers { + if bytes.Equal(validator.Signer.Bytes(), helper.GetAddress()) { + valPosition = i + 1 + isCurrentValidator = true + break + } } - delay := tempIndex - proposerIndex + 1 - // calculate delay - taskDelay := time.Duration(delay) * TaskDelayBetweenEachVal - return true, taskDelay + taskDelay := time.Duration(valPosition) * TaskDelayBetweenEachVal + return isCurrentValidator, taskDelay } // IsCurrentProposer checks if we are current proposer From 8d26c02411f65d21a1ffe40913c34f15b8854704 Mon Sep 17 00:00:00 2001 From: hanzhenjiang Date: Tue, 11 Jan 2022 16:25:06 +0800 Subject: [PATCH 13/16] delay offset and del no use config --- bridge/setu/listener/tron.go | 10 +++++----- bridge/setu/util/common.go | 10 ++++++++-- helper/config.go | 5 ++--- helper/util.go | 2 +- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/bridge/setu/listener/tron.go b/bridge/setu/listener/tron.go index cb8d3bd2..f760590c 100644 --- a/bridge/setu/listener/tron.go +++ b/bridge/setu/listener/tron.go @@ -214,7 +214,7 @@ func (tl *TronListener) queryAndBroadcastEvents(chainManagerParams *chainmanager // topup has to be processed first before validator join. so adding delay. delay := util.TaskDelayBetweenEachVal tl.sendTaskWithDelay("sendValidatorJoinToHeimdall", selectedEvent.Name, logBytes, delay) - } else if isCurrentValidator, delay := util.CalculateTaskDelay(tl.cliCtx); isCurrentValidator { + } else if isCurrentValidator, delay := util.CalculateTaskDelayWithOffset(tl.cliCtx,1); isCurrentValidator { // topup has to be processed first before validator join. so adding delay. delay = delay + util.TaskDelayBetweenEachVal tl.sendTaskWithDelay("sendValidatorJoinToHeimdall", selectedEvent.Name, logBytes, delay) @@ -237,7 +237,7 @@ func (tl *TronListener) queryAndBroadcastEvents(chainManagerParams *chainmanager } if bytes.Equal(event.SignerPubkey, pubkeyBytes) { tl.sendTaskWithDelay("sendSignerChangeToHeimdall", selectedEvent.Name, logBytes, 0) - } else if isCurrentValidator, delay := util.CalculateTaskDelay(tl.cliCtx); isCurrentValidator { + } else if isCurrentValidator, delay := util.CalculateTaskDelayWithOffset(tl.cliCtx,1); isCurrentValidator { tl.sendTaskWithDelay("sendSignerChangeToHeimdall", selectedEvent.Name, logBytes, delay) } @@ -248,7 +248,7 @@ func (tl *TronListener) queryAndBroadcastEvents(chainManagerParams *chainmanager } if util.IsEventSender(tl.cliCtx, event.ValidatorId.Uint64()) { tl.sendTaskWithDelay("sendUnstakeInitToHeimdall", selectedEvent.Name, logBytes, 0) - } else if isCurrentValidator, delay := util.CalculateTaskDelay(tl.cliCtx); isCurrentValidator { + } else if isCurrentValidator, delay := util.CalculateTaskDelayWithOffset(tl.cliCtx,1); isCurrentValidator { tl.sendTaskWithDelay("sendUnstakeInitToHeimdall", selectedEvent.Name, logBytes, delay) } @@ -264,7 +264,7 @@ func (tl *TronListener) queryAndBroadcastEvents(chainManagerParams *chainmanager } if bytes.Equal(event.User.Bytes(), helper.GetAddress()) { tl.sendTaskWithDelay("sendTopUpFeeToHeimdall", selectedEvent.Name, logBytes, 0) - } else if isCurrentValidator, delay := util.CalculateTaskDelay(tl.cliCtx); isCurrentValidator { + } else if isCurrentValidator, delay := util.CalculateTaskDelayWithOffset(tl.cliCtx,1); isCurrentValidator { tl.sendTaskWithDelay("sendTopUpFeeToHeimdall", selectedEvent.Name, logBytes, delay) } @@ -280,7 +280,7 @@ func (tl *TronListener) queryAndBroadcastEvents(chainManagerParams *chainmanager } if util.IsEventSender(tl.cliCtx, event.ValidatorId.Uint64()) { tl.sendTaskWithDelay("sendUnjailToHeimdall", selectedEvent.Name, logBytes, 0) - } else if isCurrentValidator, delay := util.CalculateTaskDelay(tl.cliCtx); isCurrentValidator { + } else if isCurrentValidator, delay := util.CalculateTaskDelayWithOffset(tl.cliCtx,1); isCurrentValidator { tl.sendTaskWithDelay("sendUnjailToHeimdall", selectedEvent.Name, logBytes, delay) } diff --git a/bridge/setu/util/common.go b/bridge/setu/util/common.go index 7376fc9c..80c77e28 100644 --- a/bridge/setu/util/common.go +++ b/bridge/setu/util/common.go @@ -140,9 +140,15 @@ func IsInProposerList(cliCtx cliContext.CLIContext, count uint64) (bool, error) return false, nil } +//default offset 0 +func CalculateTaskDelay(cliCtx cliContext.CLIContext) (bool, time.Duration){ + return CalculateTaskDelayWithOffset(cliCtx,0) +} + // CalculateTaskDelay calculates delay required for current validator to propose the tx // It solves for multiple validators sending same transaction. -func CalculateTaskDelay(cliCtx cliContext.CLIContext) (bool, time.Duration) { +// with offset +func CalculateTaskDelayWithOffset(cliCtx cliContext.CLIContext, offset int) (bool, time.Duration) { // calculate validator position valPosition := 0 isCurrentValidator := false @@ -162,7 +168,7 @@ func CalculateTaskDelay(cliCtx cliContext.CLIContext) (bool, time.Duration) { logger.Info("Fetched current validatorset list", "currentValidatorcount", len(validatorSet.Validators)) for i, validator := range validatorSet.Validators { if bytes.Equal(validator.Signer.Bytes(), helper.GetAddress()) { - valPosition = i + 1 + valPosition = i + offset isCurrentValidator = true break } diff --git a/helper/config.go b/helper/config.go index 85edde12..b3a144f2 100644 --- a/helper/config.go +++ b/helper/config.go @@ -111,12 +111,11 @@ type Configuration struct { BttcRPCUrl string `mapstructure:"bttc_rpc_url"` // RPC endpoint for bttc chain TendermintRPCUrl string `mapstructure:"tendermint_rpc_url"` // tendemint node url - TronGridURL string `mapstructure:"tron_grid_url"` // tron grid url + TronGridUrl string `mapstructure:"tron_grid_url"` // tron grid url AmqpURL string `mapstructure:"amqp_url"` // amqp url DeliveryServerURL string `mapstructure:"delivery_rest_server"` // delivery server url // tron - TronGridUrl string `mapstructure:"tron_grid_url"` // tron server url TronGridApiKey string `mapstructure:"tron_grid_api_key"` // tron api key MainchainGasLimit uint64 `mapstructure:"main_chain_gas_limit"` // gas limit to mainchain transaction. eg....submit checkpoint. @@ -266,7 +265,7 @@ func GetDefaultHeimdallConfig() Configuration { BscRPCUrl: DefaultBscRPCUrl, TendermintRPCUrl: DefaultTendermintNodeURL, - TronGridURL: DefaultTronGridUrl, + TronGridUrl: DefaultTronGridUrl, AmqpURL: DefaultAmqpURL, DeliveryServerURL: DefaultDeliveryServerURL, diff --git a/helper/util.go b/helper/util.go index 4869e102..839f61c5 100644 --- a/helper/util.go +++ b/helper/util.go @@ -850,7 +850,7 @@ func GetHeimdallServerEndpoint(endpoint string) string { // GetTronGridEndpoint returns tron server endpoint func GetTronGridEndpoint(endpoint string) string { - u, _ := url.Parse(GetConfig().TronGridURL) + u, _ := url.Parse(GetConfig().TronGridUrl) u.Path = path.Join(u.Path, endpoint) return u.String() } From 1c7347962371da988a369e33781f98305c240887 Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Fri, 4 Mar 2022 16:30:44 +0800 Subject: [PATCH 14/16] chg: small improvement !minor --- README.md | 2 +- bridge/setu/processor/staking.go | 2 +- helper/config.go | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5934921f..617c2df6 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Make sure your have go1.11+ already installed ### Install ```bash $ make install -``` +``` ### Run-delivery ```bash diff --git a/bridge/setu/processor/staking.go b/bridge/setu/processor/staking.go index a959561c..d3bc4da1 100644 --- a/bridge/setu/processor/staking.go +++ b/bridge/setu/processor/staking.go @@ -24,7 +24,7 @@ import ( ) const ( - defaultDelayDuration time.Duration = 10 * time.Second + defaultDelayDuration = 10 * time.Second ) // StakingProcessor - process staking related events diff --git a/helper/config.go b/helper/config.go index d8c23b12..7402000e 100644 --- a/helper/config.go +++ b/helper/config.go @@ -73,7 +73,6 @@ const ( DefaultStakingPollInterval = 1 * time.Minute DefaultStartListenBlock = 0 - DefaultMainchainGasLimit = uint64(5000000) DefaultMainchainMaxGasPrice = 400000000000 // 400 Gwei DefaultTronFeeLimit = uint64(1000000000) From 858d9d58dfd153dab41a97e6eb57c1121b0cbec9 Mon Sep 17 00:00:00 2001 From: bladehan1 Date: Mon, 7 Mar 2022 11:24:06 +0800 Subject: [PATCH 15/16] chg: validator nonce strict verification --- staking/handler.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/staking/handler.go b/staking/handler.go index 747df8c2..81961c3f 100644 --- a/staking/handler.go +++ b/staking/handler.go @@ -136,7 +136,7 @@ func HandleMsgStakeUpdate(ctx sdk.Context, msg types.MsgStakeUpdate, k Keeper, c return hmCommon.ErrNoValidator(k.Codespace()).Result() } - if msg.Nonce <= validator.Nonce { + if msg.Nonce != validator.Nonce+1 { k.Logger(ctx).Error("Incorrect validator nonce") return hmCommon.ErrNonce(k.Codespace()).Result() } @@ -201,7 +201,7 @@ func HandleMsgSignerUpdate(ctx sdk.Context, msg types.MsgSignerUpdate, k Keeper, } // check nonce validity - if msg.Nonce <= validator.Nonce { + if msg.Nonce != validator.Nonce+1 { k.Logger(ctx).Error("Incorrect validator nonce") return hmCommon.ErrNonce(k.Codespace()).Result() } @@ -256,7 +256,7 @@ func HandleMsgValidatorExit(ctx sdk.Context, msg types.MsgValidatorExit, k Keepe } // check nonce validity - if msg.Nonce <= validator.Nonce { + if msg.Nonce != validator.Nonce+1 { k.Logger(ctx).Error("Incorrect validator nonce") return hmCommon.ErrNonce(k.Codespace()).Result() } From dba778a9500a4a2ab0cf9a2d2430c4c0db6073ce Mon Sep 17 00:00:00 2001 From: luxueqing Date: Wed, 9 Mar 2022 16:22:54 +0800 Subject: [PATCH 16/16] chg:change default value of CheckpointerPollInterval and TronFeeLimit --- helper/config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helper/config.go b/helper/config.go index b3a144f2..b09d48e0 100644 --- a/helper/config.go +++ b/helper/config.go @@ -63,7 +63,7 @@ const ( NoACKWaitTime = 1800 * time.Second // Time ack service waits to clear buffer and elect new proposer (1800 seconds ~ 30 mins) - DefaultCheckpointerPollInterval = 5 * time.Minute + DefaultCheckpointerPollInterval = 30 * time.Minute DefaultSyncerPollInterval = 1 * time.Minute DefaultBscSyncerPollInterval = 10 * time.Second DefaultTronSyncerPollInterval = 3 * time.Second @@ -74,7 +74,7 @@ const ( DefaultStartListenBlock = 0 DefaultMainchainGasLimit = uint64(5000000) - DefaultTronFeeLimit = uint64(1000000000) + DefaultTronFeeLimit = uint64(200000000) DefaultEthBusyLimitTxs = 1000 DefaultBscBusyLimitTxs = 1000