Skip to content

Commit 07e9fb8

Browse files
committed
test executed transaction gets accepted
1 parent feaa8f6 commit 07e9fb8

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

crates/sui-core/src/consensus_validator.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,18 +312,21 @@ mod tests {
312312
use sui_protocol_config::{Chain, ProtocolConfig, ProtocolVersion};
313313
use sui_types::crypto::deterministic_random_account_key;
314314
use sui_types::error::{SuiErrorKind, UserInputError};
315+
use sui_types::executable_transaction::VerifiedExecutableTransaction;
315316
use sui_types::messages_checkpoint::{
316317
CheckpointContents, CheckpointSignatureMessage, CheckpointSummary, SignedCheckpointSummary,
317318
};
318319
use sui_types::messages_consensus::ConsensusPosition;
319320
use sui_types::{
320321
base_types::{ExecutionDigests, ObjectID},
321322
crypto::Ed25519SuiSignature,
323+
effects::TransactionEffectsAPI as _,
322324
messages_consensus::ConsensusTransaction,
323325
object::Object,
324326
signature::GenericSignature,
325327
};
326328

329+
use crate::authority::ExecutionEnv;
327330
use crate::{
328331
authority::test_authority_builder::TestAuthorityBuilder,
329332
checkpoints::CheckpointServiceNoop,
@@ -624,4 +627,68 @@ mod tests {
624627
let res = validator.verify_batch(&[&bytes]);
625628
assert!(res.is_ok(), "{res:?}");
626629
}
630+
631+
#[sim_test]
632+
async fn accept_already_executed_transaction() {
633+
let (sender, keypair) = deterministic_random_account_key();
634+
635+
let gas_object = Object::with_id_owner_for_testing(ObjectID::random(), sender);
636+
let owned_object = Object::with_id_owner_for_testing(ObjectID::random(), sender);
637+
638+
let network_config =
639+
sui_swarm_config::network_config_builder::ConfigBuilder::new_with_temp_dir()
640+
.committee_size(NonZeroUsize::new(1).unwrap())
641+
.with_objects(vec![gas_object.clone(), owned_object.clone()])
642+
.build();
643+
644+
let state = TestAuthorityBuilder::new()
645+
.with_network_config(&network_config, 0)
646+
.build()
647+
.await;
648+
649+
let epoch_store = state.load_epoch_store_one_call_per_task();
650+
651+
// Create a transaction and execute it.
652+
let transaction = test_user_transaction(
653+
&state,
654+
sender,
655+
&keypair,
656+
gas_object.clone(),
657+
vec![owned_object.clone()],
658+
)
659+
.await;
660+
let tx_digest = *transaction.digest();
661+
let cert = VerifiedExecutableTransaction::new_from_quorum_execution(transaction.clone(), 0);
662+
let (executed_effects, _) = state
663+
.try_execute_immediately(&cert, ExecutionEnv::new(), &state.epoch_store_for_testing())
664+
.await
665+
.unwrap();
666+
667+
// Verify the transaction is executed.
668+
let read_effects = state
669+
.get_transaction_cache_reader()
670+
.get_executed_effects(&tx_digest)
671+
.expect("Transaction should be executed");
672+
assert_eq!(read_effects, executed_effects);
673+
assert_eq!(read_effects.executed_epoch(), epoch_store.epoch());
674+
675+
// Now try to vote on the already executed transaction
676+
let serialized_tx = bcs::to_bytes(&ConsensusTransaction::new_user_transaction_message(
677+
&state.name,
678+
transaction.into_inner().clone(),
679+
))
680+
.unwrap();
681+
let validator = SuiTxValidator::new(
682+
state.clone(),
683+
Arc::new(NoopConsensusOverloadChecker {}),
684+
Arc::new(CheckpointServiceNoop {}),
685+
SuiTxValidatorMetrics::new(&Default::default()),
686+
);
687+
let rejected_transactions = validator
688+
.verify_and_vote_batch(&BlockRef::MAX, &[&serialized_tx])
689+
.expect("Verify and vote should succeed");
690+
691+
// The executed transaction should NOT be rejected.
692+
assert!(rejected_transactions.is_empty());
693+
}
627694
}

0 commit comments

Comments
 (0)