# Watchtower Architecture

## Architecture

<figure><img src="https://651400886-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaZ7PXq43vesxvXxlBG9x%2Fuploads%2FtghzOD3PQeLz9zY42OgZ%2FAggregator%20Architecture-Entire%20Watchtower.drawio%20(2).png?alt=media&#x26;token=4034612d-2a49-4b8d-ad23-0454e064d2fd" alt=""><figcaption></figcaption></figure>

WitnessChain Watchtowers' software stack comprise of &#x20;

1. Watchtower Client (written in Go)&#x20;
2. On-chain Smart Contracts on Ethereum & on a Layer-2 chain
   1. **Layer 1:** Operator Registry, Settlement (ServiceManager aka EigenTower) & Alert Manager
   2. **Layer 2:** DiligenceProofManager Contract
3. Centralized Aggregator (to submit "batched" bounty settlements (rewards) on Ethereum)

## Watchtower client

### Proof of Diligence

At a high level, the process of L2 state validation in a watchtower node client has 4 stages

1. Output State Root Extraction from L1
2. Output State Root Extraction (Tracer execution) from L2 Node
3. Comparison & generating proofs of diligence
4. Smart Contract integration to publish the proofs

<figure><img src="https://651400886-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaZ7PXq43vesxvXxlBG9x%2Fuploads%2Fq3ghWSP4ehgVIqDeU6Iy%2Fwatchtower_2.jpg?alt=media&#x26;token=187d295a-0d29-45b2-b831-da7a0bc8e832" alt=""><figcaption><p>Sequence of Steps</p></figcaption></figure>

## List of Key Smart Contracts and their key functions

### 1. OperatorRegistry

This is Registry-type contract for keeping track of operators. It is used for registering and deregistering new operators. Only registered and delegated EigenLayer operators are allowed into the watchtower network

### *<mark style="color:green;">addToOperatorWhitelist(\[OperatorAddress])</mark>*

<table data-header-hidden><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Called By</strong></td><td>Contract Owner</td></tr><tr><td><strong>Returns</strong></td><td>None</td></tr><tr><td><strong>Emits</strong></td><td><p></p><pre class="language-solidity"><code class="lang-solidity">OperatorsWhiteListed(operatorsList, block.number);
</code></pre></td></tr></tbody></table>

* Adds the list of operators to the whitelist mapping

### *<mark style="color:green;">suspend</mark>*<mark style="color:green;">(operator)</mark>

<table data-header-hidden><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Called By</strong></td><td>Contract Owner</td></tr><tr><td><strong>Returns</strong></td><td>None</td></tr><tr><td><strong>Emits</strong></td><td><p></p><pre class="language-solidity"><code class="lang-solidity">OperatorSuspended(operatorAddress, block.number);
</code></pre></td></tr></tbody></table>

* Removes the operator from the whitelist mapping

### *<mark style="color:green;">registerWatchtowerAsOperator(watchtower, expiry, signedMessage)</mark>*

<table data-header-hidden><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Called By</strong></td><td>Node operator</td></tr><tr><td><strong>Returns</strong></td><td>None</td></tr><tr><td><strong>Emits</strong></td><td><p></p><pre class="language-solidity"><code class="lang-solidity">WatchtowerRegisteredToOperator(msg.sender, _watchtowerAddress, block.number);
</code></pre></td></tr></tbody></table>

* Registers the operator as a watchtower

### *<mark style="color:green;">deRegister(watchtowerAddress)</mark>*

<table data-header-hidden><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Called By</strong></td><td>Node operator</td></tr><tr><td><strong>Returns</strong></td><td>None</td></tr><tr><td><strong>Emits</strong></td><td><p></p><pre class="language-solidity"><code class="lang-solidity">WatchtowerDeRegisteredFromOperator(msg.sender, watchtowerAddress, block.number);
</code></pre></td></tr></tbody></table>

* Deregisters the watchtower
* The watchtower client will no longer be able to post any proofs, until the operator registers the watchtower address again

### 2. DiligenceProofManager

The DiligenceProofManager Contract contains functionality for miners (aka Watchtowers) to submit (mine) their Proofs of Diligence for a Bounty Period (which is the period between 2 L2 Txn Batch submissions). After the next L2 output state root is posted on L1, the bounty is rewarded to the miner. Bounties are given for every L2 Output (L2 Block).&#x20;

### *<mark style="color:green;">setPoDClaimBounties(\_chainID, \_claimBounties)</mark>*

<table data-header-hidden><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Called By</strong></td><td>Owner of the Contract</td></tr><tr><td><strong>Returns</strong></td><td>None</td></tr><tr><td><strong>Emits</strong></td><td><p></p><pre class="language-solidity"><code class="lang-solidity">NewPODBountyInitialized(_chainID, _claimBounties);
</code></pre></td></tr></tbody></table>

