mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-02-17 21:34:10 -05:00
added some documentation in p3gxsreputation.cc, and the method for computing final assessment
This commit is contained in:
parent
b0940890cd
commit
78e6f67c69
@ -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
|
||||
|
@ -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) ;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user