github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/gossip/state/state.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 state 18 19 import ( 20 "bytes" 21 "errors" 22 "sync" 23 "sync/atomic" 24 "time" 25 26 pb "github.com/golang/protobuf/proto" 27 "github.com/hyperledger/fabric/core/committer" 28 "github.com/hyperledger/fabric/gossip/api" 29 "github.com/hyperledger/fabric/gossip/comm" 30 common2 "github.com/hyperledger/fabric/gossip/common" 31 "github.com/hyperledger/fabric/gossip/discovery" 32 "github.com/hyperledger/fabric/gossip/util" 33 "github.com/hyperledger/fabric/protos/common" 34 proto "github.com/hyperledger/fabric/protos/gossip" 35 "github.com/op/go-logging" 36 ) 37 38 // GossipStateProvider is the interface to acquire sequences of the ledger blocks 39 // capable to full fill missing blocks by running state replication and 40 // sending request to get missing block to other nodes 41 type GossipStateProvider interface { 42 // Retrieve block with sequence number equal to index 43 GetBlock(index uint64) *common.Block 44 45 AddPayload(payload *proto.Payload) error 46 47 // Stop terminates state transfer object 48 Stop() 49 } 50 51 const ( 52 defAntiEntropyInterval = 10 * time.Second 53 defAntiEntropyStateResponseTimeout = 3 * time.Second 54 defAntiEntropyBatchSize = 10 55 56 defChannelBufferSize = 100 57 defAntiEntropyMaxRetries = 3 58 ) 59 60 // GossipAdapter defines gossip/communication required interface for state provider 61 type GossipAdapter interface { 62 // Send sends a message to remote peers 63 Send(msg *proto.GossipMessage, peers ...*comm.RemotePeer) 64 65 // Accept returns a dedicated read-only channel for messages sent by other nodes that match a certain predicate. 66 // If passThrough is false, the messages are processed by the gossip layer beforehand. 67 // If passThrough is true, the gossip layer doesn't intervene and the messages 68 // can be used to send a reply back to the sender 69 Accept(acceptor common2.MessageAcceptor, passThrough bool) (<-chan *proto.GossipMessage, <-chan proto.ReceivedMessage) 70 71 // UpdateChannelMetadata updates the self metadata the peer 72 // publishes to other peers about its channel-related state 73 UpdateChannelMetadata(metadata []byte, chainID common2.ChainID) 74 75 // PeersOfChannel returns the NetworkMembers considered alive 76 // and also subscribed to the channel given 77 PeersOfChannel(common2.ChainID) []discovery.NetworkMember 78 } 79 80 // GossipStateProviderImpl the implementation of the GossipStateProvider interface 81 // the struct to handle in memory sliding window of 82 // new ledger block to be acquired by hyper ledger 83 type GossipStateProviderImpl struct { 84 // MessageCryptoService 85 mcs api.MessageCryptoService 86 87 // Chain id 88 chainID string 89 90 // The gossiping service 91 gossip GossipAdapter 92 93 // Channel to read gossip messages from 94 gossipChan <-chan *proto.GossipMessage 95 96 commChan <-chan proto.ReceivedMessage 97 98 // Queue of payloads which wasn't acquired yet 99 payloads PayloadsBuffer 100 101 committer committer.Committer 102 103 stateResponseCh chan proto.ReceivedMessage 104 105 stateRequestCh chan proto.ReceivedMessage 106 107 stopCh chan struct{} 108 109 done sync.WaitGroup 110 111 once sync.Once 112 113 stateTransferActive int32 114 } 115 116 var logger *logging.Logger // package-level logger 117 118 func init() { 119 logger = util.GetLogger(util.LoggingStateModule, "") 120 } 121 122 // NewGossipStateProvider creates initialized instance of gossip state provider 123 func NewGossipStateProvider(chainID string, g GossipAdapter, committer committer.Committer, mcs api.MessageCryptoService) GossipStateProvider { 124 logger := util.GetLogger(util.LoggingStateModule, "") 125 126 gossipChan, _ := g.Accept(func(message interface{}) bool { 127 // Get only data messages 128 return message.(*proto.GossipMessage).IsDataMsg() && 129 bytes.Equal(message.(*proto.GossipMessage).Channel, []byte(chainID)) 130 }, false) 131 132 remoteStateMsgFilter := func(message interface{}) bool { 133 receivedMsg := message.(proto.ReceivedMessage) 134 msg := receivedMsg.GetGossipMessage() 135 if !msg.IsRemoteStateMessage() { 136 return false 137 } 138 // If we're not running with authentication, no point 139 // in enforcing access control 140 if !receivedMsg.GetConnectionInfo().IsAuthenticated() { 141 return true 142 } 143 connInfo := receivedMsg.GetConnectionInfo() 144 authErr := mcs.VerifyByChannel(msg.Channel, connInfo.Identity, connInfo.Auth.Signature, connInfo.Auth.SignedData) 145 if authErr != nil { 146 logger.Warning("Got unauthorized nodeMetastate transfer request from", string(connInfo.Identity)) 147 return false 148 } 149 return true 150 } 151 152 // Filter message which are only relevant for nodeMetastate transfer 153 _, commChan := g.Accept(remoteStateMsgFilter, true) 154 155 height, err := committer.LedgerHeight() 156 if height == 0 { 157 // Panic here since this is an indication of invalid situation which should not happen in normal 158 // code path. 159 logger.Panic("Committer height cannot be zero, ledger should include at least one block (genesis).") 160 } 161 162 if err != nil { 163 logger.Error("Could not read ledger info to obtain current ledger height due to: ", err) 164 // Exiting as without ledger it will be impossible 165 // to deliver new blocks 166 return nil 167 } 168 169 s := &GossipStateProviderImpl{ 170 // MessageCryptoService 171 mcs: mcs, 172 173 // Chain ID 174 chainID: chainID, 175 176 // Instance of the gossip 177 gossip: g, 178 179 // Channel to read new messages from 180 gossipChan: gossipChan, 181 182 // Channel to read direct messages from other peers 183 commChan: commChan, 184 185 // Create a queue for payload received 186 payloads: NewPayloadsBuffer(height), 187 188 committer: committer, 189 190 stateResponseCh: make(chan proto.ReceivedMessage, defChannelBufferSize), 191 192 stateRequestCh: make(chan proto.ReceivedMessage, defChannelBufferSize), 193 194 stopCh: make(chan struct{}, 1), 195 196 stateTransferActive: 0, 197 198 once: sync.Once{}, 199 } 200 201 nodeMetastate := NewNodeMetastate(height - 1) 202 203 logger.Infof("Updating node metadata information, "+ 204 "current ledger sequence is at = %d, next expected block is = %d", nodeMetastate.LedgerHeight, s.payloads.Next()) 205 206 b, err := nodeMetastate.Bytes() 207 if err == nil { 208 logger.Debug("Updating gossip metadate nodeMetastate", nodeMetastate) 209 g.UpdateChannelMetadata(b, common2.ChainID(s.chainID)) 210 } else { 211 logger.Errorf("Unable to serialize node meta nodeMetastate, error = %s", err) 212 } 213 214 s.done.Add(4) 215 216 // Listen for incoming communication 217 go s.listen() 218 // Deliver in order messages into the incoming channel 219 go s.deliverPayloads() 220 // Execute anti entropy to fill missing gaps 221 go s.antiEntropy() 222 // Taking care of state request messages 223 go s.processStateRequests() 224 225 return s 226 } 227 228 func (s *GossipStateProviderImpl) listen() { 229 defer s.done.Done() 230 231 for { 232 select { 233 case msg := <-s.gossipChan: 234 logger.Debug("Received new message via gossip channel") 235 go s.queueNewMessage(msg) 236 case msg := <-s.commChan: 237 logger.Debug("Direct message ", msg) 238 go s.directMessage(msg) 239 case <-s.stopCh: 240 s.stopCh <- struct{}{} 241 logger.Debug("Stop listening for new messages") 242 return 243 } 244 } 245 } 246 247 func (s *GossipStateProviderImpl) directMessage(msg proto.ReceivedMessage) { 248 logger.Debug("[ENTER] -> directMessage") 249 defer logger.Debug("[EXIT] -> directMessage") 250 251 if msg == nil { 252 logger.Error("Got nil message via end-to-end channel, should not happen!") 253 return 254 } 255 256 if !bytes.Equal(msg.GetGossipMessage().Channel, []byte(s.chainID)) { 257 logger.Warning("Received state transfer request for channel", 258 string(msg.GetGossipMessage().Channel), "while expecting channel", s.chainID, "skipping request...") 259 return 260 } 261 262 incoming := msg.GetGossipMessage() 263 264 if incoming.GetStateRequest() != nil { 265 if len(s.stateRequestCh) < defChannelBufferSize { 266 // Forward state request to the channel, if there are too 267 // many message of state request ignore to avoid flooding. 268 s.stateRequestCh <- msg 269 } 270 } else if incoming.GetStateResponse() != nil { 271 // If no state transfer procedure activate there is 272 // no reason to process the message 273 if atomic.LoadInt32(&s.stateTransferActive) == 1 { 274 // Send signal of state response message 275 s.stateResponseCh <- msg 276 } 277 } 278 } 279 280 func (s *GossipStateProviderImpl) processStateRequests() { 281 defer s.done.Done() 282 283 for { 284 select { 285 case msg := <-s.stateRequestCh: 286 s.handleStateRequest(msg) 287 case <-s.stopCh: 288 s.stopCh <- struct{}{} 289 return 290 } 291 } 292 } 293 294 // Handle state request message, validate batch size, read current leader state to 295 // obtain required blocks, build response message and send it back 296 func (s *GossipStateProviderImpl) handleStateRequest(msg proto.ReceivedMessage) { 297 if msg == nil { 298 return 299 } 300 request := msg.GetGossipMessage().GetStateRequest() 301 302 batchSize := request.EndSeqNum - request.StartSeqNum 303 if batchSize > defAntiEntropyBatchSize { 304 logger.Errorf("Requesting blocks batchSize size (%d) greater than configured allowed"+ 305 " (%d) batching for anti-entropy. Ignoring request...", batchSize, defAntiEntropyBatchSize) 306 return 307 } 308 309 if request.StartSeqNum > request.EndSeqNum { 310 logger.Errorf("Invalid sequence interval [%d...%d], ignoring request...", request.StartSeqNum, request.EndSeqNum) 311 return 312 } 313 314 currentHeight, err := s.committer.LedgerHeight() 315 if err != nil { 316 logger.Errorf("Cannot access to current ledger height, due to %s", err) 317 return 318 } 319 if currentHeight < request.EndSeqNum { 320 logger.Warningf("Received state request to transfer blocks with sequence numbers higher [%d...%d] "+ 321 "than available in ledger (%d)", request.StartSeqNum, request.StartSeqNum, currentHeight) 322 } 323 324 endSeqNum := min(currentHeight, request.EndSeqNum) 325 326 response := &proto.RemoteStateResponse{Payloads: make([]*proto.Payload, 0)} 327 for seqNum := request.StartSeqNum; seqNum <= endSeqNum; seqNum++ { 328 logger.Debug("Reading block ", seqNum, " from the committer service") 329 blocks := s.committer.GetBlocks([]uint64{seqNum}) 330 331 if len(blocks) == 0 { 332 logger.Errorf("Wasn't able to read block with sequence number %d from ledger, skipping....", seqNum) 333 continue 334 } 335 336 blockBytes, err := pb.Marshal(blocks[0]) 337 if err != nil { 338 logger.Errorf("Could not marshal block: %s", err) 339 } 340 341 response.Payloads = append(response.Payloads, &proto.Payload{ 342 SeqNum: seqNum, 343 Data: blockBytes, 344 }) 345 } 346 // Sending back response with missing blocks 347 msg.Respond(&proto.GossipMessage{ 348 // Copy nonce field from the request, so it will be possible to match response 349 Nonce: msg.GetGossipMessage().Nonce, 350 Tag: proto.GossipMessage_CHAN_OR_ORG, 351 Channel: []byte(s.chainID), 352 Content: &proto.GossipMessage_StateResponse{response}, 353 }) 354 } 355 356 func (s *GossipStateProviderImpl) handleStateResponse(msg proto.ReceivedMessage) (uint64, error) { 357 max := uint64(0) 358 // Send signal that response for given nonce has been received 359 response := msg.GetGossipMessage().GetStateResponse() 360 // Extract payloads, verify and push into buffer 361 if len(response.GetPayloads()) == 0 { 362 return uint64(0), errors.New("Received state tranfer response without payload") 363 } 364 for _, payload := range response.GetPayloads() { 365 logger.Debugf("Received payload with sequence number %d.", payload.SeqNum) 366 if err := s.mcs.VerifyBlock(common2.ChainID(s.chainID), payload.SeqNum, payload.Data); err != nil { 367 logger.Warningf("Error verifying block with sequence number %d, due to %s", payload.SeqNum, err) 368 return uint64(0), err 369 } 370 if max < payload.SeqNum { 371 max = payload.SeqNum 372 } 373 err := s.payloads.Push(payload) 374 if err != nil { 375 logger.Warningf("Payload with sequence number %d was received earlier", payload.SeqNum) 376 } 377 } 378 return max, nil 379 } 380 381 // Stop function send halting signal to all go routines 382 func (s *GossipStateProviderImpl) Stop() { 383 // Make sure stop won't be executed twice 384 // and stop channel won't be used again 385 s.once.Do(func() { 386 s.stopCh <- struct{}{} 387 // Make sure all go-routines has finished 388 s.done.Wait() 389 // Close all resources 390 s.committer.Close() 391 close(s.stateRequestCh) 392 close(s.stateResponseCh) 393 close(s.stopCh) 394 }) 395 } 396 397 // New message notification/handler 398 func (s *GossipStateProviderImpl) queueNewMessage(msg *proto.GossipMessage) { 399 if !bytes.Equal(msg.Channel, []byte(s.chainID)) { 400 logger.Warning("Received enqueue for channel", 401 string(msg.Channel), "while expecting channel", s.chainID, "ignoring enqueue") 402 return 403 } 404 405 dataMsg := msg.GetDataMsg() 406 if dataMsg != nil { 407 // Add new payload to ordered set 408 409 logger.Debugf("Received new payload with sequence number = [%d]", dataMsg.Payload.SeqNum) 410 s.payloads.Push(dataMsg.GetPayload()) 411 } else { 412 logger.Debug("Gossip message received is not of data message type, usually this should not happen.") 413 } 414 } 415 416 func (s *GossipStateProviderImpl) deliverPayloads() { 417 defer s.done.Done() 418 419 for { 420 select { 421 // Wait for notification that next seq has arrived 422 case <-s.payloads.Ready(): 423 logger.Debugf("Ready to transfer payloads to the ledger, next sequence number is = [%d]", s.payloads.Next()) 424 // Collect all subsequent payloads 425 for payload := s.payloads.Pop(); payload != nil; payload = s.payloads.Pop() { 426 rawBlock := &common.Block{} 427 if err := pb.Unmarshal(payload.Data, rawBlock); err != nil { 428 logger.Errorf("Error getting block with seqNum = %d due to (%s)...dropping block", payload.SeqNum, err) 429 continue 430 } 431 if rawBlock.Data == nil || rawBlock.Header == nil { 432 logger.Errorf("Block with claimed sequence %d has no header (%v) or data (%v)", 433 payload.SeqNum, rawBlock.Header, rawBlock.Data) 434 continue 435 } 436 logger.Debug("New block with claimed sequence number ", payload.SeqNum, " transactions num ", len(rawBlock.Data.Data)) 437 s.commitBlock(rawBlock) 438 } 439 case <-s.stopCh: 440 s.stopCh <- struct{}{} 441 logger.Debug("State provider has been stoped, finishing to push new blocks.") 442 return 443 } 444 } 445 } 446 447 func (s *GossipStateProviderImpl) antiEntropy() { 448 defer s.done.Done() 449 defer logger.Debug("State Provider stopped, stopping anti entropy procedure.") 450 451 for { 452 select { 453 case <-s.stopCh: 454 s.stopCh <- struct{}{} 455 return 456 case <-time.After(defAntiEntropyInterval): 457 current, err := s.committer.LedgerHeight() 458 if err != nil { 459 // Unable to read from ledger continue to the next round 460 logger.Error("Cannot obtain ledger height, due to", err) 461 continue 462 } 463 if current == 0 { 464 logger.Error("Ledger reported block height of 0 but this should be impossible") 465 continue 466 } 467 max := s.maxAvailableLedgerHeight() 468 469 if current-1 >= max { 470 continue 471 } 472 473 s.requestBlocksInRange(uint64(current), uint64(max)) 474 } 475 } 476 } 477 478 // Iterate over all available peers and check advertised meta state to 479 // find maximum available ledger height across peers 480 func (s *GossipStateProviderImpl) maxAvailableLedgerHeight() uint64 { 481 max := uint64(0) 482 for _, p := range s.gossip.PeersOfChannel(common2.ChainID(s.chainID)) { 483 if nodeMetastate, err := FromBytes(p.Metadata); err == nil { 484 if max < nodeMetastate.LedgerHeight { 485 max = nodeMetastate.LedgerHeight 486 } 487 } 488 } 489 return max 490 } 491 492 // GetBlocksInRange capable to acquire blocks with sequence 493 // numbers in the range [start...end]. 494 func (s *GossipStateProviderImpl) requestBlocksInRange(start uint64, end uint64) { 495 atomic.StoreInt32(&s.stateTransferActive, 1) 496 defer atomic.StoreInt32(&s.stateTransferActive, 0) 497 498 for prev := start; prev <= end; { 499 next := min(end, prev+defAntiEntropyBatchSize) 500 501 gossipMsg := s.stateRequestMessage(prev, next) 502 503 responseReceived := false 504 tryCounts := 0 505 506 for !responseReceived { 507 if tryCounts > defAntiEntropyMaxRetries { 508 logger.Warningf("Wasn't able to get blocks in range [%d...%d], after %d retries", 509 prev, next, tryCounts) 510 return 511 } 512 // Select peers to ask for blocks 513 peer, err := s.selectPeerToRequestFrom(next) 514 if err != nil { 515 logger.Warningf("Cannot send state request for blocks in range [%d...%d], due to", 516 prev, next, err) 517 return 518 } 519 520 logger.Debugf("State transfer, with peer %s, requesting blocks in range [%d...%d], "+ 521 "for chainID %s", peer.Endpoint, prev, next, s.chainID) 522 523 s.gossip.Send(gossipMsg, peer) 524 tryCounts++ 525 526 // Wait until timeout or response arrival 527 select { 528 case msg := <-s.stateResponseCh: 529 if msg.GetGossipMessage().Nonce != gossipMsg.Nonce { 530 continue 531 } 532 // Got corresponding response for state request, can continue 533 index, err := s.handleStateResponse(msg) 534 if err != nil { 535 logger.Warningf("Wasn't able to process state response for "+ 536 "blocks [%d...%d], due to %s", prev, next, err) 537 continue 538 } 539 prev = index + 1 540 responseReceived = true 541 case <-time.After(defAntiEntropyStateResponseTimeout): 542 case <-s.stopCh: 543 s.stopCh <- struct{}{} 544 return 545 } 546 } 547 } 548 } 549 550 // Generate state request message for given blocks in range [beginSeq...endSeq] 551 func (s *GossipStateProviderImpl) stateRequestMessage(beginSeq uint64, endSeq uint64) *proto.GossipMessage { 552 return &proto.GossipMessage{ 553 Nonce: util.RandomUInt64(), 554 Tag: proto.GossipMessage_CHAN_OR_ORG, 555 Channel: []byte(s.chainID), 556 Content: &proto.GossipMessage_StateRequest{ 557 StateRequest: &proto.RemoteStateRequest{ 558 StartSeqNum: beginSeq, 559 EndSeqNum: endSeq, 560 }, 561 }, 562 } 563 } 564 565 // Select peer which has required blocks to ask missing blocks from 566 func (s *GossipStateProviderImpl) selectPeerToRequestFrom(height uint64) (*comm.RemotePeer, error) { 567 // Filter peers which posses required range of missing blocks 568 peers := s.filterPeers(s.hasRequiredHeight(height)) 569 570 n := len(peers) 571 if n == 0 { 572 return nil, errors.New("there are no peers to ask for missing blocks from") 573 } 574 575 // Select peers to ask for blocks 576 return peers[util.RandomInt(n)], nil 577 } 578 579 // filterPeers return list of peers which aligns the predicate provided 580 func (s *GossipStateProviderImpl) filterPeers(predicate func(peer discovery.NetworkMember) bool) []*comm.RemotePeer { 581 var peers []*comm.RemotePeer 582 583 for _, member := range s.gossip.PeersOfChannel(common2.ChainID(s.chainID)) { 584 if predicate(member) { 585 peers = append(peers, &comm.RemotePeer{Endpoint: member.PreferredEndpoint(), PKIID: member.PKIid}) 586 } 587 } 588 589 return peers 590 } 591 592 // hasRequiredHeight returns predicate which is capable to filter peers with ledger height above than indicated 593 // by provided input parameter 594 func (s *GossipStateProviderImpl) hasRequiredHeight(height uint64) func(peer discovery.NetworkMember) bool { 595 return func(peer discovery.NetworkMember) bool { 596 if nodeMetadata, err := FromBytes(peer.Metadata); err != nil { 597 logger.Errorf("Unable to de-serialize node meta state, error = %s", err) 598 } else if nodeMetadata.LedgerHeight >= height { 599 return true 600 } 601 602 return false 603 } 604 } 605 606 // GetBlock return ledger block given its sequence number as a parameter 607 func (s *GossipStateProviderImpl) GetBlock(index uint64) *common.Block { 608 // Try to read missing block from the ledger, should return no nil with 609 // content including at least one block 610 if blocks := s.committer.GetBlocks([]uint64{index}); blocks != nil && len(blocks) > 0 { 611 return blocks[0] 612 } 613 614 return nil 615 } 616 617 // AddPayload add new payload into state 618 func (s *GossipStateProviderImpl) AddPayload(payload *proto.Payload) error { 619 620 logger.Debug("Adding new payload into the buffer, seqNum = ", payload.SeqNum) 621 return s.payloads.Push(payload) 622 } 623 624 func (s *GossipStateProviderImpl) commitBlock(block *common.Block) error { 625 if err := s.committer.Commit(block); err != nil { 626 logger.Errorf("Got error while committing(%s)", err) 627 return err 628 } 629 630 // Update ledger level within node metadata 631 nodeMetastate := NewNodeMetastate(block.Header.Number) 632 // Decode nodeMetastate to byte array 633 b, err := nodeMetastate.Bytes() 634 if err == nil { 635 s.gossip.UpdateChannelMetadata(b, common2.ChainID(s.chainID)) 636 } else { 637 638 logger.Errorf("Unable to serialize node meta nodeMetastate, error = %s", err) 639 } 640 641 logger.Debugf("Channel [%s]: Created block [%d] with %d transaction(s)", 642 s.chainID, block.Header.Number, len(block.Data.Data)) 643 644 return nil 645 } 646 647 func min(a uint64, b uint64) uint64 { 648 return b ^ ((a ^ b) & (-(uint64(a-b) >> 63))) 649 }