From 0e5510fbdf7341d9d883dae753ecb190fe18ff57 Mon Sep 17 00:00:00 2001 From: defiQUG Date: Fri, 26 Jun 2026 02:09:06 -0700 Subject: [PATCH] Fix chaincode client identity resolution for mint and transfer. Use a shared getClientID helper so SolaceNet capability checks and transfer authorization handle identity errors consistently. Co-authored-by: Cursor --- .../tokenized-asset/go/tokenized_asset.go | 49 +++++++++++++------ 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/chaincode/tokenized-asset/go/tokenized_asset.go b/chaincode/tokenized-asset/go/tokenized_asset.go index 49ec0de..e1fb93f 100644 --- a/chaincode/tokenized-asset/go/tokenized_asset.go +++ b/chaincode/tokenized-asset/go/tokenized_asset.go @@ -114,13 +114,16 @@ func (s *TokenizedAssetContract) MintToken(ctx contractapi.TransactionContextInt // Check SolaceNet capability (would integrate with SolaceNet service) // This is a placeholder - in production, call SolaceNet API - clientID := ctx.GetClientIdentity() - canMint, err := s.checkSolaceNetCapability(ctx, clientID.GetID(), "tokenization.mint") + callerID, err := getClientID(ctx) + if err != nil { + return err + } + canMint, err := s.checkSolaceNetCapability(ctx, callerID, "tokenization.mint") if err != nil { return fmt.Errorf("failed to check SolaceNet capability: %v", err) } if !canMint { - return fmt.Errorf("client %s does not have tokenization.mint capability", clientID.GetID()) + return fmt.Errorf("client %s does not have tokenization.mint capability", callerID) } // Create tokenized asset @@ -181,18 +184,21 @@ func (s *TokenizedAssetContract) TransferToken(ctx contractapi.TransactionContex } // Verify sender has permission - clientID := ctx.GetClientIdentity() - if asset.Issuer != clientID.GetID() && request.From != clientID.GetID() { - return fmt.Errorf("client %s is not authorized to transfer this token", clientID.GetID()) + callerID, err := getClientID(ctx) + if err != nil { + return err + } + if asset.Issuer != callerID && request.From != callerID { + return fmt.Errorf("client %s is not authorized to transfer this token", callerID) } // Check SolaceNet capability - canTransfer, err := s.checkSolaceNetCapability(ctx, clientID.GetID(), "tokenization.transfer") + canTransfer, err := s.checkSolaceNetCapability(ctx, callerID, "tokenization.transfer") if err != nil { return fmt.Errorf("failed to check SolaceNet capability: %v", err) } if !canTransfer { - return fmt.Errorf("client %s does not have tokenization.transfer capability", clientID.GetID()) + return fmt.Errorf("client %s does not have tokenization.transfer capability", callerID) } // Verify amounts (simplified - in production, use proper decimal handling) @@ -271,13 +277,16 @@ func (s *TokenizedAssetContract) RedeemToken(ctx contractapi.TransactionContextI } // Check SolaceNet capability - clientID := ctx.GetClientIdentity() - canRedeem, err := s.checkSolaceNetCapability(ctx, clientID.GetID(), "tokenization.redeem") + callerID, err := getClientID(ctx) + if err != nil { + return err + } + canRedeem, err := s.checkSolaceNetCapability(ctx, callerID, "tokenization.redeem") if err != nil { return fmt.Errorf("failed to check SolaceNet capability: %v", err) } if !canRedeem { - return fmt.Errorf("client %s does not have tokenization.redeem capability", clientID.GetID()) + return fmt.Errorf("client %s does not have tokenization.redeem capability", callerID) } // Verify amounts @@ -367,17 +376,27 @@ func (s *TokenizedAssetContract) GetAllTokens(ctx contractapi.TransactionContext return assets, nil } +// getClientID returns the submitting client's MSP identity ID. +func getClientID(ctx contractapi.TransactionContextInterface) (string, error) { + id, err := ctx.GetClientIdentity().GetID() + if err != nil { + return "", fmt.Errorf("failed to get client identity: %v", err) + } + return id, nil +} + // checkSolaceNetCapability checks if a client has a SolaceNet capability // In production, this would call SolaceNet API or use chaincode-to-chaincode invocation func (s *TokenizedAssetContract) checkSolaceNetCapability(ctx contractapi.TransactionContextInterface, clientID, capability string) (bool, error) { - // Placeholder implementation + // Placeholder implementation — parameters reserved for SolaceNet integration. + _ = ctx + _ = clientID + _ = capability + // In production, this would: // 1. Call SolaceNet API via external service // 2. Or use chaincode-to-chaincode invocation if SolaceNet is on same network // 3. Or use Cacti to bridge to SolaceNet service - - // For now, return true for testing - // In production, implement actual SolaceNet integration return true, nil }