eMule 47c. TK4 Mod 2.0a



The TK4 Mod has 4 credit system options.

TK4 Credit System

Objectives.

I believe a credit system does two things, it helps you download a file faster because you give more data to people who share and hence you get data back from them faster as most of them will be using a credit system. You give less data to Leeches,(people who deliberately take and do not give). This protect the network, because if everyone leeched, there would be no file sharing.

Firstly I will describe the newest credit systems, the TK4 system. Note C++ for all of the systems is at the end of this document.

Overview.

If you are sharing completed files and someone downloads data from one of these from you they probably cannot give you data back as you have all of the file. So in the TK4 system their credit rating remains unchanged. If you are downloading a file and someone takes data from you from the parts of the file you have they will be subject to the credit system and depending on how much they have given they may have their credit rating reduced. At any time if anyone gives you data they get a credit rating increase. The credit system works basically like this:

credit start point = 10
allowance = 'Mb given'/4 + 1 Mb

if 'Mb taken' greater than 'Mb given + allowance + 1Mb (they have taken more than they gave + some)

Then if the file is a file we are downloading

	if '(Mb taken - allowance)' is between 1 to 81Mb credit multiplier range = 9 to 1
	math:  10 - square root('(Mb taken - allowance)' - 'Mb given')
	if '(Mb taken - allowance)' is greater than 81Mb credit multiplier range = 1 to 0.14
	math:   9 / square root('(Mb taken - allowance)' -'Mb given')
