---
# System prepended metadata

title: Untitled

---

```solidity=
struct Validator {
    address addr.
    bytes blskey;
    uint votingPower
}

struct Checkpoint {
    uint256 epochId
    uint256 blockNumber
    uint256 startEpochBlockNumber
    bytes32 eventRoot
}

mapping(uint256 => Checkpoint) public checkpoints;


function verifyCheckpoint(
    //supernet id to avoid replay attack
    uint chainID,
  //@todo Do we need to send checkpointHash or to derive from data?
    bytes aggregatedSignature, 
    bytes validatorsBitmap, //which validators signed checkpoint
    uint epochId,
    uint blockNumber, //checkpoint identifier
    bytes32 blockHash,
    uint round,
    bytes32 eventRoot,
    bytes32 currentValidatorSetHash,
    Validator[] nextValidators,
) public {
    //check that checkpoint have enough voting power
    checkQuorum(validatorsBitmap);
    
    nextValidatorSetHash = currentValidatorSetHash
    // need to update validator set. Do we need new epoch id there?
    if (len(nextValidators)>0) {
        nextValidatorSetHash = calculateNextValidatorSetHash(nextValidators)
    }
    
    // derive checkpoint hash from checkpoint data    
    checkpointHash = verifyCheckpointHash(blockNumber, blockHash, round, epochId, eventRoot, currentValidatorSetHash, nextValidatorSetHash);
    // verify checkpoint signature      
    verifySignature(checkpointHash, aggregatedSignature, validatorsBitmap); 

	// store intermediatory checkpoints and override latest epoch id
	if (checkpoints[epochId] == null) {
	    checkpoints[epochId] = eventRootHash; 
    } else if (checkpoints[epochId].blockNumber < blockNumber) {
		checkpoints[epochId] = eventRootHash;
	}
    
    if (len(nextValidators)>0) {
        updateValidatorSet(nextValidators);
        epoch++
    }
}
```

```solidity=
struct L2Event {
    uint counter;
    address sender;
    address receiver;
    bytes data;
    L2StateSynced(++counter, msg.sender, receiver, data)
}
function doExit(uint epochID, L2Event exitEvent, bytes exitProof) public {
    checkProof(checkpoints[epochID], exitEvent, exitProof);
    saveExit(exitEvent);
    makeExit();
}

```










```solidity=

struct Checkpoint {
    uint256 epochId,
    uint256 endBlock,
    bytes32 eventRoot
}

uint256 public currentEpochId;
bytes32 public currentValidatorSetHash;
Validator[] public currentValidators;
mapping(uint256 => Checkpoint) public checkpoints;



submitCheckpoint(
    uint256 chainID, //supernet id to avoid replay attack
    bytes aggregatedSignature, 
    bytes validatorsBitmap, //which validators signed checkpoint
    uint epochId,
    uint blockNumber, //checkpoint identifier
    bytes32 blockHash,
    uint round,
    bytes32 eventRoot,
    Validator[] nextValidators,
) {
    // Epoch Id will always be next one
    require(currentEpochId + 1 = epochId);
    
    // create hash of next validators
    // will it be same as currentValidators if it's not epoch change
    byte32 nextValidatorSetHash = currentValidatorSetHash;
    if (len(nextValidators) != 0) {
        nextValidatorSetHash = hash(nextValidators);
    }

    //check that checkpoint have enough voting power
    checkQuorum(validatorsBitmap);

    // derive checkpoint hash from checkpoint data    
    // Hash will have new validator set along with epoch id, start block, end block, event root
    checkpointHash = verifyCheckpointHash(chainID, blockNumber, blockHash, round, epochId, eventRoot, currentValidatorSetHash, nextValidatorSetHash);
    // verify checkpoint signature   
    // sigs will be current validator set's sig, so verify against the current validator set
    verifySignature(checkpointHash, aggregatedSignature, validatorsBitmap);

	// store intermediatory checkpoints and override it with latest epoch id
	if (
		checkpoints[epochId] == null || checkpoints[epochId].endBlock < endBlock
	) {

        checkpoints[epochId] = { epochId, blockNumber as endBlock, eventRootHash };

        // epoch changed - update stored validator set and validator set hash
        if (nextValidatorSetHash != currentValidatorSetHash) {
            currentValidators = nextValidators;
            currentValidatorSetHash = nextValidatorSetHash;
            currentEpochId = currentEpochId + 1;
        }

        return;
	}
	
	// Code should never reach here
	assert(false);
}
```