github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/orderer/sbft/simplebft/preprepare.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 simplebft
    18  
    19  import (
    20  	"bytes"
    21  	"time"
    22  
    23  	"github.com/hyperledger/fabric/orderer/common/filter"
    24  )
    25  
    26  func (s *SBFT) sendPreprepare(batch []*Request, committers []filter.Committer) {
    27  	seq := s.nextSeq()
    28  
    29  	data := make([][]byte, len(batch))
    30  	for i, req := range batch {
    31  		data[i] = req.Payload
    32  	}
    33  
    34  	lasthash := hash(s.sys.LastBatch(s.chainId).Header)
    35  
    36  	m := &Preprepare{
    37  		Seq:   &seq,
    38  		Batch: s.makeBatch(seq.Seq, lasthash, data),
    39  	}
    40  
    41  	s.sys.Persist(s.chainId, preprepared, m)
    42  	s.broadcast(&Msg{&Msg_Preprepare{m}})
    43  	log.Infof("replica %d: sendPreprepare", s.id)
    44  	s.handleCheckedPreprepare(m, committers)
    45  }
    46  
    47  func (s *SBFT) handlePreprepare(pp *Preprepare, src uint64) {
    48  	if src == s.id {
    49  		log.Infof("replica %d: ignoring preprepare from self: %d", s.id, src)
    50  		return
    51  	}
    52  	if src != s.primaryID() {
    53  		log.Infof("replica %d: preprepare from non-primary %d", s.id, src)
    54  		return
    55  	}
    56  	nextSeq := s.nextSeq()
    57  	if *pp.Seq != nextSeq {
    58  		log.Infof("replica %d: preprepare does not match expected %v, got %v", s.id, nextSeq, *pp.Seq)
    59  		return
    60  	}
    61  	if s.cur.subject.Seq.Seq == pp.Seq.Seq {
    62  		log.Infof("replica %d: duplicate preprepare for %v", s.id, *pp.Seq)
    63  		return
    64  	}
    65  	if pp.Batch == nil {
    66  		log.Infof("replica %d: preprepare without batches", s.id)
    67  		return
    68  	}
    69  
    70  	batchheader, err := s.checkBatch(pp.Batch, true, false)
    71  	if err != nil || batchheader.Seq != pp.Seq.Seq {
    72  		log.Infof("replica %d: preprepare %v batches head inconsistent from %d: %s", s.id, pp.Seq, src, err)
    73  		return
    74  	}
    75  
    76  	prevhash := s.sys.LastBatch(s.chainId).Hash()
    77  	if !bytes.Equal(batchheader.PrevHash, prevhash) {
    78  		log.Infof("replica %d: preprepare batches prev hash does not match expected %s, got %s", s.id, hash2str(batchheader.PrevHash), hash2str(prevhash))
    79  		return
    80  	}
    81  
    82  	blockOK, committers := s.getCommittersFromBatch(pp.Batch)
    83  	if !blockOK {
    84  		log.Debugf("Replica %d found Byzantine block in preprepare, Seq: %d View: %d", s.id, pp.Seq.Seq, pp.Seq.View)
    85  		s.sendViewChange()
    86  		return
    87  	}
    88  	log.Infof("replica %d: handlePrepare", s.id)
    89  	s.handleCheckedPreprepare(pp, committers)
    90  }
    91  
    92  func (s *SBFT) acceptPreprepare(pp *Preprepare, committers []filter.Committer) {
    93  	sub := Subject{Seq: pp.Seq, Digest: pp.Batch.Hash()}
    94  
    95  	log.Infof("replica %d: accepting preprepare for %v, %x", s.id, sub.Seq, sub.Digest)
    96  	s.sys.Persist(s.chainId, preprepared, pp)
    97  
    98  	s.cur = reqInfo{
    99  		subject:    sub,
   100  		timeout:    s.sys.Timer(time.Duration(s.config.RequestTimeoutNsec)*time.Nanosecond, s.requestTimeout),
   101  		preprep:    pp,
   102  		prep:       make(map[uint64]*Subject),
   103  		commit:     make(map[uint64]*Subject),
   104  		checkpoint: make(map[uint64]*Checkpoint),
   105  		committers: committers,
   106  	}
   107  }
   108  
   109  func (s *SBFT) handleCheckedPreprepare(pp *Preprepare, committers []filter.Committer) {
   110  	s.acceptPreprepare(pp, committers)
   111  	if !s.isPrimary() {
   112  		s.sendPrepare()
   113  		s.processBacklog()
   114  	}
   115  
   116  	s.maybeSendCommit()
   117  }
   118  
   119  ////////////////////////////////////////////////
   120  
   121  func (s *SBFT) requestTimeout() {
   122  	log.Infof("replica %d: request timed out: %s", s.id, s.cur.subject.Seq)
   123  	s.sendViewChange()
   124  }