if 'Mb given' is greater than 'Mb taken' (they have given more than they have taken)
	credit multiplier range = 10 to 342
	math: 10 + log(2.72+('Mb given'-'Mb taken)*4)+('Mb taken/12)
There is no absolute range for multipliers but I have quoted a range of 0.14< to >342 (Assumes around a max. 4Gb difference) with a starting point of 10. Clients with failed SUI will start at 10, but not go up.


The eMule standard system.

The eMule standard system documented as working thus:

There are two different credit modifier calculated:

  Ratio1 = Uploaded Total x 2 / Downloaded Total
  Ratio2 = SQRT(Uploaded Total + 2)

Both ratios are compared and the lower value is used as modifier. Some boundary conditions also exist:

  Uploaded Total << 1MB => Modifier = 1
  Downloaded Total = 0 => Modifier = 10
  The modifier may not be lower than 1 or higher than 10

But as of version 46c the actual code does this:

There are two different credit modifier calculated:

  Ratio1 = Uploaded Total x 2 / Downloaded Total
  Ratio2 = SQRT(Uploaded Total + 2)

Both ratios are compared and the lower value is used as modifier.
Some boundary conditions also exist:

  Uploaded Total > 0.95MB => Modifier = 1
  The modifier may not be lower than 1 or higher than 10

Although this may change in future eMules as this *is* the eMule credit system whether by design or not. If you select 'eMule Standard' credit system. You will be selecting the same algorithm as in the un-mod'ed eMule 46c.


Lovelace.

Lovelace is the credit system from the Lovelace mod and is a popular credit system.
Below is algorithm implemented for Lovelace:

dl-modifier=100*((1-1/(1+exp((3*{MB uploaded to us}^2-{MB downloaded from us}^2)/1000)))^6.6667)
new credit system (start:1, max:100, min:0.1, ratio:1:1.5, only one formula)
Only clients using the 'SecureHash' are able to get a multiplier of 100. All others will stick at 10.
Eastshare.

Eastshare is the credit from the Eastshare mod another popular credit system.

base ratings: id. users(100); invalid id. users(0); min.=10, max.=5000
  +6 per MB uploaded and -2 for downloaded; +100 if upload 1MB+; if rating < 50 and upload 1MB+, rating = 50
For those of you who know C++ below is the GetScoreRatio() with some comments remove,(for easy reading in a text only format)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Changed for version 1.3c to speed up the code results are unchanged, Eastshare code updated form Eastshare for 1.4g.
Changed for version 1.5e to further reduce CPU usage.
float CClientCredits::GetScoreRatio(uint32 dwForIP, CUpDownClient* pClient) const
{  //Why make a duplicate call? 
	EIdentState currentIDstate = GetCurrentIdentState(dwForIP);// get the client ident status
	float result;//result returned
	
	switch(thePrefs.creditsystem_tk4){	

case 0:{/*STANDARD eMule credit system - RANGE 1.0F - 10.0F */
        //Below the credit system as per eMule above the system as per it's description on the eMule site
        // bad guy - no credits for you
		if((currentIDstate == IS_IDFAILED || currentIDstate == IS_IDBADGUY || currentIDstate == IS_IDNEEDED) && theApp.clientcredits->CryptoAvailable()) return 1.0F;
		 //Given less than 1Mb
		if (GetDownloadedTotal() < 1000000)	return 1.0F;
		result = 10.0F;
		if(GetUploadedTotal()) result = (float)(((double)GetDownloadedTotal()*2.0)/(double)GetUploadedTotal());
		// Ratio2 = SQRT(given in Mb + 2)
		float result2 = (float)sqrt((float)(GetDownloadedTotal()/1048576.0) + 2.0F);
		//Take the lowest value
		if(result > result2)	result = result2;
		//keep within range
		if(result > 1.0F) return 1.0F;
		if (result > 10.0F) return 10.0F;
		return result;
	   }
	 
case 1:{/*LOVELACE credit formula -TK4 implementation- RANGE 0.1F - 100.0F //anti-leeching */
	    /*lovelace: dl-modifier=100*((1-1/(1+exp((3*{MB uploaded to us}^2-{MB downloaded from us}^2)/1000)))^6.6667)
		Credit system (start:1, max:100, min:0.1, ratio:1:1.5, only one formula)
		CreditThefts will not get any credits. Only clients using the 'SecureHash' are able to get a multiplier of 100. All others will stick at 10.
		CreditThefts part not implemented! */  	
		
		//	bad guy - no credits for you (they get 1.0F)
		if((currentIDstate == IS_IDFAILED || currentIDstate == IS_IDBADGUY || currentIDstate == IS_IDNEEDED) && theApp.clientcredits->CryptoAvailable())	return 0.1F;

		float uPloadMbSqd   =  powf(((float)GetDownloadedTotal()/1048576.0F),2.0F);
		float dOwnloadMbSqd =  powf(((float)GetUploadedTotal()/1048576.0F),2.0F);

		result = 100.0F*powf(1.0F-1.0F/(float)(1.0F+ exp((3.0F*uPloadMbSqd-dOwnloadMbSqd)/1000.0F)),6.6667F);
		//Client does not have secure hash so they have a maximum credit ceiling of 10
		if((currentIDstate!=IS_IDENTIFIED || m_pCredits->nKeySize == 0)  && result>10.0F) return 10.0F;
		//Keep within range,(needed?)
		if(result<0.1F) return 0.1F;
  		return result;
	   }
case 2:{// EastShare START - Added by TAHO, new Credit System //Modified by Pretender
		if((currentIDstate == IS_IDFAILED || currentIDstate == IS_IDBADGUY || currentIDstate == IS_IDNEEDED) && theApp.clientcredits->CryptoAvailable()) return 1.0F; //is before the switch in Eastshare
		result = 100;
		result += (float)((double)GetDownloadedTotal()/174762.67 - (double)GetUploadedTotal()/524288); //Modefied by Pretender - 20040120
			
		if((double)GetDownloadedTotal() > 1048576)
		  {
			result += 100; 
			if(result&<50 && ((double)GetDownloadedTotal()*10 > (double)GetUploadedTotal())) result=50;
		   } //Modefied by Pretender - 20040330

		if( result < 10 )
		  {
			result = 10;
		   } else 
			 if( result > 5000 )
		            {
			          result = 5000;
		             }
		result = result / 100;
		return result;
	 // EastShare END - Added by TAHO, new Credit System
	   }
case 3:
default:
	   {//TK4 credit formula. Aims punish leechers quickly but be fair to those we want nothing from and reward sharers
		 //float result = 10.0F;
		 uint64 DownTotalInt;//added to remove a Divide by 4 and repalce it with a >> 2
		 //if SUI failed then credit starts at 10 as for everyone else but will not go up
		 if((currentIDstate == IS_IDFAILED || currentIDstate == IS_IDBADGUY || currentIDstate == IS_IDNEEDED) && theApp.clientcredits->CryptoAvailable()){
			 // CUpDownClient* pClient = theApp.clientlist->FindClientByIP(dwForIP);//Get 'client' so we can get file info
			  float dOwnloadedSessionTotal = (float)(DownTotalInt = pClient->GetTransferredDown());
			  float uPloadedSessionTotal = (float)pClient->GetTransferredUp();
			  float allowance = (float)(DownTotalInt >> 2);
			  //partfile 10 - 0.14 complete 10
			  if(uPloadedSessionTotal > (float)(dOwnloadedSessionTotal + allowance + 1048576.0F)){
				 CKnownFile* file = theApp.sharedfiles->GetFileByID(pClient->GetUploadFileID());
			     if(file!=NULL){//Are they requesting a file? NULL can be produced when client details calls getscoreratio() without this line eMule will crash.
					            if(file->IsPartFile()){//It's a file we are trying to obtain so we want to give to givers so we may get the file quicker.
							       float MbSqd =sqrt((float)(uPloadedSessionTotal-(dOwnloadedSessionTotal + allowance))/1048576.0F);
							       if(MbSqd > 9.0F) return ( 9.0F / MbSqd); //above 81mb values 1 - 0 9/(9 - x)
							         else	      return (10.0F - MbSqd); //for the first 81Mb (10 -(0-9))
							      }

				}
			  } 
			return 10.0F;
		    }
		//float is 1e38 it should be sufficient given 1 Gig is 1e9 hence 1000Gig is 1e12....
		float dOwnloadedTotal =  (float)( DownTotalInt = GetDownloadedTotal());//(Given to us)
		float uPloadedTotal = (float)GetUploadedTotal(); //(Taken from us)
		float allowance = (float)(DownTotalInt >> 2);//reward uploaders with 1 Mb allowance for every 4Mb uploaded over what they have uploaded.
		if(uPloadedTotal>(float)(dOwnloadedTotal + allowance + 1048576.0F))//If they have taken above (1Mb + 'allowance')
		  {
 		   //  CUpDownClient* pClient = theApp.clientlist->FindClientByIP(dwForIP);//Get 'client' so we can get file info
			  CKnownFile* file = theApp.sharedfiles->GetFileByID(pClient->GetUploadFileID());
			  if(file!=NULL){//Are they requesting a file? NULL can be produced when client details calls getscoreratio() without this line eMule will crash.
			                 if(file->IsPartFile()){//It's a file we are trying to obtain so we want to give to givers so we may get the file quicker.
							       float MbSqd =sqrt((float)(uPloadedTotal-(dOwnloadedTotal + allowance))/1048576.0F);
							       if(MbSqd > 9.0F) return ( 9.0F / MbSqd); //above 81mb values 1 - 0 9/(9 - x)
							         else	      return (10.0F - MbSqd); //for the first 81Mb (10 -(0-9))
							      }
						    }
			} else //We may owe them :o) give a small proportional boost to an uploader
			 	  if(dOwnloadedTotal>uPloadedTotal){ // return  log(2.72 + (given - taken in Mb * 4)) + (given in bytes / 12Mb) + 10 (eg +1 for every 12Mb +.5  6Mb etc)
						return ( log(2.72F + (float)(dOwnloadedTotal-uPloadedTotal)/262144.0F) + (float)(10.0F + dOwnloadedTotal/12582912.0F) );
						}
		      return 10.0F;
           }
	   
	}//end switch

}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Below is eMule credit system as it should be according to its documentation:

		// bad guy - no credits for you
		if((currentIDstate == IS_IDFAILED || currentIDstate == IS_IDBADGUY || currentIDstate == IS_IDNEEDED) && theApp.clientcredits->CryptoAvailable()) return 1.0F;
		//Given < 1Mb
		if (GetDownloadedTotal() > 1048576)	return 1.0F; //was 1000000 (Fix CiccioBastardo - Bastard Mod Dev)
		//Not taken anything full credit else credit = (given*2)/taken
		if(!GetUploadedTotal())	return 10.0F;  //was result = 10.0F - TK4 Fix
		  else {
			    float result = (float)(((double)GetDownloadedTotal()*2.0)/(double)GetUploadedTotal());
		        // Ratio2 = SQRT(given in Mb + 2)
		        float result2 = (float)sqrt((float)(GetDownloadedTotal()/1048576.0) + 2.0F);
		        //Take the lowest value
		        if(result > result2)	result = result2;
		        //keep within range
		        if(result < 1.0F)	return 1.0F;
		        if (result > 10.0F)	return 10.0F;
		        return result;
			 }