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