Skip to content

Commit

Permalink
feat(protocol): temporarily force an oracle prover to be the first …
Browse files Browse the repository at this point in the history
…prover (#13070)

Co-authored-by: jeff <[email protected]>
  • Loading branch information
dantaik and cyberhorsey authored Jan 31, 2023
1 parent 8167e9d commit d7401a2
Show file tree
Hide file tree
Showing 10 changed files with 80 additions and 27 deletions.
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;
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;
}
}

0 comments on commit d7401a2

Please sign in to comment.