@@ -7,172 +7,107 @@ SPDX-License-Identifier: Apache-2.0
77package ttx
88
99import (
10- "encoding/base64"
11- "time"
12-
1310 "github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors"
1411 "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/id"
1512 "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/sig"
16- "github.com/hyperledger-labs/fabric-smart-client/platform/view/services/storage/kvs"
1713 "github.com/hyperledger-labs/fabric-smart-client/platform/view/view"
18- "github.com/hyperledger-labs/fabric-token-sdk/token"
1914 "github.com/hyperledger-labs/fabric-token-sdk/token/services/tokens"
2015 "github.com/hyperledger-labs/fabric-token-sdk/token/services/utils"
21- session2 "github.com/hyperledger-labs/fabric-token-sdk/token/services/utils/json/session"
2216)
2317
18+ // AcceptView is used to accept tokens without the need to generate any signature.
19+ // This is a view executed by a responder.
20+ // This view is to be used in conjunction with CollectEndorsementsView.
21+ // Usually, AcceptView is preceded by an invocation of `tx.ReceiveTransaction(context)`
22+ // necessary if the initiator has invoked CollectEndorsementsView.
2423type AcceptView struct {
25- tx * Transaction
26- options * EndorsementsOpts
24+ tx * Transaction
25+ opts [] EndorsementsOpt
2726}
2827
28+ // NewAcceptView returns a new instance of AcceptView given in input a transaction.
2929func NewAcceptView (tx * Transaction , opts ... EndorsementsOpt ) * AcceptView {
30- options , err := CompileCollectEndorsementsOpts (opts ... )
31- if err != nil {
32- panic (err )
33- }
34- return & AcceptView {tx : tx , options : options }
30+ return & AcceptView {tx : tx , opts : opts }
3531}
3632
33+ // Call accepts the tokens created by the transaction this view has been created with.
3734func (s * AcceptView ) Call (context view.Context ) (interface {}, error ) {
38- if err := s .respondToSignatureRequests (context ); err != nil {
39- return nil , err
35+ // validate inputs
36+ if s .tx == nil {
37+ return nil , errors .WithMessagef (ErrInvalidInput , "transaction is nil" )
4038 }
4139
42- // Store transaction in the token transaction database
40+ // store transaction in the token transaction database
4341 if err := StoreTransactionRecords (context , s .tx ); err != nil {
4442 return nil , errors .Wrapf (err , "failed storing transaction records %s" , s .tx .ID ())
4543 }
4644
45+ // ack
46+ if err := s .ack (context ); err != nil {
47+ return nil , errors .Wrapf (err , "failed acknowledging transaction %s" , s .tx .ID ())
48+ }
49+
50+ // metrics
51+ labels := []string {
52+ "network" , s .tx .Network (),
53+ "channel" , s .tx .Channel (),
54+ "namespace" , s .tx .Namespace (),
55+ }
56+ GetMetrics (context ).AcceptedTransactions .With (labels ... ).Add (1 )
57+
58+ // cache request
59+ if err := s .cacheRequest (context ); err != nil {
60+ return nil , errors .Wrapf (err , "failed caching request for [%s]" , s .tx .ID ())
61+ }
62+
63+ return s .tx , nil
64+ }
65+
66+ // ack sends back an acknowledgement by signing the received transaction
67+ // with the identity of the FSC node running this stack.
68+ func (s * AcceptView ) ack (context view.Context ) error {
4769 txRaw := s .tx .FromRaw
48- // Send back an acknowledgement
4970 idProvider , err := id .GetProvider (context )
5071 if err != nil {
51- return nil , errors .Wrapf (err , "failed to get identity provider" )
72+ return errors .Wrapf (err , "failed to get identity provider" )
5273 }
5374 defaultIdentity := idProvider .DefaultIdentity ()
5475
5576 logger .DebugfContext (context .Context (), "signing ack response [%s] with identity [%s]" , utils .Hashable (txRaw ), defaultIdentity )
5677 sigService , err := sig .GetService (context )
5778 if err != nil {
58- return nil , errors .Wrapf (err , "failed to get sig service" )
79+ return errors .Wrapf (err , "failed to get sig service" )
5980 }
6081 signer , err := sigService .GetSigner (defaultIdentity )
6182 if err != nil {
62- return nil , errors .WithMessagef (err , "failed to get signer for default identity" )
83+ return errors .WithMessagef (err , "failed to get signer for default identity" )
6384 }
6485 logger .DebugfContext (context .Context (), "Sign ack for distribution" )
6586 sigma , err := signer .Sign (txRaw )
6687 if err != nil {
67- return nil , errors .WithMessagef (err , "failed to sign ack response" )
88+ return errors .WithMessagef (err , "failed to sign ack response" )
6889 }
6990
7091 // Ack for distribution
7192 // Send the signature back
7293 session := context .Session ()
7394 logger .DebugfContext (context .Context (), "ack response: [%s] from [%s]" , utils .Hashable (sigma ), defaultIdentity )
7495 if err := session .SendWithContext (context .Context (), sigma ); err != nil {
75- return nil , errors .WithMessagef (err , "failed sending ack" )
96+ return errors .WithMessagef (err , "failed sending ack" )
7697 }
98+ return nil
99+ }
77100
101+ func (s * AcceptView ) cacheRequest (context view.Context ) error {
78102 // cache the token request into the tokens db
79103 t , err := tokens .GetService (context , s .tx .TMSID ())
80104 if err != nil {
81- return nil , errors .Wrapf (err , "failed to get tokens db for [%s]" , s .tx .TMSID ())
105+ return errors .Wrapf (err , "failed to get tokens db for [%s]" , s .tx .TMSID ())
82106 }
83107
84108 if err := t .CacheRequest (context .Context (), s .tx .TMSID (), s .tx .TokenRequest ); err != nil {
85109 logger .WarnfContext (context .Context (), "failed to cache token request [%s], this might cause delay, investigate when possible: [%s]" , s .tx .TokenRequest .Anchor , err )
86110 }
87111
88- labels := []string {
89- "network" , s .tx .Network (),
90- "channel" , s .tx .Channel (),
91- "namespace" , s .tx .Namespace (),
92- }
93- GetMetrics (context ).AcceptedTransactions .With (labels ... ).Add (1 )
94-
95- return s .tx , nil
96- }
97-
98- func (s * AcceptView ) respondToSignatureRequests (context view.Context ) error {
99- requestsToBeSigned , err := requestsToBeSigned (context .Context (), s .tx .TokenRequest )
100- if err != nil {
101- return errors .Wrapf (err , "failed collecting requests of signature" )
102- }
103- logger .DebugfContext (context .Context (), "respond to signature requests [%s][%d]" , s .tx .ID (), len (requestsToBeSigned ))
104-
105- session := context .Session ()
106- for i := range requestsToBeSigned {
107- logger .DebugfContext (context .Context (), "Sign request no %d" , i )
108- signatureRequest := & SignatureRequest {}
109-
110- if i == 0 {
111- logger .DebugfContext (context .Context (), "First request is fetched from KVS" )
112- k , err := kvs .CreateCompositeKey ("signatureRequest" , []string {s .tx .ID ()})
113- if err != nil {
114- return errors .Wrap (err , "failed to generate key to store signature request" )
115- }
116- var srStr string
117- if kvss , err := context .GetService (& kvs.KVS {}); err != nil {
118- return errors .Wrap (err , "failed to get KVS from context" )
119- } else if err := kvss .(* kvs.KVS ).Get (context .Context (), k , & srStr ); err != nil {
120- return errors .Wrap (err , "failed to store signature request" )
121- }
122- srRaw , err := base64 .StdEncoding .DecodeString (srStr )
123- if err != nil {
124- return errors .Wrap (err , "failed to decode signature request" )
125- }
126- if err := Unmarshal (srRaw , signatureRequest ); err != nil {
127- return errors .Wrap (err , "failed unmarshalling signature request" )
128- }
129- } else {
130- logger .DebugfContext (context .Context (), "Receiving signature request..." )
131- jsonSession := session2 .JSON (context )
132- err := jsonSession .ReceiveWithTimeout (signatureRequest , time .Minute )
133- if err != nil {
134- return errors .Wrap (err , "failed reading signature request" )
135- }
136- }
137- logger .DebugfContext (context .Context (), "Fetched request from session" )
138- tms , err := token .GetManagementService (context , token .WithTMS (s .tx .Network (), s .tx .Channel (), s .tx .Namespace ()))
139- if err != nil {
140- return errors .Wrapf (err , "failed getting TMS for [%s:%s:%s]" , s .tx .Network (), s .tx .Channel (), s .tx .Namespace ())
141- }
142-
143- if ! tms .SigService ().IsMe (context .Context (), signatureRequest .Signer ) {
144- return errors .Errorf ("identity [%s] is not me" , signatureRequest .Signer .UniqueID ())
145- }
146- signer , err := s .tx .TokenService ().SigService ().GetSigner (context .Context (), signatureRequest .Signer )
147- if err != nil {
148- return errors .Wrapf (err , "cannot find signer for [%s]" , signatureRequest .Signer .UniqueID ())
149- }
150- logger .DebugfContext (context .Context (), "Sign message" )
151- sigma , err := signer .Sign (signatureRequest .MessageToSign ())
152- if err != nil {
153- return errors .Wrapf (err , "failed signing request" )
154- }
155- logger .DebugfContext (context .Context (), "Send back signature..." )
156-
157- err = session .SendWithContext (context .Context (), sigma )
158- if err != nil {
159- return errors .Wrapf (err , "failed sending signature back" )
160- }
161- }
162-
163- if len (requestsToBeSigned ) > 0 {
164- logger .DebugfContext (context .Context (), "wait the transaction to be sent back [%s]" , s .tx .ID ())
165- // expect again to receive a transaction
166- tx , err := ReceiveTransaction (context )
167- if err != nil {
168- return errors .Wrapf (err , "expected to receive a transaction" )
169- }
170- // TODO: check that the token requests match
171- s .tx = tx
172- logger .DebugfContext (context .Context (), "wait the transaction to be sent back [%s], received" , s .tx .ID ())
173- } else {
174- logger .DebugfContext (context .Context (), "no need to wait the transaction to be sent back [%s]" , s .tx .ID ())
175- }
176-
177112 return nil
178113}
0 commit comments