MCPcopy
hub / github.com/hyperledger/fabric / HandleTransaction

Method HandleTransaction

core/chaincode/handler.go:247–311  ·  view source on GitHub ↗

HandleTransaction is a middleware function that obtains and verifies a transaction context prior to forwarding the message to the provided delegate. Response messages returned by the delegate are sent to the chat stream. Any errors returned by the delegate are packaged as chaincode error messages.

(msg *pb.ChaincodeMessage, delegate handleFunc)

Source from the content-addressed store, hash-verified

245// returned by the delegate are sent to the chat stream. Any errors returned by the
246// delegate are packaged as chaincode error messages.
247func (h *Handler) HandleTransaction(msg *pb.ChaincodeMessage, delegate handleFunc) {
248 startTime := time.Now()
249 meterLabels := []string{
250 "type", msg.Type.String(),
251 "channel", msg.ChannelId,
252 "chaincode", h.chaincodeID,
253 }
254
255 // Recover from panics that can occur when the transaction context is cleaned up
256 // (e.g., iterators closed) due to execution timeout while this goroutine is still
257 // actively using those resources. This prevents peer crashes from nil pointer
258 // dereferences in the underlying LevelDB iterator.
259 // See https://github.com/hyperledger/fabric/issues/5048
260 defer func() {
261 if r := recover(); r != nil {
262 chaincodeLogger.Errorf("[%s] Recovered from panic handling %s: %v", shorttxid(msg.Txid), msg.Type, r)
263 resp := &pb.ChaincodeMessage{
264 Type: pb.ChaincodeMessage_ERROR,
265 Payload: []byte(fmt.Sprintf("%s failed: transaction ID: %s: panic during execution", msg.Type, msg.Txid)),
266 Txid: msg.Txid,
267 ChannelId: msg.ChannelId,
268 }
269 h.ActiveTransactions.Remove(msg.ChannelId, msg.Txid)
270 h.serialSendAsync(resp)
271
272 meterLabels = append(meterLabels, "success", "false")
273 h.Metrics.ShimRequestDuration.With(meterLabels...).Observe(time.Since(startTime).Seconds())
274 h.Metrics.ShimRequestsCompleted.With(meterLabels...).Add(1)
275 }
276 }()
277
278 chaincodeLogger.Debugf("[%s] handling %s from chaincode", shorttxid(msg.Txid), msg.Type.String())
279 if !h.registerTxid(msg) {
280 return
281 }
282
283 var txContext *TransactionContext
284 var err error
285 if msg.Type == pb.ChaincodeMessage_INVOKE_CHAINCODE {
286 txContext, err = h.getTxContextForInvoke(msg.ChannelId, msg.Txid, msg.Payload, "")
287 } else {
288 txContext, err = h.isValidTxSim(msg.ChannelId, msg.Txid, "no ledger context")
289 }
290
291 h.Metrics.ShimRequestsReceived.With(meterLabels...).Add(1)
292
293 var resp *pb.ChaincodeMessage
294 if err == nil {
295 resp, err = delegate(msg, txContext)
296 }
297
298 if err != nil {
299 err = errors.Wrapf(err, "%s failed: transaction ID: %s", msg.Type, msg.Txid)
300 chaincodeLogger.Errorf("[%s] Failed to handle %s. error: %+v", shorttxid(msg.Txid), msg.Type, err)
301 resp = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: []byte(err.Error()), Txid: msg.Txid, ChannelId: msg.ChannelId}
302 }
303
304 chaincodeLogger.Debugf("[%s] Completed %s. Sending %s", shorttxid(msg.Txid), msg.Type, resp.Type)

Callers 2

handler_test.goFile · 0.80

Calls 14

serialSendAsyncMethod · 0.95
registerTxidMethod · 0.95
getTxContextForInvokeMethod · 0.95
isValidTxSimMethod · 0.95
DebugfMethod · 0.80
shorttxidFunction · 0.70
NowMethod · 0.65
ErrorfMethod · 0.65
RemoveMethod · 0.65
WithMethod · 0.65
AddMethod · 0.65
ErrorMethod · 0.65

Tested by

no test coverage detected