@@ -203,7 +203,7 @@ func (c *Controller) ValidateProposal(rcBuildHeight uint64, qc *lib.QuorumCertif
203203 return
204204 }
205205 // play the block against the state machine to generate a block result
206- blockResult , err = c .ApplyAndValidateBlock (block , false )
206+ blockResult , err = c .ApplyAndValidateBlock (block , c . LastValidatorSet [ c . ChainHeight ()][ c . Config . ChainId ], false )
207207 if err != nil {
208208 // exit with error
209209 return
@@ -244,7 +244,7 @@ func (c *Controller) CommitCertificate(qc *lib.QuorumCertificate, block *lib.Blo
244244 // reset the FSM to ensure stale proposal validations don't come into play
245245 c .FSM .Reset ()
246246 // apply the block against the state machine
247- blockResult , err = c .ApplyAndValidateBlock (block , true )
247+ blockResult , err = c .ApplyAndValidateBlock (block , c . LastValidatorSet [ c . ChainHeight ()][ c . Config . ChainId ], true )
248248 if err != nil {
249249 // exit with error
250250 return
@@ -284,6 +284,8 @@ func (c *Controller) CommitCertificate(qc *lib.QuorumCertificate, block *lib.Blo
284284 c .log .Infof ("Committed block %s at H:%d 🔒" , lib .BytesToTruncatedString (qc .BlockHash ), block .BlockHeader .Height )
285285 // set up the finite state machine for the next height
286286 c .FSM , err = fsm .New (c .Config , storeI , c .Metrics , c .log )
287+ // set the reference to lastCertificate on the new FSM
288+ c .FSM .LastValidatorSet = c .LastValidatorSet
287289 if err != nil {
288290 // exit with error
289291 return err
@@ -300,10 +302,15 @@ func (c *Controller) CommitCertificate(qc *lib.QuorumCertificate, block *lib.Blo
300302 c .Mempool .FSM .Reset ()
301303 // update telemetry (using proper defer to ensure time.Since is evaluated at defer execution)
302304 defer c .UpdateTelemetry (qc , block , time .Since (start ))
303- // publish the root chain info to the nested chain subscribers
304- for _ , id := range c .RCManager .ChainIds () {
305+ // publish root chain information to all nested chain subscribers.
306+ // Currently using hardcoded chain IDs (1, 2) instead of dynamically fetching IDs
307+ // from RCManager since only these two chains exist. This will be updated to use
308+ // dynamic chain discovery when additional chains are added.
309+ // TODO: Optimize rcManager publishing for subchains (it should publish to themselves too by default)
310+ // for _, id := range c.RCManager.ChainIds() {
311+ for _ , id := range []uint64 {1 , 2 } {
305312 // get the root chain info
306- info , e := c .FSM .LoadRootChainInfo (id , 0 )
313+ info , e := c .FSM .LoadRootChainInfo (id , 0 , c . LastValidatorSet [ c . ChainHeight ()][ id ] )
307314 if e != nil {
308315 // don't log 'no-validators' error as this is possible
309316 if e .Error () != lib .ErrNoValidators ().Error () {
@@ -313,9 +320,17 @@ func (c *Controller) CommitCertificate(qc *lib.QuorumCertificate, block *lib.Blo
313320 }
314321 // set the timestamp
315322 info .Timestamp = ts
323+ // save current validator set for the next height
324+ valSet , _ := c .FSM .GetCommitteeMembers (id )
325+ if _ , found := c .LastValidatorSet [c .ChainHeight ()+ 1 ]; ! found {
326+ c .LastValidatorSet [c .ChainHeight ()+ 1 ] = make (map [uint64 ]* lib.ValidatorSet )
327+ }
328+ c .LastValidatorSet [c .ChainHeight ()+ 1 ][id ] = & valSet
316329 // publish root chain information
317330 go c .RCManager .Publish (id , info )
318331 }
332+ // remove older validator set heights
333+ delete (c .LastValidatorSet , c .ChainHeight ()- 2 )
319334 // exit
320335 return
321336}
@@ -339,7 +354,7 @@ func (c *Controller) CommitCertificateParallel(qc *lib.QuorumCertificate, block
339354 // reset the FSM to ensure stale proposal validations don't come into play
340355 c .FSM .Reset ()
341356 // apply the block against the state machine
342- blockResult , err = c .ApplyAndValidateBlock (block , true )
357+ blockResult , err = c .ApplyAndValidateBlock (block , c . LastValidatorSet [ c . ChainHeight ()][ c . Config . ChainId ], true )
343358 if err != nil {
344359 // exit with error
345360 return
@@ -395,8 +410,18 @@ func (c *Controller) CommitCertificateParallel(qc *lib.QuorumCertificate, block
395410 }
396411 // publish the root chain info to the nested chain subscribers
397412 for _ , id := range c .RCManager .ChainIds () {
413+ // get latest validator set
414+ valSet , err := c .FSM .GetCommitteeMembers (id )
415+ if err != nil {
416+ return err
417+ }
418+ // TODO handle err
419+ if _ , found := c .LastValidatorSet [c .ChainHeight ()+ 1 ]; ! found {
420+ c .LastValidatorSet [c .ChainHeight ()+ 1 ] = make (map [uint64 ]* lib.ValidatorSet )
421+ }
422+ c .LastValidatorSet [c .ChainHeight ()+ 1 ][id ] = & valSet
398423 // get the root chain info
399- info , e := c .FSM .LoadRootChainInfo (id , 0 )
424+ info , e := c .FSM .LoadRootChainInfo (id , 0 , c . LastValidatorSet [ c . ChainHeight ()][ id ] )
400425 if e != nil {
401426 // don't log 'no-validators' error as this is possible
402427 if e .Error () != lib .ErrNoValidators ().Error () {
@@ -445,7 +470,7 @@ func (c *Controller) CommitCertificateParallel(qc *lib.QuorumCertificate, block
445470// INTERNAL HELPERS BELOW
446471
447472// ApplyAndValidateBlock() plays the block against the state machine which returns a result that is compared against the candidate block header
448- func (c * Controller ) ApplyAndValidateBlock (block * lib.Block , commit bool ) (b * lib.BlockResult , err lib.ErrorI ) {
473+ func (c * Controller ) ApplyAndValidateBlock (block * lib.Block , lastValidatorSet * lib. ValidatorSet , commit bool ) (b * lib.BlockResult , err lib.ErrorI ) {
449474 // define convenience variables for the block header, hash, and height
450475 candidate , candidateHash , candidateHeight := block .BlockHeader , lib .BytesToString (block .BlockHeader .Hash ), block .BlockHeader .Height
451476 // check the last qc in the candidate and set it in the ephemeral indexer to prepare for block application
@@ -456,7 +481,7 @@ func (c *Controller) ApplyAndValidateBlock(block *lib.Block, commit bool) (b *li
456481 // log the start of 'apply block'
457482 c .log .Debugf ("Applying block %s for height %d" , candidateHash [:20 ], candidateHeight )
458483 // apply the block against the state machine
459- compare , txResults , _ , failed , err := c .FSM .ApplyBlock (context .Background (), block , false )
484+ compare , txResults , _ , failed , err := c .FSM .ApplyBlock (context .Background (), block , lastValidatorSet , false )
460485 if err != nil {
461486 // exit with error
462487 return
0 commit comments