aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/consensus-timestamp.go63
-rw-r--r--core/consensus-timestamp_test.go2
2 files changed, 39 insertions, 26 deletions
diff --git a/core/consensus-timestamp.go b/core/consensus-timestamp.go
index 833194b..a1ace97 100644
--- a/core/consensus-timestamp.go
+++ b/core/consensus-timestamp.go
@@ -24,32 +24,40 @@ import (
"github.com/dexon-foundation/dexon-consensus/core/types"
)
-// consensusTimestamp is for Concensus Timestamp Algorithm.
+// consensusTimestamp calculates a block's finalization timestamp. Notice that
+// the Finalization timestamps are increasing (but not strictly increasing).
+// Instance functions:
+// - processBlocks(blocks []*types.Block) error
+// called with blocks output from total ordering
+// - appendConfig(round uint64, config *types.Config) error
+// called when a new config is known
+// - synced() bool
+// called in sync mode
type consensusTimestamp struct {
- chainTimestamps []time.Time
+ timestampsOfChains []time.Time
- // This part keeps configs for each round.
+ // Stores number of chains for rounds.
numChainsOfRounds []uint32
numChainsBase uint64
// dMoment represents the genesis time.
dMoment time.Time
- // lastTimestamp represents previous assigned consensus timestamp.
+
+ // lastTimestamp is the previous assigned consensus timestamp.
lastTimestamp time.Time
}
var (
- // ErrTimestampNotIncrease would be reported if the timestamp is not strickly
- // increasing on the same chain.
+ // ErrTimestampNotIncrease for timestamp is not strictly increasing on one
+ // chain.
ErrTimestampNotIncrease = errors.New("timestamp is not increasing")
// ErrNoRoundConfig for no round config found.
ErrNoRoundConfig = errors.New("no round config found")
- // ErrConsensusTimestampRewind would be reported if the generated timestamp
- // is rewinded.
+ // ErrConsensusTimestampRewind for rewinding timestamp.
ErrConsensusTimestampRewind = errors.New("consensus timestamp rewind")
)
-// newConsensusTimestamp creates timestamper object.
+// newConsensusTimestamp creates consensus timestamp instance.
func newConsensusTimestamp(
dMoment time.Time, round uint64, numChains uint32) *consensusTimestamp {
@@ -58,10 +66,10 @@ func newConsensusTimestamp(
ts[i] = dMoment
}
return &consensusTimestamp{
- numChainsOfRounds: []uint32{numChains},
- numChainsBase: round,
- dMoment: dMoment,
- chainTimestamps: ts,
+ numChainsOfRounds: []uint32{numChains},
+ numChainsBase: round,
+ dMoment: dMoment,
+ timestampsOfChains: ts,
}
}
@@ -69,7 +77,6 @@ func newConsensusTimestamp(
// a config for round R, next time you can only append the config for round R+1.
func (ct *consensusTimestamp) appendConfig(
round uint64, config *types.Config) error {
-
if round != uint64(len(ct.numChainsOfRounds))+ct.numChainsBase {
return ErrRoundNotIncreasing
}
@@ -77,14 +84,14 @@ func (ct *consensusTimestamp) appendConfig(
return nil
}
-func (ct *consensusTimestamp) resizeChainTimetamps(numChain uint32) {
- l := uint32(len(ct.chainTimestamps))
+func (ct *consensusTimestamp) resizeTimetamps(numChain uint32) {
+ l := uint32(len(ct.timestampsOfChains))
if numChain > l {
for i := l; i < numChain; i++ {
- ct.chainTimestamps = append(ct.chainTimestamps, ct.dMoment)
+ ct.timestampsOfChains = append(ct.timestampsOfChains, ct.dMoment)
}
} else if numChain < l {
- ct.chainTimestamps = ct.chainTimestamps[:numChain]
+ ct.timestampsOfChains = ct.timestampsOfChains[:numChain]
}
}
@@ -96,30 +103,36 @@ func (ct *consensusTimestamp) processBlocks(blocks []*types.Block) (err error) {
// interleave with r-1 and r+1.
round := block.Position.Round
if ct.numChainsBase == round || ct.numChainsBase+1 == round {
- // Normal case, no need to modify chainTimestamps.
+ // Normal case, no need to modify timestampsOfChains.
} else if ct.numChainsBase+2 == round {
+ // Resize timestampsOfChains if block from r+2 comes, because the interleave
+ // of rounds must be less than 1. Resize the size to
+ // max(numChainsOfRounds[r+1], numChainsOfRounds[r+2]).
if len(ct.numChainsOfRounds) < 2 {
return ErrNoRoundConfig
}
ct.numChainsBase++
ct.numChainsOfRounds = ct.numChainsOfRounds[1:]
if ct.numChainsOfRounds[0] > ct.numChainsOfRounds[1] {
- ct.resizeChainTimetamps(ct.numChainsOfRounds[0])
+ ct.resizeTimetamps(ct.numChainsOfRounds[0])
} else {
- ct.resizeChainTimetamps(ct.numChainsOfRounds[1])
+ ct.resizeTimetamps(ct.numChainsOfRounds[1])
}
} else {
// Error if round < base or round > base + 2.
return ErrInvalidRoundID
}
- ts := ct.chainTimestamps[:ct.numChainsOfRounds[round-ct.numChainsBase]]
+ ts := ct.timestampsOfChains[:ct.numChainsOfRounds[round-ct.numChainsBase]]
if block.Finalization.Timestamp, err = getMedianTime(ts); err != nil {
return
}
- if block.Timestamp.Before(ct.chainTimestamps[block.Position.ChainID]) {
+ if block.Timestamp.Before(ct.timestampsOfChains[block.Position.ChainID]) {
return ErrTimestampNotIncrease
}
- ct.chainTimestamps[block.Position.ChainID] = block.Timestamp
+ ct.timestampsOfChains[block.Position.ChainID] = block.Timestamp
+ // If the finalization timestamp is before the last timestamp, set it to
+ // the last one. Notice that the finalization timestamps are increasing but
+ // not strictly increasing.
if block.Finalization.Timestamp.Before(ct.lastTimestamp) {
block.Finalization.Timestamp = ct.lastTimestamp
} else {
@@ -132,7 +145,7 @@ func (ct *consensusTimestamp) processBlocks(blocks []*types.Block) (err error) {
func (ct *consensusTimestamp) isSynced() bool {
numChain := ct.numChainsOfRounds[0]
for i := uint32(0); i < numChain; i++ {
- if ct.chainTimestamps[i].Equal(ct.dMoment) {
+ if ct.timestampsOfChains[i].Equal(ct.dMoment) {
return false
}
}
diff --git a/core/consensus-timestamp_test.go b/core/consensus-timestamp_test.go
index a093c12..bbc58a2 100644
--- a/core/consensus-timestamp_test.go
+++ b/core/consensus-timestamp_test.go
@@ -170,7 +170,7 @@ func (s *ConsensusTimestampTest) TestTimestampConfigChange() {
s.Require().NoError(err)
}
-func (s *ConsensusTimestampTest) TestRoundInterleave() {
+func (s *ConsensusTimestampTest) TestTimestampRoundInterleave() {
chainNum := 9
sigma := 100 * time.Millisecond
now := time.Now().UTC()