From 5f5a85bd0aced3d479709cc81a632b3634ffe530 Mon Sep 17 00:00:00 2001 From: Xun Li Date: Wed, 27 Apr 2022 17:56:23 -0700 Subject: [PATCH] Add test (and fix) to ensure idempotent response when confirm after tx handle (#1631) --- sui_core/src/authority.rs | 4 ++- sui_core/src/unit_tests/authority_tests.rs | 38 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/sui_core/src/authority.rs b/sui_core/src/authority.rs index 32e1a996483c0..e42bcf270e014 100644 --- a/sui_core/src/authority.rs +++ b/sui_core/src/authority.rs @@ -190,7 +190,9 @@ impl AuthorityState { let transaction_digest = transaction.digest(); // Ensure an idempotent answer. - if self._database.transaction_exists(&transaction_digest)? { + if self._database.transaction_exists(&transaction_digest)? + || self._database.effects_exists(&transaction_digest)? + { let transaction_info = self.make_transaction_info(&transaction_digest).await?; return Ok(transaction_info); } diff --git a/sui_core/src/unit_tests/authority_tests.rs b/sui_core/src/unit_tests/authority_tests.rs index de753ec3167f8..e23d4a8e5fbec 100644 --- a/sui_core/src/unit_tests/authority_tests.rs +++ b/sui_core/src/unit_tests/authority_tests.rs @@ -1173,6 +1173,44 @@ async fn test_authority_persist() { assert_eq!(obj2.owner, recipient); } +#[tokio::test] +async fn test_idempotent_reversed_confirmation() { + // In this test we exercise the case where an authority first receive the certificate, + // and then receive the raw transaction latter. We should still ensure idempotent + // response and be able to get back the same result. + let recipient = dbg_addr(2); + let (sender, sender_key) = get_key_pair(); + + let object = Object::with_owner_for_testing(sender); + let object_ref = object.compute_object_reference(); + let gas_object = Object::with_owner_for_testing(sender); + let gas_object_ref = gas_object.compute_object_reference(); + let authority_state = init_state_with_objects([object, gas_object]).await; + + let certified_transfer_transaction = init_certified_transfer_transaction( + sender, + &sender_key, + recipient, + object_ref, + gas_object_ref, + &authority_state, + ); + let result1 = authority_state + .handle_confirmation_transaction(ConfirmationTransaction::new( + certified_transfer_transaction.clone(), + )) + .await; + assert!(result1.is_ok()); + let result2 = authority_state + .handle_transaction(certified_transfer_transaction.transaction) + .await; + assert!(result2.is_ok()); + assert_eq!( + result1.unwrap().signed_effects.unwrap().effects, + result2.unwrap().signed_effects.unwrap().effects + ); +} + // helpers #[cfg(test)]