github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/orderer/sbft/simplebft/batch.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  	"fmt"
    21  	"reflect"
    22  
    23  	"github.com/golang/protobuf/proto"
    24  	"github.com/hyperledger/fabric/orderer/common/filter"
    25  )
    26  
    27  func (s *SBFT) makeBatch(seq uint64, prevHash []byte, data [][]byte) *Batch {
    28  	datahash := merkleHashData(data)
    29  
    30  	batchhead := &BatchHeader{
    31  		Seq:      seq,
    32  		PrevHash: prevHash,
    33  		DataHash: datahash,
    34  	}
    35  	rawHeader, err := proto.Marshal(batchhead)
    36  	if err != nil {
    37  		panic(err)
    38  	}
    39  	return &Batch{
    40  		Header:   rawHeader,
    41  		Payloads: data,
    42  	}
    43  }
    44  
    45  func (s *SBFT) checkBatch(b *Batch, checkData bool, needSigs bool) (*BatchHeader, error) {
    46  	batchheader := &BatchHeader{}
    47  	err := proto.Unmarshal(b.Header, batchheader)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  
    52  	if checkData {
    53  		datahash := merkleHashData(b.Payloads)
    54  		if !reflect.DeepEqual(datahash, batchheader.DataHash) {
    55  			return nil, fmt.Errorf("malformed batches: invalid hash")
    56  		}
    57  	}
    58  
    59  	if batchheader.PrevHash == nil {
    60  		// TODO check against root hash, which should be part of constructor
    61  	} else if needSigs {
    62  		if len(b.Signatures) < s.oneCorrectQuorum() {
    63  			return nil, fmt.Errorf("insufficient number of signatures on batches: need %d, got %d", s.oneCorrectQuorum(), len(b.Signatures))
    64  		}
    65  	}
    66  
    67  	bh := b.Hash()
    68  	for r, sig := range b.Signatures {
    69  		err = s.sys.CheckSig(bh, r, sig)
    70  		if err != nil {
    71  			return nil, err
    72  		}
    73  	}
    74  
    75  	return batchheader, nil
    76  }
    77  
    78  ////////////////////////////////////////
    79  
    80  // Hash returns the hash of the Batch.
    81  func (b *Batch) Hash() []byte {
    82  	return hash(b.Header)
    83  }
    84  
    85  func (b *Batch) DecodeHeader() *BatchHeader {
    86  	batchheader := &BatchHeader{}
    87  	err := proto.Unmarshal(b.Header, batchheader)
    88  	if err != nil {
    89  		panic(err)
    90  	}
    91  
    92  	return batchheader
    93  }
    94  
    95  func (s *SBFT) getCommittersFromBatch(reqBatch *Batch) (bool, []filter.Committer) {
    96  	reqs := make([]*Request, 0, len(reqBatch.Payloads))
    97  	for _, pl := range reqBatch.Payloads {
    98  		req := &Request{Payload: pl}
    99  		reqs = append(reqs, req)
   100  	}
   101  	batches := make([][]*Request, 0, 1)
   102  	comms := [][]filter.Committer{}
   103  	for _, r := range reqs {
   104  		b, c, valid := s.sys.Validate(s.chainId, r)
   105  		if !valid {
   106  			return false, nil
   107  		}
   108  		batches = append(batches, b...)
   109  		comms = append(comms, c...)
   110  	}
   111  	if len(batches) > 1 || len(batches) != len(comms) {
   112  		return false, nil
   113  	}
   114  
   115  	if len(batches) == 0 {
   116  		_, committer := s.sys.Cut(s.chainId)
   117  		return true, committer
   118  	} else {
   119  		return true, comms[0]
   120  	}
   121  }