@@ -18,6 +18,7 @@ import (
1818 "sync/atomic"
1919 "time"
2020
21+ "github.com/hyperledger/fabric-protos-go-apiv2/common"
2122 "github.com/hyperledger/fabric-protos-go-apiv2/orderer"
2223 "github.com/hyperledger/fabric-x-common/common/policies"
2324 "github.com/hyperledger/fabric-x-orderer/common/configstore"
@@ -26,6 +27,8 @@ import (
2627 "github.com/hyperledger/fabric-x-orderer/config"
2728 "github.com/hyperledger/fabric-x-orderer/node"
2829 nodeconfig "github.com/hyperledger/fabric-x-orderer/node/config"
30+ "github.com/hyperledger/fabric-x-orderer/node/delivery"
31+ "github.com/hyperledger/fabric-x-orderer/node/ledger"
2932 protos "github.com/hyperledger/fabric-x-orderer/node/protos/comm"
3033)
3134
@@ -34,6 +37,11 @@ type Net interface {
3437 Address () string
3538}
3639
40+ type ConfigPuller interface {
41+ PullConfigBlocks () <- chan * common.Block
42+ Stop ()
43+ }
44+
3745type Router struct {
3846 mapper ShardMapper
3947 net Net
@@ -46,6 +54,7 @@ type Router struct {
4654 stopChan chan struct {}
4755 configStore * configstore.Store
4856 configSubmitter ConfigurationSubmitter
57+ configPuller ConfigPuller
4958}
5059
5160func NewRouter (config * nodeconfig.RouterNodeConfig , logger types.Logger ) * Router {
@@ -81,13 +90,43 @@ func NewRouter(config *nodeconfig.RouterNodeConfig, logger types.Logger) *Router
8190 configSubmitter := NewConfigSubmitter (config .Consenter .Endpoint , tlsCAsOfConsenter ,
8291 config .TLSCertificateFile , config .TLSPrivateKeyFile , logger )
8392
93+ configStore , err := configstore .NewStore (config .ConfigStorePath )
94+ if err != nil {
95+ logger .Panicf ("Failed creating router config store: %s" , err )
96+ }
97+
98+ seekInfo := NextSeekInfoFromConfigStore (configStore , logger )
99+
100+ // TODO - pull cofig blocks from all consenter nodes, not only the one in party
101+ configPuller := delivery .NewConsensusConfigPuller (config , logger , seekInfo )
102+
84103 verifier := createVerifier (config )
85104
86- r := createRouter (shardIDs , batcherEndpoints , tlsCAsOfBatchers , config , logger , verifier , configSubmitter )
105+ r := createRouter (shardIDs , batcherEndpoints , tlsCAsOfBatchers , config , logger , configStore , verifier , configSubmitter , configPuller )
87106 r .init ()
88107 return r
89108}
90109
110+ // NextSeekInfoFromConfigStore creates a SeekInfo to start pulling config blocks from consensus, based on the last connfig block stored in the config store.
111+ func NextSeekInfoFromConfigStore (configStore * configstore.Store , logger types.Logger ) * orderer.SeekInfo {
112+ lastBlock , err := configStore .Last ()
113+ if err != nil {
114+ logger .Panicf ("Failed getting last config block from config store: %s" , err )
115+ }
116+
117+ // check if last block is genesis block
118+ if lastBlock .GetHeader ().GetNumber () == 0 {
119+ return delivery .NextSeekInfo (1 )
120+ }
121+
122+ ordererBlockMetadata := lastBlock .Metadata .Metadata [common .BlockMetadataIndex_ORDERER ]
123+ _ , _ , _ , lastDecisionNumber , _ , _ , _ , err := ledger .AssemblerBlockMetadataFromBytes (ordererBlockMetadata )
124+ if err != nil {
125+ logger .Panicf ("Failed extracting decision number from last config block: %s" , err )
126+ }
127+ return delivery .NextSeekInfo (uint64 (lastDecisionNumber ) + 1 )
128+ }
129+
91130func (r * Router ) StartRouterService () <- chan struct {} {
92131 srv := node .CreateGRPCRouter (r .routerNodeConfig )
93132
@@ -108,6 +147,8 @@ func (r *Router) StartRouterService() <-chan struct{} {
108147
109148 r .configSubmitter .Start ()
110149
150+ go r .pullAndProcessConfigBlocks ()
151+
111152 return stop
112153}
113154
@@ -184,7 +225,7 @@ func (r *Router) Deliver(server orderer.AtomicBroadcast_DeliverServer) error {
184225 return fmt .Errorf ("not implemented" )
185226}
186227
187- func createRouter (shardIDs []types.ShardID , batcherEndpoints map [types.ShardID ]string , batcherRootCAs map [types.ShardID ][][]byte , rconfig * nodeconfig.RouterNodeConfig , logger types.Logger , verifier * requestfilter.RulesVerifier , configSubmitter ConfigurationSubmitter ) * Router {
228+ func createRouter (shardIDs []types.ShardID , batcherEndpoints map [types.ShardID ]string , batcherRootCAs map [types.ShardID ][][]byte , rconfig * nodeconfig.RouterNodeConfig , logger types.Logger , configStore * configstore. Store , verifier * requestfilter.RulesVerifier , configSubmitter ConfigurationSubmitter , configPuller ConfigPuller ) * Router {
188229 if rconfig .NumOfConnectionsForBatcher == 0 {
189230 rconfig .NumOfConnectionsForBatcher = config .DefaultRouterParams .NumberOfConnectionsPerBatcher
190231 }
@@ -193,11 +234,6 @@ func createRouter(shardIDs []types.ShardID, batcherEndpoints map[types.ShardID]s
193234 rconfig .NumOfgRPCStreamsPerConnection = config .DefaultRouterParams .NumberOfStreamsPerConnection
194235 }
195236
196- configStore , err := configstore .NewStore (rconfig .ConfigStorePath )
197- if err != nil {
198- logger .Panicf ("Failed creating router config store: %s" , err )
199- }
200-
201237 r := & Router {
202238 mapper : MapperCRC64 {
203239 Logger : logger ,
@@ -211,6 +247,7 @@ func createRouter(shardIDs []types.ShardID, batcherEndpoints map[types.ShardID]s
211247 stopChan : make (chan struct {}),
212248 configStore : configStore ,
213249 configSubmitter : configSubmitter ,
250+ configPuller : configPuller ,
214251 }
215252
216253 for _ , shardId := range shardIDs {
@@ -363,6 +400,37 @@ func createVerifier(config *nodeconfig.RouterNodeConfig) *requestfilter.RulesVer
363400 return rv
364401}
365402
403+ // pullAndProcessConfigBlocks pulls config blocks from consensus and processes them. this function should be run as a goroutine.
404+ func (r * Router ) pullAndProcessConfigBlocks () {
405+ configBlocksChan := r .configPuller .PullConfigBlocks ()
406+ defer func () {
407+ r .configPuller .Stop ()
408+ r .logger .Infof ("Stopped config puller" )
409+ }()
410+
411+ for {
412+ select {
413+ case configBlock , ok := <- configBlocksChan :
414+ if ! ok {
415+ r .logger .Infof ("Config blocks channel closed, stopping config blocks processing" )
416+ return
417+ }
418+ r .logger .Infof ("Received new config block from consensus with block number %d" , configBlock .GetHeader ().GetNumber ())
419+
420+ // TODO process the config block. store in config store and apply.
421+ if err := r .configStore .Add (configBlock ); err != nil {
422+ r .logger .Errorf ("Failed adding config block to config store: %s" , err )
423+ continue
424+ }
425+ r .logger .Infof ("Added config block %d to config store" , configBlock .GetHeader ().GetNumber ())
426+
427+ case <- r .stopChan :
428+ r .logger .Infof ("Stopping config blocks processing" )
429+ return
430+ }
431+ }
432+ }
433+
366434// IsAllStreamsOK checks that all the streams accross all shard-routers are non-faulty.
367435// Use for testing only.
368436func (r * Router ) IsAllStreamsOK () bool {
@@ -384,3 +452,13 @@ func (r *Router) IsAllConnectionsDown() bool {
384452 }
385453 return true
386454}
455+
456+ // GetConfigStoreSize returns the number of config blocks stored in the config store.
457+ // Use for testing only.
458+ func (r * Router ) GetConfigStoreSize () int {
459+ list , err := r .configStore .ListBlockNumbers ()
460+ if err != nil {
461+ r .logger .Panicf ("Failed listing config store block numbers: %s" , err )
462+ }
463+ return len (list )
464+ }
0 commit comments