Skip to content

Commit 581ebac

Browse files
committed
Update flashtestation service with latest contracts
1 parent 201311d commit 581ebac

File tree

11 files changed

+334
-296
lines changed

11 files changed

+334
-296
lines changed

Cargo.lock

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/op-rbuilder/Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ moka = "0.12"
125125
http = "1.0"
126126
sha3 = "0.10"
127127
hex = "0.4"
128-
ureq = "2.10"
128+
reqwest = "0.12.23"
129129
k256 = "0.13.4"
130130

131131
rollup-boost = { git = "http://github.com/flashbots/rollup-boost", rev = "b86af43969557bee18f17ec1d6bcd3e984f910b2" }
@@ -136,6 +136,9 @@ tar = { version = "0.4", optional = true }
136136
ctor = { version = "0.4.2", optional = true }
137137
rlimit = { version = "0.10", optional = true }
138138
macros = { path = "src/tests/framework/macros", optional = true }
139+
hyper = { version = "1.7.0", features = ["http1"], optional = true }
140+
hyper-util = { version = "0.1.11", optional = true }
141+
http-body-util = { version = "0.1.3", optional = true }
139142
testcontainers = "0.24.0"
140143
dirs-next = "2.0.0"
141144

@@ -157,6 +160,9 @@ reth-ipc = { workspace = true }
157160
reth-node-builder = { workspace = true, features = ["test-utils"] }
158161
ctor = "0.4.2"
159162
rlimit = { version = "0.10" }
163+
hyper = { version = "1.7.0", features = ["http1"] }
164+
hyper-util = { version = "0.1.11" }
165+
http-body-util = { version = "0.1.3" }
160166

161167
[features]
162168
default = ["jemalloc"]

