Skip to content

Commit

Permalink
AuthorMapping precompile getters (#2143)
Browse files Browse the repository at this point in the history
* nimbusIdOf

* addressOf

* keysOf

* no_std

* fix warnings
  • Loading branch information
nanocryk authored Mar 6, 2023
1 parent 75ec7ea commit c738580
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 12 deletions.
2 changes: 1 addition & 1 deletion precompiles/assets-erc20/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use precompile_utils::{
precompile_set::*,
testing::{AddressInPrefixedSet, MockAccount},
};
use sp_core::{H160, H256};
use sp_core::H256;
use sp_runtime::traits::{BlakeTwo256, ConstU32, IdentityLookup};

pub type AccountId = MockAccount;
Expand Down
21 changes: 21 additions & 0 deletions precompiles/author-mapping/AuthorMappingInterface.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,25 @@ interface AuthorMapping {
///
/// @param keys The new session keys
function setKeys(bytes memory keys) external;

/// @dev Get the nimbus ID of the given addresss
///
/// @custom:selector 3cb194f2
/// @param who The address for which we want to know the nimbus id
/// @return id The nimbus ID, or zero if this address don't have a nimbus ID.
function nimbusIdOf(address who) external returns (bytes32);

/// @dev Get the address of the given nimbus ID
///
/// @custom:selector bb34534c
/// @param nimbusId The nimbus ID for which we want to know the address
/// @return address The address, or zero if this nimbus ID is unknown.
function addressOf(bytes32 nimbusId) external returns (address);

/// @dev Get the keys of the given nimbus ID
///
/// @custom:selector 089b7a68
/// @param nimbusId The nimbus ID for which we want to know the keys
/// @return keys Keys, or empty if this nimbus ID is unknown.
function keysOf(bytes32 nimbusId) external returns (bytes memory keys);
}
2 changes: 1 addition & 1 deletion precompiles/author-mapping/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pallet-author-mapping = { workspace = true, features = [ "std" ] }
precompile-utils = { workspace = true, features = [ "std", "testing" ] }

# Substrate
pallet-balances = { workspace = true }
pallet-balances = { workspace = true, features = [ "std" ] }
pallet-scheduler = { workspace = true }
pallet-timestamp = { workspace = true }
scale-info = { workspace = true, features = [ "derive" ] }
Expand Down
47 changes: 46 additions & 1 deletion precompiles/author-mapping/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ use frame_support::{
dispatch::{Dispatchable, GetDispatchInfo, PostDispatchInfo},
traits::Get,
};
use nimbus_primitives::NimbusId;
use pallet_author_mapping::Call as AuthorMappingCall;
use pallet_evm::AddressMapping;
use parity_scale_codec::Encode;
use precompile_utils::prelude::*;
use sp_core::crypto::UncheckedFrom;
use sp_core::H256;
use sp_core::{H160, H256};
use sp_std::marker::PhantomData;

#[cfg(test)]
Expand Down Expand Up @@ -61,6 +63,7 @@ where
<Runtime::RuntimeCall as Dispatchable>::RuntimeOrigin: From<Option<Runtime::AccountId>>,
Runtime::RuntimeCall: From<AuthorMappingCall<Runtime>>,
Runtime::Hash: From<H256>,
Runtime::AccountId: Into<H160>,
{
// The dispatchable wrappers are next. They dispatch a Substrate inner Call.
#[precompile::public("addAssociation(bytes32)")]
Expand Down Expand Up @@ -154,4 +157,46 @@ where

Ok(())
}

#[precompile::public("nimbusIdOf(address)")]
#[precompile::view]
fn nimbus_id_of(handle: &mut impl PrecompileHandle, address: Address) -> EvmResult<H256> {
handle.record_cost(RuntimeHelper::<Runtime>::db_read_gas_cost())?;
let account = Runtime::AddressMapping::into_account_id(address.0);

let nimbus_id = pallet_author_mapping::Pallet::<Runtime>::nimbus_id_of(&account)
.map(|x| H256::from(sp_core::sr25519::Public::from(x).0))
.unwrap_or(H256::zero());
Ok(nimbus_id)
}

#[precompile::public("addressOf(bytes32)")]
#[precompile::view]
fn address_of(handle: &mut impl PrecompileHandle, nimbus_id: H256) -> EvmResult<Address> {
handle.record_cost(RuntimeHelper::<Runtime>::db_read_gas_cost())?;

let nimbus_id = sp_core::sr25519::Public::unchecked_from(nimbus_id);
let nimbus_id: NimbusId = nimbus_id.into();

let address: H160 = pallet_author_mapping::Pallet::<Runtime>::account_id_of(&nimbus_id)
.map(|x| x.into())
.unwrap_or(H160::zero());

Ok(Address(address))
}

#[precompile::public("keysOf(bytes32)")]
#[precompile::view]
fn keys_of(handle: &mut impl PrecompileHandle, nimbus_id: H256) -> EvmResult<UnboundedBytes> {
handle.record_cost(RuntimeHelper::<Runtime>::db_read_gas_cost())?;

let nimbus_id = sp_core::sr25519::Public::unchecked_from(nimbus_id);
let nimbus_id: NimbusId = nimbus_id.into();

let keys = pallet_author_mapping::Pallet::<Runtime>::keys_of(&nimbus_id)
.map(|x| x.encode())
.unwrap_or_default();

Ok(keys.into())
}
}
4 changes: 3 additions & 1 deletion precompiles/author-mapping/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use frame_support::{
};
use frame_system::EnsureRoot;
use pallet_evm::{EnsureAddressNever, EnsureAddressRoot, SubstrateBlockHashMapping};
use precompile_utils::{precompile_set::*, testing::MockAccount};
use precompile_utils::{mock_account, precompile_set::*, testing::MockAccount};
use sp_core::{H256, U256};
use sp_io;
use sp_runtime::traits::{BlakeTwo256, IdentityLookup};
Expand Down Expand Up @@ -101,6 +101,8 @@ pub type Precompiles<R> =

