github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/core/peer/peer.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package peer 18 19 import ( 20 "fmt" 21 "math" 22 "net" 23 "sync" 24 25 "github.com/hyperledger/fabric/common/configtx" 26 configtxapi "github.com/hyperledger/fabric/common/configtx/api" 27 configvaluesapi "github.com/hyperledger/fabric/common/configvalues" 28 mockconfigtx "github.com/hyperledger/fabric/common/mocks/configtx" 29 mockpolicies "github.com/hyperledger/fabric/common/mocks/policies" 30 "github.com/hyperledger/fabric/common/policies" 31 "github.com/hyperledger/fabric/core/comm" 32 "github.com/hyperledger/fabric/core/committer" 33 "github.com/hyperledger/fabric/core/committer/txvalidator" 34 "github.com/hyperledger/fabric/core/ledger" 35 "github.com/hyperledger/fabric/core/ledger/ledgermgmt" 36 "github.com/hyperledger/fabric/gossip/service" 37 mspmgmt "github.com/hyperledger/fabric/msp/mgmt" 38 "github.com/hyperledger/fabric/protos/common" 39 pb "github.com/hyperledger/fabric/protos/peer" 40 "github.com/hyperledger/fabric/protos/utils" 41 "github.com/op/go-logging" 42 "github.com/spf13/viper" 43 "google.golang.org/grpc" 44 ) 45 46 var peerLogger = logging.MustGetLogger("peer") 47 48 type chainSupport struct { 49 configtxapi.Manager 50 configvaluesapi.Application 51 ledger ledger.PeerLedger 52 } 53 54 func (cs *chainSupport) Ledger() ledger.PeerLedger { 55 return cs.ledger 56 } 57 58 // chain is a local struct to manage objects in a chain 59 type chain struct { 60 cs *chainSupport 61 cb *common.Block 62 committer committer.Committer 63 } 64 65 // chains is a local map of chainID->chainObject 66 var chains = struct { 67 sync.RWMutex 68 list map[string]*chain 69 }{list: make(map[string]*chain)} 70 71 //MockInitialize resets chains for test env 72 func MockInitialize() { 73 ledgermgmt.InitializeTestEnv() 74 chains.list = nil 75 chains.list = make(map[string]*chain) 76 chainInitializer = func(string) { return } 77 } 78 79 var chainInitializer func(string) 80 81 // Initialize sets up any chains that the peer has from the persistence. This 82 // function should be called at the start up when the ledger and gossip 83 // ready 84 func Initialize(init func(string)) { 85 chainInitializer = init 86 87 var cb *common.Block 88 var ledger ledger.PeerLedger 89 ledgermgmt.Initialize() 90 ledgerIds, err := ledgermgmt.GetLedgerIDs() 91 if err != nil { 92 panic(fmt.Errorf("Error in initializing ledgermgmt: %s", err)) 93 } 94 for _, cid := range ledgerIds { 95 peerLogger.Infof("Loading chain %s", cid) 96 if ledger, err = ledgermgmt.OpenLedger(cid); err != nil { 97 peerLogger.Warningf("Failed to load ledger %s(%s)", cid, err) 98 peerLogger.Debugf("Error while loading ledger %s with message %s. We continue to the next ledger rather than abort.", cid, err) 99 continue 100 } 101 if cb, err = getCurrConfigBlockFromLedger(ledger); err != nil { 102 peerLogger.Warningf("Failed to find config block on ledger %s(%s)", cid, err) 103 peerLogger.Debugf("Error while looking for config block on ledger %s with message %s. We continue to the next ledger rather than abort.", cid, err) 104 continue 105 } 106 // Create a chain if we get a valid ledger with config block 107 if err = createChain(cid, ledger, cb); err != nil { 108 peerLogger.Warningf("Failed to load chain %s(%s)", cid, err) 109 peerLogger.Debugf("Error reloading chain %s with message %s. We continue to the next chain rather than abort.", cid, err) 110 continue 111 } 112 113 InitChain(cid) 114 } 115 } 116 117 // Take care to initialize chain after peer joined, for example deploys system CCs 118 func InitChain(cid string) { 119 if chainInitializer != nil { 120 // Initialize chaincode, namely deploy system CC 121 peerLogger.Debugf("Init chain %s", cid) 122 chainInitializer(cid) 123 } 124 } 125 126 func getCurrConfigBlockFromLedger(ledger ledger.PeerLedger) (*common.Block, error) { 127 // Config blocks contain only 1 transaction, so we look for 1-tx 128 // blocks and check the transaction type 129 var envelope *common.Envelope 130 var tx *common.Payload 131 var block *common.Block 132 var err error 133 var currBlockNumber uint64 = math.MaxUint64 134 for currBlockNumber >= 0 { 135 if block, err = ledger.GetBlockByNumber(currBlockNumber); err != nil { 136 return nil, err 137 } 138 if block.Data != nil && len(block.Data.Data) == 1 { 139 if envelope, err = utils.ExtractEnvelope(block, 0); err != nil { 140 peerLogger.Warning("Failed to get Envelope from Block %d.", block.Header.Number) 141 currBlockNumber = block.Header.Number - 1 142 continue 143 } 144 if tx, err = utils.ExtractPayload(envelope); err != nil { 145 peerLogger.Warning("Failed to get Payload from Block %d.", block.Header.Number) 146 currBlockNumber = block.Header.Number - 1 147 continue 148 } 149 chdr, err := utils.UnmarshalChannelHeader(tx.Header.ChannelHeader) 150 if err != nil { 151 peerLogger.Warning("Failed to get ChannelHeader from Block %d, error %s.", block.Header.Number, err) 152 currBlockNumber = block.Header.Number - 1 153 continue 154 } 155 if chdr.Type == int32(common.HeaderType_CONFIG) { 156 return block, nil 157 } 158 } 159 currBlockNumber = block.Header.Number - 1 160 } 161 return nil, fmt.Errorf("Failed to find config block.") 162 } 163 164 // createChain creates a new chain object and insert it into the chains 165 func createChain(cid string, ledger ledger.PeerLedger, cb *common.Block) error { 166 167 configEnvelope, err := configtx.ConfigEnvelopeFromBlock(cb) 168 if err != nil { 169 return err 170 } 171 172 configtxInitializer := configtx.NewInitializer() 173 174 gossipEventer := service.GetGossipService().NewConfigEventer() 175 176 gossipCallbackWrapper := func(cm configtxapi.Manager) { 177 gossipEventer.ProcessConfigUpdate(&chainSupport{ 178 Manager: cm, 179 Application: configtxInitializer.ApplicationConfig(), 180 }) 181 } 182 183 configtxManager, err := configtx.NewManagerImpl( 184 configEnvelope, 185 configtxInitializer, 186 []func(cm configtxapi.Manager){gossipCallbackWrapper}, 187 ) 188 if err != nil { 189 return err 190 } 191 192 // TODO remove once all references to mspmgmt are gone from peer code 193 mspmgmt.XXXSetMSPManager(cid, configtxManager.MSPManager()) 194 195 cs := &chainSupport{ 196 Manager: configtxManager, 197 Application: configtxManager.ApplicationConfig(), // TODO, refactor as this is accessible through Manager 198 ledger: ledger, 199 } 200 201 c := committer.NewLedgerCommitter(ledger, txvalidator.NewTxValidator(cs)) 202 service.GetGossipService().InitializeChannel(cs.ChainID(), c) 203 204 chains.Lock() 205 defer chains.Unlock() 206 chains.list[cid] = &chain{ 207 cs: cs, 208 cb: cb, 209 committer: c, 210 } 211 return nil 212 } 213 214 // CreateChainFromBlock creates a new chain from config block 215 func CreateChainFromBlock(cb *common.Block) error { 216 cid, err := utils.GetChainIDFromBlock(cb) 217 if err != nil { 218 return err 219 } 220 var ledger ledger.PeerLedger 221 if ledger, err = createLedger(cid); err != nil { 222 return err 223 } 224 225 if err := ledger.Commit(cb); err != nil { 226 peerLogger.Errorf("Unable to get genesis block committed into the ledger, chainID %v", cid) 227 return err 228 } 229 return createChain(cid, ledger, cb) 230 } 231 232 // MockCreateChain used for creating a ledger for a chain for tests 233 // without havin to join 234 func MockCreateChain(cid string) error { 235 var ledger ledger.PeerLedger 236 var err error 237 if ledger, err = createLedger(cid); err != nil { 238 return err 239 } 240 241 i := mockconfigtx.Initializer{ 242 Resources: mockconfigtx.Resources{ 243 PolicyManagerVal: &mockpolicies.Manager{ 244 Policy: &mockpolicies.Policy{}, 245 }, 246 }, 247 } 248 249 chains.Lock() 250 defer chains.Unlock() 251 chains.list[cid] = &chain{ 252 cs: &chainSupport{ 253 ledger: ledger, 254 Manager: &mockconfigtx.Manager{Initializer: i}, 255 }, 256 } 257 258 return nil 259 } 260 261 // GetLedger returns the ledger of the chain with chain ID. Note that this 262 // call returns nil if chain cid has not been created. 263 func GetLedger(cid string) ledger.PeerLedger { 264 chains.RLock() 265 defer chains.RUnlock() 266 if c, ok := chains.list[cid]; ok { 267 return c.cs.ledger 268 } 269 return nil 270 } 271 272 // GetPolicyManager returns the policy manager of the chain with chain ID. Note that this 273 // call returns nil if chain cid has not been created. 274 func GetPolicyManager(cid string) policies.Manager { 275 chains.RLock() 276 defer chains.RUnlock() 277 if c, ok := chains.list[cid]; ok { 278 return c.cs.PolicyManager() 279 } 280 return nil 281 } 282 283 // GetCurrConfigBlock returns the cached config block of the specified chain. 284 // Note that this call returns nil if chain cid has not been created. 285 func GetCurrConfigBlock(cid string) *common.Block { 286 chains.RLock() 287 defer chains.RUnlock() 288 if c, ok := chains.list[cid]; ok { 289 return c.cb 290 } 291 return nil 292 } 293 294 // SetCurrConfigBlock sets the current config block of the specified chain 295 func SetCurrConfigBlock(block *common.Block, cid string) error { 296 chains.Lock() 297 defer chains.Unlock() 298 if c, ok := chains.list[cid]; ok { 299 c.cb = block 300 // TODO: Change MSP config 301 // c.mspmgr.Reconfig(block) 302 303 // TODO: Change gossip configs 304 return nil 305 } 306 return fmt.Errorf("Chain %s doesn't exist on the peer", cid) 307 } 308 309 // All ledgers are located under `peer.fileSystemPath` 310 func createLedger(cid string) (ledger.PeerLedger, error) { 311 var ledger ledger.PeerLedger 312 if ledger = GetLedger(cid); ledger != nil { 313 return ledger, nil 314 } 315 return ledgermgmt.CreateLedger(cid) 316 } 317 318 // NewPeerClientConnection Returns a new grpc.ClientConn to the configured local PEER. 319 func NewPeerClientConnection() (*grpc.ClientConn, error) { 320 return NewPeerClientConnectionWithAddress(viper.GetString("peer.address")) 321 } 322 323 // GetLocalIP returns the non loopback local IP of the host 324 func GetLocalIP() string { 325 addrs, err := net.InterfaceAddrs() 326 if err != nil { 327 return "" 328 } 329 for _, address := range addrs { 330 // check the address type and if it is not a loopback then display it 331 if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { 332 if ipnet.IP.To4() != nil { 333 return ipnet.IP.String() 334 } 335 } 336 } 337 return "" 338 } 339 340 // NewPeerClientConnectionWithAddress Returns a new grpc.ClientConn to the configured local PEER. 341 func NewPeerClientConnectionWithAddress(peerAddress string) (*grpc.ClientConn, error) { 342 if comm.TLSEnabled() { 343 return comm.NewClientConnectionWithAddress(peerAddress, true, true, comm.InitTLSForPeer()) 344 } 345 return comm.NewClientConnectionWithAddress(peerAddress, true, false, nil) 346 } 347 348 // GetChannelsInfo returns an array with information about all channels for 349 // this peer 350 func GetChannelsInfo() []*pb.ChannelInfo { 351 // array to store metadata for all channels 352 var channelInfoArray []*pb.ChannelInfo 353 354 chains.RLock() 355 defer chains.RUnlock() 356 for key := range chains.list { 357 channelInfo := &pb.ChannelInfo{ChannelId: key} 358 359 // add this specific chaincode's metadata to the array of all chaincodes 360 channelInfoArray = append(channelInfoArray, channelInfo) 361 } 362 363 return channelInfoArray 364 } 365 366 // GetPolicyManagerMgmt returns a special PolicyManager whose 367 // only function is to give access to the policy manager of 368 // a given channel. If the channel does not exists then, 369 // it returns nil. 370 // The only method implemented is therefore 'Manager'. 371 func GetPolicyManagerMgmt() policies.Manager { 372 return &policyManagerMgmt{} 373 } 374 375 type policyManagerMgmt struct{} 376 377 func (c *policyManagerMgmt) GetPolicy(id string) (policies.Policy, bool) { 378 panic("implement me") 379 } 380 381 // Manager returns the policy manager associated to a channel 382 // specified by a path of length 1 that has the name of the channel as the only 383 // coordinate available. 384 // If the path has length different from 1, then the method returns (nil, false). 385 // If the channel does not exists, then the method returns (nil, false) 386 // Nothing is created. 387 func (c *policyManagerMgmt) Manager(path []string) (policies.Manager, bool) { 388 if len(path) != 1 { 389 return nil, false 390 } 391 392 policyManager := GetPolicyManager(path[0]) 393 return policyManager, policyManager != nil 394 } 395 396 func (c *policyManagerMgmt) BasePath() string { 397 panic("implement me") 398 } 399 400 func (c *policyManagerMgmt) PolicyNames() []string { 401 panic("implement me") 402 }