@@ -41,7 +41,7 @@ bool OptimizerAgent::doOptimizedConsensus(block_id _blockId, uint64_t _lastBlock
41
41
}
42
42
43
43
44
- auto lastWinner = getLastWinner (_blockId);
44
+ auto lastWinner = getPreviousWinner (_blockId);
45
45
46
46
// if last time there was no winner (default block)
47
47
// we do not optimize
@@ -52,17 +52,41 @@ bool OptimizerAgent::doOptimizedConsensus(block_id _blockId, uint64_t _lastBlock
52
52
}
53
53
54
54
// redo full consensus each 17 blocks to
55
- // determine the winner. Othewise optimize
56
- return (uint64_t ) _blockId % (nodeCount + 1 ) != 0 ;
55
+ // determine the winner.
57
56
58
- }
57
+ if ((uint64_t )_blockId % (nodeCount + 1 ) == 0 ) {
58
+ return false ;
59
+ }
59
60
61
+ // optimize
62
+ return true ;
63
+ }
60
64
65
+ // get the schain index for block priority leader. Note that for convinience
66
+ // the priority leader is numbered from 0 to 15
61
67
uint64_t OptimizerAgent::getPriorityLeaderForBlock (uint64_t _nodeCount, block_id &_blockID) {
62
68
uint64_t priorityLeader;
63
69
64
- uint64_t seed;
70
+ if (doOptimizedConsensus (_blockID,
71
+ getSchain ()->getLastCommittedBlockTimeStamp ().getS ())) {
72
+ // in optimized consensus the priority leader is just the previous winner from this block_id minus 16
73
+ // we want the previous winner to win again
74
+ auto previousWinner = (uint64_t ) getSchain ()->getOptimizerAgent ()->getPreviousWinner (_blockID);
75
+ CHECK_STATE (previousWinner > 0 )
76
+ priorityLeader = previousWinner - 1 ;
77
+ } else {
78
+ // full consensus the priority leader is randomly selected for each block
79
+ // based on random seed
80
+ auto seed = calculateRandomSeedForConsensus (_blockID);
81
+ priorityLeader = (seed % _nodeCount);
82
+ }
65
83
84
+ CHECK_STATE (priorityLeader < _nodeCount);
85
+ return priorityLeader;
86
+ }
87
+
88
+ uint64_t OptimizerAgent::calculateRandomSeedForConsensus (const block_id &_blockID) const {
89
+ uint64_t seed;
66
90
if (_blockID <= 1 ) {
67
91
seed = 1 ;
68
92
} else {
@@ -72,26 +96,27 @@ uint64_t OptimizerAgent::getPriorityLeaderForBlock(uint64_t _nodeCount, block_id
72
96
BOOST_THROW_EXCEPTION (InvalidStateException (
73
97
" Can not read block " + to_string (_blockID - 1 ) + " from LevelDB" ,
74
98
__CLASS_NAME__ ));
75
- seed = *((uint64_t *) previousBlock->getHash ().data ());
76
- }
77
-
78
- priorityLeader = ((uint64_t ) seed) % _nodeCount;
79
99
80
- if (doOptimizedConsensus (_blockID,
81
- getSchain ()->getLastCommittedBlockTimeStamp ().getS ())) {
82
- priorityLeader = (uint64_t ) getSchain ()->getOptimizerAgent ()->getLastWinner (_blockID);
100
+ // now get the seed. In full consensus priority leader for the block id will be derived from it
101
+ if (getSchain ()->fastConsensusPatch (previousBlock->getTimeStampS ())) {
102
+ // for newer consensus, the nodes a given priority in round robin fashion
103
+ seed = (uint64_t ) _blockID;
104
+ } else {
105
+ // the legacy seed is not perfect since blockhash can be manipulated by block proposer
106
+ seed = *((uint64_t *) previousBlock->getHash ().data ());
107
+ }
83
108
}
84
- CHECK_STATE (priorityLeader <= _nodeCount);
85
- return priorityLeader;
109
+ return seed;
86
110
}
87
111
88
-
89
- schain_index OptimizerAgent::getLastWinner (block_id _blockId) {
90
- // first 16 blocks we do not know the winner
112
+ // will return the index for the proposer that won 16 blocks ago
113
+ schain_index OptimizerAgent::getPreviousWinner (block_id _blockId) {
114
+ // first 16 blocks we do not know the previous winner
91
115
if ((uint64_t ) _blockId <= getSchain ()->getNodeCount ()) {
92
116
return 0 ;
93
117
}
94
- auto block = getSchain ()->getBlock ((uint64_t ) _blockId - (uint64_t ) getSchain ()->getNodeCount ());
118
+ auto block =
119
+ getSchain ()->getBlock ((uint64_t ) _blockId - (uint64_t ) getSchain ()->getNodeCount ());
95
120
96
121
if (!block) {
97
122
return 0 ;
@@ -105,7 +130,7 @@ schain_index OptimizerAgent::skipSendingProposalToTheNetwork(block_id _blockId)
105
130
// if node chain index is not equal to the last winner
106
131
return (getSchain ()->getOptimizerAgent ()->doOptimizedConsensus (_blockId,
107
132
getSchain ()->getLastCommittedBlockTimeStamp ().getS ()) &&
108
- (getSchain ()->getOptimizerAgent ()->getLastWinner (_blockId) != getSchain ()->getSchainIndex ()));
133
+ (getSchain ()->getOptimizerAgent ()->getPreviousWinner (_blockId) != getSchain ()->getSchainIndex ()));
109
134
}
110
135
111
136
0 commit comments