Skip to content

Commit

Permalink
merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
imabdulbasit committed Jan 20, 2025
2 parents 471f7ca + 018fbc5 commit 00d48b5
Show file tree
Hide file tree
Showing 35 changed files with 4,690 additions and 378 deletions.
1 change: 1 addition & 0 deletions .env.contracts.example
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export FEE_CONTRACT_ADDRESS=
# The etherscan API key is needed to verify contracts on etherscan.
export ETHERSCAN_API_KEY=
export SOLC_VERSION=
export ARBISCAN_API_KEY=

# foundry scripts
export DEPLOYER_PRIVATE_KEY= #include the 0x prefix
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
cargo build --locked --release --workspace
- name: Build sequencer-sqlite
run: cargo build --release --manifest-path ./sequencer-sqlite/Cargo.toml --target-dir ./target
run: cargo build --locked --release --manifest-path ./sequencer-sqlite/Cargo.toml --target-dir ./target

- name: Build Espresso Dev Node
# Espresso Dev Node currently requires testing feature, so it is built separately.
Expand Down
4 changes: 0 additions & 4 deletions .vscode/ltex.dictionary.en-US.txt

This file was deleted.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ To deploy to sepolia set `SEPOLIA_RPC_URL` and `MNEMONIC` env vars and run

forge script DeployHotShot --broadcast --rpc-url sepolia

To additionally verify the contact on etherscan set the `ETHERSCAN_API_KEY` env var and run
To additionally verify the contract on etherscan set the `ETHERSCAN_API_KEY` env var and run

forge script DeployHotShot --broadcast --rpc-url sepolia --verify

Expand Down

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion contract-bindings/artifacts/LightClientMock_bytecode.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion contract-bindings/artifacts/LightClient_bytecode.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions contract-bindings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod erc1967_proxy;
pub mod fee_contract;
pub mod i_plonk_verifier;
pub mod light_client;
pub mod light_client_arbitrum;
pub mod light_client_mock;
pub mod light_client_state_update_vk;
pub mod light_client_state_update_vk_mock;
Expand Down
3,238 changes: 3,238 additions & 0 deletions contract-bindings/src/light_client_arbitrum.rs

Large diffs are not rendered by default.

86 changes: 19 additions & 67 deletions contract-bindings/src/permissioned_stake_table.rs

Large diffs are not rendered by default.

263 changes: 263 additions & 0 deletions contracts/broadcast/LightClientArb.s.sol/421614/run-latest.json

Large diffs are not rendered by default.

53 changes: 53 additions & 0 deletions contracts/broadcast/PlonkVerifier.s.sol/421614/run-latest.json

Large diffs are not rendered by default.

54 changes: 35 additions & 19 deletions contracts/rust/adapter/src/stake_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ impl NodeInfoJf {
da: rng.gen(),
}
}

pub fn stake_table_key_sol(&self) -> permissioned_stake_table::G2Point {
bls_jf_to_sol(self.stake_table_key)
}
}

