Skip to content

Commit

Permalink
Merge pull request #110 from Layr-Labs/proofupdates
Browse files Browse the repository at this point in the history
EigenPod Proof Updates
  • Loading branch information
Sidu28 authored Aug 1, 2023
2 parents 8cbe4b6 + 877cfba commit 1db5c07
Show file tree
Hide file tree
Showing 14 changed files with 607 additions and 250 deletions.
2 changes: 1 addition & 1 deletion docs/docgen/libraries/BeaconChainProofs.md
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ struct WithdrawalProofs {
bytes32 blockHeaderRoot;
bytes32 blockBodyRoot;
bytes32 slotRoot;
bytes32 blockNumberRoot;
bytes32 timestampRoot;
bytes32 executionPayloadRoot;
}
```
Expand Down
6 changes: 1 addition & 5 deletions src/contracts/core/StrategyManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ import "../interfaces/IEigenPodManager.sol";
import "../permissions/Pausable.sol";
import "./StrategyManagerStorage.sol";


import "forge-std/Test.sol";

/**
* @title The primary entry- and exit-point for funds into and out of EigenLayer.
* @author Layr Labs, Inc.
Expand All @@ -32,8 +29,7 @@ contract StrategyManager is
OwnableUpgradeable,
ReentrancyGuardUpgradeable,
Pausable,
StrategyManagerStorage,
Test
StrategyManagerStorage
{
using SafeERC20 for IERC20;

Expand Down
24 changes: 15 additions & 9 deletions src/contracts/interfaces/IEigenPod.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ interface IEigenPod {
uint64 restakedBalanceGwei;
// status of the validator
VALIDATOR_STATUS status;
//slot number of the validator's most recent balance update
uint64 mostRecentBalanceUpdateSlot;
}

enum PARTIAL_WITHDRAWAL_CLAIM_STATUS {
Expand Down Expand Up @@ -84,8 +86,8 @@ interface IEigenPod {
/// @notice an indicator of whether or not the podOwner has ever "fully restaked" by successfully calling `verifyCorrectWithdrawalCredentials`.
function hasRestaked() external view returns (bool);

/// @notice block number of the most recent withdrawal
function mostRecentWithdrawalBlockNumber() external view returns (uint64);
/// @notice block timestamp of the most recent withdrawal
function mostRecentWithdrawalTimestamp() external view returns (uint64);

/// @notice Returns the validatorInfo struct for the provided pubkeyHash
function validatorPubkeyHashToInfo(bytes32 validatorPubkeyHash) external view returns (ValidatorInfo memory);
Expand All @@ -103,17 +105,18 @@ interface IEigenPod {
* this contract. It also verifies the current (not effective) balance of the validator. It verifies the provided proof of the ETH validator against the beacon chain state
* root, marks the validator as 'active' in EigenLayer, and credits the restaked ETH in Eigenlayer.
* @param oracleBlockNumber is the Beacon Chain blockNumber whose state root the `proof` will be proven against.
* @param validatorIndex is the index of the validator being proven, refer to consensus specs
* @param proofs is the bytes that prove the ETH validator's balance and withdrawal credentials against a beacon chain state root
* @param validatorIndices is the list of indices of the validator being proven, refer to consensus specs
* @param proofs is an array of proofs, where each proof proves the ETH validator's balance and withdrawal credentials against a beacon chain state root
* @param validatorFields are the fields of the "Validator Container", refer to consensus specs
* for details: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#validator
*/
function verifyWithdrawalCredentialsAndBalance(
function verifyWithdrawalCredentials(
uint64 oracleBlockNumber,
uint40 validatorIndex,
bytes memory proofs,
bytes32[] calldata validatorFields
uint40[] calldata validatorIndices,
BeaconChainProofs.WithdrawalCredentialProofs[] calldata proofs,
bytes32[][] calldata validatorFields
) external;


/**
* @notice This function records an overcommitment of stake to EigenLayer on behalf of a certain ETH validator.
Expand All @@ -130,7 +133,7 @@ interface IEigenPod {
*/
function verifyBalanceUpdate(
uint40 validatorIndex,
BeaconChainProofs.ValidatorFieldsAndBalanceProofs calldata proofs,
BeaconChainProofs.BalanceUpdateProofs calldata proofs,
bytes32[] calldata validatorFields,
uint256 beaconChainETHStrategyIndex,
uint64 oracleBlockNumber
Expand All @@ -154,6 +157,9 @@ interface IEigenPod {
uint64 oracleBlockNumber
) external;

/// @notice Called by the pod owner to withdraw the balance of the pod when `hasRestaked` is set to false
function activateRestaking() external;

/// @notice Called by the pod owner to withdraw the balance of the pod when `hasRestaked` is set to false
function withdrawBeforeRestaking() external;

Expand Down
53 changes: 41 additions & 12 deletions src/contracts/libraries/BeaconChainProofs.sol
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ library BeaconChainProofs {
uint256 internal constant BALANCE_INDEX = 12;
uint256 internal constant EXECUTION_PAYLOAD_HEADER_INDEX = 24;
uint256 internal constant HISTORICAL_BATCH_STATE_ROOT_INDEX = 1;
uint256 internal constant BEACON_STATE_SLOT_INDEX = 2;
uint256 internal constant LATEST_BLOCK_HEADER_ROOT_INDEX = 4;

// in validator
uint256 internal constant VALIDATOR_PUBKEY_INDEX = 0;
Expand All @@ -82,7 +84,7 @@ library BeaconChainProofs {
uint256 internal constant VALIDATOR_WITHDRAWABLE_EPOCH_INDEX = 7;

// in execution payload header
uint256 internal constant BLOCK_NUMBER_INDEX = 6;
uint256 internal constant TIMESTAMP_INDEX = 9;
uint256 internal constant WITHDRAWALS_ROOT_INDEX = 14;

//in execution payload
Expand All @@ -103,29 +105,36 @@ library BeaconChainProofs {


struct WithdrawalProofs {
bytes32 beaconStateRoot;
bytes latestBlockHeaderProof;
bytes blockHeaderProof;
bytes withdrawalProof;
bytes slotProof;
bytes executionPayloadProof;
bytes blockNumberProof;
bytes timestampProof;
uint64 blockHeaderRootIndex;
uint64 withdrawalIndex;
bytes32 blockHeaderRoot;
bytes32 blockBodyRoot;
bytes32 slotRoot;
bytes32 blockNumberRoot;
bytes32 timestampRoot;
bytes32 executionPayloadRoot;
}

struct ValidatorFieldsAndBalanceProofs {
bytes validatorFieldsProof;
struct BalanceUpdateProofs {
bytes32 beaconStateRoot;
bytes latestBlockHeaderProof;
bytes validatorBalanceProof;
bytes slotProof;
bytes32 balanceRoot;
bytes32 slotRoot;
}

struct ValidatorFieldsProof {
bytes validatorProof;
uint40 validatorIndex;
//struct ValidatorFieldsProof {
struct WithdrawalCredentialProofs {
bytes32 beaconStateRoot;
bytes latestBlockHeaderProof;
bytes validatorFieldsProof;
}

/**
Expand Down Expand Up @@ -198,6 +207,26 @@ library BeaconChainProofs {
require(Merkle.verifyInclusionSha256(proof, beaconStateRoot, balanceRoot, balanceIndex), "BeaconChainProofs.verifyValidatorBalance: Invalid merkle proof");
}

function verifySlotRoot(
bytes32 beaconStateRoot,
bytes calldata proof,
bytes32 slotRoot
) internal view {
require(proof.length == 32 * (BEACON_STATE_FIELD_TREE_HEIGHT), "BeaconChainProofs.verifySlotRoot: Proof has incorrect length");
//Next we verify the slot against the blockHeaderRoot
require(Merkle.verifyInclusionSha256(proof, beaconStateRoot, slotRoot, BEACON_STATE_SLOT_INDEX), "BeaconChainProofs.verifyWithdrawalProofs: Invalid slot merkle proof");
}

function verifyStateRootAgainstLatestBlockHeaderRoot(
bytes32 beaconStateRoot,
bytes32 latestBlockHeaderRoot,
bytes calldata proof
) internal view {
require(proof.length == 32 * (BEACON_STATE_FIELD_TREE_HEIGHT), "BeaconChainProofs.verifyStateRootAgainstLatestBlockHeaderRoot: Proof has incorrect length");
//Next we verify the slot against the blockHeaderRoot
require(Merkle.verifyInclusionSha256(proof, beaconStateRoot, latestBlockHeaderRoot, LATEST_BLOCK_HEADER_ROOT_INDEX), "BeaconChainProofs.verifyStateRootAgainstLatestBlockHeaderRoot: Invalid latest block header root merkle proof");
}

/**
* @notice This function verifies the slot and the withdrawal fields for a given withdrawal
* @param beaconStateRoot is the beacon chain state root to be proven against.
Expand All @@ -223,8 +252,8 @@ library BeaconChainProofs {
"BeaconChainProofs.verifyWithdrawalProofs: executionPayloadProof has incorrect length");
require(proofs.slotProof.length == 32 * (BEACON_BLOCK_HEADER_FIELD_TREE_HEIGHT),
"BeaconChainProofs.verifyWithdrawalProofs: slotProof has incorrect length");
require(proofs.blockNumberProof.length == 32 * (EXECUTION_PAYLOAD_HEADER_FIELD_TREE_HEIGHT),
"BeaconChainProofs.verifyWithdrawalProofs: blockNumberProof has incorrect length");
require(proofs.timestampProof.length == 32 * (EXECUTION_PAYLOAD_HEADER_FIELD_TREE_HEIGHT),
"BeaconChainProofs.verifyWithdrawalProofs: timestampProof has incorrect length");


/**
Expand All @@ -244,8 +273,8 @@ library BeaconChainProofs {
require(Merkle.verifyInclusionSha256(proofs.executionPayloadProof, proofs.blockHeaderRoot, proofs.executionPayloadRoot, executionPayloadIndex),
"BeaconChainProofs.verifyWithdrawalProofs: Invalid executionPayload merkle proof");

// Next we verify the blockNumberRoot against the executionPayload root
require(Merkle.verifyInclusionSha256(proofs.blockNumberProof, proofs.executionPayloadRoot, proofs.blockNumberRoot, BLOCK_NUMBER_INDEX),
// Next we verify the timestampRoot against the executionPayload root
require(Merkle.verifyInclusionSha256(proofs.timestampProof, proofs.executionPayloadRoot, proofs.timestampRoot, TIMESTAMP_INDEX),
"BeaconChainProofs.verifyWithdrawalProofs: Invalid blockNumber merkle proof");

/**
Expand Down
Loading

0 comments on commit 1db5c07

Please sign in to comment.