Beispiel #1
0
class OrchestratorProtocol( pb.Root ) :

    #-------------------------------------------------
    def __init__ (self) :
        log.startLogging(sys.stdout)
        log.msg("Server Running...")
        self.orchestrator = Orchestrator( )

    #-------------------------------------------------
    # Send group is set message to all users in the group
    def groupIsSet(self, groupID):        

        participants = self.orchestrator.getParticipants(groupID)
        for user in participants :
            params = self.orchestrator.getGroupIsSetParameters( user, groupID )

            log.msg ('sending groupIsSet message to {0}'.format(user))
            
            self.orchestrator.getUserRef(user).callRemote \
                ( "groupIsSet", groupID.encode(), params[0], params[1], params[2] ) 
        return

    #--------------------------------------------------
    # operations available to remote in this section
    #-------------------------------------------------- 

    # Register user with Orchestrator
    def remote_register(self, username, ref):
        self.orchestrator.register( username, ref )

    #-------------------------------------------------
    def remote_createGroup(self, proposer, m, n):
        try :
            results =  self.orchestrator.createGroup(proposer, m, n)
        except Exception as inst:
            raise OrchestratorError( inst.args )

        groupId = results[0]
        inviteList = results[1]

        for invitee in inviteList :
            invitee.callRemote("invite", groupId).addCallback \
                    (self.acceptInviteCallback)

        return groupId 


    #-------------------------------------------------
    # This sends a request for data to all participants of group
    def remote_sharePublicKey( self, user, groupId, calcType ) :
        groupId = groupId.decode()
        self.orchestrator.setCalcType (groupId, calcType.decode())         

        if not self.orchestrator.validGroup(groupId) :
            errMsg = 'Group Id is not valid: {0}'.format(groupId)
            raise OrchestratorError( errMsg )

        if self.orchestrator.isLocked(groupId) :
            errMsg = 'Group Id is locked, try again later: {0}'.format(groupId)
            raise OrchestratorError( errMsg )
        
        self.orchestrator.lock(groupId)

        participants = self.orchestrator.getParticipants(groupId)

        if user not in participants :
            errMsg = 'user is not in the group: {0}'.format(user)
            raise OrchestratorError( errMsg ) 
        
        userRefs = self.orchestrator.getUserReferences(groupId)
        calcType = self.orchestrator.calcType( groupId )
        for ref in userRefs :
            ref.callRemote("requestData", groupId, calcType).addCallback \
                (self.collateDataCallback)        
        return 

    #-------------------------------------------------
    def remote_sharePublicKeyCompleted( self, groupId, user ) :
        groupId = groupId.decode()
        self.orchestrator.unLock( groupId )


    #-------------------------------------------------
    def remote_initiatePresigning( self, user, groupId, number ) :
        groupId = groupId.decode()
                
        if self.orchestrator.isLocked(groupId) :
            errMsg = 'Group Id is locked, try again later: {0}'.format(groupId)
            raise OrchestratorError( errMsg )  

        self.orchestrator.lock( groupId ) 
        return [user, groupId, number]

    #-------------------------------------------------
    # This sends a request for data to all participants of group
    def remote_presigning( self, user, groupId, calcType ) :
        
        groupId = groupId.decode()
        calcType = calcType.decode()
        self.orchestrator.setCalcType( groupId, calcType )
       
        log.msg("presigning: user={0}, groupId={1}, calcType={2}".format(user, groupId, calcType) )

        if not self.orchestrator.validGroup(groupId) :
            errMsg = 'Group Id is not valid: {0}'.format(groupId)
            raise OrchestratorError( errMsg )


        participants = self.orchestrator.getParticipants(groupId)

        if user not in participants :
            errMsg = 'user is not in the group: {0}'.format(user)
            raise OrchestratorError( errMsg ) 

        userRefs = self.orchestrator.getUserReferences(groupId)
        for ref in userRefs :
            ref.callRemote("requestData", groupId, calcType).addCallback \
                (self.collateDataCallback)        
        return
    
    #-------------------------------------------------
    def remote_presigningCompleted( self, groupId ) :
        groupId = groupId.decode()

        if not self.orchestrator.validGroup(groupId) :
            errMsg = 'Group Id is not valid: {0}'.format(groupId)
            raise OrchestratorError( errMsg )

        self.orchestrator.unLock( groupId )


    #-------------------------------------------------
    def remote_collateVWData( self, groupId, ordinal, data ) :
        log.msg("Collating VW Data")
        groupId = groupId.decode()
        if self.orchestrator.collateVWData( groupId, ordinal, data ) :
            collatedData = self.orchestrator.getCollatedVWData( groupId )

            # send the public data out to all group participants
            userRefs = self.orchestrator.getUserReferences( groupId )
            for ref in userRefs :
                ref.callRemote( "sharedVWData", groupId, collatedData)
    
    
    #-------------------------------------------------        
    def remote_ephemeralKeyCompleted( self, groupId, user ) :
        groupId = groupId.decode()
        log.msg("EphemeralKey has been completed, groupId = {0}, user = {1}".format \
            (groupId, user))
        
        if self.orchestrator.allEphemeralKeysCompleted( user, groupId ) :
            # send the public data out to all group participants
            userRefs = self.orchestrator.getUserReferences( groupId )
            for ref in userRefs :
                ref.callRemote( "completed", groupId)

    
    #-------------------------------------------------
    # This sends a request for data to all participants of group
    def remote_sign( self, user, groupId, msg ) :
        log.msg("remote_sign")
        groupId = groupId.decode()
        msg = msg.decode()
       
        log.msg("sign: user={0}, groupId={1}, msg={2}".format(user, groupId, msg))

        if not self.orchestrator.validGroup(groupId) :
            errMsg = 'Group Id is not valid: {0}'.format(groupId)
            raise OrchestratorError( errMsg )

        if self.orchestrator.isLocked(groupId) :
            errMsg = 'Group Id is locked, try again later: {0}'.format(groupId)
            raise OrchestratorError( errMsg )
        
        self.orchestrator.lock(groupId)        

        participants = self.orchestrator.getParticipants(groupId)

        # check the user is in the group, then set the signer
        if user not in participants :
            errMsg = 'user is not in the group: {0}'.format(user)
            raise OrchestratorError( errMsg ) 
        self.orchestrator.setSigner(groupId, user)

        userRefs = self.orchestrator.getUserReferences(groupId)
        for ref in userRefs :
            ref.callRemote("requestSignatureData", groupId, msg).addCallback \
                (self.signingCallback)        
        return


    #-------------------------------------------------
    # routes eval (f_x) through from the fromOridnal, to toOrdinal
    def remote_routeEvals(self, gid, user, toOrdinal, fromOrdinal, f_x) :
        groupId = gid.decode()
        log.msg("routeEvals. toOrdinal={0}, fromOrdinal={1}, f_x={2}".format(toOrdinal, fromOrdinal, f_x))

        # go from ordinal to user
        refDict = self.orchestrator.getPtpReferences( user, groupId )
        refDict[toOrdinal].callRemote("distributeEvals", \
            groupId, toOrdinal, fromOrdinal, f_x)
        return 
        
    #-------------------------------------------------
    # called when a Player has received all their Evals
    def remote_receivedAllEvals(self, gid, ordinal ) :
        log.msg("receivedAllEvals")
        groupId = gid.decode()

        # if all Players have received their Eval data then continue
        if self.orchestrator.allEvalsReceived( groupId, ordinal ) :

            collatedData = self.orchestrator.getCollatedData( groupId) 
            
            # send the public data out to all group participants
            userRefs = self.orchestrator.getUserReferences( groupId )
            for ref in userRefs :
                ref.callRemote( "createSecret", groupId, self.orchestrator.calcType(groupId), collatedData[0], collatedData[1])\
                    .addCallbacks(self.secretVerificationCallback, self.verificationErrorCallback)


    #--------------------------------------------------
    # Callback operations available in this section
    #-------------------------------------------------- 

    def acceptInviteCallback(self, data ) :
        
        user        = data[0]
        groupID     = data[1]
        acceptance  = data[2]    

        if self.orchestrator.acceptInvite(user, groupID, acceptance) :
            self.groupIsSet(groupID)


    #-------------------------------------------------
    # collate data
    def collateDataCallback(self,  data ) :
        #JAS
        # TODO : can remove user from this as not used here!
        log.msg('collateDataCallback')
        groupId     = data[0]
        ordinal     = data[1]
        user        = data[2] 
        hiddenPoly  = data[3]
        hiddenEvals = data[4]

        # if True then ready to distribute data

        if self.orchestrator.collateData( groupId, ordinal, hiddenPoly, hiddenEvals) :

            # Call the shareEvals, pass in a different set of ordinal:refs for each
            userRefs        = self.orchestrator.getUserReferences( groupId )

            participants = self.orchestrator.getParticipants( groupId )
            
            for p, ref in zip(participants, userRefs) :
                newUserRefs = self.orchestrator.getPtpReferences( p, groupId )
                toOrdinals = []
                for key, value in newUserRefs.items() :
                    
                    toOrdinals.append(key)

                log.msg(toOrdinals)
                ref.callRemote("shareEvals", groupId, toOrdinals )
                

            log.msg('finished in collateDataCallback')

            # // following part is the orig                    
            #collatedData = self.orchestrator.getCollatedData(groupId) 
            
            # send the public data out to all group participants
            #userRefs = self.orchestrator.getUserReferences( groupId )
            #for ref in userRefs :
            #    ref.callRemote( "createSecret", groupId, self.orchestrator.calcType(groupId), collatedData[0], collatedData[1], collatedData[2])\
            #        .addCallbacks(self.secretVerificationCallback, self.verificationErrorCallback)


    #-------------------------------------------------
    # Receives verification from all group members
    def secretVerificationCallback(self, data):

        user        = data[0]
        groupId     = data[1]


        if self.orchestrator.secretVerification(user, groupId) :
            calcType = self.orchestrator.calcType(groupId)
            log.msg("secretVerification complete for: {0}".format(calcType))

            # contact all the group participants with verification success
            userRefs = self.orchestrator.getUserReferences(groupId)
            for ref in userRefs :
                ref.callRemote("groupIsVerified", groupId, calcType)


    #-------------------------------------------------
    def verificationErrorCallback(self, data):

        l = data.value.split("'")[1::2]

        user    = l[0]
        groupId = l[1]
        reason  = l[2]

        log.msg ("Verification Error: groupId = {0}, user = {1}, reason = {2}".format\
                ( groupId, user, reason ))

        # contact all the group participants to delete group
        userRefs = self.orchestrator.getUserReferences(groupId)
        for ref in userRefs :
            ref.callRemote("deleteGroup", groupId )

    #-------------------------------------------------
    # Signing callback with data: 
    def signingCallback(self,  data ) :
        log.msg("signingCallback")
        groupId     = data[0]
        ordinal     = data[1]
        sig         = data[2]
        msg         = data[3]
        
        # if True then ready to distribute data
        if self.orchestrator.signature( groupId, ordinal, sig) :
            signatureData = self.orchestrator.getSignatureData(groupId) 
            
            # send the signature data out to the signer
            userRef = self.orchestrator.getSignerReference( groupId )
            userRef.callRemote( "readyToSign", groupId, msg, signatureData) \
                .addCallbacks(self.signingCompletedCallback, self.signingErrorCallback)

    #-------------------------------------------------- 
    def signingCompletedCallback ( self, groupId ) :
        log.msg("signingCompletedCallback: groupId = {0}".format(groupId))

        self.orchestrator.unLock(groupId)

    #-------------------------------------------------- 
    def signingErrorCallback ( self, groupId ) :
        log.msg("signingErrorCallback: groupId = {0}".format(groupId)) 
