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 }