Skip to content

Commit e42a276

Browse files
committed
Review Response: check before and afte
1 parent 1fc586b commit e42a276

File tree

1 file changed

+136
-114
lines changed

1 file changed

+136
-114
lines changed

integration_tests/src/tests/evm_notification_test.rs

Lines changed: 136 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ use fvm_shared::{
1313
piece::PieceInfo,
1414
sector::{RegisteredSealProof, SectorNumber},
1515
};
16+
use fvm_shared::address::Address;
1617
use num_traits::Zero;
1718
use vm_api::VM;
1819
use vm_api::util::serialize_ok;
20+
use cid::Cid;
1921

2022
use crate::util::{
2123
PrecommitMetadata, advance_by_deadline_to_epoch, create_accounts, create_miner,
@@ -112,6 +114,9 @@ pub fn evm_receives_ddo_notifications_test(v: &dyn VM) {
112114

113115
precommit_sectors_v2(v, 1, meta, &worker, &miner_addr, seal_proof, sector_number, true, None);
114116

117+
// Before prove commit no notifications have been received
118+
check_receiver_notification_count(v, &worker, &evm_robust_addr, 0);
119+
115120
// Advance time to prove commit epoch
116121
let prove_time = v.epoch() + 151;
117122
advance_by_deadline_to_epoch(v, &miner_addr, prove_time);
@@ -140,118 +145,135 @@ pub fn evm_receives_ddo_notifications_test(v: &dyn VM) {
140145
assert!(prove_result.code.is_success(), "ProveCommit failed: {}", prove_result.message);
141146

142147
/* ***Verify that the EVM contract received the notifications correctly*** */
143-
// 1. Call totalNotifications() to verify only one notification witnessed
144-
{
145-
let call_params = NotificationReceiver::totalNotificationsCall::new(()).abi_encode();
146-
let call_result = v
147-
.execute_message(
148-
&worker,
149-
&evm_robust_addr,
150-
&TokenAmount::zero(),
151-
fil_actor_evm::Method::InvokeContract as u64,
152-
Some(serialize_ok(&ContractParams(call_params.to_vec()))),
153-
)
154-
.unwrap();
155-
156-
assert!(
157-
call_result.code.is_success(),
158-
"Failed to call totalNotifications: {}",
159-
call_result.message
160-
);
161-
162-
// Decode the return value
163-
let return_data: BytesDe = call_result.ret.unwrap().deserialize().unwrap();
164-
let total_notifications = AlloyU256::abi_decode(&return_data.0)
165-
.expect("Failed to decode totalNotifications return value");
166-
assert_eq!(
167-
total_notifications,
168-
AlloyU256::from(1),
169-
"Expected 1 notification, got {}",
170-
total_notifications
171-
);
172-
}
173-
174-
// 2. Call getNotification(0) to verify the notification contents match exactly what was sent
175-
{
176-
let call_params =
177-
NotificationReceiver::getNotificationCall::new((AlloyU256::from(0),)).abi_encode();
178-
let call_result = v
179-
.execute_message(
180-
&worker,
181-
&evm_robust_addr,
182-
&TokenAmount::zero(),
183-
fil_actor_evm::Method::InvokeContract as u64,
184-
Some(serialize_ok(&ContractParams(call_params.to_vec()))),
185-
)
186-
.unwrap();
187-
assert!(
188-
call_result.code.is_success(),
189-
"Failed to call getNotification: {}",
190-
call_result.message
191-
);
192-
193-
// Decode the return value - it returns a tuple of (uint64, int64, bytes, uint64, bytes)
194-
let return_data: BytesDe = call_result.ret.unwrap().deserialize().unwrap();
195-
196-
// Use the generated abi_decode_returns function
197-
let notification_result =
198-
NotificationReceiver::getNotificationCall::abi_decode_returns(&return_data.0)
199-
.expect("Failed to decode getNotification return value");
200-
201-
let received_sector = notification_result.sector;
202-
let minimum_commitment_epoch = notification_result.minimumCommitmentEpoch;
203-
let data_cid_bytes = notification_result.dataCid;
204-
let received_piece_size = notification_result.pieceSize;
205-
let received_payload = notification_result.payload;
206-
207-
assert_eq!(
208-
received_sector, sector_number,
209-
"Sector number mismatch: expected {}, got {}",
210-
sector_number, received_sector
211-
);
212-
213-
assert_eq!(
214-
received_piece_size, piece_size0.0,
215-
"Piece size mismatch: expected {}, got {}",
216-
piece_size0.0, received_piece_size
217-
);
218-
219-
// Check payload matches exactly what we set in the manifest (hex "cafe")
220-
let expected_payload_bytes = notification_payload.to_vec();
221-
assert_eq!(
222-
received_payload.as_ref(),
223-
expected_payload_bytes.as_slice(),
224-
"Payload mismatch: expected 0x{}, got 0x{}",
225-
hex::encode(&expected_payload_bytes),
226-
hex::encode(&received_payload)
227-
);
228-
229-
// Check the piece CID data is present
230-
// The contract receives the CID with an extra leading byte from the CBOR encoding,
231-
// so we verify it contains the expected CID data after the first byte
232-
let expected_cid_bytes = piece_cid0.to_bytes();
233-
assert!(!data_cid_bytes.is_empty(), "Data CID should not be empty");
234-
// Verify the CID data matches
235-
assert_eq!(data_cid_bytes[0], 0, "Data CID should start with 0x00 for ipld cbor reasons");
236-
assert_eq!(
237-
&data_cid_bytes[1..],
238-
expected_cid_bytes,
239-
"Piece CID data mismatch: expected 0x{}, got 0x{}",
240-
hex::encode(&expected_cid_bytes),
241-
hex::encode(&data_cid_bytes[1..])
242-
);
243-
244-
// Verify minimum_commitment_epoch matches the sector expiration
245-
// The sector expiration is set to: precommit_epoch + min_sector_expiration + max_prove_commit_duration
246-
let policy = Policy::default();
247-
let expected_expiration = precommit_epoch
248-
+ policy.min_sector_expiration
249-
+ max_prove_commit_duration(&policy, seal_proof).unwrap();
250-
251-
assert_eq!(
252-
minimum_commitment_epoch, expected_expiration,
253-
"Minimum commitment epoch mismatch: expected {}, got {}",
254-
expected_expiration, minimum_commitment_epoch
255-
);
256-
}
148+
let policy = Policy::default();
149+
let expected_notification = ExpectedNotification {
150+
sector: sector_number,
151+
minimum_commitment_epoch: precommit_epoch + policy.min_sector_expiration + max_prove_commit_duration(&policy, seal_proof).unwrap(),
152+
piece_cid: piece_cid0,
153+
piece_size: piece_size0.0,
154+
payload: notification_payload.to_vec(),
155+
};
156+
157+
check_receiver_notification_count(v, &worker, &evm_robust_addr, 1);
158+
check_receiver_notification_at(v, &worker, &evm_robust_addr, 0, &expected_notification);
159+
}
160+
161+
// Helper functions checking state of receiver contract
162+
163+
pub fn check_receiver_notification_count(v: &dyn VM, sender_addr: &Address, receiver_addr: &Address, expected_count: u64) {
164+
let call_params = NotificationReceiver::totalNotificationsCall::new(()).abi_encode();
165+
let call_result = v
166+
.execute_message(
167+
&sender_addr,
168+
&receiver_addr,
169+
&TokenAmount::zero(),
170+
fil_actor_evm::Method::InvokeContract as u64,
171+
Some(serialize_ok(&ContractParams(call_params.to_vec()))),
172+
)
173+
.unwrap();
174+
175+
assert!(
176+
call_result.code.is_success(),
177+
"Failed to call totalNotifications: {}",
178+
call_result.message
179+
);
180+
181+
// Decode the return value
182+
let return_data: BytesDe = call_result.ret.unwrap().deserialize().unwrap();
183+
let total_notifications = AlloyU256::abi_decode(&return_data.0)
184+
.expect("Failed to decode totalNotifications return value");
185+
assert_eq!(
186+
total_notifications,
187+
AlloyU256::from(expected_count),
188+
"Expected {} notification(s), got {}",
189+
expected_count,
190+
total_notifications
191+
);
192+
}
193+
194+
/// Struct to hold all notification values for checking against contract state.
195+
#[derive(Debug, Clone, PartialEq, Eq)]
196+
pub struct ExpectedNotification {
197+
pub sector: u64,
198+
pub minimum_commitment_epoch: i64,
199+
pub piece_cid: Cid,
200+
pub piece_size: u64,
201+
pub payload: Vec<u8>,
202+
}
203+
204+
pub fn check_receiver_notification_at(v: &dyn VM, sender_addr: &Address, receiver_addr: &Address, index: u64, expected: &ExpectedNotification) {
205+
let call_params =
206+
NotificationReceiver::getNotificationCall::new((AlloyU256::from(index),)).abi_encode();
207+
let call_result = v
208+
.execute_message(
209+
&sender_addr,
210+
&receiver_addr,
211+
&TokenAmount::zero(),
212+
fil_actor_evm::Method::InvokeContract as u64,
213+
Some(serialize_ok(&ContractParams(call_params.to_vec()))),
214+
)
215+
.unwrap();
216+
assert!(
217+
call_result.code.is_success(),
218+
"Failed to call getNotification: {}",
219+
call_result.message
220+
);
221+
222+
// Decode the return value - it returns a tuple of (uint64, int64, bytes, uint64, bytes)
223+
let return_data: BytesDe = call_result.ret.unwrap().deserialize().unwrap();
224+
225+
// Use the generated abi_decode_returns function
226+
let notification_result =
227+
NotificationReceiver::getNotificationCall::abi_decode_returns(&return_data.0)
228+
.expect("Failed to decode getNotification return value");
229+
230+
let received_sector = notification_result.sector;
231+
let minimum_commitment_epoch = notification_result.minimumCommitmentEpoch;
232+
let data_cid_bytes = notification_result.dataCid;
233+
let received_piece_size = notification_result.pieceSize;
234+
let received_payload = notification_result.payload;
235+
236+
assert_eq!(
237+
received_sector, expected.sector,
238+
"Sector number mismatch: expected {}, got {}",
239+
expected.sector, received_sector
240+
);
241+
242+
assert_eq!(
243+
received_piece_size, expected.piece_size,
244+
"Piece size mismatch: expected {}, got {}",
245+
expected.piece_size, received_piece_size
246+
);
247+
248+
let expected_payload_bytes = expected.payload.to_vec();
249+
assert_eq!(
250+
received_payload.as_ref(),
251+
expected_payload_bytes.as_slice(),
252+
"Payload mismatch: expected 0x{:x?}, got 0x{:x?}",
253+
&expected_payload_bytes,
254+
&received_payload.as_ref()
255+
);
256+
257+
// Check the piece CID data is present
258+
// The contract receives the CID with an extra leading byte from the CBOR encoding,
259+
// so we verify it contains the expected CID data after the first byte
260+
let expected_cid_bytes = expected.piece_cid.to_bytes();
261+
assert!(!data_cid_bytes.is_empty(), "Data CID should not be empty");
262+
// Verify the CID data matches
263+
assert_eq!(data_cid_bytes[0], 0, "Data CID should start with 0x00 for ipld cbor reasons");
264+
assert_eq!(
265+
&data_cid_bytes[1..],
266+
expected_cid_bytes,
267+
"Piece CID data mismatch: expected {:x?}, got {:x?}",
268+
&expected_cid_bytes,
269+
&data_cid_bytes[1..]
270+
);
271+
272+
assert_eq!(
273+
minimum_commitment_epoch, expected.minimum_commitment_epoch,
274+
"Minimum commitment epoch mismatch: expected {}, got {}",
275+
expected.minimum_commitment_epoch, minimum_commitment_epoch
276+
);
257277
}
278+
279+

0 commit comments

Comments
 (0)