Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ incremental = false

[workspace.dependencies]
# reth
gravity-api-types = { package = "api-types", git = "https://github.com/Galxe/gravity-aptos", rev = "b1f68dc85781ef0d28a568d9d64604b153be9d9e" }
gravity-api-types = { package = "api-types", git = "https://github.com/Galxe/gravity-aptos", rev = "a64f8adc274bf2681df796766ef9a5b195fee44b" }
reth = { path = "bin/reth" }
reth-storage-rpc-provider = { path = "crates/storage/rpc-provider" }
reth-basic-payload-builder = { path = "crates/payload/basic" }
Expand Down
61 changes: 48 additions & 13 deletions crates/pipe-exec-layer-ext-v2/execute/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ use crate::{
construct_metadata_txn, construct_validator_txn_from_extra_data,
dkg::{convert_dkg_start_event_to_api, DKGStartEvent},
system_txns_into_executed_ordered_block_result,
types::DataRecorded,
types::{DataRecorded, OracleDelivered},
SystemTxnResult, DKG_ADDR, NATIVE_MINT_PRECOMPILE_ADDR, NATIVE_ORACLE_ADDR,
RANDOMNESS_BY_HEIGHT_PRECOMPILE_ADDR, SYSTEM_CALLER,
},
Expand Down Expand Up @@ -105,26 +105,33 @@ fn extract_gravity_events_from_system_receipts(
"extract gravity events from receipt"
);
for log in &receipt.logs {
// Parse DataRecorded events only from NativeOracle.
// Parse both historical and current delivery events only from NativeOracle.
if log.address == NATIVE_ORACLE_ADDR {
if let Ok(event) = DataRecorded::decode_log(&log) {
let delivery = DataRecorded::decode_log(&log)
.map(|event| (event.sourceType, event.sourceId, event.nonce))
.or_else(|_| {
OracleDelivered::decode_log(&log)
.map(|event| (event.sourceType, event.sourceId, event.nonce))
});

if let Ok((source_type, source_id, nonce)) = delivery {
info!(target: "execute_ordered_block",
number=?block_number,
source_type=?event.sourceType,
source_id=?event.sourceId,
nonce=?event.nonce,
"data recorded event"
source_type=?source_type,
source_id=?source_id,
nonce=?nonce,
"oracle delivery event"
);
// Keep only the latest nonce for each (sourceType, sourceId)
let key = (event.sourceType, event.sourceId);
let key = (source_type, source_id);
data_records
.entry(key)
.and_modify(|existing_nonce| {
if event.nonce > *existing_nonce {
*existing_nonce = event.nonce;
if nonce > *existing_nonce {
*existing_nonce = nonce;
}
})
.or_insert(event.nonce);
.or_insert(nonce);
}
}

Expand All @@ -142,7 +149,7 @@ fn extract_gravity_events_from_system_receipts(
}
}

// Convert collected DataRecorded events to ProviderJWKs
// Convert collected delivery events to ProviderJWKs.
if !data_records.is_empty() {
let api_jwks: Vec<ProviderJWKs> = data_records
.into_iter()
Expand All @@ -168,7 +175,7 @@ fn extract_gravity_events_from_system_receipts(
number=?block_number,
epoch=?epoch,
provider_count=?api_jwks.len(),
"constructed ProviderJWKs from DataRecorded events"
"constructed ProviderJWKs from oracle delivery events"
);

gravity_events.push(GravityEvent::ObservedJWKsUpdated(epoch, api_jwks));
Expand Down Expand Up @@ -222,6 +229,34 @@ mod tests {
}
}

#[test]
fn extract_gravity_events_accepts_oracle_delivered_from_native_oracle_only() {
let event = OracleDelivered {
sourceType: 3,
sourceId: U256::from(4),
nonce: 5,
sourcePosition: 6,
payloadHash: B256::from([0x77; 32]),
};
let forged_receipts =
vec![receipt_with_log(Address::from([0x42; 20]), event.encode_log_data())];

let events = extract_gravity_events_from_system_receipts(&forged_receipts, 10, 7);
assert!(events.is_empty(), "forged OracleDelivered emitter must not produce GravityEvent");

let valid_receipts = vec![receipt_with_log(NATIVE_ORACLE_ADDR, event.encode_log_data())];
let events = extract_gravity_events_from_system_receipts(&valid_receipts, 10, 7);
assert_eq!(events.len(), 1);
match &events[0] {
GravityEvent::ObservedJWKsUpdated(epoch, jwks) => {
assert_eq!(*epoch, 7);
assert_eq!(jwks.len(), 1);
assert_eq!(jwks[0].version, 5);
}
other => panic!("expected ObservedJWKsUpdated, got {other:?}"),
}
}

#[test]
fn extract_gravity_events_ignores_dkg_start_from_wrong_emitter() {
let event = DKGStartEvent {
Expand Down
74 changes: 70 additions & 4 deletions crates/pipe-exec-layer-ext-v2/execute/src/onchain_config/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,21 @@ sol! {
/// @notice Nonce must be strictly increasing for each source
error NonceNotIncreasing(uint32 sourceType, uint256 sourceId, uint128 currentNonce, uint128 providedNonce);

/// @notice Nonce must be exactly the next value for each source
error NonceNotSequential(uint32 sourceType, uint256 sourceId, uint128 expectedNonce, uint128 providedNonce);

/// @notice Batch arrays have mismatched lengths
error OracleBatchArrayLengthMismatch(uint256 noncesLength, uint256 payloadsLength, uint256 gasLimitsLength);
error OracleBatchArrayLengthMismatch(
uint256 noncesLength,
uint256 blockNumbersLength,
uint256 payloadsLength,
uint256 gasLimitsLength
);
Comment on lines +63 to +68

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve decoding of the legacy batch-length error

When replaying or diagnosing a pre-upgrade block whose NativeOracle returns the former three-argument OracleBatchArrayLengthMismatch(uint256,uint256,uint256), its selector no longer matches this replacement four-argument declaration, so decode_revert_error classifies the known fatal contract error as an unknown revert. Keep a separately named legacy ABI declaration and handle both selectors to retain pre-hardfork error compatibility.

Useful? React with 👍 / 👎.


/// @notice Oracle source position exceeds the contract's uint128 range
error OracleSourcePositionOverflow(uint256 sourcePosition);

// -------------------- JWKManager Errors (for reference, callback failures don't revert main tx) --------------------
// -------------------- JWKManager Errors (for reference) --------------------
/// @notice JWK version must be strictly increasing
error JWKVersionNotIncreasing(bytes issuer, uint64 currentVersion, uint64 providedVersion);
}
Expand Down Expand Up @@ -182,13 +193,25 @@ pub fn decode_revert_error(output: &Bytes) -> Option<SystemTxnError> {
Some(SystemTxnError {
name: "OracleBatchArrayLengthMismatch".into(),
details: format!(
"Array length mismatch: nonces={}, payloads={}, gasLimits={}",
err.noncesLength, err.payloadsLength, err.gasLimitsLength
"Array length mismatch: nonces={}, positions={}, payloads={}, gasLimits={}",
err.noncesLength,
err.blockNumbersLength,
err.payloadsLength,
err.gasLimitsLength
),
severity: ErrorSeverity::Fatal,
})
}

s if s == OracleSourcePositionOverflow::SELECTOR => {
let err = OracleSourcePositionOverflow::abi_decode(output).ok()?;
Some(SystemTxnError {
name: "OracleSourcePositionOverflow".into(),
details: format!("Oracle source position exceeds uint128: {}", err.sourcePosition),
severity: ErrorSeverity::Fatal,
})
}

// -------------------- Recoverable Errors --------------------
s if s == ReconfigurationNotInProgress::SELECTOR => Some(SystemTxnError {
name: "ReconfigurationNotInProgress".into(),
Expand Down Expand Up @@ -226,6 +249,18 @@ pub fn decode_revert_error(output: &Bytes) -> Option<SystemTxnError> {
})
}

s if s == NonceNotSequential::SELECTOR => {
let err = NonceNotSequential::abi_decode(output).ok()?;
Some(SystemTxnError {
name: "NonceNotSequential".into(),
details: format!(
"Oracle nonce not sequential: sourceType={}, sourceId={}, expected={}, provided={}",
err.sourceType, err.sourceId, err.expectedNonce, err.providedNonce
),
severity: ErrorSeverity::Recoverable,
})
}

// Unknown selector
_ => None,
}
Expand Down Expand Up @@ -334,6 +369,37 @@ mod tests {
assert_eq!(err.severity, ErrorSeverity::Recoverable);
}

#[test]
fn test_decode_nonce_not_sequential() {
let error = NonceNotSequential {
sourceType: 3,
sourceId: alloy_primitives::U256::from(42),
expectedNonce: 11,
providedNonce: 13,
};
let result = decode_revert_error(&error.abi_encode().into()).unwrap();

assert_eq!(result.name, "NonceNotSequential");
assert_eq!(result.severity, ErrorSeverity::Recoverable);
assert!(result.details.contains("expected=11"));
assert!(result.details.contains("provided=13"));
}

#[test]
fn test_decode_current_batch_length_mismatch() {
let error = OracleBatchArrayLengthMismatch {
noncesLength: alloy_primitives::U256::from(1),
blockNumbersLength: alloy_primitives::U256::from(2),
payloadsLength: alloy_primitives::U256::from(3),
gasLimitsLength: alloy_primitives::U256::from(4),
};
let result = decode_revert_error(&error.abi_encode().into()).unwrap();

assert_eq!(result.name, "OracleBatchArrayLengthMismatch");
assert_eq!(result.severity, ErrorSeverity::Fatal);
assert!(result.details.contains("positions=2"));
}

#[test]
fn test_decode_unknown_error() {
// Random bytes that don't match any known error
Expand Down
Loading
Loading