mirror of
https://github.com/tendermint/tendermint.git
synced 2026-08-27 19:37:08 +00:00
state: add an IsTimely function to implement the check for timely in proposer-based timestamps
This commit is contained in:
@@ -304,6 +304,24 @@ func MedianTime(commit *types.Commit, validators *types.ValidatorSet) time.Time
|
||||
return weightedMedian(weightedTimes, totalVotingPower)
|
||||
}
|
||||
|
||||
// IsTimely validates that the passed in block timestamp is 'timely' according to the proposer-based timestamp algorithm.
|
||||
// To evaluate if a timestamp is timely, it is compared to the local time of the validator along with the configured
|
||||
// Precision and MsgDelay parameters.
|
||||
// Specifically, a proposed block timestamp is considered timely if it is satisfies the following inequalities:
|
||||
//
|
||||
// proposedBlockTime < validatorLocalTime + Precision + MsgDelay && proposedBlockTime > validatorLocaltime - Precision.
|
||||
//
|
||||
// For more information on the meaning of 'timely', see the proposer-based timestamp specification:
|
||||
// https://github.com/tendermint/spec/tree/master/spec/consensus/proposer-based-timestamp
|
||||
func IsTimely(bt time.Time, lt time.Time, precision time.Duration, msgDelay time.Duration) bool {
|
||||
lhs := lt.Add(-precision).UnixMilli()
|
||||
rhs := lt.Add(precision).Add(msgDelay).UnixMilli()
|
||||
if lhs < bt.UnixMilli() && bt.UnixMilli() < rhs {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Genesis
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
tmtime "github.com/tendermint/tendermint/libs/time"
|
||||
)
|
||||
|
||||
@@ -55,3 +56,53 @@ func TestWeightedMedian(t *testing.T) {
|
||||
assert.Equal(t, true, (median.After(t1) || median.Equal(t1)) &&
|
||||
(median.Before(t4) || median.Equal(t4)))
|
||||
}
|
||||
|
||||
func TestIsTimely(t *testing.T) {
|
||||
genesisTime, err := time.Parse(time.RFC3339, "2019-03-13T23:00:00Z")
|
||||
require.NoError(t, err)
|
||||
testCases := []struct {
|
||||
name string
|
||||
blockTime time.Time
|
||||
localTime time.Time
|
||||
precision time.Duration
|
||||
msgDelay time.Duration
|
||||
expectTimely bool
|
||||
}{
|
||||
{
|
||||
// Checking that the following inequality evaluates to true:
|
||||
// 1 - 2 < 0 < 1 + 2 + 1
|
||||
name: "basic timely",
|
||||
blockTime: genesisTime,
|
||||
localTime: genesisTime.Add(1 * time.Millisecond),
|
||||
precision: time.Millisecond * 2,
|
||||
msgDelay: time.Millisecond,
|
||||
expectTimely: true,
|
||||
},
|
||||
{
|
||||
// Checking that the following inequality evaluates to false:
|
||||
// 3 - 2 < 0 < 3 + 2 + 1
|
||||
name: "local time too large",
|
||||
blockTime: genesisTime,
|
||||
localTime: genesisTime.Add(3 * time.Millisecond),
|
||||
precision: time.Millisecond * 2,
|
||||
msgDelay: time.Millisecond,
|
||||
expectTimely: false,
|
||||
},
|
||||
{
|
||||
// Checking that the following inequality evaluates to false:
|
||||
// 0 - 2 < 2 < 2 + 1
|
||||
name: "block time too large",
|
||||
blockTime: genesisTime.Add(4 * time.Millisecond),
|
||||
localTime: genesisTime,
|
||||
precision: time.Millisecond * 2,
|
||||
msgDelay: time.Millisecond,
|
||||
expectTimely: false,
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
ti := IsTimely(testCase.blockTime, testCase.localTime, testCase.precision, testCase.msgDelay)
|
||||
assert.Equal(t, testCase.expectTimely, ti)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user