* The owner of the Contract sets the Bounty Amount.
* Consider PoD bounties are just reward points for now. Lets say 1 point for every L2 block mined successfully by a WatchTower. A detailed Points documentation is in progress.

### *<mark style="color:green;">setPoIClaimBounties(\_chainID, \_claimBounties)</mark>*

<table data-header-hidden><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Called By</strong></td><td>Owner of the Contract</td></tr><tr><td><strong>Returns</strong></td><td>None</td></tr><tr><td><strong>Emits</strong></td><td><p></p><pre class="language-solidity"><code class="lang-solidity">NewPOIBountyInitialized(_chainID, _claimBounties);
</code></pre></td></tr></tbody></table>

* The owner of the Contract sets the Bounty Amount.
* Consider PoI bounties are just reward points for now. Lets say 1 point for every L2 block mined successfully by a WatchTower. A detailed Points documentation is in progress.

### *<mark style="color:green;">submitPoDProof (chainID, l2\_blockNumber, proofOfDiligence, signatureProofOfDiligence)</mark>*

| **Called By** | WatchTower (EigenLayer Node Operator) |
| ------------- | ------------------------------------- |
| **Returns**   | None                                  |
| **Emits**     | NewBountyClaimed event                |

* Watchtower(s) submits/mine a L2 block by submitting the Hash(intermediate state root) and signing the Hash.
* Validations on Contract take care if the right sender is sending this transaction

### *<mark style="color:green;">submitPoIProof (chainID, l2\_blockNumber, proofOfDiligence, signatureProofOfDiligence)</mark>*

| **Called By** | WatchTower (EigenLayer Node Operator) |
| ------------- | ------------------------------------- |
| **Returns**   | None                                  |
| **Emits**     | NewBountyClaimed event                |

* Watchtower(s) submits/mine a L2 block for a PoI proof.
* Validations on Contract take care if the right sender is sending this transaction

### 3. AlertManager

This contract is used for keeping track of alerts raised by watchtowers

### *<mark style="color:green;">raiseAlert(chainID, l2BlockNumber, originalOutputRoot, computedOutputRoot, proofofDiligence)</mark>*

<table data-header-hidden><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Called By</strong></td><td>Node Operator</td></tr><tr><td><strong>Returns</strong></td><td>None</td></tr><tr><td><strong>Emits</strong></td><td><p></p><pre class="language-solidity"><code class="lang-solidity">NewAlertRaised(msg.sender, _chainID, _l2BlockNumber);
</code></pre></td></tr></tbody></table>

* Raise an alert when there is a mismatch in output root between what is exeucte on L2 Node and asserted on L1 Contract

### *<mark style="color:green;">getAlerts(chainID,L2BlockNumber)</mark>*

<table data-header-hidden><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Called By</strong></td><td>Node Operator</td></tr><tr><td><strong>Returns</strong></td><td><p></p><pre class="language-solidity"><code class="lang-solidity">// chainID => block number => list of alerts raised
<strong>mapping(uint256 => mapping(uint256 => Alert[]))
</strong></code></pre></td></tr><tr><td><strong>Emits</strong></td><td>None</td></tr></tbody></table>

* Get all alerts raised so far a particular chainID and L2BlockNumber

### 4. WitnessHub (AVS ServiceManager Contract)

The WitnessHub Contract enables the aggregator to process settlements for collective submissions of Proofs of Diligence and Proofs of Inclusion provided by watchtowers on a Layer 2 (L2) blockchain. These submissions correspond to a Bounty Period, which is defined as the interval between two transactions on the L2 chain.

### *<mark style="color:green;">updateRewards (</mark>*<mark style="color:green;">chainID, blockNumBegin, blockNumEnd, operatorsList, proofRewards, rewardHash</mark>*<mark style="color:green;">)</mark>*

| **Called By** | Aggregator       |
| ------------- | ---------------- |
| **Returns**   | None             |
| **Emits**     | NewRewardsUpdate |

* Accepts a list of operators and proof rewards, which correspond to the aggregated rewards for the operators across their watchtowers's proof submissions for a particular chain id and a range of blocks. This function may only be called by the aggregator.

## Aggregator

An aggregator, a centralised entity managed by Witness Chain, listens for the PoD and PoI submissions made by the watchtowers on the L2 chain contracts (DiligenceProofManager). It employs a "weighted stake" strategy to determine the winning watchtower for each group of blocks.&#x20;

This approach allows for a fair and transparent winning process. The winning watchtower's information, along with the number of wins and a Proof of Settlement, is then recorded on the WitnessHub settlement contract on Layer 1 (L1).&#x20;

The aggregator has the flexibility to adjust the settlement frequency based on gas costs, optimizing the balance between operational efficiency and cost-effectiveness.
