github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/orderer/sbft/backend/backend.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 backend 18 19 import ( 20 "bytes" 21 "fmt" 22 "io" 23 "sort" 24 "strings" 25 "sync" 26 "time" 27 28 "golang.org/x/net/context" 29 "google.golang.org/grpc" 30 "google.golang.org/grpc/transport" 31 32 "crypto/ecdsa" 33 crand "crypto/rand" 34 "math/big" 35 36 "crypto" 37 "crypto/rsa" 38 "crypto/sha256" 39 "encoding/asn1" 40 "encoding/gob" 41 42 "github.com/golang/protobuf/proto" 43 "github.com/hyperledger/fabric/orderer/common/filter" 44 commonfilter "github.com/hyperledger/fabric/orderer/common/filter" 45 "github.com/hyperledger/fabric/orderer/multichain" 46 "github.com/hyperledger/fabric/orderer/sbft/connection" 47 "github.com/hyperledger/fabric/orderer/sbft/persist" 48 s "github.com/hyperledger/fabric/orderer/sbft/simplebft" 49 cb "github.com/hyperledger/fabric/protos/common" 50 "github.com/op/go-logging" 51 ) 52 53 const headerIndex = 0 54 const signaturesIndex = 1 55 const metadataLen = 2 56 57 var logger = logging.MustGetLogger("backend") 58 59 type Backend struct { 60 conn *connection.Manager 61 lock sync.Mutex 62 peers map[uint64]chan<- *s.MultiChainMsg 63 queue chan Executable 64 persistence *persist.Persist 65 66 self *PeerInfo 67 // address to PeerInfo mapping 68 peerInfo map[string]*PeerInfo 69 70 // chainId to instance mapping 71 consensus map[string]s.Receiver 72 lastBatches map[string]*s.Batch 73 supports map[string]multichain.ConsenterSupport 74 } 75 76 type consensusConn Backend 77 78 type StackConfig struct { 79 ListenAddr string 80 CertFile string 81 KeyFile string 82 DataDir string 83 } 84 85 type PeerInfo struct { 86 info connection.PeerInfo 87 id uint64 88 } 89 90 type peerInfoSlice []*PeerInfo 91 92 func (pi peerInfoSlice) Len() int { 93 return len(pi) 94 } 95 96 func (pi peerInfoSlice) Less(i, j int) bool { 97 return strings.Compare(pi[i].info.Fingerprint(), pi[j].info.Fingerprint()) == -1 98 } 99 100 func (pi peerInfoSlice) Swap(i, j int) { 101 pi[i], pi[j] = pi[j], pi[i] 102 } 103 104 func NewBackend(peers map[string][]byte, conn *connection.Manager, persist *persist.Persist) (*Backend, error) { 105 c := &Backend{ 106 conn: conn, 107 peers: make(map[uint64]chan<- *s.MultiChainMsg), 108 peerInfo: make(map[string]*PeerInfo), 109 supports: make(map[string]multichain.ConsenterSupport), 110 consensus: make(map[string]s.Receiver), 111 lastBatches: make(map[string]*s.Batch), 112 } 113 114 var peerInfo []*PeerInfo 115 for addr, cert := range peers { 116 pi, err := connection.NewPeerInfo(addr, cert) 117 if err != nil { 118 return nil, err 119 } 120 cpi := &PeerInfo{info: pi} 121 if pi.Fingerprint() == conn.Self.Fingerprint() { 122 c.self = cpi 123 } 124 peerInfo = append(peerInfo, cpi) 125 c.peerInfo[pi.Fingerprint()] = cpi 126 } 127 128 sort.Sort(peerInfoSlice(peerInfo)) 129 for i, pi := range peerInfo { 130 pi.id = uint64(i) 131 logger.Infof("replica %d: %s", i, pi.info.Fingerprint()) 132 } 133 134 if c.self == nil { 135 return nil, fmt.Errorf("peer list does not contain local node") 136 } 137 138 logger.Infof("we are replica %d (%s)", c.self.id, c.self.info) 139 140 for _, peer := range c.peerInfo { 141 if peer == c.self { 142 continue 143 } 144 go c.connectWorker(peer) 145 } 146 RegisterConsensusServer(conn.Server, (*consensusConn)(c)) 147 c.persistence = persist 148 c.queue = make(chan Executable) 149 go c.run() 150 return c, nil 151 } 152 153 // GetMyId returns the ID of the backend in the SFTT network (1..N) 154 func (b *Backend) GetMyId() uint64 { 155 return b.self.id 156 } 157 158 // Enqueue enqueues an Envelope for a chainId for ordering, marshalling it first 159 func (b *Backend) Enqueue(chainID string, env *cb.Envelope) bool { 160 requestbytes, err := proto.Marshal(env) 161 if err != nil { 162 return false 163 } 164 b.enqueueRequest(chainID, requestbytes) 165 return true 166 } 167 168 func (b *Backend) connectWorker(peer *PeerInfo) { 169 timeout := 1 * time.Second 170 171 delay := time.After(0) 172 for { 173 // pace reconnect attempts 174 <-delay 175 176 // set up for next 177 delay = time.After(timeout) 178 179 logger.Infof("connecting to replica %d (%s)", peer.id, peer.info) 180 conn, err := b.conn.DialPeer(peer.info, grpc.WithBlock(), grpc.WithTimeout(timeout)) 181 if err != nil { 182 logger.Warningf("could not connect to replica %d (%s): %s", peer.id, peer.info, err) 183 continue 184 } 185 186 ctx := context.TODO() 187 188 client := NewConsensusClient(conn) 189 consensus, err := client.Consensus(ctx, &Handshake{}) 190 if err != nil { 191 logger.Warningf("could not establish consensus stream with replica %d (%s): %s", peer.id, peer.info, err) 192 continue 193 } 194 logger.Noticef("connection to replica %d (%s) established", peer.id, peer.info) 195 196 for { 197 msg, err := consensus.Recv() 198 if err == io.EOF || err == transport.ErrConnClosing { 199 break 200 } 201 if err != nil { 202 logger.Warningf("consensus stream with replica %d (%s) broke: %v", peer.id, peer.info, err) 203 break 204 } 205 b.enqueueForReceive(msg.ChainID, msg.Msg, peer.id) 206 } 207 } 208 } 209 210 func (b *Backend) enqueueConnection(chainID string, peerid uint64) { 211 go func() { 212 b.queue <- &connectionEvent{chainID: chainID, peerid: peerid} 213 }() 214 } 215 216 func (b *Backend) enqueueRequest(chainID string, request []byte) { 217 go func() { 218 b.queue <- &requestEvent{chainId: chainID, req: request} 219 }() 220 } 221 222 func (b *Backend) enqueueForReceive(chainID string, msg *s.Msg, src uint64) { 223 go func() { 224 b.queue <- &msgEvent{chainId: chainID, msg: msg, src: src} 225 }() 226 } 227 228 func (b *Backend) initTimer(t *Timer, d time.Duration) { 229 send := func() { 230 if t.execute { 231 b.queue <- t 232 } 233 } 234 time.AfterFunc(d, send) 235 } 236 237 func (b *Backend) run() { 238 for { 239 e := <-b.queue 240 e.Execute(b) 241 } 242 } 243 244 // AddSbftPeer adds a new SBFT peer for the given chainId using the given support and configuration 245 func (b *Backend) AddSbftPeer(chainID string, support multichain.ConsenterSupport, config *s.Config) (*s.SBFT, error) { 246 b.supports[chainID] = support 247 return s.New(b.GetMyId(), chainID, config, b) 248 } 249 250 func (b *Backend) Validate(chainID string, req *s.Request) ([][]*s.Request, [][]filter.Committer, bool) { 251 // ([][]*cb.Envelope, [][]filter.Committer, bool) { 252 // If the message is a valid normal message and fills a batch, the batch, committers, true is returned 253 // If the message is a valid special message (like a config message) it terminates the current batch 254 // and returns the current batch and committers (if it is not empty), plus a second batch containing the special transaction and commiter, and true 255 env := &cb.Envelope{} 256 err := proto.Unmarshal(req.Payload, env) 257 if err != nil { 258 logger.Panicf("Request format error: %s", err) 259 } 260 envbatch, committers, accepted := b.supports[chainID].BlockCutter().Ordered(env) 261 if accepted { 262 if len(envbatch) == 1 { 263 rb1 := toRequestBatch(envbatch[0]) 264 return [][]*s.Request{rb1}, committers, true 265 } 266 if len(envbatch) == 2 { 267 rb1 := toRequestBatch(envbatch[0]) 268 rb2 := toRequestBatch(envbatch[1]) 269 return [][]*s.Request{rb1, rb2}, committers, true 270 } 271 272 return nil, nil, true 273 } 274 return nil, nil, false 275 } 276 277 func (b *Backend) Cut(chainID string) ([]*s.Request, []filter.Committer) { 278 envbatch, committers := b.supports[chainID].BlockCutter().Cut() 279 return toRequestBatch(envbatch), committers 280 } 281 282 func toRequestBatch(envelopes []*cb.Envelope) []*s.Request { 283 rqs := make([]*s.Request, 0, len(envelopes)) 284 for _, e := range envelopes { 285 requestbytes, err := proto.Marshal(e) 286 if err != nil { 287 logger.Panicf("Cannot marshal envelope: %s", err) 288 } 289 rq := &s.Request{Payload: requestbytes} 290 rqs = append(rqs, rq) 291 } 292 return rqs 293 } 294 295 // Consensus implements the SBFT consensus gRPC interface 296 func (c *consensusConn) Consensus(_ *Handshake, srv Consensus_ConsensusServer) error { 297 pi := connection.GetPeerInfo(srv) 298 peer, ok := c.peerInfo[pi.Fingerprint()] 299 300 if !ok || !peer.info.Cert().Equal(pi.Cert()) { 301 logger.Infof("rejecting connection from unknown replica %s", pi) 302 return fmt.Errorf("unknown peer certificate") 303 } 304 logger.Infof("connection from replica %d (%s)", peer.id, pi) 305 306 ch := make(chan *s.MultiChainMsg) 307 c.lock.Lock() 308 if oldch, ok := c.peers[peer.id]; ok { 309 logger.Debugf("replacing connection from replica %d", peer.id) 310 close(oldch) 311 } 312 c.peers[peer.id] = ch 313 c.lock.Unlock() 314 315 for chainID, _ := range c.supports { 316 ((*Backend)(c)).enqueueConnection(chainID, peer.id) 317 } 318 319 var err error 320 for msg := range ch { 321 err = srv.Send(msg) 322 if err != nil { 323 c.lock.Lock() 324 delete(c.peers, peer.id) 325 c.lock.Unlock() 326 327 logger.Infof("lost connection from replica %d (%s): %s", peer.id, pi, err) 328 } 329 } 330 331 return err 332 } 333 334 // Unicast sends to all external SBFT peers 335 func (b *Backend) Broadcast(msg *s.MultiChainMsg) error { 336 b.lock.Lock() 337 for _, ch := range b.peers { 338 ch <- msg 339 } 340 b.lock.Unlock() 341 return nil 342 } 343 344 // Unicast sends to a specific external SBFT peer identified by chainId and dest 345 func (b *Backend) Unicast(chainID string, msg *s.Msg, dest uint64) error { 346 b.lock.Lock() 347 ch, ok := b.peers[dest] 348 b.lock.Unlock() 349 350 if !ok { 351 err := fmt.Errorf("peer not found: %v", dest) 352 logger.Debug(err) 353 return err 354 } 355 ch <- &s.MultiChainMsg{Msg: msg, ChainID: chainID} 356 return nil 357 } 358 359 // AddReceiver adds a receiver instance for a given chainId 360 func (b *Backend) AddReceiver(chainId string, recv s.Receiver) { 361 b.consensus[chainId] = recv 362 b.lastBatches[chainId] = &s.Batch{Header: nil, Signatures: nil, Payloads: [][]byte{}} 363 } 364 365 // Send sends to a specific SBFT peer identified by chainId and dest 366 func (b *Backend) Send(chainID string, msg *s.Msg, dest uint64) { 367 if dest == b.self.id { 368 b.enqueueForReceive(chainID, msg, b.self.id) 369 return 370 } 371 b.Unicast(chainID, msg, dest) 372 } 373 374 // Timer starts a timer 375 func (b *Backend) Timer(d time.Duration, tf func()) s.Canceller { 376 tm := &Timer{tf: tf, execute: true} 377 b.initTimer(tm, d) 378 return tm 379 } 380 381 // Deliver writes a block 382 func (b *Backend) Deliver(chainId string, batch *s.Batch, committers []commonfilter.Committer) { 383 blockContents := make([]*cb.Envelope, 0, len(batch.Payloads)) 384 for _, p := range batch.Payloads { 385 envelope := &cb.Envelope{} 386 err := proto.Unmarshal(p, envelope) 387 if err == nil { 388 blockContents = append(blockContents, envelope) 389 } else { 390 logger.Warningf("Payload cannot be unmarshalled.") 391 } 392 } 393 block := b.supports[chainId].CreateNextBlock(blockContents) 394 395 // TODO SBFT needs to use Rawledger's structures and signatures over the Block. 396 // This a quick and dirty solution to make it work. 397 block.Metadata = &cb.BlockMetadata{} 398 metadata := make([][]byte, metadataLen) 399 metadata[headerIndex] = batch.Header 400 metadata[signaturesIndex] = encodeSignatures(batch.Signatures) 401 block.Metadata.Metadata = metadata 402 b.lastBatches[chainId] = batch 403 b.supports[chainId].WriteBlock(block, committers, nil) 404 } 405 406 // Persist persists data identified by a chainId and a key 407 func (b *Backend) Persist(chainId string, key string, data proto.Message) { 408 compk := fmt.Sprintf("chain-%s-%s", chainId, key) 409 if data == nil { 410 b.persistence.DelState(compk) 411 } else { 412 bytes, err := proto.Marshal(data) 413 if err != nil { 414 panic(err) 415 } 416 b.persistence.StoreState(compk, bytes) 417 } 418 } 419 420 // Restore loads persisted data identified by chainId and key 421 func (b *Backend) Restore(chainId string, key string, out proto.Message) bool { 422 compk := fmt.Sprintf("chain-%s-%s", chainId, key) 423 val, err := b.persistence.ReadState(compk) 424 if err != nil { 425 return false 426 } 427 err = proto.Unmarshal(val, out) 428 return (err == nil) 429 } 430 431 // LastBatch returns the last batch for a given chain identified by its ID 432 func (b *Backend) LastBatch(chainId string) *s.Batch { 433 return b.lastBatches[chainId] 434 } 435 436 // Sign signs a given data 437 func (b *Backend) Sign(data []byte) []byte { 438 return Sign(b.conn.Cert.PrivateKey, data) 439 } 440 441 // CheckSig checks a signature 442 func (b *Backend) CheckSig(data []byte, src uint64, sig []byte) error { 443 leaf := b.conn.Cert.Leaf 444 if leaf == nil { 445 panic("No public key found: certificate leaf is nil.") 446 } 447 return CheckSig(leaf.PublicKey, data, sig) 448 } 449 450 // Reconnect requests connection to a replica identified by its ID and chainId 451 func (b *Backend) Reconnect(chainId string, replica uint64) { 452 b.enqueueConnection(chainId, replica) 453 } 454 455 // Sign signs a given data 456 func Sign(privateKey crypto.PrivateKey, data []byte) []byte { 457 var err error 458 var encsig []byte 459 hash := sha256.Sum256(data) 460 switch pvk := privateKey.(type) { 461 case *rsa.PrivateKey: 462 encsig, err = pvk.Sign(crand.Reader, hash[:], crypto.SHA256) 463 if err != nil { 464 panic(err) 465 } 466 case *ecdsa.PrivateKey: 467 r, s, err := ecdsa.Sign(crand.Reader, pvk, hash[:]) 468 if err != nil { 469 panic(err) 470 } 471 encsig, err = asn1.Marshal(struct{ R, S *big.Int }{r, s}) 472 default: 473 panic("Unsupported private key type given.") 474 } 475 if err != nil { 476 panic(err) 477 } 478 return encsig 479 } 480 481 // CheckSig checks a signature 482 func CheckSig(publicKey crypto.PublicKey, data []byte, sig []byte) error { 483 hash := sha256.Sum256(data) 484 switch p := publicKey.(type) { 485 case *ecdsa.PublicKey: 486 s := struct{ R, S *big.Int }{} 487 rest, err := asn1.Unmarshal(sig, &s) 488 if err != nil { 489 return err 490 } 491 if len(rest) != 0 { 492 return fmt.Errorf("invalid signature (problem with asn unmarshalling for ECDSA)") 493 } 494 ok := ecdsa.Verify(p, hash[:], s.R, s.S) 495 if !ok { 496 return fmt.Errorf("invalid signature (problem with verification)") 497 } 498 return nil 499 case *rsa.PublicKey: 500 err := rsa.VerifyPKCS1v15(p, crypto.SHA256, hash[:], sig) 501 return err 502 default: 503 return fmt.Errorf("Unsupported public key type.") 504 } 505 } 506 507 func encodeSignatures(signatures map[uint64][]byte) []byte { 508 var buf bytes.Buffer 509 enc := gob.NewEncoder(&buf) 510 err := enc.Encode(signatures) 511 if err != nil { 512 panic(err) 513 } 514 return buf.Bytes() 515 } 516 517 func decodeSignatures(encodedSignatures []byte) map[uint64][]byte { 518 if len(encodedSignatures) == 0 { 519 return nil 520 } 521 buf := bytes.NewBuffer(encodedSignatures) 522 var r map[uint64][]byte 523 dec := gob.NewDecoder(buf) 524 err := dec.Decode(&r) 525 if err != nil { 526 panic(err) 527 } 528 return r 529 }