Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
83d682c
Adding a new voting mechanism for resharing
SimonRastikian May 22, 2026
7feb1b1
Useless compat struct
SimonRastikian May 22, 2026
a9bd4eb
Adding comment
SimonRastikian May 22, 2026
b48bbf1
Accepted snap
SimonRastikian May 22, 2026
2b84e86
Solving conflicts
SimonRastikian May 22, 2026
ba25723
abi changed
SimonRastikian May 22, 2026
376beb3
Some small nits by Reynaldo
SimonRastikian May 27, 2026
871f188
Merge branch 'main' into 3169-per-domain-ReconstructionThreshold-in-r…
SimonRastikian May 27, 2026
7187ab3
No need for skip_serializing_if
SimonRastikian May 27, 2026
d3df8b5
Merge branch 'main' into 3169-per-domain-ReconstructionThreshold-in-r…
SimonRastikian May 27, 2026
b93c5d2
fixing the bug generated due to conflict solving
SimonRastikian May 28, 2026
a1c8d56
Merge branch 'main' into 3169-per-domain-ReconstructionThreshold-in-r…
SimonRastikian May 28, 2026
b64f863
Merge branch 'main' into 3169-per-domain-ReconstructionThreshold-in-r…
SimonRastikian May 29, 2026
a724aed
cargo fmt
SimonRastikian May 29, 2026
220132f
abi test
SimonRastikian May 29, 2026
a37858b
Merge branch 'main' into 3169-per-domain-ReconstructionThreshold-in-r…
SimonRastikian May 29, 2026
188521b
Merge branch 'main' into 3169-per-domain-ReconstructionThreshold-in-r…
SimonRastikian May 29, 2026
a025892
Conversion Error
SimonRastikian Jun 1, 2026
274cb6a
cargo fmt
SimonRastikian Jun 1, 2026
59a1fae
comment
SimonRastikian Jun 1, 2026
fca347b
reject proposals that would leave CaitSith domains with differing rec…
SimonRastikian Jun 1, 2026
cdae919
Less flaky tests
SimonRastikian Jun 1, 2026
34ba83c
cargo fmt
SimonRastikian Jun 1, 2026
af28d30
ProposedThresholdParameters type-split
SimonRastikian Jun 2, 2026
8e8adc8
fixing clippy
SimonRastikian Jun 2, 2026
cd87025
Merge branch 'main' into 3169-per-domain-ReconstructionThreshold-in-r…
SimonRastikian Jun 3, 2026
fa1790a
Merge branch 'main' into 3169-per-domain-ReconstructionThreshold-in-r…
SimonRastikian Jun 3, 2026
caa00f1
fixing syntax
SimonRastikian Jun 3, 2026
5511ec9
flatten overlaid-thresholds tests into tests module
SimonRastikian Jun 5, 2026
e804ee5
gate with_per_domain_thresholds behind cfg(test)
SimonRastikian Jun 5, 2026
df34102
fix vote test comment wording
SimonRastikian Jun 5, 2026
76e5269
test migration through the shadow vote type
SimonRastikian Jun 5, 2026
41a5989
Fixing conflicts
SimonRastikian Jun 8, 2026
c7b6123
Changing comments
SimonRastikian Jun 8, 2026
ad6b8fc
fixing cargo doc
SimonRastikian Jun 8, 2026
304a3d2
aligning the tests
SimonRastikian Jun 8, 2026
aff981c
flatten strategy
SimonRastikian Jun 8, 2026
9f5c1dc
use outside of fn
SimonRastikian Jun 8, 2026
c4a5a37
rework comment
SimonRastikian Jun 8, 2026
7ea2180
change cryptographic to governance
SimonRastikian Jun 8, 2026
3863326
Merge branch 'main' into 3169-per-domain-ReconstructionThreshold-in-r…
SimonRastikian Jun 8, 2026
9128952
Adding TODO
SimonRastikian Jun 8, 2026
1695875
gMerge branch '3169-per-domain-ReconstructionThreshold-in-resharing' …
SimonRastikian Jun 8, 2026
df4ad09
More comments
SimonRastikian Jun 8, 2026
cc40c21
Comma separated
SimonRastikian Jun 8, 2026
726635d
Fixing CI
SimonRastikian Jun 8, 2026
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
36 changes: 35 additions & 1 deletion crates/contract/src/dto_mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::{
key_state::{AuthenticatedAccountId, AuthenticatedParticipantId, KeyForDomain, Keyset},
participants::{ParticipantInfo, Participants},
threshold_votes::ThresholdParametersVotes,
thresholds::ThresholdParameters,
thresholds::{ProposedThresholdParameters, ThresholdParameters},
},
state::{
ProtocolContractState,
Expand Down Expand Up @@ -214,10 +214,28 @@ impl IntoContractType<Participants> for dtos::Participants {

impl IntoContractType<ThresholdParameters> for dtos::ThresholdParameters {
fn into_contract_type(self) -> ThresholdParameters {
// This conversion is intentionally infallible: `new_unvalidated` skips the
// absolute/relative (>= 60%) threshold checks. Validation is not the job of the
// DTO mapping — every contract entry point that accepts these parameters
// (`init`, `init_running`, `vote_new_parameters`) calls `validate()` /
// `validate_incoming_proposal` downstream, so production proposals are still
// rejected if they violate the threshold bounds. Deferring validation here also
// lets tests construct parameters with sub-production thresholds.
ThresholdParameters::new_unvalidated(self.participants.into_contract_type(), self.threshold)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I did not want to change that but question to the public: Why is this a new_unvalidated instead of the normal new (with validation)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@gilcu3 do you have an idea?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think to allow low threshold values in tests that would otherwise not pass in production (e.g. >= 60%)

}
}

impl IntoContractType<ProposedThresholdParameters> for dtos::ProposedThresholdParameters {
fn into_contract_type(self) -> ProposedThresholdParameters {
// Infallible for the same reason as `ThresholdParameters` above: the
// proposal is validated downstream in `process_new_parameters_proposal`.
ProposedThresholdParameters::new(
self.parameters.into_contract_type(),
self.per_domain_thresholds,
)
}
}

impl TryIntoContractType<EventLog> for dtos::EventLog {
type Error = Error;
fn try_into_contract_type(self) -> Result<EventLog, Self::Error> {
Expand Down Expand Up @@ -636,6 +654,12 @@ mod to_dto {
}
}

impl From<ProposedThresholdParameters> for dtos::ProposedThresholdParameters {
fn from(params: ProposedThresholdParameters) -> Self {
(&params).into_dto_type()
}
}

impl From<ParticipantInfo> for dtos::ParticipantInfo {
fn from(info: ParticipantInfo) -> Self {
dtos::ParticipantInfo {
Expand Down Expand Up @@ -729,6 +753,15 @@ impl IntoInterfaceType<dtos::ThresholdParameters> for &ThresholdParameters {
}
}

impl IntoInterfaceType<dtos::ProposedThresholdParameters> for &ProposedThresholdParameters {
fn into_dto_type(self) -> dtos::ProposedThresholdParameters {
dtos::ProposedThresholdParameters {
parameters: self.parameters().into_dto_type(),
per_domain_thresholds: self.per_domain_thresholds().clone(),
}
}
}

// --- Voting types ---

impl IntoInterfaceType<dtos::ThresholdParametersVotes> for &ThresholdParametersVotes {
Expand Down Expand Up @@ -853,6 +886,7 @@ impl IntoInterfaceType<dtos::ResharingContractState> for &ResharingContractState
.iter()
.map(|a| a.into_dto_type())
.collect(),
per_domain_thresholds: self.per_domain_thresholds.clone(),
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions crates/contract/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,10 @@ pub enum DomainError {
"Reconstruction threshold {threshold} overflowed when computing the DamgardEtAl bound."
)]
ReconstructionThresholdOverflow { threshold: u64 },
#[error(
"Resharing proposal references domain ID {domain_id}, which is not in the current registry."
)]
UnknownDomainInProposal { domain_id: DomainId },
#[error("CaitSith threshold mismatch: expected {expected}, found {found}.")]
CaitsithThresholdMismatch { expected: u64, found: u64 },
}
Expand Down
23 changes: 17 additions & 6 deletions crates/contract/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ use primitives::{
domain::DomainRegistry,
key_state::{AuthenticatedParticipantId, EpochId, KeyEventId, Keyset},
signature::{SignRequestArgs, SignatureRequest, YieldIndex},
thresholds::{Threshold, ThresholdParameters},
thresholds::{ProposedThresholdParameters, Threshold, ThresholdParameters},
};
use tee::measurements::{ContractExpectedMeasurements, MeasurementVoteAction, MeasurementVotes};
use tee::proposal::{CodeHashesVotes, LauncherHashVotes};
Expand Down Expand Up @@ -873,10 +873,10 @@ impl MpcContract {
pub fn vote_new_parameters(
&mut self,
prospective_epoch_id: EpochId,
proposal: dtos::ThresholdParameters,
proposal: dtos::ProposedThresholdParameters,
) -> Result<(), Error> {
Self::assert_caller_is_signer();
let proposal: ThresholdParameters = proposal.into_contract_type();
let proposal: ProposedThresholdParameters = proposal.into_contract_type();
log!(
"vote_new_parameters: signer={}, proposal={:?}",
env::signer_account_id(),
Expand Down Expand Up @@ -1604,7 +1604,11 @@ impl MpcContract {
)
.expect("Require valid threshold parameters"); // this should never happen.
current_params.validate_incoming_proposal(&threshold_parameters)?;
let res = running_state.transition_to_resharing_no_checks(&threshold_parameters);
// TEE-driven resharing only changes the participant set, so the
// per-domain reconstruction-threshold overlay is empty.
let proposed_parameters =
ProposedThresholdParameters::new(threshold_parameters, BTreeMap::new());
let res = running_state.transition_to_resharing_no_checks(&proposed_parameters);
if let Some(resharing) = res {
self.protocol_state = ProtocolContractState::Resharing(resharing);
}
Expand Down Expand Up @@ -3676,7 +3680,10 @@ mod tests {
.build();
testing_env!(voting_context);

let proposal = ThresholdParameters::new(participants, threshold).unwrap();
let proposal = ProposedThresholdParameters::new(
ThresholdParameters::new(participants, threshold).unwrap(),
BTreeMap::new(),
);
contract.vote_new_parameters(EpochId::new(1), (&proposal).into_dto_type())
}

Expand Down Expand Up @@ -3781,7 +3788,10 @@ mod tests {
// so signer_account_id (the participant) != predecessor_account_id (the forwarder).
let (mut contract, participants, first_participant_id) = setup_tee_test_contract(3, 2);
let threshold = Threshold::new(2);
let proposal = ThresholdParameters::new(participants, threshold).unwrap();
let proposal = ProposedThresholdParameters::new(
ThresholdParameters::new(participants, threshold).unwrap(),
BTreeMap::new(),
);

let ctx = VMContextBuilder::new()
.signer_account_id(first_participant_id)
Expand Down Expand Up @@ -5169,6 +5179,7 @@ mod tests {
expected_params,
),
cancellation_requests: HashSet::new(),
per_domain_thresholds: BTreeMap::new(),
};

assert_eq!(*resharing_state, expected_resharing_state);
Expand Down
Loading
Loading