github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/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  	"errors"
    21  	"fmt"
    22  	"net"
    23  	"sync"
    24  
    25  	"github.com/golang/protobuf/proto"
    26  	"github.com/hyperledger/fabric/common/config"
    27  	"github.com/hyperledger/fabric/common/configtx"
    28  	configtxapi "github.com/hyperledger/fabric/common/configtx/api"
    29  	configtxtest "github.com/hyperledger/fabric/common/configtx/test"
    30  	"github.com/hyperledger/fabric/common/flogging"
    31  	mockconfigtx "github.com/hyperledger/fabric/common/mocks/configtx"
    32  	mockpolicies "github.com/hyperledger/fabric/common/mocks/policies"
    33  	"github.com/hyperledger/fabric/common/policies"
    34  	"github.com/hyperledger/fabric/core/comm"
    35  	"github.com/hyperledger/fabric/core/committer"
    36  	"github.com/hyperledger/fabric/core/committer/txvalidator"
    37  	"github.com/hyperledger/fabric/core/ledger"
    38  	"github.com/hyperledger/fabric/core/ledger/ledgermgmt"
    39  	"github.com/hyperledger/fabric/gossip/api"
    40  	"github.com/hyperledger/fabric/gossip/service"
    41  	"github.com/hyperledger/fabric/msp"
    42  	mspmgmt "github.com/hyperledger/fabric/msp/mgmt"
    43  	"github.com/hyperledger/fabric/protos/common"
    44  	mspprotos "github.com/hyperledger/fabric/protos/msp"
    45  	pb "github.com/hyperledger/fabric/protos/peer"
    46  	"github.com/hyperledger/fabric/protos/utils"
    47  	"github.com/spf13/viper"
    48  	"google.golang.org/grpc"
    49  )
    50  
    51  var peerLogger = flogging.MustGetLogger("peer")
    52  
    53  var peerServer comm.GRPCServer
    54  
    55  // singleton instance to manage CAs for the peer across channel config changes
    56  var rootCASupport = comm.GetCASupport()
    57  
    58  type chainSupport struct {
    59  	configtxapi.Manager
    60  	config.Application
    61  	ledger ledger.PeerLedger
    62  }
    63  
    64  func (cs *chainSupport) Ledger() ledger.PeerLedger {
    65  	return cs.ledger
    66  }
    67  
    68  func (cs *chainSupport) GetMSPIDs(cid string) []string {
    69  	return GetMSPIDs(cid)
    70  }
    71  
    72  // chain is a local struct to manage objects in a chain
    73  type chain struct {
    74  	cs        *chainSupport
    75  	cb        *common.Block
    76  	committer committer.Committer
    77  }
    78  
    79  // chains is a local map of chainID->chainObject
    80  var chains = struct {
    81  	sync.RWMutex
    82  	list map[string]*chain
    83  }{list: make(map[string]*chain)}
    84  
    85  //MockInitialize resets chains for test env
    86  func MockInitialize() {
    87  	ledgermgmt.InitializeTestEnv()
    88  	chains.list = nil
    89  	chains.list = make(map[string]*chain)
    90  	chainInitializer = func(string) { return }
    91  }
    92  
    93  var chainInitializer func(string)
    94  
    95  var mockMSPIDGetter func(string) []string
    96  
    97  func MockSetMSPIDGetter(mspIDGetter func(string) []string) {
    98  	mockMSPIDGetter = mspIDGetter
    99  }
   100  
   101  // Initialize sets up any chains that the peer has from the persistence. This
   102  // function should be called at the start up when the ledger and gossip
   103  // ready
   104  func Initialize(init func(string)) {
   105  	chainInitializer = init
   106  
   107  	var cb *common.Block
   108  	var ledger ledger.PeerLedger
   109  	ledgermgmt.Initialize()
   110  	ledgerIds, err := ledgermgmt.GetLedgerIDs()
   111  	if err != nil {
   112  		panic(fmt.Errorf("Error in initializing ledgermgmt: %s", err))
   113  	}
   114  	for _, cid := range ledgerIds {
   115  		peerLogger.Infof("Loading chain %s", cid)
   116  		if ledger, err = ledgermgmt.OpenLedger(cid); err != nil {
   117  			peerLogger.Warningf("Failed to load ledger %s(%s)", cid, err)
   118  			peerLogger.Debugf("Error while loading ledger %s with message %s. We continue to the next ledger rather than abort.", cid, err)
   119  			continue
   120  		}
   121  		if cb, err = getCurrConfigBlockFromLedger(ledger); err != nil {
   122  			peerLogger.Warningf("Failed to find config block on ledger %s(%s)", cid, err)
   123  			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)
   124  			continue
   125  		}
   126  		// Create a chain if we get a valid ledger with config block
   127  		if err = createChain(cid, ledger, cb); err != nil {
   128  			peerLogger.Warningf("Failed to load chain %s(%s)", cid, err)
   129  			peerLogger.Debugf("Error reloading chain %s with message %s. We continue to the next chain rather than abort.", cid, err)
   130  			continue
   131  		}
   132  
   133  		InitChain(cid)
   134  	}
   135  }
   136  
   137  // Take care to initialize chain after peer joined, for example deploys system CCs
   138  func InitChain(cid string) {
   139  	if chainInitializer != nil {
   140  		// Initialize chaincode, namely deploy system CC
   141  		peerLogger.Debugf("Init chain %s", cid)
   142  		chainInitializer(cid)
   143  	}
   144  }
   145  
   146  func getCurrConfigBlockFromLedger(ledger ledger.PeerLedger) (*common.Block, error) {
   147  	peerLogger.Debugf("Getting config block")
   148  
   149  	// get last block.  Last block number is Height-1
   150  	blockchainInfo, err := ledger.GetBlockchainInfo()
   151  	if err != nil {
   152  		return nil, err
   153  	}
   154  	lastBlock, err := ledger.GetBlockByNumber(blockchainInfo.Height - 1)
   155  	if err != nil {
   156  		return nil, err
   157  	}
   158  
   159  	// get most recent config block location from last block metadata
   160  	configBlockIndex, err := utils.GetLastConfigIndexFromBlock(lastBlock)
   161  	if err != nil {
   162  		return nil, err
   163  	}
   164  
   165  	// get most recent config block
   166  	configBlock, err := ledger.GetBlockByNumber(configBlockIndex)
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  
   171  	peerLogger.Debugf("Got config block[%d]", configBlockIndex)
   172  	return configBlock, nil
   173  }
   174  
   175  // createChain creates a new chain object and insert it into the chains
   176  func createChain(cid string, ledger ledger.PeerLedger, cb *common.Block) error {
   177  
   178  	envelopeConfig, err := utils.ExtractEnvelope(cb, 0)
   179  	if err != nil {
   180  		return err
   181  	}
   182  
   183  	configtxInitializer := configtx.NewInitializer()
   184  
   185  	gossipEventer := service.GetGossipService().NewConfigEventer()
   186  
   187  	gossipCallbackWrapper := func(cm configtxapi.Manager) {
   188  		ac, ok := configtxInitializer.ApplicationConfig()
   189  		if !ok {
   190  			// TODO, handle a missing ApplicationConfig more gracefully
   191  			ac = nil
   192  		}
   193  		gossipEventer.ProcessConfigUpdate(&chainSupport{
   194  			Manager:     cm,
   195  			Application: ac,
   196  		})
   197  		service.GetGossipService().SuspectPeers(func(identity api.PeerIdentityType) bool {
   198  			// TODO: this is a place-holder that would somehow make the MSP layer suspect
   199  			// that a given certificate is revoked, or its intermediate CA is revoked.
   200  			// In the meantime, before we have such an ability, we return true in order
   201  			// to suspect ALL identities in order to validate all of them.
   202  			return true
   203  		})
   204  	}
   205  
   206  	trustedRootsCallbackWrapper := func(cm configtxapi.Manager) {
   207  		updateTrustedRoots(cm)
   208  	}
   209  
   210  	configtxManager, err := configtx.NewManagerImpl(
   211  		envelopeConfig,
   212  		configtxInitializer,
   213  		[]func(cm configtxapi.Manager){gossipCallbackWrapper, trustedRootsCallbackWrapper},
   214  	)
   215  	if err != nil {
   216  		return err
   217  	}
   218  
   219  	// TODO remove once all references to mspmgmt are gone from peer code
   220  	mspmgmt.XXXSetMSPManager(cid, configtxManager.MSPManager())
   221  
   222  	ac, ok := configtxInitializer.ApplicationConfig()
   223  	if !ok {
   224  		ac = nil
   225  	}
   226  	cs := &chainSupport{
   227  		Manager:     configtxManager,
   228  		Application: ac, // TODO, refactor as this is accessible through Manager
   229  		ledger:      ledger,
   230  	}
   231  
   232  	c := committer.NewLedgerCommitterReactive(ledger, txvalidator.NewTxValidator(cs), func(block *common.Block) error {
   233  		chainID, err := utils.GetChainIDFromBlock(block)
   234  		if err != nil {
   235  			return err
   236  		}
   237  		return SetCurrConfigBlock(block, chainID)
   238  	})
   239  
   240  	ordererAddresses := configtxManager.ChannelConfig().OrdererAddresses()
   241  	if len(ordererAddresses) == 0 {
   242  		return errors.New("No ordering service endpoint provided in configuration block")
   243  	}
   244  	service.GetGossipService().InitializeChannel(cs.ChainID(), c, ordererAddresses)
   245  
   246  	chains.Lock()
   247  	defer chains.Unlock()
   248  	chains.list[cid] = &chain{
   249  		cs:        cs,
   250  		cb:        cb,
   251  		committer: c,
   252  	}
   253  	return nil
   254  }
   255  
   256  // CreateChainFromBlock creates a new chain from config block
   257  func CreateChainFromBlock(cb *common.Block) error {
   258  	cid, err := utils.GetChainIDFromBlock(cb)
   259  	if err != nil {
   260  		return err
   261  	}
   262  
   263  	var l ledger.PeerLedger
   264  	if l, err = ledgermgmt.CreateLedger(cb); err != nil {
   265  		return fmt.Errorf("Cannot create ledger from genesis block, due to %s", err)
   266  	}
   267  
   268  	return createChain(cid, l, cb)
   269  }
   270  
   271  // MockCreateChain used for creating a ledger for a chain for tests
   272  // without havin to join
   273  func MockCreateChain(cid string) error {
   274  	var ledger ledger.PeerLedger
   275  	var err error
   276  
   277  	if ledger = GetLedger(cid); ledger == nil {
   278  		gb, _ := configtxtest.MakeGenesisBlock(cid)
   279  		if ledger, err = ledgermgmt.CreateLedger(gb); err != nil {
   280  			return err
   281  		}
   282  	}
   283  
   284  	// Here we need to mock also the policy manager
   285  	// in order for the ACL to be checked
   286  	initializer := mockconfigtx.Initializer{
   287  		Resources: mockconfigtx.Resources{
   288  			PolicyManagerVal: &mockpolicies.Manager{
   289  				Policy: &mockpolicies.Policy{},
   290  			},
   291  		},
   292  		PolicyProposerVal: &mockconfigtx.PolicyProposer{
   293  			Transactional: mockconfigtx.Transactional{},
   294  		},
   295  		ValueProposerVal: &mockconfigtx.ValueProposer{
   296  			Transactional: mockconfigtx.Transactional{},
   297  		},
   298  	}
   299  	manager := &mockconfigtx.Manager{
   300  		Initializer: initializer,
   301  	}
   302  
   303  	chains.Lock()
   304  	defer chains.Unlock()
   305  
   306  	chains.list[cid] = &chain{
   307  		cs: &chainSupport{
   308  			Manager: manager,
   309  			ledger:  ledger},
   310  	}
   311  
   312  	return nil
   313  }
   314  
   315  // GetLedger returns the ledger of the chain with chain ID. Note that this
   316  // call returns nil if chain cid has not been created.
   317  func GetLedger(cid string) ledger.PeerLedger {
   318  	chains.RLock()
   319  	defer chains.RUnlock()
   320  	if c, ok := chains.list[cid]; ok {
   321  		return c.cs.ledger
   322  	}
   323  	return nil
   324  }
   325  
   326  // GetPolicyManager returns the policy manager of the chain with chain ID. Note that this
   327  // call returns nil if chain cid has not been created.
   328  func GetPolicyManager(cid string) policies.Manager {
   329  	chains.RLock()
   330  	defer chains.RUnlock()
   331  	if c, ok := chains.list[cid]; ok {
   332  		return c.cs.PolicyManager()
   333  	}
   334  	return nil
   335  }
   336  
   337  // GetCurrConfigBlock returns the cached config block of the specified chain.
   338  // Note that this call returns nil if chain cid has not been created.
   339  func GetCurrConfigBlock(cid string) *common.Block {
   340  	chains.RLock()
   341  	defer chains.RUnlock()
   342  	if c, ok := chains.list[cid]; ok {
   343  		return c.cb
   344  	}
   345  	return nil
   346  }
   347  
   348  // updates the trusted roots for the peer based on updates to channels
   349  func updateTrustedRoots(cm configtxapi.Manager) {
   350  	// this is triggered on per channel basis so first update the roots for the channel
   351  	peerLogger.Debugf("Updating trusted root authorities for channel %s", cm.ChainID())
   352  	var secureConfig comm.SecureServerConfig
   353  	var err error
   354  	// only run is TLS is enabled
   355  	secureConfig, err = GetSecureConfig()
   356  	if err == nil && secureConfig.UseTLS {
   357  		buildTrustedRootsForChain(cm)
   358  
   359  		// now iterate over all roots for all app and orderer chains
   360  		trustedRoots := [][]byte{}
   361  		rootCASupport.RLock()
   362  		defer rootCASupport.RUnlock()
   363  		for _, roots := range rootCASupport.AppRootCAsByChain {
   364  			trustedRoots = append(trustedRoots, roots...)
   365  		}
   366  		// also need to append statically configured root certs
   367  		if len(secureConfig.ClientRootCAs) > 0 {
   368  			trustedRoots = append(trustedRoots, secureConfig.ClientRootCAs...)
   369  		}
   370  		if len(secureConfig.ServerRootCAs) > 0 {
   371  			trustedRoots = append(trustedRoots, secureConfig.ServerRootCAs...)
   372  		}
   373  
   374  		server := GetPeerServer()
   375  		// now update the client roots for the peerServer
   376  		if server != nil {
   377  			err := server.SetClientRootCAs(trustedRoots)
   378  			if err != nil {
   379  				msg := "Failed to update trusted roots for peer from latest config " +
   380  					"block.  This peer may not be able to communicate " +
   381  					"with members of channel %s (%s)"
   382  				peerLogger.Warningf(msg, cm.ChainID(), err)
   383  			}
   384  		}
   385  	}
   386  }
   387  
   388  // populates the appRootCAs and orderRootCAs maps by getting the
   389  // root and intermediate certs for all msps associated with the MSPManager
   390  func buildTrustedRootsForChain(cm configtxapi.Manager) {
   391  	rootCASupport.Lock()
   392  	defer rootCASupport.Unlock()
   393  
   394  	appRootCAs := [][]byte{}
   395  	ordererRootCAs := [][]byte{}
   396  	appOrgMSPs := make(map[string]struct{})
   397  
   398  	ac, ok := cm.ApplicationConfig()
   399  	if ok {
   400  		//loop through app orgs and build map of MSPIDs
   401  		for _, appOrg := range ac.Organizations() {
   402  			appOrgMSPs[appOrg.MSPID()] = struct{}{}
   403  		}
   404  	}
   405  
   406  	cid := cm.ChainID()
   407  	peerLogger.Debugf("updating root CAs for channel [%s]", cid)
   408  	msps, err := cm.MSPManager().GetMSPs()
   409  	if err != nil {
   410  		peerLogger.Errorf("Error getting root CAs for channel %s (%s)", cid, err)
   411  	}
   412  	if err == nil {
   413  		for k, v := range msps {
   414  			// check to see if this is a FABRIC MSP
   415  			if v.GetType() == msp.FABRIC {
   416  				for _, root := range v.GetRootCerts() {
   417  					sid, err := root.Serialize()
   418  					if err == nil {
   419  						id := &mspprotos.SerializedIdentity{}
   420  						err = proto.Unmarshal(sid, id)
   421  						if err == nil {
   422  							// check to see of this is an app org MSP
   423  							if _, ok := appOrgMSPs[k]; ok {
   424  								peerLogger.Debugf("adding app root CAs for MSP [%s]", k)
   425  								appRootCAs = append(appRootCAs, id.IdBytes)
   426  							} else {
   427  								peerLogger.Debugf("adding orderer root CAs for MSP [%s]", k)
   428  								ordererRootCAs = append(ordererRootCAs, id.IdBytes)
   429  							}
   430  						}
   431  					}
   432  				}
   433  				for _, intermediate := range v.GetIntermediateCerts() {
   434  					sid, err := intermediate.Serialize()
   435  					if err == nil {
   436  						id := &mspprotos.SerializedIdentity{}
   437  						err = proto.Unmarshal(sid, id)
   438  						if err == nil {
   439  							// check to see of this is an app org MSP
   440  							if _, ok := appOrgMSPs[k]; ok {
   441  								peerLogger.Debugf("adding app root CAs for MSP [%s]", k)
   442  								appRootCAs = append(appRootCAs, id.IdBytes)
   443  							} else {
   444  								peerLogger.Debugf("adding orderer root CAs for MSP [%s]", k)
   445  								ordererRootCAs = append(ordererRootCAs, id.IdBytes)
   446  							}
   447  						}
   448  					}
   449  				}
   450  			}
   451  		}
   452  		rootCASupport.AppRootCAsByChain[cid] = appRootCAs
   453  		rootCASupport.OrdererRootCAsByChain[cid] = ordererRootCAs
   454  	}
   455  }
   456  
   457  // GetMSPIDs returns the ID of each application MSP defined on this chain
   458  func GetMSPIDs(cid string) []string {
   459  	chains.RLock()
   460  	defer chains.RUnlock()
   461  
   462  	//if mock is set, use it to return MSPIDs
   463  	//used for tests without a proper join
   464  	if mockMSPIDGetter != nil {
   465  		return mockMSPIDGetter(cid)
   466  	}
   467  	if c, ok := chains.list[cid]; ok {
   468  		if c == nil || c.cs == nil {
   469  			return nil
   470  		}
   471  		ac, ok := c.cs.ApplicationConfig()
   472  		if !ok || ac.Organizations() == nil {
   473  			return nil
   474  		}
   475  
   476  		orgs := ac.Organizations()
   477  		toret := make([]string, len(orgs))
   478  		i := 0
   479  		for _, org := range orgs {
   480  			toret[i] = org.MSPID()
   481  			i++
   482  		}
   483  
   484  		return toret
   485  	}
   486  	return nil
   487  }
   488  
   489  // SetCurrConfigBlock sets the current config block of the specified chain
   490  func SetCurrConfigBlock(block *common.Block, cid string) error {
   491  	chains.Lock()
   492  	defer chains.Unlock()
   493  	if c, ok := chains.list[cid]; ok {
   494  		c.cb = block
   495  		return nil
   496  	}
   497  	return fmt.Errorf("Chain %s doesn't exist on the peer", cid)
   498  }
   499  
   500  // NewPeerClientConnection Returns a new grpc.ClientConn to the configured local PEER.
   501  func NewPeerClientConnection() (*grpc.ClientConn, error) {
   502  	return NewPeerClientConnectionWithAddress(viper.GetString("peer.address"))
   503  }
   504  
   505  // GetLocalIP returns the non loopback local IP of the host
   506  func GetLocalIP() string {
   507  	addrs, err := net.InterfaceAddrs()
   508  	if err != nil {
   509  		return ""
   510  	}
   511  	for _, address := range addrs {
   512  		// check the address type and if it is not a loopback then display it
   513  		if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
   514  			if ipnet.IP.To4() != nil {
   515  				return ipnet.IP.String()
   516  			}
   517  		}
   518  	}
   519  	return ""
   520  }
   521  
   522  // NewPeerClientConnectionWithAddress Returns a new grpc.ClientConn to the configured local PEER.
   523  func NewPeerClientConnectionWithAddress(peerAddress string) (*grpc.ClientConn, error) {
   524  	if comm.TLSEnabled() {
   525  		return comm.NewClientConnectionWithAddress(peerAddress, true, true, comm.InitTLSForPeer())
   526  	}
   527  	return comm.NewClientConnectionWithAddress(peerAddress, true, false, nil)
   528  }
   529  
   530  // GetChannelsInfo returns an array with information about all channels for
   531  // this peer
   532  func GetChannelsInfo() []*pb.ChannelInfo {
   533  	// array to store metadata for all channels
   534  	var channelInfoArray []*pb.ChannelInfo
   535  
   536  	chains.RLock()
   537  	defer chains.RUnlock()
   538  	for key := range chains.list {
   539  		channelInfo := &pb.ChannelInfo{ChannelId: key}
   540  
   541  		// add this specific chaincode's metadata to the array of all chaincodes
   542  		channelInfoArray = append(channelInfoArray, channelInfo)
   543  	}
   544  
   545  	return channelInfoArray
   546  }
   547  
   548  // NewChannelPolicyManagerGetter returns a new instance of ChannelPolicyManagerGetter
   549  func NewChannelPolicyManagerGetter() policies.ChannelPolicyManagerGetter {
   550  	return &channelPolicyManagerGetter{}
   551  }
   552  
   553  type channelPolicyManagerGetter struct{}
   554  
   555  func (c *channelPolicyManagerGetter) Manager(channelID string) (policies.Manager, bool) {
   556  	policyManager := GetPolicyManager(channelID)
   557  	return policyManager, policyManager != nil
   558  }
   559  
   560  // CreatePeerServer creates an instance of comm.GRPCServer
   561  // This server is used for peer communications
   562  func CreatePeerServer(listenAddress string,
   563  	secureConfig comm.SecureServerConfig) (comm.GRPCServer, error) {
   564  
   565  	var err error
   566  	peerServer, err = comm.NewGRPCServer(listenAddress, secureConfig)
   567  	if err != nil {
   568  		peerLogger.Errorf("Failed to create peer server (%s)", err)
   569  		return nil, err
   570  	}
   571  	return peerServer, nil
   572  }
   573  
   574  // GetPeerServer returns the peer server instance
   575  func GetPeerServer() comm.GRPCServer {
   576  	return peerServer
   577  }