aboutsummaryrefslogtreecommitdiffstats
path: root/core/lattice-data.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/lattice-data.go')
-rw-r--r--core/lattice-data.go113
1 files changed, 60 insertions, 53 deletions
diff --git a/core/lattice-data.go b/core/lattice-data.go
index 6fe810a..f1ab2de 100644
--- a/core/lattice-data.go
+++ b/core/lattice-data.go
@@ -362,6 +362,35 @@ func (data *latticeData) addFinalizedBlock(block *types.Block) (err error) {
return
}
+// isBindTip checks if a block's fields should follow up its parent block.
+func (data *latticeData) isBindTip(
+ pos types.Position, tip *types.Block) (bindTip bool, err error) {
+ if tip == nil {
+ return
+ }
+ if pos.Round < tip.Position.Round {
+ err = ErrInvalidRoundID
+ return
+ }
+ tipConfig := data.getConfig(tip.Position.Round)
+ if tip.Timestamp.After(tipConfig.roundEndTime) {
+ if pos.Round == tip.Position.Round {
+ err = ErrRoundNotSwitch
+ return
+ }
+ if pos.Round == tip.Position.Round+1 {
+ bindTip = true
+ }
+ } else {
+ if pos.Round != tip.Position.Round {
+ err = ErrInvalidRoundID
+ return
+ }
+ bindTip = true
+ }
+ return
+}
+
// prepareBlock setups fields of a block based on its ChainID and Round,
// including:
// - Acks
@@ -375,7 +404,6 @@ func (data *latticeData) prepareBlock(b *types.Block) error {
config *latticeDataConfig
acks common.Hashes
bindTip bool
- chainTip *types.Block
)
if config = data.getConfig(b.Position.Round); config == nil {
return ErrUnknownRoundID
@@ -388,30 +416,16 @@ func (data *latticeData) prepareBlock(b *types.Block) error {
b.Position.Height = 0
b.ParentHash = common.Hash{}
// Decide valid timestamp range.
- homeChain := data.chains[b.Position.ChainID]
- if homeChain.tip != nil {
- chainTip = homeChain.tip
- if b.Position.Round < chainTip.Position.Round {
- return ErrInvalidRoundID
- }
- chainTipConfig := data.getConfig(chainTip.Position.Round)
- if chainTip.Timestamp.After(chainTipConfig.roundEndTime) {
- if b.Position.Round == chainTip.Position.Round {
- return ErrRoundNotSwitch
- }
- if b.Position.Round == chainTip.Position.Round+1 {
- bindTip = true
- }
- } else {
- if b.Position.Round != chainTip.Position.Round {
- return ErrInvalidRoundID
- }
- bindTip = true
- }
+ chainTip := data.chains[b.Position.ChainID].tip
+ if chainTip != nil {
// TODO(mission): find a way to prevent us to assign a witness height
// from Jurassic period.
b.Witness.Height = chainTip.Witness.Height
}
+ bindTip, err := data.isBindTip(b.Position, chainTip)
+ if err != nil {
+ return err
+ }
// For blocks with continuous round ID, assign timestamp range based on
// parent block and bound config.
if bindTip {
@@ -461,40 +475,48 @@ func (data *latticeData) prepareBlock(b *types.Block) error {
// - ParentHash and Height from parent block. If there is no valid parent block
// (ex. Newly added chain or bootstrap), these fields would be setup as
// genesis block.
-func (data *latticeData) prepareEmptyBlock(b *types.Block) {
+func (data *latticeData) prepareEmptyBlock(b *types.Block) (err error) {
// emptyBlock has no proposer.
b.ProposerID = types.NodeID{}
- var acks common.Hashes
// Reset fields to make sure we got these information from parent block.
b.Position.Height = 0
- b.Position.Round = 0
b.ParentHash = common.Hash{}
b.Timestamp = time.Time{}
// Decide valid timestamp range.
- homeChain := data.chains[b.Position.ChainID]
- if homeChain.tip != nil {
- chainTip := homeChain.tip
+ config := data.getConfig(b.Position.Round)
+ chainTip := data.chains[b.Position.ChainID].tip
+ bindTip, err := data.isBindTip(b.Position, chainTip)
+ if err != nil {
+ return
+ }
+ if bindTip {
b.ParentHash = chainTip.Hash
- chainTipConfig := data.getConfig(chainTip.Position.Round)
- if chainTip.Timestamp.After(chainTipConfig.roundEndTime) {
- b.Position.Round = chainTip.Position.Round + 1
- } else {
- b.Position.Round = chainTip.Position.Round
- }
b.Position.Height = chainTip.Position.Height + 1
- b.Timestamp = chainTip.Timestamp.Add(chainTipConfig.minBlockTimeInterval)
+ b.Timestamp = chainTip.Timestamp.Add(config.minBlockTimeInterval)
b.Witness.Height = chainTip.Witness.Height
b.Witness.Data = make([]byte, len(chainTip.Witness.Data))
copy(b.Witness.Data, chainTip.Witness.Data)
- acks = append(acks, chainTip.Hash)
+ b.Acks = common.NewSortedHashes(common.Hashes{chainTip.Hash})
+ } else {
+ b.Timestamp = config.roundBeginTime
}
- b.Acks = common.NewSortedHashes(acks)
+ return
}
// TODO(mission): make more abstraction for this method.
// nextHeight returns the next height of a chain.
-func (data *latticeData) nextPosition(chainID uint32) types.Position {
- return data.chains[chainID].nextPosition()
+func (data *latticeData) nextHeight(
+ round uint64, chainID uint32) (uint64, error) {
+ chainTip := data.chains[chainID].tip
+ bindTip, err := data.isBindTip(
+ types.Position{Round: round, ChainID: chainID}, chainTip)
+ if err != nil {
+ return 0, err
+ }
+ if bindTip {
+ return chainTip.Position.Height + 1, nil
+ }
+ return 0, nil
}
// findBlock seeks blocks in memory or db.
@@ -609,21 +631,6 @@ func (s *chainStatus) addBlock(b *types.Block) {
s.tip = b
}
-// TODO(mission): change back to nextHeight.
-// nextPosition returns a valid position for new block in this chain.
-func (s *chainStatus) nextPosition() types.Position {
- if s.tip == nil {
- return types.Position{
- ChainID: s.ID,
- Height: 0,
- }
- }
- return types.Position{
- ChainID: s.ID,
- Height: s.tip.Position.Height + 1,
- }
-}
-
// purgeBlock purges a block from cache, make sure this block is already saved
// in blockdb.
func (s *chainStatus) purgeBlock(b *types.Block) error {