Add offchain client specification for SSV clusters#2
Add offchain client specification for SSV clusters#2GalRogozinski wants to merge 24 commits intomainfrom
Conversation
This document specifies the offchain oracle client for SSV clusters, detailing its scope, timing configuration, finalization requirements, data sources, Merkle tree construction, and client architecture.
Updated timing configuration section and adjusted logic for handling epochs and rounds. Modified function signatures and clarified client responsibilities.
Updated configuration format from JSON to YAML in documentation.
SPEC.md
Outdated
| ### 5.3 Odd-Leaf Handling (Empty Leaf) | ||
|
|
||
| Simply duplicate the last leaf. Ensure OpenZepplin compatibility like in [the following library]( https://github.com/cbergoon/merkletree). |
There was a problem hiding this comment.
Internal contradiction: "Empty Leaf" vs "Duplicate Last Leaf"
Section 5.3 title says "Odd-Leaf Handling (Empty Leaf)" but the text says "duplicate the last leaf."
Then Step 7 (L289-L293) says:
If number of leaves is odd, append `emptyLeaf`.
These are different concepts:
- Duplicate last leaf:
leaves.append(leaves[-1]) - Empty leaf:
leaves.append(keccak256(0x00...00))or similar
This ambiguity would cause different implementations to produce different roots.
Suggested fix: Pick ONE approach and be explicit:
### 5.3 Odd-Leaf Handling
If the number of leaves at any tree level is odd, duplicate the last node.
This is the Bitcoin/standard approach for balanced tree construction.
Example: [A, B, C] → [A, B, C, C] → build tree
SPEC.md
Outdated
| For each cluster `c`: | ||
|
|
||
| - `clusterId` – `bytes32` (canonical cluster identifier). | ||
| - `effectiveBalance` – integer (e.g. `uint64` / `uint256`), with agreed units (e.g. Gwei or ETH @marco ?). |
There was a problem hiding this comment.
This question must be resolved before the spec is finalized
There was a problem hiding this comment.
@olegshmuelov please use uint64, gwei.
There was a problem hiding this comment.
@mtabasco
How do you decode the effective balance?
Aleg will use uint64 (since no uint256 type in go)
Solidity can be fine with this?
| * @param clusterOwner Owner address of the cluster | ||
| * @param operatorIds Array of operator IDs in the cluster | ||
| * @param cluster Current cluster state (provided by oracle) | ||
| * @param effectiveBalance Total cluster effective balance in wei (sum of all validators) |
There was a problem hiding this comment.
The UpdateClusterBalance function signature has an inconsistency in units.
The NatSpec comment says:
* @param effectiveBalance Total cluster effective balance in wei (sum of all validators)But Section 4.1 and 5.1 define effectiveBalance as uint64 in gwei, not wei.
SPEC.md
Outdated
| - Log permanent failure for this round and wait for manual intervention. | ||
|
|
||
| 10. **Optional: update cluster balance** | ||
| - Listen to the `RootCommitted(merkleRoot, blockNum, block.timestamp)` event and validate the correct `merkleRoot` is constructed for `blockNum`. |
There was a problem hiding this comment.
The RootCommitted event signature in Section 10 differs from Section 6.1.
|
|
||
| The `effectiveBalance` of the cluster is the sum of all its SSV validators. | ||
| If the `effectiveBalance` of a validator is below or equal to the (EJECTION_BALANCE)(https://eth2book.info/capella/annotated-spec/#validator-cycle) of 16 ETH, | ||
| If the `effectiveBalance` of a validator is below or equal to the 32 ETH, |
| ##### 5.2 Ordering | ||
|
|
||
| - Collect all leaves. | ||
| - Sort by `clusterId` ascending (as `bytes32`). | ||
| - Construct `leaves[]` in that order. | ||
|
|
||
| This ordering guarantees a deterministic Merkle tree. |
There was a problem hiding this comment.
Sorting by leaf hash (instead of clusterID) is equally deterministic and provides compatibility with OpenZeppelin's StandardMerkleTree tooling. This allows external verification using their JavaScript library without custom implementations.
This document specifies the offchain oracle client for SSV clusters, detailing its scope, timing configuration, finalization requirements, data sources, Merkle tree construction, and client architecture.