pallet_evm_precompile_author_mapping/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
20
21use fp_evm::PrecompileHandle;
22use frame_support::{
23 dispatch::{GetDispatchInfo, PostDispatchInfo},
24 traits::Get,
25};
26use nimbus_primitives::NimbusId;
27use pallet_author_mapping::Call as AuthorMappingCall;
28use pallet_evm::AddressMapping;
29use parity_scale_codec::Encode;
30use precompile_utils::prelude::*;
31use sp_core::crypto::UncheckedFrom;
32use sp_core::{H160, H256};
33use sp_runtime::traits::Dispatchable;
34use sp_std::marker::PhantomData;
35
36#[cfg(test)]
37mod mock;
38#[cfg(test)]
39mod tests;
40
41pub struct AuthorMappingPrecompile<Runtime>(PhantomData<Runtime>);
43
44pub struct GetKeysSize<R>(PhantomData<R>);
48
49impl<R: pallet_author_mapping::Config> Get<u32> for GetKeysSize<R> {
50 fn get() -> u32 {
51 pallet_author_mapping::pallet::keys_size::<R>()
52 .try_into()
53 .expect("keys size to fit in u32")
54 }
55}
56
57#[precompile_utils::precompile]
58#[precompile::test_concrete_types(mock::Runtime)]
59impl<Runtime> AuthorMappingPrecompile<Runtime>
60where
61 Runtime: pallet_author_mapping::Config + pallet_evm::Config + frame_system::Config,
62 Runtime::RuntimeCall: Dispatchable<PostInfo = PostDispatchInfo> + GetDispatchInfo,
63 Runtime::RuntimeCall: From<AuthorMappingCall<Runtime>>,
64 Runtime::Hash: From<H256>,
65 Runtime::AccountId: Into<H160>,
66 <Runtime as pallet_evm::Config>::AddressMapping: AddressMapping<Runtime::AccountId>,
67{
68 #[precompile::public("addAssociation(bytes32)")]
70 #[precompile::public("add_association(bytes32)")]
71 fn add_association(handle: &mut impl PrecompileHandle, nimbus_id: H256) -> EvmResult {
72 let nimbus_id = sp_core::sr25519::Public::unchecked_from(nimbus_id).into();
73
74 log::trace!(
75 target: "author-mapping-precompile",
76 "Associating author id {:?}", nimbus_id
77 );
78
79 let origin = Runtime::AddressMapping::into_account_id(handle.context().caller);
80 let call = AuthorMappingCall::<Runtime>::add_association { nimbus_id };
81
82 RuntimeHelper::<Runtime>::try_dispatch(
83 handle,
84 frame_system::RawOrigin::Signed(origin).into(),
85 call,
86 0,
87 )?;
88
89 Ok(())
90 }
91
92 #[precompile::public("updateAssociation(bytes32,bytes32)")]
93 #[precompile::public("update_association(bytes32,bytes32)")]
94 fn update_association(
95 handle: &mut impl PrecompileHandle,
96 old_nimbus_id: H256,
97 new_nimbus_id: H256,
98 ) -> EvmResult {
99 let old_nimbus_id = sp_core::sr25519::Public::unchecked_from(old_nimbus_id).into();
100 let new_nimbus_id = sp_core::sr25519::Public::unchecked_from(new_nimbus_id).into();
101
102 log::trace!(
103 target: "author-mapping-precompile",
104 "Updating author id {:?} for {:?}", old_nimbus_id, new_nimbus_id
105 );
106
107 let origin = Runtime::AddressMapping::into_account_id(handle.context().caller);
108 let call = AuthorMappingCall::<Runtime>::update_association {
109 old_nimbus_id,
110 new_nimbus_id,
111 };
112
113 RuntimeHelper::<Runtime>::try_dispatch(
114 handle,
115 frame_system::RawOrigin::Signed(origin).into(),
116 call,
117 0,
118 )?;
119
120 Ok(())
121 }
122
123 #[precompile::public("clearAssociation(bytes32)")]
124 #[precompile::public("clear_association(bytes32)")]
125 fn clear_association(handle: &mut impl PrecompileHandle, nimbus_id: H256) -> EvmResult {
126 let nimbus_id = sp_core::sr25519::Public::unchecked_from(nimbus_id).into();
127
128 log::trace!(
129 target: "author-mapping-precompile",
130 "Clearing author id {:?}", nimbus_id
131 );
132
133 let origin = Runtime::AddressMapping::into_account_id(handle.context().caller);
134 let call = AuthorMappingCall::<Runtime>::clear_association { nimbus_id };
135
136 RuntimeHelper::<Runtime>::try_dispatch(
137 handle,
138 frame_system::RawOrigin::Signed(origin).into(),
139 call,
140 0,
141 )?;
142
143 Ok(())
144 }
145
146 #[precompile::public("removeKeys()")]
147 #[precompile::public("remove_keys()")]
148 fn remove_keys(handle: &mut impl PrecompileHandle) -> EvmResult {
149 log::trace!(
150 target: "author-mapping-precompile",
151 "Removing keys"
152 );
153
154 let origin = Runtime::AddressMapping::into_account_id(handle.context().caller);
155 let call = AuthorMappingCall::<Runtime>::remove_keys {};
156
157 RuntimeHelper::<Runtime>::try_dispatch(
158 handle,
159 frame_system::RawOrigin::Signed(origin).into(),
160 call,
161 0,
162 )?;
163
164 Ok(())
165 }
166
167 #[precompile::public("setKeys(bytes)")]
168 #[precompile::public("set_keys(bytes)")]
169 fn set_keys(
170 handle: &mut impl PrecompileHandle,
171 keys: BoundedBytes<GetKeysSize<Runtime>>,
172 ) -> EvmResult {
173 let origin = Runtime::AddressMapping::into_account_id(handle.context().caller);
174 let call = AuthorMappingCall::<Runtime>::set_keys { keys: keys.into() };
175
176 RuntimeHelper::<Runtime>::try_dispatch(
177 handle,
178 frame_system::RawOrigin::Signed(origin).into(),
179 call,
180 0,
181 )?;
182
183 Ok(())
184 }
185
186 #[precompile::public("nimbusIdOf(address)")]
187 #[precompile::view]
188 fn nimbus_id_of(handle: &mut impl PrecompileHandle, address: Address) -> EvmResult<H256> {
189 handle.record_db_read::<Runtime>(68)?;
192 let account = Runtime::AddressMapping::into_account_id(address.0);
193
194 let nimbus_id = pallet_author_mapping::Pallet::<Runtime>::nimbus_id_of(&account)
195 .map(|x| H256::from(sp_core::sr25519::Public::from(x).0))
196 .unwrap_or(H256::zero());
197 Ok(nimbus_id)
198 }
199
200 #[precompile::public("addressOf(bytes32)")]
201 #[precompile::view]
202 fn address_of(handle: &mut impl PrecompileHandle, nimbus_id: H256) -> EvmResult<Address> {
203 handle.record_db_read::<Runtime>(116)?;
206
207 let nimbus_id = sp_core::sr25519::Public::unchecked_from(nimbus_id);
208 let nimbus_id: NimbusId = nimbus_id.into();
209
210 let address: H160 = pallet_author_mapping::Pallet::<Runtime>::account_id_of(&nimbus_id)
211 .map(|x| x.into())
212 .unwrap_or(H160::zero());
213
214 Ok(Address(address))
215 }
216
217 #[precompile::public("keysOf(bytes32)")]
218 #[precompile::view]
219 fn keys_of(handle: &mut impl PrecompileHandle, nimbus_id: H256) -> EvmResult<UnboundedBytes> {
220 handle.record_db_read::<Runtime>(116)?;
223
224 let nimbus_id = sp_core::sr25519::Public::unchecked_from(nimbus_id);
225 let nimbus_id: NimbusId = nimbus_id.into();
226
227 let keys = pallet_author_mapping::Pallet::<Runtime>::keys_of(&nimbus_id)
228 .map(|x| x.encode())
229 .unwrap_or_default();
230
231 Ok(keys.into())
232 }
233}