initial proposerWaitsUntil implementation

This commit is contained in:
William Banfield
2021-11-14 16:42:30 -05:00
parent 0d2a5de203
commit 6f173b8bba
2 changed files with 58 additions and 0 deletions

View File

@@ -2412,3 +2412,15 @@ func repairWalFile(src, dst string) error {
return nil
}
// proposerWaitUntil determines when the proposer should propose its next block
// Block times must be monotonically increasing, so if the block time of the previous
// block is larger than the proposer's current time, then the proposer will sleep
// until its local clock exceeds the previous block time.
func proposerWaitUntil(lt tmtime.Source, h types.Header) time.Time {
t := lt.Now()
if t.After(h.Time) {
return t
}
return h.Time
}

View File

@@ -17,6 +17,7 @@ import (
"github.com/tendermint/tendermint/libs/log"
tmpubsub "github.com/tendermint/tendermint/libs/pubsub"
tmrand "github.com/tendermint/tendermint/libs/rand"
tmtimemocks "github.com/tendermint/tendermint/libs/time/mocks"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/tendermint/tendermint/types"
)
@@ -2440,6 +2441,51 @@ func TestSignSameVoteTwice(t *testing.T) {
require.Equal(t, vote, vote2)
}
func TestProposerWaitUntil(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
expectedTime time.Time
}{
{
name: "block time greater than local time",
blockTime: genesisTime.Add(5 * time.Nanosecond),
localTime: genesisTime.Add(1 * time.Nanosecond),
expectedTime: genesisTime.Add(5 * time.Nanosecond),
},
{
name: "local time greater than block time",
blockTime: genesisTime.Add(1 * time.Nanosecond),
localTime: genesisTime.Add(5 * time.Nanosecond),
expectedTime: genesisTime.Add(5 * time.Nanosecond),
},
{
name: "both times equal",
blockTime: genesisTime.Add(5 * time.Nanosecond),
localTime: genesisTime.Add(5 * time.Nanosecond),
expectedTime: genesisTime.Add(5 * time.Nanosecond),
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
b := types.Block{
Header: types.Header{
Time: testCase.blockTime,
},
}
mockSource := new(tmtimemocks.Source)
mockSource.On("Now").Return(testCase.localTime)
ti := proposerWaitUntil(mockSource, b.Header)
assert.Equal(t, testCase.expectedTime, ti)
})
}
}
// subscribe subscribes test client to the given query and returns a channel with cap = 1.
func subscribe(eventBus *types.EventBus, q tmpubsub.Query) <-chan tmpubsub.Message {
sub, err := eventBus.Subscribe(context.Background(), testSubscriber, q)