added some documentation in p3gxsreputation.cc, and the method for computing final assessment

This commit is contained in:
csoler 2015-10-06 23:56:39 -04:00
parent b0940890cd
commit 78e6f67c69
3 changed files with 120 additions and 82 deletions

View File

@ -28,24 +28,28 @@
#include "retroshare/rsids.h"
#include "retroshare/rsgxsifacetypes.h"
typedef uint32_t GRouterServiceId ;
typedef uint64_t GRouterMsgPropagationId ;
class RsReputations
{
public:
// This is the interface file for the reputation system
//
enum Opinion { OPINION_NEGATIVE = -1, OPINION_NEUTRAL = 0, OPINION_POSITIVE = 1 } ;
enum Opinion { OPINION_NEGATIVE = 0, OPINION_NEUTRAL = 1, OPINION_POSITIVE = 2 } ;
enum Assessment { ASSESSMENT_BAD = 0, ASSESSMENT_OK = 1 } ;
struct ReputationInfo
{
RsReputations::Opinion mOwnOpinion ;
float mOverallReputationScore ;
RsReputations::Assessment mAssessment; // this should help clients in taking decisions
};
virtual bool setOwnOpinion(const RsGxsId& key_id, const Opinion& op) =0;
virtual bool getReputationInfo(const RsGxsId& id,ReputationInfo& info) =0 ;
// This one is a proxy designed to allow fast checking of a GXS id.
// it basically returns true if assessment is ASSESSMENT_OK
virtual bool isIdentityOk(const RsGxsId& id) =0;
};
// To access reputations from anywhere

View File

