@E-K
How do you solve the so called 'Nothing @ Stake' problem if with NXT style POS(i did not much clear about how NXT slove this also)?
Thanks.
I would suggest the following change to the NXT scheme.
As we have already discussed, that it's better that the personal raises exponentially (doubles every 7 seconds) rather than linearity (for NXT it increases by the amount of your stake every second), we can be sure that the maximum possible target will be *never* reached later than in 30 minutes.
What if we allow
everyone, even those without any stake, to solve PoS blocks once one particular target reaches its highest possible value.
Highest possible value would mean "T=UINT64_MAX" and any other block's PoS hash H is by nature "H<=T".
To reflect the worst case, accounts that have no stake value, indeed do participate in the PoS, but differently.
Their base_target is 1, and their personal_target also starts with 1, their PoS hash is assumed to be UINT64_MAX, and their personal target is doubling every 7 seconds. If there is at least one account with a stake he will find the block instead, for sure.
Otherwise, after 30 minutes (and not before), an account without stake can generate a block when the target has reached UINT64_MAX.
Right now, regular accounts calculate their current target value like this:
double balance = getCurrentStakeBalance();
double personal_target = base_target * balance;
if(personal_target < base_target || personal_target > max_target)
personal_target = max_target;
if(personal_target != max_target){
// Now increase exponentially so that target doubles every 7 seconds. This ensures that even if target is 1 (worst case) a block will be found after 30 minutes max.
double factor = pow(2, (1.0/7.0)*time_diff_to_last_block);
// TODO, correct to handle integer overflow this way?
double new_target = personal_target * factor;
if(new_target
personal_target = max_target;
}else{
personal_target = new_target;
}
}
we would need a change like this (see the else branch that calculated 0-stake target value starting from 1 and so reflecting the worst case. Furthermore, it can only stake once the worst case itself has been reached, i.e., die target has gone past uint64_max):
double balance = getCurrentStakeBalance();
if(balance > 0){
double personal_target = base_target * balance;
if(personal_target < base_target || personal_target > max_target)
personal_target = max_target;
if(personal_target != max_target){
// Now increase exponentially so that target doubles every 7 seconds. This ensures that even if target is 1 (worst case) a block will be found after 30 minutes max.
double factor = pow(2, (1.0/7.0)*time_diff_to_last_block);
// TODO, correct to handle integer overflow this way?
double new_target = personal_target * factor;
if(new_target
personal_target = max_target;
}else{
personal_target = new_target;
}
}
}
else{
double personal_target = 1;
double factor = pow(2, (1.0/7.0)*time_diff_to_last_block);
double new_target = personal_target * factor;
if(new_target
personal_target = max_target;
}else{
personal_target = 0; // Only if gone past max_target balance=0 account can stake
}
}