Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update pallet-relayer to use Contraints V2 #433

Merged
merged 17 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified crypto/server/entropy_metadata.scale
Binary file not shown.
8 changes: 6 additions & 2 deletions crypto/server/src/helpers/substrate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,12 @@ pub async fn make_register(
assert!(is_registering_1.is_none());

// register the user
let registering_tx =
entropy::tx().relayer().register(constraint_account.clone(), Static(key_visibility), None);
let empty_program = vec![];
let registering_tx = entropy::tx().relayer().register(
constraint_account.clone(),
Static(key_visibility),
empty_program,
);

api.tx()
.sign_and_submit_then_watch_default(&registering_tx, &sig_req_account)
Expand Down
3 changes: 2 additions & 1 deletion crypto/server/src/user/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,8 +663,9 @@ pub async fn put_register_request_on_chain(
let sig_req_account =
PairSigner::<EntropyConfig, sp_core::sr25519::Pair>::new(sig_req_keyring.pair());

let empty_program = vec![];
let registering_tx =
entropy::tx().relayer().register(constraint_account, Static(key_visibility), None);
entropy::tx().relayer().register(constraint_account, Static(key_visibility), empty_program);

api.tx()
.sign_and_submit_then_watch_default(&registering_tx, &sig_req_account)
Expand Down
20 changes: 20 additions & 0 deletions pallets/constraints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,26 @@ pub mod pallet {
}

impl<T: Config> Pallet<T> {
/// Write a program for a given signature-request account directly into storage.
///
/// # Note
///
/// This does not perform any checks against the submitter of the request and whether or
/// not they are allowed to update a program for the given account.
pub fn set_program_unchecked(
sig_req_account: &T::AccountId,
program: Vec<u8>,
) -> Result<(), Error<T>> {
ensure!(
program.len() as u32 <= T::MaxV2BytecodeLength::get(),
Error::<T>::V2ConstraintLengthExceeded
);

V2Bytecode::<T>::insert(sig_req_account, program);

Ok(())
}

/// Sets the constraints for a given signature-request account without validating the
/// constraints (eg ACL length checks, etc.)
pub fn set_constraints_unchecked(
Expand Down
4 changes: 2 additions & 2 deletions pallets/propagation/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ fn knows_how_to_mock_several_http_calls() {
Propagation::post_dkg(1).unwrap();

System::set_block_number(3);
assert_ok!(Relayer::register(RuntimeOrigin::signed(1), 2, KeyVisibility::Public, None,));
assert_ok!(Relayer::register(RuntimeOrigin::signed(2), 3, KeyVisibility::Public, None,));
assert_ok!(Relayer::register(RuntimeOrigin::signed(1), 2, KeyVisibility::Public, vec![],));
assert_ok!(Relayer::register(RuntimeOrigin::signed(2), 3, KeyVisibility::Public, vec![],));
// full send
Propagation::post_dkg(4).unwrap();
// test pruning
Expand Down
20 changes: 10 additions & 10 deletions pallets/relayer/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,14 @@ pub fn add_non_syncing_validators<T: Config>(

benchmarks! {
register {
// number of addresses in the ACL
let a in 0 .. <T as pallet_constraints::Config>::MaxAclLength::get();
let b in 0 .. <T as pallet_constraints::Config>::MaxAclLength::get();
let constraints = generate_benchmarking_constraints(a, b);
// Since we're usually using `steps >> 1` when running benches this shouldn't take too long to
// run
let p in 0..<T as pallet_constraints::Config>::MaxV2BytecodeLength::get();
let program = vec![0u8; p as usize];

let constraint_account: T::AccountId = whitelisted_caller();
let sig_req_account: T::AccountId = whitelisted_caller();

}: _(RawOrigin::Signed(sig_req_account.clone()), constraint_account, KeyVisibility::Public, Some(constraints))
}: _(RawOrigin::Signed(sig_req_account.clone()), constraint_account, KeyVisibility::Public, program)
verify {
assert_last_event::<T>(Event::SignalRegister(sig_req_account.clone()).into());
assert!(Registering::<T>::contains_key(sig_req_account));
Expand All @@ -77,11 +76,12 @@ benchmarks! {
let validators = add_non_syncing_validators::<T>(sig_party_size, 0, i as u8);
<ThresholdToStash<T>>::insert(&threshold_account, &validators[i]);
}

<Registering<T>>::insert(&sig_req_account, RegisteringDetails::<T> {
is_registering: true,
constraint_account: sig_req_account.clone(),
program_modification_account: sig_req_account.clone(),
confirmations: vec![],
constraints: None,
program: vec![],
key_visibility: KeyVisibility::Public,
});
}: confirm_register(RawOrigin::Signed(threshold_account), sig_req_account.clone(), 0, BoundedVec::default())
Expand All @@ -103,9 +103,9 @@ confirm_register_registered {
let confirmation: Vec<u8> = (1u8..=adjusted_sig_size.try_into().unwrap()).collect();
<Registering<T>>::insert(&sig_req_account, RegisteringDetails::<T> {
is_registering: true,
constraint_account: sig_req_account.clone(),
program_modification_account: sig_req_account.clone(),
confirmations: confirmation,
constraints: None,
program: vec![],
key_visibility: KeyVisibility::Public,
});
}: confirm_register(RawOrigin::Signed(threshold_account), sig_req_account.clone(), 0, BoundedVec::default())
Expand Down
88 changes: 50 additions & 38 deletions pallets/relayer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
//! # Relayer Pallet
//!
//!
//! ## Overview
//!
//! Allows a user to ask to sign, register with the network and allows a node to confirm
//! signing was completed properly.
//! Entrypoint into the Entropy network.
//!
//! It allows a user to submit a registration request to the network initiating the distributed key
//! generation (DKG) process.
//!
//! After this process validator nodes on the network can confirm that they have received a
//! key-share from the registering user. Once enough validators have signaled that they have the
//! user's key-share (right now this is one validator per partition) the user can be considered as
//! registered.
//!
//! ### Public Functions
//!
//! prep_transaction - declares intent to sign, this gets relayed to thereshold network
//! register - register's a user and that they have created and distributed entropy shards
//! confirm_done - allows a node to confirm signing has happened and if a failure occured
//! `register` - Allows a user to signal their intent to register onto the Entropy network.
//! `confirm_register` - Allows validator nodes to confirm that they have recieved a user's
//! key-share. After enough succesful confirmations from validators that user will be succesfully
//! registered.

#![cfg_attr(not(feature = "std"), no_std)]
#![allow(clippy::new_without_default)]
#![allow(clippy::or_fun_call)]
Expand All @@ -30,7 +38,7 @@ pub mod weights;

#[frame_support::pallet]
pub mod pallet {
use entropy_shared::{Constraints, KeyVisibility, SIGNING_PARTY_SIZE};
use entropy_shared::{KeyVisibility, SIGNING_PARTY_SIZE};
use frame_support::{
dispatch::{DispatchResult, DispatchResultWithPostInfo, Pays},
inherent::Vec,
Expand Down Expand Up @@ -66,9 +74,9 @@ pub mod pallet {
#[scale_info(skip_type_params(T))]
pub struct RegisteringDetails<T: Config> {
pub is_registering: bool,
pub constraint_account: T::AccountId,
pub program_modification_account: T::AccountId,
pub confirmations: Vec<u8>,
pub constraints: Option<Constraints>,
pub program: Vec<u8>,
pub key_visibility: KeyVisibility,
}

Expand Down Expand Up @@ -162,54 +170,58 @@ pub mod pallet {
IpAddressError,
SigningGroupError,
NoSyncedValidators,
MaxProgramLengthExceeded,
}

/// Allows a user to kick off signing process
/// `sig_request`: signature request for user
#[pallet::call]
impl<T: Config> Pallet<T> {
/// Signals that a user wants to register an account with Entropy.
/// Allows a user to signal that they want to register an account with the Entropy network.
///
/// This should be called by the signature-request account, and specify the initial
/// constraint-modification `AccountId` that can set constraints.
/// The caller provides an initial program, if any, an account which is able to modify a
/// the program, and the program's permission level on the network.
///
/// Note that a user needs to be confirmed by validators through the
/// [`Self::confirm_register`] extrinsic before they can be considered as registered on the
/// network.
#[pallet::call_index(0)]
#[pallet::weight({
let (mut evm_acl_len, mut btc_acl_len) = (0, 0);
if let Some(constraints) = &initial_constraints {
(evm_acl_len, btc_acl_len) = ConstraintsPallet::<T>::constraint_weight_values(constraints);
}
<T as Config>::WeightInfo::register(evm_acl_len, btc_acl_len)
<T as Config>::WeightInfo::register(initial_program.len() as u32)
})]
pub fn register(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this requires we pass an initial program at registration?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe (pending the discussion below), but mostly that there's a change in field names and the type of a program (Option vs. Vec<u8>).

origin: OriginFor<T>,
constraint_account: T::AccountId,
program_modification_account: T::AccountId,
key_visibility: KeyVisibility,
initial_constraints: Option<Constraints>,
initial_program: Vec<u8>,
) -> DispatchResult {
let sig_req_account = ensure_signed(origin)?;

// ensure account isn't already registered or has existing constraints
// Ensure account isn't already registered or has existing constraints
ensure!(!Registered::<T>::contains_key(&sig_req_account), Error::<T>::AlreadySubmitted);
ensure!(
!Registering::<T>::contains_key(&sig_req_account),
Error::<T>::AlreadySubmitted
);
if let Some(constraints) = &initial_constraints {
ConstraintsPallet::<T>::validate_constraints(constraints)?;
}

ensure!(
initial_program.len() as u32
<= <T as pallet_constraints::Config>::MaxV2BytecodeLength::get(),
Error::<T>::MaxProgramLengthExceeded,
);

let block_number = <frame_system::Pallet<T>>::block_number();
Dkg::<T>::try_mutate(block_number, |messages| -> Result<_, DispatchError> {
messages.push(sig_req_account.clone().encode());
Ok(())
})?;
// put account into a registering state

// Put account into a registering state
Registering::<T>::insert(
&sig_req_account,
RegisteringDetails::<T> {
is_registering: true,
constraint_account: constraint_account.clone(),
program_modification_account,
confirmations: vec![],
constraints: initial_constraints,
program: initial_program,
key_visibility,
},
);
Expand All @@ -222,9 +234,11 @@ pub mod pallet {
Ok(())
}

/// Used by validators to confirm they have received a key-share from a user that is
/// registering. After a validator from each partition confirms they have a
/// keyshare, this should get the user to a `Registered` state
/// Allows validators to confirm that they have received a key-share from a user that is
/// in the process of registering.
///
/// After a validator from each partition confirms they have a keyshare the user will be
/// considered as registered on the network.
#[pallet::call_index(2)]
#[pallet::weight({
let weight =
Expand Down Expand Up @@ -271,17 +285,15 @@ pub mod pallet {
Registering::<T>::remove(&sig_req_account);

AllowedToModifyConstraints::<T>::insert(
&registering_info.constraint_account,
&registering_info.program_modification_account,
sig_req_account.clone(),
(),
);

if let Some(constraints) = registering_info.constraints {
ConstraintsPallet::<T>::set_constraints_unchecked(
&sig_req_account,
&constraints,
);
}
ConstraintsPallet::<T>::set_program_unchecked(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like using set unchecked, as in set program we charge a deposit for length of program, here I believe people can post an arbitrary sized program for free

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I can tell this doesn't change the previous deposit/weight behaviour for this extrinsic.

So the user calling the register extrinsic does get charged by program length (before that was being done with the evm_acl and btc_alc related functions).

The validators never got charged this deposit since Constraints::set_constraints_unchecked() doesn't require a deposit, and the confirm_* weight functions don't account for this either.

If we do want to charge for this some questions come up:

  • Who pays for this?
    • In the current workflow it would seem like the validators would, although maybe want the sig_req_account to
  • Which pallet should handle this?
    • It should be the Constraints pallet imo, but it might make the workflow a bit trickier

And technically the wouldn't be arbitrarily length program, they can only go up to T::MaxV2BytecodeLength 😛

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmmm ya that does need to be solved, but we can charge them the deposit in the register extrinsic and then ya do set unchecked later on

&sig_req_account,
registering_info.program,
)?;

let weight =
<T as Config>::WeightInfo::confirm_register_registered(confirmation_length);
Expand Down
Loading