@ -70,57 +70,65 @@ const int kMaximumSetSize = 100;
* std::map<RsPeerId, ReputationConfig> mConfig;
*
* Updates from p3GxsReputation -> p3IdService.
*
*
* Updates from p3IdService -> p3GxsReputation.
*
* Each peer locally stores reputations for all GXS ids. If not stored, a default value
* is used, corresponding to a neutral opinion. Peers also share their reputation level
* with their neighbor nodes.
*
* The calculation method is the following:
*
* Local values:
* Good: 2
* Neutral: 1
* Bad: 0
*
* Overall reputation score:
*
* if(own_opinion == 0) // means we dont' care
* r = average_of_friends_opinions
* else
* r = own_opinion
*
* Decisions based on reputation score:
*
* 0 x1 1 x2 2
* | <-----------------------------------------------------------------------> |
* ---------+
* Lobbies | Msgs dropped
* Forums | Msgs dropped
* Messages | Msgs dropped
* ---------+----------------------------------------------------------------------------
*
* We select x1=0.5
*
* => to kill an identity, either you, or at least 50% of your friends need to flag it
* as bad.
* Rules:
* * a single peer cannot drastically change the behavior of a given GXS id
* * it should be easy for many peers to globally kill a GXS id
*
* Typical examples:
*
* Friends | Friend average | Own | alpha | Score
* -----------+---------------------+----------+------------+--------------
* 10 | 0.5 | 1 | 0.25 | 0.375
* 10 | 1.0 | 1 | 0.25 | 1.0
* 10 | 1.0 | 0 | 0.25 | 1.0
*
* To check:
* [ ] Opinions are saved/loaded accross restart
* [ ] Opinions are transmitted to friends
* [ ] Opinions are transmitted to friends when updated
*
* To do:
* [ ] Test the whole thing
* [ ] Implement a system to allow not storing info when we don't have it
*/
const int32_t REPUTATION_OFFSET = 100000;
const int32_t LOWER_LIMIT = -100;
const int32_t UPPER_LIMIT = 100;
int32_t ConvertFromSerialised(uint32_t value, bool limit)
{
int32_t converted = ((int32_t) value) - REPUTATION_OFFSET ;
if (limit)
{
if (converted < LOWER_LIMIT)
{
converted = LOWER_LIMIT;
}
if (converted > UPPER_LIMIT)
{
converted = UPPER_LIMIT;
}
}
return converted;
}
uint32_t ConvertToSerialised(int32_t value, bool limit)
{
if (limit)
{
if (value < LOWER_LIMIT)
{
value = LOWER_LIMIT;
}
if (value > UPPER_LIMIT)
{
value = UPPER_LIMIT;
}
}
value += REPUTATION_OFFSET;
if (value < 0)
{
value = 0;
}
return (uint32_t) value;
}
const uint32_t LOWER_LIMIT = 0;
const uint32_t UPPER_LIMIT = 2;
const float REPUTATION_ASSESSMENT_THRESHOLD_X1 = 0.5f ;
p3GxsReputation::p3GxsReputation(p3LinkMgr *lm)
:p3Service(), p3Config(),
@ -133,7 +141,6 @@ p3GxsReputation::p3GxsReputation(p3LinkMgr *lm)
mReputationsUpdated = false;
}
const std::string GXS_REPUTATION_APP_NAME = "gxsreputation";
const uint16_t GXS_REPUTATION_APP_MAJOR_VERSION = 1;
const uint16_t GXS_REPUTATION_APP_MINOR_VERSION = 0;
@ -275,7 +282,7 @@ bool p3GxsReputation::SendReputations(RsGxsReputationRequestItem *request)
}
RsGxsId gxsId = rit->first;
pkt->mOpinions[gxsId] = ConvertToSerialised(rit->second.mOwnOpinion, true);
pkt->mOpinions[gxsId] = rit->second.mOwnOpinion;
pkt->mLatestUpdate = rit->second.mOwnOpinionTs;
if (pkt->mLatestUpdate == (uint32_t) now)
{
@ -341,8 +348,8 @@ bool p3GxsReputation::RecvReputations(RsGxsReputationUpdateItem *item)
rit = mReputations.find(gxsId);
}
Reputation &reputation = rit->second;
reputation.mOpinions[peerid] = ConvertFromSerialised(it->second, true);
Reputation& reputation = rit->second;
reputation.mOpinions[peerid] = std::min(it->second,UPPER_LIMIT); // filters potentially tweaked reputation score sent by friend
int previous = reputation.mReputation;
if (previous != reputation.CalculateReputation())
@ -382,10 +389,39 @@ bool p3GxsReputation::updateLatestUpdate(RsPeerId peerid, time_t ts)
bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, RsReputations::ReputationInfo& info)
{
std::cerr << __PRETTY_FUNCTION__ << ": not implemented yet!" << std::endl;
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
std::map<RsGxsId,Reputation>::const_iterator it = mReputations.find(gxsid);
if (it == mReputations.end())
{
info.mOwnOpinion = RsReputations::OPINION_NEUTRAL ;
info.mOverallReputationScore = float(RsReputations::OPINION_NEUTRAL) ;
info.mAssessment = RsReputations::ASSESSMENT_OK ;
}
else
{
info.mOwnOpinion = RsReputations::Opinion(it->second.mOwnOpinion) ;
info.mOverallReputationScore = float(RsReputations::OPINION_NEUTRAL) ;
if(info.mOverallReputationScore > REPUTATION_ASSESSMENT_THRESHOLD_X1)
info.mAssessment = RsReputations::ASSESSMENT_OK ;
else
info.mAssessment = RsReputations::ASSESSMENT_BAD ;
}
return true ;
}
bool p3GxsReputation::isIdentityOk(const RsGxsId &id)
{
RsReputations::ReputationInfo info ;
getReputationInfo(id,info) ;
return info.mAssessment == RsReputations::ASSESSMENT_OK ;
}
bool p3GxsReputation::setOwnOpinion(const RsGxsId& gxsid, const RsReputations::Opinion& opinion)
{
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
@ -477,15 +513,15 @@ bool p3GxsReputation::saveList(bool& cleanup, std::list<RsItem*> &savelist)
{
RsGxsReputationSetItem *item = new RsGxsReputationSetItem();
item->mGxsId = rit->first;
item->mOwnOpinion = ConvertToSerialised(rit->second.mOwnOpinion, false);
item->mOwnOpinion = rit->second.mOwnOpinion;
item->mOwnOpinionTS = rit->second.mOwnOpinionTs;
item->mReputation = ConvertToSerialised(rit->second.mReputation, false);
item->mReputation = rit->second.mReputation;
std::map<RsPeerId, int32_t>::iterator oit;
std::map<RsPeerId, uint32_t>::iterator oit;
for(oit = rit->second.mOpinions.begin(); oit != rit->second.mOpinions.end(); ++oit)
{
// should be already limited.
item->mOpinions[oit->first] = ConvertToSerialised(oit->second, false);
item->mOpinions[oit->first] = oit->second;
}
savelist.push_back(item);
@ -554,14 +590,14 @@ bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std:
// expensive ... but necessary.
RsPeerId peerId(oit->first);
if (peerSet.end() != peerSet.find(peerId))
reputation.mOpinions[peerId] = ConvertFromSerialised(oit->second, true);
reputation.mOpinions[peerId] = oit->second;
}
reputation.mOwnOpinion = ConvertFromSerialised(item->mOwnOpinion, false);
reputation.mOwnOpinion = item->mOwnOpinion;
reputation.mOwnOpinionTs = item->mOwnOpinionTS;
// if dropping entries has changed the score -> must update.
int previous = ConvertFromSerialised(item->mReputation, false);
int previous = item->mReputation;
if (previous != reputation.CalculateReputation())
{
mUpdatedReputations.insert(gxsId);
@ -688,6 +724,18 @@ float Reputation::CalculateReputation()
{
// the calculation of reputation makes the whole thing
std::cerr << __PRETTY_FUNCTION__ << ": not implemented yet!" << std::endl;
return 0.0 ;
if(mOwnOpinion == RsReputations::OPINION_NEUTRAL)
{
uint32_t friend_total = 0;
for(std::map<RsPeerId,uint32_t>::const_iterator it(mOpinions.begin());it!=mOpinions.end();++it)
friend_total += it->second ;
if(friend_total == 0) // includes the case of no friends!
return 0.0f ;
else
return friend_total / float(mOpinions.size()) ;
}
else
return float(mOwnOpinion) ;
}

View File

@ -59,15 +59,14 @@ class Reputation
{
public:
Reputation()
:mOwnOpinion(0), mOwnOpinionTs(0), mReputation(0) { return; }
:mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0), mReputation(RsReputations::OPINION_NEUTRAL) { }
Reputation(const RsGxsId& about)
:mGxsId(about), mOwnOpinion(0), mOwnOpinionTs(0), mReputation(0) { return; }
:mOwnOpinion(RsReputations::OPINION_NEUTRAL), mOwnOpinionTs(0), mReputation(RsReputations::OPINION_NEUTRAL) { }
float CalculateReputation();
RsGxsId mGxsId;
std::map<RsPeerId, int32_t> mOpinions;
std::map<RsPeerId, uint32_t> mOpinions;
int32_t mOwnOpinion;
time_t mOwnOpinionTs;
@ -90,28 +89,16 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations /
/***** Interface for RsReputations *****/
virtual bool setOwnOpinion(const RsGxsId& key_id, const Opinion& op) ;
virtual bool getReputationInfo(const RsGxsId& id,ReputationInfo& info) ;
virtual bool isIdentityOk(const RsGxsId& id) ;
/***** overloaded from p3Service *****/
/*!
* This retrieves all chat msg items and also (important!)
* processes chat-status items that are in service item queue. chat msg item requests are also processed and not returned
* (important! also) notifications sent to notify base on receipt avatar, immediate status and custom status
* : notifyCustomState, notifyChatStatus, notifyPeerHasNewAvatar
* @see NotifyBase
*/
virtual int tick();
virtual int status();
/*!
* Interface stuff.
*/
/*************** pqiMonitor callback ***********************/
//virtual void statusChange(const std::list<pqipeer> &plist);
/************* from p3Config *******************/
virtual RsSerialiser *setupSerialiser() ;
virtual bool saveList(bool& cleanup, std::list<RsItem*>&) ;
@ -133,7 +120,6 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations /
void sendReputationRequests();
int sendReputationRequest(RsPeerId peerid);
private:
RsMutex mReputationMtx;