impl From<NodeInfoJf> for NodeInfo {
Expand Down Expand Up @@ -173,25 +177,7 @@ impl From<NodeInfo> for NodeInfoJf {
schnorr_vk,
is_da,
} = value;
let stake_table_key = {
let g2 = diff_test_bn254::ParsedG2Point {
x0: bls_vk.x_0,
x1: bls_vk.x_1,
y0: bls_vk.y_0,
y1: bls_vk.y_1,
};
let g2_affine = short_weierstrass::Affine::<ark_bn254::g2::Config>::from(g2);
let mut bytes = vec![];
// TODO: remove serde round-trip once jellyfin provides a way to
// convert from Affine representation to VerKey.
//
// Serialization and de-serialization shouldn't fail.
g2_affine
.into_group()
.serialize_compressed(&mut bytes)
.unwrap();
BLSPubKey::deserialize_compressed(&bytes[..]).unwrap()
};
let stake_table_key = bls_sol_to_jf(bls_vk);
let state_ver_key = {
let g1_point: ParsedEdOnBN254Point = schnorr_vk.into();
let state_sk_affine = twisted_edwards::Affine::<EdwardsConfig>::from(g1_point);
Expand Down Expand Up @@ -221,6 +207,36 @@ impl From<PeerConfigKeys<BLSPubKey>> for NodeInfoJf {
}
}

pub fn bls_jf_to_sol(bls_vk: BLSPubKey) -> permissioned_stake_table::G2Point {
let ParsedG2Point { x0, x1, y0, y1 } = bls_vk.to_affine().into();
permissioned_stake_table::G2Point {
x_0: x0,
x_1: x1,
y_0: y0,
y_1: y1,
}
}

pub fn bls_sol_to_jf(bls_vk: permissioned_stake_table::G2Point) -> BLSPubKey {
let g2 = diff_test_bn254::ParsedG2Point {
x0: bls_vk.x_0,
x1: bls_vk.x_1,
y0: bls_vk.y_0,
y1: bls_vk.y_1,
};
let g2_affine = short_weierstrass::Affine::<ark_bn254::g2::Config>::from(g2);
let mut bytes = vec![];
// TODO: remove serde round-trip once jellyfin provides a way to
// convert from Affine representation to VerKey.
//
// Serialization and de-serialization shouldn't fail.
g2_affine
.into_group()
.serialize_compressed(&mut bytes)
.unwrap();
BLSPubKey::deserialize_compressed(&bytes[..]).unwrap()
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
85 changes: 85 additions & 0 deletions contracts/script/LightClientArb.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import { Script } from "forge-std/Script.sol";
import { LightClientArbitrum } from "../src/LightClientArbitrum.sol";
import { LightClient as LC } from "../src/LightClient.sol";
import { Upgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol";

contract DeployLightClientArbitrum is Script {
// Deployment Errors
error SetPermissionedProverFailed();
error OwnerTransferFailed();
error RetentionPeriodIsNotSetCorrectly();
error InitialStateIsNotSetCorrectly();

function run(uint32 numInitValidators, uint32 stateHistoryRetentionPeriod, address owner)
public
returns (
address proxyAddress,
address implementationAddress,
LC.LightClientState memory lightClientState
)
{
address deployer;

string memory ledgerCommand = vm.envString("USE_HARDWARE_WALLET");
if (keccak256(bytes(ledgerCommand)) == keccak256(bytes("true"))) {
deployer = vm.envAddress("DEPLOYER_HARDWARE_WALLET_ADDRESS");
} else {
// get the deployer info from the environment
string memory seedPhrase = vm.envString("DEPLOYER_MNEMONIC");
uint32 seedPhraseOffset = uint32(vm.envUint("DEPLOYER_MNEMONIC_OFFSET"));
(deployer,) = deriveRememberKey(seedPhrase, seedPhraseOffset);
}

vm.startBroadcast(deployer);

string[] memory cmds = new string[](3);
cmds[0] = "diff-test";
cmds[1] = "mock-genesis";
cmds[2] = vm.toString(uint256(numInitValidators));

bytes memory result = vm.ffi(cmds);
(LC.LightClientState memory state, LC.StakeTableState memory stakeState) =
abi.decode(result, (LC.LightClientState, LC.StakeTableState));

proxyAddress = Upgrades.deployUUPSProxy(
"LightClientArbitrum.sol:LightClientArbitrum",
abi.encodeCall(
LC.initialize, (state, stakeState, stateHistoryRetentionPeriod, deployer)
)
);

LightClientArbitrum lightClientArbitrumProxy = LightClientArbitrum(proxyAddress);

// Currently, the light client is in prover mode so set the permissioned prover
address permissionedProver = vm.envAddress("PERMISSIONED_PROVER_ADDRESS");
lightClientArbitrumProxy.setPermissionedProver(permissionedProver);

// transfer ownership to the multisig
lightClientArbitrumProxy.transferOwnership(owner);

// verify post deployment details
if (lightClientArbitrumProxy.permissionedProver() != permissionedProver) {
revert SetPermissionedProverFailed();
}
if (lightClientArbitrumProxy.owner() != owner) revert OwnerTransferFailed();
if (lightClientArbitrumProxy.stateHistoryRetentionPeriod() != stateHistoryRetentionPeriod) {
revert RetentionPeriodIsNotSetCorrectly();
}
if (lightClientArbitrumProxy.stateHistoryFirstIndex() != 0) {
revert InitialStateIsNotSetCorrectly();
}
if (lightClientArbitrumProxy.getStateHistoryCount() != 0) {
revert InitialStateIsNotSetCorrectly();
}

// Get the implementation address
implementationAddress = Upgrades.getImplementationAddress(proxyAddress);

vm.stopBroadcast();

return (proxyAddress, implementationAddress, state);
}
}
2 changes: 1 addition & 1 deletion contracts/script/PlonkVerifier.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ pragma solidity ^0.8.20;
import { Script } from "forge-std/Script.sol";

import { Options, Upgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol";

/// @notice Deploys an upgradeable Plonk Verifier Contract using the OpenZeppelin Upgrades plugin.
/// @dev The Upgrades library has a deployImplementation function which is used here

contract DeployPlonkVerifierScript is Script {
string public contractName = "PlonkVerifier.sol";

Expand Down
19 changes: 19 additions & 0 deletions contracts/script/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -368,3 +368,22 @@ This error occurs when build_info is set to true in the foundry.toml configurati
foundry profile is set to default when running commands like `just gen-bindings`.
Solution: `export FOUNDRY_PROFILE=default`
## Deploy LightClientArbitrum
Additional Pre-requisites:
- an API key from arbiscan to verify the contract.
```bash
source .env.contracts && \
forge clean && \
forge script contracts/script/LightClientArb.s.sol:DeployLightClientArbitrum $NUM_INIT_VALIDATORS $STATE_HISTORY_RETENTION_PERIOD $SAFE_MULTISIG_ADDRESS \
--sig 'run(uint32, uint32, address)' \
--ffi \
--rpc-url $RPC_URL \
--libraries contracts/src/libraries/PlonkVerifier.sol:PlonkVerifier:$PLONK_VERIFIER_ADDRESS \
--build-info true \
--verify --etherscan-api-key $ARBISCAN_API_KEY \
--broadcast
```
2 changes: 0 additions & 2 deletions contracts/src/LightClient.sol
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,6 @@ contract LightClient is Initializable, OwnableUpgradeable, UUPSUpgradeable {
finalizedState = _genesis;

stateHistoryRetentionPeriod = _stateHistoryRetentionPeriod;

updateStateHistory(uint64(currentBlockNumber()), uint64(block.timestamp), _genesis);
}

// === State Modifying APIs ===
Expand Down
10 changes: 5 additions & 5 deletions contracts/src/PermissionedStakeTable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { EdOnBN254 } from "./libraries/EdOnBn254.sol";
* @dev An stake table mapping with owner-only access control.
*/
contract PermissionedStakeTable is Ownable {
event StakersUpdated(NodeInfo[] removed, NodeInfo[] added);
event StakersUpdated(BN254.G2Point[] removed, NodeInfo[] added);

error StakerAlreadyExists(BN254.G2Point);
error StakerNotFound(BN254.G2Point);
Expand All @@ -33,7 +33,7 @@ contract PermissionedStakeTable is Ownable {

// public methods

function update(NodeInfo[] memory stakersToRemove, NodeInfo[] memory newStakers)
function update(BN254.G2Point[] memory stakersToRemove, NodeInfo[] memory newStakers)
public
onlyOwner
{
Expand All @@ -55,12 +55,12 @@ contract PermissionedStakeTable is Ownable {
}
}

function remove(NodeInfo[] memory stakersToRemove) internal {
function remove(BN254.G2Point[] memory stakersToRemove) internal {
// TODO: revert if array empty
for (uint256 i = 0; i < stakersToRemove.length; i++) {
bytes32 stakerID = _hashBlsKey(stakersToRemove[i].blsVK);
bytes32 stakerID = _hashBlsKey(stakersToRemove[i]);
if (!stakers[stakerID]) {
revert StakerNotFound(stakersToRemove[i].blsVK);
revert StakerNotFound(stakersToRemove[i]);
}
stakers[stakerID] = false;
}
Expand Down
Loading

0 comments on commit 00d48b5

Please sign in to comment.