-
Notifications
You must be signed in to change notification settings - Fork 39
Add block builder tee proofs #236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: flashtestations
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -670,3 +670,96 @@ To establish trust in expected measurements, the TEE block builder must be built | |
4. **Verification**: Independent parties can follow the build process and verify that it produces the same measurements | ||
|
||
This allows anyone to verify that the expected measurements correspond to the published source code. | ||
|
||
## Block Builder TEE Proofs | ||
|
||
The Flashtestations protocol can be extended to provide cryptographic guarantees that blocks were constructed by an authorized TEE-based block builder. This section describes how block builders running in a TEE can prove block authenticity through an onchain verification mechanism. | ||
|
||
### Core Mechanism | ||
|
||
The block builder TEE proof system works through a final transaction appended to each block. This transaction: | ||
|
||
1. Calls a designated smart contract method that accepts a block content hash | ||
2. Verifies the caller's authorization using `isAllowedPolicy(block_builder_policy_id, msg.sender)` | ||
3. Provides cryptographic evidence that the block was constructed by a valid TEE-based block builder | ||
|
||
The key insight is that the required private key to sign this transaction is protected within the TEE environment. Thus, only a genuine TEE-based block builder with the proper attestation can successfully execute this transaction. | ||
|
||
### Block Building Process | ||
|
||
When building a block, the TEE block builder: | ||
|
||
1. Produces a block according to the L2 protocol rules | ||
2. Computes the block content hash using the `ComputeBlockContentHash` function: | ||
|
||
```solidity | ||
function ComputeBlockContentHash(block, transactions) { | ||
// Create ordered list of all transaction hashes | ||
transactionHashes = [] | ||
for each tx in transactions: | ||
txHash = keccak256(rlp_encode(tx)) | ||
transactionHashes.append(txHash) | ||
|
||
// Compute a single hash over block data and transaction hashes | ||
// This ensures the hash covers the exact transaction set and order | ||
return keccak256(abi.encode( | ||
block.parentHash, | ||
block.number, | ||
block.timestamp, | ||
transactionHashes | ||
)) | ||
} | ||
``` | ||
|
||
3. Computes `blockContentHash = ComputeBlockContentHash(block, block.transactions)` | ||
|
||
This block content hash formulation provides a balance between rollup compatibility and verification strength: | ||
- Contains the minimal set of elements needed to uniquely identify a block's contents | ||
- Compatible with data available on L1 for most optimistic and ZK rollup implementations | ||
- Enables signature verification without requiring state root dependencies | ||
- Supports future L1 verification of block authenticity across different rollup designs | ||
|
||
### Verification Contract | ||
|
||
The smart contract that verifies block builder TEE proofs would implement: | ||
|
||
```solidity | ||
// Block builder verification contract | ||
function verifyBlockBuilderProof(bytes32 blockContentHash) external { | ||
// Check if the caller is an authorized TEE block builder | ||
require( | ||
IAllowlist(ALLOWLIST_CONTRACT).isAllowedPolicy(BLOCK_BUILDER_POLICY_ID, msg.sender), | ||
"Unauthorized block builder" | ||
); | ||
|
||
// At this point, we know: | ||
// 1. The caller is a registered address from an attested TEE | ||
// 2. The TEE is running an approved block builder workload (via policy) | ||
|
||
// Additional validation can be performed on the blockContentHash | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What validation would this be? I can't think of anything useful we can do with a nonstandard hash like the one we have here. Solidity doesn't have retrospection so we can't look at the previous transactions to validate the blockContentHash onchain; all we can do is rely on the TEE to correctly compute this hash. If we can't think of anything, can we remove this comment so it's not ambiguous what we mean here? That would simplify things for implementers |
||
|
||
emit BlockBuilderProofVerified( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should add version here (see above comment) |
||
msg.sender, | ||
block.number, | ||
blockContentHash | ||
); | ||
} | ||
``` | ||
|
||
### Security Properties | ||
|
||
This mechanism provides several important security guarantees: | ||
|
||
1. **Block Authenticity**: Each block contains cryptographic proof that it was produced by an authorized TEE block builder | ||
2. **Non-Transferability**: The proof cannot be stolen or reused by unauthorized parties due to TEE protection of signing keys | ||
3. **Policy Flexibility**: The system can adapt to new block builder implementations by updating the policy without contract changes | ||
4. **Auditability**: All proofs are recorded onchain for transparency and verification | ||
|
||
### Integration with Rollup Systems | ||
|
||
For rollup systems, this proof mechanism: | ||
|
||
1. Can be included as the final transaction in each block | ||
2. Enables L1 contracts to verify that blocks were built by authorized TEEs | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this possible? L1 contracts do not have access to the EIP-4844 blobs that (see this explainer on EIP-4844 specifically the wording "Blobs are persisted in beacon nodes, not in execution layer"). If we want to expose this data to L1's, we'd need some way to bridge this transaction call to the L1. Maybe we want to do that, but it'll increase the gas cost of this (which we want to keep as cheap as possible). I think we should remove this line for now, as it's not clear it's possible. |
||
3. Provides a foundation for stronger security guarantees in optimistic rollups | ||
4. Supports cross-chain verification of block authenticity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should add a
uint8 version
argument here, so we can easily communicate the version of flashtestations this verification is meant for. Without this for example, if we later decide that we want to we want to change how the blockContentHash is calculated, then we'll have no way to communicate to offchain verifiers how to recompute theblockContentHash
offchain.The downside of this is that it will slightly increase L1 gas cost because of the additional calldata. But it's just a single 8-bit value, so it's very little.