github.com/cranelv/ethereum_mpc@v0.0.0-20191031014521-23aeb1415092/consensus_pbft/helper/engine.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 helper
    18  
    19  import (
    20  	"github.com/ethereum/go-ethereum/consensus_pbft"
    21  	"github.com/ethereum/go-ethereum/consensus_pbft/peer"
    22  
    23  	"fmt"
    24  	"sync"
    25  
    26  	"github.com/ethereum/go-ethereum/consensus_pbft/controller"
    27  	"github.com/ethereum/go-ethereum/consensus_pbft/util"
    28  	"golang.org/x/net/context"
    29  	"github.com/ethereum/go-ethereum/log"
    30  	"github.com/ethereum/go-ethereum/consensus_pbft/message"
    31  	"github.com/ethereum/go-ethereum/consensus_pbft/singletons"
    32  	"github.com/ethereum/go-ethereum/consensus_pbft/pbftTypes"
    33  )
    34  
    35  // EngineImpl implements a struct to hold consensus.Consenter, PeerEndpoint and MessageFan
    36  type EngineImpl struct {
    37  	consenter    consensus_pbft.Consenter
    38  	helper       *Helper
    39  	peer         pbftTypes.Peer
    40  	consensusFan *util.MessageFan
    41  	txExecute message.TaskExecuteInterface
    42  }
    43  
    44  // GetHandlerFactory returns new NewConsensusHandler
    45  func (eng *EngineImpl) GetHandlerFactory() peer.HandlerFactory {
    46  	return NewConsensusHandler
    47  }
    48  
    49  // ProcessTransactionMsg processes a Message in context of a Transaction
    50  func (eng *EngineImpl) ProcessTaskMsg(msg *message.Message, task *message.Task) (response *peer.Response) {
    51  	//TODO: Do we always verify security, or can we supply a flag on the invoke ot this functions so to bypass check for locally generated transactions?
    52  	if true /*tx.Type == pb.Transaction_CHAINCODE_QUERY*/ {
    53  		if !engine.helper.valid {
    54  			singletons.Log.Warn("Rejecting query because state is currently not valid")
    55  			return &peer.Response{Status: peer.Response_FAILURE,
    56  				Msg: []byte("Error: state may be inconsistent, cannot query")}
    57  		}
    58  
    59  		// The secHelper is set during creat ChaincodeSupport, so we don't need this step
    60  		// cxt := context.WithValue(context.Background(), "security", secHelper)
    61  		cxt := context.Background()
    62  		//query will ignore events as these are not stored on ledger (and query can report
    63  		//"event" data synchronously anyway)
    64  		result, err := eng.txExecute.Execute(cxt, task)
    65  		if err != nil {
    66  			response = &peer.Response{Status: peer.Response_FAILURE,
    67  				Msg: []byte(fmt.Sprintf("Error:%s", err))}
    68  		} else {
    69  			response = &peer.Response{Status: peer.Response_SUCCESS, Msg: result.Paload}
    70  		}
    71  	} else {
    72  		// Chaincode Transaction
    73  		response = &peer.Response{Status: peer.Response_SUCCESS, Msg: task.Paload}
    74  
    75  		//TODO: Do we need to verify security, or can we supply a flag on the invoke ot this functions
    76  		// If we fail to marshal or verify the tx, don't send it to consensus plugin
    77  		if response.Status == peer.Response_FAILURE {
    78  			return response
    79  		}
    80  
    81  		// Pass the message to the consenter (eg. PBFT) NOTE: Make sure engine has been initialized
    82  		if eng.consenter == nil {
    83  			return &peer.Response{Status: peer.Response_FAILURE, Msg: []byte("Engine not initialized")}
    84  		}
    85  		// TODO, do we want to put these requests into a queue? This will block until
    86  		// the consenter gets around to handling the message, but it also provides some
    87  		// natural feedback to the REST API to determine how long it takes to queue messages
    88  		err := eng.consenter.RecvMsg(msg, eng.peer.GetPeerId())
    89  		if err != nil {
    90  			response = &peer.Response{Status: peer.Response_FAILURE, Msg: []byte(err.Error())}
    91  		}
    92  	}
    93  	return response
    94  }
    95  
    96  func (eng *EngineImpl) setConsenter(consenter consensus_pbft.Consenter) *EngineImpl {
    97  	eng.consenter = consenter
    98  	return eng
    99  }
   100  
   101  func (eng *EngineImpl) setNode(peer pbftTypes.Peer) *EngineImpl {
   102  	eng.peer = peer
   103  	return eng
   104  }
   105  
   106  var engineOnce sync.Once
   107  
   108  var engine *EngineImpl
   109  
   110  func getEngineImpl() *EngineImpl {
   111  	return engine
   112  }
   113  
   114  // GetEngine returns initialized peer.Engine
   115  func GetEngine(coord peer.MessageHandlerCoordinator) (peer.Engine, error) {
   116  	var err error
   117  	engineOnce.Do(func() {
   118  		engine = new(EngineImpl)
   119  		engine.helper = NewHelper(coord)
   120  		engine.consenter = controller.NewConsenter(engine.helper)
   121  		engine.helper.setConsenter(engine.consenter)
   122  		engine.peer = coord.(pbftTypes.Peer)
   123  		engine.consensusFan = util.NewMessageFan()
   124  
   125  		go func() {
   126  			log.Debug("Starting up message thread for consenter")
   127  
   128  			// The channel never closes, so this should never break
   129  			for msg := range engine.consensusFan.GetOutChannel() {
   130  				engine.consenter.RecvMsg(msg.Msg, msg.Sender)
   131  			}
   132  		}()
   133  	})
   134  	return engine, err
   135  }