Beispiel #2
0
class OrchestratorProtocol( rpc.TSServiceServicer ) :

    def __init__( self ) : 
        print('in OrchestratorProtocol:__init__')

        self.orchestrator = Orchestrator( )

    #-------------------------------------------------
    # Send group is set message to all users in the group
    def groupIsSet(self, gid):        

        userRefs = self.orchestrator.getUserReferences( gid )
        participants = self.orchestrator.getParticipants(gid)
        print('gid = {0}, participants = {1}'.format(gid, participants))
        
        t = self.orchestrator.getDegree( gid )   
        counter = 1
        
        participantList = []


        for user in participants :
                
            ref = self.orchestrator.getUserRef(user)
            print('user {0} : ref {1} '.format(user, ref) ) 
            
            player = stub.Player( name=user, port=ref[1] )
            
            aParticipant = stub.GroupIsSetRequest.Participant( ordinal=counter, playerId=player)            
            participantList.append( aParticipant )
            
            counter = counter + 1

        gReq = stub.GroupIsSetRequest( groupId=gid, degree=t, participants=participantList )

        for user in participants :

            print ('sending groupIsSet message to {0}'.format(user))
            ref = self.orchestrator.getUserRef(user)

            
            response = ref[0].CallGroupIsSet( gReq )

        return


    #--------------------------------------------------
    # operations available to remote in this section
    #-------------------------------------------------- 

    # Register user with Orchestrator        
    def CallRegister(self, request, context):

        player = request.playerId
        client_port = str(player.port)
        print('client_port = {0}'.format(client_port))

        # create a gRPC channel + stub
        client_channel = grpc.insecure_channel('localhost' + ':' + str(client_port))
        client_conn = rpc.TSServiceStub( client_channel )

        self.orchestrator.register( player.name, (client_conn, client_port) )
    
        return stub.RegisterReply( success = True ) 


    #-------------------------------------------------
    def CallCreateGroup(self, request, context) :
        
        print('user = {0}, m = {1}, n = {2} '.format \
            ( request.userId, request.m, request.n ) )

        results = None
        try :
            results =  self.orchestrator.createGroup(request.userId, request.m, request.n)
        except Exception as inst:
            #raise OrchestratorError( inst.args )
            print('ERROR in OrchestratorProtocol:CallCreateGroup')

        gid = results[0]
        inviteList = results[1]

        for invitee in inviteList :
            idMsg = stub.IdentityMessage( groupId=gid )
            call_future = invitee[0].CallInvite.future( stub.InviteRequest ( id=idMsg ) )
            call_future.add_done_callback( self.acceptInviteCallback )

        idMsg = stub.IdentityMessage( userId=request.userId, groupId=gid )
        print('returning a creategroupreply')
        return stub.CreateGroupReply( id=idMsg )


    #-------------------------------------------------
    # This sends a request for data to all participants of group
    def CallShareSecret( self, request, context ) :

        print('in CallShareSecret')
        gid = request.id.groupId
        self.orchestrator.setCalcType (gid, request.calculation )       

        if not self.orchestrator.validGroup(gid) :
            errMsg = 'Group Id is not valid: {0}'.format(gid)
            #raise OrchestratorError( errMsg )
            print('ERROR in OrchestratorProtocol:CallShareSecret')
            print(errMsg)

        if self.orchestrator.isLocked(gid) :
            errMsg = 'Group Id is locked, try again later: {0}'.format(gid)
            #raise OrchestratorError( errMsg )
            print('ERROR in OrchestratorProtocol:CallShareSecret')
            print(errMsg)
        
        self.orchestrator.lock(gid)

        participants = self.orchestrator.getParticipants(gid)

        if request.id.userId not in participants :
            errMsg = 'user is not in the group: {0}'.format(request.id.userId)
            #raise OrchestratorError( errMsg ) 
            print('ERROR in OrchestratorProtocol:CallShareSecret')
            print(errMsg)
        
        userRefs = self.orchestrator.getUserReferences(gid)
        calcType = self.orchestrator.calcType( gid )
        idMsg = stub.IdentityMessage( userId=request.id.userId, groupId=gid )
        
        for ref in userRefs :
            print('calling request data...')

            call_future = ref[0].CallShareSecretData.future( stub.ShareSecretDataRequest( id=idMsg ))
            call_future.add_done_callback( self.collateDataCallback )      

        
        return stub.ShareSecretReply( id=idMsg, success=True )

    #-------------------------------------------------
    def CallInitiatePresign(self, request, context) :
        gid = request.id.groupId 

        if self.orchestrator.isLocked(gid) :
            errMsg = 'Group Id is locked, try again later: {0}'.format(gid)
            #raise OrchestratorError( errMsg )  
            print('ERROR: ' + errMsg )

        self.orchestrator.lock( gid ) 
        idMsg = stub.IdentityMessage( userId=request.id.userId, groupId=gid )
        return stub.InitPresignReply \
            ( id=idMsg, number=request.number )


    #-------------------------------------------------
    def CallPresigning (self, request, context) :
        user        = request.id.userId 
        gid         = request.id.groupId 
        calcType    = request.calculation 

        self.orchestrator.setCalcType( gid, calcType )
       
        print("presigning: user={0}, groupId={1}, calcType={2}".format \
            (user, gid, calcType) )

        if not self.orchestrator.validGroup(gid) :
            errMsg = 'Group Id is not valid: {0}'.format(gid)
            #raise OrchestratorError( errMsg )
            print('ERROR: ' + errMsg )


        participants = self.orchestrator.getParticipants(gid)

        if user not in participants :
            errMsg = 'user is not in the group: {0}'.format(user)
            #raise OrchestratorError( errMsg ) 
            print('ERROR: ' + errMsg )

        userRefs = self.orchestrator.getUserReferences(gid)
        for ref in userRefs : 
    
            print('calling request data...')
            idMsg = stub.IdentityMessage( userId=user, groupId=gid )            
            call_future = ref[0].CallShareSecretData.future \
                ( stub.ShareSecretDataRequest( id=idMsg ))
            call_future.add_done_callback( self.collateDataCallback )      
            
        return stub.PresigningReply( success=True )      

    #-------------------------------------------------
    def CallShareVW(self, request, context) :
        gid     = request.id.groupId 
        user    = request.id.userId 

        print("Collating VW Data")

        # orchestrator expects a tuple ()
        data = ( request.data.v, request.data.w )
        idMsg = stub.IdentityMessage( userId=user, groupId=gid )       

        if self.orchestrator.collateVWData( gid, request.data.ordinal, data ) :
            collatedData = self.orchestrator.getCollatedVWData( gid )


            vwList = []
            for ordinal, vw in collatedData.items() :
                vwdata = stub.VWData( ordinal=ordinal, v=vw[0], w=vw[1] )
                vwList.append( vwdata )

            # send the public data out to all group participants
            userRefs = self.orchestrator.getUserReferences( gid )
                       
            for ref in userRefs :
                
                ref[0].CallCollatedVWShare( stub.CollatedVWShareRequest \
                    ( id=idMsg, data=vwList )   )  

        return stub.ShareVWDataMessageReply( id=idMsg, success=True )   

    #-------------------------------------------------
    def CallPubKeyComplete(self, request, context) :
        print('Sharing public key completed: {0}'.format(request.groupId))
        self.orchestrator.unLock( request.groupId )   

        return stub.GenericReply( success=True )      

    #-------------------------------------------------
    def CallEphemKeyComplete(self, request, context) :
        print("EphemeralKey has been completed, groupId = {0}, user = {1}".format \
            (request.groupId, request.userId))

        if self.orchestrator.allEphemeralKeysCompleted( request.userId, request.groupId ) :
            # send the public data out to all group participants
            userRefs = self.orchestrator.getUserReferences( request.groupId )
            for ref in userRefs :
                ref[0].CallCompleted( stub.IdentityMessage \
                    ( groupId=request.groupId ) )

        return stub.GenericReply( success=True )  

    #-------------------------------------------------
    def CallPresignComplete(self, request, context) :        
        groupId = request.groupId

        if not self.orchestrator.validGroup(groupId) :
            errMsg = 'Group Id is not valid: {0}'.format(groupId)
            #raise OrchestratorError( errMsg )
            print('ERROR: CallPresignComplete ' + errMsg )

        self.orchestrator.unLock( groupId )

        return stub.GenericReply( success=True ) 


    #-------------------------------------------------
    # This sends a request for data to all participants of group
    def CallInitSignature(self, request, context) :

        gid         = request.id.groupId
        msg         = request.message
        userId      = request.id.userId
       
        print("sign: user={0}, groupId={1}, msg={2}".format(userId, gid, msg))

        if not self.orchestrator.validGroup(gid) :
            errMsg = 'Group Id is not valid: {0}'.format(gid)
            #raise OrchestratorError( errMsg )
            print('ERROR: ' + msg)

        if self.orchestrator.isLocked(gid) :
            errMsg = 'Group Id is locked, try again later: {0}'.format(gid)
            #raise OrchestratorError( errMsg )
            print('ERROR: ' + msg)
        
        self.orchestrator.lock(gid)        

        participants = self.orchestrator.getParticipants(gid)

        # check the user is in the group, then set the signer
        if userId not in participants :
            errMsg = 'user is not in the group: {0}'.format(useId)
            #raise OrchestratorError( errMsg ) 
            print( 'ERROR: ' + msg )
        self.orchestrator.setSigner(gid, userId)

        userRefs = self.orchestrator.getUserReferences(gid)
        for ref in userRefs :
            call_future = ref[0].CallShareOfSignature.future( stub.ShareOfSigRequest \
                ( groupId=gid, message=msg ) )
           
            call_future.add_done_callback( self.signingCallback )      

            #ref.callRemote("requestSignatureData", groupId, msg).addCallback \
            #    (self.signingCallback)       
            #  
        return stub.InitSignatureReply( success=True ) 


    #--------------------------------------------------
    # Callback operations available in this section
    #-------------------------------------------------- 
    
    def acceptInviteCallback (self, call_future ) :
        
        res = call_future.result() 
        if self.orchestrator.acceptInvite(res.id.userId, res.id.groupId, res.acceptance) :
            self.groupIsSet(res.id.groupId)  
            print('acceptInviteCallback: group is set!')  


    #--------------------------------------------------                 
    def collateDataCallback (self, call_future ) :
        res = call_future.result()
        
        print('collateDataCallback')

        # if True then ready to distribute data
        if self.orchestrator.collateData( res.id.groupId, res.ordinal, res.hiddenPoly, res.hiddenEvals) :

            # Call the shareEvals, pass in a different set of ordinal:refs for each
            userRefs = self.orchestrator.getUserReferences( res.id.groupId )
            participants = self.orchestrator.getParticipants( res.id.groupId )

            idMsg = stub.IdentityMessage( groupId=res.id.groupId )
            
            for ref in userRefs :
                ref[0].CallInitShareEvals( stub.InitShareEvalsRequest ( id=idMsg ) )
            

    #---------------------------------------------------
    def CallReceivedAllEvals ( self, request, context ) :

        gid     = request.id.groupId
        ord     = request.ordinal

        print('receivedAllEvals')

        # if all Players have received their Eval data then continue
        if self.orchestrator.allEvalsReceived( gid, ord ) :


            collatedData = self.orchestrator.getCollatedData( gid) 
            
            # send the public data out to all group participants
            userRefs = self.orchestrator.getUserReferences( gid )

            # get hiddenPoly into suitable format
            hpList  = []
            for ordinalB, coeffs in collatedData[0].items() :
                hp = stub.hiddenPolynomial(ordinal=ordinalB,coefficients=coeffs)
                hpList.append(hp)


            # get hidden evals into a suitable format
            hidEvalList = []
            for ordinalC, evals in collatedData[1].items() :
                l_of_hep            = stub.listOfPolynomials()
                l_of_hep.ordinal    = ordinalC

                for e in evals :
                    l_of_hep.ep.add(ordinal=e.ordinal, f_x=e.f_x)

                hidEvalList.append(l_of_hep)
    
            idMsg = stub.IdentityMessage( groupId=gid )
            for ref in userRefs :
                print('calling createsecret...')

                call_future = ref[0].CallCollatedSecretShare.future( stub.CollatedSecretRequest( \
                    id=idMsg, calculation=self.orchestrator.calcType(gid), \
                        hiddenPolys=hpList, hiddenEvals=hidEvalList ))
                call_future.add_done_callback( self.secretVerificationCallback )      
        
        print('returning True from CallReceivedAllEvals')
        return stub.RxAllEvalsReply( success=True )
    
    #--------------------------------------------------
    def secretVerificationCallback (self, call_future ) :
        res     = call_future.result() 
        gid     = res.id.groupId
        user    = res.id.userId
        
        print('secretVerificationCallback: ')  

        idMsg = stub.IdentityMessage( userId=user, groupId=gid )
        if self.orchestrator.secretVerification(user, gid) :
            calcType = self.orchestrator.calcType(gid)
            print("secretVerification complete for: {0}".format(calcType))

            # contact all the group participants with verification success
            userRefs = self.orchestrator.getUserReferences(gid)
            for ref in userRefs :
                ref[0].CallGroupIsVerified( stub.GroupIsVerifiedRequest \
                    ( id=idMsg, calculation=calcType ) )

    #--------------------------------------------------                 
    def signingCallback (self, call_future ) :
        res = call_future.result()

        gid         = res.id.groupId
        ordinal     = res.ordinal
        sig         = res.signature
        msg         = res.message
        
        # if True then ready to distribute data
        if self.orchestrator.signature( gid, ordinal, sig) :
            signatureDict = self.orchestrator.getSignatureData(gid) 

            sigList = []
            for ord, sig in signatureDict.items() :
                sigData = stub.SigData( ordinal=ord, signature=sig )
                sigList.append(sigData)
            
            # send the signature data out to the signer
            userRef = self.orchestrator.getSignerReference( gid )
            idMsg = stub.IdentityMessage( userId=res.id.userId, groupId=gid )

            call_future = userRef[0].CallSignMessage.future( stub.SignDataMessage \
                ( id=idMsg, message=msg, signatures=sigList ) )
            call_future.add_done_callback( self.signingCompletedCallback )    


    #--------------------------------------------------                 
    def signingCompletedCallback (self, call_future ) :
        res = call_future.result()    
        print(res)
        self.orchestrator.clearSignatureSetFlag(res.id.groupId)
        self.orchestrator.unLock(res.id.groupId)