pub type PCall = AuthorMappingPrecompileCall<Runtime>;

mock_account!(AuthorMappingAccount, |_| MockAccount::from_u64(1));

parameter_types! {
pub BlockGasLimit: U256 = U256::max_value();
pub PrecompilesValue: Precompiles<Runtime> = Precompiles::new();
Expand Down
125 changes: 123 additions & 2 deletions precompiles/author-mapping/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
// along with Moonbeam. If not, see <http://www.gnu.org/licenses/>.

use crate::mock::{
events, ExtBuilder, PCall, Precompiles, PrecompilesValue, Runtime, RuntimeCall, RuntimeOrigin,
events, AuthorMappingAccount, ExtBuilder, PCall, Precompiles, PrecompilesValue, Runtime,
RuntimeCall, RuntimeOrigin,
};
use frame_support::{assert_ok, dispatch::Dispatchable};
use nimbus_primitives::NimbusId;
Expand All @@ -24,7 +25,7 @@ use pallet_balances::Event as BalancesEvent;
use pallet_evm::{Call as EvmCall, Event as EvmEvent};
use precompile_utils::{prelude::*, testing::*};
use sp_core::crypto::UncheckedFrom;
use sp_core::{H256, U256};
use sp_core::{H160, H256, U256};

fn precompiles() -> Precompiles<Runtime> {
PrecompilesValue::get()
Expand Down Expand Up @@ -70,6 +71,9 @@ fn selectors() {
assert!(PCall::clear_association_selectors().contains(&0x448b54d6));
assert!(PCall::remove_keys_selectors().contains(&0xa36fee17));
assert!(PCall::set_keys_selectors().contains(&0xf1ec919c));
assert!(PCall::nimbus_id_of_selectors().contains(&0x3cb194f2));
assert!(PCall::address_of_selectors().contains(&0xbb34534c));
assert!(PCall::keys_of_selectors().contains(&0x089b7a68));
}

#[test]
Expand All @@ -82,6 +86,9 @@ fn modifiers() {
tester.test_default_modifier(PCall::clear_association_selectors());
tester.test_default_modifier(PCall::remove_keys_selectors());
tester.test_default_modifier(PCall::set_keys_selectors());
tester.test_view_modifier(PCall::nimbus_id_of_selectors());
tester.test_view_modifier(PCall::address_of_selectors());
tester.test_view_modifier(PCall::keys_of_selectors());
});
}

Expand Down Expand Up @@ -359,6 +366,120 @@ fn set_keys_works() {
})
}

mod nimbus_id_of {
use super::*;

fn call(address: impl Into<H160>, expected: H256) {
let address = address.into();
ExtBuilder::default()
.with_balances(vec![(Alice.into(), 1000)])
.build()
.execute_with(|| {
let first_nimbus_id: NimbusId =
sp_core::sr25519::Public::unchecked_from([1u8; 32]).into();
let first_vrf_key: NimbusId =
sp_core::sr25519::Public::unchecked_from([3u8; 32]).into();

let call = RuntimeCall::AuthorMapping(AuthorMappingCall::set_keys {
keys: keys_wrapper::<Runtime>(first_nimbus_id.clone(), first_vrf_key.clone()),
});
assert_ok!(call.dispatch(RuntimeOrigin::signed(Alice.into())));

precompiles()
.prepare_test(
Bob,
AuthorMappingAccount,
PCall::nimbus_id_of {
address: Address(address),
},
)
.execute_returns_encoded(expected);
})
}

#[test]
fn known_address() {
call(Alice, H256::from([1u8; 32]));
}

#[test]
fn unknown_address() {
call(Bob, H256::from([0u8; 32]));
}
}

