github.com/anjalikarhana/fabric@v2.1.1+incompatible/orderer/common/cluster/util.go (about) 1 /* 2 Copyright IBM Corp. 2017 All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package cluster 8 9 import ( 10 "bytes" 11 "crypto/tls" 12 "crypto/x509" 13 "encoding/hex" 14 "encoding/json" 15 "encoding/pem" 16 "fmt" 17 "sync" 18 "sync/atomic" 19 "time" 20 21 "github.com/hyperledger/fabric-protos-go/common" 22 "github.com/hyperledger/fabric/bccsp" 23 "github.com/hyperledger/fabric/common/channelconfig" 24 "github.com/hyperledger/fabric/common/configtx" 25 "github.com/hyperledger/fabric/common/flogging" 26 "github.com/hyperledger/fabric/common/policies" 27 "github.com/hyperledger/fabric/common/tools/protolator" 28 "github.com/hyperledger/fabric/common/util" 29 "github.com/hyperledger/fabric/internal/pkg/comm" 30 "github.com/hyperledger/fabric/protoutil" 31 "github.com/pkg/errors" 32 "google.golang.org/grpc" 33 ) 34 35 // ConnByCertMap maps certificates represented as strings 36 // to gRPC connections 37 type ConnByCertMap map[string]*grpc.ClientConn 38 39 // Lookup looks up a certificate and returns the connection that was mapped 40 // to the certificate, and whether it was found or not 41 func (cbc ConnByCertMap) Lookup(cert []byte) (*grpc.ClientConn, bool) { 42 conn, ok := cbc[string(cert)] 43 return conn, ok 44 } 45 46 // Put associates the given connection to the certificate 47 func (cbc ConnByCertMap) Put(cert []byte, conn *grpc.ClientConn) { 48 cbc[string(cert)] = conn 49 } 50 51 // Remove removes the connection that is associated to the given certificate 52 func (cbc ConnByCertMap) Remove(cert []byte) { 53 delete(cbc, string(cert)) 54 } 55 56 func (cbc ConnByCertMap) Size() int { 57 return len(cbc) 58 } 59 60 // MemberMapping defines NetworkMembers by their ID 61 type MemberMapping map[uint64]*Stub 62 63 // Put inserts the given stub to the MemberMapping 64 func (mp MemberMapping) Put(stub *Stub) { 65 mp[stub.ID] = stub 66 } 67 68 // ByID retrieves the Stub with the given ID from the MemberMapping 69 func (mp MemberMapping) ByID(ID uint64) *Stub { 70 return mp[ID] 71 } 72 73 // LookupByClientCert retrieves a Stub with the given client certificate 74 func (mp MemberMapping) LookupByClientCert(cert []byte) *Stub { 75 for _, stub := range mp { 76 if bytes.Equal(stub.ClientTLSCert, cert) { 77 return stub 78 } 79 } 80 return nil 81 } 82 83 // ServerCertificates returns a set of the server certificates 84 // represented as strings 85 func (mp MemberMapping) ServerCertificates() StringSet { 86 res := make(StringSet) 87 for _, member := range mp { 88 res[string(member.ServerTLSCert)] = struct{}{} 89 } 90 return res 91 } 92 93 // StringSet is a set of strings 94 type StringSet map[string]struct{} 95 96 // union adds the elements of the given set to the StringSet 97 func (ss StringSet) union(set StringSet) { 98 for k := range set { 99 ss[k] = struct{}{} 100 } 101 } 102 103 // subtract removes all elements in the given set from the StringSet 104 func (ss StringSet) subtract(set StringSet) { 105 for k := range set { 106 delete(ss, k) 107 } 108 } 109 110 // PredicateDialer creates gRPC connections 111 // that are only established if the given predicate 112 // is fulfilled 113 type PredicateDialer struct { 114 lock sync.RWMutex 115 Config comm.ClientConfig 116 } 117 118 func (dialer *PredicateDialer) UpdateRootCAs(serverRootCAs [][]byte) { 119 dialer.lock.Lock() 120 defer dialer.lock.Unlock() 121 dialer.Config.SecOpts.ServerRootCAs = serverRootCAs 122 } 123 124 // Dial creates a new gRPC connection that can only be established, if the remote node's 125 // certificate chain satisfy verifyFunc 126 func (dialer *PredicateDialer) Dial(address string, verifyFunc RemoteVerifier) (*grpc.ClientConn, error) { 127 dialer.lock.RLock() 128 cfg := dialer.Config.Clone() 129 dialer.lock.RUnlock() 130 131 cfg.SecOpts.VerifyCertificate = verifyFunc 132 client, err := comm.NewGRPCClient(cfg) 133 if err != nil { 134 return nil, errors.WithStack(err) 135 } 136 return client.NewConnection(address, func(tlsConfig *tls.Config) { 137 // We need to dynamically overwrite the TLS root CAs, 138 // as they may be updated. 139 dialer.lock.RLock() 140 serverRootCAs := dialer.Config.Clone().SecOpts.ServerRootCAs 141 dialer.lock.RUnlock() 142 143 tlsConfig.RootCAs = x509.NewCertPool() 144 for _, pem := range serverRootCAs { 145 tlsConfig.RootCAs.AppendCertsFromPEM(pem) 146 } 147 }) 148 } 149 150 // DERtoPEM returns a PEM representation of the DER 151 // encoded certificate 152 func DERtoPEM(der []byte) string { 153 return string(pem.EncodeToMemory(&pem.Block{ 154 Type: "CERTIFICATE", 155 Bytes: der, 156 })) 157 } 158 159 // StandardDialer wraps an ClientConfig, and provides 160 // a means to connect according to given EndpointCriteria. 161 type StandardDialer struct { 162 Config comm.ClientConfig 163 } 164 165 // Dial dials an address according to the given EndpointCriteria 166 func (dialer *StandardDialer) Dial(endpointCriteria EndpointCriteria) (*grpc.ClientConn, error) { 167 cfg := dialer.Config.Clone() 168 cfg.SecOpts.ServerRootCAs = endpointCriteria.TLSRootCAs 169 170 client, err := comm.NewGRPCClient(cfg) 171 if err != nil { 172 return nil, errors.Wrap(err, "failed creating gRPC client") 173 } 174 175 return client.NewConnection(endpointCriteria.Endpoint) 176 } 177 178 //go:generate mockery -dir . -name BlockVerifier -case underscore -output ./mocks/ 179 180 // BlockVerifier verifies block signatures. 181 type BlockVerifier interface { 182 // VerifyBlockSignature verifies a signature of a block. 183 // It has an optional argument of a configuration envelope 184 // which would make the block verification to use validation rules 185 // based on the given configuration in the ConfigEnvelope. 186 // If the config envelope passed is nil, then the validation rules used 187 // are the ones that were applied at commit of previous blocks. 188 VerifyBlockSignature(sd []*protoutil.SignedData, config *common.ConfigEnvelope) error 189 } 190 191 // BlockSequenceVerifier verifies that the given consecutive sequence 192 // of blocks is valid. 193 type BlockSequenceVerifier func(blocks []*common.Block, channel string) error 194 195 // Dialer creates a gRPC connection to a remote address 196 type Dialer interface { 197 Dial(endpointCriteria EndpointCriteria) (*grpc.ClientConn, error) 198 } 199 200 // VerifyBlocks verifies the given consecutive sequence of blocks is valid, 201 // and returns nil if it's valid, else an error. 202 func VerifyBlocks(blockBuff []*common.Block, signatureVerifier BlockVerifier) error { 203 if len(blockBuff) == 0 { 204 return errors.New("buffer is empty") 205 } 206 // First, we verify that the block hash in every block is: 207 // Equal to the hash in the header 208 // Equal to the previous hash in the succeeding block 209 for i := range blockBuff { 210 if err := VerifyBlockHash(i, blockBuff); err != nil { 211 return err 212 } 213 } 214 215 var config *common.ConfigEnvelope 216 var isLastBlockConfigBlock bool 217 // Verify all configuration blocks that are found inside the block batch, 218 // with the configuration that was committed (nil) or with one that is picked up 219 // during iteration over the block batch. 220 for _, block := range blockBuff { 221 configFromBlock, err := ConfigFromBlock(block) 222 if err == errNotAConfig { 223 isLastBlockConfigBlock = false 224 continue 225 } 226 if err != nil { 227 return err 228 } 229 // The block is a configuration block, so verify it 230 if err := VerifyBlockSignature(block, signatureVerifier, config); err != nil { 231 return err 232 } 233 config = configFromBlock 234 isLastBlockConfigBlock = true 235 } 236 237 // Verify the last block's signature 238 lastBlock := blockBuff[len(blockBuff)-1] 239 240 // If last block is a config block, we verified it using the policy of the previous block, so it's valid. 241 if isLastBlockConfigBlock { 242 return nil 243 } 244 245 return VerifyBlockSignature(lastBlock, signatureVerifier, config) 246 } 247 248 var errNotAConfig = errors.New("not a config block") 249 250 // ConfigFromBlock returns a ConfigEnvelope if exists, or a *NotAConfigBlock error. 251 // It may also return some other error in case parsing failed. 252 func ConfigFromBlock(block *common.Block) (*common.ConfigEnvelope, error) { 253 if block == nil || block.Data == nil || len(block.Data.Data) == 0 { 254 return nil, errors.New("empty block") 255 } 256 txn := block.Data.Data[0] 257 env, err := protoutil.GetEnvelopeFromBlock(txn) 258 if err != nil { 259 return nil, errors.WithStack(err) 260 } 261 payload, err := protoutil.UnmarshalPayload(env.Payload) 262 if err != nil { 263 return nil, errors.WithStack(err) 264 } 265 if block.Header.Number == 0 { 266 configEnvelope, err := configtx.UnmarshalConfigEnvelope(payload.Data) 267 if err != nil { 268 return nil, errors.Wrap(err, "invalid config envelope") 269 } 270 return configEnvelope, nil 271 } 272 if payload.Header == nil { 273 return nil, errors.New("nil header in payload") 274 } 275 chdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader) 276 if err != nil { 277 return nil, errors.WithStack(err) 278 } 279 if common.HeaderType(chdr.Type) != common.HeaderType_CONFIG { 280 return nil, errNotAConfig 281 } 282 configEnvelope, err := configtx.UnmarshalConfigEnvelope(payload.Data) 283 if err != nil { 284 return nil, errors.Wrap(err, "invalid config envelope") 285 } 286 return configEnvelope, nil 287 } 288 289 // VerifyBlockHash verifies the hash chain of the block with the given index 290 // among the blocks of the given block buffer. 291 func VerifyBlockHash(indexInBuffer int, blockBuff []*common.Block) error { 292 if len(blockBuff) <= indexInBuffer { 293 return errors.Errorf("index %d out of bounds (total %d blocks)", indexInBuffer, len(blockBuff)) 294 } 295 block := blockBuff[indexInBuffer] 296 if block.Header == nil { 297 return errors.New("missing block header") 298 } 299 seq := block.Header.Number 300 dataHash := protoutil.BlockDataHash(block.Data) 301 // Verify data hash matches the hash in the header 302 if !bytes.Equal(dataHash, block.Header.DataHash) { 303 computedHash := hex.EncodeToString(dataHash) 304 claimedHash := hex.EncodeToString(block.Header.DataHash) 305 return errors.Errorf("computed hash of block (%d) (%s) doesn't match claimed hash (%s)", 306 seq, computedHash, claimedHash) 307 } 308 // We have a previous block in the buffer, ensure current block's previous hash matches the previous one. 309 if indexInBuffer > 0 { 310 prevBlock := blockBuff[indexInBuffer-1] 311 currSeq := block.Header.Number 312 if prevBlock.Header == nil { 313 return errors.New("previous block header is nil") 314 } 315 prevSeq := prevBlock.Header.Number 316 if prevSeq+1 != currSeq { 317 return errors.Errorf("sequences %d and %d were received consecutively", prevSeq, currSeq) 318 } 319 if !bytes.Equal(block.Header.PreviousHash, protoutil.BlockHeaderHash(prevBlock.Header)) { 320 claimedPrevHash := hex.EncodeToString(block.Header.PreviousHash) 321 actualPrevHash := hex.EncodeToString(protoutil.BlockHeaderHash(prevBlock.Header)) 322 return errors.Errorf("block [%d]'s hash (%s) mismatches block [%d]'s prev block hash (%s)", 323 prevSeq, actualPrevHash, currSeq, claimedPrevHash) 324 } 325 } 326 return nil 327 } 328 329 // SignatureSetFromBlock creates a signature set out of a block. 330 func SignatureSetFromBlock(block *common.Block) ([]*protoutil.SignedData, error) { 331 if block.Metadata == nil || len(block.Metadata.Metadata) <= int(common.BlockMetadataIndex_SIGNATURES) { 332 return nil, errors.New("no metadata in block") 333 } 334 metadata, err := protoutil.GetMetadataFromBlock(block, common.BlockMetadataIndex_SIGNATURES) 335 if err != nil { 336 return nil, errors.Errorf("failed unmarshaling medatata for signatures: %v", err) 337 } 338 339 var signatureSet []*protoutil.SignedData 340 for _, metadataSignature := range metadata.Signatures { 341 sigHdr, err := protoutil.UnmarshalSignatureHeader(metadataSignature.SignatureHeader) 342 if err != nil { 343 return nil, errors.Errorf("failed unmarshaling signature header for block with id %d: %v", 344 block.Header.Number, err) 345 } 346 signatureSet = append(signatureSet, 347 &protoutil.SignedData{ 348 Identity: sigHdr.Creator, 349 Data: util.ConcatenateBytes(metadata.Value, 350 metadataSignature.SignatureHeader, protoutil.BlockHeaderBytes(block.Header)), 351 Signature: metadataSignature.Signature, 352 }, 353 ) 354 } 355 return signatureSet, nil 356 } 357 358 // VerifyBlockSignature verifies the signature on the block with the given BlockVerifier and the given config. 359 func VerifyBlockSignature(block *common.Block, verifier BlockVerifier, config *common.ConfigEnvelope) error { 360 signatureSet, err := SignatureSetFromBlock(block) 361 if err != nil { 362 return err 363 } 364 return verifier.VerifyBlockSignature(signatureSet, config) 365 } 366 367 // EndpointCriteria defines criteria of how to connect to a remote orderer node. 368 type EndpointCriteria struct { 369 Endpoint string // Endpoint of the form host:port 370 TLSRootCAs [][]byte // PEM encoded TLS root CA certificates 371 } 372 373 // String returns a string representation of this EndpointCriteria 374 func (ep EndpointCriteria) String() string { 375 var formattedCAs []interface{} 376 for _, rawCAFile := range ep.TLSRootCAs { 377 var bl *pem.Block 378 pemContent := rawCAFile 379 for { 380 bl, pemContent = pem.Decode(pemContent) 381 if bl == nil { 382 break 383 } 384 cert, err := x509.ParseCertificate(bl.Bytes) 385 if err != nil { 386 break 387 } 388 389 issuedBy := cert.Issuer.String() 390 if cert.Issuer.String() == cert.Subject.String() { 391 issuedBy = "self" 392 } 393 394 info := make(map[string]interface{}) 395 info["Expired"] = time.Now().After(cert.NotAfter) 396 info["Subject"] = cert.Subject.String() 397 info["Issuer"] = issuedBy 398 formattedCAs = append(formattedCAs, info) 399 } 400 } 401 402 formattedEndpointCriteria := make(map[string]interface{}) 403 formattedEndpointCriteria["Endpoint"] = ep.Endpoint 404 formattedEndpointCriteria["CAs"] = formattedCAs 405 406 rawJSON, err := json.Marshal(formattedEndpointCriteria) 407 if err != nil { 408 return fmt.Sprintf("{\"Endpoint\": \"%s\"}", ep.Endpoint) 409 } 410 411 return string(rawJSON) 412 } 413 414 // EndpointconfigFromConfigBlock retrieves TLS CA certificates and endpoints 415 // from a config block. 416 func EndpointconfigFromConfigBlock(block *common.Block, bccsp bccsp.BCCSP) ([]EndpointCriteria, error) { 417 if block == nil { 418 return nil, errors.New("nil block") 419 } 420 envelopeConfig, err := protoutil.ExtractEnvelope(block, 0) 421 if err != nil { 422 return nil, err 423 } 424 425 bundle, err := channelconfig.NewBundleFromEnvelope(envelopeConfig, bccsp) 426 if err != nil { 427 return nil, errors.Wrap(err, "failed extracting bundle from envelope") 428 } 429 msps, err := bundle.MSPManager().GetMSPs() 430 if err != nil { 431 return nil, errors.Wrap(err, "failed obtaining MSPs from MSPManager") 432 } 433 ordererConfig, ok := bundle.OrdererConfig() 434 if !ok { 435 return nil, errors.New("failed obtaining orderer config from bundle") 436 } 437 438 mspIDsToCACerts := make(map[string][][]byte) 439 var aggregatedTLSCerts [][]byte 440 for _, org := range ordererConfig.Organizations() { 441 // Validate that every orderer org has a corresponding MSP instance in the MSP Manager. 442 msp, exists := msps[org.MSPID()] 443 if !exists { 444 return nil, errors.Errorf("no MSP found for MSP with ID of %s", org.MSPID()) 445 } 446 447 // Build a per org mapping of the TLS CA certs for this org, 448 // and aggregate all TLS CA certs into aggregatedTLSCerts to be used later on. 449 var caCerts [][]byte 450 caCerts = append(caCerts, msp.GetTLSIntermediateCerts()...) 451 caCerts = append(caCerts, msp.GetTLSRootCerts()...) 452 mspIDsToCACerts[org.MSPID()] = caCerts 453 aggregatedTLSCerts = append(aggregatedTLSCerts, caCerts...) 454 } 455 456 endpointsPerOrg := perOrgEndpoints(ordererConfig, mspIDsToCACerts) 457 if len(endpointsPerOrg) > 0 { 458 return endpointsPerOrg, nil 459 } 460 461 return globalEndpointsFromConfig(aggregatedTLSCerts, bundle), nil 462 } 463 464 func perOrgEndpoints(ordererConfig channelconfig.Orderer, mspIDsToCerts map[string][][]byte) []EndpointCriteria { 465 var endpointsPerOrg []EndpointCriteria 466 467 for _, org := range ordererConfig.Organizations() { 468 for _, endpoint := range org.Endpoints() { 469 endpointsPerOrg = append(endpointsPerOrg, EndpointCriteria{ 470 TLSRootCAs: mspIDsToCerts[org.MSPID()], 471 Endpoint: endpoint, 472 }) 473 } 474 } 475 476 return endpointsPerOrg 477 } 478 479 func globalEndpointsFromConfig(aggregatedTLSCerts [][]byte, bundle *channelconfig.Bundle) []EndpointCriteria { 480 var globalEndpoints []EndpointCriteria 481 for _, endpoint := range bundle.ChannelConfig().OrdererAddresses() { 482 globalEndpoints = append(globalEndpoints, EndpointCriteria{ 483 Endpoint: endpoint, 484 TLSRootCAs: aggregatedTLSCerts, 485 }) 486 } 487 return globalEndpoints 488 } 489 490 //go:generate mockery -dir . -name VerifierFactory -case underscore -output ./mocks/ 491 492 // VerifierFactory creates BlockVerifiers. 493 type VerifierFactory interface { 494 // VerifierFromConfig creates a BlockVerifier from the given configuration. 495 VerifierFromConfig(configuration *common.ConfigEnvelope, channel string) (BlockVerifier, error) 496 } 497 498 // VerificationRegistry registers verifiers and retrieves them. 499 type VerificationRegistry struct { 500 LoadVerifier func(chain string) BlockVerifier 501 Logger *flogging.FabricLogger 502 VerifierFactory VerifierFactory 503 VerifiersByChannel map[string]BlockVerifier 504 } 505 506 // RegisterVerifier adds a verifier into the registry if applicable. 507 func (vr *VerificationRegistry) RegisterVerifier(chain string) { 508 if _, exists := vr.VerifiersByChannel[chain]; exists { 509 vr.Logger.Debugf("No need to register verifier for chain %s", chain) 510 return 511 } 512 513 v := vr.LoadVerifier(chain) 514 if v == nil { 515 vr.Logger.Errorf("Failed loading verifier for chain %s", chain) 516 return 517 } 518 519 vr.VerifiersByChannel[chain] = v 520 vr.Logger.Infof("Registered verifier for chain %s", chain) 521 } 522 523 // RetrieveVerifier returns a BlockVerifier for the given channel, or nil if not found. 524 func (vr *VerificationRegistry) RetrieveVerifier(channel string) BlockVerifier { 525 verifier, exists := vr.VerifiersByChannel[channel] 526 if exists { 527 return verifier 528 } 529 vr.Logger.Errorf("No verifier for channel %s exists", channel) 530 return nil 531 } 532 533 // BlockCommitted notifies the VerificationRegistry upon a block commit, which may 534 // trigger a registration of a verifier out of the block in case the block is a config block. 535 func (vr *VerificationRegistry) BlockCommitted(block *common.Block, channel string) { 536 conf, err := ConfigFromBlock(block) 537 // The block doesn't contain a config block, but is a valid block 538 if err == errNotAConfig { 539 vr.Logger.Debugf("Committed block [%d] for channel %s that is not a config block", 540 block.Header.Number, channel) 541 return 542 } 543 // The block isn't a valid block 544 if err != nil { 545 vr.Logger.Errorf("Failed parsing block of channel %s: %v, content: %s", 546 channel, err, BlockToString(block)) 547 return 548 } 549 550 // The block contains a config block 551 verifier, err := vr.VerifierFactory.VerifierFromConfig(conf, channel) 552 if err != nil { 553 vr.Logger.Errorf("Failed creating a verifier from a config block for channel %s: %v, content: %s", 554 channel, err, BlockToString(block)) 555 return 556 } 557 558 vr.VerifiersByChannel[channel] = verifier 559 560 vr.Logger.Debugf("Committed config block [%d] for channel %s", block.Header.Number, channel) 561 } 562 563 // BlockToString returns a string representation of this block. 564 func BlockToString(block *common.Block) string { 565 buff := &bytes.Buffer{} 566 protolator.DeepMarshalJSON(buff, block) 567 return buff.String() 568 } 569 570 // BlockCommitFunc signals a block commit. 571 type BlockCommitFunc func(block *common.Block, channel string) 572 573 // LedgerInterceptor intercepts block commits. 574 type LedgerInterceptor struct { 575 Channel string 576 InterceptBlockCommit BlockCommitFunc 577 LedgerWriter 578 } 579 580 // Append commits a block into the ledger, and also fires the configured callback. 581 func (interceptor *LedgerInterceptor) Append(block *common.Block) error { 582 defer interceptor.InterceptBlockCommit(block, interceptor.Channel) 583 return interceptor.LedgerWriter.Append(block) 584 } 585 586 // BlockVerifierAssembler creates a BlockVerifier out of a config envelope 587 type BlockVerifierAssembler struct { 588 Logger *flogging.FabricLogger 589 BCCSP bccsp.BCCSP 590 } 591 592 // VerifierFromConfig creates a BlockVerifier from the given configuration. 593 func (bva *BlockVerifierAssembler) VerifierFromConfig(configuration *common.ConfigEnvelope, channel string) (BlockVerifier, error) { 594 bundle, err := channelconfig.NewBundle(channel, configuration.Config, bva.BCCSP) 595 if err != nil { 596 return nil, errors.Wrap(err, "failed extracting bundle from envelope") 597 } 598 policyMgr := bundle.PolicyManager() 599 600 return &BlockValidationPolicyVerifier{ 601 Logger: bva.Logger, 602 PolicyMgr: policyMgr, 603 Channel: channel, 604 BCCSP: bva.BCCSP, 605 }, nil 606 } 607 608 // BlockValidationPolicyVerifier verifies signatures based on the block validation policy. 609 type BlockValidationPolicyVerifier struct { 610 Logger *flogging.FabricLogger 611 Channel string 612 PolicyMgr policies.Manager 613 BCCSP bccsp.BCCSP 614 } 615 616 // VerifyBlockSignature verifies the signed data associated to a block, optionally with the given config envelope. 617 func (bv *BlockValidationPolicyVerifier) VerifyBlockSignature(sd []*protoutil.SignedData, envelope *common.ConfigEnvelope) error { 618 policyMgr := bv.PolicyMgr 619 // If the envelope passed isn't nil, we should use a different policy manager. 620 if envelope != nil { 621 bundle, err := channelconfig.NewBundle(bv.Channel, envelope.Config, bv.BCCSP) 622 if err != nil { 623 buff := &bytes.Buffer{} 624 protolator.DeepMarshalJSON(buff, envelope.Config) 625 bv.Logger.Errorf("Failed creating a new bundle for channel %s, Config content is: %s", bv.Channel, buff.String()) 626 return err 627 } 628 bv.Logger.Infof("Initializing new PolicyManager for channel %s", bv.Channel) 629 policyMgr = bundle.PolicyManager() 630 } 631 policy, exists := policyMgr.GetPolicy(policies.BlockValidation) 632 if !exists { 633 return errors.Errorf("policy %s wasn't found", policies.BlockValidation) 634 } 635 return policy.EvaluateSignedData(sd) 636 } 637 638 //go:generate mockery -dir . -name BlockRetriever -case underscore -output ./mocks/ 639 640 // BlockRetriever retrieves blocks 641 type BlockRetriever interface { 642 // Block returns a block with the given number, 643 // or nil if such a block doesn't exist. 644 Block(number uint64) *common.Block 645 } 646 647 // LastConfigBlock returns the last config block relative to the given block. 648 func LastConfigBlock(block *common.Block, blockRetriever BlockRetriever) (*common.Block, error) { 649 if block == nil { 650 return nil, errors.New("nil block") 651 } 652 if blockRetriever == nil { 653 return nil, errors.New("nil blockRetriever") 654 } 655 lastConfigBlockNum, err := protoutil.GetLastConfigIndexFromBlock(block) 656 if err != nil { 657 return nil, err 658 } 659 lastConfigBlock := blockRetriever.Block(lastConfigBlockNum) 660 if lastConfigBlock == nil { 661 return nil, errors.Errorf("unable to retrieve last config block [%d]", lastConfigBlockNum) 662 } 663 return lastConfigBlock, nil 664 } 665 666 // StreamCountReporter reports the number of streams currently connected to this node 667 type StreamCountReporter struct { 668 Metrics *Metrics 669 count uint32 670 } 671 672 func (scr *StreamCountReporter) Increment() { 673 count := atomic.AddUint32(&scr.count, 1) 674 scr.Metrics.reportStreamCount(count) 675 } 676 677 func (scr *StreamCountReporter) Decrement() { 678 count := atomic.AddUint32(&scr.count, ^uint32(0)) 679 scr.Metrics.reportStreamCount(count) 680 } 681 682 type certificateExpirationCheck struct { 683 minimumExpirationWarningInterval time.Duration 684 expiresAt time.Time 685 expirationWarningThreshold time.Duration 686 lastWarning time.Time 687 nodeName string 688 endpoint string 689 alert func(string, ...interface{}) 690 } 691 692 func (exp *certificateExpirationCheck) checkExpiration(currentTime time.Time, channel string) { 693 timeLeft := exp.expiresAt.Sub(currentTime) 694 if timeLeft > exp.expirationWarningThreshold { 695 return 696 } 697 698 timeSinceLastWarning := currentTime.Sub(exp.lastWarning) 699 if timeSinceLastWarning < exp.minimumExpirationWarningInterval { 700 return 701 } 702 703 exp.alert("Certificate of %s from %s for channel %s expires in less than %v", 704 exp.nodeName, exp.endpoint, channel, timeLeft) 705 exp.lastWarning = currentTime 706 }