time.Now().Round(0).UTC() for all times externally communicated

This commit is contained in:
Jae Kwon 2018-05-15 18:52:49 -07:00
parent e1a3f16fa4
commit e429aa2121
26 changed files with 97 additions and 70 deletions

View File

@ -70,7 +70,7 @@ var (
part1 = partSet.GetPart(0)
part2 = partSet.GetPart(1)
seenCommit1 = &types.Commit{Precommits: []*types.Vote{{Height: 10,
Timestamp: time.Now().UTC()}}}
Timestamp: time.Now().Round(0).UTC()}}}
)
// TODO: This test should be simplified ...
@ -91,7 +91,7 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) {
block := makeBlock(bs.Height()+1, state)
validPartSet := block.MakePartSet(2)
seenCommit := &types.Commit{Precommits: []*types.Vote{{Height: 10,
Timestamp: time.Now().UTC()}}}
Timestamp: time.Now().Round(0).UTC()}}}
bs.SaveBlock(block, partSet, seenCommit)
require.Equal(t, bs.Height(), block.Header.Height, "expecting the new height to be changed")
@ -103,7 +103,7 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) {
Height: 1,
NumTxs: 100,
ChainID: "block_test",
Time: time.Now(),
Time: time.Now().Round(0).UTC(),
}
header2 := header1
header2.Height = 4
@ -111,7 +111,7 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) {
// End of setup, test data
commitAtH10 := &types.Commit{Precommits: []*types.Vote{{Height: 10,
Timestamp: time.Now().UTC()}}}
Timestamp: time.Now().Round(0).UTC()}}}
tuples := []struct {
block *types.Block
parts *types.PartSet
@ -335,7 +335,7 @@ func TestBlockFetchAtHeight(t *testing.T) {
partSet := block.MakePartSet(2)
seenCommit := &types.Commit{Precommits: []*types.Vote{{Height: 10,
Timestamp: time.Now().UTC()}}}
Timestamp: time.Now().Round(0).UTC()}}}
bs.SaveBlock(block, partSet, seenCommit)
require.Equal(t, bs.Height(), block.Header.Height, "expecting the new height to be changed")

View File

