mirror of
https://github.com/tendermint/tendermint.git
synced 2026-02-13 07:11:13 +00:00
Compare commits
9 Commits
wb/state-a
...
wb/propose
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57722da6ec | ||
|
|
6ee6f349a1 | ||
|
|
00cbab12c9 | ||
|
|
c7c6f40b84 | ||
|
|
792f250a6d | ||
|
|
f36f94e5e9 | ||
|
|
4a5e6da299 | ||
|
|
12eb73d51d | ||
|
|
6f173b8bba |
115
internal/consensus/pbts_test.go
Normal file
115
internal/consensus/pbts_test.go
Normal file
@@ -0,0 +1,115 @@
|
||||
package consensus
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
tmtimemocks "github.com/tendermint/tendermint/libs/time/mocks"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
func TestProposerWaitTime(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
|
||||
expectedWait time.Duration
|
||||
}{
|
||||
{
|
||||
name: "block time greater than local time",
|
||||
blockTime: genesisTime.Add(5 * time.Nanosecond),
|
||||
localTime: genesisTime.Add(1 * time.Nanosecond),
|
||||
expectedWait: 4 * time.Nanosecond,
|
||||
},
|
||||
{
|
||||
name: "local time greater than block time",
|
||||
blockTime: genesisTime.Add(1 * time.Nanosecond),
|
||||
localTime: genesisTime.Add(5 * time.Nanosecond),
|
||||
expectedWait: 0,
|
||||
},
|
||||
{
|
||||
name: "both times equal",
|
||||
blockTime: genesisTime.Add(5 * time.Nanosecond),
|
||||
localTime: genesisTime.Add(5 * time.Nanosecond),
|
||||
expectedWait: 0,
|
||||
},
|
||||
}
|
||||
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 := proposerWaitTime(mockSource, b.Header)
|
||||
assert.Equal(t, testCase.expectedWait, ti)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProposalTimeout(t *testing.T) {
|
||||
genesisTime, err := time.Parse(time.RFC3339, "2019-03-13T23:00:00Z")
|
||||
require.NoError(t, err)
|
||||
testCases := []struct {
|
||||
name string
|
||||
localTime time.Time
|
||||
previousBlockTime time.Time
|
||||
precision time.Duration
|
||||
msgDelay time.Duration
|
||||
expectedDuration time.Duration
|
||||
}{
|
||||
{
|
||||
name: "MsgDelay + Precision has not quite elapsed",
|
||||
localTime: genesisTime.Add(525 * time.Millisecond),
|
||||
previousBlockTime: genesisTime.Add(6 * time.Millisecond),
|
||||
precision: time.Millisecond * 20,
|
||||
msgDelay: time.Millisecond * 500,
|
||||
expectedDuration: 1 * time.Millisecond,
|
||||
},
|
||||
{
|
||||
name: "MsgDelay + Precision equals current time",
|
||||
localTime: genesisTime.Add(525 * time.Millisecond),
|
||||
previousBlockTime: genesisTime.Add(5 * time.Millisecond),
|
||||
precision: time.Millisecond * 20,
|
||||
msgDelay: time.Millisecond * 500,
|
||||
expectedDuration: 0,
|
||||
},
|
||||
{
|
||||
name: "MsgDelay + Precision has elapsed",
|
||||
localTime: genesisTime.Add(725 * time.Millisecond),
|
||||
previousBlockTime: genesisTime.Add(5 * time.Millisecond),
|
||||
precision: time.Millisecond * 20,
|
||||
msgDelay: time.Millisecond * 500,
|
||||
expectedDuration: 0,
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
b := types.Block{
|
||||
Header: types.Header{
|
||||
Time: testCase.previousBlockTime,
|
||||
},
|
||||
}
|
||||
|
||||
mockSource := new(tmtimemocks.Source)
|
||||
mockSource.On("Now").Return(testCase.localTime)
|
||||
|
||||
tp := types.TimestampParams{
|
||||
Precision: testCase.precision,
|
||||
MsgDelay: testCase.msgDelay,
|
||||
}
|
||||
|
||||
ti := proposalStepWaitingTime(mockSource, b.Header, tp)
|
||||
assert.Equal(t, testCase.expectedDuration, ti)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -2412,3 +2412,39 @@ func repairWalFile(src, dst string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// proposerWaitTime determines how long the proposer should wait to propose its next block.
|
||||
// If the result is zero, a block can be proposed immediately.
|
||||
//
|
||||
// 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 proposerWaitTime(lt tmtime.Source, h types.Header) time.Duration {
|
||||
t := lt.Now()
|
||||
if h.Time.After(t) {
|
||||
return h.Time.Sub(t)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// proposalStepWaitingTime is used along with the `timeout-propose` configuration
|
||||
// parameter to determines how long a validator will wait for a block to be sent from a proposer.
|
||||
// proposalStepWaitingTime ensures that the validator waits long enough for the proposer to
|
||||
// deliver a block with a monotically increasing timestamp.
|
||||
//
|
||||
// To ensure that the validator waits long enough, it must wait until the previous
|
||||
// block's timestamp. It also must account for the difference between its own clock and
|
||||
// the proposer's clock, i.e. the 'Precision', and the amount of time for the message to be transmitted,
|
||||
// i.e. the MsgDelay.
|
||||
//
|
||||
// The result of proposalStepWaitingTime is compared with the configured `timeout-propose` duration,
|
||||
// and the validator waits for whichever duration is larger before advancing to the next step
|
||||
// and prevoting nil.
|
||||
func proposalStepWaitingTime(lt tmtime.Source, h types.Header, tp types.TimestampParams) time.Duration {
|
||||
t := lt.Now()
|
||||
wt := h.Time.Add(tp.Precision).Add(tp.MsgDelay)
|
||||
if t.After(wt) {
|
||||
return 0
|
||||
}
|
||||
return wt.Sub(t)
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ func (p *Proposal) IsTimely(clock tmtime.Source, tp TimestampParams) bool {
|
||||
lt := clock.Now()
|
||||
lhs := lt.Add(-tp.Precision)
|
||||
rhs := lt.Add(tp.Precision).Add(tp.MsgDelay)
|
||||
if lhs.Before(p.Timestamp) && p.Timestamp.Before(rhs) {
|
||||
if lhs.Before(p.Timestamp) && rhs.After(p.Timestamp) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user