Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(protocol): partially randomize prover reward #13184

Merged
merged 24 commits into from
Feb 22, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/protocol/contracts/L1/TaikoData.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ library TaikoData {
uint64 proofTimeCap;
uint64 bootstrapDiscountHalvingPeriod;
uint64 initialUncleDelay;
uint64 proverRewardRandomizedPercentage;
bool enableTokenomics;
bool enablePublicInputsCheck;
bool enableProofValidation;
Expand Down
13 changes: 12 additions & 1 deletion packages/protocol/contracts/L1/TaikoL1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ contract TaikoL1 is
}

function getBlockFee() public view returns (uint256) {
(, uint fee, uint deposit) = LibProposing.getBlockFee(
(, uint256 fee, uint256 deposit) = LibProposing.getBlockFee(
state,
getConfig()
);
Expand Down Expand Up @@ -287,6 +287,17 @@ contract TaikoL1 is
return LibUtils.getUncleProofDelay(state, getConfig(), blockId);
}

function getProverRewardBips(
uint256 proverRewardRandomizedPercentage,
uint256 numProvers
) public view returns (uint256[] memory) {
return
LibVerifying.getProverRewardBips(
proverRewardRandomizedPercentage,
numProvers
);
}

function getConfig() public pure virtual returns (TaikoData.Config memory) {
return LibSharedConfig.getConfig();
}
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/contracts/L1/libs/LibProposing.sol
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ library LibProposing {
TaikoData.State storage state,
uint256 commitConfirmations,
TaikoData.BlockMetadata memory meta
) private {
) private view {
if (commitConfirmations == 0) {
return;
}
Expand Down
69 changes: 52 additions & 17 deletions packages/protocol/contracts/L1/libs/LibVerifying.sol
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,47 @@ library LibVerifying {
reward = (reward * (10000 - config.rewardBurnBips)) / 10000;
}

function getProverRewardBips(
uint256 proverRewardRandomizedPercentage,
uint256 numProvers
) public view returns (uint256[] memory weights) {
uint256 randomized = proverRewardRandomizedPercentage;
if (randomized > 100) {
randomized = 100;
}

uint256 sum;
uint256 i;

if (randomized > 0) {
unchecked {
// calculate the randomized weight
uint256 seed = block.prevrandao;
for (i = 0; i < numProvers; ++i) {
weights[i] = uint16(seed * (1 + i));
cyberhorsey marked this conversation as resolved.
Show resolved Hide resolved
sum += weights[i];
}
for (i = 0; i < numProvers; ++i) {
weights[i] = (weights[i] * 100 * randomized) / sum;
}
}
}
unchecked {
// calculate the randomized and the fixed weight
sum = (1 << numProvers) - 1;
for (i = 0; i < numProvers; ++i) {
uint256 weight = 1 << (numProvers - 1 - i);
weights[i] += (weight * 100 * (100 - randomized)) / sum;
}
}
}

function _refundProposerDeposit(
TaikoData.ProposedBlock storage target,
uint256 tRelBp,
TkoToken tkoToken
) private {
uint refund = (target.deposit * (10000 - tRelBp)) / 10000;
uint256 refund = (target.deposit * (10000 - tRelBp)) / 10000;
if (refund > 0 && tkoToken.balanceOf(target.proposer) > 0) {
// Do not refund proposer with 0 TKO balance.
tkoToken.mint(target.proposer, refund);
Expand All @@ -166,30 +201,30 @@ library LibVerifying {
uint256 reward,
TkoToken tkoToken
) private {
uint start;
uint count = fc.provers.length;
uint256 start;
uint256 count = fc.provers.length;

if (config.enableOracleProver) {
start = 1;
count -= 1;
}

uint sum = (1 << count) - 1;
uint weight = 1 << (count - 1);
for (uint i = 0; i < count; ++i) {
uint proverReward = (reward * weight) / sum;
if (proverReward == 0) {
break;
}
uint256[] memory weights = getProverRewardBips(
config.proverRewardRandomizedPercentage,
count
);

if (tkoToken.balanceOf(fc.provers[start + i]) == 0) {
// Reduce reward to 1 wei as a penalty if the prover
// has 0 TKO balance. This allows the next prover reward
// to be fully paid.
proverReward = uint256(1);
for (uint i = 0; i < count; ++i) {
uint256 proverReward = (reward * weights[i]) / 10000;
davidtaikocha marked this conversation as resolved.
Show resolved Hide resolved
if (proverReward != 0) {
if (tkoToken.balanceOf(fc.provers[start + i]) == 0) {
// Reduce reward to 1 wei as a penalty if the prover
// has 0 TKO balance. This allows the next prover reward
// to be fully paid.
proverReward = uint256(1);
}
tkoToken.mint(fc.provers[start + i], proverReward);
}
tkoToken.mint(fc.provers[start + i], proverReward);
weight = weight >> 1;
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/protocol/contracts/libs/LibSharedConfig.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ library LibSharedConfig {
proofTimeCap: 60 minutes,
bootstrapDiscountHalvingPeriod: 180 days,
initialUncleDelay: 60 minutes,
proverRewardRandomizedPercentage: 0,
enableTokenomics: false,
enablePublicInputsCheck: true,
enableProofValidation: false,
Expand Down
1 change: 1 addition & 0 deletions packages/protocol/contracts/test/L1/TestTaikoL1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ contract TestTaikoL1 is TaikoL1, IProofVerifier {
config.proofTimeCap = 4 seconds;
config.bootstrapDiscountHalvingPeriod = 180 days;
config.initialUncleDelay = 1 seconds;
config.proverRewardRandomizedPercentage = 20;
config.enableTokenomics = false;
config.enablePublicInputsCheck = false;
config.enableOracleProver = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ contract TestTaikoL1EnableTokenomics is TaikoL1, IProofVerifier {
config.proofTimeCap = 5 seconds;
config.bootstrapDiscountHalvingPeriod = 1 seconds;
config.initialUncleDelay = 1 seconds;
config.proverRewardRandomizedPercentage = 20;
config.enableTokenomics = true;
config.enablePublicInputsCheck = false;
config.enableProofValidation = false;
Expand Down
1 change: 1 addition & 0 deletions packages/protocol/contracts/test/L1/TestTaikoL2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ contract TestTaikoL2 is TaikoL2 {
config.proofTimeCap = 60 minutes;
config.bootstrapDiscountHalvingPeriod = 180 days;
config.initialUncleDelay = 1 minutes;
config.proverRewardRandomizedPercentage = 20;
config.enableTokenomics = true;
config.enablePublicInputsCheck = false;
config.enableProofValidation = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ contract TestTaikoL2EnablePublicInputsCheck is TaikoL2 {
config.proofTimeCap = 60 minutes;
config.bootstrapDiscountHalvingPeriod = 180 days;
config.initialUncleDelay = 1 minutes;
config.proverRewardRandomizedPercentage = 0;
config.enableTokenomics = true;
config.enablePublicInputsCheck = true;
config.enableProofValidation = true;
Expand Down