@ -53,7 +53,7 @@ func initFilesWithConfig(config *cfg.Config) error {
} else {
genDoc := types.GenesisDoc{
ChainID: cmn.Fmt("test-chain-%v", cmn.RandStr(6)),
GenesisTime: time.Now(),
GenesisTime: time.Now().Round(0).UTC(),
}
genDoc.Validators = []types.GenesisValidator{{
PubKey: pv.GetPubKey(),

View File

@ -112,7 +112,7 @@ func testnetFiles(cmd *cobra.Command, args []string) error {
// Generate genesis doc from generated validators
genDoc := &types.GenesisDoc{
GenesisTime: time.Now(),
GenesisTime: time.Now().Round(0).UTC(),
ChainID: "chain-" + cmn.RandStr(6),
Validators: genVals,
}

View File

@ -75,7 +75,7 @@ func (vs *validatorStub) signVote(voteType byte, hash []byte, header types.PartS
ValidatorAddress: vs.PrivValidator.GetAddress(),
Height: vs.Height,
Round: vs.Round,
Timestamp: time.Now().UTC(),
Timestamp: time.Now().Round(0).UTC(),
Type: voteType,
BlockID: types.BlockID{hash, header},
}
@ -420,7 +420,7 @@ func randGenesisDoc(numValidators int, randPower bool, minPower int64) (*types.G
sort.Sort(types.PrivValidatorsByAddress(privValidators))
return &types.GenesisDoc{
GenesisTime: time.Now(),
GenesisTime: time.Now().Round(0).UTC(),
ChainID: config.ChainID(),
Validators: validators,
}, privValidators

View File

@ -1201,7 +1201,7 @@ func (ps *PeerState) ApplyNewRoundStepMessage(msg *NewRoundStepMessage) {
psCatchupCommitRound := ps.PRS.CatchupCommitRound
psCatchupCommit := ps.PRS.CatchupCommit
startTime := time.Now().Add(-1 * time.Duration(msg.SecondsSinceStartTime) * time.Second)
startTime := time.Now().Round(0).UTC().Add(-1 * time.Duration(msg.SecondsSinceStartTime) * time.Second)
ps.PRS.Height = msg.Height
ps.PRS.Round = msg.Round
ps.PRS.Step = msg.Step

View File

@ -199,7 +199,7 @@ func TestReactorRecordsVotes(t *testing.T) {
ValidatorAddress: val.Address,
Height: 2,
Round: 0,
Timestamp: time.Now().UTC(),
Timestamp: time.Now().Round(0).UTC(),
Type: types.VoteTypePrevote,
BlockID: types.BlockID{},
}

View File

@ -13,6 +13,7 @@ import (
"testing"
"time"
"github.com/davecgh/go-spew/spew"
"github.com/stretchr/testify/require"
"github.com/tendermint/abci/example/kvstore"
@ -139,6 +140,11 @@ LOOP:
logger := log.NewNopLogger()
stateDB := dbm.NewMemDB()
state, _ := sm.MakeGenesisStateFromFile(consensusReplayConfig.GenesisFile())
fmt.Println("==== QQQ ")
spew.Dump(state)
fmt.Println("==== QQQ ")
spew.Dump(consensusReplayConfig.GenesisFile())
fmt.Println("==== QQQ ")
privValidator := loadPrivValidator(consensusReplayConfig)
blockDB := dbm.NewMemDB()
cs := newConsensusStateWithConfigAndBlockStore(consensusReplayConfig, state, privValidator, kvstore.NewKVStoreApplication(), blockDB)

View File

@ -386,8 +386,8 @@ func (cs *ConsensusState) updateRoundStep(round int, step cstypes.RoundStepType)
// enterNewRound(height, 0) at cs.StartTime.
func (cs *ConsensusState) scheduleRound0(rs *cstypes.RoundState) {
//cs.Logger.Info("scheduleRound0", "now", time.Now(), "startTime", cs.StartTime)
sleepDuration := rs.StartTime.Sub(time.Now()) // nolint: gotype, gosimple
//cs.Logger.Info("scheduleRound0", "now", time.Now().Round(0).UTC(), "startTime", cs.StartTime)
sleepDuration := rs.StartTime.Sub(time.Now().Round(0).UTC()) // nolint: gotype, gosimple
cs.scheduleTimeout(sleepDuration, rs.Height, 0, cstypes.RoundStepNewHeight)
}
@ -477,7 +477,7 @@ func (cs *ConsensusState) updateToState(state sm.State) {
// to be gathered for the first block.
// And alternative solution that relies on clocks:
// cs.StartTime = state.LastBlockTime.Add(timeoutCommit)
cs.StartTime = cs.config.Commit(time.Now())
cs.StartTime = cs.config.Commit(time.Now().Round(0).UTC())
} else {
cs.StartTime = cs.config.Commit(cs.CommitTime)
}
@ -672,7 +672,7 @@ func (cs *ConsensusState) enterNewRound(height int64, round int) {
return
}
if now := time.Now(); cs.StartTime.After(now) {
if now := time.Now().Round(0).UTC(); cs.StartTime.After(now) {
cs.Logger.Info("Need to set a buffer and log message here for sanity.", "startTime", cs.StartTime, "now", now)
}
@ -941,7 +941,10 @@ func (cs *ConsensusState) defaultDoPrevote(height int64, round int) {
return
}
// Validate proposal block
// Validate proposal block timestamp.
// TODOerr := cs.validate
// Validate proposal block.
err := cs.blockExec.ValidateBlock(cs.state, cs.ProposalBlock)
if err != nil {
// ProposalBlock is invalid, prevote nil.
@ -950,8 +953,8 @@ func (cs *ConsensusState) defaultDoPrevote(height int64, round int) {
return
}
// Prevote cs.ProposalBlock
// NOTE: the proposal signature is validated when it is received,
// Prevote cs.ProposalBlock.
// NOTE: The proposal signature is validated when it is received,
// and the proposal block parts are validated as they are received (against the merkle hash in the proposal)
logger.Info("enterPrevote: ProposalBlock is valid")
cs.signAddVote(types.VoteTypePrevote, cs.ProposalBlock.Hash(), cs.ProposalBlockParts.Header())
@ -1112,7 +1115,7 @@ func (cs *ConsensusState) enterCommit(height int64, commitRound int) {
// keep cs.Round the same, commitRound points to the right Precommits set.
cs.updateRoundStep(cs.Round, cstypes.RoundStepCommit)
cs.CommitRound = commitRound
cs.CommitTime = time.Now()
cs.CommitTime = time.Now().Round(0).UTC()
cs.newStep()
// Maybe finalize immediately.
@ -1521,7 +1524,7 @@ func (cs *ConsensusState) signVote(type_ byte, hash []byte, header types.PartSet
ValidatorIndex: valIndex,
Height: cs.Height,
Round: cs.Round,
Timestamp: time.Now().UTC(),
Timestamp: time.Now().Round(0).UTC(),
Type: type_,
BlockID: types.BlockID{hash, header},
}

View File

@ -55,7 +55,7 @@ func makeVoteHR(t *testing.T, height int64, round int, privVals []types.PrivVali
ValidatorIndex: valIndex,
Height: height,
Round: round,
Timestamp: time.Now().UTC(),
Timestamp: time.Now().Round(0).UTC(),
Type: types.VoteTypePrecommit,
BlockID: types.BlockID{[]byte("fakehash"), types.PartSetHeader{}},
}

View File

@ -27,7 +27,7 @@ func BenchmarkRoundStateDeepCopy(b *testing.B) {
for i := 0; i < nval; i++ {
precommits[i] = &types.Vote{
ValidatorAddress: types.Address(cmn.RandBytes(20)),
Timestamp: time.Now(),
Timestamp: time.Now().Round(0).UTC(),
BlockID: blockID,
Signature: sig,
}
@ -40,7 +40,7 @@ func BenchmarkRoundStateDeepCopy(b *testing.B) {
block := &types.Block{
Header: &types.Header{
ChainID: cmn.RandStr(12),
Time: time.Now(),
Time: time.Now().Round(0).UTC(),
LastBlockID: blockID,
LastCommitHash: cmn.RandBytes(20),
DataHash: cmn.RandBytes(20),
@ -62,7 +62,7 @@ func BenchmarkRoundStateDeepCopy(b *testing.B) {
parts := block.MakePartSet(4096)
// Random Proposal
proposal := &types.Proposal{
Timestamp: time.Now(),
Timestamp: time.Now().Round(0).UTC(),
BlockPartsHeader: types.PartSetHeader{
Hash: cmn.RandBytes(20),
},
@ -73,8 +73,8 @@ func BenchmarkRoundStateDeepCopy(b *testing.B) {
// TODO: hvs :=
rs := &RoundState{
StartTime: time.Now(),
CommitTime: time.Now(),
StartTime: time.Now().Round(0).UTC(),
CommitTime: time.Now().Round(0).UTC(),
Validators: vset,
Proposal: proposal,
ProposalBlock: block,

View File

@ -116,7 +116,7 @@ func (wal *baseWAL) Save(msg WALMessage) {
}
// Write the wal message
if err := wal.enc.Encode(&TimedWALMessage{time.Now(), msg}); err != nil {
if err := wal.enc.Encode(&TimedWALMessage{time.Now().Round(0).UTC(), msg}); err != nil {
cmn.PanicQ(cmn.Fmt("Error writing msg to consensus wal: %v \n\nMessage: %v", err, msg))
}

View File

@ -16,7 +16,7 @@ import (
)
func TestWALEncoderDecoder(t *testing.T) {
now := time.Now()
now := time.Now().Round(0).UTC()
msgs := []TimedWALMessage{
TimedWALMessage{Time: now, Msg: EndHeightMessage{0}},
TimedWALMessage{Time: now, Msg: timeoutInfo{Duration: time.Second, Height: 1, Round: 1, Step: types.RoundStepPropose}},
@ -93,7 +93,7 @@ func benchmarkWalDecode(b *testing.B, n int) {
enc := NewWALEncoder(buf)
data := nBytes(n)
enc.Encode(&TimedWALMessage{Msg: data, Time: time.Now().Round(time.Second)})
enc.Encode(&TimedWALMessage{Msg: data, Time: time.Now().Round(time.Second).UTC()})
encoded := buf.Bytes()

View File

@ -3,24 +3,35 @@
Tendermint provides a deterministic, Byzantine fault-tolerant, source of time.
Time in Tendermint is defined with the Time field of the block header.
It satisfies the following properties:
It satisfies the following property:
- Time Monotonicity: Time is monotonically increasing, i.e., given
a header H1 for height h1 and a header H2 for height `h2 = h1 + 1`, `H1.Time < H2.Time`.
- Time Validity: Given a set of Commit votes that forms the `block.LastCommit` field, a range of
valid values for the Time field of the block header is defined only by
Precommit messages (from the LastCommit field) sent by correct processes, i.e.,
a faulty process cannot arbitrarily increase the Time value.
In the context of Tendermint, time is of type int64 and denotes UNIX time in milliseconds, i.e.,
corresponds to the number of milliseconds since January 1, 1970. Before defining rules that need to be enforced by the
Tendermint consensus protocol, so the properties above holds, we introduce the following definition:
Beyond satisfying time monotinicity, Tendermint also checks the following
propoerty only just before signing a prevote:
- median of a set of `Vote` messages is equal to the median of `Vote.Time` fields of the corresponding `Vote` messages,
where the value of `Vote.Time` is counted number of times proportional to the process voting power. As in Tendermint
the voting power is not uniform (one process one vote), a vote message is actually an aggregator of the same votes whose
number is equal to the voting power of the process that has casted the corresponding votes message.
- Temporal Time Validity: Time is greater than MinValidTime(last_block_time,
new_block_time, now, ideal_block_duration, round) and MaxValidTime(last_block_time, now, round)
```go
func MinValidTime(last_block_time, new_block_time, now time.Time, ideal_block_duration time.Duration, round int) error {
if !last_block_time.Before(new_block_time) {
return errors.New("New block time cannot be before the last block time")
}
if !new_block_time.Before(now) {
return errors.New("New block time cannot be in the future")
}
}
```
In the context of Tendermint, time denotes UNIX time in milliseconds, i.e.,
corresponds to the number of milliseconds since January 1, 1970.
the time monotinicity only occurs at the prevote step. When
Let's consider the following example:
- we have four processes p1, p2, p3 and p4, with the following voting power distribution (p1, 23), (p2, 27), (p3, 10)
and (p4, 10). The total voting power is 70 (`N = 3f+1`, where `N` is the total voting power, and `f` is the maximum voting
@ -41,13 +52,13 @@ rs.Proposal.Timestamp == rs.ProposalBlock.Header.Time`.
- Furthermore, when creating the `vote` message, the following rules for determining `vote.Time` field should hold:
- if `rs.Proposal` is defined then
`vote.Time = max(rs.Proposal.Timestamp + 1, time.Now())`, where `time.Now()`
`vote.Time = max(rs.Proposal.Timestamp + 1, time.Now().Round(0).UTC())`, where `time.Now().Round(0).UTC()`
denotes local Unix time in milliseconds.
- if `rs.Proposal` is not defined and `rs.Votes` contains +2/3 of the corresponding vote messages (votes for the
current height and round, and with the corresponding type (`Prevote` or `Precommit`)), then
`vote.Time = max(median(getVotes(rs.Votes, vote.Height, vote.Round, vote.Type)), time.Now())`,
`vote.Time = max(median(getVotes(rs.Votes, vote.Height, vote.Round, vote.Type)), time.Now().Round(0).UTC())`,
where `getVotes` function returns the votes for particular `Height`, `Round` and `Type`.
The second rule is relevant for the case when a process jumps to a higher round upon receiving +2/3 votes for a higher

View File

@ -25,7 +25,7 @@ func initializeValidatorState(valAddr []byte, height int64) dbm.DB {
}
state := sm.State{
LastBlockHeight: 0,
LastBlockTime: time.Now(),
LastBlockTime: time.Now().Round(0).UTC(),
Validators: valSet,
LastHeightValidatorsChanged: 1,
ConsensusParams: types.ConsensusParams{

View File

@ -97,7 +97,7 @@ func makeVote(header *types.Header, vals *types.ValidatorSet, key crypto.PrivKey
ValidatorIndex: idx,
Height: header.Height,
Round: 1,
Timestamp: time.Now().UTC(),
Timestamp: time.Now().Round(0).UTC(),
Type: types.VoteTypePrecommit,
BlockID: types.BlockID{Hash: header.Hash()},
}
@ -115,7 +115,7 @@ func genHeader(chainID string, height int64, txs types.Txs,
return &types.Header{
ChainID: chainID,
Height: height,
Time: time.Now(),
Time: time.Now().Round(0).UTC(),
NumTxs: int64(len(txs)),
TotalTxs: int64(len(txs)),
// LastBlockID

View File

@ -60,7 +60,7 @@ func TestBeginBlockAbsentValidators(t *testing.T) {
prevParts := types.PartSetHeader{}
prevBlockID := types.BlockID{prevHash, prevParts}
now := time.Now().UTC()
now := time.Now().Round(0).UTC()
testCases := []struct {
desc string
lastCommitPrecommits []*types.Vote

View File

@ -6,6 +6,7 @@ import (
"io/ioutil"
"time"
"github.com/davecgh/go-spew/spew"
"github.com/tendermint/tendermint/types"
)
@ -140,6 +141,7 @@ func MakeGenesisDocFromFile(genDocFile string) (*types.GenesisDoc, error) {
return nil, fmt.Errorf("Couldn't read GenesisDoc file: %v", err)
}
genDoc, err := types.GenesisDocFromJSON(genDocJSON)
fmt.Println(">>>", string(genDocJSON), spew.Sdump(genDoc))
if err != nil {
return nil, fmt.Errorf("Error reading GenesisDoc: %v", err)
}

View File

@ -13,12 +13,12 @@ import (
// Validate block
func validateBlock(stateDB dbm.DB, s State, b *types.Block) error {
// validate internal consistency
// Validate internal consistency.
if err := b.ValidateBasic(); err != nil {
return err
}
// validate basic info
// Validate basic info.
if b.ChainID != s.ChainID {
return fmt.Errorf("Wrong Block.Header.ChainID. Expected %v, got %v", s.ChainID, b.ChainID)
}
@ -33,18 +33,21 @@ func validateBlock(stateDB dbm.DB, s State, b *types.Block) error {
}
*/
// validate prev block info
// Validate prev block info.
if !b.LastBlockID.Equals(s.LastBlockID) {
return fmt.Errorf("Wrong Block.Header.LastBlockID. Expected %v, got %v", s.LastBlockID, b.LastBlockID)
return fmt.Errorf("Wrong Block.Header.LastBlockID. Expected %v, got %v", s.LastBlockID, b.LastBlockID)
}
newTxs := int64(len(b.Data.Txs))
if b.TotalTxs != s.LastBlockTotalTx+newTxs {
return fmt.Errorf("Wrong Block.Header.TotalTxs. Expected %v, got %v", s.LastBlockTotalTx+newTxs, b.TotalTxs)
}
if !b.Time.After(s.LastBlockTime) {
return fmt.Errorf("Bad Block.Time. Expected something greater than %v (last block time), but got %v", s.LastBlockTime, b.Time)
}
// validate app info
// Validate app info.
if !bytes.Equal(b.AppHash, s.AppHash) {
return fmt.Errorf("Wrong Block.Header.AppHash. Expected %X, got %v", s.AppHash, b.AppHash)
return fmt.Errorf("Wrong Block.Header.AppHash. Expected %X, got %v", s.AppHash, b.AppHash)
}
if !bytes.Equal(b.ConsensusHash, s.ConsensusParams.Hash()) {
return fmt.Errorf("Wrong Block.Header.ConsensusHash. Expected %X, got %v", s.ConsensusParams.Hash(), b.ConsensusHash)

View File

@ -29,7 +29,7 @@ func MakeBlock(height int64, txs []Tx, commit *Commit) *Block {
block := &Block{
Header: &Header{
Height: height,
Time: time.Now(),
Time: time.Now().Round(0), // Strip monotonic.
NumTxs: int64(len(txs)),
},
LastCommit: commit,

View File

@ -84,9 +84,11 @@ func (genDoc *GenesisDoc) ValidateAndComplete() error {
}
}
if genDoc.GenesisTime.IsZero() {
genDoc.GenesisTime = time.Now()
}
/*
if genDoc.GenesisTime.IsZero() {
genDoc.GenesisTime = time.Now().Round(0).UTC()
}
*/
return nil
}

View File

@ -309,7 +309,7 @@ func checkVotesOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (time.T
}
// set the times to the same value and check equality
now := types.CanonicalTime(time.Now())
now := types.CanonicalTime(time.Now().Round(0).UTC())
lastVote.Timestamp = now
newVote.Timestamp = now
lastVoteBytes, _ := cdc.MarshalJSON(lastVote)
@ -335,7 +335,7 @@ func checkProposalsOnlyDifferByTimestamp(lastSignBytes, newSignBytes []byte) (ti
}
// set the times to the same value and check equality
now := types.CanonicalTime(time.Now())
now := types.CanonicalTime(time.Now().Round(0).UTC())
lastProposal.Timestamp = now
newProposal.Timestamp = now
lastProposalBytes, _ := cdc.MarshalJSON(lastProposal)

View File

@ -229,7 +229,7 @@ func newVote(addr types.Address, idx int, height int64, round int, typ byte, blo
Height: height,
Round: round,
Type: typ,
Timestamp: time.Now().UTC(),
Timestamp: time.Now().Round(0).UTC(),
BlockID: blockID,
}
}
@ -239,7 +239,7 @@ func newProposal(height int64, round int, partsHeader types.PartSetHeader) *type
Height: height,
Round: round,
BlockPartsHeader: partsHeader,
Timestamp: time.Now().UTC(),
Timestamp: time.Now().Round(0).UTC(),
}
}

View File

@ -34,7 +34,7 @@ func NewProposal(height int64, round int, blockPartsHeader PartSetHeader, polRou
return &Proposal{
Height: height,
Round: round,
Timestamp: time.Now().UTC(),
Timestamp: time.Now().Round(0).UTC(),
BlockPartsHeader: blockPartsHeader,
POLRound: polRound,
POLBlockID: polBlockID,

View File

@ -16,7 +16,7 @@ func MakeCommit(blockID BlockID, height int64, round int,
Round: round,
Type: VoteTypePrecommit,
BlockID: blockID,
Timestamp: time.Now().UTC(),
Timestamp: time.Now().Round(0).UTC(),
}
_, err := signAddVote(validators[i], vote, voteSet)

View File

@ -327,7 +327,7 @@ func TestValidatorSetVerifyCommit(t *testing.T) {
ValidatorIndex: 0,
Height: height,
Round: 0,
Timestamp: time.Now().UTC(),
Timestamp: time.Now().Round(0).UTC(),
Type: VoteTypePrecommit,
BlockID: blockID,
}

View File

@ -83,7 +83,7 @@ func TestAddVote(t *testing.T) {
Height: height,
Round: round,
Type: VoteTypePrevote,
Timestamp: time.Now().UTC(),
Timestamp: time.Now().Round(0).UTC(),
BlockID: BlockID{nil, PartSetHeader{}},
}
_, err := signAddVote(val0, vote, voteSet)
@ -113,7 +113,7 @@ func Test2_3Majority(t *testing.T) {
Height: height,
Round: round,
Type: VoteTypePrevote,
Timestamp: time.Now().UTC(),
Timestamp: time.Now().Round(0).UTC(),
BlockID: BlockID{nil, PartSetHeader{}},
}
// 6 out of 10 voted for nil.
@ -169,7 +169,7 @@ func Test2_3MajorityRedux(t *testing.T) {
ValidatorIndex: -1, // NOTE: must fill in
Height: height,
Round: round,
Timestamp: time.Now().UTC(),
Timestamp: time.Now().Round(0).UTC(),
Type: VoteTypePrevote,
BlockID: BlockID{blockHash, blockPartsHeader},
}
@ -264,7 +264,7 @@ func TestBadVotes(t *testing.T) {
ValidatorIndex: -1,
Height: height,
Round: round,
Timestamp: time.Now().UTC(),
Timestamp: time.Now().Round(0).UTC(),
Type: VoteTypePrevote,
BlockID: BlockID{nil, PartSetHeader{}},
}
@ -326,7 +326,7 @@ func TestConflicts(t *testing.T) {
ValidatorIndex: -1,
Height: height,
Round: round,
Timestamp: time.Now().UTC(),
Timestamp: time.Now().Round(0).UTC(),
Type: VoteTypePrevote,
BlockID: BlockID{nil, PartSetHeader{}},
}
@ -455,7 +455,7 @@ func TestMakeCommit(t *testing.T) {
ValidatorIndex: -1,
Height: height,
Round: round,
Timestamp: time.Now().UTC(),
Timestamp: time.Now().Round(0).UTC(),
Type: VoteTypePrecommit,
BlockID: BlockID{blockHash, blockPartsHeader},
}