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  }