mod address_of {
use super::*;

fn call(nimbus_id: H256, expected: impl Into<H160>) {
let expected = expected.into();
ExtBuilder::default()
.with_balances(vec![(Alice.into(), 1000)])
.build()
.execute_with(|| {
let first_nimbus_id: NimbusId =
sp_core::sr25519::Public::unchecked_from([1u8; 32]).into();
let first_vrf_key: NimbusId =
sp_core::sr25519::Public::unchecked_from([3u8; 32]).into();

let call = RuntimeCall::AuthorMapping(AuthorMappingCall::set_keys {
keys: keys_wrapper::<Runtime>(first_nimbus_id.clone(), first_vrf_key.clone()),
});
assert_ok!(call.dispatch(RuntimeOrigin::signed(Alice.into())));

precompiles()
.prepare_test(Bob, AuthorMappingAccount, PCall::address_of { nimbus_id })
.execute_returns_encoded(Address(expected));
})
}

#[test]
fn known_id() {
call(H256::from([1u8; 32]), Alice);
}

#[test]
fn unknown_id() {
call(H256::from([42u8; 32]), Address(H160::zero()));
}
}

mod keys_of {
use super::*;

fn call(nimbus_id: H256, expected: Vec<u8>) {
let expected: UnboundedBytes = expected.into();
ExtBuilder::default()
.with_balances(vec![(Alice.into(), 1000)])
.build()
.execute_with(|| {
let first_nimbus_id: NimbusId =
sp_core::sr25519::Public::unchecked_from([1u8; 32]).into();
let first_vrf_key: NimbusId =
sp_core::sr25519::Public::unchecked_from([3u8; 32]).into();

let call = RuntimeCall::AuthorMapping(AuthorMappingCall::set_keys {
keys: keys_wrapper::<Runtime>(first_nimbus_id.clone(), first_vrf_key.clone()),
});
assert_ok!(call.dispatch(RuntimeOrigin::signed(Alice.into())));

precompiles()
.prepare_test(Bob, AuthorMappingAccount, PCall::keys_of { nimbus_id })
.execute_returns_encoded(expected);
})
}

#[test]
fn known_id() {
call(H256::from([1u8; 32]), vec![3u8; 32]);
}

#[test]
fn unknown_id() {
call(H256::from([42u8; 32]), Vec::new());
}
}

#[test]
fn test_solidity_interface_has_all_function_selectors_documented_and_implemented() {
for file in ["AuthorMappingInterface.sol"] {
Expand Down
2 changes: 1 addition & 1 deletion precompiles/batch/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use frame_support::traits::Everything;
use frame_support::{construct_runtime, parameter_types, weights::Weight};
use pallet_evm::{EnsureAddressNever, EnsureAddressRoot};
use precompile_utils::{mock_account, precompile_set::*, testing::MockAccount};
use sp_core::{H160, H256};
use sp_core::H256;
use sp_runtime::{
traits::{BlakeTwo256, IdentityLookup},
Perbill,
Expand Down
1 change: 0 additions & 1 deletion precompiles/call-permit/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use frame_support::traits::Everything;
use frame_support::{construct_runtime, pallet_prelude::*, parameter_types};
use pallet_evm::{EnsureAddressNever, EnsureAddressRoot};
use precompile_utils::{mock_account, precompile_set::*, testing::MockAccount};
use sp_core::H160;
use sp_core::H256;
use sp_runtime::{
traits::{BlakeTwo256, IdentityLookup},
Expand Down
8 changes: 4 additions & 4 deletions precompiles/utils/src/testing/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,14 @@ macro_rules! mock_account {
}
}

impl From<$name> for H160 {
fn from(value: $name) -> H160 {
impl From<$name> for sp_core::H160 {
fn from(value: $name) -> sp_core::H160 {
MockAccount::from(value).into()
}
}

impl From<$name> for H256 {
fn from(value: $name) -> H256 {
impl From<$name> for sp_core::H256 {
fn from(value: $name) -> sp_core::H256 {
MockAccount::from(value).into()
}
}
Expand Down

0 comments on commit c738580

Please sign in to comment.