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): temporarily force an oracle prover to be the first prover #13070

Merged
merged 14 commits into from
Jan 31, 2023
1 change: 1 addition & 0 deletions packages/protocol/contracts/L1/TaikoData.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ library TaikoData {
uint64 initialUncleDelay;
bool enableTokenomics;
bool enablePublicInputsCheck;
bool enableOracleProver;
}

struct BlockMetadata {
Expand Down
6 changes: 3 additions & 3 deletions packages/protocol/contracts/L1/libs/LibProposing.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ library LibProposing {
// the tokenomics.

// TODO(daniel): remove this special address.
address specialProposer = resolver.resolve("special_proposer", true);
address soloProposer = resolver.resolve("solo_proposer", true);
require(
specialProposer == address(0) || specialProposer == msg.sender,
"L1:specialProposer"
soloProposer == address(0) || soloProposer == msg.sender,
"L1:soloProposer"
);

assert(!LibUtils.isHalted(state));
Expand Down
59 changes: 45 additions & 14 deletions packages/protocol/contracts/L1/libs/LibProving.sol
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,27 @@ library LibProving {
meta: evidence.meta
});

bytes32 blockHash = evidence.header.hashBlockHeader();

// For alpha-2 testnet, the network allows any address to submit ZKP,
// but a special prover can skip ZKP verification if the ZKP is empty.

bool skipZKPVerification;

// TODO(daniel): remove this special address.
if (msg.sender == resolver.resolve("special_prover", true)) {
// Skip ZKP verification
} else {
if (config.enableOracleProver) {
bytes32 _blockHash = state
.forkChoices[target.id][evidence.header.parentHash].blockHash;

if (msg.sender == resolver.resolve("oracle_prover", false)) {
require(_blockHash == 0, "L1:mustBeFirstProver");
skipZKPVerification = true;
} else {
require(_blockHash != 0, "L1:mustNotBeFirstProver");
}
}

bytes32 blockHash = evidence.header.hashBlockHeader();

if (!skipZKPVerification) {
for (uint256 i = 0; i < config.zkProofsPerBlock; ++i) {
require(
proofVerifier.verifyZKP({
Expand Down Expand Up @@ -301,23 +313,25 @@ library LibProving {
];

if (fc.blockHash == 0) {
// This is the first proof for this block.
fc.blockHash = blockHash;
fc.provenAt = uint64(block.timestamp);
} else {
if (fc.blockHash != blockHash) {
// We have a problem here: two proofs are both valid but claims
// the new block has different hashes.
LibUtils.halt(state, true);
return;
}

if (!config.enableOracleProver) {
// If the oracle prover is not enabled
// we use the first prover's timestamp
fc.provenAt = uint64(block.timestamp);
} else {
// We keep fc.provenAt as 0.
}
} else {
require(
fc.provers.length < config.maxProofsPerForkChoice,
"L1:proof:tooMany"
);

require(
block.timestamp <
fc.provenAt == 0 ||
block.timestamp <
LibUtils.getUncleProofDeadline({
state: state,
config: config,
Expand All @@ -330,6 +344,23 @@ library LibProving {
for (uint256 i = 0; i < fc.provers.length; ++i) {
require(fc.provers[i] != prover, "L1:prover:dup");
}

if (fc.blockHash != blockHash) {
// We have a problem here: two proofs are both valid but claims
// the new block has different hashes.
if (config.enableOracleProver) {
revert("L1:proof:conflict");
} else {
LibUtils.halt(state, true);
return;
}
}

if (config.enableOracleProver && fc.provenAt == 0) {
// If the oracle prover is enabled, we
// use the second prover's timestamp.
fc.provenAt = uint64(block.timestamp);
}
}

fc.provers.push(prover);
Expand Down
27 changes: 21 additions & 6 deletions packages/protocol/contracts/L1/libs/LibVerifying.sol
Original file line number Diff line number Diff line change
Expand Up @@ -153,22 +153,35 @@ library LibVerifying {
}

function _rewardProvers(
TaikoData.Config memory config,
TaikoData.ForkChoice storage fc,
uint256 reward,
TkoToken tkoToken
) private {
uint sum = 2 ** fc.provers.length - 1;
for (uint i = 0; i < fc.provers.length; ++i) {
uint weight = (1 << (fc.provers.length - i - 1));
uint start;
uint 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;
dantaik marked this conversation as resolved.
Show resolved Hide resolved
if (proverReward == 0) {
break;
}

if (tkoToken.balanceOf(fc.provers[i]) == 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[i], proverReward);
tkoToken.mint(fc.provers[start + i], proverReward);
weight = weight >> 1;
}
}

Expand Down Expand Up @@ -197,7 +210,7 @@ library LibVerifying {
resolver.resolve("tko_token", false)
);

_rewardProvers(fc, reward, tkoToken);
_rewardProvers(config, fc, reward, tkoToken);
_refundProposerDeposit(target, tRelBp, tkoToken);
}
// Update feeBase and avgProofTime
Expand Down Expand Up @@ -241,6 +254,8 @@ library LibVerifying {
uint256 blockId
) private view returns (bool) {
return
// TODO(daniel): remove the next line.
(!config.enableOracleProver || fc.provers.length > 1) &&
fc.blockHash != 0 &&
block.timestamp >
LibUtils.getUncleProofDeadline({
Expand Down
5 changes: 3 additions & 2 deletions packages/protocol/contracts/libs/LibSharedConfig.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ library LibSharedConfig {
proofTimeCap: 60 minutes,
bootstrapDiscountHalvingPeriod: 180 days,
initialUncleDelay: 60 minutes,
enableTokenomics: false,
enablePublicInputsCheck: true
enableTokenomics: true,
enablePublicInputsCheck: true,
enableOracleProver: true
});
}
}
5 changes: 3 additions & 2 deletions packages/protocol/contracts/libs/LibZKP.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ library LibZKP {
address prover,
bytes32 txListHash
) internal view returns (bool verified) {
// TODO(david):public input is assembled in client software for testing purposes right now, move this part of logic
// to here.
// TODO(david):public input is assembled in client software
// for testing purposes right now, move this part of logic
// here in this contract.
(verified, ) = plonkVerifier.staticcall(zkproof);
}
}
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 @@ -49,6 +49,7 @@ contract TestTaikoL1 is TaikoL1, IProofVerifier {
config.initialUncleDelay = 1 minutes;
config.enableTokenomics = false;
config.enablePublicInputsCheck = true;
config.enableOracleProver = false;
}

function verifyZKP(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ contract TestTaikoL1EnableTokenomics is TaikoL1, IProofVerifier {
config.initialUncleDelay = 1 seconds;
config.enableTokenomics = true;
config.enablePublicInputsCheck = false;
config.enableOracleProver = false;
}

function verifyZKP(
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 @@ -50,5 +50,6 @@ contract TestTaikoL2 is TaikoL2 {
config.initialUncleDelay = 1 minutes;
config.enableTokenomics = true;
config.enablePublicInputsCheck = false;
config.enableOracleProver = false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,6 @@ contract TestTaikoL2EnablePublicInputsCheck is TaikoL2 {
config.initialUncleDelay = 1 minutes;
config.enableTokenomics = true;
config.enablePublicInputsCheck = true;
config.enableOracleProver = false;
}
}