Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Commit eb9b94b

Browse files
[FAB-3902] RegisterTxEvent to return error code
Change-Id: I500d4a793b45bf9ec3bbd580e08e31b3c597076a Signed-off-by: biljana lukovic <biljana.lukovic@securekey.com>
1 parent 9bc35ce commit eb9b94b

File tree

4 files changed

+95
-11
lines changed

4 files changed

+95
-11
lines changed

fabric-client/events/eventhub.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ type EventHub interface {
4949
Disconnect()
5050
RegisterChaincodeEvent(ccid string, eventname string, callback func(*ChaincodeEvent)) *ChainCodeCBE
5151
UnregisterChaincodeEvent(cbe *ChainCodeCBE)
52-
RegisterTxEvent(txID string, callback func(string, error))
52+
RegisterTxEvent(txID string, callback func(string, pb.TxValidationCode, error))
5353
UnregisterTxEvent(txID string)
5454
RegisterBlockEvent(callback func(*common.Block))
5555
UnregisterBlockEvent(callback func(*common.Block))
@@ -74,7 +74,7 @@ type eventHub struct {
7474
// Map of clients registered for block events
7575
blockRegistrants []func(*common.Block)
7676
// Map of clients registered for transactional events
77-
txRegistrants map[string]func(string, error)
77+
txRegistrants map[string]func(string, pb.TxValidationCode, error)
7878
// peer addr to connect to
7979
peerAddr string
8080
// peer tls certificate
@@ -125,7 +125,7 @@ func (ccf *consumerClientFactory) newEventsClient(peerAddress string, certificat
125125
func NewEventHub() EventHub {
126126
chaincodeRegistrants := make(map[string][]*ChainCodeCBE)
127127
blockRegistrants := make([]func(*common.Block), 0)
128-
txRegistrants := make(map[string]func(string, error))
128+
txRegistrants := make(map[string]func(string, pb.TxValidationCode, error))
129129

130130
eventHub := &eventHub{
131131
chaincodeRegistrants: chaincodeRegistrants,
@@ -395,7 +395,7 @@ func (eventHub *eventHub) UnregisterChaincodeEvent(cbe *ChainCodeCBE) {
395395
* @param {function} callback Function that takes a single parameter which
396396
* is a json object representation of type "message Transaction"
397397
*/
398-
func (eventHub *eventHub) RegisterTxEvent(txID string, callback func(string, error)) {
398+
func (eventHub *eventHub) RegisterTxEvent(txID string, callback func(string, pb.TxValidationCode, error)) {
399399
logger.Debugf("reg txid %s\n", txID)
400400

401401
eventHub.mtx.Lock()
@@ -424,6 +424,7 @@ func (eventHub *eventHub) txCallback(block *common.Block) {
424424

425425
txFilter := util.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
426426
for i, v := range block.Data.Data {
427+
427428
if env, err := utils.GetEnvelopeFromBlock(v); err != nil {
428429
logger.Errorf("error extracting Envelope from block: %v\n", err)
429430
return
@@ -446,10 +447,9 @@ func (eventHub *eventHub) txCallback(block *common.Block) {
446447
callback := eventHub.getTXRegistrant(channelHeader.TxId)
447448
if callback != nil {
448449
if txFilter.IsInvalid(i) {
449-
callback(channelHeader.TxId, fmt.Errorf("Received invalid transaction from channel %s\n", channelHeader.ChannelId))
450-
450+
callback(channelHeader.TxId, txFilter.Flag(i), fmt.Errorf("Received invalid transaction from channel %s", channelHeader.ChannelId))
451451
} else {
452-
callback(channelHeader.TxId, nil)
452+
callback(channelHeader.TxId, txFilter.Flag(i), nil)
453453
}
454454
} else {
455455
logger.Debugf("No callback registered for TxID: %s\n", channelHeader.TxId)
@@ -487,7 +487,7 @@ func (eventHub *eventHub) getChaincodeRegistrants(chaincodeID string) []*ChainCo
487487
return clone
488488
}
489489

490-
func (eventHub *eventHub) getTXRegistrant(txID string) func(string, error) {
490+
func (eventHub *eventHub) getTXRegistrant(txID string) func(string, pb.TxValidationCode, error) {
491491
eventHub.mtx.RLock()
492492
defer eventHub.mtx.RUnlock()
493493
return eventHub.txRegistrants[txID]

fabric-client/events/eventhub_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func TestDeadlock(t *testing.T) {
6262
go flood(eventsPerThread, threads, func() {
6363
transactionID := generateTxID()
6464
received := newCompletionHandler(timeout)
65-
eventHub.RegisterTxEvent(transactionID, func(txID string, err error) {
65+
eventHub.RegisterTxEvent(transactionID, func(txID string, code pb.TxValidationCode, err error) {
6666
txCompletion.done()
6767
received.done()
6868
})

fabric-client/helpers/events.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ limitations under the License.
1919

2020
package helpers
2121

22-
import "github.com/hyperledger/fabric-sdk-go/fabric-client/events"
22+
import (
23+
"github.com/hyperledger/fabric-sdk-go/fabric-client/events"
24+
pb "github.com/hyperledger/fabric/protos/peer"
25+
)
2326

2427
// RegisterTxEvent registers on the given eventhub for the give transaction
2528
// returns a boolean channel which receives true when the event is complete
@@ -28,7 +31,7 @@ func RegisterTxEvent(txID string, eventHub events.EventHub) (chan bool, chan err
2831
done := make(chan bool)
2932
fail := make(chan error)
3033

31-
eventHub.RegisterTxEvent(txID, func(txId string, err error) {
34+
eventHub.RegisterTxEvent(txID, func(txId string, errorCode pb.TxValidationCode, err error) {
3235
if err != nil {
3336
logger.Debugf("Received error event for txid(%s)\n", txId)
3437
fail <- err

test/integration/events_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
fabricClient "github.com/hyperledger/fabric-sdk-go/fabric-client"
2828
fcUtil "github.com/hyperledger/fabric-sdk-go/fabric-client/helpers"
2929
"github.com/hyperledger/fabric/protos/common"
30+
pb "github.com/hyperledger/fabric/protos/peer"
3031
)
3132

3233
func TestEvents(t *testing.T) {
@@ -55,6 +56,7 @@ func TestEvents(t *testing.T) {
5556

5657
testFailedTx(t, testSetup)
5758

59+
testFailedTxErrorCode(t, testSetup)
5860
// Test disconnect event hub
5961
testSetup.EventHub.Disconnect()
6062
if testSetup.EventHub.IsConnected() {
@@ -109,6 +111,7 @@ func testFailedTx(t *testing.T, testSetup BaseSetupImpl) {
109111
select {
110112
case <-done1:
111113
case <-fail1:
114+
t.Fatalf("Received fail for second invoke")
112115
case <-done2:
113116
t.Fatalf("Received success for second invoke")
114117
case <-fail2:
@@ -121,6 +124,84 @@ func testFailedTx(t *testing.T, testSetup BaseSetupImpl) {
121124

122125
}
123126

127+
func testFailedTxErrorCode(t *testing.T, testSetup BaseSetupImpl) {
128+
129+
// Arguments for events CC
130+
var args []string
131+
args = append(args, "invoke")
132+
args = append(args, "invoke")
133+
args = append(args, "SEVERE")
134+
135+
tpResponses1, tx1, err := fcUtil.CreateAndSendTransactionProposal(testSetup.Chain, testSetup.ChainCodeID, testSetup.ChainID, args, []fabricClient.Peer{testSetup.Chain.GetPrimaryPeer()}, nil)
136+
if err != nil {
137+
t.Fatalf("CreateAndSendTransactionProposal return error: %v \n", err)
138+
}
139+
140+
tpResponses2, tx2, err := fcUtil.CreateAndSendTransactionProposal(testSetup.Chain, testSetup.ChainCodeID, testSetup.ChainID, args, []fabricClient.Peer{testSetup.Chain.GetPrimaryPeer()}, nil)
141+
if err != nil {
142+
t.Fatalf("CreateAndSendTransactionProposal return error: %v \n", err)
143+
}
144+
145+
done := make(chan bool)
146+
fail := make(chan error)
147+
var errorValidationCode pb.TxValidationCode
148+
testSetup.EventHub.RegisterTxEvent(tx1, func(txId string, errorCode pb.TxValidationCode, err error) {
149+
if err != nil {
150+
errorValidationCode = errorCode
151+
fail <- err
152+
} else {
153+
done <- true
154+
}
155+
})
156+
157+
defer testSetup.EventHub.UnregisterTxEvent(tx1)
158+
159+
done2 := make(chan bool)
160+
fail2 := make(chan error)
161+
162+
testSetup.EventHub.RegisterTxEvent(tx2, func(txId string, errorCode pb.TxValidationCode, err error) {
163+
if err != nil {
164+
errorValidationCode = errorCode
165+
fail2 <- err
166+
} else {
167+
done2 <- true
168+
}
169+
})
170+
171+
defer testSetup.EventHub.UnregisterTxEvent(tx2)
172+
173+
// Test invalid transaction: create 2 invoke requests in quick succession that modify
174+
// the same state variable which should cause one invoke to be invalid
175+
_, err = fcUtil.CreateAndSendTransaction(testSetup.Chain, tpResponses1)
176+
if err != nil {
177+
t.Fatalf("First invoke failed err: %v", err)
178+
}
179+
_, err = fcUtil.CreateAndSendTransaction(testSetup.Chain, tpResponses2)
180+
if err != nil {
181+
t.Fatalf("Second invoke failed err: %v", err)
182+
}
183+
184+
for i := 0; i < 2; i++ {
185+
select {
186+
case <-done:
187+
case <-fail:
188+
t.Fatalf("Received fail for second invoke")
189+
case <-done2:
190+
t.Fatalf("Received success for second invoke")
191+
case <-fail2:
192+
// success
193+
fmt.Println("Received error validation Code ", errorValidationCode)
194+
if errorValidationCode.String() != "MVCC_READ_CONFLICT" {
195+
t.Fatalf("Expected error code MVCC_READ_CONFLICT")
196+
}
197+
return
198+
case <-time.After(time.Second * 30):
199+
t.Fatalf("invoke Didn't receive block event for txid1(%s) or txid1(%s)", tx1, tx2)
200+
}
201+
}
202+
203+
}
204+
124205
func testMultipleBlockEventCallbacks(t *testing.T, testSetup BaseSetupImpl) {
125206

126207
// Arguments for events CC

0 commit comments

Comments
 (0)