crates/op-rbuilder/src/builders/builder_tx.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use alloy_consensus::TxEip1559;
22
use alloy_eips::{Encodable2718, eip7623::TOTAL_COST_FLOOR_PER_TOKEN};
33
use alloy_evm::Database;
44
use alloy_primitives::{
5-
Address, B256, Log, TxKind,
5+
Address, B256, Log, TxKind, U256,
66
map::foldhash::{HashSet, HashSetExt},
77
};
88
use core::fmt::Debug;
@@ -13,9 +13,7 @@ use reth_node_api::PayloadBuilderError;
1313
use reth_optimism_primitives::OpTransactionSigned;
1414
use reth_primitives::Recovered;
1515
use reth_provider::{ProviderError, StateProvider};
16-
use reth_revm::{
17-
State, database::StateProviderDatabase, db::states::bundle_state::BundleRetention,
18-
};
16+
use reth_revm::{State, database::StateProviderDatabase};
1917
use revm::{
2018
DatabaseCommit,
2119
context::result::{EVMError, ResultAndState},
@@ -57,6 +55,9 @@ pub enum BuilderTransactionError {
5755
/// Signature signing fails
5856
#[error("failed to sign transaction: {0}")]
5957
SigningError(secp256k1::Error),
58+
/// Invalid tx errors during evm execution.
59+
#[error("invalid transaction error {0}")]
60+
InvalidTransactionError(Box<dyn core::error::Error + Send + Sync>),
6061
/// Unrecoverable error during evm execution.
6162
#[error("evm execution error {0}")]
6263
EvmExecutionError(Box<dyn core::error::Error + Send + Sync>),
@@ -187,7 +188,6 @@ pub trait BuilderTransactions<ExtraCtx: Debug + Default = ()>: Debug {
187188
.map_err(|err| BuilderTransactionError::EvmExecutionError(Box::new(err)))?;
188189

189190
evm.db_mut().commit(state);
190-
evm.db_mut().merge_transitions(BundleRetention::Reverts);
191191
}
192192

193193
Ok(simulation_state)
@@ -283,7 +283,7 @@ impl BuilderTxBase {
283283
}
284284
}
285285

286-
pub(crate) fn get_nonce(
286+
pub fn get_nonce(
287287
db: &mut State<impl Database>,
288288
address: Address,
289289
) -> Result<u64, BuilderTransactionError> {
@@ -292,6 +292,15 @@ pub(crate) fn get_nonce(
292292
.map_err(|_| BuilderTransactionError::AccountLoadFailed(address))
293293
}
294294

295-
pub(crate) fn log_exists(logs: &[Log], topic: &B256) -> bool {
295+
pub fn get_balance(
296+
db: &mut State<impl Database>,
297+
address: Address,
298+
) -> Result<U256, BuilderTransactionError> {
299+
db.load_cache_account(address)
300+
.map(|acc| acc.account_info().unwrap_or_default().balance)
301+
.map_err(|_| BuilderTransactionError::AccountLoadFailed(address))
302+
}
303+
304+
pub fn log_exists(logs: &[Log], topic: &B256) -> bool {
296305
logs.iter().any(|log| log.topics().first() == Some(topic))
297306
}

crates/op-rbuilder/src/builders/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ impl<ExtraCtx: Debug + Default> OpPayloadBuilderCtx<ExtraCtx> {
480480
}
481481
if exclude_reverting_txs {
482482
log_txn(TxnExecutionResult::RevertedAndExcluded);
483-
info!(target: "payload_builder", tx_hash = ?tx.tx_hash(), "skipping reverted transaction");
483+
info!(target: "payload_builder", tx_hash = ?tx.tx_hash(), result = ?result, "skipping reverted transaction");
484484
best_txs.mark_invalid(tx.signer(), tx.nonce());
485485
continue;
486486
} else {

crates/op-rbuilder/src/builders/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ mod flashblocks;
2121
mod generator;
2222
mod standard;
2323

24-
pub use builder_tx::{BuilderTransactionCtx, BuilderTransactionError, BuilderTransactions};
24+
pub use builder_tx::{
25+
BuilderTransactionCtx, BuilderTransactionError, BuilderTransactions, get_balance, get_nonce,
26+
log_exists,
27+
};
2528
pub use context::OpPayloadBuilderCtx;
2629
pub use flashblocks::FlashblocksBuilder;
2730
pub use standard::StandardBuilder;

crates/op-rbuilder/src/builders/standard/payload.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,15 @@ impl<Txs: PayloadTxsBounds> OpBuilder<'_, Txs> {
347347
// 4. if mem pool transactions are requested we execute them
348348

349349
// gas reserved for builder tx
350-
let builder_txs = builder_tx.add_builder_txs(&state_provider, &mut info, ctx, db, true)?;
350+
let builder_txs =
351+
match builder_tx.add_builder_txs(&state_provider, &mut info, ctx, db, true) {
352+
Ok(builder_txs) => builder_txs,
353+
Err(e) => {
354+
error!(target: "payload_builder", "Error adding builder txs to block: {}", e);
355+
vec![]
356+
}
357+
};
358+
351359
let builder_tx_gas = builder_txs.iter().fold(0, |acc, tx| acc + tx.gas_used);
352360
let block_gas_limit = ctx.block_gas_limit().saturating_sub(builder_tx_gas);
353361
if block_gas_limit == 0 {
@@ -394,7 +402,9 @@ impl<Txs: PayloadTxsBounds> OpBuilder<'_, Txs> {
394402
}
395403

396404
// Add builder tx to the block
397-
builder_tx.add_builder_txs(&state_provider, &mut info, ctx, db, false)?;
405+
if let Err(e) = builder_tx.add_builder_txs(&state_provider, &mut info, ctx, db, false) {
406+
error!(target: "payload_builder", "Error adding builder txs to fallback block: {}", e);
407+
};
398408

399409
let state_merge_start_time = Instant::now();
400410

crates/op-rbuilder/src/flashtestations/args.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
use alloy_primitives::{Address, U256, utils::parse_ether};
2+
use clap::Parser;
3+
use reth_optimism_cli::commands::Commands;
24

3-
use crate::tx_signer::Signer;
5+
use crate::{args::Cli, tx_signer::Signer};
46

57
/// Parameters for Flashtestations configuration
68
/// The names in the struct are prefixed with `flashtestations`
7-
#[derive(Debug, Clone, Default, PartialEq, Eq, clap::Args)]
9+
#[derive(Debug, Clone, PartialEq, Eq, clap::Args)]
810
pub struct FlashtestationsArgs {
911
/// When set to true, the builder will initiate the flashtestations
1012
/// workflow within the bootstrapping and block building process.
@@ -91,3 +93,13 @@ pub struct FlashtestationsArgs {
9193
)]
9294
pub builder_proof_version: u8,
9395
}
96+
97+
impl Default for FlashtestationsArgs {
98+
fn default() -> Self {
99+
let args = Cli::parse_from(["dummy", "node"]);
100+
let Commands::Node(node_command) = args.command else {
101+
unreachable!()
102+
};
103+
node_command.ext.flashtestations
104+
}
105+
}
Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use std::io::Read;
1+
use reqwest::Client;
22
use tracing::info;
3-
use ureq;
43

54
const DEBUG_QUOTE_SERVICE_URL: &str = "http://ns31695324.ip-141-94-163.eu:10080/attest";
65

@@ -12,55 +11,55 @@ pub struct AttestationConfig {
1211
/// The URL of the quote provider
1312
pub quote_provider: Option<String>,
1413
}
15-
16-
/// Trait for attestation providers
17-
pub trait AttestationProvider {
18-
fn get_attestation(&self, report_data: [u8; 64]) -> eyre::Result<Vec<u8>>;
19-
}
20-
2114
/// Remote attestation provider
15+
#[derive(Debug, Clone)]
2216
pub struct RemoteAttestationProvider {
17+
client: Client,
2318
service_url: String,
2419
}
2520

2621
impl RemoteAttestationProvider {
2722
pub fn new(service_url: String) -> Self {
28-
Self { service_url }
23+
let client = Client::new();
24+
Self {
25+
client,
26+
service_url,
27+
}
2928
}
3029
}
3130

32-
impl AttestationProvider for RemoteAttestationProvider {
33-
fn get_attestation(&self, report_data: [u8; 64]) -> eyre::Result<Vec<u8>> {
31+
impl RemoteAttestationProvider {
32+
pub async fn get_attestation(&self, report_data: [u8; 64]) -> eyre::Result<Vec<u8>> {
3433
let report_data_hex = hex::encode(report_data);
3534
let url = format!("{}/{}", self.service_url, report_data_hex);
3635

3736
info!(target: "flashtestations", url = url, "fetching quote in debug mode");
3837

39-
let response = ureq::get(&url)
38+
let response = self
39+
.client
40+
.get(&url)
4041
.timeout(std::time::Duration::from_secs(10))
41-
.call()?;
42-
43-
let mut body = Vec::new();
44-
response.into_reader().read_to_end(&mut body)?;
42+
.send()
43+
.await?
44+
.error_for_status()?;
45+
let body = response.bytes().await?.to_vec();
4546

4647
Ok(body)
4748
}
4849
}
4950

50-
pub fn get_attestation_provider(
51-
config: AttestationConfig,
52-
) -> Box<dyn AttestationProvider + Send + Sync> {
51+
pub fn get_attestation_provider(config: AttestationConfig) -> RemoteAttestationProvider {
5352
if config.debug {
54-
Box::new(RemoteAttestationProvider::new(
53+
RemoteAttestationProvider::new(
5554
config
5655
.quote_provider
5756
.unwrap_or(DEBUG_QUOTE_SERVICE_URL.to_string()),
58-
))
57+
)
5958
} else {
60-
Box::new(RemoteAttestationProvider::new(
59+
RemoteAttestationProvider::new(
6160
config
6261
.quote_provider
6362
.expect("remote quote provider must be specified when not in debug mode"),
64-
))
63+
)
6564
}
6665
}

crates/op-rbuilder/src/flashtestations/mod.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,98 @@
1+
use alloy_sol_types::{Error, sol};
2+
use op_revm::OpHaltReason;
3+
4+
// https://github.com/flashbots/flashtestations/commit/7cc7f68492fe672a823dd2dead649793aac1f216
5+
sol!(
6+
#[sol(rpc, abi)]
7+
#[derive(Debug)]
8+
interface IFlashtestationRegistry {
9+
function registerTEEService(bytes calldata rawQuote, bytes calldata extendedRegistrationData) external;
10+
11+
/// @notice Emitted when a TEE service is registered
12+
/// @param teeAddress The address of the TEE service
13+
/// @param rawQuote The raw quote from the TEE device
14+
/// @param alreadyExists Whether the TEE service is already registered
15+
event TEEServiceRegistered(address indexed teeAddress, bytes rawQuote, bool alreadyExists);
16+
17+
/// @notice Emitted when the attestation contract is the 0x0 address
18+
error InvalidAttestationContract();
19+
/// @notice Emitted when the signature is expired because the deadline has passed
20+
error ExpiredSignature(uint256 deadline);
21+
/// @notice Emitted when the quote is invalid according to the Automata DCAP Attestation contract
22+
error InvalidQuote(bytes output);
23+
/// @notice Emitted when the report data length is too short
24+
error InvalidReportDataLength(uint256 length);
25+
/// @notice Emitted when the registration data hash does not match the expected hash
26+
error InvalidRegistrationDataHash(bytes32 expected, bytes32 received);
27+
/// @notice Emitted when the byte size is exceeded
28+
error ByteSizeExceeded(uint256 size);
29+
/// @notice Emitted when the TEE service is already registered when registering
30+
error TEEServiceAlreadyRegistered(address teeAddress);
31+
/// @notice Emitted when the signer doesn't match the TEE address
32+
error SignerMustMatchTEEAddress(address signer, address teeAddress);
33+
/// @notice Emitted when the TEE service is not registered
34+
error TEEServiceNotRegistered(address teeAddress);
35+
/// @notice Emitted when the TEE service is already invalid when trying to invalidate a TEE registration
36+
error TEEServiceAlreadyInvalid(address teeAddress);
37+
/// @notice Emitted when the TEE service is still valid when trying to invalidate a TEE registration
38+
error TEEIsStillValid(address teeAddress);
39+
/// @notice Emitted when the nonce is invalid when verifying a signature
40+
error InvalidNonce(uint256 expected, uint256 provided);
41+
}
42+
43+
#[sol(rpc, abi)]
44+
#[derive(Debug)]
45+
interface IBlockBuilderPolicy {
46+
function verifyBlockBuilderProof(uint8 version, bytes32 blockContentHash) external;
47+
48+
/// @notice Emitted when a block builder proof is successfully verified
49+
/// @param caller The address that called the verification function (TEE address)
50+
/// @param workloadId The workload identifier of the TEE
51+
/// @param version The flashtestation protocol version used
52+
/// @param blockContentHash The hash of the block content
53+
/// @param commitHash The git commit hash associated with the workload
54+
event BlockBuilderProofVerified(
55+
address caller, bytes32 workloadId, uint8 version, bytes32 blockContentHash, string commitHash
56+
);
57+
58+
/// @notice Emitted when the registry is the 0x0 address
59+
error InvalidRegistry();
60+
/// @notice Emitted when a workload to be added is already in the policy
61+
error WorkloadAlreadyInPolicy();
62+
/// @notice Emitted when a workload to be removed is not in the policy
63+
error WorkloadNotInPolicy();
64+
/// @notice Emitted when the address is not in the approvedWorkloads mapping
65+
error UnauthorizedBlockBuilder(address caller);
66+
/// @notice Emitted when the nonce is invalid
67+
error InvalidNonce(uint256 expected, uint256 provided);
68+
/// @notice Emitted when the commit hash is empty
69+
error EmptyCommitHash();
70+
/// @notice Emitted when the source locators array is empty
71+
error EmptySourceLocators();
72+
}
73+
74+
struct BlockData {
75+
bytes32 parentHash;
76+
uint256 blockNumber;
77+
uint256 timestamp;
78+
bytes32[] transactionHashes;
79+
}
80+
81+
type WorkloadId is bytes32;
82+
);
83+
84+
#[derive(Debug, thiserror::Error)]
85+
pub enum FlashtestationRevertReason {
86+
#[error("flashtestation registry error: {0:?}")]
87+
FlashtestationRegistry(IFlashtestationRegistry::IFlashtestationRegistryErrors),
88+
#[error("block builder policy error: {0:?}")]
89+
BlockBuilderPolicy(IBlockBuilderPolicy::IBlockBuilderPolicyErrors),
90+
#[error("unknown revert: {0} err: {1}")]
91+
Unknown(String, Error),
92+
#[error("halt: {0:?}")]
93+
Halt(OpHaltReason),
94+
}
95+
196
pub mod args;
297
pub mod attestation;
398
pub mod service;

0 commit comments

Comments
 (0)