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 }