@@ -72,6 +72,12 @@ func (r *RequestApprovalResponderView) Call(context view.Context) (any, error) {
7272 }
7373 defer request .Rws .Done ()
7474
75+ // validate proposal
76+ err = r .validateProposal (context , request )
77+ if err != nil {
78+ return nil , errors .Join (ErrValidateProposal , err )
79+ }
80+
7581 // validate
7682 err = r .validate (context , request , func (id token.ID ) ([]byte , error ) {
7783 key , err := r .keyTranslator .CreateOutputKey (id .TxId , id .Index )
@@ -153,7 +159,7 @@ func (r *RequestApprovalResponderView) receive(ctx view.Context) (*Request, erro
153159 return nil , errors .Wrapf (ErrInvalidProposal , "non empty namespaces" )
154160 }
155161
156- // TODO: check that tx contains a valid endorser proposal
162+ // Validate chaincode name and version
157163 if name , version := tx .Chaincode (); name != tmsID .Namespace || version != ChaincodeVersion {
158164 return nil , errors .Wrapf (ErrInvalidProposal , "invalid chaincode" )
159165 }
@@ -180,6 +186,80 @@ func (r *RequestApprovalResponderView) receive(ctx view.Context) (*Request, erro
180186 }, nil
181187}
182188
189+ func (r * RequestApprovalResponderView ) validateProposal (ctx view.Context , request * Request ) error {
190+ logger .DebugfContext (ctx .Context (), "Validate proposal for TX [%s]" , request .Anchor )
191+
192+ // Get the signed proposal from the underlying Fabric transaction
193+ signedProposal := request .Tx .Transaction .SignedProposal ()
194+ if signedProposal == nil {
195+ return errors .Errorf ("signed proposal is nil for tx [%s]" , request .Anchor )
196+ }
197+
198+ // Get the proposal
199+ proposal := request .Tx .Transaction .Proposal ()
200+ if proposal == nil {
201+ return errors .Errorf ("proposal is nil for tx [%s]" , request .Anchor )
202+ }
203+
204+ // Verify the proposal signature
205+ // The signature verification ensures that the proposal was signed by the creator
206+ creator := request .Tx .Transaction .Creator ()
207+ if len (creator ) == 0 {
208+ return errors .Errorf ("creator is empty for tx [%s]" , request .Anchor )
209+ }
210+
211+ // Get the proposal bytes for signature verification from the signed proposal
212+ proposalBytes := signedProposal .ProposalBytes ()
213+ if len (proposalBytes ) == 0 {
214+ return errors .Errorf ("proposal bytes are empty for tx [%s]" , request .Anchor )
215+ }
216+
217+ // Verify the signature on the proposal
218+ signature := signedProposal .Signature ()
219+ if len (signature ) == 0 {
220+ return errors .Errorf ("proposal signature is empty for tx [%s]" , request .Anchor )
221+ }
222+
223+ // Verify the signature over the proposal using the TMS signature service
224+ // Try to get a verifier for the creator identity - try owner, issuer, and auditor verifiers
225+ sigService := request .Tms .SigService ()
226+
227+ // Try owner verifier first
228+ verifier , err := sigService .OwnerVerifier (ctx .Context (), creator )
229+ if err != nil {
230+ // Try issuer verifier
231+ verifier , err = sigService .IssuerVerifier (ctx .Context (), creator )
232+ if err != nil {
233+ // Try auditor verifier
234+ verifier , err = sigService .AuditorVerifier (ctx .Context (), creator )
235+ if err != nil {
236+ return errors .Wrapf (err , "failed to get verifier for creator for tx [%s]" , request .Anchor )
237+ }
238+ }
239+ }
240+
241+ // Verify the signature
242+ err = verifier .Verify (proposalBytes , signature )
243+ if err != nil {
244+ return errors .Wrapf (err , "failed to verify proposal signature for tx [%s]" , request .Anchor )
245+ }
246+
247+ // Validate that the token actions in the request are consistent with the proposal
248+ // The token request should match what's in the transient data
249+ // This ensures the relationship between the action, read-write set, and token actions
250+ if len (request .RequestRaw ) == 0 {
251+ return errors .Errorf ("token request is empty for tx [%s]" , request .Anchor )
252+ }
253+
254+ // The actions will be validated in the validate() method which checks:
255+ // - Token actions are valid
256+ // - Read-write set is consistent with the actions
257+ // - Signatures on token actions are valid
258+
259+ logger .DebugfContext (ctx .Context (), "Proposal signature verified successfully for TX [%s]" , request .Anchor )
260+ return nil
261+ }
262+
183263func (r * RequestApprovalResponderView ) translate (ctx context.Context , request * Request ) error {
184264 // prepare the rws as usual
185265 txID := request .Anchor
0 commit comments