diff --git a/internal/consensus/state.go b/internal/consensus/state.go index 9dd8d660c..e3113015c 100644 --- a/internal/consensus/state.go +++ b/internal/consensus/state.go @@ -1319,7 +1319,7 @@ func (cs *State) proposalIsTimely() bool { MessageDelay: cs.state.ConsensusParams.Timing.MessageDelay, } - return cs.Proposal.IsTimely(cs.ProposalReceiveTime, tp, cs.state.InitialHeight) + return cs.Proposal.IsTimely(cs.ProposalReceiveTime, tp) } func (cs *State) defaultDoPrevote(height int64, round int32) { @@ -1417,7 +1417,7 @@ func (cs *State) defaultDoPrevote(height int64, round int32) { } } - logger.Debug("prevote step: ProposalBlock is valid but was not our locked block or" + + logger.Debug("prevote step: ProposalBlock is valid but was not our locked block or " + "did not receive a more recent majority; prevoting nil") cs.signAddVote(tmproto.PrevoteType, nil, types.PartSetHeader{}) } diff --git a/internal/state/state.go b/internal/state/state.go index fcbacdfcc..027da4e54 100644 --- a/internal/state/state.go +++ b/internal/state/state.go @@ -263,18 +263,10 @@ func (state State) MakeBlock( // Build base block with block data. block := types.MakeBlock(height, txs, commit, evidence) - // Set time. - var timestamp time.Time - if height == state.InitialHeight { - timestamp = state.LastBlockTime // genesis time - } else { - timestamp = time.Now() - } - // Fill rest of header with state data. block.Header.Populate( state.Version.Consensus, state.ChainID, - timestamp, state.LastBlockID, + time.Now(), state.LastBlockID, state.Validators.Hash(), state.NextValidators.Hash(), state.ConsensusParams.HashConsensusParams(), state.AppHash, state.LastResultsHash, proposerAddress, diff --git a/internal/state/validation.go b/internal/state/validation.go index 8bec8f119..900b7b787 100644 --- a/internal/state/validation.go +++ b/internal/state/validation.go @@ -117,8 +117,8 @@ func validateBlock(state State, block *types.Block) error { case block.Height == state.InitialHeight: genesisTime := state.LastBlockTime - if !block.Time.Equal(genesisTime) { - return fmt.Errorf("block time %v is not equal to genesis time %v", + if block.Time.Before(genesisTime) { + return fmt.Errorf("block time %v is before genesis time %v", block.Time, genesisTime, ) diff --git a/rpc/client/evidence_test.go b/rpc/client/evidence_test.go index ae4e29f52..9187ddc1a 100644 --- a/rpc/client/evidence_test.go +++ b/rpc/client/evidence_test.go @@ -15,15 +15,11 @@ import ( "github.com/tendermint/tendermint/types" ) -// For some reason the empty node used in tests has a time of -// 2018-10-10 08:20:13.695936996 +0000 UTC -// this is because the test genesis time is set here -// so in order to validate evidence we need evidence to be the same time -var defaultTestTime = time.Date(2018, 10, 10, 8, 20, 13, 695936996, time.UTC) - func newEvidence(t *testing.T, val *privval.FilePV, vote *types.Vote, vote2 *types.Vote, - chainID string) *types.DuplicateVoteEvidence { + chainID string, + timestamp time.Time, +) *types.DuplicateVoteEvidence { t.Helper() var err error @@ -39,7 +35,7 @@ func newEvidence(t *testing.T, val *privval.FilePV, validator := types.NewValidator(val.Key.PubKey, 10) valSet := types.NewValidatorSet([]*types.Validator{validator}) - ev, err := types.NewDuplicateVoteEvidence(vote, vote2, defaultTestTime, valSet) + ev, err := types.NewDuplicateVoteEvidence(vote, vote2, timestamp, valSet) require.NoError(t, err) return ev } @@ -48,6 +44,7 @@ func makeEvidences( t *testing.T, val *privval.FilePV, chainID string, + timestamp time.Time, ) (correct *types.DuplicateVoteEvidence, fakes []*types.DuplicateVoteEvidence) { vote := types.Vote{ ValidatorAddress: val.Key.Address, @@ -55,7 +52,7 @@ func makeEvidences( Height: 1, Round: 0, Type: tmproto.PrevoteType, - Timestamp: defaultTestTime, + Timestamp: timestamp, BlockID: types.BlockID{ Hash: tmhash.Sum(tmrand.Bytes(tmhash.Size)), PartSetHeader: types.PartSetHeader{ @@ -67,7 +64,7 @@ func makeEvidences( vote2 := vote vote2.BlockID.Hash = tmhash.Sum([]byte("blockhash2")) - correct = newEvidence(t, val, &vote, &vote2, chainID) + correct = newEvidence(t, val, &vote, &vote2, chainID, timestamp) fakes = make([]*types.DuplicateVoteEvidence, 0) @@ -75,34 +72,34 @@ func makeEvidences( { v := vote2 v.ValidatorAddress = []byte("some_address") - fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID)) + fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID, timestamp)) } // different height { v := vote2 v.Height = vote.Height + 1 - fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID)) + fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID, timestamp)) } // different round { v := vote2 v.Round = vote.Round + 1 - fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID)) + fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID, timestamp)) } // different type { v := vote2 v.Type = tmproto.PrecommitType - fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID)) + fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID, timestamp)) } // exactly same vote { v := vote - fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID)) + fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID, timestamp)) } return correct, fakes diff --git a/rpc/client/rpc_test.go b/rpc/client/rpc_test.go index 12c13d686..a94af8d72 100644 --- a/rpc/client/rpc_test.go +++ b/rpc/client/rpc_test.go @@ -516,10 +516,12 @@ func TestClientMethodCalls(t *testing.T) { t.Run("BraodcastDuplicateVote", func(t *testing.T) { chainID := conf.ChainID() - correct, fakes := makeEvidences(t, pv, chainID) - // make sure that the node has produced enough blocks waitForBlock(ctx, t, c, 2) + evidenceHeight := int64(1) + block, _ := c.Block(ctx, &evidenceHeight) + ts := block.Block.Time + correct, fakes := makeEvidences(t, pv, chainID, ts) result, err := c.BroadcastEvidence(ctx, correct) require.NoError(t, err, "BroadcastEvidence(%s) failed", correct) diff --git a/types/proposal.go b/types/proposal.go index d32ab65dd..15b205d68 100644 --- a/types/proposal.go +++ b/types/proposal.go @@ -89,18 +89,16 @@ func (p *Proposal) ValidateBasic() error { // // 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 (p *Proposal) IsTimely(recvTime time.Time, tp TimingParams, initialHeight int64) bool { +func (p *Proposal) IsTimely(recvTime time.Time, tp TimingParams) bool { // lhs is `proposedBlockTime - Precision` in the first inequality lhs := p.Timestamp.Add(-tp.Precision) // rhs is `proposedBlockTime + MsgDelay + Precision` in the second inequality rhs := p.Timestamp.Add(tp.MessageDelay).Add(tp.Precision) - recvTimeAfterOrEqLHS := recvTime.After(lhs) || recvTime.Equal(lhs) - recvTimeBeforeOrEqRHS := recvTime.Before(rhs) || recvTime.Equal(rhs) - if recvTimeAfterOrEqLHS && (p.Height == initialHeight || recvTimeBeforeOrEqRHS) { - return true + if recvTime.Before(lhs) || recvTime.After(rhs) { + return false } - return false + return true } // String returns a string representation of the Proposal. diff --git a/types/proposal_test.go b/types/proposal_test.go index 63875b12c..b7ef8c741 100644 --- a/types/proposal_test.go +++ b/types/proposal_test.go @@ -198,7 +198,6 @@ func TestIsTimely(t *testing.T) { require.NoError(t, err) testCases := []struct { name string - genesisHeight int64 proposalHeight int64 proposalTime time.Time recvTime time.Time @@ -211,7 +210,6 @@ func TestIsTimely(t *testing.T) { // Checking that the following inequality evaluates to true: // 0 - 2 <= 1 <= 0 + 1 + 2 name: "basic timely", - genesisHeight: 1, proposalHeight: 2, proposalTime: genesisTime, recvTime: genesisTime.Add(1 * time.Nanosecond), @@ -223,7 +221,6 @@ func TestIsTimely(t *testing.T) { // Checking that the following inequality evaluates to false: // 0 - 2 <= 4 <= 0 + 1 + 2 name: "local time too large", - genesisHeight: 1, proposalHeight: 2, proposalTime: genesisTime, recvTime: genesisTime.Add(4 * time.Nanosecond), @@ -235,7 +232,6 @@ func TestIsTimely(t *testing.T) { // Checking that the following inequality evaluates to false: // 4 - 2 <= 0 <= 4 + 2 + 1 name: "proposal time too large", - genesisHeight: 1, proposalHeight: 2, proposalTime: genesisTime.Add(4 * time.Nanosecond), recvTime: genesisTime, @@ -243,32 +239,6 @@ func TestIsTimely(t *testing.T) { msgDelay: time.Nanosecond, expectTimely: false, }, - { - // Checking that the following inequality evaluates to true: - // 0 - 2 <= 4 - // and the following check is skipped - // 4 <= 0 + 1 + 2 - name: "local time too large but proposal is for genesis", - genesisHeight: 1, - proposalHeight: 1, - proposalTime: genesisTime, - recvTime: genesisTime.Add(4 * time.Nanosecond), - precision: time.Nanosecond * 2, - msgDelay: time.Nanosecond, - expectTimely: true, - }, - { - // Checking that the following inequality evaluates to false: - // 4 - 2 <= 0 - name: "proposal time too large for genesis block proposal", - genesisHeight: 1, - proposalHeight: 1, - proposalTime: genesisTime.Add(4 * time.Nanosecond), - recvTime: genesisTime, - precision: time.Nanosecond * 2, - msgDelay: time.Nanosecond, - expectTimely: false, - }, } for _, testCase := range testCases { @@ -283,7 +253,7 @@ func TestIsTimely(t *testing.T) { MessageDelay: testCase.msgDelay, } - ti := p.IsTimely(testCase.recvTime, tp, testCase.genesisHeight) + ti := p.IsTimely(testCase.recvTime, tp) assert.Equal(t, testCase.expectTimely, ti) }) }