diff --git a/core/service/blockMainService.go b/core/service/blockMainService.go index 4ad5cd2b0..fbd3e94c0 100644 --- a/core/service/blockMainService.go +++ b/core/service/blockMainService.go @@ -400,14 +400,6 @@ func (bs *BlockService) PushBlock(previousBlock, block *model.Block, broadcast, blocker.BlockErr, "DuplicateBlockPool", ) } - - block.CumulativeDifficulty, err = bs.BlocksmithStrategy.CalculateCumulativeDifficulty(previousBlock, block) - if err != nil { - return blocker.NewBlocker( - blocker.BlockErr, - fmt.Sprintf("CalculateCummulativeDifficultyError:%v", err), - ) - } } // start db transaction here @@ -449,12 +441,6 @@ func (bs *BlockService) PushBlock(previousBlock, block *model.Block, broadcast, return blocker.NewBlocker(blocker.BlockErr, err.Error()) } - blockInsertQuery, blockInsertValue := bs.BlockQuery.InsertBlock(block) - err = bs.QueryExecutor.ExecuteTransaction(blockInsertQuery, blockInsertValue...) - if err != nil { - bs.queryAndCacheRollbackProcess("") - return err - } var transactionIDs = make([]int64, len(block.GetTransactions())) mempoolMap, err = bs.MempoolService.GetMempoolTransactions() if err != nil { @@ -558,7 +544,6 @@ func (bs *BlockService) PushBlock(previousBlock, block *model.Block, broadcast, // when start smithing from a block with height > 0, since SortedBlocksmiths are computed after a block is pushed, // for the first block that is pushed, we don't know who are the blocksmith to be rewarded // sort blocksmiths for current block - activeRegistries, scoreSum, err := bs.NodeRegistrationService.GetActiveRegistryNodeWithTotalParticipationScore() if err != nil { bs.queryAndCacheRollbackProcess("") @@ -605,6 +590,23 @@ func (bs *BlockService) PushBlock(previousBlock, block *model.Block, broadcast, } } } + + if block.Height > 0 { + block.CumulativeDifficulty, err = bs.BlocksmithStrategy.CalculateCumulativeDifficulty(previousBlock, block) + if err != nil { + return blocker.NewBlocker( + blocker.BlockErr, + fmt.Sprintf("CalculateCummulativeDifficultyError:%v", err), + ) + } + } + + blockInsertQuery, blockInsertValue := bs.BlockQuery.InsertBlock(block) + err = bs.QueryExecutor.ExecuteTransaction(blockInsertQuery, blockInsertValue...) + if err != nil { + bs.queryAndCacheRollbackProcess("") + return err + } // nodeRegistryProcess precess to admit & expel node registry nodeAdmissionTimestamp, err := bs.nodeRegistryProcess(block) if err != nil { diff --git a/core/smith/strategy/blocksmithStrategyMain.go b/core/smith/strategy/blocksmithStrategyMain.go index d465fe9f6..20eb2b7b3 100644 --- a/core/smith/strategy/blocksmithStrategyMain.go +++ b/core/smith/strategy/blocksmithStrategyMain.go @@ -40,7 +40,6 @@ type ( candidates []Candidate me Candidate lastBlockHash []byte - lastBlockEstimatedPersistTime int64 rng *crypto.RandomNumberGenerator } ) @@ -86,11 +85,6 @@ func (bss *BlocksmithStrategyMain) WillSmith(prevBlock *model.Block) (int64, err if err != nil { return blocksmithIndex, err } - // reset previousBlockEstimatedPersistTime - bss.lastBlockEstimatedPersistTime, err = bss.estimatePreviousBlockPersistTime(prevBlock) - if err != nil { - return blocksmithIndex, err - } } if len(bss.candidates) > 0 { lastCandidate = bss.candidates[len(bss.candidates)-1] @@ -189,12 +183,16 @@ func (bss *BlocksmithStrategyMain) AddCandidate(prevBlock *model.Block) error { } activeNodeRegistryCount := len(activeNodeRegistry) - round, err := bss.GetSmithingRound(&model.Block{Timestamp: bss.lastBlockEstimatedPersistTime}, &model.Block{Timestamp: now}) + round, err := bss.GetSmithingRound(prevBlock, &model.Block{Timestamp: now}) if err != nil { return err } currCandidateCount := len(bss.candidates) newCandidateCount := currCandidateCount + lastBlockEstimatedPersistTime, err := bss.estimatePreviousBlockPersistTime(prevBlock) + if err != nil { + return err + } for i := 0; i < round-currCandidateCount; i++ { var ( idx int @@ -206,7 +204,7 @@ func (bss *BlocksmithStrategyMain) AddCandidate(prevBlock *model.Block) error { NodeID: activeNodeRegistry[idx].Node.GetNodeID(), NodePublicKey: activeNodeRegistry[idx].Node.GetNodePublicKey(), } - startTime := bss.lastBlockEstimatedPersistTime + + startTime := lastBlockEstimatedPersistTime + bss.Chaintype.GetSmithingPeriod() + int64(newCandidateCount)*bss.Chaintype.GetBlocksmithTimeGap() expiryTime := startTime + bss.Chaintype.GetBlocksmithNetworkTolerance() + bss.Chaintype.GetBlocksmithBlockCreationTime() candidate = Candidate{ @@ -226,12 +224,14 @@ func (bss *BlocksmithStrategyMain) AddCandidate(prevBlock *model.Block) error { } func (bss *BlocksmithStrategyMain) CalculateCumulativeDifficulty(prevBlock, block *model.Block) (string, error) { - round, err := bss.GetSmithingRound(prevBlock, block) + // all blocksmith up to current blocksmith + blocksmiths, err := bss.GetBlocksBlocksmiths(prevBlock, block) if err != nil { return "", err } prevCummulativeDiff, _ := new(big.Int).SetString(prevBlock.GetCumulativeDifficulty(), 10) - currentCumulativeDifficulty := new(big.Int).SetInt64(constant.CumulativeDifficultyDivisor / int64(round)) + currentCumulativeDifficulty := new(big.Int).SetInt64(constant.CumulativeDifficultyDivisor / int64(len(blocksmiths))) + newCummulativeDifficulty := new(big.Int).Add(prevCummulativeDiff, currentCumulativeDifficulty) return newCummulativeDifficulty.String(), nil } @@ -272,7 +272,7 @@ func (bss *BlocksmithStrategyMain) IsBlockValid(prevBlock, block *model.Block) e for i := 0; i < len(validRandomNumbers); i++ { idx = bss.convertRandomNumberToIndex(validRandomNumbers[i], int64(len(activeNodeRegistry))) if bytes.Equal(activeNodeRegistry[idx].Node.NodePublicKey, block.BlocksmithPublicKey) { - startTime, endTime, err := bss.getValidBlockCreationTime(prevBlock, round-(len(validRandomNumbers)-i)) + startTime, endTime, err := bss.getValidBlockCreationTime(prevBlock, round-len(validRandomNumbers)+(i+1)) if err != nil { return err } @@ -369,6 +369,8 @@ func (bss *BlocksmithStrategyMain) GetBlocksBlocksmiths(previousBlock, block *mo if err != nil { return nil, err } + var blocksmithIndex = -1 + for i := 0; i < round; i++ { randomNumber := rng.Next() skippedNodeIdx := bss.convertRandomNumberToIndex(randomNumber, int64(len(activeNodeRegistry))) @@ -379,19 +381,13 @@ func (bss *BlocksmithStrategyMain) GetBlocksBlocksmiths(previousBlock, block *mo }) isValidBlocksmith := bytes.Equal(activeNodeRegistry[skippedNodeIdx].Node.GetNodePublicKey(), block.GetBlocksmithPublicKey()) if isValidBlocksmith { - startTime, endTime, err := bss.getValidBlockPersistTime(previousBlock, i+1) - if err != nil { - return nil, err - } - if block.GetTimestamp() >= startTime && block.GetTimestamp() < endTime { - break - } + blocksmithIndex = i } - if i == round-1 && !isValidBlocksmith { + if i == round-1 && blocksmithIndex < 0 { return nil, blocker.NewBlocker(blocker.ValidationErr, "GetBlocksBlocksmith:BlocksmithNotInCandidates") } } - return result, nil + return result[:blocksmithIndex+1], nil } func (bss *BlocksmithStrategyMain) GetSmithingIndex( @@ -407,7 +403,11 @@ func (bss *BlocksmithStrategyMain) GetSmithingIndex( return 0, err } - timeGap := block.GetTimestamp() - previousBlock.GetTimestamp() + previousBlockEstimatedPersistTime, err := bss.estimatePreviousBlockPersistTime(previousBlock) + if err != nil { + return 0, err + } + timeGap := block.GetTimestamp() - previousBlockEstimatedPersistTime if timeGap < bss.Chaintype.GetSmithingPeriod()+bss.Chaintype.GetBlocksmithTimeGap() { // first blocksmith, validate if blocksmith public key is valid randomNumber := rng.Next() diff --git a/core/smith/strategy/blocksmithStrategyMain_test.go b/core/smith/strategy/blocksmithStrategyMain_test.go index 7530c870a..9c479e7ab 100644 --- a/core/smith/strategy/blocksmithStrategyMain_test.go +++ b/core/smith/strategy/blocksmithStrategyMain_test.go @@ -262,6 +262,21 @@ func TestBlocksmithStrategyMain_GetBlocksBlocksmiths(t *testing.T) { NodePublicKey: mockNodeRegistries[3].Node.NodePublicKey, Score: big.NewInt(mockNodeRegistries[3].ParticipationScore), }, + { + NodeID: mockNodeRegistries[3].Node.NodeID, + NodePublicKey: mockNodeRegistries[3].Node.NodePublicKey, + Score: big.NewInt(mockNodeRegistries[3].ParticipationScore), + }, + { + NodeID: mockNodeRegistries[3].Node.NodeID, + NodePublicKey: mockNodeRegistries[3].Node.NodePublicKey, + Score: big.NewInt(mockNodeRegistries[3].ParticipationScore), + }, + { + NodeID: mockNodeRegistries[3].Node.NodeID, + NodePublicKey: mockNodeRegistries[3].Node.NodePublicKey, + Score: big.NewInt(mockNodeRegistries[3].ParticipationScore), + }, }, wantErr: false, },