sp_runtime/traits/transaction_extension/
dispatch_transaction.rs1use crate::{
21 generic::ExtensionVersion,
22 traits::AsTransactionAuthorizedOrigin,
23 transaction_validity::{InvalidTransaction, TransactionSource},
24};
25
26use super::*;
27
28pub trait DispatchTransaction<Call: Dispatchable> {
32 type Origin;
34 type Info;
36 type Result;
38 type Val;
40 type Pre;
42 fn validate_only(
47 &self,
48 origin: Self::Origin,
49 call: &Call,
50 info: &Self::Info,
51 len: usize,
52 source: TransactionSource,
53 extension_version: ExtensionVersion,
54 ) -> Result<(ValidTransaction, Self::Val, Self::Origin), TransactionValidityError>;
55 fn validate_and_prepare(
57 self,
58 origin: Self::Origin,
59 call: &Call,
60 info: &Self::Info,
61 len: usize,
62 extension_version: ExtensionVersion,
63 ) -> Result<(Self::Pre, Self::Origin), TransactionValidityError>;
64 fn dispatch_transaction(
66 self,
67 origin: Self::Origin,
68 call: Call,
69 info: &Self::Info,
70 len: usize,
71 extension_version: ExtensionVersion,
72 ) -> Self::Result;
73 fn test_run(
77 self,
78 origin: Self::Origin,
79 call: &Call,
80 info: &Self::Info,
81 len: usize,
82 extension_version: ExtensionVersion,
83 substitute: impl FnOnce(
84 Self::Origin,
85 ) -> crate::DispatchResultWithInfo<<Call as Dispatchable>::PostInfo>,
86 ) -> Self::Result;
87}
88
89impl<T: TransactionExtension<Call>, Call: Dispatchable + Encode> DispatchTransaction<Call> for T
90where
91 <Call as Dispatchable>::RuntimeOrigin: AsTransactionAuthorizedOrigin,
92{
93 type Origin = <Call as Dispatchable>::RuntimeOrigin;
94 type Info = DispatchInfoOf<Call>;
95 type Result = crate::ApplyExtrinsicResultWithInfo<PostDispatchInfoOf<Call>>;
96 type Val = T::Val;
97 type Pre = T::Pre;
98
99 fn validate_only(
100 &self,
101 origin: Self::Origin,
102 call: &Call,
103 info: &DispatchInfoOf<Call>,
104 len: usize,
105 source: TransactionSource,
106 extension_version: ExtensionVersion,
107 ) -> Result<(ValidTransaction, T::Val, Self::Origin), TransactionValidityError> {
108 match self.validate(
109 origin,
110 call,
111 info,
112 len,
113 self.implicit()?,
114 &TxBaseImplication((extension_version, call)),
115 source,
116 ) {
117 Ok((_, _, origin)) if !origin.is_transaction_authorized() =>
119 Err(InvalidTransaction::UnknownOrigin.into()),
120 res => res,
121 }
122 }
123 fn validate_and_prepare(
124 self,
125 origin: Self::Origin,
126 call: &Call,
127 info: &DispatchInfoOf<Call>,
128 len: usize,
129 extension_version: ExtensionVersion,
130 ) -> Result<(T::Pre, Self::Origin), TransactionValidityError> {
131 let (_, val, origin) = self.validate_only(
132 origin,
133 call,
134 info,
135 len,
136 TransactionSource::InBlock,
137 extension_version,
138 )?;
139 let pre = self.prepare(val, &origin, &call, info, len)?;
140 Ok((pre, origin))
141 }
142 fn dispatch_transaction(
143 self,
144 origin: <Call as Dispatchable>::RuntimeOrigin,
145 call: Call,
146 info: &DispatchInfoOf<Call>,
147 len: usize,
148 extension_version: ExtensionVersion,
149 ) -> Self::Result {
150 let (pre, origin) =
151 self.validate_and_prepare(origin, &call, info, len, extension_version)?;
152 let mut res = call.dispatch(origin);
153 let pd_res = res.map(|_| ()).map_err(|e| e.error);
154 let post_info = match &mut res {
155 Ok(info) => info,
156 Err(err) => &mut err.post_info,
157 };
158 post_info.set_extension_weight(info);
159 T::post_dispatch(pre, info, post_info, len, &pd_res)?;
160 Ok(res)
161 }
162 fn test_run(
163 self,
164 origin: Self::Origin,
165 call: &Call,
166 info: &Self::Info,
167 len: usize,
168 extension_version: ExtensionVersion,
169 substitute: impl FnOnce(
170 Self::Origin,
171 ) -> crate::DispatchResultWithInfo<<Call as Dispatchable>::PostInfo>,
172 ) -> Self::Result {
173 let (pre, origin) =
174 self.validate_and_prepare(origin, &call, info, len, extension_version)?;
175 let mut res = substitute(origin);
176 let pd_res = res.map(|_| ()).map_err(|e| e.error);
177 let post_info = match &mut res {
178 Ok(info) => info,
179 Err(err) => &mut err.post_info,
180 };
181 post_info.set_extension_weight(info);
182 T::post_dispatch(pre, info, post_info, len, &pd_res)?;
183 Ok(res)
184 }
185}