Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2ed4888
Merge pull request #101 from bttcprotocol/master
bladehan1 Nov 28, 2024
179a063
support tron dynamic checkpoint and add CheckpointPollInterval to che…
sgz13140 Mar 2, 2026
9fefa0e
upgrade dependencies
sgz13140 Mar 3, 2026
1d110f8
enable to set if increase gas price and the ratio when submit checkpo…
sgz13140 Mar 3, 2026
17cacfd
support set bsc start listen block by config file
sgz13140 Mar 3, 2026
65874fb
fix the problem of submitting repeat checkpoint sync tx
sgz13140 Mar 3, 2026
870834a
modify log
sgz13140 Mar 3, 2026
b6e5fb3
add TriggerConstantContractWithRetry
sgz13140 Mar 3, 2026
8259608
modify the checkpoint timeout func when open tron dynamic feature
sgz13140 Mar 4, 2026
953d9b2
Merge pull request #125 from sgz13140/upgrade-dependency
mengcody Mar 6, 2026
4a090f4
Merge pull request #127 from sgz13140/feat/bsc-start-listen-block
mengcody Mar 6, 2026
0904f12
Merge pull request #128 from sgz13140/feat/checkpoint_speedup
mengcody Mar 6, 2026
57f6820
Merge pull request #129 from sgz13140/fix/checkpoint-sync-repeat
mengcody Mar 6, 2026
6a7288f
change attempt value in TriggerConstantContractWithRetry
sgz13140 Mar 6, 2026
71a1822
Merge pull request #130 from sgz13140/tron-rpc-retry
mengcody Mar 6, 2026
20e5c34
change conflix
sgz13140 Mar 6, 2026
3000e5f
Merge pull request #131 from sgz13140/feat/gas-price
mengcody Mar 6, 2026
645aa8b
process CalcCheckpointTimeout when tronMaxLength or pollTime equals 0
sgz13140 Mar 9, 2026
43f6f6b
ignore in handler when CalcCheckpointTimeout returns 0
sgz13140 Mar 9, 2026
61fe071
Merge pull request #133 from sgz13140/feat/checkpoint_speedup
mengcody Mar 10, 2026
e275901
add return
sgz13140 Apr 7, 2026
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
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v1
uses: actions/setup-go@v5
with:
go-version: 1.21
- name: "Build binaries"
Expand All @@ -17,4 +17,4 @@ jobs:
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
with:
file: ./cover.out
file: ./cover.out
6 changes: 3 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v1
uses: actions/setup-go@v5
with:
go-version: 1.17
go-version: 1.21
- name: "Run lint"
uses: golangci/golangci-lint-action@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Validator node for Bittorrent Chain Network. It uses peppermint, customized [Ten

### Install from source

Make sure your have go1.11+ already installed
Make sure your have go1.21+ already installed

### Install
```bash
Expand Down
14 changes: 11 additions & 3 deletions auth/querier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,19 @@ func (suite *QuerierTestSuite) TestQueryParams() {
require.Equal(t, uint64(8), params.TxSizeCostPerByte)

{
// When params are not set, querier should return zero values instead of panicking
happ := app.Setup(true)
ctx := happ.BaseApp.NewContext(true, abci.Header{})
querier := auth.NewQuerier(happ.AccountKeeper)
require.Panics(t, func() {
querier(ctx, path, req)
})
res, err = querier(ctx, path, req)
require.NoError(t, err)
require.NotNil(t, res)

var zeroParams types.Params
err4 := json.Unmarshal(res, &zeroParams)
require.NoError(t, err4)
// Params should be zero values when not initialized
require.Equal(t, uint64(0), zeroParams.MaxMemoCharacters)
require.Equal(t, uint64(0), zeroParams.TxSigLimit)
}
}
2 changes: 1 addition & 1 deletion bridge/setu/broadcaster/broadcaster.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ func (tb *TxBroadcaster) BroadcastToMatic(msg bor.CallMsg) error {
maticClient := helper.GetMaticClient()

// get auth
auth, err := helper.GenerateAuthObj(maticClient, *msg.To, msg.Data)
auth, err := helper.GenerateAuthObj(maticClient, *msg.To, msg.Data, false)

if err != nil {
tb.logger.Error("Error generating auth object", "error", err)
Expand Down
66 changes: 55 additions & 11 deletions bridge/setu/listener/heimdall.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package listener
import (
"context"
"encoding/json"
"fmt"
"math/big"
"strconv"
"sync"
Expand All @@ -16,7 +17,6 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
checkpointTypes "github.com/maticnetwork/heimdall/checkpoint/types"
clerkTypes "github.com/maticnetwork/heimdall/clerk/types"
featureManagerTypes "github.com/maticnetwork/heimdall/featuremanager/types"
slashingTypes "github.com/maticnetwork/heimdall/slashing/types"
stakingTypes "github.com/maticnetwork/heimdall/staking/types"
htype "github.com/maticnetwork/heimdall/types"
Expand Down Expand Up @@ -48,8 +48,17 @@ func (hl *HeimdallListener) Start() error {

// Heimdall pollIntervall = (minimal pollInterval of rootchain and matichain)
pollInterval := helper.GetConfig().EthSyncerPollInterval
if helper.GetConfig().CheckpointerPollInterval < helper.GetConfig().EthSyncerPollInterval {
pollInterval = helper.GetConfig().CheckpointerPollInterval

checkpointPollInterval := helper.GetConfig().CheckpointerPollInterval

// fetch initial checkpoint params (will retry up to 10 times or exit service)
checkpointParams := util.GetCheckpointParamsWithRetry(hl.cliCtx)
if checkpointParams.CheckpointPollInterval > 0 {
checkpointPollInterval = checkpointParams.CheckpointPollInterval
}

if checkpointPollInterval < helper.GetConfig().EthSyncerPollInterval {
pollInterval = checkpointPollInterval
}

hl.Logger.Info("Start polling for events", "pollInterval", pollInterval)
Expand Down Expand Up @@ -104,14 +113,17 @@ func (hl *HeimdallListener) StartPolling(ctx context.Context, pollInterval time.

hl.Logger.Info("Fetching new events between", "fromBlock", fromBlock, "toBlock", toBlock)

// set to avoid deduplicate checkpoint-sync events by (rootChain, number, startBlock, endBlock)
checkpointSyncSet := make(map[string]struct{})

// Querying and processing Begin events
for i := fromBlock; i <= toBlock; i++ {
events, err := helper.GetBeginBlockEvents(hl.httpClient, int64(i))
if err != nil {
hl.Logger.Error("Error fetching begin block events", "error", err)
}
for _, event := range events {
hl.ProcessBlockEvent(sdk.StringifyEvent(event), int64(i))
hl.ProcessBlockEvent(sdk.StringifyEvent(event), int64(i), checkpointSyncSet)
}
}

Expand Down Expand Up @@ -194,11 +206,18 @@ func (hl *HeimdallListener) fetchFromAndToBlock() (uint64, uint64, error) {
return fromBlock, toBlock, err
}
}
maxQueryBlocks := helper.GetConfig().HeimdallMaxQueryBlocks
if maxQueryBlocks == 0 {
maxQueryBlocks = helper.DefaultHeimdallMaxQueryBlocks
}
if maxQueryBlocks != 0 && toBlock-fromBlock > uint64(maxQueryBlocks) {
toBlock = fromBlock + uint64(maxQueryBlocks)
}
return fromBlock, toBlock, err
}

// ProcessBlockEvent - process Blockevents (BeginBlock, EndBlock events) from heimdall.
func (hl *HeimdallListener) ProcessBlockEvent(event sdk.StringEvent, blockHeight int64) {
func (hl *HeimdallListener) ProcessBlockEvent(event sdk.StringEvent, blockHeight int64, checkpointSyncSet map[string]struct{}) {
hl.Logger.Info("Received block event from Heimdall", "eventType", event.Type, "height", blockHeight)
eventBytes, err := json.Marshal(event)
if err != nil {
Expand All @@ -210,6 +229,13 @@ func (hl *HeimdallListener) ProcessBlockEvent(event sdk.StringEvent, blockHeight
case checkpointTypes.EventTypeCheckpoint:
hl.sendBlockTask("sendCheckpointToRootchain", eventBytes, blockHeight)
case checkpointTypes.EventTypeCheckpointSync:
key := hl.getCheckpointSyncKey(event)
if _, exists := checkpointSyncSet[key]; exists {
hl.Logger.Info("CheckpointSync duplicate, skip sending task", "key", key)
return
}

checkpointSyncSet[key] = struct{}{}
hl.sendBlockTask("sendCheckpointSyncToStakeChain", eventBytes, blockHeight)
case slashingTypes.EventTypeSlashLimit:
hl.sendBlockTask("sendTickToHeimdall", eventBytes, blockHeight)
Expand All @@ -228,6 +254,24 @@ func (hl *HeimdallListener) ProcessBlockEvent(event sdk.StringEvent, blockHeight
}
}

func (hl *HeimdallListener) getCheckpointSyncKey(event sdk.StringEvent) string {
var rootChain string
var number, startBlock, endBlock uint64
for _, attr := range event.Attributes {
switch attr.Key {
case checkpointTypes.AttributeKeyRootChain:
rootChain = attr.Value
case checkpointTypes.AttributeKeyHeaderIndex:
number, _ = strconv.ParseUint(attr.Value, 10, 64)
case checkpointTypes.AttributeKeyStartBlock:
startBlock, _ = strconv.ParseUint(attr.Value, 10, 64)
case checkpointTypes.AttributeKeyEndBlock:
endBlock, _ = strconv.ParseUint(attr.Value, 10, 64)
}
}
return fmt.Sprintf("%s_%d_%d_%d", rootChain, number, startBlock, endBlock)
}

func (hl *HeimdallListener) sendBlockTask(taskName string, eventBytes []byte, blockHeight int64) {
// create machinery task
signature := &tasks.Signature{
Expand Down Expand Up @@ -293,12 +337,12 @@ func (hl *HeimdallListener) StartPollingEventRecord(ctx context.Context, pollInt
}

func (hl *HeimdallListener) loadEventRecords(ctx context.Context, pollInterval time.Duration) {
targetFeature, err := util.GetTargetFeatureConfig(hl.cliCtx, featureManagerTypes.DynamicCheckpoint)
if err != nil || !targetFeature.IsOpen {
hl.Logger.Info("Feature not supported... goroutine exists")

return
}
//targetFeature, err := util.GetTargetFeatureConfig(hl.cliCtx, featureManagerTypes.DynamicCheckpoint)
//if err != nil || !targetFeature.IsOpen {
// hl.Logger.Info("Feature not supported... goroutine exists")
//
// return
//}

if atomic.LoadUint32(&hl.stateSyncedInitializationRun) == 1 {
hl.Logger.Info("Last ProcessEventRecords not finished... goroutine exists")
Expand Down
11 changes: 9 additions & 2 deletions bridge/setu/listener/maticchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"time"

"github.com/RichardKnop/machinery/v1/tasks"
"github.com/maticnetwork/heimdall/bridge/setu/util"
"github.com/maticnetwork/heimdall/helper"
)

Expand Down Expand Up @@ -33,9 +34,15 @@ func (ml *MaticChainListener) Start() error {
// start header process
go ml.StartHeaderProcess(headerCtx)

ml.Logger.Info("Start polling for header blocks", "pollInterval", helper.GetConfig().CheckpointerPollInterval)
pollInterval := helper.GetConfig().CheckpointerPollInterval
params := util.GetCheckpointParamsWithRetry(ml.cliCtx)
if params.CheckpointPollInterval > 0 {
pollInterval = params.CheckpointPollInterval
}

ml.Logger.Info("Start polling for header blocks", "pollInterval", pollInterval)

go ml.StartPolling(ctx, helper.GetConfig().CheckpointerPollInterval, true, nil)
go ml.StartPolling(ctx, pollInterval, true, nil)

// subscribed to new head
ml.Logger.Info("Subscribed to new head")
Expand Down
66 changes: 53 additions & 13 deletions bridge/setu/processor/checkpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,23 @@ func (cp *CheckpointProcessor) startPolling(ctx context.Context) {
now := time.Now()
baseTime := time.Unix(0, 0)
// no-ack ticker interval keep same with checkpoint interval
noAckInterval := helper.GetConfig().CheckpointerPollInterval
checkpointPollInterval := helper.GetConfig().CheckpointerPollInterval

// fetch initial checkpoint params (will retry up to 10 times or exit service)
checkpointParams := util.GetCheckpointParamsWithRetry(cp.cliCtx)
if checkpointParams.CheckpointPollInterval > 0 {
checkpointPollInterval = checkpointParams.CheckpointPollInterval
}

// adjust no-ack ticker to tick at the middle of checkpoint interval
firstIntervalForNoAck := noAckInterval - (now.UTC().Sub(baseTime) % noAckInterval) - noAckInterval/2 // nolint: gomnd
firstIntervalForNoAck := checkpointPollInterval - (now.UTC().Sub(baseTime) % checkpointPollInterval) - checkpointPollInterval/2 // nolint: gomnd
if firstIntervalForNoAck <= 0 {
firstIntervalForNoAck += noAckInterval
firstIntervalForNoAck += checkpointPollInterval
}

tickerForNoAck := time.NewTicker(firstIntervalForNoAck)
syncInterval := helper.GetConfig().CheckpointerPollInterval / 2
syncInterval := checkpointPollInterval / 2
noAckInterval := checkpointPollInterval
tickerForSync := time.NewTicker(syncInterval)
// stop ticker when everything done
defer tickerForNoAck.Stop()
Expand Down Expand Up @@ -568,10 +576,10 @@ func (cp *CheckpointProcessor) createAndSendCheckpointToHeimdall(checkpointConte
latestCheckpoint, err := util.GetlastestCheckpoint(cp.cliCtx, rootChain)
// event checkpoint is older than or equal to latest checkpoint
if err == nil && latestCheckpoint != nil && latestCheckpoint.EndBlock+1 < start {
cp.Logger.Debug("Need to resubmit Checkpoint ack first", "start", start, "last_end", latestCheckpoint.EndBlock)
cp.Logger.Info("Need to resubmit Checkpoint ack first", "start", start, "last_end", latestCheckpoint.EndBlock)
err := cp.resubmitCheckpointAck(checkpointContext, rootChain)
if err != nil {
cp.Logger.Info("Error while resubmit checkpoint ack", "root", rootChain, "err", err)
cp.Logger.Error("Error while resubmit checkpoint ack", "root", rootChain, "err", err)
return err
}
return nil
Expand Down Expand Up @@ -840,16 +848,40 @@ func (cp *CheckpointProcessor) checkIfNoAckIsRequired(checkpointContext *Checkpo
currentTime := time.Now().UTC()

timeDiff := currentTime.Sub(checkpointCreationTime)
if timeDiff.Seconds() >= helper.GetConfig().CheckpointerPollInterval.Seconds() && index == 0 {
index = math.Floor(timeDiff.Seconds() / helper.GetConfig().CheckpointerPollInterval.Seconds())

// checkpoint params
checkpointParams := checkpointContext.CheckpointParams

var checkpointPollInterval time.Duration
if checkpointParams.CheckpointPollInterval > 0 {
checkpointPollInterval = checkpointParams.CheckpointPollInterval
} else {
checkpointPollInterval = helper.GetConfig().CheckpointerPollInterval
}

if index == 0 {
var checkpointTimeout time.Duration
isOpen, tronMaxLength, err := cp.getTronDynamicCheckpointProposalWithErr()
if err != nil {
cp.Logger.Error("failed to check if no ack is required. Error while fetching dynamic checkpoint feature", "error", err)
return false, uint64(index)
}
if isOpen {
checkpointTimeout, err = helper.CalcCheckpointTimeout(tronMaxLength, checkpointPollInterval)
if err != nil {
cp.Logger.Error("failed to CalcCheckpointTimeout", "error", err)
return false, uint64(index)
}
} else {
checkpointTimeout = checkpointPollInterval
}

// checkpoint params
checkpointParams := checkpointContext.CheckpointParams
if timeDiff.Seconds() >= checkpointTimeout.Seconds() && index == 0 {
index = math.Floor(timeDiff.Seconds() / checkpointTimeout.Seconds())
}

if index == 0 {
return false, uint64(index)
}

// check if difference between no-ack time and current time
lastNoAck := cp.getLastNoAckTime()
Expand Down Expand Up @@ -991,9 +1023,7 @@ func (cp *CheckpointProcessor) Stop() {
cp.cancelNoACKPolling()
}

//
// utils
//
func (cp *CheckpointProcessor) getCheckpointContext(rootChain string) (*CheckpointContext, error) {
// fetch chain params for different root chains
chainmanagerParams, err := util.GetNewChainParams(cp.cliCtx, rootChain)
Expand Down Expand Up @@ -1090,3 +1120,13 @@ func (cp *CheckpointProcessor) getDynamicCheckpointProposal(rootType string) (bo

return fea.IsOpen, fea.IntConf[strings.ToLower(rootType)] != 0, fea.IntConf["maxLength"]
}

func (cp *CheckpointProcessor) getTronDynamicCheckpointProposalWithErr() (bool, int, error) {
fea, err := util.GetTronDynamicCheckpointFeature(cp.cliCtx)
if err != nil {
cp.Logger.Error("Error while fetching dynamic checkpoint feature", "error", err)

return false, 0, err
}
return fea.IsOpen, fea.IntConf["maxLength"], err
}
2 changes: 1 addition & 1 deletion bridge/setu/processor/checkpointsync.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func (cp *CheckpointProcessor) sendCheckpointSyncToStakeChain(eventBytes string,
} else {
txHash := common.FromHex(txHash)
if err := cp.createAndSendCheckpointSyncToTron(checkpointContext, number, startBlock, endBlock, rootChain, blockHeight, txHash); err != nil {
cp.Logger.Error("Error sending checkpoint to rootchain", "error", err)
cp.Logger.Error("Error sending checkpoint sync to rootchain", "error", err)
return err
}
}
Expand Down
Loading
Loading