diff --git a/fsm/transaction.go b/fsm/transaction.go index 72351f8641..dad64c8766 100644 --- a/fsm/transaction.go +++ b/fsm/transaction.go @@ -243,7 +243,7 @@ func (s *StateMachine) CheckReplay(tx *lib.Transaction, txHash string) lib.Error } } // this gives the protocol a theoretically safe tx indexer prune height - maxHeight, minHeight := s.Height()+BlockAcceptanceRange, uint64(0) + maxHeight, minHeight := maxAcceptedTxHeight(s.Height()), uint64(0) // if height is after the BlockAcceptanceRange blocks if s.Height() > BlockAcceptanceRange { // update the minimum height @@ -257,6 +257,13 @@ func (s *StateMachine) CheckReplay(tx *lib.Transaction, txHash string) lib.Error return nil } +func maxAcceptedTxHeight(height uint64) uint64 { + if height > math.MaxUint64-BlockAcceptanceRange { + return math.MaxUint64 + } + return height + BlockAcceptanceRange +} + // CheckMessage() performs basic validations on the msg payload func (s *StateMachine) CheckMessage(msg *anypb.Any) (message lib.MessageI, err lib.ErrorI) { // ensure the message isn't nil diff --git a/fsm/transaction_test.go b/fsm/transaction_test.go index b5a43d380c..7691f1bc23 100644 --- a/fsm/transaction_test.go +++ b/fsm/transaction_test.go @@ -665,6 +665,16 @@ func TestCheckReplay(t *testing.T) { }, height: 122, }, + { + name: "maximum height overflow guard", + detail: "near max uint64 height should not wrap the maximum accepted tx height", + tx: &lib.Transaction{ + CreatedHeight: math.MaxUint64 - 1, + NetworkId: 1, + ChainId: 1, + }, + height: math.MaxUint64 - 1, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) {