#![allow(clippy::boxed_local)]
use std::sync::Arc;
use tracing::debug;
use casper_types::{Chainspec, Timestamp, Transaction};
pub(crate) use crate::components::transaction_acceptor::{Error, Event};
use crate::{
components::{transaction_acceptor::EventMetadata, Component},
effect::{
announcements::TransactionAcceptorAnnouncement, requests::StorageRequest, EffectBuilder,
EffectExt, Effects, Responder,
},
types::MetaTransaction,
utils::Source,
NodeRng,
};
const COMPONENT_NAME: &str = "fake_transaction_acceptor";
pub(crate) trait ReactorEventT:
From<Event> + From<TransactionAcceptorAnnouncement> + From<StorageRequest> + Send
{
}
impl<REv> ReactorEventT for REv where
REv: From<Event> + From<TransactionAcceptorAnnouncement> + From<StorageRequest> + Send
{
}
#[derive(Debug)]
pub struct FakeTransactionAcceptor {
is_active: bool,
chainspec: Chainspec,
}
impl FakeTransactionAcceptor {
pub(crate) fn new() -> Self {
FakeTransactionAcceptor {
is_active: true,
chainspec: Chainspec::default(),
}
}
pub(crate) fn set_active(&mut self, new_setting: bool) {
self.is_active = new_setting;
}
fn accept<REv: ReactorEventT>(
&mut self,
effect_builder: EffectBuilder<REv>,
transaction: Transaction,
source: Source,
maybe_responder: Option<Responder<Result<(), Error>>>,
) -> Effects<Event> {
let meta_transaction = MetaTransaction::from_transaction(
&transaction,
self.chainspec.core_config.pricing_handling,
&self.chainspec.transaction_config,
)
.unwrap();
let event_metadata = Box::new(EventMetadata::new(
transaction.clone(),
meta_transaction,
source,
maybe_responder,
Timestamp::now(),
));
effect_builder
.put_transaction_to_storage(transaction)
.event(move |is_new| Event::PutToStorageResult {
event_metadata,
is_new,
})
}
fn handle_put_to_storage<REv: ReactorEventT>(
&self,
effect_builder: EffectBuilder<REv>,
event_metadata: Box<EventMetadata>,
is_new: bool,
) -> Effects<Event> {
let EventMetadata {
meta_transaction: _,
transaction,
source,
maybe_responder,
verification_start_timestamp: _,
} = *event_metadata;
let mut effects = Effects::new();
if is_new {
effects.extend(
effect_builder
.announce_new_transaction_accepted(Arc::new(transaction), source)
.ignore(),
);
}
if let Some(responder) = maybe_responder {
effects.extend(responder.respond(Ok(())).ignore());
}
effects
}
}
impl<REv: ReactorEventT> Component<REv> for FakeTransactionAcceptor {
type Event = Event;
fn handle_event(
&mut self,
effect_builder: EffectBuilder<REv>,
_rng: &mut NodeRng,
event: Self::Event,
) -> Effects<Self::Event> {
if !self.is_active {
debug!(
?event,
"FakeTransactionAcceptor: not active - ignoring event"
);
return Effects::new();
}
debug!(?event, "FakeTransactionAcceptor: handling event");
match event {
Event::Accept {
transaction,
source,
maybe_responder,
} => self.accept(effect_builder, transaction, source, maybe_responder),
Event::PutToStorageResult {
event_metadata,
is_new,
..
} => self.handle_put_to_storage(effect_builder, event_metadata, is_new),
_ => unimplemented!("unexpected {:?}", event),
}
}
fn name(&self) -> &str {
COMPONENT_NAME
}
}