From cc7ac2a971c2ae1a4b9615969d07a4c6f915b23f Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 24 Sep 2026 13:34:08 +0700 Subject: [PATCH 1/4] feat(platform)!: split a seated moderation team's pot by its reward split and settle it before team changes A seated elected team claims its contract's moderators pot by its proposal's rewardSplit: the leader share, the equal share between the other members and the action share by each one's count of bans, suspensions, warnings and document deletions since the last settle (equally when nobody acted). Every part rounds down and the remainder stays in the pot. The counts live in the moderated contract's other tree at key 48, created with an elected contract. Every settle resets them: a claim, and the settle an addedModerator or removedModerator create or delete forces first, which ignores the once-per-epoch limit and writes no last claim. The claim proof of an elected contract's moderators pot shows the claimant's balance alone: the contract does not name a seated team. Co-Authored-By: Claude Opus 5.5 --- .../document_type/action_fees/mod.rs | 23 +- packages/rs-dpp/src/moderation_charter/mod.rs | 12 +- .../src/moderation_charter/reward_split.rs | 283 ++++++++++++ .../common/seated_moderation_charter/mod.rs | 235 +++++++++- .../state_transitions/batch/state/v0/mod.rs | 20 + .../batch/state/v0/moderators_pot_settle.rs | 206 +++++++++ .../contract_fee_claim/state/v0/mod.rs | 143 +++++- .../contract_user_moderation/state/v0/mod.rs | 71 ++- .../tests/seated_team.rs | 2 + .../tests/seated_team/pot.rs | 437 ++++++++++++++++++ packages/rs-drive/grovedb-structure.json | 46 ++ .../contract/moderation/action_count_tests.rs | 280 +++++++++++ .../moderation/estimated_costs/mod.rs | 27 ++ .../moderation/estimated_costs/v0/mod.rs | 36 +- .../mod.rs | 173 +++++++ .../v0/mod.rs | 97 ++++ .../insert_contract_moderation_trees/mod.rs | 5 +- .../v0/mod.rs | 17 +- .../src/drive/contract/moderation/mod.rs | 9 + .../mod.rs | 62 +++ .../v0/mod.rs | 63 +++ .../mod.rs | 65 +++ .../v0/mod.rs | 42 ++ .../src/drive/contract/moderation/types.rs | 20 + packages/rs-drive/src/drive/contract/paths.rs | 35 ++ .../rs-drive/src/drive/contract/structure.rs | 42 +- .../prove/prove_state_transition/v0/mod.rs | 9 +- .../document/documents_batch_transition.rs | 19 +- .../contract/contract_fee_claim_transition.rs | 20 +- .../contract_user_moderation_transition.rs | 41 ++ .../src/state_transition_action/batch/mod.rs | 16 + .../state_transition_action/batch/v0/mod.rs | 9 + .../contract/contract_fee_claim/mod.rs | 7 + .../contract_fee_claim/transformer.rs | 6 +- .../contract/contract_fee_claim/v0/mod.rs | 8 +- .../contract_fee_claim/v0/transformer.rs | 6 +- .../contract/contract_user_moderation/mod.rs | 20 + .../contract_user_moderation/v0/mod.rs | 6 + .../v0/transformer.rs | 1 + .../state_transition_action/contract/mod.rs | 2 + .../contract/moderators_pot_settlement.rs | 82 ++++ packages/rs-drive/src/structure/tests.rs | 58 ++- .../drive_op_batch/contract_moderation.rs | 43 +- .../v0/mod.rs | 5 +- .../drive_contract_method_versions/mod.rs | 8 + .../drive_contract_method_versions/v1.rs | 4 + .../drive_contract_method_versions/v2.rs | 4 + .../drive_contract_method_versions/v3.rs | 4 + .../drive_contract_method_versions/v4.rs | 4 + 49 files changed, 2763 insertions(+), 70 deletions(-) create mode 100644 packages/rs-dpp/src/moderation_charter/reward_split.rs create mode 100644 packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/moderators_pot_settle.rs create mode 100644 packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team/pot.rs create mode 100644 packages/rs-drive/src/drive/contract/moderation/action_count_tests.rs create mode 100644 packages/rs-drive/src/drive/contract/moderation/fetch_contract_moderation_action_counts/mod.rs create mode 100644 packages/rs-drive/src/drive/contract/moderation/fetch_contract_moderation_action_counts/v0/mod.rs create mode 100644 packages/rs-drive/src/drive/contract/moderation/remove_contract_moderation_action_counts/mod.rs create mode 100644 packages/rs-drive/src/drive/contract/moderation/remove_contract_moderation_action_counts/v0/mod.rs create mode 100644 packages/rs-drive/src/drive/contract/moderation/set_contract_moderation_action_count/mod.rs create mode 100644 packages/rs-drive/src/drive/contract/moderation/set_contract_moderation_action_count/v0/mod.rs create mode 100644 packages/rs-drive/src/state_transition_action/contract/moderators_pot_settlement.rs diff --git a/packages/rs-dpp/src/data_contract/document_type/action_fees/mod.rs b/packages/rs-dpp/src/data_contract/document_type/action_fees/mod.rs index bbcb80f0963..93c7fd44ebf 100644 --- a/packages/rs-dpp/src/data_contract/document_type/action_fees/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/action_fees/mod.rs @@ -104,7 +104,8 @@ impl ActionFeePricing { pub enum ContractFeePot { /// The pot the contract owner claims Owner, - /// The pot the contract's moderation team shares equally + /// The pot the contract's moderation team shares: equally for a declared team, by its + /// proposal's reward split for a seated elected team Moderators, } @@ -126,6 +127,26 @@ impl ContractFeePot { .unwrap_or_default(), } } + + /// The identities whose balances the proof of a claim of this pot of `contract` by + /// `claimant_id` shows: the recipients, or for the moderators pot of an elected contract + /// the claimant alone. The team a seated charter pays is the charter contract's, which the + /// contract does not say, so neither the prover nor the verifier could name it; the + /// claimant, a member of whichever team claimed, is in the transition. + pub fn claim_proof_identities( + &self, + contract: &DataContract, + claimant_id: Identifier, + ) -> BTreeSet { + let elected = contract + .config() + .moderation() + .is_some_and(|moderation| moderation.moderators.elected().is_some()); + match self { + ContractFeePot::Moderators if elected => BTreeSet::from([claimant_id]), + _ => self.recipients(contract), + } + } } impl fmt::Display for ContractFeePot { diff --git a/packages/rs-dpp/src/moderation_charter/mod.rs b/packages/rs-dpp/src/moderation_charter/mod.rs index 4a78825cd1a..aab67bf439e 100644 --- a/packages/rs-dpp/src/moderation_charter/mod.rs +++ b/packages/rs-dpp/src/moderation_charter/mod.rs @@ -36,6 +36,7 @@ //! [`SubmittedCharter`] and [`ElectedCharter`] read the documents' properties, and //! [`validate_submitted_charter`] reads a proposal. Nothing here reads state. +mod reward_split; mod v0; use crate::balances::credits::Credits; @@ -134,15 +135,18 @@ pub mod property_names { pub const MEMBER_ID: &str = "memberId"; } -/// How a team splits every claim of the moderators pot: three percentages summing to 100. +/// How a team splits every settle of the moderators pot, a claim or a change of the team: three +/// percentages summing to 100. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ModerationCharterRewardSplit { /// The share of the leader. pub leader: u8, - /// The share split equally between the members other than the leader. + /// The share split equally between the members other than the leader; the leader's when + /// it has no member. pub equal: u8, - /// The share split between the members by the moderation actions each signed since the - /// last claim. + /// The share split between the team, the leader included, by the moderation actions each + /// signed since the pot was last settled, or equally when nobody acted. See + /// [`ModerationCharterRewardSplit::payouts`]. pub actions: u8, } diff --git a/packages/rs-dpp/src/moderation_charter/reward_split.rs b/packages/rs-dpp/src/moderation_charter/reward_split.rs new file mode 100644 index 00000000000..46feebd3e68 --- /dev/null +++ b/packages/rs-dpp/src/moderation_charter/reward_split.rs @@ -0,0 +1,283 @@ +//! How a seated team's moderators pot is paid out: its proposal's `rewardSplit`. + +use super::ModerationCharterRewardSplit; +use crate::balances::credits::Credits; +use crate::ProtocolError; +use platform_value::Identifier; +use std::collections::{BTreeMap, BTreeSet}; + +/// The percentages of a reward split are of a whole of 100. +const WHOLE: u128 = 100; + +impl ModerationCharterRewardSplit { + /// What a settle of `pot` credits pays each identity of a seated team: the leader + /// `leader_id`, and `members`, the active members besides it. `action_counts` holds the + /// moderation actions each one signed since the pot was last settled; a count of an + /// identity that is not on the team is left out. + /// + /// - The leader share, `leader` percent of the pot, goes to the leader. + /// - The equal share, `equal` percent, is split equally between the members; with no + /// member besides the leader it goes to the leader, who is then the whole team. + /// - The action share, `actions` percent, is split between the team, the leader included, + /// in proportion to each one's action count; when nobody acted, it is split equally + /// between them. + /// + /// Every share and every part of one is rounded down to the credit, so a settle never pays + /// more than the pot holds. What the rounding leaves, a few credits at most, stays in the + /// pot for the next settle, so no identity is favoured by the order of the identity ids. + /// An identity whose parts all round down to nothing is left out of the result. + /// + /// Fails when the three percentages do not add up to 100, which the charter contract's + /// `propertyConstraints` rule `rewardSplitIsWhole` refuses at every write. + pub fn payouts( + &self, + pot: Credits, + leader_id: Identifier, + members: &BTreeSet, + action_counts: &BTreeMap, + ) -> Result, ProtocolError> { + let percentages = [self.leader, self.equal, self.actions]; + if percentages + .iter() + .map(|share| u128::from(*share)) + .sum::() + != WHOLE + { + return Err(ProtocolError::CorruptedCodeExecution(format!( + "a reward split of {}/{}/{} does not add up to 100", + self.leader, self.equal, self.actions + ))); + } + let pot = u128::from(pot); + let percent_of_pot = |share: u8| pot * u128::from(share) / WHOLE; + + let mut payouts: BTreeMap = BTreeMap::new(); + let mut pay = |identity_id: Identifier, amount: u128| { + if amount > 0 { + *payouts.entry(identity_id).or_default() += amount; + } + }; + + pay(leader_id, percent_of_pot(self.leader)); + + let equal_share = percent_of_pot(self.equal); + let others: Vec = members + .iter() + .filter(|member| **member != leader_id) + .copied() + .collect(); + if others.is_empty() { + pay(leader_id, equal_share); + } else { + let each = equal_share / others.len() as u128; + for member in &others { + pay(*member, each); + } + } + + let action_share = percent_of_pot(self.actions); + let team: Vec = std::iter::once(leader_id).chain(others).collect(); + let counted: Vec<(Identifier, u128)> = team + .iter() + .map(|identity_id| { + ( + *identity_id, + u128::from(action_counts.get(identity_id).copied().unwrap_or_default()), + ) + }) + .collect(); + let total_actions: u128 = counted.iter().map(|(_, count)| count).sum(); + // In proportion to the counts; with no count at all, equally. + let by_count: Option> = counted + .iter() + .map(|(identity_id, count)| { + (action_share * count) + .checked_div(total_actions) + .map(|amount| (*identity_id, amount)) + }) + .collect(); + match by_count { + Some(parts) => { + for (identity_id, amount) in parts { + pay(identity_id, amount); + } + } + None => { + let each = action_share / team.len() as u128; + for identity_id in &team { + pay(*identity_id, each); + } + } + } + + payouts + .into_iter() + .map(|(identity_id, amount)| { + // Every part is a share of the pot, and the parts add up to at most the pot. + Credits::try_from(amount) + .map(|amount| (identity_id, amount)) + .map_err(|_| { + ProtocolError::CorruptedCodeExecution( + "a payout of a moderators pot exceeds the pot".to_string(), + ) + }) + }) + .collect() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn id(seed: u8) -> Identifier { + Identifier::from([seed; 32]) + } + + fn split(leader: u8, equal: u8, actions: u8) -> ModerationCharterRewardSplit { + ModerationCharterRewardSplit { + leader, + equal, + actions, + } + } + + fn members(seeds: &[u8]) -> BTreeSet { + seeds.iter().map(|seed| id(*seed)).collect() + } + + fn counts(entries: &[(u8, u32)]) -> BTreeMap { + entries + .iter() + .map(|(seed, count)| (id(*seed), *count)) + .collect() + } + + #[test] + fn should_pay_the_leader_share_the_equal_share_and_the_action_share_by_count() { + // 10/40/50 of 1_000: the leader takes 100, the two members 200 each of the equal 400, + // and the 500 of the action share goes 1:3:1 between the leader and the members. + let payouts = split(10, 40, 50) + .payouts( + 1_000, + id(1), + &members(&[2, 3]), + &counts(&[(1, 1), (2, 3), (3, 1)]), + ) + .expect("expected a payout"); + assert_eq!( + payouts, + BTreeMap::from([(id(1), 100 + 100), (id(2), 200 + 300), (id(3), 200 + 100)]) + ); + assert_eq!(payouts.values().sum::(), 1_000); + } + + #[test] + fn should_round_every_part_down_and_leave_the_remainder_in_the_pot() { + // 10/40/50 of 1_003: leader 100 (100.3), equal 401 (401.2) split in three is 133 each, + // actions 501 (501.5) split 2:1 between two members is 334 and 167. Paid: 100 + 399 + + // 501 = 1_000; three credits stay in the pot. + let payouts = split(10, 40, 50) + .payouts( + 1_003, + id(1), + &members(&[2, 3, 4]), + &counts(&[(2, 2), (3, 1)]), + ) + .expect("expected a payout"); + assert_eq!( + payouts, + BTreeMap::from([ + (id(1), 100), + (id(2), 133 + 334), + (id(3), 133 + 167), + (id(4), 133), + ]) + ); + assert_eq!(1_003 - payouts.values().sum::(), 3); + } + + #[test] + fn should_split_the_action_share_equally_when_nobody_acted() { + // Nobody acted since the last settle: the 600 of the action share goes 200 each to the + // leader and the two members. + let payouts = split(0, 40, 60) + .payouts(1_000, id(1), &members(&[2, 3]), &BTreeMap::new()) + .expect("expected a payout"); + assert_eq!( + payouts, + BTreeMap::from([(id(1), 200), (id(2), 200 + 200), (id(3), 200 + 200)]) + ); + } + + #[test] + fn should_pay_a_leader_alone_the_whole_pot() { + let payouts = split(10, 40, 50) + .payouts(1_000, id(1), &BTreeSet::new(), &counts(&[(1, 7)])) + .expect("expected a payout"); + assert_eq!(payouts, BTreeMap::from([(id(1), 1_000)])); + } + + #[test] + fn should_ignore_the_count_of_an_identity_that_is_not_on_the_team() { + let payouts = split(0, 0, 100) + .payouts(900, id(1), &members(&[2]), &counts(&[(2, 1), (9, 5)])) + .expect("expected a payout"); + assert_eq!(payouts, BTreeMap::from([(id(2), 900)])); + } + + #[test] + fn should_leave_out_an_identity_whose_parts_round_to_nothing() { + // 2 credits split 0/0/100 by counts 1:1:1 is 0 each: nobody is paid. + let payouts = split(0, 0, 100) + .payouts( + 2, + id(1), + &members(&[2, 3]), + &counts(&[(1, 1), (2, 1), (3, 1)]), + ) + .expect("expected no failure"); + assert!(payouts.is_empty()); + // A member without an action gets nothing of an action-only split. + let payouts = split(0, 0, 100) + .payouts(10, id(1), &members(&[2]), &counts(&[(1, 1)])) + .expect("expected a payout"); + assert_eq!(payouts, BTreeMap::from([(id(1), 10)])); + } + + #[test] + fn should_never_leave_the_leader_among_the_members() { + // A member set that names the leader counts it once, as the leader. + let payouts = split(0, 100, 0) + .payouts(100, id(1), &members(&[1, 2]), &BTreeMap::new()) + .expect("expected a payout"); + assert_eq!(payouts, BTreeMap::from([(id(2), 100)])); + } + + #[test] + fn should_pay_the_largest_pot_without_overflowing() { + let pot = Credits::MAX; + let payouts = split(33, 33, 34) + .payouts( + pot, + id(1), + &members(&[2]), + &counts(&[(1, u32::MAX), (2, u32::MAX)]), + ) + .expect("expected a payout"); + let paid = payouts + .values() + .try_fold(0 as Credits, |sum, amount| sum.checked_add(*amount)); + assert!(paid.is_some_and(|paid| paid <= pot)); + } + + #[test] + fn should_refuse_a_split_that_does_not_add_up_to_one_hundred() { + assert!(split(10, 40, 40) + .payouts(1_000, id(1), &members(&[2]), &BTreeMap::new()) + .is_err()); + assert!(split(100, 100, 0) + .payouts(1_000, id(1), &members(&[2]), &BTreeMap::new()) + .is_err()); + } +} diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/common/seated_moderation_charter/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/common/seated_moderation_charter/mod.rs index b27a78f8196..db7597974a0 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/common/seated_moderation_charter/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/common/seated_moderation_charter/mod.rs @@ -30,9 +30,10 @@ use dpp::block::epoch::Epoch; use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::document::{Document, DocumentV0Getters}; use dpp::fee::fee_result::FeeResult; +use dpp::fee::Credits; use dpp::identifier::Identifier; use dpp::moderation_charter::{ - property_names, ElectedCharter, ADDED_MODERATOR_DOCUMENT_TYPE_NAME, + property_names, ElectedCharter, SubmittedCharter, ADDED_MODERATOR_DOCUMENT_TYPE_NAME, ELECTED_CHARTER_DOCUMENT_TYPE_NAME, FULL_MODERATORS_SHARE, REMOVED_MODERATOR_DOCUMENT_TYPE_NAME, SUBMITTED_CHARTER_DOCUMENT_TYPE_NAME, }; @@ -43,6 +44,8 @@ use drive::drive::document::query::QueryDocumentsOutcomeV0Methods; use drive::drive::Drive; use drive::grovedb::TransactionArg; use drive::query::{DriveDocumentQuery, InternalClauses, WhereClause, WhereOperator}; +use drive::state_transition_action::contract::moderators_pot_settlement::ModeratorsPotSettlement; +use std::collections::BTreeSet; /// The charter seated on an elected contract, as stored by the moderation charters contract #[derive(Debug, Clone, PartialEq, Eq)] @@ -79,6 +82,43 @@ pub(crate) fn fetch_seated_moderation_charter( .next() else { return Ok(None); }; + seated_charter_of(document).map(Some) +} + +/// The elected charter stored at `elected_charter_id`, `None` when there is none. A stored +/// elected charter is a seated one: only a contest's winner is ever written to the type's +/// storage. One read by id, billed. +pub(crate) fn fetch_moderation_charter_by_id( + drive: &Drive, + elected_charter_id: Identifier, + epoch: &Epoch, + execution_context: &mut StateTransitionExecutionContext, + transaction: TransactionArg, + platform_version: &PlatformVersion, +) -> Result, Error> { + let contract = drive + .cache + .system_data_contracts + .load_moderation_charters(platform_version)?; + let document_type = contract.document_type_for_name(ELECTED_CHARTER_DOCUMENT_TYPE_NAME)?; + let Some(document) = fetch_document_with_id( + drive, + &contract, + document_type, + elected_charter_id, + epoch, + execution_context, + transaction, + platform_version, + )? + else { + return Ok(None); + }; + seated_charter_of(document).map(Some) +} + +/// Reads a stored elected charter document. +fn seated_charter_of(document: Document) -> Result { // The schema admitted the document when it was filed, so it reads. let charter = ElectedCharter::from_document_properties(document.properties()) .into_data() @@ -87,11 +127,11 @@ pub(crate) fn fetch_seated_moderation_charter( "a stored elected charter does not read as one", )) })?; - Ok(Some(SeatedModerationCharter { + Ok(SeatedModerationCharter { id: document.id(), leader_id: document.owner_id(), charter, - })) + }) } impl SeatedModerationCharter { @@ -148,6 +188,61 @@ impl SeatedModerationCharter { transaction: TransactionArg, platform_version: &PlatformVersion, ) -> Result { + let proposal = self.fetch_proposal_document( + drive, + epoch, + execution_context, + transaction, + platform_version, + )?; + // The share alone is read: nothing else of the proposal decides the discount. The + // schema bounds it to 0 to 100 and leaves it out for the full amount. + let share = proposal + .properties() + .get_optional_integer::(property_names::MODERATORS_SHARE) + .map_err(|_| { + Error::Execution(ExecutionError::DriveIncoherence( + "a stored moderation charter proposal's share is not a percentage", + )) + })?; + Ok(share.unwrap_or(FULL_MODERATORS_SHARE)) + } + + /// The proposal the team runs on: its reasons, its share and its reward split. One read of + /// the `submittedCharter` by id, billed. + pub(crate) fn fetch_proposal( + &self, + drive: &Drive, + epoch: &Epoch, + execution_context: &mut StateTransitionExecutionContext, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + let proposal = self.fetch_proposal_document( + drive, + epoch, + execution_context, + transaction, + platform_version, + )?; + // The schema admitted the proposal when it was filed, so it reads. + SubmittedCharter::from_document_properties(proposal.properties()) + .into_data() + .map_err(|_| { + Error::Execution(ExecutionError::DriveIncoherence( + "a stored moderation charter proposal does not read as one", + )) + }) + } + + fn fetch_proposal_document( + &self, + drive: &Drive, + epoch: &Epoch, + execution_context: &mut StateTransitionExecutionContext, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { let contract = drive .cache .system_data_contracts @@ -156,7 +251,7 @@ impl SeatedModerationCharter { contract.document_type_for_name(SUBMITTED_CHARTER_DOCUMENT_TYPE_NAME)?; // The elected charter's reference proved the proposal when the charter was filed, and // a proposal can not be deleted. - let proposal = fetch_document_with_id( + fetch_document_with_id( drive, &contract, document_type, @@ -168,18 +263,134 @@ impl SeatedModerationCharter { )? .ok_or(Error::Execution(ExecutionError::DriveIncoherence( "the proposal of a seated charter is not stored", - )))?; - // The share alone is read: nothing else of the proposal decides the discount. The - // schema bounds it to 0 to 100 and leaves it out for the full amount. - let share = proposal - .properties() - .get_optional_integer::(property_names::MODERATORS_SHARE) + ))) + } + + /// The active members of the team besides the leader ([`ElectedCharter::active_members`]): + /// the charter's `members` less its `removedModerator` documents, plus its + /// `addedModerator` documents. Two billed queries of the `byElectedCharterMember` indexes, + /// each bounded: a removal names one of the charter's members, and the target's + /// `maxAddedModerators` caps the additions that exist. A query that can find nothing is not + /// made. + #[allow(clippy::too_many_arguments)] + pub(crate) fn fetch_active_members( + &self, + drive: &Drive, + max_added_moderators: u16, + epoch: &Epoch, + execution_context: &mut StateTransitionExecutionContext, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let removals_bound = u16::try_from(self.charter.members.len()).unwrap_or(u16::MAX); + let member_ids = |document_type_name: &str, + limit: u16, + execution_context: &mut StateTransitionExecutionContext| + -> Result, Error> { + if limit == 0 { + return Ok(vec![]); + } + query_charter_documents( + drive, + document_type_name, + [(property_names::ELECTED_CHARTER_ID, self.id)], + limit, + epoch, + execution_context, + transaction, + platform_version, + )? + .iter() + .map(|document| { + // The schema requires the member of every team change. + document + .properties() + .get_identifier(property_names::MEMBER_ID) + .map_err(|_| { + Error::Execution(ExecutionError::DriveIncoherence( + "a stored moderation team change names its member", + )) + }) + }) + .collect() + }; + let removed = member_ids( + REMOVED_MODERATOR_DOCUMENT_TYPE_NAME, + removals_bound, + execution_context, + )?; + let added = member_ids( + ADDED_MODERATOR_DOCUMENT_TYPE_NAME, + max_added_moderators, + execution_context, + )?; + Ok(self + .charter + .active_members(self.leader_id, &added, &removed)) + } + + /// The settle of the moderators pot of the elected contract `contract_id`, holding + /// `pot_credits`, to the team as it is now: what the proposal's reward split pays the + /// leader and each active member ([`dpp::moderation_charter::ModerationCharterRewardSplit::payouts`]), and the + /// action counts it resets, every count that exists. Reads, all billed: the active members + /// (see [`SeatedModerationCharter::fetch_active_members`]), the proposal, and the counts, + /// at most one per identity the team can hold. + /// + /// Every settle resets every count, so a count only exists for a member of the team as it + /// is at the settle: a change of the team settles first. + #[allow(clippy::too_many_arguments)] + pub(crate) fn settle_moderators_pot( + &self, + drive: &Drive, + contract_id: Identifier, + pot_credits: Credits, + max_added_moderators: u16, + epoch: &Epoch, + execution_context: &mut StateTransitionExecutionContext, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + let members = self.fetch_active_members( + drive, + max_added_moderators, + epoch, + execution_context, + transaction, + platform_version, + )?; + let proposal = self.fetch_proposal( + drive, + epoch, + execution_context, + transaction, + platform_version, + )?; + // The leader, the elected members and the additions the target allows. + let team_bound = u16::try_from(self.charter.members.len()) + .unwrap_or(u16::MAX) + .saturating_add(max_added_moderators) + .saturating_add(1); + let (fee, action_counts) = drive.fetch_contract_moderation_action_counts_with_fee( + contract_id, + team_bound, + epoch, + transaction, + platform_version, + )?; + execution_context.add_operation(ValidationOperation::PrecalculatedOperation(fee)); + let payouts = proposal + .reward_split + .payouts(pot_credits, self.leader_id, &members, &action_counts) .map_err(|_| { Error::Execution(ExecutionError::DriveIncoherence( - "a stored moderation charter proposal's share is not a percentage", + "a stored moderation charter proposal's reward split adds up to 100", )) })?; - Ok(share.unwrap_or(FULL_MODERATORS_SHARE)) + Ok(ModeratorsPotSettlement { + contract_id, + payouts, + settled_action_counts: action_counts.into_keys().collect(), + }) } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/mod.rs index 75245a879ac..76ff507d41f 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/mod.rs @@ -36,6 +36,7 @@ use crate::execution::validation::state_transition::batch::action_validation::to use crate::execution::validation::state_transition::batch::data_triggers::{data_trigger_bindings_list, DataTriggerExecutionContext, DataTriggerExecutor}; use crate::execution::validation::state_transition::batch::state::v0::added_moderator_cap::AddedModeratorCap; use crate::execution::validation::state_transition::batch::state::v0::index_only_batch_entries::IndexOnlyBatchEntries; +use crate::execution::validation::state_transition::batch::state::v0::moderators_pot_settle::ModeratorsPotSettles; use drive::state_transition_action::batch::batched_transition::document_transition::document_create_transition_action::DocumentCreateTransitionActionAccessorsV0; use crate::platform_types::platform::{PlatformStateRef}; use crate::execution::validation::state_transition::state_transitions::batch::transformer::v0::BatchTransitionTransformerV0; @@ -46,6 +47,7 @@ mod added_moderator_cap; pub mod fetch_contender; pub mod fetch_documents; mod index_only_batch_entries; +mod moderators_pot_settle; pub(in crate::execution::validation::state_transition::state_transitions::batch) trait DocumentsBatchStateTransitionStateValidationV0 { @@ -103,6 +105,12 @@ impl DocumentsBatchStateTransitionStateValidationV0 for BatchTransition { // protocol version 14 only, so no earlier batch takes this path. let mut added_moderator_cap = AddedModeratorCap::default(); + // The settles of moderators pots this batch forces: a change of a seated moderation + // team pays the target's pot out to the team as it was first. Only a create or a + // delete of the moderation charters contract's team changes takes this path, and that + // contract is in state from protocol version 14 only, so no earlier batch does. + let mut moderators_pot_settles = ModeratorsPotSettles::default(); + // Next we need to validate the structure of all actions (this means with the data contract) for transition in state_transition_action.transitions_take() { let transition_validation_result = match &transition { @@ -416,10 +424,22 @@ impl DocumentsBatchStateTransitionStateValidationV0 for BatchTransition { } } + // A change of a seated moderation team settles the team's moderators pot first. + moderators_pot_settles.settle_before_team_change( + &transition, + platform, + block_info, + execution_context, + transaction, + platform_version, + )?; + validated_transitions.push(transition); } state_transition_action.set_transitions(validated_transitions); + state_transition_action + .set_moderators_pot_settlements(moderators_pot_settles.into_settlements()); validation_result.set_data(state_transition_action.into()); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/moderators_pot_settle.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/moderators_pot_settle.rs new file mode 100644 index 00000000000..f3404713f71 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/moderators_pot_settle.rs @@ -0,0 +1,206 @@ +//! The settle of an elected contract's moderators pot that a change of its seated team forces +//! first. +//! +//! The team of a seated moderation charter changes with its leader's `addedModerator` and +//! `removedModerator` documents of the moderation charters contract, created or deleted (an +//! addition is taken back by deleting it, a removal of an elected member undone by deleting +//! it). Before any of them the target's moderators pot is paid out to the team as it was, by +//! its proposal's reward split and the action counts since the last settle, and the counts +//! start over: so no member loses what it earned with the team it earned it in, and no member +//! joins in on what was earned before it came. The once-per-epoch limit of a claim does not +//! apply, and the settle is not a claim: it leaves the pot's last claim alone, so the team may +//! still claim in the same epoch. A pot too small to pay anyone a credit is settled all the +//! same: the counts start over. +//! +//! The settle is an effect of the change, never a refusal: it is judged once the change's own +//! state validation (and for an addition the cap on additions) accepted it, and the batch +//! carries what it pays, for the batch converter to write before the change. Like the cap it +//! runs in state validation, which check tx does not run for a batch: the mempool admits the +//! change without reading the pot. At most one settle per target contract per batch: a later +//! change of the same batch finds the pot paid out and the counts reset. That is dormant while +//! `max_transitions_in_documents_batch` is 1, as it is at every protocol version. +//! +//! Only a create or a delete of the charter contract's `addedModerator` or `removedModerator` +//! takes this path. The charter contract exists in state from protocol version 14 (genesis or +//! the upgrade to 14), and a document transition against a contract that is not in state fails +//! in the transformer, before the state validation loop, so no batch of an earlier protocol +//! version reaches it: the shipped `validate_state_v0` it hooks into behaves as it did for +//! every such batch. + +use crate::error::execution::ExecutionError; +use crate::error::Error; +use crate::execution::types::execution_operation::ValidationOperation; +use crate::execution::types::state_transition_execution_context::{ + StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0, +}; +use crate::execution::validation::state_transition::common::seated_moderation_charter::fetch_moderation_charter_by_id; +use crate::execution::validation::state_transition::state_transitions::batch::fetch_document_with_id; +use crate::platform_types::platform::PlatformStateRef; +use dpp::block::block_info::BlockInfo; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::config::v2::DataContractConfigGettersV2; +use dpp::data_contract::document_type::action_fees::ContractFeePot; +use dpp::document::DocumentV0Getters; +use dpp::identifier::Identifier; +use dpp::moderation_charter::{ + property_names, ADDED_MODERATOR_DOCUMENT_TYPE_NAME, MODERATION_CHARTERS_CONTRACT_ID, + REMOVED_MODERATOR_DOCUMENT_TYPE_NAME, +}; +use dpp::platform_value::btreemap_extensions::BTreeValueMapHelper; +use dpp::version::PlatformVersion; +use drive::grovedb::TransactionArg; +use drive::state_transition_action::batch::batched_transition::document_transition::document_base_transition_action::DocumentBaseTransitionActionAccessorsV0; +use drive::state_transition_action::batch::batched_transition::document_transition::document_create_transition_action::DocumentCreateTransitionActionAccessorsV0; +use drive::state_transition_action::batch::batched_transition::document_transition::DocumentTransitionAction; +use drive::state_transition_action::batch::batched_transition::BatchedTransitionAction; +use drive::state_transition_action::contract::moderators_pot_settlement::ModeratorsPotSettlement; +use std::collections::BTreeSet; + +/// The settles one batch forces. One per batch state validation. +#[derive(Default)] +pub(super) struct ModeratorsPotSettles { + settled_targets: BTreeSet, + settlements: Vec, +} + +impl ModeratorsPotSettles { + /// When `transition` changes a seated team (a create or a delete of the moderation + /// charters contract's `addedModerator` or `removedModerator`), settles the target's + /// moderators pot to the team as it is before the change. A no-op, with nothing read, for + /// every other transition. Call it only for a transition state validation accepted. + /// + /// The reads are billed: for a delete the team change being deleted, the elected charter by + /// id, its target contract, the pot, and what the settle reads (the team, the proposal and + /// the action counts). + pub(super) fn settle_before_team_change( + &mut self, + transition: &BatchedTransitionAction, + platform: &PlatformStateRef, + block_info: &BlockInfo, + execution_context: &mut StateTransitionExecutionContext, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result<(), Error> { + let BatchedTransitionAction::DocumentAction(document_action) = transition else { + return Ok(()); + }; + let base = document_action.base(); + let document_type_name = base.document_type_name(); + if base.data_contract_id() != MODERATION_CHARTERS_CONTRACT_ID + || (document_type_name != ADDED_MODERATOR_DOCUMENT_TYPE_NAME + && document_type_name != REMOVED_MODERATOR_DOCUMENT_TYPE_NAME) + { + return Ok(()); + } + let epoch = &block_info.epoch; + let charters_contract = &base.data_contract_fetch_info_ref().contract; + let unnamed_charter = || { + Error::Execution(ExecutionError::DriveIncoherence( + "a moderation team change names its elected charter", + )) + }; + let elected_charter_id = match document_action { + // The schema requires the charter, and the create's reference validation proved it. + DocumentTransitionAction::CreateAction(create_action) => create_action + .data() + .get_identifier(property_names::ELECTED_CHARTER_ID) + .map_err(|_| unnamed_charter())?, + // The delete's state validation found the change and its owner, the leader. + DocumentTransitionAction::DeleteAction(_) => fetch_document_with_id( + platform.drive, + charters_contract, + charters_contract.document_type_for_name(document_type_name)?, + base.id(), + epoch, + execution_context, + transaction, + platform_version, + )? + .ok_or(Error::Execution(ExecutionError::CorruptedCodeExecution( + "a moderation team change the delete's state validation found is stored", + )))? + .properties() + .get_identifier(property_names::ELECTED_CHARTER_ID) + .map_err(|_| unnamed_charter())?, + // The team change types are immutable, neither transferable nor tradeable, and have + // no indexOnly storage: nothing else of them passes state validation. + _ => return Ok(()), + }; + + // A team change can only name a stored elected charter, which is a seated one: only a + // contest's winner is ever written to the type's storage. + let charter = fetch_moderation_charter_by_id( + platform.drive, + elected_charter_id, + epoch, + execution_context, + transaction, + platform_version, + )? + .ok_or(Error::Execution(ExecutionError::CorruptedCodeExecution( + "the elected charter a moderation team change refers to was found by its reference", + )))?; + let target_contract_id = charter.charter.target_contract_id; + if !self.settled_targets.insert(target_contract_id) { + return Ok(()); + } + + // The fee this call returns is billed, never the one a cached fetch info carries, + // which depends on the cache. + let (fee, target_contract) = platform.drive.get_contract_with_fetch_info_and_fee( + target_contract_id.to_buffer(), + Some(epoch), + false, + transaction, + platform_version, + )?; + let fee = fee.ok_or(Error::Execution(ExecutionError::CorruptedCodeExecution( + "fee must exist when fetching a contract with an epoch", + )))?; + execution_context.add_operation(ValidationOperation::PrecalculatedOperation(fee)); + // A charter is only filed for a contract that declares elected moderation, which is + // fixed at the contract's creation, and a contract is never deleted. + let max_added_moderators = target_contract + .as_ref() + .and_then(|fetch_info| { + fetch_info + .contract + .config() + .moderation() + .and_then(|moderation| moderation.moderators.elected()) + .map(|elected| elected.max_added_moderators) + }) + .ok_or(Error::Execution(ExecutionError::DriveIncoherence( + "the target of a stored elected charter declares elected moderation", + )))?; + + let (fee, fee_pot) = platform.drive.fetch_contract_fee_pot_with_fee( + target_contract_id, + ContractFeePot::Moderators, + epoch, + transaction, + platform_version, + )?; + execution_context.add_operation(ValidationOperation::PrecalculatedOperation(fee)); + + let settlement = charter.settle_moderators_pot( + platform.drive, + target_contract_id, + fee_pot.credits, + max_added_moderators, + epoch, + execution_context, + transaction, + platform_version, + )?; + if !settlement.is_empty() { + self.settlements.push(settlement); + } + Ok(()) + } + + /// What the batch pays out and resets before its changes + pub(super) fn into_settlements(self) -> Vec { + self.settlements + } +} diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_fee_claim/state/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_fee_claim/state/v0/mod.rs index ece48a435a4..fc77c1aa85d 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_fee_claim/state/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_fee_claim/state/v0/mod.rs @@ -4,7 +4,9 @@ use crate::execution::types::execution_operation::ValidationOperation; use crate::execution::types::state_transition_execution_context::{ StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0, }; -use crate::execution::validation::state_transition::common::seated_moderation_charter::fetch_seated_moderation_charter; +use crate::execution::validation::state_transition::common::seated_moderation_charter::{ + fetch_seated_moderation_charter, SeatedModerationCharter, +}; use crate::platform_types::platform::PlatformRef; use crate::rpc::core::CoreRPCLike; use dpp::block::block_info::BlockInfo; @@ -103,37 +105,45 @@ impl ContractFeeClaimStateTransitionStateValidationV0 for ContractFeeClaimTransi return refuse(DataContractNotPresentError::new(contract_id).into()); }; - // Only who a payout of the pot goes to may claim it: the contract owner for the owner - // pot, a member of the moderation team for the moderators pot. A contract that - // declares no moderation has no team, so nobody claims its moderators pot. - let recipients = pot.recipients(&contract_fetch_info.contract); - if !recipients.contains(&claimant_id) { - return refuse( - ContractFeeClaimNotAllowedError::new(contract_id, pot, claimant_id).into(), - ); - } - // The recipients of an elected contract's moderators pot are its interim team, who may - // claim it only until a charter is seated (decentralized moderation teams): from - // then on the pot is the seated team's, and it accumulates for that team, unsettled, - // as it does under an interim that names nobody. Whether one is seated is read, billed, - // only for an interim recipient. + // An elected contract's moderators pot is its seated team's once a charter is seated + // (decentralized moderation teams): the leader or an active member claims it for the + // team, and it is split by the proposal's reward split. Whether one is seated is read, + // billed. Until then it is its interim team's, as the declaration names it. let elected = contract_fetch_info .contract .config() .moderation() - .is_some_and(|moderation| moderation.moderators.elected().is_some()); - if pot == ContractFeePot::Moderators - && elected - && fetch_seated_moderation_charter( + .and_then(|moderation| moderation.moderators.elected()); + if let (ContractFeePot::Moderators, Some(elected)) = (pot, elected) { + if let Some(charter) = fetch_seated_moderation_charter( platform.drive, contract_id, &block_info.epoch, execution_context, tx, platform_version, - )? - .is_some() - { + )? { + return claim_seated_moderators_pot_v0( + self, + platform, + block_info, + &charter, + elected.max_added_moderators, + execution_context, + tx, + platform_version, + ); + } + } + + // Only who a payout of the pot goes to may claim it: the contract owner for the owner + // pot, a member of the moderation team for the moderators pot. A contract that + // declares no moderation has no team, so nobody claims its moderators pot. The + // recipients of an elected contract's moderators pot are its interim team, who claim it + // only until a charter is seated: from then on it is the seated team's (above), and it + // accumulates for that team, unsettled, as it does under an interim that names nobody. + let recipients = pot.recipients(&contract_fetch_info.contract); + if !recipients.contains(&claimant_id) { return refuse( ContractFeeClaimNotAllowedError::new(contract_id, pot, claimant_id).into(), ); @@ -165,12 +175,101 @@ impl ContractFeeClaimStateTransitionStateValidationV0 for ContractFeeClaimTransi epoch_index, block_info.time_ms, payouts, + vec![], ) .into(), )) } } +/// The claim of the moderators pot of an elected contract with a seated charter: the +/// signer is the leader or an active member of the seated team, the pot was not claimed in +/// this epoch yet, and the proposal's reward split pays someone at least a credit. The +/// split reads the team, the proposal and the team's moderation action counts, all billed, +/// and the claim resets the counts. Every refusal is paid for by bumping the signer's +/// contract nonce. +#[allow(clippy::too_many_arguments)] +fn claim_seated_moderators_pot_v0( + transition: &ContractFeeClaimTransition, + platform: &PlatformRef, + block_info: &BlockInfo, + charter: &SeatedModerationCharter, + max_added_moderators: u16, + execution_context: &mut StateTransitionExecutionContext, + tx: TransactionArg, + platform_version: &PlatformVersion, +) -> Result, Error> { + let contract_id = transition.data_contract_id(); + let claimant_id = transition.owner_id(); + let pot = ContractFeePot::Moderators; + let epoch = &block_info.epoch; + let refuse = |error: ConsensusError| { + Ok(ConsensusValidationResult::new_with_data_and_errors( + StateTransitionAction::BumpIdentityDataContractNonceAction( + BumpIdentityDataContractNonceAction::from_borrowed_contract_fee_claim_transition( + transition, + ), + ), + vec![error], + )) + }; + + // The interim moderators, the owner among them, claim no more once a charter is seated. + if !charter.seats( + platform.drive, + claimant_id, + epoch, + execution_context, + tx, + platform_version, + )? { + return refuse(ContractFeeClaimNotAllowedError::new(contract_id, pot, claimant_id).into()); + } + + let (fee, fee_pot) = platform.drive.fetch_contract_fee_pot_with_fee( + contract_id, + pot, + epoch, + tx, + platform_version, + )?; + execution_context.add_operation(ValidationOperation::PrecalculatedOperation(fee)); + + let epoch_index = epoch.index; + if fee_pot.last_claim_epoch() == Some(epoch_index) { + return refuse( + ContractFeesAlreadyClaimedThisEpochError::new(contract_id, pot, epoch_index).into(), + ); + } + + let settlement = charter.settle_moderators_pot( + platform.drive, + contract_id, + fee_pot.credits, + max_added_moderators, + epoch, + execution_context, + tx, + platform_version, + )?; + // A claim that would pay nobody a credit is refused, as for a declared team; what the + // split leaves over waits in the pot for the next settle. + if settlement.payouts.is_empty() { + return refuse(ContractFeesNothingToClaimError::new(contract_id, pot).into()); + } + + Ok(ConsensusValidationResult::new_with_data( + ContractFeeClaimTransitionAction::from_borrowed_transition_with_payouts( + transition, + epoch_index, + block_info.time_ms, + settlement.payouts, + settlement.settled_action_counts, + ) + .into(), + )) +} + /// What each of `recipients` is paid out of `credits`: an equal share each, `None` when there /// is nobody to pay or the share rounds down to nothing. What the equal split leaves over, less /// than one credit per recipient, stays in the pot for the next claim, so no recipient is diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/state/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/state/v0/mod.rs index 7b2b1bf0768..3746c2b5565 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/state/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/state/v0/mod.rs @@ -290,13 +290,22 @@ impl ContractUserModerationStateTransitionStateValidationV0 for ContractUserMode return refuse(error); } - Ok(ConsensusValidationResult::new_with_data( + let moderation_action = ContractUserModerationTransitionAction::from_borrowed_transition_with_status( self, &status, block_info.time_ms, - ) - .into(), + ); + let moderation_action = moderators.count_for_signer( + moderation_action, + platform.drive, + epoch, + execution_context, + tx, + platform_version, + )?; + Ok(ConsensusValidationResult::new_with_data( + moderation_action.into(), )) } } @@ -489,7 +498,7 @@ fn transform_document_deletion_v0( } }; - Ok(ConsensusValidationResult::new_with_data( + let moderation_action = ContractUserModerationTransitionAction::from_borrowed_transition_with_document_deletion( transition, ContractDocumentDeletionContext { @@ -499,8 +508,17 @@ fn transform_document_deletion_v0( document_hash, replaces_restored_record, }, - ) - .into(), + ); + let moderation_action = moderators.count_for_signer( + moderation_action, + platform.drive, + epoch, + execution_context, + tx, + platform_version, + )?; + Ok(ConsensusValidationResult::new_with_data( + moderation_action.into(), )) } @@ -840,6 +858,47 @@ impl<'a> Moderators<'a> { } } + /// `action`, counted for its signer when a member of a seated team signs a ban, a + /// suspension, a warning or a document deletion: the signer's moderation action count since + /// the moderators pot was last settled is read (one point read, billed) and the action + /// carries it one higher, for Drive to write. What a settle splits the pot's action share + /// by. A reversal (an unban, an unsuspension, a clearing, a restore) counts for nothing, + /// and neither does an action of the moderators a declaration names, who share the pot + /// equally. + #[allow(clippy::too_many_arguments)] + fn count_for_signer( + &self, + action: ContractUserModerationTransitionAction, + drive: &Drive, + epoch: &Epoch, + execution_context: &mut StateTransitionExecutionContext, + tx: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { + let Moderators::Seated { .. } = self else { + return Ok(action); + }; + let counts = matches!( + action.action(), + ContractUserModerationAction::Ban { .. } + | ContractUserModerationAction::Suspend { .. } + | ContractUserModerationAction::Warn { .. } + | ContractUserModerationAction::DeleteDocument { .. } + ); + if !counts { + return Ok(action); + } + let (fee, count) = drive.fetch_contract_moderation_action_count_with_fee( + action.data_contract_id(), + action.moderator_id(), + epoch, + tx, + platform_version, + )?; + execution_context.add_operation(ValidationOperation::PrecalculatedOperation(fee)); + Ok(action.with_moderation_action_count(count.saturating_add(1))) + } + /// Whether a seated team lacks `ability`: on `document_type_name` for a deletion or a /// restore, on every moderated type for a list, which is contract-wide. The moderators a /// declaration names hold every ability the contract backs. diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team.rs index 17f0b53752c..defcf650db5 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team.rs @@ -54,6 +54,8 @@ use drive::util::object_size_info::DocumentInfo::DocumentRefInfo; use drive::util::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; use std::sync::Arc; +mod pot; + const REFERENCED_ENTITY_NOT_FOUND: u32 = 40120; const CONTRACT_MODERATION_ABILITY_NOT_GRANTED: u32 = 41201; const MODERATION_CHARTER_ADDED_MODERATOR_LIMIT_REACHED: u32 = 41202; diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team/pot.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team/pot.rs new file mode 100644 index 00000000000..89670682b32 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team/pot.rs @@ -0,0 +1,437 @@ +//! A seated team's moderators pot (protocol version 14): claimed by the leader or an active +//! member and split by the proposal's reward split, 10/40/50 in these tests (the leader's +//! share, the share split equally between the other members, and the share split by each +//! one's moderation action count, the leader's included), every part rounded down with the +//! remainder left in the pot; and settled the same way before every change of the team, +//! whatever the epoch's claim. + +use super::*; +use dpp::data_contract::document_type::action_fees::ContractFeePotLastClaim; + +const CONTRACT_FEES_ALREADY_CLAIMED_THIS_EPOCH: u32 = 41111; + +/// A claim of the contract's moderators pot by `actor` +async fn claim_by(setup: &Setup, actor: &Actor) -> StateTransition { + ContractFeeClaimTransition::try_from_identity_with_signer( + &actor.identity, + &CRITICAL_KEY_ID, + setup.contract.id(), + ContractFeePot::Moderators, + actor.contract_nonce(), + 0, + &actor.signer, + PlatformVersion::latest(), + None, + ) + .await + .expect("expected to build the claim") +} + +/// A warning of the stranger by `actor`, processed: a counted action +async fn warn_stranger(team: &Team, actor: &Actor, transaction: &Transaction<'_>) { + let setup = &team.setup; + let warn = setup + .moderate(actor, warn_action(setup.stranger.id(), "calm down")) + .await; + assert_success(&setup.process(&warn, transaction)); +} + +/// The contract's moderation action counts +fn counts(team: &Team, transaction: &Transaction) -> BTreeMap { + team.setup + .platform + .drive + .fetch_contract_moderation_action_counts( + team.setup.contract.id(), + 31, + Some(transaction), + PlatformVersion::latest(), + ) + .expect("expected to read the counts") +} + +/// The balances of `actors`, in order +fn balances(setup: &Setup, actors: &[&Actor], transaction: &Transaction) -> Vec { + actors + .iter() + .map(|actor| setup.balance(actor.id(), Some(transaction))) + .collect() +} + +/// What `actor`'s balance moved by since `before` +fn gained(setup: &Setup, actor: &Actor, before: Credits, transaction: &Transaction) -> i128 { + setup.balance(actor.id(), Some(transaction)) as i128 - before as i128 +} + +/// What `execution` cost `actor`: its gas, less the storage refund a deletion gives it +fn net_cost(execution: &StateTransitionExecutionResult, actor: &Actor) -> i128 { + let fees = fees_of(execution); + let refund = fees + .fee_refunds + .calculate_refunds_amount_for_identity(actor.id()) + .unwrap_or_default(); + fees.total_base_fee() as i128 - refund as i128 +} + +/// The last claim of the contract's moderators pot +fn last_claim(team: &Team, transaction: &Transaction) -> Option { + team.setup + .platform + .drive + .fetch_contract_fee_pot( + team.setup.contract.id(), + ContractFeePot::Moderators, + Some(transaction), + PlatformVersion::latest(), + ) + .expect("expected to fetch the moderators pot") + .last_claim +} + +/// Three posts fill the pot with 300_000_000 credits. The leader warns once, the elected member +/// twice and an added member four times: the action share, 150_000_000, goes 1:2:4, which +/// rounds down twice. A member claims for the team: the leader takes 10% and a seventh of the +/// action share, the two members 20% each and their sevenths, and the two credits the split +/// leaves wait in the pot. The counts start over. A joiner the leader did not add, and the +/// interim, claim nothing. +#[tokio::test] +async fn should_split_a_seated_teams_claim_by_its_reward_split_rounding_each_part_down() { + let team = Team::new(InterimModerators::ContractOwner).await; + let setup = &team.setup; + let added = &team.joiners[0]; + team.award(); + // An addition while the pot is empty and nobody acted settles nothing. + team.process_and_commit(&team.addition_of(added).await); + for _ in 0..3 { + team.posted_by(&setup.user).await; + } + let pot = 3 * MODERATORS_PART; + + let transaction = setup.platform.drive.grove.start_transaction(); + for (actor, times) in [(&team.leader, 1), (&team.member, 2), (added, 4)] { + for _ in 0..times { + warn_stranger(&team, actor, &transaction).await; + } + } + assert_eq!( + counts(&team, &transaction), + BTreeMap::from([ + (team.leader.id(), 1), + (team.member.id(), 2), + (added.id(), 4) + ]) + ); + assert_eq!(team.moderators_pot(&transaction), pot); + + // Only the team claims: not a joiner the leader did not add, nor the interim. + for actor in [&team.joiners[1], &setup.owner] { + assert_paid_with_code( + &setup.process(&claim_by(setup, actor).await, &transaction), + CONTRACT_FEE_CLAIM_NOT_ALLOWED, + ); + } + + let before = balances(setup, &[&team.leader, &team.member, added], &transaction); + let claim = claim_by(setup, &team.member).await; + assert!(setup.check_tx(&claim).is_empty()); + let execution = setup.process(&claim, &transaction); + assert_success(&execution); + + let leader_share = 30_000_000; + let equal_each = 60_000_000; + let (leader_actions, member_actions, added_actions) = (21_428_571, 42_857_142, 85_714_285); + assert_eq!( + gained(setup, &team.leader, before[0], &transaction), + (leader_share + leader_actions) as i128 + ); + assert_eq!( + gained(setup, added, before[2], &transaction), + (equal_each + added_actions) as i128 + ); + // The claimant is paid its part and pays the claim's gas. + assert_eq!( + gained(setup, &team.member, before[1], &transaction), + (equal_each + member_actions) as i128 - gas_of(&execution) as i128 + ); + assert_eq!( + team.moderators_pot(&transaction), + pot - leader_share - 2 * equal_each - (leader_actions + member_actions + added_actions) + ); + assert_eq!(team.moderators_pot(&transaction), 2); + assert!(counts(&team, &transaction).is_empty()); + assert_eq!( + last_claim(&team, &transaction).map(|claim| claim.claimant_id), + Some(team.member.id()) + ); +} + +/// Nobody acted since the last settle: the action share is split equally between the leader +/// and the member, as the equal share goes to the member alone. +#[tokio::test] +async fn should_split_the_action_share_equally_when_the_team_did_not_act() { + let team = Team::new(InterimModerators::ContractOwner).await; + let setup = &team.setup; + team.award(); + for _ in 0..3 { + team.posted_by(&setup.user).await; + } + + let transaction = setup.platform.drive.grove.start_transaction(); + assert!(counts(&team, &transaction).is_empty()); + let before = setup.balance(team.leader.id(), Some(&transaction)); + let execution = setup.process(&claim_by(setup, &team.member).await, &transaction); + assert_success(&execution); + // 10% and half of 50% of 300_000_000 to the leader, 40% and the other half to the member. + assert_eq!( + gained(setup, &team.leader, before, &transaction), + 30_000_000 + 75_000_000 + ); + assert_eq!(team.moderators_pot(&transaction), 0); +} + +/// A ban, a suspension, a warning and a document deletion by a member of the seated team count +/// for it; lifting them and a restore do not, and neither do the interim's actions before the +/// seating. Every settle resets the counts: a claim, and a change of the team. +#[tokio::test] +async fn should_count_each_signers_actions_and_reset_the_counts_at_every_settle() { + let team = Team::new(InterimModerators::ContractOwner).await; + let setup = &team.setup; + let post = team.posted_by(&setup.stranger).await; + + // The interim acts before the seating: nothing counts. + let transaction = setup.platform.drive.grove.start_transaction(); + let interim_warn = setup + .moderate(&setup.owner, warn_action(setup.user.id(), "first")) + .await; + assert_success(&setup.process(&interim_warn, &transaction)); + assert!(counts(&team, &transaction).is_empty()); + setup.commit(transaction); + team.award(); + + let transaction = setup.platform.drive.grove.start_transaction(); + let stored = setup + .stored_document(POST, post.id(), Some(&transaction)) + .expect("expected the post to be stored"); + let leader_actions = [ + ban_action(setup.user.id()), + suspend_action(setup.stranger.id(), LATER), + warn_action(setup.stranger.id(), "calm down"), + delete_action(POST, post.id()), + ]; + for (count, action) in (1..).zip(leader_actions) { + let moderation = setup.moderate(&team.leader, action).await; + assert_success(&setup.process(&moderation, &transaction)); + assert_eq!( + counts(&team, &transaction), + BTreeMap::from([(team.leader.id(), count)]) + ); + } + let reversals = [ + unban_action(setup.user.id()), + unsuspend_action(setup.stranger.id()), + clear_warnings_action(setup.stranger.id()), + restore_action(POST, setup.document_bytes(POST, &stored)), + ]; + for action in reversals { + let moderation = setup.moderate(&team.member, action).await; + assert_success(&setup.process(&moderation, &transaction)); + } + warn_stranger(&team, &team.member, &transaction).await; + assert_eq!( + counts(&team, &transaction), + BTreeMap::from([(team.leader.id(), 4), (team.member.id(), 1)]) + ); + + // A claim resets them. + assert_success(&setup.process(&claim_by(setup, &team.leader).await, &transaction)); + assert!(counts(&team, &transaction).is_empty()); + + // So does a change of the team. + warn_stranger(&team, &team.member, &transaction).await; + warn_stranger(&team, &team.member, &transaction).await; + assert_eq!( + counts(&team, &transaction), + BTreeMap::from([(team.member.id(), 2)]) + ); + assert_success(&setup.process(&team.addition_of(&team.joiners[0]).await, &transaction)); + assert!(counts(&team, &transaction).is_empty()); +} + +/// Before the leader adds a member, the pot is paid out to the team as it was: the new member +/// gets nothing of what was earned before it came, and the counts start over. The settle is no +/// claim: the last claim stays as it was and the team still claims in the same epoch. +#[tokio::test] +async fn should_settle_the_pot_to_the_team_as_it_was_before_an_addition() { + let team = Team::new(InterimModerators::ContractOwner).await; + let setup = &team.setup; + let added = &team.joiners[0]; + team.award(); + team.posted_by(&setup.user).await; + + let transaction = setup.platform.drive.grove.start_transaction(); + warn_stranger(&team, &team.member, &transaction).await; + let before = balances(setup, &[&team.leader, &team.member, added], &transaction); + let execution = setup.process(&team.addition_of(added).await, &transaction); + assert_success(&execution); + // 100_000_000: 10% to the leader; the member's 40% and the whole action share, its the + // only count. + assert_eq!( + gained(setup, &team.member, before[1], &transaction), + 90_000_000 + ); + assert_eq!( + gained(setup, &team.leader, before[0], &transaction), + 10_000_000 - gas_of(&execution) as i128 + ); + assert_eq!(gained(setup, added, before[2], &transaction), 0); + assert_eq!(team.moderators_pot(&transaction), 0); + assert!(counts(&team, &transaction).is_empty()); + assert_eq!(last_claim(&team, &transaction), None); + setup.commit(transaction); + + // The added member shares what is earned from now on, and the team claims in the same + // epoch the settle ran in. + team.posted_by(&setup.user).await; + let transaction = setup.platform.drive.grove.start_transaction(); + let before = setup.balance(added.id(), Some(&transaction)); + assert_success(&setup.process(&claim_by(setup, &team.leader).await, &transaction)); + // 20% and a third of 50% of 100_000_000. + assert_eq!( + gained(setup, added, before, &transaction), + 20_000_000 + 16_666_666 + ); +} + +/// Before the leader removes a member, and before it undoes a removal or an addition by +/// deleting it, the pot is paid out to the team as it was, even in an epoch the team already +/// claimed in: the removed member is paid for what it did, a member coming back gets nothing +/// of what was earned while it was away, and one whose addition is taken back is paid first. +#[tokio::test] +async fn should_settle_the_pot_before_a_removal_and_before_a_change_is_undone() { + let team = Team::new(InterimModerators::ContractOwner).await; + let setup = &team.setup; + let added = &team.joiners[0]; + team.award(); + team.posted_by(&setup.user).await; + + // The team claims in this epoch; a change still settles. + let transaction = setup.platform.drive.grove.start_transaction(); + assert_success(&setup.process(&claim_by(setup, &team.leader).await, &transaction)); + setup.commit(transaction); + team.posted_by(&setup.user).await; + + let transaction = setup.platform.drive.grove.start_transaction(); + assert_paid_with_code( + &setup.process(&claim_by(setup, &team.member).await, &transaction), + CONTRACT_FEES_ALREADY_CLAIMED_THIS_EPOCH, + ); + warn_stranger(&team, &team.member, &transaction).await; + let before = balances(setup, &[&team.leader, &team.member], &transaction); + let (removal, removing) = team.removed(&team.member).await; + let execution = setup.process(&removing, &transaction); + assert_success(&execution); + assert_eq!( + gained(setup, &team.member, before[1], &transaction), + 90_000_000 + ); + assert_eq!( + gained(setup, &team.leader, before[0], &transaction), + 10_000_000 - gas_of(&execution) as i128 + ); + assert_eq!(team.moderators_pot(&transaction), 0); + assert!(counts(&team, &transaction).is_empty()); + setup.commit(transaction); + + // Earned while the member was away: the leader, alone on the team, takes it all when the + // removal is undone. + team.posted_by(&setup.user).await; + let transaction = setup.platform.drive.grove.start_transaction(); + let before = balances(setup, &[&team.leader, &team.member], &transaction); + let execution = setup.process( + &team + .undoing(REMOVED_MODERATOR_DOCUMENT_TYPE_NAME, removal) + .await, + &transaction, + ); + assert_success(&execution); + // The deletion also refunds the leader the storage of its removal. + assert_eq!( + gained(setup, &team.leader, before[0], &transaction), + MODERATORS_PART as i128 - net_cost(&execution, &team.leader) + ); + assert_eq!(gained(setup, &team.member, before[1], &transaction), 0); + setup.commit(transaction); + + // An added member whose addition is taken back is paid its part first: with nobody + // acting, a third of 50% and half of 40% of 100_000_000. + let (addition, adding) = team.added(added).await; + team.process_and_commit(&adding); + team.posted_by(&setup.user).await; + let transaction = setup.platform.drive.grove.start_transaction(); + let before = balances(setup, &[&team.member, added], &transaction); + assert_success( + &setup.process( + &team + .undoing(ADDED_MODERATOR_DOCUMENT_TYPE_NAME, addition) + .await, + &transaction, + ), + ); + for (actor, before) in [(&team.member, before[0]), (added, before[1])] { + assert_eq!( + gained(setup, actor, before, &transaction), + 20_000_000 + 16_666_666 + ); + } + // What the thirds leave waits in the pot. + assert_eq!(team.moderators_pot(&transaction), 2); +} + +/// The proof of a seated team's claim shows the pot with its last claim and the claimant's +/// balance: the contract does not say which team a seated charter pays, so neither the prover +/// nor a client verifying against the contract could name the others. +#[tokio::test] +async fn should_prove_a_seated_teams_claim_with_the_claimants_balance() { + let team = Team::new(InterimModerators::ContractOwner).await; + let setup = &team.setup; + team.award(); + team.posted_by(&setup.user).await; + let claim = claim_by(setup, &team.member).await; + team.process_and_commit(&claim); + + let platform_version = PlatformVersion::latest(); + let proof = setup + .platform + .drive + .prove_state_transition(&claim, None, platform_version) + .expect("expected to prove the state transition") + .into_data() + .expect("expected proof bytes"); + let contract = setup.contract.clone(); + let (_, outcome) = Drive::verify_state_transition_was_executed_with_proof( + &claim, + &BlockInfo::default(), + &proof, + &|id| Ok((*id == contract.id()).then(|| Arc::new(contract.clone()))), + platform_version, + ) + .expect("expected the proof to verify"); + let StateTransitionProofResult::VerifiedContractFeeClaim( + contract_id, + pot, + last_claim, + remaining, + balances, + ) = outcome.into_result() + else { + panic!("expected a contract fee claim result"); + }; + assert_eq!(contract_id, setup.contract.id()); + assert_eq!(pot, ContractFeePot::Moderators); + assert_eq!(last_claim.claimant_id, team.member.id()); + assert_eq!(remaining, 0); + assert_eq!( + balances, + BTreeMap::from([(team.member.id(), setup.balance(team.member.id(), None))]) + ); +} diff --git a/packages/rs-drive/grovedb-structure.json b/packages/rs-drive/grovedb-structure.json index a2845ab71a4..fda302fe679 100644 --- a/packages/rs-drive/grovedb-structure.json +++ b/packages/rs-drive/grovedb-structure.json @@ -3047,6 +3047,52 @@ "description": "The last claim of the contract's owner fee pot: the epoch and the block time it was paid out in, and the identity that claimed, which is the contract owner. Written by the first claim and replaced by every later one; a pot is claimed at most once per epoch.", "children": [] }, + { + "id": "contracts.contract.other.moderation_action_counts", + "key": { + "type": "fixed", + "hex": "30", + "label": "ModerationActionCounts", + "constant": "CONTRACT_MODERATION_ACTION_COUNTS_KEY" + }, + "kinds": [ + "Tree" + ], + "flags": [ + "EpochOwned", + "None" + ], + "flags_note": "The contract's flags. Only the system contracts the upgrades to protocol versions 6, 9 and 13 registered carry them (wallet utils, token history, keyword search and document history), owned by the all-zero system owner in the epoch of the upgrade. Genesis, state transitions and later upgrades write none.", + "since": 14, + "presence": "lazy", + "source": "packages/rs-drive/src/drive/contract/paths.rs", + "description": "How many moderation actions each member of the contract's seated moderation team signed since its moderators pot was last settled. Created with a contract that declares elected moderation. Read by the team's actions and by a settle, never by a document transition, so it sorts below the version item.", + "children": [ + { + "id": "contracts.contract.other.moderation_action_counts.member", + "key": { + "type": "dynamic", + "name": "identity_id", + "matcher": { + "type": "len", + "len": 32 + }, + "encoding": "identifier32", + "description": "The member of the seated team" + }, + "kinds": [ + "Item" + ], + "flags_note": "None: the member whose action writes the count pays for it, and the settle that deletes it refunds nobody.", + "value": "u32 big endian", + "since": 14, + "presence": "always", + "source": "packages/rs-drive/src/drive/contract/paths.rs", + "description": "The member's count of bans, suspensions, warnings and document deletions since the last settle. Rewritten one higher by each; every settle, a claim or a change of the team, pays the pot's action share by the counts and deletes them.", + "children": [] + } + ] + }, { "id": "contracts.contract.other.version", "key": { diff --git a/packages/rs-drive/src/drive/contract/moderation/action_count_tests.rs b/packages/rs-drive/src/drive/contract/moderation/action_count_tests.rs new file mode 100644 index 00000000000..5a8faa09cb7 --- /dev/null +++ b/packages/rs-drive/src/drive/contract/moderation/action_count_tests.rs @@ -0,0 +1,280 @@ +//! The moderation action counts of an elected contract's seated team (`[64, id, 2, 48]`). + +use crate::drive::contract::paths::{ + contract_other_path, CONTRACT_BANLIST_KEY, CONTRACT_MODERATION_ACTION_COUNTS_KEY, + CONTRACT_OTHER_KEY, CONTRACT_VERSION_KEY, +}; +use crate::drive::{Drive, RootTree}; +use crate::util::batch::{ContractModerationOperationType, DriveOperation}; +use crate::util::grove_operations::DirectQueryType; +use crate::util::test_helpers::setup::setup_drive_with_initial_state_structure; +use dpp::block::block_info::BlockInfo; +use dpp::block::epoch::Epoch; +use dpp::data_contract::accessors::v0::{DataContractV0Getters, DataContractV0Setters}; +use dpp::data_contract::config::moderation::{ + ContractModerationConfig, ContractModerators, ElectedModerators, InterimModerators, + ModerationAbility, DEFAULT_ELECTION_WINDOW_SECONDS, +}; +use dpp::data_contract::DataContract; +use dpp::identifier::Identifier; +use dpp::tests::fixtures::get_data_contract_fixture; +use dpp::version::PlatformVersion; +use grovedb::Element; +use std::collections::{BTreeMap, BTreeSet}; + +fn member(seed: u8) -> Identifier { + Identifier::from([seed; 32]) +} + +/// A contract keeping the lists given, whose moderators are elected when `elected`, the owner +/// otherwise +fn contract_keeping( + banlist: bool, + suspensions: bool, + warnings: bool, + elected: bool, +) -> DataContract { + let platform_version = PlatformVersion::latest(); + let mut contract = + get_data_contract_fixture(None, 0, platform_version.protocol_version).data_contract_owned(); + let moderators = if elected { + ContractModerators::Elected(Box::new(ElectedModerators { + join_window: DEFAULT_ELECTION_WINDOW_SECONDS, + vote_window: DEFAULT_ELECTION_WINDOW_SECONDS, + challenge_cool_down: 1_209_600, + election_delay: None, + max_added_moderators: 0, + moderated_document_types: BTreeMap::from([( + "niceDocument".to_string(), + BTreeSet::from([ModerationAbility::Ban]), + )]), + interim: InterimModerators::NotYetUsable, + owner_protected: false, + })) + } else { + ContractModerators::ContractOwner + }; + contract.set_config(contract.config().clone().with_moderation(Some( + ContractModerationConfig { + banlist, + suspensions, + warnings, + moderators, + }, + ))); + contract +} + +fn elected_contract(drive: &Drive, platform_version: &PlatformVersion) -> DataContract { + let contract = contract_keeping(true, false, false, true); + drive + .insert_contract( + &contract, + BlockInfo::default(), + true, + None, + platform_version, + ) + .expect("expected to insert the contract"); + contract +} + +fn has_counts_tree(drive: &Drive, contract_id: Identifier) -> bool { + drive + .grove_has_raw( + (&contract_other_path(contract_id.as_slice())).into(), + &[CONTRACT_MODERATION_ACTION_COUNTS_KEY], + DirectQueryType::StatefulDirectQuery, + None, + &mut vec![], + &PlatformVersion::latest().drive, + ) + .expect("expected to query the other tree") +} + +fn set_count( + identity_id: Identifier, + count: u32, + contract_id: Identifier, +) -> DriveOperation<'static> { + DriveOperation::ContractModerationOperation(ContractModerationOperationType::SetActionCount { + contract_id, + identity_id, + count, + }) +} + +fn apply( + drive: &Drive, + operations: Vec, + apply: bool, +) -> dpp::fee::fee_result::FeeResult { + drive + .apply_drive_operations( + operations, + apply, + &BlockInfo::default(), + None, + PlatformVersion::latest(), + None, + ) + .expect("expected to apply the operations") +} + +#[test] +fn should_create_the_action_counts_tree_with_an_elected_contract_only() { + let platform_version = PlatformVersion::latest(); + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); + let elected = elected_contract(&drive, platform_version); + assert!(has_counts_tree(&drive, elected.id())); + + let owned = contract_keeping(true, false, false, false); + let mut owned_contract = owned; + owned_contract.set_id(member(0x77)); + drive + .insert_contract( + &owned_contract, + BlockInfo::default(), + true, + None, + platform_version, + ) + .expect("expected to insert the contract"); + assert!(!has_counts_tree(&drive, owned_contract.id())); +} + +#[test] +fn should_write_read_and_reset_the_action_counts() { + let platform_version = PlatformVersion::latest(); + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); + let contract_id = elected_contract(&drive, platform_version).id(); + + assert!(drive + .fetch_contract_moderation_action_counts(contract_id, 31, None, platform_version) + .expect("expected to read the counts") + .is_empty()); + + // The first count of a member is an insert, estimated as one. + let estimated = apply(&drive, vec![set_count(member(1), 1, contract_id)], false); + let applied = apply(&drive, vec![set_count(member(1), 1, contract_id)], true); + assert_eq!(estimated.storage_fee, applied.storage_fee); + assert!(estimated.processing_fee >= applied.processing_fee); + // A later one replaces it with the same size: no storage. + let replaced = apply(&drive, vec![set_count(member(1), 2, contract_id)], true); + assert_eq!(replaced.storage_fee, 0); + apply(&drive, vec![set_count(member(2), 5, contract_id)], true); + + let epoch = Epoch::new(0).expect("epoch"); + let (fee, counts) = drive + .fetch_contract_moderation_action_counts_with_fee( + contract_id, + 31, + &epoch, + None, + platform_version, + ) + .expect("expected to read the counts"); + assert!(fee.processing_fee > 0); + assert_eq!(counts, BTreeMap::from([(member(1), 2), (member(2), 5)])); + let (_, count) = drive + .fetch_contract_moderation_action_count_with_fee( + contract_id, + member(2), + &epoch, + None, + platform_version, + ) + .expect("expected to read a count"); + assert_eq!(count, 5); + let (_, count) = drive + .fetch_contract_moderation_action_count_with_fee( + contract_id, + member(3), + &epoch, + None, + platform_version, + ) + .expect("expected to read a count"); + assert_eq!(count, 0, "a member that did not act has no count"); + + // The limit bounds the read. + assert_eq!( + drive + .fetch_contract_moderation_action_counts(contract_id, 1, None, platform_version) + .expect("expected to read the counts") + .len(), + 1 + ); + + // A settle deletes them, refunding nobody: they carry no storage flags. + let reset = DriveOperation::ContractModerationOperation( + ContractModerationOperationType::RemoveActionCounts { + contract_id, + identity_ids: vec![member(1), member(2)], + }, + ); + let estimated = apply(&drive, vec![reset.clone()], false); + let applied = apply(&drive, vec![reset], true); + assert!(estimated.processing_fee >= applied.processing_fee); + assert!(applied.fee_refunds.0.is_empty()); + assert!(drive + .fetch_contract_moderation_action_counts(contract_id, 31, None, platform_version) + .expect("expected to read the counts") + .is_empty()); +} + +/// The root key of the Merk at `path`/`key`, read from the tree element that points at it. +fn merk_root_key(drive: &Drive, path: &[&[u8]], key: &[u8]) -> Option> { + let platform_version = PlatformVersion::latest(); + let element = drive + .grove + .get_raw( + path.into(), + key, + None, + &platform_version.drive.grove_version, + ) + .unwrap() + .expect("expected the tree element"); + match element { + Element::Tree(root_key, _) => root_key, + other => panic!("expected a tree, got {other:?}"), + } +} + +/// The counts sort below the version item, so that created with two or three lists they leave +/// the banlist on top; with the banlist alone the version item is. +#[test] +fn should_keep_the_banlist_on_top_of_an_elected_contracts_other_tree_with_two_or_more_lists() { + let platform_version = PlatformVersion::latest(); + // (banlist, suspensions, warnings) -> the key on top of the contract's other tree + for (banlist, suspensions, warnings, top_of_other) in [ + (true, false, false, CONTRACT_VERSION_KEY), + (true, true, false, CONTRACT_BANLIST_KEY), + (true, false, true, CONTRACT_BANLIST_KEY), + // Without the counts, the one combination where the banlist sat a level down. + (true, true, true, CONTRACT_BANLIST_KEY), + ] { + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); + let contract = contract_keeping(banlist, suspensions, warnings, true); + drive + .insert_contract( + &contract, + BlockInfo::default(), + true, + None, + platform_version, + ) + .expect("expected to insert the contract"); + let contracts_root: &[u8] = Into::<&[u8; 1]>::into(RootTree::DataContractDocuments); + assert_eq!( + merk_root_key( + &drive, + &[contracts_root, contract.id().as_slice()], + &[CONTRACT_OTHER_KEY] + ), + Some(vec![top_of_other]), + "banlist {banlist}, suspensions {suspensions}, warnings {warnings}" + ); + } +} diff --git a/packages/rs-drive/src/drive/contract/moderation/estimated_costs/mod.rs b/packages/rs-drive/src/drive/contract/moderation/estimated_costs/mod.rs index 14b0b523864..4e8037975a2 100644 --- a/packages/rs-drive/src/drive/contract/moderation/estimated_costs/mod.rs +++ b/packages/rs-drive/src/drive/contract/moderation/estimated_costs/mod.rs @@ -64,6 +64,33 @@ impl Drive { } } + /// Adds the estimated layer information for writing or deleting moderation action counts + /// of an elected contract: the levels up to the contract, the contract's subtree and the + /// tree of the counts. + pub(crate) fn add_estimation_costs_for_contract_moderation_action_counts( + contract_id: [u8; 32], + estimated_costs_only_with_layer_info: &mut HashMap, + drive_version: &DriveVersion, + ) -> Result<(), Error> { + match drive_version + .methods + .contract + .moderation + .add_estimation_costs_for_contract_moderation_action_counts + { + 0 => Self::add_estimation_costs_for_contract_moderation_action_counts_v0( + contract_id, + estimated_costs_only_with_layer_info, + drive_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "add_estimation_costs_for_contract_moderation_action_counts".to_string(), + known_versions: vec![0], + received: version, + })), + } + } + /// Adds the layers a contract insertion or update touches when it creates the trees of /// the document removal records. pub(crate) fn add_estimation_costs_for_contract_document_removal_trees( diff --git a/packages/rs-drive/src/drive/contract/moderation/estimated_costs/v0/mod.rs b/packages/rs-drive/src/drive/contract/moderation/estimated_costs/v0/mod.rs index db23a92a7bb..fb785a700b7 100644 --- a/packages/rs-drive/src/drive/contract/moderation/estimated_costs/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/moderation/estimated_costs/v0/mod.rs @@ -1,12 +1,13 @@ use crate::drive::constants::{ ESTIMATED_AVERAGE_DOCUMENT_TYPE_NAME_SIZE, ESTIMATED_DOCUMENT_TYPES_DELETABLE_BY_MODERATORS, }; +use crate::drive::contract::moderation::types::CONTRACT_MODERATION_ACTION_COUNT_SIZE; use crate::drive::contract::moderation::types::{ estimated_document_removal_value_size, estimated_entry_value_size, }; use crate::drive::contract::paths::{ contract_document_removals_path, contract_document_type_removals_path, - contract_moderation_list_path, + contract_moderation_action_counts_path, contract_moderation_list_path, }; use crate::drive::Drive; use crate::error::Error; @@ -15,7 +16,7 @@ use crate::util::type_constants::DEFAULT_HASH_SIZE_U8; use dpp::data_contract::config::moderation::ContractModerationList; use dpp::version::drive_versions::DriveVersion; use grovedb::batch::KeyInfoPath; -use grovedb::EstimatedLayerCount::{ApproximateElements, PotentiallyAtMaxElements}; +use grovedb::EstimatedLayerCount::{ApproximateElements, EstimatedLevel, PotentiallyAtMaxElements}; use grovedb::EstimatedLayerSizes::{AllItems, AllSubtrees}; use grovedb::EstimatedSumTrees::NoSumTrees; use grovedb::{EstimatedLayerInformation, TreeType}; @@ -73,6 +74,37 @@ impl Drive { Ok(()) } + pub(super) fn add_estimation_costs_for_contract_moderation_action_counts_v0( + contract_id: [u8; 32], + estimated_costs_only_with_layer_info: &mut HashMap, + drive_version: &DriveVersion, + ) -> Result<(), Error> { + Self::add_estimation_costs_for_contract_moderation_trees_v0( + contract_id, + estimated_costs_only_with_layer_info, + drive_version, + )?; + + // The counts (`[64, id, 2, 48]`): one item per member of the seated team who acted + // since the last settle, keyed by identity id, a four-byte count without storage flags. + // A team is at most the leader, the elected members and the additions, so the tree is + // at most a few levels deep. + estimated_costs_only_with_layer_info.insert( + KeyInfoPath::from_known_path(contract_moderation_action_counts_path(&contract_id)), + EstimatedLayerInformation { + tree_type: TreeType::NormalTree, + estimated_layer_count: EstimatedLevel(4, false), + estimated_layer_sizes: AllItems( + DEFAULT_HASH_SIZE_U8, + CONTRACT_MODERATION_ACTION_COUNT_SIZE as u32, + None, + ), + }, + ); + + Ok(()) + } + pub(super) fn add_estimation_costs_for_contract_document_removal_trees_v0( contract_id: [u8; 32], estimated_costs_only_with_layer_info: &mut HashMap, diff --git a/packages/rs-drive/src/drive/contract/moderation/fetch_contract_moderation_action_counts/mod.rs b/packages/rs-drive/src/drive/contract/moderation/fetch_contract_moderation_action_counts/mod.rs new file mode 100644 index 00000000000..defccf7ab3d --- /dev/null +++ b/packages/rs-drive/src/drive/contract/moderation/fetch_contract_moderation_action_counts/mod.rs @@ -0,0 +1,173 @@ +mod v0; + +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use dpp::block::epoch::Epoch; +use dpp::fee::fee_result::FeeResult; +use dpp::identifier::Identifier; +use dpp::version::PlatformVersion; +use grovedb::TransactionArg; +use std::collections::BTreeMap; + +impl Drive { + /// Reads the moderation action counts of the elected contract `contract_id`: for each + /// member of the seated team who signed a counted moderation action since the moderators + /// pot was last settled, how many. At most `limit` of them, in identity id order. + /// + /// # Parameters + /// + /// * `contract_id`: The elected contract. + /// * `limit`: At most this many counts. + /// * `transaction`: The GroveDB transaction. + /// * `platform_version`: The platform version. + /// + /// # Returns + /// + /// * `Ok(BTreeMap)` with the counts. + /// * `Err(Error)` when the version is unknown, a read fails or a count is malformed. + pub fn fetch_contract_moderation_action_counts( + &self, + contract_id: Identifier, + limit: u16, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + match platform_version + .drive + .methods + .contract + .moderation + .fetch_contract_moderation_action_counts + { + 0 => self.fetch_contract_moderation_action_counts_add_to_operations_v0( + contract_id, + limit, + transaction, + &mut vec![], + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "fetch_contract_moderation_action_counts".to_string(), + known_versions: vec![0], + received: version, + })), + } + } + + /// [`Drive::fetch_contract_moderation_action_counts`] with the fee of the read, so that + /// consensus validation can bill it. + /// + /// # Parameters + /// + /// * `contract_id`: The elected contract. + /// * `limit`: At most this many counts. + /// * `epoch`: The epoch the fee is priced for. + /// * `transaction`: The GroveDB transaction. + /// * `platform_version`: The platform version. + /// + /// # Returns + /// + /// * `Ok((FeeResult, BTreeMap))` with the fee and the counts. + /// * `Err(Error)` when the version is unknown, a read fails or a count is malformed. + pub fn fetch_contract_moderation_action_counts_with_fee( + &self, + contract_id: Identifier, + limit: u16, + epoch: &Epoch, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result<(FeeResult, BTreeMap), Error> { + match platform_version + .drive + .methods + .contract + .moderation + .fetch_contract_moderation_action_counts + { + 0 => { + let mut drive_operations: Vec = vec![]; + let counts = self.fetch_contract_moderation_action_counts_add_to_operations_v0( + contract_id, + limit, + transaction, + &mut drive_operations, + platform_version, + )?; + let fee = Drive::calculate_fee( + None, + Some(drive_operations), + epoch, + self.config.epochs_per_era, + platform_version, + None, + )?; + Ok((fee, counts)) + } + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "fetch_contract_moderation_action_counts_with_fee".to_string(), + known_versions: vec![0], + received: version, + })), + } + } + + /// Reads one member's moderation action count on the elected contract `contract_id`, with + /// the fee of the read: 0 when the member signed no counted action since the moderators pot + /// was last settled. + /// + /// # Parameters + /// + /// * `contract_id`: The elected contract. + /// * `identity_id`: The member. + /// * `epoch`: The epoch the fee is priced for. + /// * `transaction`: The GroveDB transaction. + /// * `platform_version`: The platform version. + /// + /// # Returns + /// + /// * `Ok((FeeResult, u32))` with the fee and the count. + /// * `Err(Error)` when the version is unknown, the read fails or the count is malformed. + pub fn fetch_contract_moderation_action_count_with_fee( + &self, + contract_id: Identifier, + identity_id: Identifier, + epoch: &Epoch, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result<(FeeResult, u32), Error> { + match platform_version + .drive + .methods + .contract + .moderation + .fetch_contract_moderation_action_counts + { + 0 => { + let mut drive_operations: Vec = vec![]; + let count = self.fetch_contract_moderation_action_count_add_to_operations_v0( + contract_id, + identity_id, + transaction, + &mut drive_operations, + platform_version, + )?; + let fee = Drive::calculate_fee( + None, + Some(drive_operations), + epoch, + self.config.epochs_per_era, + platform_version, + None, + )?; + Ok((fee, count)) + } + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "fetch_contract_moderation_action_count_with_fee".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/drive/contract/moderation/fetch_contract_moderation_action_counts/v0/mod.rs b/packages/rs-drive/src/drive/contract/moderation/fetch_contract_moderation_action_counts/v0/mod.rs new file mode 100644 index 00000000000..abeefb736ad --- /dev/null +++ b/packages/rs-drive/src/drive/contract/moderation/fetch_contract_moderation_action_counts/v0/mod.rs @@ -0,0 +1,97 @@ +use crate::drive::contract::moderation::types::decode_moderation_action_count; +use crate::drive::contract::paths::{ + contract_moderation_action_counts_path, contract_moderation_action_counts_path_vec, +}; +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::query::{Query, QueryItem}; +use crate::util::grove_operations::DirectQueryType; +use dpp::identifier::Identifier; +use dpp::version::PlatformVersion; +use grovedb::query_result_type::QueryResultType; +use grovedb::{Element, PathQuery, SizedQuery, TransactionArg}; +use std::collections::BTreeMap; +use std::ops::RangeFull; + +impl Drive { + #[inline(always)] + pub(super) fn fetch_contract_moderation_action_counts_add_to_operations_v0( + &self, + contract_id: Identifier, + limit: u16, + transaction: TransactionArg, + drive_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let mut query = Query::new_with_direction(true); + query.insert_item(QueryItem::RangeFull(RangeFull)); + let path_query = PathQuery { + path: contract_moderation_action_counts_path_vec(contract_id.as_slice()), + query: SizedQuery { + query, + limit: Some(limit), + offset: None, + }, + }; + let (results, _) = self.grove_get_raw_path_query( + &path_query, + transaction, + QueryResultType::QueryKeyElementPairResultType, + drive_operations, + &platform_version.drive, + )?; + results + .to_key_elements() + .into_iter() + .map(|(key, element)| { + let malformed = |description: String| { + Error::Drive(DriveError::CorruptedDriveState(format!( + "moderation action count of contract {} is malformed: {}", + contract_id, description + ))) + }; + let identity_id = Identifier::from_bytes(&key) + .map_err(|_| malformed(format!("key {:?} is not an identity id", key)))?; + let Element::Item(value, _) = element else { + return Err(malformed("not an item".to_string())); + }; + Ok(( + identity_id, + decode_moderation_action_count(&value).map_err(malformed)?, + )) + }) + .collect() + } + + #[inline(always)] + pub(super) fn fetch_contract_moderation_action_count_add_to_operations_v0( + &self, + contract_id: Identifier, + identity_id: Identifier, + transaction: TransactionArg, + drive_operations: &mut Vec, + platform_version: &PlatformVersion, + ) -> Result { + let path = contract_moderation_action_counts_path(contract_id.as_slice()); + self.grove_get_raw_optional_item( + (&path).into(), + identity_id.as_slice(), + DirectQueryType::StatefulDirectQuery, + transaction, + drive_operations, + &platform_version.drive, + )? + .map(|value| { + decode_moderation_action_count(&value).map_err(|description| { + Error::Drive(DriveError::CorruptedDriveState(format!( + "moderation action count of {} on contract {} is malformed: {}", + identity_id, contract_id, description + ))) + }) + }) + .transpose() + .map(Option::unwrap_or_default) + } +} diff --git a/packages/rs-drive/src/drive/contract/moderation/insert_contract_moderation_trees/mod.rs b/packages/rs-drive/src/drive/contract/moderation/insert_contract_moderation_trees/mod.rs index d0f97958a25..9b666a5bedd 100644 --- a/packages/rs-drive/src/drive/contract/moderation/insert_contract_moderation_trees/mod.rs +++ b/packages/rs-drive/src/drive/contract/moderation/insert_contract_moderation_trees/mod.rs @@ -14,8 +14,9 @@ use std::collections::HashMap; impl Drive { /// Adds the operations that create the moderation list trees a contract's config declares /// and that do not exist yet: the banlist under key `128`, the suspension list under key - /// `192`, the warning list under key `224`, all in the contract's other tree - /// (`[64, id, 2]`). Called by the contract insertion + /// `192`, the warning list under key `224`, and for a contract that declares elected + /// moderation the tree of its team's moderation action counts under key `48`, all in the + /// contract's other tree (`[64, id, 2]`). Called by the contract insertion /// only: the lists a contract keeps are fixed when it is /// created, so a contract update never adds one. /// diff --git a/packages/rs-drive/src/drive/contract/moderation/insert_contract_moderation_trees/v0/mod.rs b/packages/rs-drive/src/drive/contract/moderation/insert_contract_moderation_trees/v0/mod.rs index 9848da1e609..f78e6915baf 100644 --- a/packages/rs-drive/src/drive/contract/moderation/insert_contract_moderation_trees/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/moderation/insert_contract_moderation_trees/v0/mod.rs @@ -1,4 +1,6 @@ -use crate::drive::contract::paths::{contract_moderation_list_key, contract_other_path}; +use crate::drive::contract::paths::{ + contract_moderation_list_key, contract_other_path, CONTRACT_MODERATION_ACTION_COUNTS_KEY, +}; use crate::drive::Drive; use crate::error::Error; use crate::fees::op::LowLevelDriveOperation; @@ -49,6 +51,19 @@ impl Drive { )?; } + // An elected contract's seated team counts its moderation actions between two settles + // of the moderators pot. Elected moderation is declared at creation and never entered + // by an update, so the tree is created here, with the lists, and never lazily. + if moderation.moderators.elected().is_some() { + self.batch_insert_empty_tree( + contract_other_path, + DriveKeyInfo::KeyRef(&[CONTRACT_MODERATION_ACTION_COUNTS_KEY]), + storage_flags, + batch_operations, + &platform_version.drive, + )?; + } + Ok(()) } } diff --git a/packages/rs-drive/src/drive/contract/moderation/mod.rs b/packages/rs-drive/src/drive/contract/moderation/mod.rs index 6b90422dbf2..e187d9edd3e 100644 --- a/packages/rs-drive/src/drive/contract/moderation/mod.rs +++ b/packages/rs-drive/src/drive/contract/moderation/mod.rs @@ -51,6 +51,8 @@ mod estimated_costs; #[cfg(feature = "server")] mod fetch_contract_document_removals; #[cfg(feature = "server")] +mod fetch_contract_moderation_action_counts; +#[cfg(feature = "server")] mod fetch_contract_moderation_entries; #[cfg(feature = "server")] mod fetch_contract_moderation_status; @@ -68,12 +70,19 @@ mod queries; #[cfg(feature = "server")] mod remove_contract_ban; #[cfg(feature = "server")] +mod remove_contract_moderation_action_counts; +#[cfg(feature = "server")] mod remove_contract_suspension; #[cfg(feature = "server")] mod remove_contract_warnings; +#[cfg(feature = "server")] +mod set_contract_moderation_action_count; /// Query and result types shared by the fetch and verify sides. pub mod types; +#[cfg(test)] +#[cfg(feature = "server")] +mod action_count_tests; #[cfg(test)] #[cfg(feature = "server")] mod document_removal_tests; diff --git a/packages/rs-drive/src/drive/contract/moderation/remove_contract_moderation_action_counts/mod.rs b/packages/rs-drive/src/drive/contract/moderation/remove_contract_moderation_action_counts/mod.rs new file mode 100644 index 00000000000..ca74fe796bc --- /dev/null +++ b/packages/rs-drive/src/drive/contract/moderation/remove_contract_moderation_action_counts/mod.rs @@ -0,0 +1,62 @@ +mod v0; + +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use dpp::identifier::Identifier; +use dpp::version::PlatformVersion; +use grovedb::batch::KeyInfoPath; +use grovedb::{EstimatedLayerInformation, TransactionArg}; +use std::collections::HashMap; + +impl Drive { + /// The operations that delete the moderation action counts of `identity_ids` on the + /// elected contract `contract_id`: the reset a settle of the moderators pot makes after + /// paying the pot out by them. Each count must exist. With layer information the + /// operations are built for estimation only. + /// + /// # Parameters + /// + /// * `contract_id`: The elected contract. + /// * `identity_ids`: The members whose counts go. + /// * `estimated_costs_only_with_layer_info`: The estimation map for a dry run. + /// * `transaction`: The GroveDB transaction. + /// * `platform_version`: The platform version. + /// + /// # Returns + /// + /// * `Ok(Vec)` with the operations. + /// * `Err(Error)` when the version is unknown or GroveDB refuses an operation. + pub fn remove_contract_moderation_action_counts_operations( + &self, + contract_id: Identifier, + identity_ids: &[Identifier], + estimated_costs_only_with_layer_info: &mut Option< + HashMap, + >, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + match platform_version + .drive + .methods + .contract + .moderation + .remove_contract_moderation_action_counts + { + 0 => self.remove_contract_moderation_action_counts_operations_v0( + contract_id, + identity_ids, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "remove_contract_moderation_action_counts_operations".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/drive/contract/moderation/remove_contract_moderation_action_counts/v0/mod.rs b/packages/rs-drive/src/drive/contract/moderation/remove_contract_moderation_action_counts/v0/mod.rs new file mode 100644 index 00000000000..d1c0926214c --- /dev/null +++ b/packages/rs-drive/src/drive/contract/moderation/remove_contract_moderation_action_counts/v0/mod.rs @@ -0,0 +1,63 @@ +use crate::drive::contract::moderation::types::CONTRACT_MODERATION_ACTION_COUNT_SIZE; +use crate::drive::contract::paths::contract_moderation_action_counts_path; +use crate::drive::Drive; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::util::grove_operations::BatchDeleteApplyType; +use crate::util::type_constants::DEFAULT_HASH_SIZE_U32; +use dpp::identifier::Identifier; +use dpp::version::PlatformVersion; +use grovedb::batch::KeyInfoPath; +use grovedb::{EstimatedLayerInformation, TransactionArg}; +use grovedb::{MaybeTree, TreeType}; +use std::collections::HashMap; + +impl Drive { + #[inline(always)] + pub(super) fn remove_contract_moderation_action_counts_operations_v0( + &self, + contract_id: Identifier, + identity_ids: &[Identifier], + estimated_costs_only_with_layer_info: &mut Option< + HashMap, + >, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let mut batch_operations: Vec = vec![]; + if identity_ids.is_empty() { + return Ok(batch_operations); + } + let apply_type = if let Some(estimated_costs_only_with_layer_info) = + estimated_costs_only_with_layer_info + { + Drive::add_estimation_costs_for_contract_moderation_action_counts( + contract_id.to_buffer(), + estimated_costs_only_with_layer_info, + &platform_version.drive, + )?; + BatchDeleteApplyType::StatelessBatchDelete { + in_tree_type: TreeType::NormalTree, + estimated_key_size: DEFAULT_HASH_SIZE_U32, + estimated_value_size: CONTRACT_MODERATION_ACTION_COUNT_SIZE as u32, + } + } else { + BatchDeleteApplyType::StatefulBatchDelete { + is_known_to_be_subtree_with_sum: Some(MaybeTree::NotTree), + } + }; + let path = contract_moderation_action_counts_path(contract_id.as_slice()); + for identity_id in identity_ids { + // A count carries no storage flags, so its removal refunds nobody. + self.batch_delete( + (&path).into(), + identity_id.as_slice(), + apply_type, + transaction, + &mut batch_operations, + &platform_version.drive, + )?; + } + Ok(batch_operations) + } +} diff --git a/packages/rs-drive/src/drive/contract/moderation/set_contract_moderation_action_count/mod.rs b/packages/rs-drive/src/drive/contract/moderation/set_contract_moderation_action_count/mod.rs new file mode 100644 index 00000000000..f366d07b182 --- /dev/null +++ b/packages/rs-drive/src/drive/contract/moderation/set_contract_moderation_action_count/mod.rs @@ -0,0 +1,65 @@ +mod v0; + +use crate::drive::Drive; +use crate::error::drive::DriveError; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use dpp::identifier::Identifier; +use dpp::version::PlatformVersion; +use grovedb::batch::KeyInfoPath; +use grovedb::EstimatedLayerInformation; +use std::collections::HashMap; + +impl Drive { + /// The operations that write `identity_id`'s count of moderation actions on the elected + /// contract `contract_id` since the moderators pot was last settled: an insert for the + /// member's first counted action of the period, a replacement of the same size after. With + /// layer information the operations are built for estimation only. + /// + /// The count carries no storage flags: the member whose action writes it pays for it, and + /// the settle that deletes it refunds nobody, as for a document a moderator deletes. + /// + /// # Parameters + /// + /// * `contract_id`: The elected contract. + /// * `identity_id`: The member of the seated team that signed the action. + /// * `count`: The count to store, the action included. + /// * `estimated_costs_only_with_layer_info`: The estimation map for a dry run. + /// * `platform_version`: The platform version. + /// + /// # Returns + /// + /// * `Ok(Vec)` with the operations. + /// * `Err(Error)` when the version is unknown. + pub fn set_contract_moderation_action_count_operations( + &self, + contract_id: Identifier, + identity_id: Identifier, + count: u32, + estimated_costs_only_with_layer_info: &mut Option< + HashMap, + >, + platform_version: &PlatformVersion, + ) -> Result, Error> { + match platform_version + .drive + .methods + .contract + .moderation + .set_contract_moderation_action_count + { + 0 => self.set_contract_moderation_action_count_operations_v0( + contract_id, + identity_id, + count, + estimated_costs_only_with_layer_info, + platform_version, + ), + version => Err(Error::Drive(DriveError::UnknownVersionMismatch { + method: "set_contract_moderation_action_count_operations".to_string(), + known_versions: vec![0], + received: version, + })), + } + } +} diff --git a/packages/rs-drive/src/drive/contract/moderation/set_contract_moderation_action_count/v0/mod.rs b/packages/rs-drive/src/drive/contract/moderation/set_contract_moderation_action_count/v0/mod.rs new file mode 100644 index 00000000000..aa6dee30372 --- /dev/null +++ b/packages/rs-drive/src/drive/contract/moderation/set_contract_moderation_action_count/v0/mod.rs @@ -0,0 +1,42 @@ +use crate::drive::contract::moderation::types::encode_moderation_action_count; +use crate::drive::contract::paths::contract_moderation_action_counts_path_vec; +use crate::drive::Drive; +use crate::error::Error; +use crate::fees::op::LowLevelDriveOperation; +use crate::fees::op::LowLevelDriveOperation::GroveOperation; +use dpp::identifier::Identifier; +use dpp::version::PlatformVersion; +use grovedb::batch::{KeyInfoPath, QualifiedGroveDbOp}; +use grovedb::{Element, EstimatedLayerInformation}; +use std::collections::HashMap; + +impl Drive { + #[inline(always)] + pub(super) fn set_contract_moderation_action_count_operations_v0( + &self, + contract_id: Identifier, + identity_id: Identifier, + count: u32, + estimated_costs_only_with_layer_info: &mut Option< + HashMap, + >, + platform_version: &PlatformVersion, + ) -> Result, Error> { + if let Some(estimated_costs_only_with_layer_info) = estimated_costs_only_with_layer_info { + Drive::add_estimation_costs_for_contract_moderation_action_counts( + contract_id.to_buffer(), + estimated_costs_only_with_layer_info, + &platform_version.drive, + )?; + } + // No storage flags: every count has the same size, so a replacement adds no bytes for + // anyone to own, and the settle that deletes the counts refunds nobody. + let op = QualifiedGroveDbOp::insert_or_replace_op( + contract_moderation_action_counts_path_vec(contract_id.as_slice()), + identity_id.to_vec(), + Element::new_item(encode_moderation_action_count(count)), + ) + .dont_check_for_backwards_references(); + Ok(vec![GroveOperation(op)]) + } +} diff --git a/packages/rs-drive/src/drive/contract/moderation/types.rs b/packages/rs-drive/src/drive/contract/moderation/types.rs index 46eb858c511..415f1fa43b7 100644 --- a/packages/rs-drive/src/drive/contract/moderation/types.rs +++ b/packages/rs-drive/src/drive/contract/moderation/types.rs @@ -181,6 +181,26 @@ impl ContractDocumentRemovalEntry { } } +/// The stored size of a moderation action count: a u32, big-endian. +pub const CONTRACT_MODERATION_ACTION_COUNT_SIZE: usize = 4; + +/// Encodes a moderation action count. +pub fn encode_moderation_action_count(count: u32) -> Vec { + count.to_be_bytes().to_vec() +} + +/// Decodes a moderation action count. +pub fn decode_moderation_action_count(value: &[u8]) -> Result { + let bytes: [u8; CONTRACT_MODERATION_ACTION_COUNT_SIZE] = value.try_into().map_err(|_| { + format!( + "moderation action count holds {} bytes, expected {}", + value.len(), + CONTRACT_MODERATION_ACTION_COUNT_SIZE + ) + })?; + Ok(u32::from_be_bytes(bytes)) +} + /// The stored size of what a document removal starts with: the document owner's id, the /// moderator's id, the removal time as a u64, the hash of the removed document and the tag /// byte that says whether a restoration follows. diff --git a/packages/rs-drive/src/drive/contract/paths.rs b/packages/rs-drive/src/drive/contract/paths.rs index 206d80ebf68..8a963c35808 100644 --- a/packages/rs-drive/src/drive/contract/paths.rs +++ b/packages/rs-drive/src/drive/contract/paths.rs @@ -219,6 +219,21 @@ pub const CONTRACT_WARNINGS_KEY: u8 = 224; /// it leaves the banlist on top. pub const CONTRACT_DOCUMENT_REMOVALS_KEY: u8 = 16; +/// The key under a contract's other tree (`[64, id, 2]`) of the moderation action counts of a +/// contract that declares elected moderation (protocol version 14): `identity id -> Item(count, +/// u32 big-endian)`, one per member of the seated team who signed a counted moderation action +/// (a ban, a suspension, a warning or a document deletion) since the moderators pot was last +/// settled. Every settle, a claim or a change of the team, pays the pot out by them and +/// deletes them. Created with an elected contract, the only kind that has a seated team. +/// +/// Read by the moderation actions of the team and by a settle, never by a document transition, +/// so it sorts below `64`: created together with the lists of an elected contract it keeps the +/// banlist on top when the contract keeps two or three lists, with or without removal records +/// beside them (the combination of every ability included), where a key above `128` would push +/// it down in most of those. It costs the banlist a level for a contract keeping the banlist +/// alone, or the banlist and one other list beside removal records. +pub const CONTRACT_MODERATION_ACTION_COUNTS_KEY: u8 = 48; + /// `[64, contract id, 2]`: the contract's other tree. pub fn contract_other_path(contract_id: &[u8]) -> [&[u8]; 3] { [ @@ -274,6 +289,26 @@ pub fn contract_moderation_list_path_vec( ] } +/// `[64, contract id, 2, 48]`: the moderation action counts of an elected contract. +pub fn contract_moderation_action_counts_path(contract_id: &[u8]) -> [&[u8]; 4] { + [ + Into::<&[u8; 1]>::into(RootTree::DataContractDocuments), + contract_id, + &[CONTRACT_OTHER_KEY], + &[CONTRACT_MODERATION_ACTION_COUNTS_KEY], + ] +} + +/// `[64, contract id, 2, 48]`: the moderation action counts of an elected contract. +pub fn contract_moderation_action_counts_path_vec(contract_id: &[u8]) -> Vec> { + vec![ + Into::<&[u8; 1]>::into(RootTree::DataContractDocuments).to_vec(), + contract_id.to_vec(), + vec![CONTRACT_OTHER_KEY], + vec![CONTRACT_MODERATION_ACTION_COUNTS_KEY], + ] +} + /// The key under the prefunded specialized balances tree (`[40]`) of the sum tree holding every /// contract's owner fee pot (protocol version 14): `contract id -> SumItem(credits)`. The /// `owner` parts of the contract's document action fees accumulate there until the owner diff --git a/packages/rs-drive/src/drive/contract/structure.rs b/packages/rs-drive/src/drive/contract/structure.rs index 32626ba4da1..dfe1d7500b0 100644 --- a/packages/rs-drive/src/drive/contract/structure.rs +++ b/packages/rs-drive/src/drive/contract/structure.rs @@ -1,7 +1,7 @@ use crate::drive::contract::paths::{ CONTRACT_BANLIST_KEY, CONTRACT_DOCUMENT_REMOVALS_KEY, CONTRACT_LAST_MODERATORS_FEE_CLAIM_KEY, - CONTRACT_LAST_OWNER_FEE_CLAIM_KEY, CONTRACT_OTHER_KEY, CONTRACT_SUSPENSIONS_KEY, - CONTRACT_VERSION_KEY, CONTRACT_WARNINGS_KEY, + CONTRACT_LAST_OWNER_FEE_CLAIM_KEY, CONTRACT_MODERATION_ACTION_COUNTS_KEY, CONTRACT_OTHER_KEY, + CONTRACT_SUSPENSIONS_KEY, CONTRACT_VERSION_KEY, CONTRACT_WARNINGS_KEY, }; use crate::drive::document::structure::document_type; use crate::drive::RootTree; @@ -150,6 +150,44 @@ pub(crate) fn structure() -> StructureNode { ), ), ), + StructureNode::fixed( + "moderation_action_counts", + &[CONTRACT_MODERATION_ACTION_COUNTS_KEY], + "ModerationActionCounts", + "CONTRACT_MODERATION_ACTION_COUNTS_KEY", + ) + .kind(ElementKind::Tree) + .lazy() + .flags(&[FlagsKind::EpochOwned, FlagsKind::None], CONTRACT_FLAGS) + .describe( + "How many moderation actions each member of the contract's \ + seated moderation team signed since its moderators pot \ + was last settled. Created with a contract that declares \ + elected moderation. Read by the team's actions and by a \ + settle, never by a document transition, so it sorts \ + below the version item.", + ) + .child( + StructureNode::identifier( + "member", + "identity_id", + "The member of the seated team", + ) + .kind(ElementKind::Item) + .flags( + &[FlagsKind::None], + "None: the member whose action writes the count pays \ + for it, and the settle that deletes it refunds nobody.", + ) + .value("u32 big endian") + .describe( + "The member's count of bans, suspensions, warnings and \ + document deletions since the last settle. Rewritten \ + one higher by each; every settle, a claim or a change \ + of the team, pays the pot's action share by the counts \ + and deletes them.", + ), + ), StructureNode::fixed( "version", &[CONTRACT_VERSION_KEY], diff --git a/packages/rs-drive/src/prove/prove_state_transition/v0/mod.rs b/packages/rs-drive/src/prove/prove_state_transition/v0/mod.rs index 177446b4088..f42ceacc6f8 100644 --- a/packages/rs-drive/src/prove/prove_state_transition/v0/mod.rs +++ b/packages/rs-drive/src/prove/prove_state_transition/v0/mod.rs @@ -377,7 +377,8 @@ impl Drive { } } // The pot the claim paid out with its last claim (epoch, time, claimant), and the balance - // of every identity a payout of that pot goes to. + // of every identity a payout of that pot goes to, or the claimant's alone for the + // moderators pot of an elected contract. StateTransition::ContractFeeClaim(st) => { let contract_id = st.data_contract_id(); let Some(contract_fetch_info) = self.get_contract_with_fetch_info( @@ -392,9 +393,13 @@ impl Drive { contract_id )))); }; + // The moderators pot of an elected contract proves the claimant's balance + // alone: the team a seated charter pays is not in the contract. Only a + // contract fee claim takes this arm, a transition protocol version 14 + // introduced, so no earlier proof changes. let recipients: Vec<[u8; 32]> = st .pot() - .recipients(&contract_fetch_info.contract) + .claim_proof_identities(&contract_fetch_info.contract, st.owner_id()) .into_iter() .map(|recipient| recipient.to_buffer()) .collect(); diff --git a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/documents_batch_transition.rs b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/documents_batch_transition.rs index 1704a87a76c..15e22067639 100644 --- a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/documents_batch_transition.rs +++ b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/documents_batch_transition.rs @@ -39,12 +39,23 @@ impl DriveHighLevelOperationConverter for BatchTransitionAction { } // Protocol version 14: the batch also sweeps the lapsed suspensions the transformer // found for its owner, one delete per (contract, identity) after the transitions' - // own operations, always the owner's own suspension. + // own operations, always the owner's own suspension. And before a change of a + // seated moderation team, it settles the team's moderators pot first: the payouts + // its state validation settled and the reset of the action counts, operations on + // other keys than the change's own. 1 => { let owner_id = self.owner_id(); let lapsed_suspensions = self.lapsed_suspensions().clone(); + let settlements = self.moderators_pot_settlements().to_vec(); let transitions = self.transitions_owned(); - let mut operations = transitions + let mut operations = settlements + .into_iter() + .map(|settlement| settlement.into_drive_operations()) + .collect::>, Error>>()? + .into_iter() + .flatten() + .collect::>(); + let transition_operations = transitions .into_iter() .map(|transition| { transition.into_high_level_batch_drive_operations( @@ -55,8 +66,8 @@ impl DriveHighLevelOperationConverter for BatchTransitionAction { }) .collect::>, Error>>()? .into_iter() - .flatten() - .collect::>(); + .flatten(); + operations.extend(transition_operations); operations.extend(lapsed_suspensions.into_iter().map(|contract_id| { DriveOperation::ContractModerationOperation( ContractModerationOperationType::RemoveSuspension { diff --git a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/contract/contract_fee_claim_transition.rs b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/contract/contract_fee_claim_transition.rs index ad96a3925ba..f107901a99b 100644 --- a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/contract/contract_fee_claim_transition.rs +++ b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/contract/contract_fee_claim_transition.rs @@ -4,8 +4,13 @@ use crate::error::Error; use crate::state_transition_action::action_convert_to_operations::DriveHighLevelOperationConverter; use crate::state_transition_action::contract::contract_fee_claim::v0::ContractFeeClaimTransitionActionV0; use crate::state_transition_action::contract::contract_fee_claim::ContractFeeClaimTransitionAction; -use crate::util::batch::DriveOperation::{ContractFeePotOperation, IdentityOperation}; -use crate::util::batch::{ContractFeePotOperationType, DriveOperation, IdentityOperationType}; +use crate::util::batch::DriveOperation::{ + ContractFeePotOperation, ContractModerationOperation, IdentityOperation, +}; +use crate::util::batch::{ + ContractFeePotOperationType, ContractModerationOperationType, DriveOperation, + IdentityOperationType, +}; use dpp::block::epoch::Epoch; use dpp::fee::Credits; use dpp::version::PlatformVersion; @@ -31,6 +36,7 @@ impl DriveHighLevelOperationConverter for ContractFeeClaimTransitionAction { identity_contract_nonce, pot, payouts, + settled_action_counts, .. }) = self; @@ -61,6 +67,16 @@ impl DriveHighLevelOperationConverter for ContractFeeClaimTransitionAction { added_balance, }) })); + // A seated moderation team's pot was split by the action counts, which start + // over. + if !settled_action_counts.is_empty() { + operations.push(ContractModerationOperation( + ContractModerationOperationType::RemoveActionCounts { + contract_id, + identity_ids: settled_action_counts, + }, + )); + } operations.push(ContractFeePotOperation( ContractFeePotOperationType::SetLastClaim { contract_id, diff --git a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/contract/contract_user_moderation_transition.rs b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/contract/contract_user_moderation_transition.rs index 94b03dc3a5a..75277846761 100644 --- a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/contract/contract_user_moderation_transition.rs +++ b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/contract/contract_user_moderation_transition.rs @@ -46,6 +46,7 @@ impl DriveHighLevelOperationConverter for ContractUserModerationTransitionAction warning, document_deletion, document_restoration, + moderation_action_count, .. }, ) = self; @@ -251,6 +252,18 @@ impl DriveHighLevelOperationConverter for ContractUserModerationTransitionAction } } + // A member of an elected contract's seated team signed an action that counts + // toward its share of the moderators pot. + if let Some(count) = moderation_action_count { + operations.push(ContractModerationOperation( + ContractModerationOperationType::SetActionCount { + contract_id, + identity_id: moderator_id, + count, + }, + )); + } + Ok(operations) } version => Err(Error::Drive(DriveError::UnknownVersionMismatch { @@ -282,6 +295,7 @@ mod tests { warning: None, document_deletion: None, document_restoration: None, + moderation_action_count: None, user_fee_increase: 0, }) } @@ -408,6 +422,33 @@ mod tests { )); } + #[test] + fn should_write_the_moderation_action_count_of_a_seated_team_member_last() { + let platform_version = PlatformVersion::latest(); + let epoch = Epoch::new(0).expect("epoch"); + let target = Identifier::from([0xCC; 32]); + + let ops = action( + ContractUserModerationAction::Ban { + identity_id: target, + reason: ContractModerationReason::from_text("spam"), + }, + false, + ) + .with_moderation_action_count(3) + .into_high_level_drive_operations(&epoch, platform_version) + .expect("operations"); + assert_eq!(ops.len(), 3); + assert!(matches!( + &ops[2], + ContractModerationOperation(ContractModerationOperationType::SetActionCount { + identity_id, + count: 3, + .. + }) if *identity_id == Identifier::from([0xAA; 32]) + )); + } + #[test] fn should_replace_an_existing_suspension() { let platform_version = PlatformVersion::latest(); diff --git a/packages/rs-drive/src/state_transition_action/batch/mod.rs b/packages/rs-drive/src/state_transition_action/batch/mod.rs index 7acdd669e96..1bab5ccbb55 100644 --- a/packages/rs-drive/src/state_transition_action/batch/mod.rs +++ b/packages/rs-drive/src/state_transition_action/batch/mod.rs @@ -1,5 +1,6 @@ use crate::state_transition_action::batch::batched_transition::BatchedTransitionAction; use crate::state_transition_action::batch::v0::BatchTransitionActionV0; +use crate::state_transition_action::contract::moderators_pot_settlement::ModeratorsPotSettlement; use derive_more::From; use dpp::data_contract::accessors::v0::DataContractV0Getters; use dpp::data_contract::document_type::accessors::DocumentTypeV0Getters; @@ -266,6 +267,21 @@ impl BatchTransitionAction { BatchTransitionAction::V0(v0) => &v0.lapsed_suspensions, } } + + /// The settles of moderators pots the batch forces before it changes a seated team + pub fn moderators_pot_settlements(&self) -> &[ModeratorsPotSettlement] { + match self { + BatchTransitionAction::V0(v0) => &v0.moderators_pot_settlements, + } + } + + /// Records the settles of moderators pots the batch forces before it changes a seated + /// team + pub fn set_moderators_pot_settlements(&mut self, settlements: Vec) { + match self { + BatchTransitionAction::V0(v0) => v0.moderators_pot_settlements = settlements, + } + } } impl BatchTransitionAction { diff --git a/packages/rs-drive/src/state_transition_action/batch/v0/mod.rs b/packages/rs-drive/src/state_transition_action/batch/v0/mod.rs index 7bdaf6a8b36..0f0bc5787a6 100644 --- a/packages/rs-drive/src/state_transition_action/batch/v0/mod.rs +++ b/packages/rs-drive/src/state_transition_action/batch/v0/mod.rs @@ -2,6 +2,7 @@ use crate::state_transition_action::batch::batched_transition::document_transiti use crate::state_transition_action::batch::{ GasPayer, ResolvedContractGroupMemberships, ResolvedGasSponsor, }; +use crate::state_transition_action::contract::moderators_pot_settlement::ModeratorsPotSettlement; use dpp::prelude::FeeMultiplier; use dpp::consensus::state::document::document_action_fee_agreement_mismatch_error::DocumentActionFeeAgreementMismatchError; use dpp::consensus::state::document::document_action_fee_agreement_not_set_error::DocumentActionFeeAgreementNotSetError; @@ -58,6 +59,14 @@ pub struct BatchTransitionActionV0 { /// the batch executes: the first document transition after a suspension lapses sweeps it. /// Only ever the owner's own: the identity is not stored, so nothing can queue another's. pub lapsed_suspensions: BTreeSet, + + /// The settles of elected contracts' moderators pots the batch forces before it changes a + /// seated team (protocol version 14): an `addedModerator` or `removedModerator` of the + /// moderation charters contract created or deleted pays the pot out to the team as it was + /// before the change, by its proposal's reward split, and resets the action counts. Set + /// by the batch's state validation, which reads the team, the pot and the counts; empty + /// for every other batch. + pub moderators_pot_settlements: Vec, } impl BatchTransitionActionV0 { diff --git a/packages/rs-drive/src/state_transition_action/contract/contract_fee_claim/mod.rs b/packages/rs-drive/src/state_transition_action/contract/contract_fee_claim/mod.rs index dc7781c3683..3aad657b2ff 100644 --- a/packages/rs-drive/src/state_transition_action/contract/contract_fee_claim/mod.rs +++ b/packages/rs-drive/src/state_transition_action/contract/contract_fee_claim/mod.rs @@ -75,6 +75,13 @@ impl ContractFeeClaimTransitionAction { } } + /// The members whose moderation action counts the claim resets + pub fn settled_action_counts(&self) -> &[Identifier] { + match self { + ContractFeeClaimTransitionAction::V0(action) => &action.settled_action_counts, + } + } + /// fee multiplier pub fn user_fee_increase(&self) -> UserFeeIncrease { match self { diff --git a/packages/rs-drive/src/state_transition_action/contract/contract_fee_claim/transformer.rs b/packages/rs-drive/src/state_transition_action/contract/contract_fee_claim/transformer.rs index ed85aa38e02..c3925a08636 100644 --- a/packages/rs-drive/src/state_transition_action/contract/contract_fee_claim/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/contract/contract_fee_claim/transformer.rs @@ -8,13 +8,14 @@ use dpp::state_transition::contract_fee_claim_transition::ContractFeeClaimTransi use std::collections::BTreeMap; impl ContractFeeClaimTransitionAction { - /// The action of a borrowed transition, carrying the epoch and the block time of the claim - /// and what each recipient is paid + /// The action of a borrowed transition, carrying the epoch and the block time of the claim, + /// what each recipient is paid and whose moderation action counts the claim resets pub fn from_borrowed_transition_with_payouts( value: &ContractFeeClaimTransition, epoch_index: EpochIndex, time_ms: TimestampMillis, payouts: BTreeMap, + settled_action_counts: Vec, ) -> Self { match value { ContractFeeClaimTransition::V0(v0) => { @@ -23,6 +24,7 @@ impl ContractFeeClaimTransitionAction { epoch_index, time_ms, payouts, + settled_action_counts, ) .into() } diff --git a/packages/rs-drive/src/state_transition_action/contract/contract_fee_claim/v0/mod.rs b/packages/rs-drive/src/state_transition_action/contract/contract_fee_claim/v0/mod.rs index a227cd97d9e..56be4cfd140 100644 --- a/packages/rs-drive/src/state_transition_action/contract/contract_fee_claim/v0/mod.rs +++ b/packages/rs-drive/src/state_transition_action/contract/contract_fee_claim/v0/mod.rs @@ -23,9 +23,13 @@ pub struct ContractFeeClaimTransitionActionV0 { /// the time of the block the claim executes in, recorded with the pot's last claim pub time_ms: TimestampMillis, /// what each recipient is paid, as settled when the transition was validated: the whole - /// owner pot to the contract owner, or an equal share of the moderators pot to every - /// member of the moderation team. Never empty, and every amount is above zero. + /// owner pot to the contract owner, an equal share of the moderators pot to every member + /// of a declared moderation team, or a seated team's pot split by its proposal's reward + /// split. Never empty, and every amount is above zero. pub payouts: BTreeMap, + /// the members of an elected contract's seated team whose moderation action counts the + /// claim of its moderators pot split the pot by and resets; empty for every other claim + pub settled_action_counts: Vec, /// fee multiplier pub user_fee_increase: UserFeeIncrease, } diff --git a/packages/rs-drive/src/state_transition_action/contract/contract_fee_claim/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/contract/contract_fee_claim/v0/transformer.rs index b477713201f..297ccbceb78 100644 --- a/packages/rs-drive/src/state_transition_action/contract/contract_fee_claim/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/contract/contract_fee_claim/v0/transformer.rs @@ -7,13 +7,14 @@ use dpp::state_transition::contract_fee_claim_transition::v0::ContractFeeClaimTr use std::collections::BTreeMap; impl ContractFeeClaimTransitionActionV0 { - /// The action of a borrowed transition, carrying the epoch and the block time of the claim - /// and what each recipient is paid + /// The action of a borrowed transition, carrying the epoch and the block time of the claim, + /// what each recipient is paid and whose moderation action counts the claim resets pub fn from_borrowed_transition_with_payouts( value: &ContractFeeClaimTransitionV0, epoch_index: EpochIndex, time_ms: TimestampMillis, payouts: BTreeMap, + settled_action_counts: Vec, ) -> Self { let ContractFeeClaimTransitionV0 { owner_id, @@ -31,6 +32,7 @@ impl ContractFeeClaimTransitionActionV0 { epoch_index, time_ms, payouts, + settled_action_counts, user_fee_increase: *user_fee_increase, } } diff --git a/packages/rs-drive/src/state_transition_action/contract/contract_user_moderation/mod.rs b/packages/rs-drive/src/state_transition_action/contract/contract_user_moderation/mod.rs index 8127253ae32..1b4e9ccf4ac 100644 --- a/packages/rs-drive/src/state_transition_action/contract/contract_user_moderation/mod.rs +++ b/packages/rs-drive/src/state_transition_action/contract/contract_user_moderation/mod.rs @@ -72,6 +72,26 @@ impl ContractUserModerationTransitionAction { } } + /// The signer's moderation action count on the elected contract after this action, when + /// the action counts for a member of the seated team + pub fn moderation_action_count(&self) -> Option { + match self { + ContractUserModerationTransitionAction::V0(action) => action.moderation_action_count, + } + } + + /// The same action, counted for its signer, a member of the elected contract's seated team: + /// `count` is the signer's moderation action count since the moderators pot was last + /// settled, this action included + pub fn with_moderation_action_count(self, count: u32) -> Self { + match self { + ContractUserModerationTransitionAction::V0(mut action) => { + action.moderation_action_count = Some(count); + ContractUserModerationTransitionAction::V0(action) + } + } + } + /// fee multiplier pub fn user_fee_increase(&self) -> UserFeeIncrease { match self { diff --git a/packages/rs-drive/src/state_transition_action/contract/contract_user_moderation/v0/mod.rs b/packages/rs-drive/src/state_transition_action/contract/contract_user_moderation/v0/mod.rs index 967e8ab017d..db94a2fb773 100644 --- a/packages/rs-drive/src/state_transition_action/contract/contract_user_moderation/v0/mod.rs +++ b/packages/rs-drive/src/state_transition_action/contract/contract_user_moderation/v0/mod.rs @@ -32,6 +32,12 @@ pub struct ContractUserModerationTransitionActionV0 { /// what a document restore read and decoded when the transition was validated, `None` /// for every other action pub document_restoration: Option, + /// the signer's count of moderation actions on the elected contract since its moderators + /// pot was last settled, this action included, when the signer is on the contract's seated + /// team and the action counts (a ban, a suspension, a warning or a document deletion); + /// `None` otherwise. Read when the transition was validated, so Drive writes it without + /// reading again + pub moderation_action_count: Option, /// fee multiplier pub user_fee_increase: UserFeeIncrease, } diff --git a/packages/rs-drive/src/state_transition_action/contract/contract_user_moderation/v0/transformer.rs b/packages/rs-drive/src/state_transition_action/contract/contract_user_moderation/v0/transformer.rs index c7c4e1aca41..a253b6cb2f3 100644 --- a/packages/rs-drive/src/state_transition_action/contract/contract_user_moderation/v0/transformer.rs +++ b/packages/rs-drive/src/state_transition_action/contract/contract_user_moderation/v0/transformer.rs @@ -38,6 +38,7 @@ impl ContractUserModerationTransitionActionV0 { }), document_deletion: None, document_restoration: None, + moderation_action_count: None, user_fee_increase: *user_fee_increase, } } diff --git a/packages/rs-drive/src/state_transition_action/contract/mod.rs b/packages/rs-drive/src/state_transition_action/contract/mod.rs index b501ccb64c8..f8f26592d01 100644 --- a/packages/rs-drive/src/state_transition_action/contract/mod.rs +++ b/packages/rs-drive/src/state_transition_action/contract/mod.rs @@ -6,3 +6,5 @@ pub mod contract_user_moderation; pub mod data_contract_create; /// update pub mod data_contract_update; +/// the settle of an elected contract's moderators pot +pub mod moderators_pot_settlement; diff --git a/packages/rs-drive/src/state_transition_action/contract/moderators_pot_settlement.rs b/packages/rs-drive/src/state_transition_action/contract/moderators_pot_settlement.rs new file mode 100644 index 00000000000..7e7dd960ca2 --- /dev/null +++ b/packages/rs-drive/src/state_transition_action/contract/moderators_pot_settlement.rs @@ -0,0 +1,82 @@ +use crate::error::fee::FeeError; +use crate::error::Error; +use crate::util::batch::DriveOperation::{ + ContractFeePotOperation, ContractModerationOperation, IdentityOperation, +}; +use crate::util::batch::{ + ContractFeePotOperationType, ContractModerationOperationType, DriveOperation, + IdentityOperationType, +}; +use dpp::data_contract::document_type::action_fees::ContractFeePot; +use dpp::fee::Credits; +use dpp::identifier::Identifier; +use std::collections::BTreeMap; + +/// A settle of the moderators pot of a contract with a seated moderation team, as settled when +/// the transition was validated: what each identity of the team is paid by its proposal's +/// reward split, and whose moderation action counts the settle resets. A claim of the pot +/// settles it, and so does every change of the team, beforehand. +#[derive(Debug, Clone, Default, PartialEq, Eq)] +pub struct ModeratorsPotSettlement { + /// The elected contract whose moderators pot is settled. + pub contract_id: Identifier, + /// What each identity is paid: every amount is above zero, and they add up to at most + /// the pot. May be empty when the pot holds too little to pay anyone a credit. + pub payouts: BTreeMap, + /// The members whose moderation action counts exist and are deleted by the settle. + pub settled_action_counts: Vec, +} + +impl ModeratorsPotSettlement { + /// Whether the settle changes nothing: nobody is paid and no count is reset. + pub fn is_empty(&self) -> bool { + self.payouts.is_empty() && self.settled_action_counts.is_empty() + } + + /// What is taken out of the pot: the sum of the payouts. + pub fn paid_out(&self) -> Result { + self.payouts + .values() + .try_fold(0 as Credits, |total, amount| total.checked_add(*amount)) + .ok_or(Error::Fee(FeeError::Overflow( + "the payouts of a moderators pot settle overflow credits", + ))) + } + + /// The operations of the settle: the credits paid out leave the pot and reach the + /// balances of the team, so they only move, and the counts the payouts were split by are + /// deleted. + pub fn into_drive_operations<'a>(self) -> Result>, Error> { + let paid_out = self.paid_out()?; + let ModeratorsPotSettlement { + contract_id, + payouts, + settled_action_counts, + } = self; + let mut operations = vec![]; + if paid_out > 0 { + operations.push(ContractFeePotOperation( + ContractFeePotOperationType::DeductFromPot { + contract_id, + pot: ContractFeePot::Moderators, + amount: paid_out, + }, + )); + } + operations.extend(payouts.into_iter().map(|(identity_id, added_balance)| { + IdentityOperation(IdentityOperationType::AddToIdentityBalance { + identity_id: identity_id.to_buffer(), + added_balance, + }) + })); + if !settled_action_counts.is_empty() { + operations.push(ContractModerationOperation( + ContractModerationOperationType::RemoveActionCounts { + contract_id, + identity_ids: settled_action_counts, + }, + )); + } + Ok(operations) + } +} diff --git a/packages/rs-drive/src/structure/tests.rs b/packages/rs-drive/src/structure/tests.rs index 8babc356afe..01a104d3cc4 100644 --- a/packages/rs-drive/src/structure/tests.rs +++ b/packages/rs-drive/src/structure/tests.rs @@ -322,7 +322,8 @@ mod fixtures { use dpp::data_contract::associated_token::token_pre_programmed_distribution::TokenPreProgrammedDistribution; use dpp::data_contract::config::moderation::{ ContractDocumentRemoval, ContractModerationConfig, ContractModerationReason, - ContractModerators, ContractWarning, + ContractModerators, ContractWarning, ElectedModerators, InterimModerators, + ModerationAbility, DEFAULT_ELECTION_WINDOW_SECONDS, }; use dpp::data_contract::config::v0::{DataContractConfigSettersV0, DataContractConfigV0}; use dpp::data_contract::config::DataContractConfig; @@ -817,6 +818,60 @@ mod fixtures { conformance_of(&drive, "moderated_contract", run); } + /// A contract whose moderators are elected, keeping the banlist, with one member of its + /// seated team's moderation action counted + fn elected_contract(run: &mut FixtureRun) { + let platform_version = PlatformVersion::latest(); + let drive = setup_drive_with_initial_state_structure(Some(platform_version)); + let contract = setup_contract( + &drive, + "tests/supporting_files/contract/family/family-contract.json", + Some([11; 32]), + None, + Some(|contract: &mut DataContract| { + contract.set_config(contract.config().clone().with_moderation(Some( + ContractModerationConfig { + banlist: true, + suspensions: false, + warnings: false, + moderators: ContractModerators::Elected(Box::new(ElectedModerators { + join_window: DEFAULT_ELECTION_WINDOW_SECONDS, + vote_window: DEFAULT_ELECTION_WINDOW_SECONDS, + challenge_cool_down: 1_209_600, + election_delay: None, + max_added_moderators: 0, + moderated_document_types: BTreeMap::from([( + "person".to_string(), + BTreeSet::from([ModerationAbility::Ban]), + )]), + interim: InterimModerators::NotYetUsable, + owner_protected: false, + })), + }, + ))) + }), + None, + Some(platform_version), + ); + drive + .apply_drive_operations( + vec![DriveOperation::ContractModerationOperation( + ContractModerationOperationType::SetActionCount { + contract_id: contract.id(), + identity_id: Identifier::from([0x24; 32]), + count: 3, + }, + )], + true, + &BlockInfo::default(), + None, + platform_version, + None, + ) + .expect("expected to count a moderation action"); + conformance_of(&drive, "elected_contract", run); + } + /// A contract that keeps the banlist and the warning list, with one identity carrying two /// warnings fn warned_contract(run: &mut FixtureRun) { @@ -1505,6 +1560,7 @@ mod fixtures { contracts_with_documents(&mut run); moderated_contract(&mut run); warned_contract(&mut run); + elected_contract(&mut run); contract_with_document_removals(&mut run); tokens_and_group_actions(&mut run); address_balances(&mut run); diff --git a/packages/rs-drive/src/util/batch/drive_op_batch/contract_moderation.rs b/packages/rs-drive/src/util/batch/drive_op_batch/contract_moderation.rs index a2abadab067..f13e62e0541 100644 --- a/packages/rs-drive/src/util/batch/drive_op_batch/contract_moderation.rs +++ b/packages/rs-drive/src/util/batch/drive_op_batch/contract_moderation.rs @@ -13,8 +13,8 @@ use grovedb::{EstimatedLayerInformation, TransactionArg}; use platform_version::version::PlatformVersion; use std::collections::HashMap; -/// Operations on a moderated contract's banlist, suspension list, warning list and document -/// removal records. +/// Operations on a moderated contract's banlist, suspension list, warning list, document +/// removal records and, for an elected contract, its team's moderation action counts. #[derive(Clone, Debug)] pub enum ContractModerationOperationType { /// Puts an identity on the banlist. @@ -106,6 +106,24 @@ pub enum ContractModerationOperationType { /// (`Drive::apply_drive_operations` generation 1). A moderator's document deletion carries /// it, so the deleted document's owner gets no storage refund. ForfeitStorageRefunds, + /// Writes a seated moderation team member's count of moderation actions on an elected + /// contract since the moderators pot was last settled. + SetActionCount { + /// The elected contract. + contract_id: Identifier, + /// The member that signed the action. + identity_id: Identifier, + /// The count to store, the action included. + count: u32, + }, + /// Deletes moderation action counts of an elected contract: the reset of a settle of its + /// moderators pot. Each count must exist. + RemoveActionCounts { + /// The elected contract. + contract_id: Identifier, + /// The members whose counts go. + identity_ids: Vec, + }, } impl DriveLowLevelOperationConverter for ContractModerationOperationType { @@ -224,6 +242,27 @@ impl DriveLowLevelOperationConverter for ContractModerationOperationType { platform_version, ), ContractModerationOperationType::ForfeitStorageRefunds => Ok(vec![]), + ContractModerationOperationType::SetActionCount { + contract_id, + identity_id, + count, + } => drive.set_contract_moderation_action_count_operations( + contract_id, + identity_id, + count, + estimated_costs_only_with_layer_info, + platform_version, + ), + ContractModerationOperationType::RemoveActionCounts { + contract_id, + identity_ids, + } => drive.remove_contract_moderation_action_counts_operations( + contract_id, + &identity_ids, + estimated_costs_only_with_layer_info, + transaction, + platform_version, + ), } } } diff --git a/packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs b/packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs index 0f358c11eed..99da1122a03 100644 --- a/packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs +++ b/packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs @@ -1375,8 +1375,11 @@ impl Drive { contract_id )), ))?; + // The prover's identities: the moderators pot of an elected contract proves + // the claimant's balance alone (a contract fee claim exists from protocol + // version 14 only, so no earlier proof changes). let recipients: Vec<[u8; 32]> = pot - .recipients(&contract) + .claim_proof_identities(&contract, transition.owner_id()) .into_iter() .map(|recipient| recipient.to_buffer()) .collect(); diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/mod.rs b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/mod.rs index b7a25f8c676..d6d2c930e18 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/mod.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/mod.rs @@ -39,6 +39,14 @@ pub struct DriveContractModerationMethodVersions { pub prove_contract_document_removals: FeatureVersion, pub insert_contract_document_removal_trees: FeatureVersion, pub add_estimation_costs_for_contract_document_removal: FeatureVersion, + /// Writes a seated moderation team member's count of moderation actions since the last + /// settle of the moderators pot (`[64, id, 2, 48]`, protocol version 14) + pub set_contract_moderation_action_count: FeatureVersion, + /// Reads every moderation action count of an elected contract + pub fetch_contract_moderation_action_counts: FeatureVersion, + /// Deletes moderation action counts: the reset at a settle of the moderators pot + pub remove_contract_moderation_action_counts: FeatureVersion, + pub add_estimation_costs_for_contract_moderation_action_counts: FeatureVersion, } /// Drive methods for the two fee pots a contract's document action fees accumulate in diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v1.rs b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v1.rs index 2286de56422..d38370593ab 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v1.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v1.rs @@ -63,6 +63,10 @@ pub const DRIVE_CONTRACT_METHOD_VERSIONS_V1: DriveContractMethodVersions = prove_contract_document_removals: 0, insert_contract_document_removal_trees: 0, add_estimation_costs_for_contract_document_removal: 0, + set_contract_moderation_action_count: 0, + fetch_contract_moderation_action_counts: 0, + remove_contract_moderation_action_counts: 0, + add_estimation_costs_for_contract_moderation_action_counts: 0, }, fee_pots: DriveContractFeePotMethodVersions { insert_contract_fee_pot_trees: 0, diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v2.rs b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v2.rs index 207a0d3f979..4f98a9d9dec 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v2.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v2.rs @@ -63,6 +63,10 @@ pub const DRIVE_CONTRACT_METHOD_VERSIONS_V2: DriveContractMethodVersions = prove_contract_document_removals: 0, insert_contract_document_removal_trees: 0, add_estimation_costs_for_contract_document_removal: 0, + set_contract_moderation_action_count: 0, + fetch_contract_moderation_action_counts: 0, + remove_contract_moderation_action_counts: 0, + add_estimation_costs_for_contract_moderation_action_counts: 0, }, fee_pots: DriveContractFeePotMethodVersions { insert_contract_fee_pot_trees: 0, diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v3.rs b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v3.rs index 77d1bbe2f44..2bf0336bf99 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v3.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v3.rs @@ -74,6 +74,10 @@ pub const DRIVE_CONTRACT_METHOD_VERSIONS_V3: DriveContractMethodVersions = prove_contract_document_removals: 0, insert_contract_document_removal_trees: 0, add_estimation_costs_for_contract_document_removal: 0, + set_contract_moderation_action_count: 0, + fetch_contract_moderation_action_counts: 0, + remove_contract_moderation_action_counts: 0, + add_estimation_costs_for_contract_moderation_action_counts: 0, }, fee_pots: DriveContractFeePotMethodVersions { insert_contract_fee_pot_trees: 0, diff --git a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v4.rs b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v4.rs index e48c216956e..1086bc79ea4 100644 --- a/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v4.rs +++ b/packages/rs-platform-version/src/version/drive_versions/drive_contract_method_versions/v4.rs @@ -61,6 +61,10 @@ pub const DRIVE_CONTRACT_METHOD_VERSIONS_V4: DriveContractMethodVersions = prove_contract_document_removals: 0, insert_contract_document_removal_trees: 0, add_estimation_costs_for_contract_document_removal: 0, + set_contract_moderation_action_count: 0, + fetch_contract_moderation_action_counts: 0, + remove_contract_moderation_action_counts: 0, + add_estimation_costs_for_contract_moderation_action_counts: 0, }, ..DRIVE_CONTRACT_METHOD_VERSIONS_V3 }; From 97c4a2c16740cd7b1620a5bb24ec4a8fdc0fe150 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 24 Sep 2026 13:59:22 +0700 Subject: [PATCH 2/4] feat(platform)!: a seated moderation team acts only on reasons its proposal lists A moderation reason gains reasonDocumentId, the moderation charters contract's reason document the action is taken on: appended to the transition's reason, tag bit 2 where it is stored, field 4 of the gRPC reason, reasonDocumentId in wasm-dpp2. A seated elected team's ban, suspension, warning or document deletion must name a reason its proposal lists, or is refused, paid, in a block and in the mempool (ModerationReasonNotListedError, 41203). A proposal with no reason can take no such action. Reversals carry no reason and are not checked, and the interim and declared moderators are not bound. Co-Authored-By: Claude Opus 5.5 --- .../clients/drive/v0/nodejs/drive_pbjs.js | 31 + .../platform/v0/nodejs/platform_pbjs.js | 31 + .../platform/v0/nodejs/platform_protoc.js | 74 +- .../platform/v0/objective-c/Platform.pbobjc.h | 8 +- .../platform/v0/objective-c/Platform.pbobjc.m | 11 + .../platform/v0/python/platform_pb2.py | 1599 +++++++++-------- .../clients/platform/v0/web/platform_pb.d.ts | 8 + .../clients/platform/v0/web/platform_pb.js | 74 +- .../protos/platform/v0/platform.proto | 6 +- .../data_contract/config/moderation/reason.rs | 40 +- packages/rs-dpp/src/errors/consensus/codes.rs | 1 + .../state/contract_moderation/mod.rs | 2 + .../moderation_reason_not_listed_error.rs | 81 + .../src/errors/consensus/state/state_error.rs | 15 +- .../mod.rs | 2 + .../v0/mod.rs | 2 + .../contract_user_moderation/state/v0/mod.rs | 70 + .../contract_user_moderation/tests.rs | 3 + .../tests/seated_team.rs | 150 +- .../tests/seated_team/reasons.rs | 167 ++ .../contract_document_removals/v0/mod.rs | 2 + .../contract_moderation_entries/v0/mod.rs | 3 + .../contract_moderation_status/v0/mod.rs | 1 + .../query/contract_moderation_queries/mod.rs | 2 + .../src/types/contract_moderation.rs | 22 + .../rs-drive-proof-verifier/src/unproved.rs | 6 + packages/rs-drive/grovedb-structure.json | 2 +- .../moderation/document_removal_tests.rs | 1 + .../src/drive/contract/moderation/mod.rs | 10 +- .../src/drive/contract/moderation/tests.rs | 1 + .../src/drive/contract/moderation/types.rs | 84 +- .../rs-drive/src/drive/contract/structure.rs | 9 +- .../src/errors/consensus/consensus_error.rs | 4 + .../transitions/user_moderation.rs | 20 +- .../ContractUserModerationTransition.spec.ts | 21 +- 35 files changed, 1745 insertions(+), 818 deletions(-) create mode 100644 packages/rs-dpp/src/errors/consensus/state/contract_moderation/moderation_reason_not_listed_error.rs create mode 100644 packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team/reasons.rs diff --git a/packages/dapi-grpc/clients/drive/v0/nodejs/drive_pbjs.js b/packages/dapi-grpc/clients/drive/v0/nodejs/drive_pbjs.js index 0c4cfa4a527..e58c12a40a1 100644 --- a/packages/dapi-grpc/clients/drive/v0/nodejs/drive_pbjs.js +++ b/packages/dapi-grpc/clients/drive/v0/nodejs/drive_pbjs.js @@ -24311,6 +24311,7 @@ $root.org = (function() { * @property {number|null} [code] ContractModerationReason code * @property {string|null} [text] ContractModerationReason text * @property {Array.|null} [documents] ContractModerationReason documents + * @property {Uint8Array|null} [reasonDocumentId] ContractModerationReason reasonDocumentId */ /** @@ -24353,6 +24354,14 @@ $root.org = (function() { */ ContractModerationReason.prototype.documents = $util.emptyArray; + /** + * ContractModerationReason reasonDocumentId. + * @member {Uint8Array} reasonDocumentId + * @memberof org.dash.platform.dapi.v0.ContractModerationReason + * @instance + */ + ContractModerationReason.prototype.reasonDocumentId = $util.newBuffer([]); + /** * Creates a new ContractModerationReason instance using the specified properties. * @function create @@ -24384,6 +24393,8 @@ $root.org = (function() { if (message.documents != null && message.documents.length) for (var i = 0; i < message.documents.length; ++i) $root.org.dash.platform.dapi.v0.ContractModerationDocument.encode(message.documents[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); + if (message.reasonDocumentId != null && Object.hasOwnProperty.call(message, "reasonDocumentId")) + writer.uint32(/* id 4, wireType 2 =*/34).bytes(message.reasonDocumentId); return writer; }; @@ -24429,6 +24440,9 @@ $root.org = (function() { message.documents = []; message.documents.push($root.org.dash.platform.dapi.v0.ContractModerationDocument.decode(reader, reader.uint32())); break; + case 4: + message.reasonDocumentId = reader.bytes(); + break; default: reader.skipType(tag & 7); break; @@ -24479,6 +24493,9 @@ $root.org = (function() { return "documents." + error; } } + if (message.reasonDocumentId != null && message.hasOwnProperty("reasonDocumentId")) + if (!(message.reasonDocumentId && typeof message.reasonDocumentId.length === "number" || $util.isString(message.reasonDocumentId))) + return "reasonDocumentId: buffer expected"; return null; }; @@ -24508,6 +24525,11 @@ $root.org = (function() { message.documents[i] = $root.org.dash.platform.dapi.v0.ContractModerationDocument.fromObject(object.documents[i]); } } + if (object.reasonDocumentId != null) + if (typeof object.reasonDocumentId === "string") + $util.base64.decode(object.reasonDocumentId, message.reasonDocumentId = $util.newBuffer($util.base64.length(object.reasonDocumentId)), 0); + else if (object.reasonDocumentId.length >= 0) + message.reasonDocumentId = object.reasonDocumentId; return message; }; @@ -24529,6 +24551,13 @@ $root.org = (function() { if (options.defaults) { object.code = 0; object.text = ""; + if (options.bytes === String) + object.reasonDocumentId = ""; + else { + object.reasonDocumentId = []; + if (options.bytes !== Array) + object.reasonDocumentId = $util.newBuffer(object.reasonDocumentId); + } } if (message.code != null && message.hasOwnProperty("code")) object.code = message.code; @@ -24539,6 +24568,8 @@ $root.org = (function() { for (var j = 0; j < message.documents.length; ++j) object.documents[j] = $root.org.dash.platform.dapi.v0.ContractModerationDocument.toObject(message.documents[j], options); } + if (message.reasonDocumentId != null && message.hasOwnProperty("reasonDocumentId")) + object.reasonDocumentId = options.bytes === String ? $util.base64.encode(message.reasonDocumentId, 0, message.reasonDocumentId.length) : options.bytes === Array ? Array.prototype.slice.call(message.reasonDocumentId) : message.reasonDocumentId; return object; }; diff --git a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js index fe1a9322bd1..9e0d1874e0c 100644 --- a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js +++ b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js @@ -23803,6 +23803,7 @@ $root.org = (function() { * @property {number|null} [code] ContractModerationReason code * @property {string|null} [text] ContractModerationReason text * @property {Array.|null} [documents] ContractModerationReason documents + * @property {Uint8Array|null} [reasonDocumentId] ContractModerationReason reasonDocumentId */ /** @@ -23845,6 +23846,14 @@ $root.org = (function() { */ ContractModerationReason.prototype.documents = $util.emptyArray; + /** + * ContractModerationReason reasonDocumentId. + * @member {Uint8Array} reasonDocumentId + * @memberof org.dash.platform.dapi.v0.ContractModerationReason + * @instance + */ + ContractModerationReason.prototype.reasonDocumentId = $util.newBuffer([]); + /** * Creates a new ContractModerationReason instance using the specified properties. * @function create @@ -23876,6 +23885,8 @@ $root.org = (function() { if (message.documents != null && message.documents.length) for (var i = 0; i < message.documents.length; ++i) $root.org.dash.platform.dapi.v0.ContractModerationDocument.encode(message.documents[i], writer.uint32(/* id 3, wireType 2 =*/26).fork()).ldelim(); + if (message.reasonDocumentId != null && Object.hasOwnProperty.call(message, "reasonDocumentId")) + writer.uint32(/* id 4, wireType 2 =*/34).bytes(message.reasonDocumentId); return writer; }; @@ -23921,6 +23932,9 @@ $root.org = (function() { message.documents = []; message.documents.push($root.org.dash.platform.dapi.v0.ContractModerationDocument.decode(reader, reader.uint32())); break; + case 4: + message.reasonDocumentId = reader.bytes(); + break; default: reader.skipType(tag & 7); break; @@ -23971,6 +23985,9 @@ $root.org = (function() { return "documents." + error; } } + if (message.reasonDocumentId != null && message.hasOwnProperty("reasonDocumentId")) + if (!(message.reasonDocumentId && typeof message.reasonDocumentId.length === "number" || $util.isString(message.reasonDocumentId))) + return "reasonDocumentId: buffer expected"; return null; }; @@ -24000,6 +24017,11 @@ $root.org = (function() { message.documents[i] = $root.org.dash.platform.dapi.v0.ContractModerationDocument.fromObject(object.documents[i]); } } + if (object.reasonDocumentId != null) + if (typeof object.reasonDocumentId === "string") + $util.base64.decode(object.reasonDocumentId, message.reasonDocumentId = $util.newBuffer($util.base64.length(object.reasonDocumentId)), 0); + else if (object.reasonDocumentId.length >= 0) + message.reasonDocumentId = object.reasonDocumentId; return message; }; @@ -24021,6 +24043,13 @@ $root.org = (function() { if (options.defaults) { object.code = 0; object.text = ""; + if (options.bytes === String) + object.reasonDocumentId = ""; + else { + object.reasonDocumentId = []; + if (options.bytes !== Array) + object.reasonDocumentId = $util.newBuffer(object.reasonDocumentId); + } } if (message.code != null && message.hasOwnProperty("code")) object.code = message.code; @@ -24031,6 +24060,8 @@ $root.org = (function() { for (var j = 0; j < message.documents.length; ++j) object.documents[j] = $root.org.dash.platform.dapi.v0.ContractModerationDocument.toObject(message.documents[j], options); } + if (message.reasonDocumentId != null && message.hasOwnProperty("reasonDocumentId")) + object.reasonDocumentId = options.bytes === String ? $util.base64.encode(message.reasonDocumentId, 0, message.reasonDocumentId.length) : options.bytes === Array ? Array.prototype.slice.call(message.reasonDocumentId) : message.reasonDocumentId; return object; }; diff --git a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js index 54dc934ca3e..fa87ce9ee2a 100644 --- a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js +++ b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js @@ -29829,7 +29829,8 @@ proto.org.dash.platform.dapi.v0.ContractModerationReason.toObject = function(inc code: jspb.Message.getFieldWithDefault(msg, 1, 0), text: jspb.Message.getFieldWithDefault(msg, 2, ""), documentsList: jspb.Message.toObjectList(msg.getDocumentsList(), - proto.org.dash.platform.dapi.v0.ContractModerationDocument.toObject, includeInstance) + proto.org.dash.platform.dapi.v0.ContractModerationDocument.toObject, includeInstance), + reasonDocumentId: msg.getReasonDocumentId_asB64() }; if (includeInstance) { @@ -29879,6 +29880,10 @@ proto.org.dash.platform.dapi.v0.ContractModerationReason.deserializeBinaryFromRe reader.readMessage(value,proto.org.dash.platform.dapi.v0.ContractModerationDocument.deserializeBinaryFromReader); msg.addDocuments(value); break; + case 4: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setReasonDocumentId(value); + break; default: reader.skipField(); break; @@ -29930,6 +29935,13 @@ proto.org.dash.platform.dapi.v0.ContractModerationReason.serializeBinaryToWriter proto.org.dash.platform.dapi.v0.ContractModerationDocument.serializeBinaryToWriter ); } + f = /** @type {!(string|Uint8Array)} */ (jspb.Message.getField(message, 4)); + if (f != null) { + writer.writeBytes( + 4, + f + ); + } }; @@ -30025,6 +30037,66 @@ proto.org.dash.platform.dapi.v0.ContractModerationReason.prototype.clearDocument }; +/** + * optional bytes reason_document_id = 4; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.ContractModerationReason.prototype.getReasonDocumentId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +}; + + +/** + * optional bytes reason_document_id = 4; + * This is a type-conversion wrapper around `getReasonDocumentId()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.ContractModerationReason.prototype.getReasonDocumentId_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getReasonDocumentId())); +}; + + +/** + * optional bytes reason_document_id = 4; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getReasonDocumentId()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.ContractModerationReason.prototype.getReasonDocumentId_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getReasonDocumentId())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.ContractModerationReason} returns this + */ +proto.org.dash.platform.dapi.v0.ContractModerationReason.prototype.setReasonDocumentId = function(value) { + return jspb.Message.setField(this, 4, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.ContractModerationReason} returns this + */ +proto.org.dash.platform.dapi.v0.ContractModerationReason.prototype.clearReasonDocumentId = function() { + return jspb.Message.setField(this, 4, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.ContractModerationReason.prototype.hasReasonDocumentId = function() { + return jspb.Message.getField(this, 4) != null; +}; + + diff --git a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h index 3606e8786a6..da54ca04964 100644 --- a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h +++ b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h @@ -3006,12 +3006,13 @@ typedef GPB_ENUM(ContractModerationReason_FieldNumber) { ContractModerationReason_FieldNumber_Code = 1, ContractModerationReason_FieldNumber_Text = 2, ContractModerationReason_FieldNumber_DocumentsArray = 3, + ContractModerationReason_FieldNumber_ReasonDocumentId = 4, }; /** * Why a moderator banned, suspended or warned an identity, or deleted a * document. Nothing checks what a moderator writes, and the documents cited - * are not looked up. + * are not looked up, except the reason document a seated elected team names. **/ GPB_FINAL @interface ContractModerationReason : GPBMessage @@ -3027,6 +3028,11 @@ GPB_FINAL @interface ContractModerationReason : GPBMessage /** The number of items in @c documentsArray without causing the array to be created. */ @property(nonatomic, readonly) NSUInteger documentsArray_Count; +/** The 32-byte id of the moderation charters contract's `reason` */ +@property(nonatomic, readwrite, copy, null_resettable) NSData *reasonDocumentId; +/** Test to see if @c reasonDocumentId has been set. */ +@property(nonatomic, readwrite) BOOL hasReasonDocumentId; + @end #pragma mark - ContractWarning diff --git a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m index 0b15165621b..676ed5bea3e 100644 --- a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m +++ b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m @@ -6304,12 +6304,14 @@ @implementation ContractModerationReason @dynamic hasCode, code; @dynamic text; @dynamic documentsArray, documentsArray_Count; +@dynamic hasReasonDocumentId, reasonDocumentId; typedef struct ContractModerationReason__storage_ { uint32_t _has_storage_[1]; uint32_t code; NSString *text; NSMutableArray *documentsArray; + NSData *reasonDocumentId; } ContractModerationReason__storage_; // This method is threadsafe because it is initially called @@ -6345,6 +6347,15 @@ + (GPBDescriptor *)descriptor { .flags = GPBFieldRepeated, .dataType = GPBDataTypeMessage, }, + { + .name = "reasonDocumentId", + .dataTypeSpecific.clazz = Nil, + .number = ContractModerationReason_FieldNumber_ReasonDocumentId, + .hasIndex = 2, + .offset = (uint32_t)offsetof(ContractModerationReason__storage_, reasonDocumentId), + .flags = GPBFieldOptional, + .dataType = GPBDataTypeBytes, + }, }; GPBDescriptor *localDescriptor = [GPBDescriptor allocDescriptorForClass:[ContractModerationReason class] diff --git a/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py b/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py index ba7846cf43d..704d8452641 100644 --- a/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py +++ b/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py @@ -23,7 +23,7 @@ syntax='proto3', serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\x0eplatform.proto\x12\x19org.dash.platform.dapi.v0\x1a\x1egoogle/protobuf/wrappers.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x81\x01\n\x05Proof\x12\x15\n\rgrovedb_proof\x18\x01 \x01(\x0c\x12\x13\n\x0bquorum_hash\x18\x02 \x01(\x0c\x12\x11\n\tsignature\x18\x03 \x01(\x0c\x12\r\n\x05round\x18\x04 \x01(\r\x12\x15\n\rblock_id_hash\x18\x05 \x01(\x0c\x12\x13\n\x0bquorum_type\x18\x06 \x01(\r\"\x98\x01\n\x10ResponseMetadata\x12\x12\n\x06height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12 \n\x18\x63ore_chain_locked_height\x18\x02 \x01(\r\x12\r\n\x05\x65poch\x18\x03 \x01(\r\x12\x13\n\x07time_ms\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x18\n\x10protocol_version\x18\x05 \x01(\r\x12\x10\n\x08\x63hain_id\x18\x06 \x01(\t\"L\n\x1dStateTransitionBroadcastError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\";\n\x1f\x42roadcastStateTransitionRequest\x12\x18\n\x10state_transition\x18\x01 \x01(\x0c\"\"\n BroadcastStateTransitionResponse\"\xa4\x01\n\x12GetIdentityRequest\x12P\n\x02v0\x18\x01 \x01(\x0b\x32\x42.org.dash.platform.dapi.v0.GetIdentityRequest.GetIdentityRequestV0H\x00\x1a\x31\n\x14GetIdentityRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xc1\x01\n\x17GetIdentityNonceRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentityNonceRequest.GetIdentityNonceRequestV0H\x00\x1a?\n\x19GetIdentityNonceRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf6\x01\n\x1fGetIdentityContractNonceRequest\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentityContractNonceRequest.GetIdentityContractNonceRequestV0H\x00\x1a\\\n!GetIdentityContractNonceRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x13\n\x0b\x63ontract_id\x18\x02 \x01(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xc0\x01\n\x19GetIdentityBalanceRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetIdentityBalanceRequest.GetIdentityBalanceRequestV0H\x00\x1a\x38\n\x1bGetIdentityBalanceRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xec\x01\n$GetIdentityBalanceAndRevisionRequest\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionRequest.GetIdentityBalanceAndRevisionRequestV0H\x00\x1a\x43\n&GetIdentityBalanceAndRevisionRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9e\x02\n\x13GetIdentityResponse\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetIdentityResponse.GetIdentityResponseV0H\x00\x1a\xa7\x01\n\x15GetIdentityResponseV0\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbc\x02\n\x18GetIdentityNonceResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetIdentityNonceResponse.GetIdentityNonceResponseV0H\x00\x1a\xb6\x01\n\x1aGetIdentityNonceResponseV0\x12\x1c\n\x0eidentity_nonce\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xe5\x02\n GetIdentityContractNonceResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse.GetIdentityContractNonceResponseV0H\x00\x1a\xc7\x01\n\"GetIdentityContractNonceResponseV0\x12%\n\x17identity_contract_nonce\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\x8e\x02\n&GetIdentityKeysRemainingBudgetsRequest\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsRequest.GetIdentityKeysRemainingBudgetsRequestV0H\x00\x1a_\n(GetIdentityKeysRemainingBudgetsRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x0f\n\x07key_ids\x18\x02 \x03(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\x96\x06\n\'GetIdentityKeysRemainingBudgetsResponse\x12z\n\x02v0\x18\x01 \x01(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsResponse.GetIdentityKeysRemainingBudgetsResponseV0H\x00\x1a\xe3\x04\n)GetIdentityKeysRemainingBudgetsResponseV0\x12\xa4\x01\n\x16keys_remaining_budgets\x18\x01 \x01(\x0b\x32\x81\x01.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsResponse.GetIdentityKeysRemainingBudgetsResponseV0.KeysRemainingBudgetsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x61\n\x17KeyRemainingBudgetEntry\x12\x0e\n\x06key_id\x18\x01 \x01(\r\x12!\n\x10remaining_budget\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x42\x13\n\x11_remaining_budget\x1a\xaf\x01\n\x14KeysRemainingBudgets\x12\x96\x01\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsResponse.GetIdentityKeysRemainingBudgetsResponseV0.KeyRemainingBudgetEntryB\x08\n\x06resultB\t\n\x07version\"\xbd\x02\n\x1aGetIdentityBalanceResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetIdentityBalanceResponse.GetIdentityBalanceResponseV0H\x00\x1a\xb1\x01\n\x1cGetIdentityBalanceResponseV0\x12\x15\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb1\x04\n%GetIdentityBalanceAndRevisionResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0H\x00\x1a\x84\x03\n\'GetIdentityBalanceAndRevisionResponseV0\x12\x9b\x01\n\x14\x62\x61lance_and_revision\x18\x01 \x01(\x0b\x32{.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0.BalanceAndRevisionH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a?\n\x12\x42\x61lanceAndRevision\x12\x13\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x14\n\x08revision\x18\x02 \x01(\x04\x42\x02\x30\x01\x42\x08\n\x06resultB\t\n\x07version\"\xd1\x01\n\x0eKeyRequestType\x12\x36\n\x08\x61ll_keys\x18\x01 \x01(\x0b\x32\".org.dash.platform.dapi.v0.AllKeysH\x00\x12@\n\rspecific_keys\x18\x02 \x01(\x0b\x32\'.org.dash.platform.dapi.v0.SpecificKeysH\x00\x12:\n\nsearch_key\x18\x03 \x01(\x0b\x32$.org.dash.platform.dapi.v0.SearchKeyH\x00\x42\t\n\x07request\"\t\n\x07\x41llKeys\"\x1f\n\x0cSpecificKeys\x12\x0f\n\x07key_ids\x18\x01 \x03(\r\"\xb6\x01\n\tSearchKey\x12I\n\x0bpurpose_map\x18\x01 \x03(\x0b\x32\x34.org.dash.platform.dapi.v0.SearchKey.PurposeMapEntry\x1a^\n\x0fPurposeMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.org.dash.platform.dapi.v0.SecurityLevelMap:\x02\x38\x01\"\xbf\x02\n\x10SecurityLevelMap\x12]\n\x12security_level_map\x18\x01 \x03(\x0b\x32\x41.org.dash.platform.dapi.v0.SecurityLevelMap.SecurityLevelMapEntry\x1aw\n\x15SecurityLevelMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12M\n\x05value\x18\x02 \x01(\x0e\x32>.org.dash.platform.dapi.v0.SecurityLevelMap.KeyKindRequestType:\x02\x38\x01\"S\n\x12KeyKindRequestType\x12\x1f\n\x1b\x43URRENT_KEY_OF_KIND_REQUEST\x10\x00\x12\x1c\n\x18\x41LL_KEYS_OF_KIND_REQUEST\x10\x01\"\xda\x02\n\x16GetIdentityKeysRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetIdentityKeysRequest.GetIdentityKeysRequestV0H\x00\x1a\xda\x01\n\x18GetIdentityKeysRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12?\n\x0crequest_type\x18\x02 \x01(\x0b\x32).org.dash.platform.dapi.v0.KeyRequestType\x12+\n\x05limit\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\x99\x03\n\x17GetIdentityKeysResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentityKeysResponse.GetIdentityKeysResponseV0H\x00\x1a\x96\x02\n\x19GetIdentityKeysResponseV0\x12\x61\n\x04keys\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetIdentityKeysResponse.GetIdentityKeysResponseV0.KeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\x04Keys\x12\x12\n\nkeys_bytes\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xef\x02\n GetIdentitiesContractKeysRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentitiesContractKeysRequest.GetIdentitiesContractKeysRequestV0H\x00\x1a\xd1\x01\n\"GetIdentitiesContractKeysRequestV0\x12\x16\n\x0eidentities_ids\x18\x01 \x03(\x0c\x12\x13\n\x0b\x63ontract_id\x18\x02 \x01(\x0c\x12\x1f\n\x12\x64ocument_type_name\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x37\n\x08purposes\x18\x04 \x03(\x0e\x32%.org.dash.platform.dapi.v0.KeyPurpose\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x15\n\x13_document_type_nameB\t\n\x07version\"\xdf\x06\n!GetIdentitiesContractKeysResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0H\x00\x1a\xbe\x05\n#GetIdentitiesContractKeysResponseV0\x12\x8a\x01\n\x0fidentities_keys\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.IdentitiesKeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aY\n\x0bPurposeKeys\x12\x36\n\x07purpose\x18\x01 \x01(\x0e\x32%.org.dash.platform.dapi.v0.KeyPurpose\x12\x12\n\nkeys_bytes\x18\x02 \x03(\x0c\x1a\x9f\x01\n\x0cIdentityKeys\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12z\n\x04keys\x18\x02 \x03(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.PurposeKeys\x1a\x90\x01\n\x0eIdentitiesKeys\x12~\n\x07\x65ntries\x18\x01 \x03(\x0b\x32m.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.IdentityKeysB\x08\n\x06resultB\t\n\x07version\"\xa4\x02\n*GetEvonodesProposedEpochBlocksByIdsRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0H\x00\x1ah\n,GetEvonodesProposedEpochBlocksByIdsRequestV0\x12\x12\n\x05\x65poch\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x0b\n\x03ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\x08\n\x06_epochB\t\n\x07version\"\x92\x06\n&GetEvonodesProposedEpochBlocksResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0H\x00\x1a\xe2\x04\n(GetEvonodesProposedEpochBlocksResponseV0\x12\xb1\x01\n#evonodes_proposed_block_counts_info\x18\x01 \x01(\x0b\x32\x81\x01.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0.EvonodesProposedBlocksH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a?\n\x15\x45vonodeProposedBlocks\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x11\n\x05\x63ount\x18\x02 \x01(\x04\x42\x02\x30\x01\x1a\xc4\x01\n\x16\x45vonodesProposedBlocks\x12\xa9\x01\n\x1e\x65vonodes_proposed_block_counts\x18\x01 \x03(\x0b\x32\x80\x01.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0.EvonodeProposedBlocksB\x08\n\x06resultB\t\n\x07version\"\xf2\x02\n,GetEvonodesProposedEpochBlocksByRangeRequest\x12\x84\x01\n\x02v0\x18\x01 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0H\x00\x1a\xaf\x01\n.GetEvonodesProposedEpochBlocksByRangeRequestV0\x12\x12\n\x05\x65poch\x18\x01 \x01(\rH\x01\x88\x01\x01\x12\x12\n\x05limit\x18\x02 \x01(\rH\x02\x88\x01\x01\x12\x15\n\x0bstart_after\x18\x03 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x04 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x07\n\x05startB\x08\n\x06_epochB\x08\n\x06_limitB\t\n\x07version\"\xcd\x01\n\x1cGetIdentitiesBalancesRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0H\x00\x1a<\n\x1eGetIdentitiesBalancesRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9f\x05\n\x1dGetIdentitiesBalancesResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0H\x00\x1a\x8a\x04\n\x1fGetIdentitiesBalancesResponseV0\x12\x8a\x01\n\x13identities_balances\x18\x01 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0.IdentitiesBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aL\n\x0fIdentityBalance\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x18\n\x07\x62\x61lance\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\x8f\x01\n\x12IdentitiesBalances\x12y\n\x07\x65ntries\x18\x01 \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0.IdentityBalanceB\x08\n\x06resultB\t\n\x07version\"\xb4\x01\n\x16GetDataContractRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetDataContractRequest.GetDataContractRequestV0H\x00\x1a\x35\n\x18GetDataContractRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xb3\x02\n\x17GetDataContractResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetDataContractResponse.GetDataContractResponseV0H\x00\x1a\xb0\x01\n\x19GetDataContractResponseV0\x12\x17\n\rdata_contract\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\x8c\x02\n%GetDataContractsLatestVersionsRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsRequest.GetDataContractsLatestVersionsRequestV0H\x00\x1a`\n\'GetDataContractsLatestVersionsRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\x19\n\x11include_contracts\x18\x02 \x01(\x08\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xfa\x05\n&GetDataContractsLatestVersionsResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsResponse.GetDataContractsLatestVersionsResponseV0H\x00\x1a\x84\x01\n\x1e\x44\x61taContractLatestVersionEntry\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x14\n\x07version\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x1a\n\rdata_contract\x18\x03 \x01(\x0cH\x01\x88\x01\x01\x42\n\n\x08_versionB\x10\n\x0e_data_contract\x1a\x90\x01\n\x1b\x44\x61taContractsLatestVersions\x12q\n\x07\x65ntries\x18\x01 \x03(\x0b\x32`.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsResponse.DataContractLatestVersionEntry\x1a\xb0\x02\n(GetDataContractsLatestVersionsResponseV0\x12\x87\x01\n\x1e\x64\x61ta_contracts_latest_versions\x18\x01 \x01(\x0b\x32].org.dash.platform.dapi.v0.GetDataContractsLatestVersionsResponse.DataContractsLatestVersionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"R\n\x1f\x43ontractGroupDocumentTypeMember\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\"G\n\x18\x43ontractGroupTokenMember\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x16\n\x0etoken_position\x18\x02 \x01(\r\"\xd7\x01\n\x1bGetContractGroupInfoRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetContractGroupInfoRequest.GetContractGroupInfoRequestV0H\x00\x1aI\n\x1dGetContractGroupInfoRequestV0\x12\x19\n\x11\x63ontract_group_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x98\x04\n\x1cGetContractGroupInfoResponse\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetContractGroupInfoResponse.GetContractGroupInfoResponseV0H\x00\x1a~\n\x11\x43ontractGroupInfo\x12\x10\n\x08owner_id\x18\x01 \x01(\x0c\x12\x11\n\tadmin_ids\x18\x02 \x03(\x0c\x12\x11\n\x04name\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x18\n\x0b\x64\x65scription\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\x07\n\x05_nameB\x0e\n\x0c_description\x1a\x86\x02\n\x1eGetContractGroupInfoResponseV0\x12h\n\x13\x63ontract_group_info\x18\x01 \x01(\x0b\x32I.org.dash.platform.dapi.v0.GetContractGroupInfoResponse.ContractGroupInfoH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xf8\x06\n\x1eGetContractGroupMembersRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetContractGroupMembersRequest.GetContractGroupMembersRequestV0H\x00\x1a@\n\x14\x43ontractMembersQuery\x12\x18\n\x0bstart_after\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x42\x0e\n\x0c_start_after\x1a\x80\x01\n\x18\x44ocumentTypeMembersQuery\x12T\n\x0bstart_after\x18\x01 \x01(\x0b\x32:.org.dash.platform.dapi.v0.ContractGroupDocumentTypeMemberH\x00\x88\x01\x01\x42\x0e\n\x0c_start_after\x1ar\n\x11TokenMembersQuery\x12M\n\x0bstart_after\x18\x01 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractGroupTokenMemberH\x00\x88\x01\x01\x42\x0e\n\x0c_start_after\x1a\xa7\x03\n GetContractGroupMembersRequestV0\x12\x19\n\x11\x63ontract_group_id\x18\x01 \x01(\x0c\x12\x63\n\tcontracts\x18\x02 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetContractGroupMembersRequest.ContractMembersQueryH\x00\x12l\n\x0e\x64ocument_types\x18\x03 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetContractGroupMembersRequest.DocumentTypeMembersQueryH\x00\x12]\n\x06tokens\x18\x04 \x01(\x0b\x32K.org.dash.platform.dapi.v0.GetContractGroupMembersRequest.TokenMembersQueryH\x00\x12\x12\n\x05limit\x18\x05 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x42\t\n\x07membersB\x08\n\x06_limitB\t\n\x07version\"\xc9\x06\n\x1fGetContractGroupMembersResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetContractGroupMembersResponse.GetContractGroupMembersResponseV0H\x00\x1a\'\n\x0f\x43ontractMembers\x12\x14\n\x0c\x63ontract_ids\x18\x01 \x03(\x0c\x1ai\n\x13\x44ocumentTypeMembers\x12R\n\x0e\x64ocument_types\x18\x01 \x03(\x0b\x32:.org.dash.platform.dapi.v0.ContractGroupDocumentTypeMember\x1aS\n\x0cTokenMembers\x12\x43\n\x06tokens\x18\x01 \x03(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractGroupTokenMember\x1a\xc5\x03\n!GetContractGroupMembersResponseV0\x12_\n\tcontracts\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetContractGroupMembersResponse.ContractMembersH\x00\x12h\n\x0e\x64ocument_types\x18\x02 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetContractGroupMembersResponse.DocumentTypeMembersH\x00\x12Y\n\x06tokens\x18\x03 \x01(\x0b\x32G.org.dash.platform.dapi.v0.GetContractGroupMembersResponse.TokenMembersH\x00\x12\x31\n\x05proof\x18\x04 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x05 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"M\n\x1a\x43ontractModerationDocument\x12\x1a\n\x12\x64ocument_type_name\x18\x01 \x01(\t\x12\x13\n\x0b\x64ocument_id\x18\x02 \x01(\x0c\"\x8e\x01\n\x18\x43ontractModerationReason\x12\x11\n\x04\x63ode\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x0c\n\x04text\x18\x02 \x01(\t\x12H\n\tdocuments\x18\x03 \x03(\x0b\x32\x35.org.dash.platform.dapi.v0.ContractModerationDocumentB\x07\n\x05_code\"i\n\x0f\x43ontractWarning\x12\x11\n\twarned_at\x18\x01 \x01(\x04\x12\x43\n\x06reason\x18\x02 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReason\"\xc5\x02\n\"GetContractModerationStatusRequest\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetContractModerationStatusRequest.GetContractModerationStatusRequestV0H\x00\x1a\xa1\x01\n$GetContractModerationStatusRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x13\n\x0bidentity_id\x18\x02 \x01(\x0c\x12@\n\x05lists\x18\x03 \x03(\x0e\x32\x31.org.dash.platform.dapi.v0.ContractModerationList\x12\r\n\x05prove\x18\x04 \x01(\x08\x42\t\n\x07version\"\xec\x06\n#GetContractModerationStatusResponse\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractModerationStatusResponse.GetContractModerationStatusResponseV0H\x00\x1a\xb4\x03\n\x18\x43ontractModerationStatus\x12\x13\n\x06\x62\x61nned\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x1c\n\x0fsuspended_until\x18\x02 \x01(\x04H\x01\x88\x01\x01\x12@\n\x05lists\x18\x03 \x03(\x0e\x32\x31.org.dash.platform.dapi.v0.ContractModerationList\x12L\n\nban_reason\x18\x04 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReasonH\x02\x88\x01\x01\x12S\n\x11suspension_reason\x18\x05 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReasonH\x03\x88\x01\x01\x12<\n\x08warnings\x18\x06 \x03(\x0b\x32*.org.dash.platform.dapi.v0.ContractWarningB\t\n\x07_bannedB\x12\n\x10_suspended_untilB\r\n\x0b_ban_reasonB\x14\n\x12_suspension_reason\x1a\x8e\x02\n%GetContractModerationStatusResponseV0\x12i\n\x06status\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetContractModerationStatusResponse.ContractModerationStatusH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xfb\x02\n#GetContractModerationEntriesRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractModerationEntriesRequest.GetContractModerationEntriesRequestV0H\x00\x1a\xd4\x01\n%GetContractModerationEntriesRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12?\n\x04list\x18\x02 \x01(\x0e\x32\x31.org.dash.platform.dapi.v0.ContractModerationList\x12\x18\n\x0bstart_after\x18\x03 \x01(\x0cH\x00\x88\x01\x01\x12\x12\n\x05limit\x18\x04 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x0e\n\x0c_start_afterB\x08\n\x06_limitB\t\n\x07version\"\x96\x06\n$GetContractModerationEntriesResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContractModerationEntriesResponse.GetContractModerationEntriesResponseV0H\x00\x1a\xcf\x01\n\x17\x43ontractModerationEntry\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x12\n\x05until\x18\x02 \x01(\x04H\x00\x88\x01\x01\x12\x43\n\x06reason\x18\x03 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReason\x12<\n\x08warnings\x18\x04 \x03(\x0b\x32*.org.dash.platform.dapi.v0.ContractWarningB\x08\n\x06_until\x1a\x85\x01\n\x19\x43ontractModerationEntries\x12h\n\x07\x65ntries\x18\x01 \x03(\x0b\x32W.org.dash.platform.dapi.v0.GetContractModerationEntriesResponse.ContractModerationEntry\x1a\x92\x02\n&GetContractModerationEntriesResponseV0\x12l\n\x07\x65ntries\x18\x01 \x01(\x0b\x32Y.org.dash.platform.dapi.v0.GetContractModerationEntriesResponse.ContractModerationEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc3\x04\n\"GetContractDocumentRemovalsRequest\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetContractDocumentRemovalsRequest.GetContractDocumentRemovalsRequestV0H\x00\x1a#\n\x0b\x44ocumentIds\x12\x14\n\x0c\x64ocument_ids\x18\x01 \x03(\x0c\x1aN\n\x04Page\x12\x18\n\x0bstart_after\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x12\n\x05limit\x18\x02 \x01(\rH\x01\x88\x01\x01\x42\x0e\n\x0c_start_afterB\x08\n\x06_limit\x1a\xaa\x02\n$GetContractDocumentRemovalsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x61\n\x0c\x64ocument_ids\x18\x03 \x01(\x0b\x32I.org.dash.platform.dapi.v0.GetContractDocumentRemovalsRequest.DocumentIdsH\x00\x12R\n\x04page\x18\x04 \x01(\x0b\x32\x42.org.dash.platform.dapi.v0.GetContractDocumentRemovalsRequest.PageH\x00\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x0b\n\tselectionB\t\n\x07version\"\xcb\x07\n#GetContractDocumentRemovalsResponse\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.GetContractDocumentRemovalsResponseV0H\x00\x1aH\n\x1b\x43ontractDocumentRestoration\x12\x14\n\x0cmoderator_id\x18\x01 \x01(\x0c\x12\x13\n\x0brestored_at\x18\x02 \x01(\x04\x1a\xc0\x02\n\x17\x43ontractDocumentRemoval\x12\x13\n\x0b\x64ocument_id\x18\x01 \x01(\x0c\x12\x19\n\x11\x64ocument_owner_id\x18\x02 \x01(\x0c\x12\x14\n\x0cmoderator_id\x18\x03 \x01(\x0c\x12\x12\n\nremoved_at\x18\x04 \x01(\x04\x12\x43\n\x06reason\x18\x05 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReason\x12\x15\n\rdocument_hash\x18\x06 \x01(\x0c\x12o\n\x0brestoration\x18\x07 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.ContractDocumentRestoration\x1a\x84\x01\n\x18\x43ontractDocumentRemovals\x12h\n\x08removals\x18\x01 \x03(\x0b\x32V.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.ContractDocumentRemoval\x1a\x90\x02\n%GetContractDocumentRemovalsResponseV0\x12k\n\x08removals\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.ContractDocumentRemovalsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc9\x01\n\x19GetContractFeePotsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetContractFeePotsRequest.GetContractFeePotsRequestV0H\x00\x1a\x41\n\x1bGetContractFeePotsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9f\x06\n\x1aGetContractFeePotsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetContractFeePotsResponse.GetContractFeePotsResponseV0H\x00\x1aR\n\x17\x43ontractFeePotLastClaim\x12\r\n\x05\x65poch\x18\x01 \x01(\r\x12\x13\n\x07time_ms\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x13\n\x0b\x63laimant_id\x18\x03 \x01(\x0c\x1a\x88\x01\n\x0e\x43ontractFeePot\x12\x13\n\x07\x63redits\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x61\n\nlast_claim\x18\x02 \x01(\x0b\x32M.org.dash.platform.dapi.v0.GetContractFeePotsResponse.ContractFeePotLastClaim\x1a\xc0\x01\n\x0f\x43ontractFeePots\x12S\n\x05owner\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetContractFeePotsResponse.ContractFeePot\x12X\n\nmoderators\x18\x02 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetContractFeePotsResponse.ContractFeePot\x1a\xf1\x01\n\x1cGetContractFeePotsResponseV0\x12U\n\x04pots\x18\x01 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetContractFeePotsResponse.ContractFeePotsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xf1\x01\n#GetContractGroupsForContractRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractGroupsForContractRequest.GetContractGroupsForContractRequestV0H\x00\x1aK\n%GetContractGroupsForContractRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf5\x06\n$GetContractGroupsForContractResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse.GetContractGroupsForContractResponseV0H\x00\x1aQ\n\x17\x44ocumentTypeMemberships\x12\x1a\n\x12\x64ocument_type_name\x18\x01 \x01(\t\x12\x1a\n\x12\x63ontract_group_ids\x18\x02 \x03(\x0c\x1a\x46\n\x10TokenMemberships\x12\x16\n\x0etoken_position\x18\x01 \x01(\r\x12\x1a\n\x12\x63ontract_group_ids\x18\x02 \x03(\x0c\x1a\x89\x02\n\x18\x43ontractGroupMemberships\x12\x1a\n\x12\x63ontract_group_ids\x18\x01 \x03(\x0c\x12o\n\x0e\x64ocument_types\x18\x02 \x03(\x0b\x32W.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse.DocumentTypeMemberships\x12`\n\x06tokens\x18\x03 \x03(\x0b\x32P.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse.TokenMemberships\x1a\xa4\x02\n&GetContractGroupsForContractResponseV0\x12~\n\x1a\x63ontract_group_memberships\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse.ContractGroupMembershipsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb9\x01\n\x17GetDataContractsRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetDataContractsRequest.GetDataContractsRequestV0H\x00\x1a\x37\n\x19GetDataContractsRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xad\x02\n\x1eGetDataContractsByRangeRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetDataContractsByRangeRequest.GetDataContractsByRangeRequestV0H\x00\x1a\x95\x01\n GetDataContractsByRangeRequestV0\x12\x12\n\x05limit\x18\x01 \x01(\rH\x01\x88\x01\x01\x12\x15\n\x0bstart_after\x18\x02 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x03 \x01(\x0cH\x00\x12\x10\n\x08ids_only\x18\x04 \x01(\x08\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x07\n\x05startB\x08\n\x06_limitB\t\n\x07version\"\xcf\x04\n\x18GetDataContractsResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetDataContractsResponse.GetDataContractsResponseV0H\x00\x1a[\n\x11\x44\x61taContractEntry\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x32\n\rdata_contract\x18\x02 \x01(\x0b\x32\x1b.google.protobuf.BytesValue\x1au\n\rDataContracts\x12\x64\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32\x45.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractEntry\x1a\xf5\x01\n\x1aGetDataContractsResponseV0\x12[\n\x0e\x64\x61ta_contracts\x18\x01 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc5\x02\n\x1dGetDataContractHistoryRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.GetDataContractHistoryRequestV0H\x00\x1a\xb0\x01\n\x1fGetDataContractHistoryRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12+\n\x05limit\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0bstart_at_ms\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\xb2\x05\n\x1eGetDataContractHistoryResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0H\x00\x1a\x9a\x04\n GetDataContractHistoryResponseV0\x12\x8f\x01\n\x15\x64\x61ta_contract_history\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0.DataContractHistoryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a;\n\x18\x44\x61taContractHistoryEntry\x12\x10\n\x04\x64\x61te\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05value\x18\x02 \x01(\x0c\x1a\xaa\x01\n\x13\x44\x61taContractHistory\x12\x92\x01\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32s.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0.DataContractHistoryEntryB\x08\n\x06resultB\t\n\x07version\"\xe0\x1f\n\x13GetDocumentsRequest\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV0H\x00\x12R\n\x02v1\x18\x02 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1H\x00\x1a\xfe\x02\n\x12\x44ocumentFieldValue\x12\x14\n\nbool_value\x18\x01 \x01(\x08H\x00\x12\x19\n\x0bint64_value\x18\x02 \x01(\x12\x42\x02\x30\x01H\x00\x12\x1a\n\x0cuint64_value\x18\x03 \x01(\x04\x42\x02\x30\x01H\x00\x12\x16\n\x0c\x64ouble_value\x18\x04 \x01(\x01H\x00\x12\x0e\n\x04text\x18\x05 \x01(\tH\x00\x12\x15\n\x0b\x62ytes_value\x18\x06 \x01(\x0cH\x00\x12[\n\x04list\x18\x07 \x01(\x0b\x32K.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValue.ValueListH\x00\x12\x14\n\nnull_value\x18\x08 \x01(\x08H\x00\x1a^\n\tValueList\x12Q\n\x06values\x18\x01 \x03(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValueB\t\n\x07variant\x1a\xe2\x02\n\x12TimeRangeSelection\x12\\\n\x08selector\x18\x01 \x01(\x0e\x32J.org.dash.platform.dapi.v0.GetDocumentsRequest.TimeRangeSelection.Selector\x12\x19\n\x08start_ms\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x12T\n\x04grid\x18\x03 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetDocumentsRequest.TimeRangeSelection.Grid\x1a>\n\x04Grid\x12\x11\n\x05range\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x10\n\x04step\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x11\n\x05phase\x18\x03 \x01(\x04\x42\x02\x30\x01\"0\n\x08Selector\x12\n\n\x06NEWEST\x10\x00\x12\n\n\x06OLDEST\x10\x01\x12\x0c\n\x08\x42Y_START\x10\x02\x42\x0b\n\t_start_ms\x1a\x95\x02\n\x0bWhereClause\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12N\n\x08operator\x18\x02 \x01(\x0e\x32<.org.dash.platform.dapi.v0.GetDocumentsRequest.WhereOperator\x12P\n\x05value\x18\x03 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValue\x12U\n\ntime_range\x18\x04 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.TimeRangeSelection\x1a\xa4\x01\n\x0fHavingAggregate\x12Y\n\x08\x66unction\x18\x01 \x01(\x0e\x32G.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingAggregate.Function\x12\r\n\x05\x66ield\x18\x02 \x01(\t\"\'\n\x08\x46unction\x12\t\n\x05\x43OUNT\x10\x00\x12\x07\n\x03SUM\x10\x01\x12\x07\n\x03\x41VG\x10\x02\x1a\xf9\x03\n\x0cHavingClause\x12Q\n\taggregate\x18\x01 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingAggregate\x12V\n\x08operator\x18\x02 \x01(\x0e\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingClause.Operator\x12R\n\x05value\x18\x03 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValueH\x00\"\xe0\x01\n\x08Operator\x12\t\n\x05\x45QUAL\x10\x00\x12\r\n\tNOT_EQUAL\x10\x01\x12\x10\n\x0cGREATER_THAN\x10\x02\x12\x1a\n\x16GREATER_THAN_OR_EQUALS\x10\x03\x12\r\n\tLESS_THAN\x10\x04\x12\x17\n\x13LESS_THAN_OR_EQUALS\x10\x05\x12\x0b\n\x07\x42\x45TWEEN\x10\x06\x12\x1a\n\x16\x42\x45TWEEN_EXCLUDE_BOUNDS\x10\x07\x12\x18\n\x14\x42\x45TWEEN_EXCLUDE_LEFT\x10\x08\x12\x19\n\x15\x42\x45TWEEN_EXCLUDE_RIGHT\x10\t\x12\x06\n\x02IN\x10\nB\x07\n\x05right\x1a\x90\x01\n\x0bOrderClause\x12\x0f\n\x05\x66ield\x18\x01 \x01(\tH\x00\x12S\n\taggregate\x18\x03 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingAggregateH\x00\x12\x11\n\tascending\x18\x02 \x01(\x08\x42\x08\n\x06target\x1a\xbb\x01\n\x15GetDocumentsRequestV0\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12\r\n\x05where\x18\x03 \x01(\x0c\x12\x10\n\x08order_by\x18\x04 \x01(\x0c\x12\r\n\x05limit\x18\x05 \x01(\r\x12\x15\n\x0bstart_after\x18\x06 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x07 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x08 \x01(\x08\x42\x07\n\x05start\x1a\xa6\x0c\n\x15GetDocumentsRequestV1\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12Q\n\rwhere_clauses\x18\x03 \x03(\x0b\x32:.org.dash.platform.dapi.v0.GetDocumentsRequest.WhereClause\x12L\n\x08order_by\x18\x04 \x03(\x0b\x32:.org.dash.platform.dapi.v0.GetDocumentsRequest.OrderClause\x12\x12\n\x05limit\x18\x05 \x01(\rH\x01\x88\x01\x01\x12\x15\n\x0bstart_after\x18\x06 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x07 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x08 \x01(\x08\x12\\\n\x07selects\x18\t \x03(\x0b\x32K.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.Select\x12\x10\n\x08group_by\x18\n \x03(\t\x12K\n\x06having\x18\x0b \x03(\x0b\x32;.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingClause\x12\x13\n\x06offset\x18\x0c \x01(\rH\x02\x88\x01\x01\x12\x61\n\x07\x63hained\x18\r \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.ChainedJoin\x12\x62\n\x0bsub_queries\x18\x0e \x03(\x0b\x32M.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.SubQuery\x1a\xc9\x01\n\x06Select\x12\x66\n\x08\x66unction\x18\x01 \x01(\x0e\x32T.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.Select.Function\x12\r\n\x05\x66ield\x18\x02 \x01(\t\"H\n\x08\x46unction\x12\r\n\tDOCUMENTS\x10\x00\x12\t\n\x05\x43OUNT\x10\x01\x12\x07\n\x03SUM\x10\x02\x12\x07\n\x03\x41VG\x10\x03\x12\x07\n\x03MIN\x10\x04\x12\x07\n\x03MAX\x10\x05\x1a\x41\n\x0b\x43hainedJoin\x12\x15\n\rjoin_property\x18\x01 \x01(\t\x12\x1b\n\x13outer_document_type\x18\x02 \x01(\t\x1a\xa6\x04\n\x08SubQuery\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12Q\n\rwhere_clauses\x18\x03 \x03(\x0b\x32:.org.dash.platform.dapi.v0.GetDocumentsRequest.WhereClause\x12L\n\x08order_by\x18\x04 \x03(\x0b\x32:.org.dash.platform.dapi.v0.GetDocumentsRequest.OrderClause\x12\x12\n\x05limit\x18\x05 \x01(\rH\x00\x88\x01\x01\x12`\n\x04kind\x18\x06 \x01(\x0e\x32R.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.SubQuery.Kind\x12\x63\n\x04\x62ind\x18\x07 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.SubQuery.Binding\x1a\x41\n\x07\x42inding\x12\x0e\n\x06source\x18\x01 \x01(\r\x12\x17\n\x0fsource_property\x18\x02 \x01(\t\x12\r\n\x05\x66ield\x18\x03 \x01(\t\" \n\x04Kind\x12\r\n\tDOCUMENTS\x10\x00\x12\t\n\x05\x43OUNT\x10\x01\x42\x08\n\x06_limitB\x07\n\x05startB\x08\n\x06_limitB\t\n\x07_offset\"\xfa\x01\n\rWhereOperator\x12\t\n\x05\x45QUAL\x10\x00\x12\x10\n\x0cGREATER_THAN\x10\x01\x12\x1a\n\x16GREATER_THAN_OR_EQUALS\x10\x02\x12\r\n\tLESS_THAN\x10\x03\x12\x17\n\x13LESS_THAN_OR_EQUALS\x10\x04\x12\x0b\n\x07\x42\x45TWEEN\x10\x05\x12\x1a\n\x16\x42\x45TWEEN_EXCLUDE_BOUNDS\x10\x06\x12\x18\n\x14\x42\x45TWEEN_EXCLUDE_LEFT\x10\x07\x12\x19\n\x15\x42\x45TWEEN_EXCLUDE_RIGHT\x10\x08\x12\x06\n\x02IN\x10\t\x12\x0f\n\x0bSTARTS_WITH\x10\n\x12\x11\n\rIN_TIME_RANGE\x10\x0b\x42\t\n\x07version\"\xf2\x1b\n\x14GetDocumentsResponse\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0H\x00\x12T\n\x02v1\x18\x02 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1H\x00\x1a\x9b\x02\n\x16GetDocumentsResponseV0\x12\x65\n\tdocuments\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0.DocumentsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1e\n\tDocuments\x12\x11\n\tdocuments\x18\x01 \x03(\x0c\x42\x08\n\x06result\x1a\x84\x18\n\x16GetDocumentsResponseV1\x12\x61\n\x04\x64\x61ta\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.ResultDataH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1e\n\tDocuments\x12\x11\n\tdocuments\x18\x01 \x03(\x0c\x1aL\n\nCountEntry\x12\x13\n\x06in_key\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x0b\n\x03key\x18\x02 \x01(\x0c\x12\x11\n\x05\x63ount\x18\x03 \x01(\x04\x42\x02\x30\x01\x42\t\n\x07_in_key\x1ar\n\x0c\x43ountEntries\x12\x62\n\x07\x65ntries\x18\x01 \x03(\x0b\x32Q.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CountEntry\x1a\xa0\x01\n\x0c\x43ountResults\x12\x1d\n\x0f\x61ggregate_count\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x66\n\x07\x65ntries\x18\x02 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CountEntriesH\x00\x42\t\n\x07variant\x1aH\n\x08SumEntry\x12\x13\n\x06in_key\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x0b\n\x03key\x18\x02 \x01(\x0c\x12\x0f\n\x03sum\x18\x03 \x01(\x12\x42\x02\x30\x01\x42\t\n\x07_in_key\x1an\n\nSumEntries\x12`\n\x07\x65ntries\x18\x01 \x03(\x0b\x32O.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.SumEntry\x1a\x9a\x01\n\nSumResults\x12\x1b\n\raggregate_sum\x18\x01 \x01(\x12\x42\x02\x30\x01H\x00\x12\x64\n\x07\x65ntries\x18\x02 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.SumEntriesH\x00\x42\t\n\x07variant\x1a_\n\x0c\x41verageEntry\x12\x13\n\x06in_key\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x0b\n\x03key\x18\x02 \x01(\x0c\x12\x11\n\x05\x63ount\x18\x03 \x01(\x04\x42\x02\x30\x01\x12\x0f\n\x03sum\x18\x04 \x01(\x12\x42\x02\x30\x01\x42\t\n\x07_in_key\x1av\n\x0e\x41verageEntries\x12\x64\n\x07\x65ntries\x18\x01 \x03(\x0b\x32S.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.AverageEntry\x1a\x36\n\x10\x41verageAggregate\x12\x11\n\x05\x63ount\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x0f\n\x03sum\x18\x02 \x01(\x12\x42\x02\x30\x01\x1a\xfb\x01\n\x0e\x41verageResults\x12t\n\x11\x61ggregate_average\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.AverageAggregateH\x00\x12h\n\x07\x65ntries\x18\x02 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.AverageEntriesH\x00\x42\t\n\x07variant\x1az\n\x0bRankedEntry\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12\x13\n\x05\x63ount\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12\x11\n\x03sum\x18\x03 \x01(\x12\x42\x02\x30\x01H\x00\x12\r\n\x03\x61vg\x18\x04 \x01(\x01H\x00\x12\x13\n\x06in_key\x18\x05 \x01(\x0cH\x01\x88\x01\x01\x42\x07\n\x05valueB\t\n\x07_in_key\x1a\x9a\x01\n\rRankedEntries\x12\x63\n\x07\x65ntries\x18\x01 \x03(\x0b\x32R.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry\x12\x18\n\x07skipped\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x42\n\n\x08_skipped\x1a\xf7\x05\n\nResultData\x12\x65\n\tdocuments\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.DocumentsH\x00\x12\x65\n\x06\x63ounts\x18\x02 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CountResultsH\x00\x12\x61\n\x04sums\x18\x03 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.SumResultsH\x00\x12i\n\x08\x61verages\x18\x04 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.AverageResultsH\x00\x12\x66\n\x06ranked\x18\x05 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntriesH\x00\x12j\n\x07\x63hained\x18\x06 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.ChainedDocumentsH\x00\x12n\n\tcomposite\x18\x07 \x01(\x0b\x32Y.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CompositeDocumentsH\x00\x42\t\n\x07variant\x1a_\n\x10\x43hainedDocuments\x12\x17\n\x0finner_documents\x18\x01 \x03(\x0c\x12\x17\n\x0fouter_documents\x18\x02 \x03(\x0c\x12\x19\n\x11missing_outer_ids\x18\x03 \x03(\x0c\x1a\xab\x03\n\x12\x43ompositeDocuments\x12\x16\n\x0epage_documents\x18\x01 \x03(\x0c\x12}\n\x0bsub_results\x18\x02 \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CompositeDocuments.SubQueryResult\x1a\xfd\x01\n\x0eSubQueryResult\x12\x65\n\tdocuments\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.DocumentsH\x00\x12\x65\n\x06\x63ounts\x18\x02 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CountEntriesH\x00\x12\x13\n\x0bmissing_ids\x18\x03 \x03(\x0c\x42\x08\n\x06resultB\x08\n\x06resultB\t\n\x07version\"\xf4\x02\n\x19GetDocumentHistoryRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0H\x00\x1a\xeb\x01\n\x1bGetDocumentHistoryRequestV0\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x13\n\x0b\x64ocument_id\x18\x03 \x01(\x0c\x12+\n\x05limit\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x05 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0bstart_at_ms\x18\x06 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x07 \x01(\x08\x42\t\n\x07version\"\xf7\x04\n\x1aGetDocumentHistoryResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0H\x00\x1a\xeb\x03\n\x1cGetDocumentHistoryResponseV0\x12~\n\x10\x64ocument_history\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x37\n\x14\x44ocumentHistoryEntry\x12\x10\n\x04\x64\x61te\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05value\x18\x02 \x01(\x0c\x1a\x95\x01\n\x0f\x44ocumentHistory\x12\x81\x01\n\x10\x64ocument_entries\x18\x01 \x03(\x0b\x32g.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntryB\x08\n\x06resultB\t\n\x07version\"\xed\x01\n!GetIdentityByPublicKeyHashRequest\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest.GetIdentityByPublicKeyHashRequestV0H\x00\x1aM\n#GetIdentityByPublicKeyHashRequestV0\x12\x17\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xda\x02\n\"GetIdentityByPublicKeyHashResponse\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse.GetIdentityByPublicKeyHashResponseV0H\x00\x1a\xb6\x01\n$GetIdentityByPublicKeyHashResponseV0\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbd\x02\n*GetIdentityByNonUniquePublicKeyHashRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashRequest.GetIdentityByNonUniquePublicKeyHashRequestV0H\x00\x1a\x80\x01\n,GetIdentityByNonUniquePublicKeyHashRequestV0\x12\x17\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x12\x18\n\x0bstart_after\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\x0e\n\x0c_start_afterB\t\n\x07version\"\xd6\x06\n+GetIdentityByNonUniquePublicKeyHashResponse\x12\x82\x01\n\x02v0\x18\x01 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0H\x00\x1a\x96\x05\n-GetIdentityByNonUniquePublicKeyHashResponseV0\x12\x9a\x01\n\x08identity\x18\x01 \x01(\x0b\x32\x85\x01.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0.IdentityResponseH\x00\x12\x9d\x01\n\x05proof\x18\x02 \x01(\x0b\x32\x8b\x01.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0.IdentityProvedResponseH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x36\n\x10IdentityResponse\x12\x15\n\x08identity\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_identity\x1a\xa6\x01\n\x16IdentityProvedResponse\x12P\n&grovedb_identity_public_key_hash_proof\x18\x01 \x01(\x0b\x32 .org.dash.platform.dapi.v0.Proof\x12!\n\x14identity_proof_bytes\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x17\n\x15_identity_proof_bytesB\x08\n\x06resultB\t\n\x07version\"\x99\x02\n#WaitForStateTransitionResultRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest.WaitForStateTransitionResultRequestV0H\x00\x1as\n%WaitForStateTransitionResultRequestV0\x12\x1d\n\x15state_transition_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x12\x1c\n\x14request_user_balance\x18\x03 \x01(\x08\x42\t\n\x07version\"\xce\x04\n$WaitForStateTransitionResultResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse.WaitForStateTransitionResultResponseV0H\x00\x1a\x34\n\x17SuccessWithOwnerBalance\x12\x19\n\rowner_balance\x18\x01 \x01(\x04\x42\x02\x30\x01\x1a\xee\x02\n&WaitForStateTransitionResultResponseV0\x12I\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x38.org.dash.platform.dapi.v0.StateTransitionBroadcastErrorH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12}\n\x1asuccess_with_owner_balance\x18\x04 \x01(\x0b\x32W.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse.SuccessWithOwnerBalanceH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc4\x01\n\x19GetConsensusParamsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetConsensusParamsRequest.GetConsensusParamsRequestV0H\x00\x1a<\n\x1bGetConsensusParamsRequestV0\x12\x0e\n\x06height\x18\x01 \x01(\x05\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9c\x04\n\x1aGetConsensusParamsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetConsensusParamsResponse.GetConsensusParamsResponseV0H\x00\x1aP\n\x14\x43onsensusParamsBlock\x12\x11\n\tmax_bytes\x18\x01 \x01(\t\x12\x0f\n\x07max_gas\x18\x02 \x01(\t\x12\x14\n\x0ctime_iota_ms\x18\x03 \x01(\t\x1a\x62\n\x17\x43onsensusParamsEvidence\x12\x1a\n\x12max_age_num_blocks\x18\x01 \x01(\t\x12\x18\n\x10max_age_duration\x18\x02 \x01(\t\x12\x11\n\tmax_bytes\x18\x03 \x01(\t\x1a\xda\x01\n\x1cGetConsensusParamsResponseV0\x12Y\n\x05\x62lock\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetConsensusParamsResponse.ConsensusParamsBlock\x12_\n\x08\x65vidence\x18\x02 \x01(\x0b\x32M.org.dash.platform.dapi.v0.GetConsensusParamsResponse.ConsensusParamsEvidenceB\t\n\x07version\"\xe4\x01\n%GetProtocolVersionUpgradeStateRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateRequest.GetProtocolVersionUpgradeStateRequestV0H\x00\x1a\x38\n\'GetProtocolVersionUpgradeStateRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xb5\x05\n&GetProtocolVersionUpgradeStateResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0H\x00\x1a\x85\x04\n(GetProtocolVersionUpgradeStateResponseV0\x12\x87\x01\n\x08versions\x18\x01 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0.VersionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x96\x01\n\x08Versions\x12\x89\x01\n\x08versions\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0.VersionEntry\x1a:\n\x0cVersionEntry\x12\x16\n\x0eversion_number\x18\x01 \x01(\r\x12\x12\n\nvote_count\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xa3\x02\n*GetProtocolVersionUpgradeVoteStatusRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusRequest.GetProtocolVersionUpgradeVoteStatusRequestV0H\x00\x1ag\n,GetProtocolVersionUpgradeVoteStatusRequestV0\x12\x19\n\x11start_pro_tx_hash\x18\x01 \x01(\x0c\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xef\x05\n+GetProtocolVersionUpgradeVoteStatusResponse\x12\x82\x01\n\x02v0\x18\x01 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0H\x00\x1a\xaf\x04\n-GetProtocolVersionUpgradeVoteStatusResponseV0\x12\x98\x01\n\x08versions\x18\x01 \x01(\x0b\x32\x83\x01.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0.VersionSignalsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xaf\x01\n\x0eVersionSignals\x12\x9c\x01\n\x0fversion_signals\x18\x01 \x03(\x0b\x32\x82\x01.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0.VersionSignal\x1a\x35\n\rVersionSignal\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07version\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xf5\x01\n\x14GetEpochsInfoRequest\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetEpochsInfoRequest.GetEpochsInfoRequestV0H\x00\x1a|\n\x16GetEpochsInfoRequestV0\x12\x31\n\x0bstart_epoch\x18\x01 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\x11\n\tascending\x18\x03 \x01(\x08\x12\r\n\x05prove\x18\x04 \x01(\x08\x42\t\n\x07version\"\x99\x05\n\x15GetEpochsInfoResponse\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0H\x00\x1a\x9c\x04\n\x17GetEpochsInfoResponseV0\x12\x65\n\x06\x65pochs\x18\x01 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0.EpochInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1au\n\nEpochInfos\x12g\n\x0b\x65poch_infos\x18\x01 \x03(\x0b\x32R.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0.EpochInfo\x1a\xa6\x01\n\tEpochInfo\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x1e\n\x12\x66irst_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x1f\n\x17\x66irst_core_block_height\x18\x03 \x01(\r\x12\x16\n\nstart_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x0e\x66\x65\x65_multiplier\x18\x05 \x01(\x01\x12\x18\n\x10protocol_version\x18\x06 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xbf\x02\n\x1dGetFinalizedEpochInfosRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetFinalizedEpochInfosRequest.GetFinalizedEpochInfosRequestV0H\x00\x1a\xaa\x01\n\x1fGetFinalizedEpochInfosRequestV0\x12\x19\n\x11start_epoch_index\x18\x01 \x01(\r\x12\"\n\x1astart_epoch_index_included\x18\x02 \x01(\x08\x12\x17\n\x0f\x65nd_epoch_index\x18\x03 \x01(\r\x12 \n\x18\x65nd_epoch_index_included\x18\x04 \x01(\x08\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\xbd\t\n\x1eGetFinalizedEpochInfosResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0H\x00\x1a\xa5\x08\n GetFinalizedEpochInfosResponseV0\x12\x80\x01\n\x06\x65pochs\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.FinalizedEpochInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xa4\x01\n\x13\x46inalizedEpochInfos\x12\x8c\x01\n\x15\x66inalized_epoch_infos\x18\x01 \x03(\x0b\x32m.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.FinalizedEpochInfo\x1a\x9f\x04\n\x12\x46inalizedEpochInfo\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x1e\n\x12\x66irst_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x1f\n\x17\x66irst_core_block_height\x18\x03 \x01(\r\x12\x1c\n\x10\x66irst_block_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x0e\x66\x65\x65_multiplier\x18\x05 \x01(\x01\x12\x18\n\x10protocol_version\x18\x06 \x01(\r\x12!\n\x15total_blocks_in_epoch\x18\x07 \x01(\x04\x42\x02\x30\x01\x12*\n\"next_epoch_start_core_block_height\x18\x08 \x01(\r\x12!\n\x15total_processing_fees\x18\t \x01(\x04\x42\x02\x30\x01\x12*\n\x1etotal_distributed_storage_fees\x18\n \x01(\x04\x42\x02\x30\x01\x12&\n\x1atotal_created_storage_fees\x18\x0b \x01(\x04\x42\x02\x30\x01\x12\x1e\n\x12\x63ore_block_rewards\x18\x0c \x01(\x04\x42\x02\x30\x01\x12\x81\x01\n\x0f\x62lock_proposers\x18\r \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.BlockProposer\x1a\x39\n\rBlockProposer\x12\x13\n\x0bproposer_id\x18\x01 \x01(\x0c\x12\x13\n\x0b\x62lock_count\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xde\x04\n\x1cGetContestedResourcesRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetContestedResourcesRequest.GetContestedResourcesRequestV0H\x00\x1a\xcc\x03\n\x1eGetContestedResourcesRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x1a\n\x12start_index_values\x18\x04 \x03(\x0c\x12\x18\n\x10\x65nd_index_values\x18\x05 \x03(\x0c\x12\x89\x01\n\x13start_at_value_info\x18\x06 \x01(\x0b\x32g.org.dash.platform.dapi.v0.GetContestedResourcesRequest.GetContestedResourcesRequestV0.StartAtValueInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x17\n\x0forder_ascending\x18\x08 \x01(\x08\x12\r\n\x05prove\x18\t \x01(\x08\x1a\x45\n\x10StartAtValueInfo\x12\x13\n\x0bstart_value\x18\x01 \x01(\x0c\x12\x1c\n\x14start_value_included\x18\x02 \x01(\x08\x42\x16\n\x14_start_at_value_infoB\x08\n\x06_countB\t\n\x07version\"\x88\x04\n\x1dGetContestedResourcesResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0H\x00\x1a\xf3\x02\n\x1fGetContestedResourcesResponseV0\x12\x95\x01\n\x19\x63ontested_resource_values\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0.ContestedResourceValuesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a<\n\x17\x43ontestedResourceValues\x12!\n\x19\x63ontested_resource_values\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xd2\x05\n\x1cGetVotePollsByEndDateRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0H\x00\x1a\xc0\x04\n\x1eGetVotePollsByEndDateRequestV0\x12\x84\x01\n\x0fstart_time_info\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0.StartAtTimeInfoH\x00\x88\x01\x01\x12\x80\x01\n\rend_time_info\x18\x02 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0.EndAtTimeInfoH\x01\x88\x01\x01\x12\x12\n\x05limit\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x13\n\x06offset\x18\x04 \x01(\rH\x03\x88\x01\x01\x12\x11\n\tascending\x18\x05 \x01(\x08\x12\r\n\x05prove\x18\x06 \x01(\x08\x1aI\n\x0fStartAtTimeInfo\x12\x19\n\rstart_time_ms\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x13start_time_included\x18\x02 \x01(\x08\x1a\x43\n\rEndAtTimeInfo\x12\x17\n\x0b\x65nd_time_ms\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x19\n\x11\x65nd_time_included\x18\x02 \x01(\x08\x42\x12\n\x10_start_time_infoB\x10\n\x0e_end_time_infoB\x08\n\x06_limitB\t\n\x07_offsetB\t\n\x07version\"\x83\x06\n\x1dGetVotePollsByEndDateResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0H\x00\x1a\xee\x04\n\x1fGetVotePollsByEndDateResponseV0\x12\x9c\x01\n\x18vote_polls_by_timestamps\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0.SerializedVotePollsByTimestampsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aV\n\x1eSerializedVotePollsByTimestamp\x12\x15\n\ttimestamp\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1d\n\x15serialized_vote_polls\x18\x02 \x03(\x0c\x1a\xd7\x01\n\x1fSerializedVotePollsByTimestamps\x12\x99\x01\n\x18vote_polls_by_timestamps\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0.SerializedVotePollsByTimestamp\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x42\x08\n\x06resultB\t\n\x07version\"\xff\x06\n$GetContestedResourceVoteStateRequest\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0H\x00\x1a\xd5\x05\n&GetContestedResourceVoteStateRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x86\x01\n\x0bresult_type\x18\x05 \x01(\x0e\x32q.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.ResultType\x12\x36\n.allow_include_locked_and_abstaining_vote_tally\x18\x06 \x01(\x08\x12\xa3\x01\n\x18start_at_identifier_info\x18\x07 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.StartAtIdentifierInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x08 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\t \x01(\x08\x1aT\n\x15StartAtIdentifierInfo\x12\x18\n\x10start_identifier\x18\x01 \x01(\x0c\x12!\n\x19start_identifier_included\x18\x02 \x01(\x08\"I\n\nResultType\x12\r\n\tDOCUMENTS\x10\x00\x12\x0e\n\nVOTE_TALLY\x10\x01\x12\x1c\n\x18\x44OCUMENTS_AND_VOTE_TALLY\x10\x02\x42\x1b\n\x19_start_at_identifier_infoB\x08\n\x06_countB\t\n\x07version\"\x94\x0c\n%GetContestedResourceVoteStateResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0H\x00\x1a\xe7\n\n\'GetContestedResourceVoteStateResponseV0\x12\xae\x01\n\x1d\x63ontested_resource_contenders\x18\x01 \x01(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.ContestedResourceContendersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xda\x03\n\x10\x46inishedVoteInfo\x12\xad\x01\n\x15\x66inished_vote_outcome\x18\x01 \x01(\x0e\x32\x8d\x01.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.FinishedVoteInfo.FinishedVoteOutcome\x12\x1f\n\x12won_by_identity_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12$\n\x18\x66inished_at_block_height\x18\x03 \x01(\x04\x42\x02\x30\x01\x12%\n\x1d\x66inished_at_core_block_height\x18\x04 \x01(\r\x12%\n\x19\x66inished_at_block_time_ms\x18\x05 \x01(\x04\x42\x02\x30\x01\x12\x19\n\x11\x66inished_at_epoch\x18\x06 \x01(\r\"O\n\x13\x46inishedVoteOutcome\x12\x14\n\x10TOWARDS_IDENTITY\x10\x00\x12\n\n\x06LOCKED\x10\x01\x12\x16\n\x12NO_PREVIOUS_WINNER\x10\x02\x42\x15\n\x13_won_by_identity_id\x1a\xc4\x03\n\x1b\x43ontestedResourceContenders\x12\x86\x01\n\ncontenders\x18\x01 \x03(\x0b\x32r.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.Contender\x12\x1f\n\x12\x61\x62stain_vote_tally\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x1c\n\x0flock_vote_tally\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\x9a\x01\n\x12\x66inished_vote_info\x18\x04 \x01(\x0b\x32y.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.FinishedVoteInfoH\x02\x88\x01\x01\x42\x15\n\x13_abstain_vote_tallyB\x12\n\x10_lock_vote_tallyB\x15\n\x13_finished_vote_info\x1ak\n\tContender\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x17\n\nvote_count\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x15\n\x08\x64ocument\x18\x03 \x01(\x0cH\x01\x88\x01\x01\x42\r\n\x0b_vote_countB\x0b\n\t_documentB\x08\n\x06resultB\t\n\x07version\"\xd5\x05\n,GetContestedResourceVotersForIdentityRequest\x12\x84\x01\n\x02v0\x18\x01 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest.GetContestedResourceVotersForIdentityRequestV0H\x00\x1a\x92\x04\n.GetContestedResourceVotersForIdentityRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x15\n\rcontestant_id\x18\x05 \x01(\x0c\x12\xb4\x01\n\x18start_at_identifier_info\x18\x06 \x01(\x0b\x32\x8c\x01.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest.GetContestedResourceVotersForIdentityRequestV0.StartAtIdentifierInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x17\n\x0forder_ascending\x18\x08 \x01(\x08\x12\r\n\x05prove\x18\t \x01(\x08\x1aT\n\x15StartAtIdentifierInfo\x12\x18\n\x10start_identifier\x18\x01 \x01(\x0c\x12!\n\x19start_identifier_included\x18\x02 \x01(\x08\x42\x1b\n\x19_start_at_identifier_infoB\x08\n\x06_countB\t\n\x07version\"\xf1\x04\n-GetContestedResourceVotersForIdentityResponse\x12\x86\x01\n\x02v0\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse.GetContestedResourceVotersForIdentityResponseV0H\x00\x1a\xab\x03\n/GetContestedResourceVotersForIdentityResponseV0\x12\xb6\x01\n\x19\x63ontested_resource_voters\x18\x01 \x01(\x0b\x32\x90\x01.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse.GetContestedResourceVotersForIdentityResponseV0.ContestedResourceVotersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x43\n\x17\x43ontestedResourceVoters\x12\x0e\n\x06voters\x18\x01 \x03(\x0c\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x42\x08\n\x06resultB\t\n\x07version\"\xad\x05\n(GetContestedResourceIdentityVotesRequest\x12|\n\x02v0\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest.GetContestedResourceIdentityVotesRequestV0H\x00\x1a\xf7\x03\n*GetContestedResourceIdentityVotesRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12+\n\x05limit\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0forder_ascending\x18\x04 \x01(\x08\x12\xae\x01\n\x1astart_at_vote_poll_id_info\x18\x05 \x01(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest.GetContestedResourceIdentityVotesRequestV0.StartAtVotePollIdInfoH\x00\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x1a\x61\n\x15StartAtVotePollIdInfo\x12 \n\x18start_at_poll_identifier\x18\x01 \x01(\x0c\x12&\n\x1estart_poll_identifier_included\x18\x02 \x01(\x08\x42\x1d\n\x1b_start_at_vote_poll_id_infoB\t\n\x07version\"\xc8\n\n)GetContestedResourceIdentityVotesResponse\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0H\x00\x1a\x8f\t\n+GetContestedResourceIdentityVotesResponseV0\x12\xa1\x01\n\x05votes\x18\x01 \x01(\x0b\x32\x8f\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ContestedResourceIdentityVotesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xf7\x01\n\x1e\x43ontestedResourceIdentityVotes\x12\xba\x01\n!contested_resource_identity_votes\x18\x01 \x03(\x0b\x32\x8e\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ContestedResourceIdentityVote\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x1a\xad\x02\n\x12ResourceVoteChoice\x12\xad\x01\n\x10vote_choice_type\x18\x01 \x01(\x0e\x32\x92\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ResourceVoteChoice.VoteChoiceType\x12\x18\n\x0bidentity_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\"=\n\x0eVoteChoiceType\x12\x14\n\x10TOWARDS_IDENTITY\x10\x00\x12\x0b\n\x07\x41\x42STAIN\x10\x01\x12\x08\n\x04LOCK\x10\x02\x42\x0e\n\x0c_identity_id\x1a\x95\x02\n\x1d\x43ontestedResourceIdentityVote\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\'\n\x1fserialized_index_storage_values\x18\x03 \x03(\x0c\x12\x99\x01\n\x0bvote_choice\x18\x04 \x01(\x0b\x32\x83\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ResourceVoteChoiceB\x08\n\x06resultB\t\n\x07version\"\xf0\x01\n%GetPrefundedSpecializedBalanceRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceRequest.GetPrefundedSpecializedBalanceRequestV0H\x00\x1a\x44\n\'GetPrefundedSpecializedBalanceRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xed\x02\n&GetPrefundedSpecializedBalanceResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse.GetPrefundedSpecializedBalanceResponseV0H\x00\x1a\xbd\x01\n(GetPrefundedSpecializedBalanceResponseV0\x12\x15\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xd0\x01\n GetTotalCreditsInPlatformRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformRequest.GetTotalCreditsInPlatformRequestV0H\x00\x1a\x33\n\"GetTotalCreditsInPlatformRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xd9\x02\n!GetTotalCreditsInPlatformResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformResponse.GetTotalCreditsInPlatformResponseV0H\x00\x1a\xb8\x01\n#GetTotalCreditsInPlatformResponseV0\x12\x15\n\x07\x63redits\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc4\x01\n\x16GetPathElementsRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetPathElementsRequest.GetPathElementsRequestV0H\x00\x1a\x45\n\x18GetPathElementsRequestV0\x12\x0c\n\x04path\x18\x01 \x03(\x0c\x12\x0c\n\x04keys\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xa3\x03\n\x17GetPathElementsResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetPathElementsResponse.GetPathElementsResponseV0H\x00\x1a\xa0\x02\n\x19GetPathElementsResponseV0\x12i\n\x08\x65lements\x18\x01 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetPathElementsResponse.GetPathElementsResponseV0.ElementsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1c\n\x08\x45lements\x12\x10\n\x08\x65lements\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\x81\x01\n\x10GetStatusRequest\x12L\n\x02v0\x18\x01 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetStatusRequest.GetStatusRequestV0H\x00\x1a\x14\n\x12GetStatusRequestV0B\t\n\x07version\"\xe4\x10\n\x11GetStatusResponse\x12N\n\x02v0\x18\x01 \x01(\x0b\x32@.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0H\x00\x1a\xf3\x0f\n\x13GetStatusResponseV0\x12Y\n\x07version\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version\x12S\n\x04node\x18\x02 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Node\x12U\n\x05\x63hain\x18\x03 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Chain\x12Y\n\x07network\x18\x04 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Network\x12^\n\nstate_sync\x18\x05 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.StateSync\x12S\n\x04time\x18\x06 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Time\x1a\x82\x05\n\x07Version\x12\x63\n\x08software\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Software\x12\x63\n\x08protocol\x18\x02 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol\x1a^\n\x08Software\x12\x0c\n\x04\x64\x61pi\x18\x01 \x01(\t\x12\x12\n\x05\x64rive\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\ntenderdash\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_driveB\r\n\x0b_tenderdash\x1a\xcc\x02\n\x08Protocol\x12p\n\ntenderdash\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol.Tenderdash\x12\x66\n\x05\x64rive\x18\x02 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol.Drive\x1a(\n\nTenderdash\x12\x0b\n\x03p2p\x18\x01 \x01(\r\x12\r\n\x05\x62lock\x18\x02 \x01(\r\x1a<\n\x05\x44rive\x12\x0e\n\x06latest\x18\x03 \x01(\r\x12\x0f\n\x07\x63urrent\x18\x04 \x01(\r\x12\x12\n\nnext_epoch\x18\x05 \x01(\r\x1a\x7f\n\x04Time\x12\x11\n\x05local\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x05\x62lock\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x12\x18\n\x07genesis\x18\x03 \x01(\x04\x42\x02\x30\x01H\x01\x88\x01\x01\x12\x12\n\x05\x65poch\x18\x04 \x01(\rH\x02\x88\x01\x01\x42\x08\n\x06_blockB\n\n\x08_genesisB\x08\n\x06_epoch\x1a<\n\x04Node\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\x18\n\x0bpro_tx_hash\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x0e\n\x0c_pro_tx_hash\x1a\xb3\x02\n\x05\x43hain\x12\x13\n\x0b\x63\x61tching_up\x18\x01 \x01(\x08\x12\x19\n\x11latest_block_hash\x18\x02 \x01(\x0c\x12\x17\n\x0flatest_app_hash\x18\x03 \x01(\x0c\x12\x1f\n\x13latest_block_height\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x13\x65\x61rliest_block_hash\x18\x05 \x01(\x0c\x12\x19\n\x11\x65\x61rliest_app_hash\x18\x06 \x01(\x0c\x12!\n\x15\x65\x61rliest_block_height\x18\x07 \x01(\x04\x42\x02\x30\x01\x12!\n\x15max_peer_block_height\x18\t \x01(\x04\x42\x02\x30\x01\x12%\n\x18\x63ore_chain_locked_height\x18\n \x01(\rH\x00\x88\x01\x01\x42\x1b\n\x19_core_chain_locked_height\x1a\x43\n\x07Network\x12\x10\n\x08\x63hain_id\x18\x01 \x01(\t\x12\x13\n\x0bpeers_count\x18\x02 \x01(\r\x12\x11\n\tlistening\x18\x03 \x01(\x08\x1a\x85\x02\n\tStateSync\x12\x1d\n\x11total_synced_time\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1a\n\x0eremaining_time\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x17\n\x0ftotal_snapshots\x18\x03 \x01(\r\x12\"\n\x16\x63hunk_process_avg_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x0fsnapshot_height\x18\x05 \x01(\x04\x42\x02\x30\x01\x12!\n\x15snapshot_chunks_count\x18\x06 \x01(\x04\x42\x02\x30\x01\x12\x1d\n\x11\x62\x61\x63kfilled_blocks\x18\x07 \x01(\x04\x42\x02\x30\x01\x12!\n\x15\x62\x61\x63kfill_blocks_total\x18\x08 \x01(\x04\x42\x02\x30\x01\x42\t\n\x07version\"\xb1\x01\n\x1cGetCurrentQuorumsInfoRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0H\x00\x1a \n\x1eGetCurrentQuorumsInfoRequestV0B\t\n\x07version\"\xa1\x05\n\x1dGetCurrentQuorumsInfoResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0H\x00\x1a\x46\n\x0bValidatorV0\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07node_ip\x18\x02 \x01(\t\x12\x11\n\tis_banned\x18\x03 \x01(\x08\x1a\xaf\x01\n\x0eValidatorSetV0\x12\x13\n\x0bquorum_hash\x18\x01 \x01(\x0c\x12\x13\n\x0b\x63ore_height\x18\x02 \x01(\r\x12U\n\x07members\x18\x03 \x03(\x0b\x32\x44.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0\x12\x1c\n\x14threshold_public_key\x18\x04 \x01(\x0c\x1a\x92\x02\n\x1fGetCurrentQuorumsInfoResponseV0\x12\x15\n\rquorum_hashes\x18\x01 \x03(\x0c\x12\x1b\n\x13\x63urrent_quorum_hash\x18\x02 \x01(\x0c\x12_\n\x0evalidator_sets\x18\x03 \x03(\x0b\x32G.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0\x12\x1b\n\x13last_block_proposer\x18\x04 \x01(\x0c\x12=\n\x08metadata\x18\x05 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\t\n\x07version\"\xf4\x01\n\x1fGetIdentityTokenBalancesRequest\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentityTokenBalancesRequest.GetIdentityTokenBalancesRequestV0H\x00\x1aZ\n!GetIdentityTokenBalancesRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x11\n\ttoken_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xad\x05\n GetIdentityTokenBalancesResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0H\x00\x1a\x8f\x04\n\"GetIdentityTokenBalancesResponseV0\x12\x86\x01\n\x0etoken_balances\x18\x01 \x01(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0.TokenBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aG\n\x11TokenBalanceEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x07\x62\x61lance\x18\x02 \x01(\x04H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\x9a\x01\n\rTokenBalances\x12\x88\x01\n\x0etoken_balances\x18\x01 \x03(\x0b\x32p.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0.TokenBalanceEntryB\x08\n\x06resultB\t\n\x07version\"\xfc\x01\n!GetIdentitiesTokenBalancesRequest\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesRequest.GetIdentitiesTokenBalancesRequestV0H\x00\x1a\\\n#GetIdentitiesTokenBalancesRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x0cidentity_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xf2\x05\n\"GetIdentitiesTokenBalancesResponse\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0H\x00\x1a\xce\x04\n$GetIdentitiesTokenBalancesResponseV0\x12\x9b\x01\n\x17identity_token_balances\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0.IdentityTokenBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aR\n\x19IdentityTokenBalanceEntry\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x14\n\x07\x62\x61lance\x18\x02 \x01(\x04H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\xb7\x01\n\x15IdentityTokenBalances\x12\x9d\x01\n\x17identity_token_balances\x18\x01 \x03(\x0b\x32|.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0.IdentityTokenBalanceEntryB\x08\n\x06resultB\t\n\x07version\"\xe8\x01\n\x1cGetIdentityTokenInfosRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetIdentityTokenInfosRequest.GetIdentityTokenInfosRequestV0H\x00\x1aW\n\x1eGetIdentityTokenInfosRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x11\n\ttoken_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\x98\x06\n\x1dGetIdentityTokenInfosResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0H\x00\x1a\x83\x05\n\x1fGetIdentityTokenInfosResponseV0\x12z\n\x0btoken_infos\x18\x01 \x01(\x0b\x32\x63.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a(\n\x16TokenIdentityInfoEntry\x12\x0e\n\x06\x66rozen\x18\x01 \x01(\x08\x1a\xb0\x01\n\x0eTokenInfoEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x82\x01\n\x04info\x18\x02 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenIdentityInfoEntryH\x00\x88\x01\x01\x42\x07\n\x05_info\x1a\x8a\x01\n\nTokenInfos\x12|\n\x0btoken_infos\x18\x01 \x03(\x0b\x32g.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xf0\x01\n\x1eGetIdentitiesTokenInfosRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosRequest.GetIdentitiesTokenInfosRequestV0H\x00\x1aY\n GetIdentitiesTokenInfosRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x0cidentity_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xca\x06\n\x1fGetIdentitiesTokenInfosResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0H\x00\x1a\xaf\x05\n!GetIdentitiesTokenInfosResponseV0\x12\x8f\x01\n\x14identity_token_infos\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.IdentityTokenInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a(\n\x16TokenIdentityInfoEntry\x12\x0e\n\x06\x66rozen\x18\x01 \x01(\x08\x1a\xb7\x01\n\x0eTokenInfoEntry\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x86\x01\n\x04info\x18\x02 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.TokenIdentityInfoEntryH\x00\x88\x01\x01\x42\x07\n\x05_info\x1a\x97\x01\n\x12IdentityTokenInfos\x12\x80\x01\n\x0btoken_infos\x18\x01 \x03(\x0b\x32k.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.TokenInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xbf\x01\n\x17GetTokenStatusesRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetTokenStatusesRequest.GetTokenStatusesRequestV0H\x00\x1a=\n\x19GetTokenStatusesRequestV0\x12\x11\n\ttoken_ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xe7\x04\n\x18GetTokenStatusesResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0H\x00\x1a\xe1\x03\n\x1aGetTokenStatusesResponseV0\x12v\n\x0etoken_statuses\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0.TokenStatusesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x44\n\x10TokenStatusEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x13\n\x06paused\x18\x02 \x01(\x08H\x00\x88\x01\x01\x42\t\n\x07_paused\x1a\x88\x01\n\rTokenStatuses\x12w\n\x0etoken_statuses\x18\x01 \x03(\x0b\x32_.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0.TokenStatusEntryB\x08\n\x06resultB\t\n\x07version\"\xef\x01\n#GetTokenDirectPurchasePricesRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesRequest.GetTokenDirectPurchasePricesRequestV0H\x00\x1aI\n%GetTokenDirectPurchasePricesRequestV0\x12\x11\n\ttoken_ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x8b\t\n$GetTokenDirectPurchasePricesResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0H\x00\x1a\xe1\x07\n&GetTokenDirectPurchasePricesResponseV0\x12\xa9\x01\n\x1ctoken_direct_purchase_prices\x18\x01 \x01(\x0b\x32\x80\x01.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.TokenDirectPurchasePricesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x33\n\x10PriceForQuantity\x12\x10\n\x08quantity\x18\x01 \x01(\x04\x12\r\n\x05price\x18\x02 \x01(\x04\x1a\xa7\x01\n\x0fPricingSchedule\x12\x93\x01\n\x12price_for_quantity\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.PriceForQuantity\x1a\xe4\x01\n\x1dTokenDirectPurchasePriceEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x15\n\x0b\x66ixed_price\x18\x02 \x01(\x04H\x00\x12\x90\x01\n\x0evariable_price\x18\x03 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.PricingScheduleH\x00\x42\x07\n\x05price\x1a\xc8\x01\n\x19TokenDirectPurchasePrices\x12\xaa\x01\n\x1btoken_direct_purchase_price\x18\x01 \x03(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.TokenDirectPurchasePriceEntryB\x08\n\x06resultB\t\n\x07version\"\xce\x01\n\x1bGetTokenContractInfoRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetTokenContractInfoRequest.GetTokenContractInfoRequestV0H\x00\x1a@\n\x1dGetTokenContractInfoRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xfb\x03\n\x1cGetTokenContractInfoResponse\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetTokenContractInfoResponse.GetTokenContractInfoResponseV0H\x00\x1a\xe9\x02\n\x1eGetTokenContractInfoResponseV0\x12|\n\x04\x64\x61ta\x18\x01 \x01(\x0b\x32l.org.dash.platform.dapi.v0.GetTokenContractInfoResponse.GetTokenContractInfoResponseV0.TokenContractInfoDataH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aM\n\x15TokenContractInfoData\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17token_contract_position\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xef\x04\n)GetTokenPreProgrammedDistributionsRequest\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest.GetTokenPreProgrammedDistributionsRequestV0H\x00\x1a\xb6\x03\n+GetTokenPreProgrammedDistributionsRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x98\x01\n\rstart_at_info\x18\x02 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest.GetTokenPreProgrammedDistributionsRequestV0.StartAtInfoH\x00\x88\x01\x01\x12\x12\n\x05limit\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x04 \x01(\x08\x1a\x9a\x01\n\x0bStartAtInfo\x12\x15\n\rstart_time_ms\x18\x01 \x01(\x04\x12\x1c\n\x0fstart_recipient\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12%\n\x18start_recipient_included\x18\x03 \x01(\x08H\x01\x88\x01\x01\x42\x12\n\x10_start_recipientB\x1b\n\x19_start_recipient_includedB\x10\n\x0e_start_at_infoB\x08\n\x06_limitB\t\n\x07version\"\xec\x07\n*GetTokenPreProgrammedDistributionsResponse\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0H\x00\x1a\xaf\x06\n,GetTokenPreProgrammedDistributionsResponseV0\x12\xa5\x01\n\x13token_distributions\x18\x01 \x01(\x0b\x32\x85\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenDistributionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a>\n\x16TokenDistributionEntry\x12\x14\n\x0crecipient_id\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a\xd4\x01\n\x1bTokenTimedDistributionEntry\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\x12\xa1\x01\n\rdistributions\x18\x02 \x03(\x0b\x32\x89\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenDistributionEntry\x1a\xc3\x01\n\x12TokenDistributions\x12\xac\x01\n\x13token_distributions\x18\x01 \x03(\x0b\x32\x8e\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenTimedDistributionEntryB\x08\n\x06resultB\t\n\x07version\"\x82\x04\n-GetTokenPerpetualDistributionLastClaimRequest\x12\x86\x01\n\x02v0\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest.GetTokenPerpetualDistributionLastClaimRequestV0H\x00\x1aI\n\x11\x43ontractTokenInfo\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17token_contract_position\x18\x02 \x01(\r\x1a\xf1\x01\n/GetTokenPerpetualDistributionLastClaimRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12v\n\rcontract_info\x18\x02 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest.ContractTokenInfoH\x00\x88\x01\x01\x12\x13\n\x0bidentity_id\x18\x04 \x01(\x0c\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x10\n\x0e_contract_infoB\t\n\x07version\"\x93\x05\n.GetTokenPerpetualDistributionLastClaimResponse\x12\x88\x01\n\x02v0\x18\x01 \x01(\x0b\x32z.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse.GetTokenPerpetualDistributionLastClaimResponseV0H\x00\x1a\xca\x03\n0GetTokenPerpetualDistributionLastClaimResponseV0\x12\x9f\x01\n\nlast_claim\x18\x01 \x01(\x0b\x32\x88\x01.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse.GetTokenPerpetualDistributionLastClaimResponseV0.LastClaimInfoH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1ax\n\rLastClaimInfo\x12\x1a\n\x0ctimestamp_ms\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x1a\n\x0c\x62lock_height\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12\x0f\n\x05\x65poch\x18\x03 \x01(\rH\x00\x12\x13\n\traw_bytes\x18\x04 \x01(\x0cH\x00\x42\t\n\x07paid_atB\x08\n\x06resultB\t\n\x07version\"\xca\x01\n\x1aGetTokenTotalSupplyRequest\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetTokenTotalSupplyRequest.GetTokenTotalSupplyRequestV0H\x00\x1a?\n\x1cGetTokenTotalSupplyRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xaf\x04\n\x1bGetTokenTotalSupplyResponse\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse.GetTokenTotalSupplyResponseV0H\x00\x1a\xa0\x03\n\x1dGetTokenTotalSupplyResponseV0\x12\x88\x01\n\x12token_total_supply\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse.GetTokenTotalSupplyResponseV0.TokenTotalSupplyEntryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1ax\n\x15TokenTotalSupplyEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x30\n(total_aggregated_amount_in_user_accounts\x18\x02 \x01(\x04\x12\x1b\n\x13total_system_amount\x18\x03 \x01(\x04\x42\x08\n\x06resultB\t\n\x07version\"\xd2\x01\n\x13GetGroupInfoRequest\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetGroupInfoRequest.GetGroupInfoRequestV0H\x00\x1a\\\n\x15GetGroupInfoRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xd4\x05\n\x14GetGroupInfoResponse\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0H\x00\x1a\xda\x04\n\x16GetGroupInfoResponseV0\x12\x66\n\ngroup_info\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupInfoH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x04 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x34\n\x10GroupMemberEntry\x12\x11\n\tmember_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\x98\x01\n\x0eGroupInfoEntry\x12h\n\x07members\x18\x01 \x03(\x0b\x32W.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupMemberEntry\x12\x1c\n\x14group_required_power\x18\x02 \x01(\r\x1a\x8a\x01\n\tGroupInfo\x12n\n\ngroup_info\x18\x01 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupInfoEntryH\x00\x88\x01\x01\x42\r\n\x0b_group_infoB\x08\n\x06resultB\t\n\x07version\"\xed\x03\n\x14GetGroupInfosRequest\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetGroupInfosRequest.GetGroupInfosRequestV0H\x00\x1au\n\x1cStartAtGroupContractPosition\x12%\n\x1dstart_group_contract_position\x18\x01 \x01(\r\x12.\n&start_group_contract_position_included\x18\x02 \x01(\x08\x1a\xfc\x01\n\x16GetGroupInfosRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12{\n start_at_group_contract_position\x18\x02 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetGroupInfosRequest.StartAtGroupContractPositionH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x04 \x01(\x08\x42#\n!_start_at_group_contract_positionB\x08\n\x06_countB\t\n\x07version\"\xff\x05\n\x15GetGroupInfosResponse\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0H\x00\x1a\x82\x05\n\x17GetGroupInfosResponseV0\x12j\n\x0bgroup_infos\x18\x01 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x04 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x34\n\x10GroupMemberEntry\x12\x11\n\tmember_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\xc3\x01\n\x16GroupPositionInfoEntry\x12\x1f\n\x17group_contract_position\x18\x01 \x01(\r\x12j\n\x07members\x18\x02 \x03(\x0b\x32Y.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupMemberEntry\x12\x1c\n\x14group_required_power\x18\x03 \x01(\r\x1a\x82\x01\n\nGroupInfos\x12t\n\x0bgroup_infos\x18\x01 \x03(\x0b\x32_.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupPositionInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xbe\x04\n\x16GetGroupActionsRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetGroupActionsRequest.GetGroupActionsRequestV0H\x00\x1aL\n\x0fStartAtActionId\x12\x17\n\x0fstart_action_id\x18\x01 \x01(\x0c\x12 \n\x18start_action_id_included\x18\x02 \x01(\x08\x1a\xc8\x02\n\x18GetGroupActionsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12N\n\x06status\x18\x03 \x01(\x0e\x32>.org.dash.platform.dapi.v0.GetGroupActionsRequest.ActionStatus\x12\x62\n\x12start_at_action_id\x18\x04 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetGroupActionsRequest.StartAtActionIdH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x05 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x42\x15\n\x13_start_at_action_idB\x08\n\x06_count\"&\n\x0c\x41\x63tionStatus\x12\n\n\x06\x41\x43TIVE\x10\x00\x12\n\n\x06\x43LOSED\x10\x01\x42\t\n\x07version\"\xd6\x1e\n\x17GetGroupActionsResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0H\x00\x1a\xd3\x1d\n\x19GetGroupActionsResponseV0\x12r\n\rgroup_actions\x18\x01 \x01(\x0b\x32Y.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a[\n\tMintEvent\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x04\x12\x14\n\x0crecipient_id\x18\x02 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a[\n\tBurnEvent\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x04\x12\x14\n\x0c\x62urn_from_id\x18\x02 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1aJ\n\x0b\x46reezeEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1aL\n\rUnfreezeEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\x66\n\x17\x44\x65stroyFrozenFundsEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\x64\n\x13SharedEncryptedNote\x12\x18\n\x10sender_key_index\x18\x01 \x01(\r\x12\x1b\n\x13recipient_key_index\x18\x02 \x01(\r\x12\x16\n\x0e\x65ncrypted_data\x18\x03 \x01(\x0c\x1a{\n\x15PersonalEncryptedNote\x12!\n\x19root_encryption_key_index\x18\x01 \x01(\r\x12\'\n\x1f\x64\x65rivation_encryption_key_index\x18\x02 \x01(\r\x12\x16\n\x0e\x65ncrypted_data\x18\x03 \x01(\x0c\x1a\xe9\x01\n\x14\x45mergencyActionEvent\x12\x81\x01\n\x0b\x61\x63tion_type\x18\x01 \x01(\x0e\x32l.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.EmergencyActionEvent.ActionType\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\"#\n\nActionType\x12\t\n\x05PAUSE\x10\x00\x12\n\n\x06RESUME\x10\x01\x42\x0e\n\x0c_public_note\x1a\x64\n\x16TokenConfigUpdateEvent\x12 \n\x18token_config_update_item\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\xe6\x03\n\x1eUpdateDirectPurchasePriceEvent\x12\x15\n\x0b\x66ixed_price\x18\x01 \x01(\x04H\x00\x12\x95\x01\n\x0evariable_price\x18\x02 \x01(\x0b\x32{.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEvent.PricingScheduleH\x00\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x01\x88\x01\x01\x1a\x33\n\x10PriceForQuantity\x12\x10\n\x08quantity\x18\x01 \x01(\x04\x12\r\n\x05price\x18\x02 \x01(\x04\x1a\xac\x01\n\x0fPricingSchedule\x12\x98\x01\n\x12price_for_quantity\x18\x01 \x03(\x0b\x32|.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEvent.PriceForQuantityB\x07\n\x05priceB\x0e\n\x0c_public_note\x1a\xfc\x02\n\x10GroupActionEvent\x12n\n\x0btoken_event\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.TokenEventH\x00\x12t\n\x0e\x64ocument_event\x18\x02 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DocumentEventH\x00\x12t\n\x0e\x63ontract_event\x18\x03 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.ContractEventH\x00\x42\x0c\n\nevent_type\x1a\x8b\x01\n\rDocumentEvent\x12r\n\x06\x63reate\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DocumentCreateEventH\x00\x42\x06\n\x04type\x1a/\n\x13\x44ocumentCreateEvent\x12\x18\n\x10\x63reated_document\x18\x01 \x01(\x0c\x1a/\n\x13\x43ontractUpdateEvent\x12\x18\n\x10updated_contract\x18\x01 \x01(\x0c\x1a\x8b\x01\n\rContractEvent\x12r\n\x06update\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.ContractUpdateEventH\x00\x42\x06\n\x04type\x1a\xd1\x07\n\nTokenEvent\x12\x66\n\x04mint\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.MintEventH\x00\x12\x66\n\x04\x62urn\x18\x02 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.BurnEventH\x00\x12j\n\x06\x66reeze\x18\x03 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.FreezeEventH\x00\x12n\n\x08unfreeze\x18\x04 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UnfreezeEventH\x00\x12\x84\x01\n\x14\x64\x65stroy_frozen_funds\x18\x05 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DestroyFrozenFundsEventH\x00\x12}\n\x10\x65mergency_action\x18\x06 \x01(\x0b\x32\x61.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.EmergencyActionEventH\x00\x12\x82\x01\n\x13token_config_update\x18\x07 \x01(\x0b\x32\x63.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.TokenConfigUpdateEventH\x00\x12\x83\x01\n\x0cupdate_price\x18\x08 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEventH\x00\x42\x06\n\x04type\x1a\x93\x01\n\x10GroupActionEntry\x12\x11\n\taction_id\x18\x01 \x01(\x0c\x12l\n\x05\x65vent\x18\x02 \x01(\x0b\x32].org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionEvent\x1a\x84\x01\n\x0cGroupActions\x12t\n\rgroup_actions\x18\x01 \x03(\x0b\x32].org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionEntryB\x08\n\x06resultB\t\n\x07version\"\x88\x03\n\x1cGetGroupActionSignersRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionSignersRequest.GetGroupActionSignersRequestV0H\x00\x1a\xce\x01\n\x1eGetGroupActionSignersRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12T\n\x06status\x18\x03 \x01(\x0e\x32\x44.org.dash.platform.dapi.v0.GetGroupActionSignersRequest.ActionStatus\x12\x11\n\taction_id\x18\x04 \x01(\x0c\x12\r\n\x05prove\x18\x05 \x01(\x08\"&\n\x0c\x41\x63tionStatus\x12\n\n\x06\x41\x43TIVE\x10\x00\x12\n\n\x06\x43LOSED\x10\x01\x42\t\n\x07version\"\x8b\x05\n\x1dGetGroupActionSignersResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0H\x00\x1a\xf6\x03\n\x1fGetGroupActionSignersResponseV0\x12\x8b\x01\n\x14group_action_signers\x18\x01 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0.GroupActionSignersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x35\n\x11GroupActionSigner\x12\x11\n\tsigner_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\x91\x01\n\x12GroupActionSigners\x12{\n\x07signers\x18\x01 \x03(\x0b\x32j.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0.GroupActionSignerB\x08\n\x06resultB\t\n\x07version\"\xb5\x01\n\x15GetAddressInfoRequest\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetAddressInfoRequest.GetAddressInfoRequestV0H\x00\x1a\x39\n\x17GetAddressInfoRequestV0\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x85\x01\n\x10\x41\x64\x64ressInfoEntry\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12J\n\x11\x62\x61lance_and_nonce\x18\x02 \x01(\x0b\x32*.org.dash.platform.dapi.v0.BalanceAndNonceH\x00\x88\x01\x01\x42\x14\n\x12_balance_and_nonce\"1\n\x0f\x42\x61lanceAndNonce\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\r\n\x05nonce\x18\x02 \x01(\r\"_\n\x12\x41\x64\x64ressInfoEntries\x12I\n\x14\x61\x64\x64ress_info_entries\x18\x01 \x03(\x0b\x32+.org.dash.platform.dapi.v0.AddressInfoEntry\"m\n\x14\x41\x64\x64ressBalanceChange\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x19\n\x0bset_balance\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12\x1c\n\x0e\x61\x64\x64_to_balance\x18\x03 \x01(\x04\x42\x02\x30\x01H\x00\x42\x0b\n\toperation\"x\n\x1a\x42lockAddressBalanceChanges\x12\x18\n\x0c\x62lock_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12@\n\x07\x63hanges\x18\x02 \x03(\x0b\x32/.org.dash.platform.dapi.v0.AddressBalanceChange\"k\n\x1b\x41\x64\x64ressBalanceUpdateEntries\x12L\n\rblock_changes\x18\x01 \x03(\x0b\x32\x35.org.dash.platform.dapi.v0.BlockAddressBalanceChanges\"\xe1\x02\n\x16GetAddressInfoResponse\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetAddressInfoResponse.GetAddressInfoResponseV0H\x00\x1a\xe1\x01\n\x18GetAddressInfoResponseV0\x12I\n\x12\x61\x64\x64ress_info_entry\x18\x01 \x01(\x0b\x32+.org.dash.platform.dapi.v0.AddressInfoEntryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc3\x01\n\x18GetAddressesInfosRequest\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetAddressesInfosRequest.GetAddressesInfosRequestV0H\x00\x1a>\n\x1aGetAddressesInfosRequestV0\x12\x11\n\taddresses\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf1\x02\n\x19GetAddressesInfosResponse\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetAddressesInfosResponse.GetAddressesInfosResponseV0H\x00\x1a\xe8\x01\n\x1bGetAddressesInfosResponseV0\x12M\n\x14\x61\x64\x64ress_info_entries\x18\x01 \x01(\x0b\x32-.org.dash.platform.dapi.v0.AddressInfoEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb5\x01\n\x1dGetAddressesTrunkStateRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetAddressesTrunkStateRequest.GetAddressesTrunkStateRequestV0H\x00\x1a!\n\x1fGetAddressesTrunkStateRequestV0B\t\n\x07version\"\xaa\x02\n\x1eGetAddressesTrunkStateResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetAddressesTrunkStateResponse.GetAddressesTrunkStateResponseV0H\x00\x1a\x92\x01\n GetAddressesTrunkStateResponseV0\x12/\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.Proof\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\t\n\x07version\"\xf0\x01\n\x1eGetAddressesBranchStateRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetAddressesBranchStateRequest.GetAddressesBranchStateRequestV0H\x00\x1aY\n GetAddressesBranchStateRequestV0\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12\r\n\x05\x64\x65pth\x18\x02 \x01(\r\x12\x19\n\x11\x63heckpoint_height\x18\x03 \x01(\x04\x42\t\n\x07version\"\xd1\x01\n\x1fGetAddressesBranchStateResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetAddressesBranchStateResponse.GetAddressesBranchStateResponseV0H\x00\x1a\x37\n!GetAddressesBranchStateResponseV0\x12\x12\n\nmerk_proof\x18\x02 \x01(\x0c\x42\t\n\x07version\"\x9e\x02\n%GetRecentAddressBalanceChangesRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesRequest.GetRecentAddressBalanceChangesRequestV0H\x00\x1ar\n\'GetRecentAddressBalanceChangesRequestV0\x12\x18\n\x0cstart_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x02 \x01(\x08\x12\x1e\n\x16start_height_exclusive\x18\x03 \x01(\x08\x42\t\n\x07version\"\xb8\x03\n&GetRecentAddressBalanceChangesResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesResponse.GetRecentAddressBalanceChangesResponseV0H\x00\x1a\x88\x02\n(GetRecentAddressBalanceChangesResponseV0\x12`\n\x1e\x61\x64\x64ress_balance_update_entries\x18\x01 \x01(\x0b\x32\x36.org.dash.platform.dapi.v0.AddressBalanceUpdateEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"G\n\x16\x42lockHeightCreditEntry\x12\x18\n\x0c\x62lock_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x13\n\x07\x63redits\x18\x02 \x01(\x04\x42\x02\x30\x01\"\xb0\x01\n\x1d\x43ompactedAddressBalanceChange\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x19\n\x0bset_credits\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12V\n\x19\x61\x64\x64_to_credits_operations\x18\x03 \x01(\x0b\x32\x31.org.dash.platform.dapi.v0.AddToCreditsOperationsH\x00\x42\x0b\n\toperation\"\\\n\x16\x41\x64\x64ToCreditsOperations\x12\x42\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x31.org.dash.platform.dapi.v0.BlockHeightCreditEntry\"\xae\x01\n#CompactedBlockAddressBalanceChanges\x12\x1e\n\x12start_block_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1c\n\x10\x65nd_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12I\n\x07\x63hanges\x18\x03 \x03(\x0b\x32\x38.org.dash.platform.dapi.v0.CompactedAddressBalanceChange\"\x87\x01\n$CompactedAddressBalanceUpdateEntries\x12_\n\x17\x63ompacted_block_changes\x18\x01 \x03(\x0b\x32>.org.dash.platform.dapi.v0.CompactedBlockAddressBalanceChanges\"\xa9\x02\n.GetRecentCompactedAddressBalanceChangesRequest\x12\x88\x01\n\x02v0\x18\x01 \x01(\x0b\x32z.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesRequest.GetRecentCompactedAddressBalanceChangesRequestV0H\x00\x1a\x61\n0GetRecentCompactedAddressBalanceChangesRequestV0\x12\x1e\n\x12start_block_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf0\x03\n/GetRecentCompactedAddressBalanceChangesResponse\x12\x8a\x01\n\x02v0\x18\x01 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesResponse.GetRecentCompactedAddressBalanceChangesResponseV0H\x00\x1a\xa4\x02\n1GetRecentCompactedAddressBalanceChangesResponseV0\x12s\n(compacted_address_balance_update_entries\x18\x01 \x01(\x0b\x32?.org.dash.platform.dapi.v0.CompactedAddressBalanceUpdateEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xf4\x01\n GetShieldedEncryptedNotesRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesRequest.GetShieldedEncryptedNotesRequestV0H\x00\x1aW\n\"GetShieldedEncryptedNotesRequestV0\x12\x13\n\x0bstart_index\x18\x01 \x01(\x04\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xbc\x05\n!GetShieldedEncryptedNotesResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse.GetShieldedEncryptedNotesResponseV0H\x00\x1a\x9b\x04\n#GetShieldedEncryptedNotesResponseV0\x12\x8a\x01\n\x0f\x65ncrypted_notes\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse.GetShieldedEncryptedNotesResponseV0.EncryptedNotesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aW\n\rEncryptedNote\x12\x11\n\tnullifier\x18\x01 \x01(\x0c\x12\x0b\n\x03\x63mx\x18\x02 \x01(\x0c\x12\x16\n\x0e\x65ncrypted_note\x18\x03 \x01(\x0c\x12\x0e\n\x06\x63v_net\x18\x04 \x01(\x0c\x1a\x91\x01\n\x0e\x45ncryptedNotes\x12\x7f\n\x07\x65ntries\x18\x01 \x03(\x0b\x32n.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse.GetShieldedEncryptedNotesResponseV0.EncryptedNoteB\x08\n\x06resultB\t\n\x07version\"\xb4\x01\n\x19GetShieldedAnchorsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetShieldedAnchorsRequest.GetShieldedAnchorsRequestV0H\x00\x1a,\n\x1bGetShieldedAnchorsRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xb1\x03\n\x1aGetShieldedAnchorsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse.GetShieldedAnchorsResponseV0H\x00\x1a\xa5\x02\n\x1cGetShieldedAnchorsResponseV0\x12m\n\x07\x61nchors\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse.GetShieldedAnchorsResponseV0.AnchorsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\x07\x41nchors\x12\x0f\n\x07\x61nchors\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xd8\x01\n\"GetMostRecentShieldedAnchorRequest\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorRequest.GetMostRecentShieldedAnchorRequestV0H\x00\x1a\x35\n$GetMostRecentShieldedAnchorRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xdc\x02\n#GetMostRecentShieldedAnchorResponse\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorResponse.GetMostRecentShieldedAnchorResponseV0H\x00\x1a\xb5\x01\n%GetMostRecentShieldedAnchorResponseV0\x12\x10\n\x06\x61nchor\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbc\x01\n\x1bGetShieldedPoolStateRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetShieldedPoolStateRequest.GetShieldedPoolStateRequestV0H\x00\x1a.\n\x1dGetShieldedPoolStateRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xcb\x02\n\x1cGetShieldedPoolStateResponse\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedPoolStateResponse.GetShieldedPoolStateResponseV0H\x00\x1a\xb9\x01\n\x1eGetShieldedPoolStateResponseV0\x12\x1b\n\rtotal_balance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc0\x01\n\x1cGetShieldedNotesCountRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedNotesCountRequest.GetShieldedNotesCountRequestV0H\x00\x1a/\n\x1eGetShieldedNotesCountRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xd3\x02\n\x1dGetShieldedNotesCountResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetShieldedNotesCountResponse.GetShieldedNotesCountResponseV0H\x00\x1a\xbe\x01\n\x1fGetShieldedNotesCountResponseV0\x12\x1f\n\x11total_notes_count\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xd4\x01\n\x1cGetShieldedNullifiersRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedNullifiersRequest.GetShieldedNullifiersRequestV0H\x00\x1a\x43\n\x1eGetShieldedNullifiersRequestV0\x12\x12\n\nnullifiers\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x86\x05\n\x1dGetShieldedNullifiersResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0H\x00\x1a\xf1\x03\n\x1fGetShieldedNullifiersResponseV0\x12\x88\x01\n\x12nullifier_statuses\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0.NullifierStatusesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x36\n\x0fNullifierStatus\x12\x11\n\tnullifier\x18\x01 \x01(\x0c\x12\x10\n\x08is_spent\x18\x02 \x01(\x08\x1a\x8e\x01\n\x11NullifierStatuses\x12y\n\x07\x65ntries\x18\x01 \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0.NullifierStatusB\x08\n\x06resultB\t\n\x07version*Z\n\nKeyPurpose\x12\x12\n\x0e\x41UTHENTICATION\x10\x00\x12\x0e\n\nENCRYPTION\x10\x01\x12\x0e\n\nDECRYPTION\x10\x02\x12\x0c\n\x08TRANSFER\x10\x03\x12\n\n\x06VOTING\x10\x05*\xb9\x01\n\x16\x43ontractModerationList\x12(\n$CONTRACT_MODERATION_LIST_UNSPECIFIED\x10\x00\x12$\n CONTRACT_MODERATION_LIST_BANLIST\x10\x01\x12(\n$CONTRACT_MODERATION_LIST_SUSPENSIONS\x10\x02\x12%\n!CONTRACT_MODERATION_LIST_WARNINGS\x10\x03\x32\xd0P\n\x08Platform\x12\x93\x01\n\x18\x62roadcastStateTransition\x12:.org.dash.platform.dapi.v0.BroadcastStateTransitionRequest\x1a;.org.dash.platform.dapi.v0.BroadcastStateTransitionResponse\x12l\n\x0bgetIdentity\x12-.org.dash.platform.dapi.v0.GetIdentityRequest\x1a..org.dash.platform.dapi.v0.GetIdentityResponse\x12x\n\x0fgetIdentityKeys\x12\x31.org.dash.platform.dapi.v0.GetIdentityKeysRequest\x1a\x32.org.dash.platform.dapi.v0.GetIdentityKeysResponse\x12\x96\x01\n\x19getIdentitiesContractKeys\x12;.org.dash.platform.dapi.v0.GetIdentitiesContractKeysRequest\x1a<.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse\x12{\n\x10getIdentityNonce\x12\x32.org.dash.platform.dapi.v0.GetIdentityNonceRequest\x1a\x33.org.dash.platform.dapi.v0.GetIdentityNonceResponse\x12\x93\x01\n\x18getIdentityContractNonce\x12:.org.dash.platform.dapi.v0.GetIdentityContractNonceRequest\x1a;.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse\x12\xa8\x01\n\x1fgetIdentityKeysRemainingBudgets\x12\x41.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsRequest\x1a\x42.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsResponse\x12\x81\x01\n\x12getIdentityBalance\x12\x34.org.dash.platform.dapi.v0.GetIdentityBalanceRequest\x1a\x35.org.dash.platform.dapi.v0.GetIdentityBalanceResponse\x12\x8a\x01\n\x15getIdentitiesBalances\x12\x37.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest\x1a\x38.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse\x12\xa2\x01\n\x1dgetIdentityBalanceAndRevision\x12?.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionRequest\x1a@.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse\x12\xaf\x01\n#getEvonodesProposedEpochBlocksByIds\x12\x45.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest\x1a\x41.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse\x12\xb3\x01\n%getEvonodesProposedEpochBlocksByRange\x12G.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest\x1a\x41.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse\x12x\n\x0fgetDataContract\x12\x31.org.dash.platform.dapi.v0.GetDataContractRequest\x1a\x32.org.dash.platform.dapi.v0.GetDataContractResponse\x12\x8d\x01\n\x16getDataContractHistory\x12\x38.org.dash.platform.dapi.v0.GetDataContractHistoryRequest\x1a\x39.org.dash.platform.dapi.v0.GetDataContractHistoryResponse\x12\xa5\x01\n\x1egetDataContractsLatestVersions\x12@.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsRequest\x1a\x41.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsResponse\x12{\n\x10getDataContracts\x12\x32.org.dash.platform.dapi.v0.GetDataContractsRequest\x1a\x33.org.dash.platform.dapi.v0.GetDataContractsResponse\x12\x89\x01\n\x17getDataContractsByRange\x12\x39.org.dash.platform.dapi.v0.GetDataContractsByRangeRequest\x1a\x33.org.dash.platform.dapi.v0.GetDataContractsResponse\x12\x87\x01\n\x14getContractGroupInfo\x12\x36.org.dash.platform.dapi.v0.GetContractGroupInfoRequest\x1a\x37.org.dash.platform.dapi.v0.GetContractGroupInfoResponse\x12\x90\x01\n\x17getContractGroupMembers\x12\x39.org.dash.platform.dapi.v0.GetContractGroupMembersRequest\x1a:.org.dash.platform.dapi.v0.GetContractGroupMembersResponse\x12\x9f\x01\n\x1cgetContractGroupsForContract\x12>.org.dash.platform.dapi.v0.GetContractGroupsForContractRequest\x1a?.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse\x12\x9c\x01\n\x1bgetContractModerationStatus\x12=.org.dash.platform.dapi.v0.GetContractModerationStatusRequest\x1a>.org.dash.platform.dapi.v0.GetContractModerationStatusResponse\x12\x9f\x01\n\x1cgetContractModerationEntries\x12>.org.dash.platform.dapi.v0.GetContractModerationEntriesRequest\x1a?.org.dash.platform.dapi.v0.GetContractModerationEntriesResponse\x12\x9c\x01\n\x1bgetContractDocumentRemovals\x12=.org.dash.platform.dapi.v0.GetContractDocumentRemovalsRequest\x1a>.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse\x12\x81\x01\n\x12getContractFeePots\x12\x34.org.dash.platform.dapi.v0.GetContractFeePotsRequest\x1a\x35.org.dash.platform.dapi.v0.GetContractFeePotsResponse\x12\x81\x01\n\x12getDocumentHistory\x12\x34.org.dash.platform.dapi.v0.GetDocumentHistoryRequest\x1a\x35.org.dash.platform.dapi.v0.GetDocumentHistoryResponse\x12o\n\x0cgetDocuments\x12..org.dash.platform.dapi.v0.GetDocumentsRequest\x1a/.org.dash.platform.dapi.v0.GetDocumentsResponse\x12\x99\x01\n\x1agetIdentityByPublicKeyHash\x12<.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest\x1a=.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse\x12\xb4\x01\n#getIdentityByNonUniquePublicKeyHash\x12\x45.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashRequest\x1a\x46.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse\x12\x9f\x01\n\x1cwaitForStateTransitionResult\x12>.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest\x1a?.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse\x12\x81\x01\n\x12getConsensusParams\x12\x34.org.dash.platform.dapi.v0.GetConsensusParamsRequest\x1a\x35.org.dash.platform.dapi.v0.GetConsensusParamsResponse\x12\xa5\x01\n\x1egetProtocolVersionUpgradeState\x12@.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateRequest\x1a\x41.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse\x12\xb4\x01\n#getProtocolVersionUpgradeVoteStatus\x12\x45.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusRequest\x1a\x46.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse\x12r\n\rgetEpochsInfo\x12/.org.dash.platform.dapi.v0.GetEpochsInfoRequest\x1a\x30.org.dash.platform.dapi.v0.GetEpochsInfoResponse\x12\x8d\x01\n\x16getFinalizedEpochInfos\x12\x38.org.dash.platform.dapi.v0.GetFinalizedEpochInfosRequest\x1a\x39.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse\x12\x8a\x01\n\x15getContestedResources\x12\x37.org.dash.platform.dapi.v0.GetContestedResourcesRequest\x1a\x38.org.dash.platform.dapi.v0.GetContestedResourcesResponse\x12\xa2\x01\n\x1dgetContestedResourceVoteState\x12?.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest\x1a@.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse\x12\xba\x01\n%getContestedResourceVotersForIdentity\x12G.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest\x1aH.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse\x12\xae\x01\n!getContestedResourceIdentityVotes\x12\x43.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest\x1a\x44.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse\x12\x8a\x01\n\x15getVotePollsByEndDate\x12\x37.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest\x1a\x38.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse\x12\xa5\x01\n\x1egetPrefundedSpecializedBalance\x12@.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceRequest\x1a\x41.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse\x12\x96\x01\n\x19getTotalCreditsInPlatform\x12;.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformRequest\x1a<.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformResponse\x12x\n\x0fgetPathElements\x12\x31.org.dash.platform.dapi.v0.GetPathElementsRequest\x1a\x32.org.dash.platform.dapi.v0.GetPathElementsResponse\x12\x66\n\tgetStatus\x12+.org.dash.platform.dapi.v0.GetStatusRequest\x1a,.org.dash.platform.dapi.v0.GetStatusResponse\x12\x8a\x01\n\x15getCurrentQuorumsInfo\x12\x37.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest\x1a\x38.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse\x12\x93\x01\n\x18getIdentityTokenBalances\x12:.org.dash.platform.dapi.v0.GetIdentityTokenBalancesRequest\x1a;.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse\x12\x99\x01\n\x1agetIdentitiesTokenBalances\x12<.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesRequest\x1a=.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse\x12\x8a\x01\n\x15getIdentityTokenInfos\x12\x37.org.dash.platform.dapi.v0.GetIdentityTokenInfosRequest\x1a\x38.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse\x12\x90\x01\n\x17getIdentitiesTokenInfos\x12\x39.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosRequest\x1a:.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse\x12{\n\x10getTokenStatuses\x12\x32.org.dash.platform.dapi.v0.GetTokenStatusesRequest\x1a\x33.org.dash.platform.dapi.v0.GetTokenStatusesResponse\x12\x9f\x01\n\x1cgetTokenDirectPurchasePrices\x12>.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesRequest\x1a?.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse\x12\x87\x01\n\x14getTokenContractInfo\x12\x36.org.dash.platform.dapi.v0.GetTokenContractInfoRequest\x1a\x37.org.dash.platform.dapi.v0.GetTokenContractInfoResponse\x12\xb1\x01\n\"getTokenPreProgrammedDistributions\x12\x44.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest\x1a\x45.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse\x12\xbd\x01\n&getTokenPerpetualDistributionLastClaim\x12H.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest\x1aI.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse\x12\x84\x01\n\x13getTokenTotalSupply\x12\x35.org.dash.platform.dapi.v0.GetTokenTotalSupplyRequest\x1a\x36.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse\x12o\n\x0cgetGroupInfo\x12..org.dash.platform.dapi.v0.GetGroupInfoRequest\x1a/.org.dash.platform.dapi.v0.GetGroupInfoResponse\x12r\n\rgetGroupInfos\x12/.org.dash.platform.dapi.v0.GetGroupInfosRequest\x1a\x30.org.dash.platform.dapi.v0.GetGroupInfosResponse\x12x\n\x0fgetGroupActions\x12\x31.org.dash.platform.dapi.v0.GetGroupActionsRequest\x1a\x32.org.dash.platform.dapi.v0.GetGroupActionsResponse\x12\x8a\x01\n\x15getGroupActionSigners\x12\x37.org.dash.platform.dapi.v0.GetGroupActionSignersRequest\x1a\x38.org.dash.platform.dapi.v0.GetGroupActionSignersResponse\x12u\n\x0egetAddressInfo\x12\x30.org.dash.platform.dapi.v0.GetAddressInfoRequest\x1a\x31.org.dash.platform.dapi.v0.GetAddressInfoResponse\x12~\n\x11getAddressesInfos\x12\x33.org.dash.platform.dapi.v0.GetAddressesInfosRequest\x1a\x34.org.dash.platform.dapi.v0.GetAddressesInfosResponse\x12\x8d\x01\n\x16getAddressesTrunkState\x12\x38.org.dash.platform.dapi.v0.GetAddressesTrunkStateRequest\x1a\x39.org.dash.platform.dapi.v0.GetAddressesTrunkStateResponse\x12\x90\x01\n\x17getAddressesBranchState\x12\x39.org.dash.platform.dapi.v0.GetAddressesBranchStateRequest\x1a:.org.dash.platform.dapi.v0.GetAddressesBranchStateResponse\x12\xa5\x01\n\x1egetRecentAddressBalanceChanges\x12@.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesRequest\x1a\x41.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesResponse\x12\xc0\x01\n\'getRecentCompactedAddressBalanceChanges\x12I.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesRequest\x1aJ.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesResponse\x12\x96\x01\n\x19getShieldedEncryptedNotes\x12;.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesRequest\x1a<.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse\x12\x81\x01\n\x12getShieldedAnchors\x12\x34.org.dash.platform.dapi.v0.GetShieldedAnchorsRequest\x1a\x35.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse\x12\x9c\x01\n\x1bgetMostRecentShieldedAnchor\x12=.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorRequest\x1a>.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorResponse\x12\x87\x01\n\x14getShieldedPoolState\x12\x36.org.dash.platform.dapi.v0.GetShieldedPoolStateRequest\x1a\x37.org.dash.platform.dapi.v0.GetShieldedPoolStateResponse\x12\x8a\x01\n\x15getShieldedNotesCount\x12\x37.org.dash.platform.dapi.v0.GetShieldedNotesCountRequest\x1a\x38.org.dash.platform.dapi.v0.GetShieldedNotesCountResponse\x12\x8a\x01\n\x15getShieldedNullifiers\x12\x37.org.dash.platform.dapi.v0.GetShieldedNullifiersRequest\x1a\x38.org.dash.platform.dapi.v0.GetShieldedNullifiersResponseb\x06proto3' + serialized_pb=b'\n\x0eplatform.proto\x12\x19org.dash.platform.dapi.v0\x1a\x1egoogle/protobuf/wrappers.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x81\x01\n\x05Proof\x12\x15\n\rgrovedb_proof\x18\x01 \x01(\x0c\x12\x13\n\x0bquorum_hash\x18\x02 \x01(\x0c\x12\x11\n\tsignature\x18\x03 \x01(\x0c\x12\r\n\x05round\x18\x04 \x01(\r\x12\x15\n\rblock_id_hash\x18\x05 \x01(\x0c\x12\x13\n\x0bquorum_type\x18\x06 \x01(\r\"\x98\x01\n\x10ResponseMetadata\x12\x12\n\x06height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12 \n\x18\x63ore_chain_locked_height\x18\x02 \x01(\r\x12\r\n\x05\x65poch\x18\x03 \x01(\r\x12\x13\n\x07time_ms\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x18\n\x10protocol_version\x18\x05 \x01(\r\x12\x10\n\x08\x63hain_id\x18\x06 \x01(\t\"L\n\x1dStateTransitionBroadcastError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\";\n\x1f\x42roadcastStateTransitionRequest\x12\x18\n\x10state_transition\x18\x01 \x01(\x0c\"\"\n BroadcastStateTransitionResponse\"\xa4\x01\n\x12GetIdentityRequest\x12P\n\x02v0\x18\x01 \x01(\x0b\x32\x42.org.dash.platform.dapi.v0.GetIdentityRequest.GetIdentityRequestV0H\x00\x1a\x31\n\x14GetIdentityRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xc1\x01\n\x17GetIdentityNonceRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentityNonceRequest.GetIdentityNonceRequestV0H\x00\x1a?\n\x19GetIdentityNonceRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf6\x01\n\x1fGetIdentityContractNonceRequest\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentityContractNonceRequest.GetIdentityContractNonceRequestV0H\x00\x1a\\\n!GetIdentityContractNonceRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x13\n\x0b\x63ontract_id\x18\x02 \x01(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xc0\x01\n\x19GetIdentityBalanceRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetIdentityBalanceRequest.GetIdentityBalanceRequestV0H\x00\x1a\x38\n\x1bGetIdentityBalanceRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xec\x01\n$GetIdentityBalanceAndRevisionRequest\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionRequest.GetIdentityBalanceAndRevisionRequestV0H\x00\x1a\x43\n&GetIdentityBalanceAndRevisionRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9e\x02\n\x13GetIdentityResponse\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetIdentityResponse.GetIdentityResponseV0H\x00\x1a\xa7\x01\n\x15GetIdentityResponseV0\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbc\x02\n\x18GetIdentityNonceResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetIdentityNonceResponse.GetIdentityNonceResponseV0H\x00\x1a\xb6\x01\n\x1aGetIdentityNonceResponseV0\x12\x1c\n\x0eidentity_nonce\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xe5\x02\n GetIdentityContractNonceResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse.GetIdentityContractNonceResponseV0H\x00\x1a\xc7\x01\n\"GetIdentityContractNonceResponseV0\x12%\n\x17identity_contract_nonce\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\x8e\x02\n&GetIdentityKeysRemainingBudgetsRequest\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsRequest.GetIdentityKeysRemainingBudgetsRequestV0H\x00\x1a_\n(GetIdentityKeysRemainingBudgetsRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x0f\n\x07key_ids\x18\x02 \x03(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\x96\x06\n\'GetIdentityKeysRemainingBudgetsResponse\x12z\n\x02v0\x18\x01 \x01(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsResponse.GetIdentityKeysRemainingBudgetsResponseV0H\x00\x1a\xe3\x04\n)GetIdentityKeysRemainingBudgetsResponseV0\x12\xa4\x01\n\x16keys_remaining_budgets\x18\x01 \x01(\x0b\x32\x81\x01.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsResponse.GetIdentityKeysRemainingBudgetsResponseV0.KeysRemainingBudgetsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x61\n\x17KeyRemainingBudgetEntry\x12\x0e\n\x06key_id\x18\x01 \x01(\r\x12!\n\x10remaining_budget\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x42\x13\n\x11_remaining_budget\x1a\xaf\x01\n\x14KeysRemainingBudgets\x12\x96\x01\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsResponse.GetIdentityKeysRemainingBudgetsResponseV0.KeyRemainingBudgetEntryB\x08\n\x06resultB\t\n\x07version\"\xbd\x02\n\x1aGetIdentityBalanceResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetIdentityBalanceResponse.GetIdentityBalanceResponseV0H\x00\x1a\xb1\x01\n\x1cGetIdentityBalanceResponseV0\x12\x15\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb1\x04\n%GetIdentityBalanceAndRevisionResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0H\x00\x1a\x84\x03\n\'GetIdentityBalanceAndRevisionResponseV0\x12\x9b\x01\n\x14\x62\x61lance_and_revision\x18\x01 \x01(\x0b\x32{.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.GetIdentityBalanceAndRevisionResponseV0.BalanceAndRevisionH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a?\n\x12\x42\x61lanceAndRevision\x12\x13\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x14\n\x08revision\x18\x02 \x01(\x04\x42\x02\x30\x01\x42\x08\n\x06resultB\t\n\x07version\"\xd1\x01\n\x0eKeyRequestType\x12\x36\n\x08\x61ll_keys\x18\x01 \x01(\x0b\x32\".org.dash.platform.dapi.v0.AllKeysH\x00\x12@\n\rspecific_keys\x18\x02 \x01(\x0b\x32\'.org.dash.platform.dapi.v0.SpecificKeysH\x00\x12:\n\nsearch_key\x18\x03 \x01(\x0b\x32$.org.dash.platform.dapi.v0.SearchKeyH\x00\x42\t\n\x07request\"\t\n\x07\x41llKeys\"\x1f\n\x0cSpecificKeys\x12\x0f\n\x07key_ids\x18\x01 \x03(\r\"\xb6\x01\n\tSearchKey\x12I\n\x0bpurpose_map\x18\x01 \x03(\x0b\x32\x34.org.dash.platform.dapi.v0.SearchKey.PurposeMapEntry\x1a^\n\x0fPurposeMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.org.dash.platform.dapi.v0.SecurityLevelMap:\x02\x38\x01\"\xbf\x02\n\x10SecurityLevelMap\x12]\n\x12security_level_map\x18\x01 \x03(\x0b\x32\x41.org.dash.platform.dapi.v0.SecurityLevelMap.SecurityLevelMapEntry\x1aw\n\x15SecurityLevelMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12M\n\x05value\x18\x02 \x01(\x0e\x32>.org.dash.platform.dapi.v0.SecurityLevelMap.KeyKindRequestType:\x02\x38\x01\"S\n\x12KeyKindRequestType\x12\x1f\n\x1b\x43URRENT_KEY_OF_KIND_REQUEST\x10\x00\x12\x1c\n\x18\x41LL_KEYS_OF_KIND_REQUEST\x10\x01\"\xda\x02\n\x16GetIdentityKeysRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetIdentityKeysRequest.GetIdentityKeysRequestV0H\x00\x1a\xda\x01\n\x18GetIdentityKeysRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12?\n\x0crequest_type\x18\x02 \x01(\x0b\x32).org.dash.platform.dapi.v0.KeyRequestType\x12+\n\x05limit\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\x99\x03\n\x17GetIdentityKeysResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentityKeysResponse.GetIdentityKeysResponseV0H\x00\x1a\x96\x02\n\x19GetIdentityKeysResponseV0\x12\x61\n\x04keys\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetIdentityKeysResponse.GetIdentityKeysResponseV0.KeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\x04Keys\x12\x12\n\nkeys_bytes\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xef\x02\n GetIdentitiesContractKeysRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentitiesContractKeysRequest.GetIdentitiesContractKeysRequestV0H\x00\x1a\xd1\x01\n\"GetIdentitiesContractKeysRequestV0\x12\x16\n\x0eidentities_ids\x18\x01 \x03(\x0c\x12\x13\n\x0b\x63ontract_id\x18\x02 \x01(\x0c\x12\x1f\n\x12\x64ocument_type_name\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x37\n\x08purposes\x18\x04 \x03(\x0e\x32%.org.dash.platform.dapi.v0.KeyPurpose\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x15\n\x13_document_type_nameB\t\n\x07version\"\xdf\x06\n!GetIdentitiesContractKeysResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0H\x00\x1a\xbe\x05\n#GetIdentitiesContractKeysResponseV0\x12\x8a\x01\n\x0fidentities_keys\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.IdentitiesKeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aY\n\x0bPurposeKeys\x12\x36\n\x07purpose\x18\x01 \x01(\x0e\x32%.org.dash.platform.dapi.v0.KeyPurpose\x12\x12\n\nkeys_bytes\x18\x02 \x03(\x0c\x1a\x9f\x01\n\x0cIdentityKeys\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12z\n\x04keys\x18\x02 \x03(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.PurposeKeys\x1a\x90\x01\n\x0eIdentitiesKeys\x12~\n\x07\x65ntries\x18\x01 \x03(\x0b\x32m.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse.GetIdentitiesContractKeysResponseV0.IdentityKeysB\x08\n\x06resultB\t\n\x07version\"\xa4\x02\n*GetEvonodesProposedEpochBlocksByIdsRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest.GetEvonodesProposedEpochBlocksByIdsRequestV0H\x00\x1ah\n,GetEvonodesProposedEpochBlocksByIdsRequestV0\x12\x12\n\x05\x65poch\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x0b\n\x03ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\x08\n\x06_epochB\t\n\x07version\"\x92\x06\n&GetEvonodesProposedEpochBlocksResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0H\x00\x1a\xe2\x04\n(GetEvonodesProposedEpochBlocksResponseV0\x12\xb1\x01\n#evonodes_proposed_block_counts_info\x18\x01 \x01(\x0b\x32\x81\x01.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0.EvonodesProposedBlocksH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a?\n\x15\x45vonodeProposedBlocks\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x11\n\x05\x63ount\x18\x02 \x01(\x04\x42\x02\x30\x01\x1a\xc4\x01\n\x16\x45vonodesProposedBlocks\x12\xa9\x01\n\x1e\x65vonodes_proposed_block_counts\x18\x01 \x03(\x0b\x32\x80\x01.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse.GetEvonodesProposedEpochBlocksResponseV0.EvonodeProposedBlocksB\x08\n\x06resultB\t\n\x07version\"\xf2\x02\n,GetEvonodesProposedEpochBlocksByRangeRequest\x12\x84\x01\n\x02v0\x18\x01 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest.GetEvonodesProposedEpochBlocksByRangeRequestV0H\x00\x1a\xaf\x01\n.GetEvonodesProposedEpochBlocksByRangeRequestV0\x12\x12\n\x05\x65poch\x18\x01 \x01(\rH\x01\x88\x01\x01\x12\x12\n\x05limit\x18\x02 \x01(\rH\x02\x88\x01\x01\x12\x15\n\x0bstart_after\x18\x03 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x04 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x07\n\x05startB\x08\n\x06_epochB\x08\n\x06_limitB\t\n\x07version\"\xcd\x01\n\x1cGetIdentitiesBalancesRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest.GetIdentitiesBalancesRequestV0H\x00\x1a<\n\x1eGetIdentitiesBalancesRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9f\x05\n\x1dGetIdentitiesBalancesResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0H\x00\x1a\x8a\x04\n\x1fGetIdentitiesBalancesResponseV0\x12\x8a\x01\n\x13identities_balances\x18\x01 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0.IdentitiesBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aL\n\x0fIdentityBalance\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x18\n\x07\x62\x61lance\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\x8f\x01\n\x12IdentitiesBalances\x12y\n\x07\x65ntries\x18\x01 \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse.GetIdentitiesBalancesResponseV0.IdentityBalanceB\x08\n\x06resultB\t\n\x07version\"\xb4\x01\n\x16GetDataContractRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetDataContractRequest.GetDataContractRequestV0H\x00\x1a\x35\n\x18GetDataContractRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xb3\x02\n\x17GetDataContractResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetDataContractResponse.GetDataContractResponseV0H\x00\x1a\xb0\x01\n\x19GetDataContractResponseV0\x12\x17\n\rdata_contract\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\x8c\x02\n%GetDataContractsLatestVersionsRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsRequest.GetDataContractsLatestVersionsRequestV0H\x00\x1a`\n\'GetDataContractsLatestVersionsRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\x19\n\x11include_contracts\x18\x02 \x01(\x08\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xfa\x05\n&GetDataContractsLatestVersionsResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsResponse.GetDataContractsLatestVersionsResponseV0H\x00\x1a\x84\x01\n\x1e\x44\x61taContractLatestVersionEntry\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x14\n\x07version\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x1a\n\rdata_contract\x18\x03 \x01(\x0cH\x01\x88\x01\x01\x42\n\n\x08_versionB\x10\n\x0e_data_contract\x1a\x90\x01\n\x1b\x44\x61taContractsLatestVersions\x12q\n\x07\x65ntries\x18\x01 \x03(\x0b\x32`.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsResponse.DataContractLatestVersionEntry\x1a\xb0\x02\n(GetDataContractsLatestVersionsResponseV0\x12\x87\x01\n\x1e\x64\x61ta_contracts_latest_versions\x18\x01 \x01(\x0b\x32].org.dash.platform.dapi.v0.GetDataContractsLatestVersionsResponse.DataContractsLatestVersionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"R\n\x1f\x43ontractGroupDocumentTypeMember\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\"G\n\x18\x43ontractGroupTokenMember\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x16\n\x0etoken_position\x18\x02 \x01(\r\"\xd7\x01\n\x1bGetContractGroupInfoRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetContractGroupInfoRequest.GetContractGroupInfoRequestV0H\x00\x1aI\n\x1dGetContractGroupInfoRequestV0\x12\x19\n\x11\x63ontract_group_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x98\x04\n\x1cGetContractGroupInfoResponse\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetContractGroupInfoResponse.GetContractGroupInfoResponseV0H\x00\x1a~\n\x11\x43ontractGroupInfo\x12\x10\n\x08owner_id\x18\x01 \x01(\x0c\x12\x11\n\tadmin_ids\x18\x02 \x03(\x0c\x12\x11\n\x04name\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x18\n\x0b\x64\x65scription\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\x07\n\x05_nameB\x0e\n\x0c_description\x1a\x86\x02\n\x1eGetContractGroupInfoResponseV0\x12h\n\x13\x63ontract_group_info\x18\x01 \x01(\x0b\x32I.org.dash.platform.dapi.v0.GetContractGroupInfoResponse.ContractGroupInfoH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xf8\x06\n\x1eGetContractGroupMembersRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetContractGroupMembersRequest.GetContractGroupMembersRequestV0H\x00\x1a@\n\x14\x43ontractMembersQuery\x12\x18\n\x0bstart_after\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x42\x0e\n\x0c_start_after\x1a\x80\x01\n\x18\x44ocumentTypeMembersQuery\x12T\n\x0bstart_after\x18\x01 \x01(\x0b\x32:.org.dash.platform.dapi.v0.ContractGroupDocumentTypeMemberH\x00\x88\x01\x01\x42\x0e\n\x0c_start_after\x1ar\n\x11TokenMembersQuery\x12M\n\x0bstart_after\x18\x01 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractGroupTokenMemberH\x00\x88\x01\x01\x42\x0e\n\x0c_start_after\x1a\xa7\x03\n GetContractGroupMembersRequestV0\x12\x19\n\x11\x63ontract_group_id\x18\x01 \x01(\x0c\x12\x63\n\tcontracts\x18\x02 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetContractGroupMembersRequest.ContractMembersQueryH\x00\x12l\n\x0e\x64ocument_types\x18\x03 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetContractGroupMembersRequest.DocumentTypeMembersQueryH\x00\x12]\n\x06tokens\x18\x04 \x01(\x0b\x32K.org.dash.platform.dapi.v0.GetContractGroupMembersRequest.TokenMembersQueryH\x00\x12\x12\n\x05limit\x18\x05 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x42\t\n\x07membersB\x08\n\x06_limitB\t\n\x07version\"\xc9\x06\n\x1fGetContractGroupMembersResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetContractGroupMembersResponse.GetContractGroupMembersResponseV0H\x00\x1a\'\n\x0f\x43ontractMembers\x12\x14\n\x0c\x63ontract_ids\x18\x01 \x03(\x0c\x1ai\n\x13\x44ocumentTypeMembers\x12R\n\x0e\x64ocument_types\x18\x01 \x03(\x0b\x32:.org.dash.platform.dapi.v0.ContractGroupDocumentTypeMember\x1aS\n\x0cTokenMembers\x12\x43\n\x06tokens\x18\x01 \x03(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractGroupTokenMember\x1a\xc5\x03\n!GetContractGroupMembersResponseV0\x12_\n\tcontracts\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetContractGroupMembersResponse.ContractMembersH\x00\x12h\n\x0e\x64ocument_types\x18\x02 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetContractGroupMembersResponse.DocumentTypeMembersH\x00\x12Y\n\x06tokens\x18\x03 \x01(\x0b\x32G.org.dash.platform.dapi.v0.GetContractGroupMembersResponse.TokenMembersH\x00\x12\x31\n\x05proof\x18\x04 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x05 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"M\n\x1a\x43ontractModerationDocument\x12\x1a\n\x12\x64ocument_type_name\x18\x01 \x01(\t\x12\x13\n\x0b\x64ocument_id\x18\x02 \x01(\x0c\"\xc6\x01\n\x18\x43ontractModerationReason\x12\x11\n\x04\x63ode\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x0c\n\x04text\x18\x02 \x01(\t\x12H\n\tdocuments\x18\x03 \x03(\x0b\x32\x35.org.dash.platform.dapi.v0.ContractModerationDocument\x12\x1f\n\x12reason_document_id\x18\x04 \x01(\x0cH\x01\x88\x01\x01\x42\x07\n\x05_codeB\x15\n\x13_reason_document_id\"i\n\x0f\x43ontractWarning\x12\x11\n\twarned_at\x18\x01 \x01(\x04\x12\x43\n\x06reason\x18\x02 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReason\"\xc5\x02\n\"GetContractModerationStatusRequest\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetContractModerationStatusRequest.GetContractModerationStatusRequestV0H\x00\x1a\xa1\x01\n$GetContractModerationStatusRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x13\n\x0bidentity_id\x18\x02 \x01(\x0c\x12@\n\x05lists\x18\x03 \x03(\x0e\x32\x31.org.dash.platform.dapi.v0.ContractModerationList\x12\r\n\x05prove\x18\x04 \x01(\x08\x42\t\n\x07version\"\xec\x06\n#GetContractModerationStatusResponse\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractModerationStatusResponse.GetContractModerationStatusResponseV0H\x00\x1a\xb4\x03\n\x18\x43ontractModerationStatus\x12\x13\n\x06\x62\x61nned\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x1c\n\x0fsuspended_until\x18\x02 \x01(\x04H\x01\x88\x01\x01\x12@\n\x05lists\x18\x03 \x03(\x0e\x32\x31.org.dash.platform.dapi.v0.ContractModerationList\x12L\n\nban_reason\x18\x04 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReasonH\x02\x88\x01\x01\x12S\n\x11suspension_reason\x18\x05 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReasonH\x03\x88\x01\x01\x12<\n\x08warnings\x18\x06 \x03(\x0b\x32*.org.dash.platform.dapi.v0.ContractWarningB\t\n\x07_bannedB\x12\n\x10_suspended_untilB\r\n\x0b_ban_reasonB\x14\n\x12_suspension_reason\x1a\x8e\x02\n%GetContractModerationStatusResponseV0\x12i\n\x06status\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetContractModerationStatusResponse.ContractModerationStatusH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xfb\x02\n#GetContractModerationEntriesRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractModerationEntriesRequest.GetContractModerationEntriesRequestV0H\x00\x1a\xd4\x01\n%GetContractModerationEntriesRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12?\n\x04list\x18\x02 \x01(\x0e\x32\x31.org.dash.platform.dapi.v0.ContractModerationList\x12\x18\n\x0bstart_after\x18\x03 \x01(\x0cH\x00\x88\x01\x01\x12\x12\n\x05limit\x18\x04 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x0e\n\x0c_start_afterB\x08\n\x06_limitB\t\n\x07version\"\x96\x06\n$GetContractModerationEntriesResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContractModerationEntriesResponse.GetContractModerationEntriesResponseV0H\x00\x1a\xcf\x01\n\x17\x43ontractModerationEntry\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x12\n\x05until\x18\x02 \x01(\x04H\x00\x88\x01\x01\x12\x43\n\x06reason\x18\x03 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReason\x12<\n\x08warnings\x18\x04 \x03(\x0b\x32*.org.dash.platform.dapi.v0.ContractWarningB\x08\n\x06_until\x1a\x85\x01\n\x19\x43ontractModerationEntries\x12h\n\x07\x65ntries\x18\x01 \x03(\x0b\x32W.org.dash.platform.dapi.v0.GetContractModerationEntriesResponse.ContractModerationEntry\x1a\x92\x02\n&GetContractModerationEntriesResponseV0\x12l\n\x07\x65ntries\x18\x01 \x01(\x0b\x32Y.org.dash.platform.dapi.v0.GetContractModerationEntriesResponse.ContractModerationEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc3\x04\n\"GetContractDocumentRemovalsRequest\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetContractDocumentRemovalsRequest.GetContractDocumentRemovalsRequestV0H\x00\x1a#\n\x0b\x44ocumentIds\x12\x14\n\x0c\x64ocument_ids\x18\x01 \x03(\x0c\x1aN\n\x04Page\x12\x18\n\x0bstart_after\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x12\n\x05limit\x18\x02 \x01(\rH\x01\x88\x01\x01\x42\x0e\n\x0c_start_afterB\x08\n\x06_limit\x1a\xaa\x02\n$GetContractDocumentRemovalsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x61\n\x0c\x64ocument_ids\x18\x03 \x01(\x0b\x32I.org.dash.platform.dapi.v0.GetContractDocumentRemovalsRequest.DocumentIdsH\x00\x12R\n\x04page\x18\x04 \x01(\x0b\x32\x42.org.dash.platform.dapi.v0.GetContractDocumentRemovalsRequest.PageH\x00\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x0b\n\tselectionB\t\n\x07version\"\xcb\x07\n#GetContractDocumentRemovalsResponse\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.GetContractDocumentRemovalsResponseV0H\x00\x1aH\n\x1b\x43ontractDocumentRestoration\x12\x14\n\x0cmoderator_id\x18\x01 \x01(\x0c\x12\x13\n\x0brestored_at\x18\x02 \x01(\x04\x1a\xc0\x02\n\x17\x43ontractDocumentRemoval\x12\x13\n\x0b\x64ocument_id\x18\x01 \x01(\x0c\x12\x19\n\x11\x64ocument_owner_id\x18\x02 \x01(\x0c\x12\x14\n\x0cmoderator_id\x18\x03 \x01(\x0c\x12\x12\n\nremoved_at\x18\x04 \x01(\x04\x12\x43\n\x06reason\x18\x05 \x01(\x0b\x32\x33.org.dash.platform.dapi.v0.ContractModerationReason\x12\x15\n\rdocument_hash\x18\x06 \x01(\x0c\x12o\n\x0brestoration\x18\x07 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.ContractDocumentRestoration\x1a\x84\x01\n\x18\x43ontractDocumentRemovals\x12h\n\x08removals\x18\x01 \x03(\x0b\x32V.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.ContractDocumentRemoval\x1a\x90\x02\n%GetContractDocumentRemovalsResponseV0\x12k\n\x08removals\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse.ContractDocumentRemovalsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc9\x01\n\x19GetContractFeePotsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetContractFeePotsRequest.GetContractFeePotsRequestV0H\x00\x1a\x41\n\x1bGetContractFeePotsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9f\x06\n\x1aGetContractFeePotsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetContractFeePotsResponse.GetContractFeePotsResponseV0H\x00\x1aR\n\x17\x43ontractFeePotLastClaim\x12\r\n\x05\x65poch\x18\x01 \x01(\r\x12\x13\n\x07time_ms\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x13\n\x0b\x63laimant_id\x18\x03 \x01(\x0c\x1a\x88\x01\n\x0e\x43ontractFeePot\x12\x13\n\x07\x63redits\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x61\n\nlast_claim\x18\x02 \x01(\x0b\x32M.org.dash.platform.dapi.v0.GetContractFeePotsResponse.ContractFeePotLastClaim\x1a\xc0\x01\n\x0f\x43ontractFeePots\x12S\n\x05owner\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetContractFeePotsResponse.ContractFeePot\x12X\n\nmoderators\x18\x02 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetContractFeePotsResponse.ContractFeePot\x1a\xf1\x01\n\x1cGetContractFeePotsResponseV0\x12U\n\x04pots\x18\x01 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetContractFeePotsResponse.ContractFeePotsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xf1\x01\n#GetContractGroupsForContractRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetContractGroupsForContractRequest.GetContractGroupsForContractRequestV0H\x00\x1aK\n%GetContractGroupsForContractRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf5\x06\n$GetContractGroupsForContractResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse.GetContractGroupsForContractResponseV0H\x00\x1aQ\n\x17\x44ocumentTypeMemberships\x12\x1a\n\x12\x64ocument_type_name\x18\x01 \x01(\t\x12\x1a\n\x12\x63ontract_group_ids\x18\x02 \x03(\x0c\x1a\x46\n\x10TokenMemberships\x12\x16\n\x0etoken_position\x18\x01 \x01(\r\x12\x1a\n\x12\x63ontract_group_ids\x18\x02 \x03(\x0c\x1a\x89\x02\n\x18\x43ontractGroupMemberships\x12\x1a\n\x12\x63ontract_group_ids\x18\x01 \x03(\x0c\x12o\n\x0e\x64ocument_types\x18\x02 \x03(\x0b\x32W.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse.DocumentTypeMemberships\x12`\n\x06tokens\x18\x03 \x03(\x0b\x32P.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse.TokenMemberships\x1a\xa4\x02\n&GetContractGroupsForContractResponseV0\x12~\n\x1a\x63ontract_group_memberships\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse.ContractGroupMembershipsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb9\x01\n\x17GetDataContractsRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetDataContractsRequest.GetDataContractsRequestV0H\x00\x1a\x37\n\x19GetDataContractsRequestV0\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xad\x02\n\x1eGetDataContractsByRangeRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetDataContractsByRangeRequest.GetDataContractsByRangeRequestV0H\x00\x1a\x95\x01\n GetDataContractsByRangeRequestV0\x12\x12\n\x05limit\x18\x01 \x01(\rH\x01\x88\x01\x01\x12\x15\n\x0bstart_after\x18\x02 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x03 \x01(\x0cH\x00\x12\x10\n\x08ids_only\x18\x04 \x01(\x08\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x07\n\x05startB\x08\n\x06_limitB\t\n\x07version\"\xcf\x04\n\x18GetDataContractsResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetDataContractsResponse.GetDataContractsResponseV0H\x00\x1a[\n\x11\x44\x61taContractEntry\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x32\n\rdata_contract\x18\x02 \x01(\x0b\x32\x1b.google.protobuf.BytesValue\x1au\n\rDataContracts\x12\x64\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32\x45.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractEntry\x1a\xf5\x01\n\x1aGetDataContractsResponseV0\x12[\n\x0e\x64\x61ta_contracts\x18\x01 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc5\x02\n\x1dGetDataContractHistoryRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.GetDataContractHistoryRequestV0H\x00\x1a\xb0\x01\n\x1fGetDataContractHistoryRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12+\n\x05limit\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0bstart_at_ms\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\xb2\x05\n\x1eGetDataContractHistoryResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0H\x00\x1a\x9a\x04\n GetDataContractHistoryResponseV0\x12\x8f\x01\n\x15\x64\x61ta_contract_history\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0.DataContractHistoryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a;\n\x18\x44\x61taContractHistoryEntry\x12\x10\n\x04\x64\x61te\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05value\x18\x02 \x01(\x0c\x1a\xaa\x01\n\x13\x44\x61taContractHistory\x12\x92\x01\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32s.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.GetDataContractHistoryResponseV0.DataContractHistoryEntryB\x08\n\x06resultB\t\n\x07version\"\xe0\x1f\n\x13GetDocumentsRequest\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV0H\x00\x12R\n\x02v1\x18\x02 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1H\x00\x1a\xfe\x02\n\x12\x44ocumentFieldValue\x12\x14\n\nbool_value\x18\x01 \x01(\x08H\x00\x12\x19\n\x0bint64_value\x18\x02 \x01(\x12\x42\x02\x30\x01H\x00\x12\x1a\n\x0cuint64_value\x18\x03 \x01(\x04\x42\x02\x30\x01H\x00\x12\x16\n\x0c\x64ouble_value\x18\x04 \x01(\x01H\x00\x12\x0e\n\x04text\x18\x05 \x01(\tH\x00\x12\x15\n\x0b\x62ytes_value\x18\x06 \x01(\x0cH\x00\x12[\n\x04list\x18\x07 \x01(\x0b\x32K.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValue.ValueListH\x00\x12\x14\n\nnull_value\x18\x08 \x01(\x08H\x00\x1a^\n\tValueList\x12Q\n\x06values\x18\x01 \x03(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValueB\t\n\x07variant\x1a\xe2\x02\n\x12TimeRangeSelection\x12\\\n\x08selector\x18\x01 \x01(\x0e\x32J.org.dash.platform.dapi.v0.GetDocumentsRequest.TimeRangeSelection.Selector\x12\x19\n\x08start_ms\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x12T\n\x04grid\x18\x03 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetDocumentsRequest.TimeRangeSelection.Grid\x1a>\n\x04Grid\x12\x11\n\x05range\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x10\n\x04step\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x11\n\x05phase\x18\x03 \x01(\x04\x42\x02\x30\x01\"0\n\x08Selector\x12\n\n\x06NEWEST\x10\x00\x12\n\n\x06OLDEST\x10\x01\x12\x0c\n\x08\x42Y_START\x10\x02\x42\x0b\n\t_start_ms\x1a\x95\x02\n\x0bWhereClause\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12N\n\x08operator\x18\x02 \x01(\x0e\x32<.org.dash.platform.dapi.v0.GetDocumentsRequest.WhereOperator\x12P\n\x05value\x18\x03 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValue\x12U\n\ntime_range\x18\x04 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.TimeRangeSelection\x1a\xa4\x01\n\x0fHavingAggregate\x12Y\n\x08\x66unction\x18\x01 \x01(\x0e\x32G.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingAggregate.Function\x12\r\n\x05\x66ield\x18\x02 \x01(\t\"\'\n\x08\x46unction\x12\t\n\x05\x43OUNT\x10\x00\x12\x07\n\x03SUM\x10\x01\x12\x07\n\x03\x41VG\x10\x02\x1a\xf9\x03\n\x0cHavingClause\x12Q\n\taggregate\x18\x01 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingAggregate\x12V\n\x08operator\x18\x02 \x01(\x0e\x32\x44.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingClause.Operator\x12R\n\x05value\x18\x03 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDocumentsRequest.DocumentFieldValueH\x00\"\xe0\x01\n\x08Operator\x12\t\n\x05\x45QUAL\x10\x00\x12\r\n\tNOT_EQUAL\x10\x01\x12\x10\n\x0cGREATER_THAN\x10\x02\x12\x1a\n\x16GREATER_THAN_OR_EQUALS\x10\x03\x12\r\n\tLESS_THAN\x10\x04\x12\x17\n\x13LESS_THAN_OR_EQUALS\x10\x05\x12\x0b\n\x07\x42\x45TWEEN\x10\x06\x12\x1a\n\x16\x42\x45TWEEN_EXCLUDE_BOUNDS\x10\x07\x12\x18\n\x14\x42\x45TWEEN_EXCLUDE_LEFT\x10\x08\x12\x19\n\x15\x42\x45TWEEN_EXCLUDE_RIGHT\x10\t\x12\x06\n\x02IN\x10\nB\x07\n\x05right\x1a\x90\x01\n\x0bOrderClause\x12\x0f\n\x05\x66ield\x18\x01 \x01(\tH\x00\x12S\n\taggregate\x18\x03 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingAggregateH\x00\x12\x11\n\tascending\x18\x02 \x01(\x08\x42\x08\n\x06target\x1a\xbb\x01\n\x15GetDocumentsRequestV0\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12\r\n\x05where\x18\x03 \x01(\x0c\x12\x10\n\x08order_by\x18\x04 \x01(\x0c\x12\r\n\x05limit\x18\x05 \x01(\r\x12\x15\n\x0bstart_after\x18\x06 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x07 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x08 \x01(\x08\x42\x07\n\x05start\x1a\xa6\x0c\n\x15GetDocumentsRequestV1\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12Q\n\rwhere_clauses\x18\x03 \x03(\x0b\x32:.org.dash.platform.dapi.v0.GetDocumentsRequest.WhereClause\x12L\n\x08order_by\x18\x04 \x03(\x0b\x32:.org.dash.platform.dapi.v0.GetDocumentsRequest.OrderClause\x12\x12\n\x05limit\x18\x05 \x01(\rH\x01\x88\x01\x01\x12\x15\n\x0bstart_after\x18\x06 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x07 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x08 \x01(\x08\x12\\\n\x07selects\x18\t \x03(\x0b\x32K.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.Select\x12\x10\n\x08group_by\x18\n \x03(\t\x12K\n\x06having\x18\x0b \x03(\x0b\x32;.org.dash.platform.dapi.v0.GetDocumentsRequest.HavingClause\x12\x13\n\x06offset\x18\x0c \x01(\rH\x02\x88\x01\x01\x12\x61\n\x07\x63hained\x18\r \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.ChainedJoin\x12\x62\n\x0bsub_queries\x18\x0e \x03(\x0b\x32M.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.SubQuery\x1a\xc9\x01\n\x06Select\x12\x66\n\x08\x66unction\x18\x01 \x01(\x0e\x32T.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.Select.Function\x12\r\n\x05\x66ield\x18\x02 \x01(\t\"H\n\x08\x46unction\x12\r\n\tDOCUMENTS\x10\x00\x12\t\n\x05\x43OUNT\x10\x01\x12\x07\n\x03SUM\x10\x02\x12\x07\n\x03\x41VG\x10\x03\x12\x07\n\x03MIN\x10\x04\x12\x07\n\x03MAX\x10\x05\x1a\x41\n\x0b\x43hainedJoin\x12\x15\n\rjoin_property\x18\x01 \x01(\t\x12\x1b\n\x13outer_document_type\x18\x02 \x01(\t\x1a\xa6\x04\n\x08SubQuery\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12Q\n\rwhere_clauses\x18\x03 \x03(\x0b\x32:.org.dash.platform.dapi.v0.GetDocumentsRequest.WhereClause\x12L\n\x08order_by\x18\x04 \x03(\x0b\x32:.org.dash.platform.dapi.v0.GetDocumentsRequest.OrderClause\x12\x12\n\x05limit\x18\x05 \x01(\rH\x00\x88\x01\x01\x12`\n\x04kind\x18\x06 \x01(\x0e\x32R.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.SubQuery.Kind\x12\x63\n\x04\x62ind\x18\x07 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetDocumentsRequest.GetDocumentsRequestV1.SubQuery.Binding\x1a\x41\n\x07\x42inding\x12\x0e\n\x06source\x18\x01 \x01(\r\x12\x17\n\x0fsource_property\x18\x02 \x01(\t\x12\r\n\x05\x66ield\x18\x03 \x01(\t\" \n\x04Kind\x12\r\n\tDOCUMENTS\x10\x00\x12\t\n\x05\x43OUNT\x10\x01\x42\x08\n\x06_limitB\x07\n\x05startB\x08\n\x06_limitB\t\n\x07_offset\"\xfa\x01\n\rWhereOperator\x12\t\n\x05\x45QUAL\x10\x00\x12\x10\n\x0cGREATER_THAN\x10\x01\x12\x1a\n\x16GREATER_THAN_OR_EQUALS\x10\x02\x12\r\n\tLESS_THAN\x10\x03\x12\x17\n\x13LESS_THAN_OR_EQUALS\x10\x04\x12\x0b\n\x07\x42\x45TWEEN\x10\x05\x12\x1a\n\x16\x42\x45TWEEN_EXCLUDE_BOUNDS\x10\x06\x12\x18\n\x14\x42\x45TWEEN_EXCLUDE_LEFT\x10\x07\x12\x19\n\x15\x42\x45TWEEN_EXCLUDE_RIGHT\x10\x08\x12\x06\n\x02IN\x10\t\x12\x0f\n\x0bSTARTS_WITH\x10\n\x12\x11\n\rIN_TIME_RANGE\x10\x0b\x42\t\n\x07version\"\xf2\x1b\n\x14GetDocumentsResponse\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0H\x00\x12T\n\x02v1\x18\x02 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1H\x00\x1a\x9b\x02\n\x16GetDocumentsResponseV0\x12\x65\n\tdocuments\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV0.DocumentsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1e\n\tDocuments\x12\x11\n\tdocuments\x18\x01 \x03(\x0c\x42\x08\n\x06result\x1a\x84\x18\n\x16GetDocumentsResponseV1\x12\x61\n\x04\x64\x61ta\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.ResultDataH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1e\n\tDocuments\x12\x11\n\tdocuments\x18\x01 \x03(\x0c\x1aL\n\nCountEntry\x12\x13\n\x06in_key\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x0b\n\x03key\x18\x02 \x01(\x0c\x12\x11\n\x05\x63ount\x18\x03 \x01(\x04\x42\x02\x30\x01\x42\t\n\x07_in_key\x1ar\n\x0c\x43ountEntries\x12\x62\n\x07\x65ntries\x18\x01 \x03(\x0b\x32Q.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CountEntry\x1a\xa0\x01\n\x0c\x43ountResults\x12\x1d\n\x0f\x61ggregate_count\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x66\n\x07\x65ntries\x18\x02 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CountEntriesH\x00\x42\t\n\x07variant\x1aH\n\x08SumEntry\x12\x13\n\x06in_key\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x0b\n\x03key\x18\x02 \x01(\x0c\x12\x0f\n\x03sum\x18\x03 \x01(\x12\x42\x02\x30\x01\x42\t\n\x07_in_key\x1an\n\nSumEntries\x12`\n\x07\x65ntries\x18\x01 \x03(\x0b\x32O.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.SumEntry\x1a\x9a\x01\n\nSumResults\x12\x1b\n\raggregate_sum\x18\x01 \x01(\x12\x42\x02\x30\x01H\x00\x12\x64\n\x07\x65ntries\x18\x02 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.SumEntriesH\x00\x42\t\n\x07variant\x1a_\n\x0c\x41verageEntry\x12\x13\n\x06in_key\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x0b\n\x03key\x18\x02 \x01(\x0c\x12\x11\n\x05\x63ount\x18\x03 \x01(\x04\x42\x02\x30\x01\x12\x0f\n\x03sum\x18\x04 \x01(\x12\x42\x02\x30\x01\x42\t\n\x07_in_key\x1av\n\x0e\x41verageEntries\x12\x64\n\x07\x65ntries\x18\x01 \x03(\x0b\x32S.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.AverageEntry\x1a\x36\n\x10\x41verageAggregate\x12\x11\n\x05\x63ount\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x0f\n\x03sum\x18\x02 \x01(\x12\x42\x02\x30\x01\x1a\xfb\x01\n\x0e\x41verageResults\x12t\n\x11\x61ggregate_average\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.AverageAggregateH\x00\x12h\n\x07\x65ntries\x18\x02 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.AverageEntriesH\x00\x42\t\n\x07variant\x1az\n\x0bRankedEntry\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12\x13\n\x05\x63ount\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12\x11\n\x03sum\x18\x03 \x01(\x12\x42\x02\x30\x01H\x00\x12\r\n\x03\x61vg\x18\x04 \x01(\x01H\x00\x12\x13\n\x06in_key\x18\x05 \x01(\x0cH\x01\x88\x01\x01\x42\x07\n\x05valueB\t\n\x07_in_key\x1a\x9a\x01\n\rRankedEntries\x12\x63\n\x07\x65ntries\x18\x01 \x03(\x0b\x32R.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntry\x12\x18\n\x07skipped\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x42\n\n\x08_skipped\x1a\xf7\x05\n\nResultData\x12\x65\n\tdocuments\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.DocumentsH\x00\x12\x65\n\x06\x63ounts\x18\x02 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CountResultsH\x00\x12\x61\n\x04sums\x18\x03 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.SumResultsH\x00\x12i\n\x08\x61verages\x18\x04 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.AverageResultsH\x00\x12\x66\n\x06ranked\x18\x05 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.RankedEntriesH\x00\x12j\n\x07\x63hained\x18\x06 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.ChainedDocumentsH\x00\x12n\n\tcomposite\x18\x07 \x01(\x0b\x32Y.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CompositeDocumentsH\x00\x42\t\n\x07variant\x1a_\n\x10\x43hainedDocuments\x12\x17\n\x0finner_documents\x18\x01 \x03(\x0c\x12\x17\n\x0fouter_documents\x18\x02 \x03(\x0c\x12\x19\n\x11missing_outer_ids\x18\x03 \x03(\x0c\x1a\xab\x03\n\x12\x43ompositeDocuments\x12\x16\n\x0epage_documents\x18\x01 \x03(\x0c\x12}\n\x0bsub_results\x18\x02 \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CompositeDocuments.SubQueryResult\x1a\xfd\x01\n\x0eSubQueryResult\x12\x65\n\tdocuments\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.DocumentsH\x00\x12\x65\n\x06\x63ounts\x18\x02 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetDocumentsResponse.GetDocumentsResponseV1.CountEntriesH\x00\x12\x13\n\x0bmissing_ids\x18\x03 \x03(\x0c\x42\x08\n\x06resultB\x08\n\x06resultB\t\n\x07version\"\xf4\x02\n\x19GetDocumentHistoryRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetDocumentHistoryRequest.GetDocumentHistoryRequestV0H\x00\x1a\xeb\x01\n\x1bGetDocumentHistoryRequestV0\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x13\n\x0b\x64ocument_id\x18\x03 \x01(\x0c\x12+\n\x05limit\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x05 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0bstart_at_ms\x18\x06 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x07 \x01(\x08\x42\t\n\x07version\"\xf7\x04\n\x1aGetDocumentHistoryResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0H\x00\x1a\xeb\x03\n\x1cGetDocumentHistoryResponseV0\x12~\n\x10\x64ocument_history\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x37\n\x14\x44ocumentHistoryEntry\x12\x10\n\x04\x64\x61te\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05value\x18\x02 \x01(\x0c\x1a\x95\x01\n\x0f\x44ocumentHistory\x12\x81\x01\n\x10\x64ocument_entries\x18\x01 \x03(\x0b\x32g.org.dash.platform.dapi.v0.GetDocumentHistoryResponse.GetDocumentHistoryResponseV0.DocumentHistoryEntryB\x08\n\x06resultB\t\n\x07version\"\xed\x01\n!GetIdentityByPublicKeyHashRequest\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest.GetIdentityByPublicKeyHashRequestV0H\x00\x1aM\n#GetIdentityByPublicKeyHashRequestV0\x12\x17\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xda\x02\n\"GetIdentityByPublicKeyHashResponse\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse.GetIdentityByPublicKeyHashResponseV0H\x00\x1a\xb6\x01\n$GetIdentityByPublicKeyHashResponseV0\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbd\x02\n*GetIdentityByNonUniquePublicKeyHashRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashRequest.GetIdentityByNonUniquePublicKeyHashRequestV0H\x00\x1a\x80\x01\n,GetIdentityByNonUniquePublicKeyHashRequestV0\x12\x17\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x12\x18\n\x0bstart_after\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\x0e\n\x0c_start_afterB\t\n\x07version\"\xd6\x06\n+GetIdentityByNonUniquePublicKeyHashResponse\x12\x82\x01\n\x02v0\x18\x01 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0H\x00\x1a\x96\x05\n-GetIdentityByNonUniquePublicKeyHashResponseV0\x12\x9a\x01\n\x08identity\x18\x01 \x01(\x0b\x32\x85\x01.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0.IdentityResponseH\x00\x12\x9d\x01\n\x05proof\x18\x02 \x01(\x0b\x32\x8b\x01.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse.GetIdentityByNonUniquePublicKeyHashResponseV0.IdentityProvedResponseH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x36\n\x10IdentityResponse\x12\x15\n\x08identity\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x42\x0b\n\t_identity\x1a\xa6\x01\n\x16IdentityProvedResponse\x12P\n&grovedb_identity_public_key_hash_proof\x18\x01 \x01(\x0b\x32 .org.dash.platform.dapi.v0.Proof\x12!\n\x14identity_proof_bytes\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x17\n\x15_identity_proof_bytesB\x08\n\x06resultB\t\n\x07version\"\x99\x02\n#WaitForStateTransitionResultRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest.WaitForStateTransitionResultRequestV0H\x00\x1as\n%WaitForStateTransitionResultRequestV0\x12\x1d\n\x15state_transition_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x12\x1c\n\x14request_user_balance\x18\x03 \x01(\x08\x42\t\n\x07version\"\xce\x04\n$WaitForStateTransitionResultResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse.WaitForStateTransitionResultResponseV0H\x00\x1a\x34\n\x17SuccessWithOwnerBalance\x12\x19\n\rowner_balance\x18\x01 \x01(\x04\x42\x02\x30\x01\x1a\xee\x02\n&WaitForStateTransitionResultResponseV0\x12I\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x38.org.dash.platform.dapi.v0.StateTransitionBroadcastErrorH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12}\n\x1asuccess_with_owner_balance\x18\x04 \x01(\x0b\x32W.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse.SuccessWithOwnerBalanceH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc4\x01\n\x19GetConsensusParamsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetConsensusParamsRequest.GetConsensusParamsRequestV0H\x00\x1a<\n\x1bGetConsensusParamsRequestV0\x12\x0e\n\x06height\x18\x01 \x01(\x05\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x9c\x04\n\x1aGetConsensusParamsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetConsensusParamsResponse.GetConsensusParamsResponseV0H\x00\x1aP\n\x14\x43onsensusParamsBlock\x12\x11\n\tmax_bytes\x18\x01 \x01(\t\x12\x0f\n\x07max_gas\x18\x02 \x01(\t\x12\x14\n\x0ctime_iota_ms\x18\x03 \x01(\t\x1a\x62\n\x17\x43onsensusParamsEvidence\x12\x1a\n\x12max_age_num_blocks\x18\x01 \x01(\t\x12\x18\n\x10max_age_duration\x18\x02 \x01(\t\x12\x11\n\tmax_bytes\x18\x03 \x01(\t\x1a\xda\x01\n\x1cGetConsensusParamsResponseV0\x12Y\n\x05\x62lock\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetConsensusParamsResponse.ConsensusParamsBlock\x12_\n\x08\x65vidence\x18\x02 \x01(\x0b\x32M.org.dash.platform.dapi.v0.GetConsensusParamsResponse.ConsensusParamsEvidenceB\t\n\x07version\"\xe4\x01\n%GetProtocolVersionUpgradeStateRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateRequest.GetProtocolVersionUpgradeStateRequestV0H\x00\x1a\x38\n\'GetProtocolVersionUpgradeStateRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xb5\x05\n&GetProtocolVersionUpgradeStateResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0H\x00\x1a\x85\x04\n(GetProtocolVersionUpgradeStateResponseV0\x12\x87\x01\n\x08versions\x18\x01 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0.VersionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x96\x01\n\x08Versions\x12\x89\x01\n\x08versions\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse.GetProtocolVersionUpgradeStateResponseV0.VersionEntry\x1a:\n\x0cVersionEntry\x12\x16\n\x0eversion_number\x18\x01 \x01(\r\x12\x12\n\nvote_count\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xa3\x02\n*GetProtocolVersionUpgradeVoteStatusRequest\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusRequest.GetProtocolVersionUpgradeVoteStatusRequestV0H\x00\x1ag\n,GetProtocolVersionUpgradeVoteStatusRequestV0\x12\x19\n\x11start_pro_tx_hash\x18\x01 \x01(\x0c\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xef\x05\n+GetProtocolVersionUpgradeVoteStatusResponse\x12\x82\x01\n\x02v0\x18\x01 \x01(\x0b\x32t.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0H\x00\x1a\xaf\x04\n-GetProtocolVersionUpgradeVoteStatusResponseV0\x12\x98\x01\n\x08versions\x18\x01 \x01(\x0b\x32\x83\x01.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0.VersionSignalsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xaf\x01\n\x0eVersionSignals\x12\x9c\x01\n\x0fversion_signals\x18\x01 \x03(\x0b\x32\x82\x01.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse.GetProtocolVersionUpgradeVoteStatusResponseV0.VersionSignal\x1a\x35\n\rVersionSignal\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07version\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xf5\x01\n\x14GetEpochsInfoRequest\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetEpochsInfoRequest.GetEpochsInfoRequestV0H\x00\x1a|\n\x16GetEpochsInfoRequestV0\x12\x31\n\x0bstart_epoch\x18\x01 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\x11\n\tascending\x18\x03 \x01(\x08\x12\r\n\x05prove\x18\x04 \x01(\x08\x42\t\n\x07version\"\x99\x05\n\x15GetEpochsInfoResponse\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0H\x00\x1a\x9c\x04\n\x17GetEpochsInfoResponseV0\x12\x65\n\x06\x65pochs\x18\x01 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0.EpochInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1au\n\nEpochInfos\x12g\n\x0b\x65poch_infos\x18\x01 \x03(\x0b\x32R.org.dash.platform.dapi.v0.GetEpochsInfoResponse.GetEpochsInfoResponseV0.EpochInfo\x1a\xa6\x01\n\tEpochInfo\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x1e\n\x12\x66irst_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x1f\n\x17\x66irst_core_block_height\x18\x03 \x01(\r\x12\x16\n\nstart_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x0e\x66\x65\x65_multiplier\x18\x05 \x01(\x01\x12\x18\n\x10protocol_version\x18\x06 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xbf\x02\n\x1dGetFinalizedEpochInfosRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetFinalizedEpochInfosRequest.GetFinalizedEpochInfosRequestV0H\x00\x1a\xaa\x01\n\x1fGetFinalizedEpochInfosRequestV0\x12\x19\n\x11start_epoch_index\x18\x01 \x01(\r\x12\"\n\x1astart_epoch_index_included\x18\x02 \x01(\x08\x12\x17\n\x0f\x65nd_epoch_index\x18\x03 \x01(\r\x12 \n\x18\x65nd_epoch_index_included\x18\x04 \x01(\x08\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\t\n\x07version\"\xbd\t\n\x1eGetFinalizedEpochInfosResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0H\x00\x1a\xa5\x08\n GetFinalizedEpochInfosResponseV0\x12\x80\x01\n\x06\x65pochs\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.FinalizedEpochInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xa4\x01\n\x13\x46inalizedEpochInfos\x12\x8c\x01\n\x15\x66inalized_epoch_infos\x18\x01 \x03(\x0b\x32m.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.FinalizedEpochInfo\x1a\x9f\x04\n\x12\x46inalizedEpochInfo\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x1e\n\x12\x66irst_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x1f\n\x17\x66irst_core_block_height\x18\x03 \x01(\r\x12\x1c\n\x10\x66irst_block_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x0e\x66\x65\x65_multiplier\x18\x05 \x01(\x01\x12\x18\n\x10protocol_version\x18\x06 \x01(\r\x12!\n\x15total_blocks_in_epoch\x18\x07 \x01(\x04\x42\x02\x30\x01\x12*\n\"next_epoch_start_core_block_height\x18\x08 \x01(\r\x12!\n\x15total_processing_fees\x18\t \x01(\x04\x42\x02\x30\x01\x12*\n\x1etotal_distributed_storage_fees\x18\n \x01(\x04\x42\x02\x30\x01\x12&\n\x1atotal_created_storage_fees\x18\x0b \x01(\x04\x42\x02\x30\x01\x12\x1e\n\x12\x63ore_block_rewards\x18\x0c \x01(\x04\x42\x02\x30\x01\x12\x81\x01\n\x0f\x62lock_proposers\x18\r \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse.GetFinalizedEpochInfosResponseV0.BlockProposer\x1a\x39\n\rBlockProposer\x12\x13\n\x0bproposer_id\x18\x01 \x01(\x0c\x12\x13\n\x0b\x62lock_count\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xde\x04\n\x1cGetContestedResourcesRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetContestedResourcesRequest.GetContestedResourcesRequestV0H\x00\x1a\xcc\x03\n\x1eGetContestedResourcesRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x1a\n\x12start_index_values\x18\x04 \x03(\x0c\x12\x18\n\x10\x65nd_index_values\x18\x05 \x03(\x0c\x12\x89\x01\n\x13start_at_value_info\x18\x06 \x01(\x0b\x32g.org.dash.platform.dapi.v0.GetContestedResourcesRequest.GetContestedResourcesRequestV0.StartAtValueInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x17\n\x0forder_ascending\x18\x08 \x01(\x08\x12\r\n\x05prove\x18\t \x01(\x08\x1a\x45\n\x10StartAtValueInfo\x12\x13\n\x0bstart_value\x18\x01 \x01(\x0c\x12\x1c\n\x14start_value_included\x18\x02 \x01(\x08\x42\x16\n\x14_start_at_value_infoB\x08\n\x06_countB\t\n\x07version\"\x88\x04\n\x1dGetContestedResourcesResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0H\x00\x1a\xf3\x02\n\x1fGetContestedResourcesResponseV0\x12\x95\x01\n\x19\x63ontested_resource_values\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContestedResourcesResponse.GetContestedResourcesResponseV0.ContestedResourceValuesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a<\n\x17\x43ontestedResourceValues\x12!\n\x19\x63ontested_resource_values\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xd2\x05\n\x1cGetVotePollsByEndDateRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0H\x00\x1a\xc0\x04\n\x1eGetVotePollsByEndDateRequestV0\x12\x84\x01\n\x0fstart_time_info\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0.StartAtTimeInfoH\x00\x88\x01\x01\x12\x80\x01\n\rend_time_info\x18\x02 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest.GetVotePollsByEndDateRequestV0.EndAtTimeInfoH\x01\x88\x01\x01\x12\x12\n\x05limit\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x13\n\x06offset\x18\x04 \x01(\rH\x03\x88\x01\x01\x12\x11\n\tascending\x18\x05 \x01(\x08\x12\r\n\x05prove\x18\x06 \x01(\x08\x1aI\n\x0fStartAtTimeInfo\x12\x19\n\rstart_time_ms\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x13start_time_included\x18\x02 \x01(\x08\x1a\x43\n\rEndAtTimeInfo\x12\x17\n\x0b\x65nd_time_ms\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x19\n\x11\x65nd_time_included\x18\x02 \x01(\x08\x42\x12\n\x10_start_time_infoB\x10\n\x0e_end_time_infoB\x08\n\x06_limitB\t\n\x07_offsetB\t\n\x07version\"\x83\x06\n\x1dGetVotePollsByEndDateResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0H\x00\x1a\xee\x04\n\x1fGetVotePollsByEndDateResponseV0\x12\x9c\x01\n\x18vote_polls_by_timestamps\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0.SerializedVotePollsByTimestampsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aV\n\x1eSerializedVotePollsByTimestamp\x12\x15\n\ttimestamp\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1d\n\x15serialized_vote_polls\x18\x02 \x03(\x0c\x1a\xd7\x01\n\x1fSerializedVotePollsByTimestamps\x12\x99\x01\n\x18vote_polls_by_timestamps\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse.GetVotePollsByEndDateResponseV0.SerializedVotePollsByTimestamp\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x42\x08\n\x06resultB\t\n\x07version\"\xff\x06\n$GetContestedResourceVoteStateRequest\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0H\x00\x1a\xd5\x05\n&GetContestedResourceVoteStateRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x86\x01\n\x0bresult_type\x18\x05 \x01(\x0e\x32q.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.ResultType\x12\x36\n.allow_include_locked_and_abstaining_vote_tally\x18\x06 \x01(\x08\x12\xa3\x01\n\x18start_at_identifier_info\x18\x07 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest.GetContestedResourceVoteStateRequestV0.StartAtIdentifierInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x08 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\t \x01(\x08\x1aT\n\x15StartAtIdentifierInfo\x12\x18\n\x10start_identifier\x18\x01 \x01(\x0c\x12!\n\x19start_identifier_included\x18\x02 \x01(\x08\"I\n\nResultType\x12\r\n\tDOCUMENTS\x10\x00\x12\x0e\n\nVOTE_TALLY\x10\x01\x12\x1c\n\x18\x44OCUMENTS_AND_VOTE_TALLY\x10\x02\x42\x1b\n\x19_start_at_identifier_infoB\x08\n\x06_countB\t\n\x07version\"\x94\x0c\n%GetContestedResourceVoteStateResponse\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0H\x00\x1a\xe7\n\n\'GetContestedResourceVoteStateResponseV0\x12\xae\x01\n\x1d\x63ontested_resource_contenders\x18\x01 \x01(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.ContestedResourceContendersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xda\x03\n\x10\x46inishedVoteInfo\x12\xad\x01\n\x15\x66inished_vote_outcome\x18\x01 \x01(\x0e\x32\x8d\x01.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.FinishedVoteInfo.FinishedVoteOutcome\x12\x1f\n\x12won_by_identity_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12$\n\x18\x66inished_at_block_height\x18\x03 \x01(\x04\x42\x02\x30\x01\x12%\n\x1d\x66inished_at_core_block_height\x18\x04 \x01(\r\x12%\n\x19\x66inished_at_block_time_ms\x18\x05 \x01(\x04\x42\x02\x30\x01\x12\x19\n\x11\x66inished_at_epoch\x18\x06 \x01(\r\"O\n\x13\x46inishedVoteOutcome\x12\x14\n\x10TOWARDS_IDENTITY\x10\x00\x12\n\n\x06LOCKED\x10\x01\x12\x16\n\x12NO_PREVIOUS_WINNER\x10\x02\x42\x15\n\x13_won_by_identity_id\x1a\xc4\x03\n\x1b\x43ontestedResourceContenders\x12\x86\x01\n\ncontenders\x18\x01 \x03(\x0b\x32r.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.Contender\x12\x1f\n\x12\x61\x62stain_vote_tally\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x1c\n\x0flock_vote_tally\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\x9a\x01\n\x12\x66inished_vote_info\x18\x04 \x01(\x0b\x32y.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse.GetContestedResourceVoteStateResponseV0.FinishedVoteInfoH\x02\x88\x01\x01\x42\x15\n\x13_abstain_vote_tallyB\x12\n\x10_lock_vote_tallyB\x15\n\x13_finished_vote_info\x1ak\n\tContender\x12\x12\n\nidentifier\x18\x01 \x01(\x0c\x12\x17\n\nvote_count\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x15\n\x08\x64ocument\x18\x03 \x01(\x0cH\x01\x88\x01\x01\x42\r\n\x0b_vote_countB\x0b\n\t_documentB\x08\n\x06resultB\t\n\x07version\"\xd5\x05\n,GetContestedResourceVotersForIdentityRequest\x12\x84\x01\n\x02v0\x18\x01 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest.GetContestedResourceVotersForIdentityRequestV0H\x00\x1a\x92\x04\n.GetContestedResourceVotersForIdentityRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\x12\n\nindex_name\x18\x03 \x01(\t\x12\x14\n\x0cindex_values\x18\x04 \x03(\x0c\x12\x15\n\rcontestant_id\x18\x05 \x01(\x0c\x12\xb4\x01\n\x18start_at_identifier_info\x18\x06 \x01(\x0b\x32\x8c\x01.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest.GetContestedResourceVotersForIdentityRequestV0.StartAtIdentifierInfoH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x07 \x01(\rH\x01\x88\x01\x01\x12\x17\n\x0forder_ascending\x18\x08 \x01(\x08\x12\r\n\x05prove\x18\t \x01(\x08\x1aT\n\x15StartAtIdentifierInfo\x12\x18\n\x10start_identifier\x18\x01 \x01(\x0c\x12!\n\x19start_identifier_included\x18\x02 \x01(\x08\x42\x1b\n\x19_start_at_identifier_infoB\x08\n\x06_countB\t\n\x07version\"\xf1\x04\n-GetContestedResourceVotersForIdentityResponse\x12\x86\x01\n\x02v0\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse.GetContestedResourceVotersForIdentityResponseV0H\x00\x1a\xab\x03\n/GetContestedResourceVotersForIdentityResponseV0\x12\xb6\x01\n\x19\x63ontested_resource_voters\x18\x01 \x01(\x0b\x32\x90\x01.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse.GetContestedResourceVotersForIdentityResponseV0.ContestedResourceVotersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x43\n\x17\x43ontestedResourceVoters\x12\x0e\n\x06voters\x18\x01 \x03(\x0c\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x42\x08\n\x06resultB\t\n\x07version\"\xad\x05\n(GetContestedResourceIdentityVotesRequest\x12|\n\x02v0\x18\x01 \x01(\x0b\x32n.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest.GetContestedResourceIdentityVotesRequestV0H\x00\x1a\xf7\x03\n*GetContestedResourceIdentityVotesRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12+\n\x05limit\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x17\n\x0forder_ascending\x18\x04 \x01(\x08\x12\xae\x01\n\x1astart_at_vote_poll_id_info\x18\x05 \x01(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest.GetContestedResourceIdentityVotesRequestV0.StartAtVotePollIdInfoH\x00\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x1a\x61\n\x15StartAtVotePollIdInfo\x12 \n\x18start_at_poll_identifier\x18\x01 \x01(\x0c\x12&\n\x1estart_poll_identifier_included\x18\x02 \x01(\x08\x42\x1d\n\x1b_start_at_vote_poll_id_infoB\t\n\x07version\"\xc8\n\n)GetContestedResourceIdentityVotesResponse\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0H\x00\x1a\x8f\t\n+GetContestedResourceIdentityVotesResponseV0\x12\xa1\x01\n\x05votes\x18\x01 \x01(\x0b\x32\x8f\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ContestedResourceIdentityVotesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\xf7\x01\n\x1e\x43ontestedResourceIdentityVotes\x12\xba\x01\n!contested_resource_identity_votes\x18\x01 \x03(\x0b\x32\x8e\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ContestedResourceIdentityVote\x12\x18\n\x10\x66inished_results\x18\x02 \x01(\x08\x1a\xad\x02\n\x12ResourceVoteChoice\x12\xad\x01\n\x10vote_choice_type\x18\x01 \x01(\x0e\x32\x92\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ResourceVoteChoice.VoteChoiceType\x12\x18\n\x0bidentity_id\x18\x02 \x01(\x0cH\x00\x88\x01\x01\"=\n\x0eVoteChoiceType\x12\x14\n\x10TOWARDS_IDENTITY\x10\x00\x12\x0b\n\x07\x41\x42STAIN\x10\x01\x12\x08\n\x04LOCK\x10\x02\x42\x0e\n\x0c_identity_id\x1a\x95\x02\n\x1d\x43ontestedResourceIdentityVote\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1a\n\x12\x64ocument_type_name\x18\x02 \x01(\t\x12\'\n\x1fserialized_index_storage_values\x18\x03 \x03(\x0c\x12\x99\x01\n\x0bvote_choice\x18\x04 \x01(\x0b\x32\x83\x01.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse.GetContestedResourceIdentityVotesResponseV0.ResourceVoteChoiceB\x08\n\x06resultB\t\n\x07version\"\xf0\x01\n%GetPrefundedSpecializedBalanceRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceRequest.GetPrefundedSpecializedBalanceRequestV0H\x00\x1a\x44\n\'GetPrefundedSpecializedBalanceRequestV0\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xed\x02\n&GetPrefundedSpecializedBalanceResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse.GetPrefundedSpecializedBalanceResponseV0H\x00\x1a\xbd\x01\n(GetPrefundedSpecializedBalanceResponseV0\x12\x15\n\x07\x62\x61lance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xd0\x01\n GetTotalCreditsInPlatformRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformRequest.GetTotalCreditsInPlatformRequestV0H\x00\x1a\x33\n\"GetTotalCreditsInPlatformRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xd9\x02\n!GetTotalCreditsInPlatformResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformResponse.GetTotalCreditsInPlatformResponseV0H\x00\x1a\xb8\x01\n#GetTotalCreditsInPlatformResponseV0\x12\x15\n\x07\x63redits\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc4\x01\n\x16GetPathElementsRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetPathElementsRequest.GetPathElementsRequestV0H\x00\x1a\x45\n\x18GetPathElementsRequestV0\x12\x0c\n\x04path\x18\x01 \x03(\x0c\x12\x0c\n\x04keys\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xa3\x03\n\x17GetPathElementsResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetPathElementsResponse.GetPathElementsResponseV0H\x00\x1a\xa0\x02\n\x19GetPathElementsResponseV0\x12i\n\x08\x65lements\x18\x01 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetPathElementsResponse.GetPathElementsResponseV0.ElementsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1c\n\x08\x45lements\x12\x10\n\x08\x65lements\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\x81\x01\n\x10GetStatusRequest\x12L\n\x02v0\x18\x01 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetStatusRequest.GetStatusRequestV0H\x00\x1a\x14\n\x12GetStatusRequestV0B\t\n\x07version\"\xe4\x10\n\x11GetStatusResponse\x12N\n\x02v0\x18\x01 \x01(\x0b\x32@.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0H\x00\x1a\xf3\x0f\n\x13GetStatusResponseV0\x12Y\n\x07version\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version\x12S\n\x04node\x18\x02 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Node\x12U\n\x05\x63hain\x18\x03 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Chain\x12Y\n\x07network\x18\x04 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Network\x12^\n\nstate_sync\x18\x05 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.StateSync\x12S\n\x04time\x18\x06 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Time\x1a\x82\x05\n\x07Version\x12\x63\n\x08software\x18\x01 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Software\x12\x63\n\x08protocol\x18\x02 \x01(\x0b\x32Q.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol\x1a^\n\x08Software\x12\x0c\n\x04\x64\x61pi\x18\x01 \x01(\t\x12\x12\n\x05\x64rive\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\ntenderdash\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_driveB\r\n\x0b_tenderdash\x1a\xcc\x02\n\x08Protocol\x12p\n\ntenderdash\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol.Tenderdash\x12\x66\n\x05\x64rive\x18\x02 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetStatusResponse.GetStatusResponseV0.Version.Protocol.Drive\x1a(\n\nTenderdash\x12\x0b\n\x03p2p\x18\x01 \x01(\r\x12\r\n\x05\x62lock\x18\x02 \x01(\r\x1a<\n\x05\x44rive\x12\x0e\n\x06latest\x18\x03 \x01(\r\x12\x0f\n\x07\x63urrent\x18\x04 \x01(\r\x12\x12\n\nnext_epoch\x18\x05 \x01(\r\x1a\x7f\n\x04Time\x12\x11\n\x05local\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x16\n\x05\x62lock\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x88\x01\x01\x12\x18\n\x07genesis\x18\x03 \x01(\x04\x42\x02\x30\x01H\x01\x88\x01\x01\x12\x12\n\x05\x65poch\x18\x04 \x01(\rH\x02\x88\x01\x01\x42\x08\n\x06_blockB\n\n\x08_genesisB\x08\n\x06_epoch\x1a<\n\x04Node\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\x18\n\x0bpro_tx_hash\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x42\x0e\n\x0c_pro_tx_hash\x1a\xb3\x02\n\x05\x43hain\x12\x13\n\x0b\x63\x61tching_up\x18\x01 \x01(\x08\x12\x19\n\x11latest_block_hash\x18\x02 \x01(\x0c\x12\x17\n\x0flatest_app_hash\x18\x03 \x01(\x0c\x12\x1f\n\x13latest_block_height\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x13\x65\x61rliest_block_hash\x18\x05 \x01(\x0c\x12\x19\n\x11\x65\x61rliest_app_hash\x18\x06 \x01(\x0c\x12!\n\x15\x65\x61rliest_block_height\x18\x07 \x01(\x04\x42\x02\x30\x01\x12!\n\x15max_peer_block_height\x18\t \x01(\x04\x42\x02\x30\x01\x12%\n\x18\x63ore_chain_locked_height\x18\n \x01(\rH\x00\x88\x01\x01\x42\x1b\n\x19_core_chain_locked_height\x1a\x43\n\x07Network\x12\x10\n\x08\x63hain_id\x18\x01 \x01(\t\x12\x13\n\x0bpeers_count\x18\x02 \x01(\r\x12\x11\n\tlistening\x18\x03 \x01(\x08\x1a\x85\x02\n\tStateSync\x12\x1d\n\x11total_synced_time\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1a\n\x0eremaining_time\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x17\n\x0ftotal_snapshots\x18\x03 \x01(\r\x12\"\n\x16\x63hunk_process_avg_time\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x1b\n\x0fsnapshot_height\x18\x05 \x01(\x04\x42\x02\x30\x01\x12!\n\x15snapshot_chunks_count\x18\x06 \x01(\x04\x42\x02\x30\x01\x12\x1d\n\x11\x62\x61\x63kfilled_blocks\x18\x07 \x01(\x04\x42\x02\x30\x01\x12!\n\x15\x62\x61\x63kfill_blocks_total\x18\x08 \x01(\x04\x42\x02\x30\x01\x42\t\n\x07version\"\xb1\x01\n\x1cGetCurrentQuorumsInfoRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest.GetCurrentQuorumsInfoRequestV0H\x00\x1a \n\x1eGetCurrentQuorumsInfoRequestV0B\t\n\x07version\"\xa1\x05\n\x1dGetCurrentQuorumsInfoResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.GetCurrentQuorumsInfoResponseV0H\x00\x1a\x46\n\x0bValidatorV0\x12\x13\n\x0bpro_tx_hash\x18\x01 \x01(\x0c\x12\x0f\n\x07node_ip\x18\x02 \x01(\t\x12\x11\n\tis_banned\x18\x03 \x01(\x08\x1a\xaf\x01\n\x0eValidatorSetV0\x12\x13\n\x0bquorum_hash\x18\x01 \x01(\x0c\x12\x13\n\x0b\x63ore_height\x18\x02 \x01(\r\x12U\n\x07members\x18\x03 \x03(\x0b\x32\x44.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorV0\x12\x1c\n\x14threshold_public_key\x18\x04 \x01(\x0c\x1a\x92\x02\n\x1fGetCurrentQuorumsInfoResponseV0\x12\x15\n\rquorum_hashes\x18\x01 \x03(\x0c\x12\x1b\n\x13\x63urrent_quorum_hash\x18\x02 \x01(\x0c\x12_\n\x0evalidator_sets\x18\x03 \x03(\x0b\x32G.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse.ValidatorSetV0\x12\x1b\n\x13last_block_proposer\x18\x04 \x01(\x0c\x12=\n\x08metadata\x18\x05 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\t\n\x07version\"\xf4\x01\n\x1fGetIdentityTokenBalancesRequest\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentityTokenBalancesRequest.GetIdentityTokenBalancesRequestV0H\x00\x1aZ\n!GetIdentityTokenBalancesRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x11\n\ttoken_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xad\x05\n GetIdentityTokenBalancesResponse\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0H\x00\x1a\x8f\x04\n\"GetIdentityTokenBalancesResponseV0\x12\x86\x01\n\x0etoken_balances\x18\x01 \x01(\x0b\x32l.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0.TokenBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aG\n\x11TokenBalanceEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x07\x62\x61lance\x18\x02 \x01(\x04H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\x9a\x01\n\rTokenBalances\x12\x88\x01\n\x0etoken_balances\x18\x01 \x03(\x0b\x32p.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse.GetIdentityTokenBalancesResponseV0.TokenBalanceEntryB\x08\n\x06resultB\t\n\x07version\"\xfc\x01\n!GetIdentitiesTokenBalancesRequest\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesRequest.GetIdentitiesTokenBalancesRequestV0H\x00\x1a\\\n#GetIdentitiesTokenBalancesRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x0cidentity_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xf2\x05\n\"GetIdentitiesTokenBalancesResponse\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0H\x00\x1a\xce\x04\n$GetIdentitiesTokenBalancesResponseV0\x12\x9b\x01\n\x17identity_token_balances\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0.IdentityTokenBalancesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aR\n\x19IdentityTokenBalanceEntry\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x14\n\x07\x62\x61lance\x18\x02 \x01(\x04H\x00\x88\x01\x01\x42\n\n\x08_balance\x1a\xb7\x01\n\x15IdentityTokenBalances\x12\x9d\x01\n\x17identity_token_balances\x18\x01 \x03(\x0b\x32|.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse.GetIdentitiesTokenBalancesResponseV0.IdentityTokenBalanceEntryB\x08\n\x06resultB\t\n\x07version\"\xe8\x01\n\x1cGetIdentityTokenInfosRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetIdentityTokenInfosRequest.GetIdentityTokenInfosRequestV0H\x00\x1aW\n\x1eGetIdentityTokenInfosRequestV0\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x11\n\ttoken_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\x98\x06\n\x1dGetIdentityTokenInfosResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0H\x00\x1a\x83\x05\n\x1fGetIdentityTokenInfosResponseV0\x12z\n\x0btoken_infos\x18\x01 \x01(\x0b\x32\x63.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a(\n\x16TokenIdentityInfoEntry\x12\x0e\n\x06\x66rozen\x18\x01 \x01(\x08\x1a\xb0\x01\n\x0eTokenInfoEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x82\x01\n\x04info\x18\x02 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenIdentityInfoEntryH\x00\x88\x01\x01\x42\x07\n\x05_info\x1a\x8a\x01\n\nTokenInfos\x12|\n\x0btoken_infos\x18\x01 \x03(\x0b\x32g.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse.GetIdentityTokenInfosResponseV0.TokenInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xf0\x01\n\x1eGetIdentitiesTokenInfosRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosRequest.GetIdentitiesTokenInfosRequestV0H\x00\x1aY\n GetIdentitiesTokenInfosRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x14\n\x0cidentity_ids\x18\x02 \x03(\x0c\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xca\x06\n\x1fGetIdentitiesTokenInfosResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0H\x00\x1a\xaf\x05\n!GetIdentitiesTokenInfosResponseV0\x12\x8f\x01\n\x14identity_token_infos\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.IdentityTokenInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a(\n\x16TokenIdentityInfoEntry\x12\x0e\n\x06\x66rozen\x18\x01 \x01(\x08\x1a\xb7\x01\n\x0eTokenInfoEntry\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12\x86\x01\n\x04info\x18\x02 \x01(\x0b\x32s.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.TokenIdentityInfoEntryH\x00\x88\x01\x01\x42\x07\n\x05_info\x1a\x97\x01\n\x12IdentityTokenInfos\x12\x80\x01\n\x0btoken_infos\x18\x01 \x03(\x0b\x32k.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse.GetIdentitiesTokenInfosResponseV0.TokenInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xbf\x01\n\x17GetTokenStatusesRequest\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetTokenStatusesRequest.GetTokenStatusesRequestV0H\x00\x1a=\n\x19GetTokenStatusesRequestV0\x12\x11\n\ttoken_ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xe7\x04\n\x18GetTokenStatusesResponse\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0H\x00\x1a\xe1\x03\n\x1aGetTokenStatusesResponseV0\x12v\n\x0etoken_statuses\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0.TokenStatusesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x44\n\x10TokenStatusEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x13\n\x06paused\x18\x02 \x01(\x08H\x00\x88\x01\x01\x42\t\n\x07_paused\x1a\x88\x01\n\rTokenStatuses\x12w\n\x0etoken_statuses\x18\x01 \x03(\x0b\x32_.org.dash.platform.dapi.v0.GetTokenStatusesResponse.GetTokenStatusesResponseV0.TokenStatusEntryB\x08\n\x06resultB\t\n\x07version\"\xef\x01\n#GetTokenDirectPurchasePricesRequest\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesRequest.GetTokenDirectPurchasePricesRequestV0H\x00\x1aI\n%GetTokenDirectPurchasePricesRequestV0\x12\x11\n\ttoken_ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x8b\t\n$GetTokenDirectPurchasePricesResponse\x12t\n\x02v0\x18\x01 \x01(\x0b\x32\x66.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0H\x00\x1a\xe1\x07\n&GetTokenDirectPurchasePricesResponseV0\x12\xa9\x01\n\x1ctoken_direct_purchase_prices\x18\x01 \x01(\x0b\x32\x80\x01.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.TokenDirectPurchasePricesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x33\n\x10PriceForQuantity\x12\x10\n\x08quantity\x18\x01 \x01(\x04\x12\r\n\x05price\x18\x02 \x01(\x04\x1a\xa7\x01\n\x0fPricingSchedule\x12\x93\x01\n\x12price_for_quantity\x18\x01 \x03(\x0b\x32w.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.PriceForQuantity\x1a\xe4\x01\n\x1dTokenDirectPurchasePriceEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x15\n\x0b\x66ixed_price\x18\x02 \x01(\x04H\x00\x12\x90\x01\n\x0evariable_price\x18\x03 \x01(\x0b\x32v.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.PricingScheduleH\x00\x42\x07\n\x05price\x1a\xc8\x01\n\x19TokenDirectPurchasePrices\x12\xaa\x01\n\x1btoken_direct_purchase_price\x18\x01 \x03(\x0b\x32\x84\x01.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse.GetTokenDirectPurchasePricesResponseV0.TokenDirectPurchasePriceEntryB\x08\n\x06resultB\t\n\x07version\"\xce\x01\n\x1bGetTokenContractInfoRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetTokenContractInfoRequest.GetTokenContractInfoRequestV0H\x00\x1a@\n\x1dGetTokenContractInfoRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xfb\x03\n\x1cGetTokenContractInfoResponse\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetTokenContractInfoResponse.GetTokenContractInfoResponseV0H\x00\x1a\xe9\x02\n\x1eGetTokenContractInfoResponseV0\x12|\n\x04\x64\x61ta\x18\x01 \x01(\x0b\x32l.org.dash.platform.dapi.v0.GetTokenContractInfoResponse.GetTokenContractInfoResponseV0.TokenContractInfoDataH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aM\n\x15TokenContractInfoData\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17token_contract_position\x18\x02 \x01(\rB\x08\n\x06resultB\t\n\x07version\"\xef\x04\n)GetTokenPreProgrammedDistributionsRequest\x12~\n\x02v0\x18\x01 \x01(\x0b\x32p.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest.GetTokenPreProgrammedDistributionsRequestV0H\x00\x1a\xb6\x03\n+GetTokenPreProgrammedDistributionsRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x98\x01\n\rstart_at_info\x18\x02 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest.GetTokenPreProgrammedDistributionsRequestV0.StartAtInfoH\x00\x88\x01\x01\x12\x12\n\x05limit\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x04 \x01(\x08\x1a\x9a\x01\n\x0bStartAtInfo\x12\x15\n\rstart_time_ms\x18\x01 \x01(\x04\x12\x1c\n\x0fstart_recipient\x18\x02 \x01(\x0cH\x00\x88\x01\x01\x12%\n\x18start_recipient_included\x18\x03 \x01(\x08H\x01\x88\x01\x01\x42\x12\n\x10_start_recipientB\x1b\n\x19_start_recipient_includedB\x10\n\x0e_start_at_infoB\x08\n\x06_limitB\t\n\x07version\"\xec\x07\n*GetTokenPreProgrammedDistributionsResponse\x12\x80\x01\n\x02v0\x18\x01 \x01(\x0b\x32r.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0H\x00\x1a\xaf\x06\n,GetTokenPreProgrammedDistributionsResponseV0\x12\xa5\x01\n\x13token_distributions\x18\x01 \x01(\x0b\x32\x85\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenDistributionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a>\n\x16TokenDistributionEntry\x12\x14\n\x0crecipient_id\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x1a\xd4\x01\n\x1bTokenTimedDistributionEntry\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\x12\xa1\x01\n\rdistributions\x18\x02 \x03(\x0b\x32\x89\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenDistributionEntry\x1a\xc3\x01\n\x12TokenDistributions\x12\xac\x01\n\x13token_distributions\x18\x01 \x03(\x0b\x32\x8e\x01.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse.GetTokenPreProgrammedDistributionsResponseV0.TokenTimedDistributionEntryB\x08\n\x06resultB\t\n\x07version\"\x82\x04\n-GetTokenPerpetualDistributionLastClaimRequest\x12\x86\x01\n\x02v0\x18\x01 \x01(\x0b\x32x.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest.GetTokenPerpetualDistributionLastClaimRequestV0H\x00\x1aI\n\x11\x43ontractTokenInfo\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17token_contract_position\x18\x02 \x01(\r\x1a\xf1\x01\n/GetTokenPerpetualDistributionLastClaimRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12v\n\rcontract_info\x18\x02 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest.ContractTokenInfoH\x00\x88\x01\x01\x12\x13\n\x0bidentity_id\x18\x04 \x01(\x0c\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x10\n\x0e_contract_infoB\t\n\x07version\"\x93\x05\n.GetTokenPerpetualDistributionLastClaimResponse\x12\x88\x01\n\x02v0\x18\x01 \x01(\x0b\x32z.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse.GetTokenPerpetualDistributionLastClaimResponseV0H\x00\x1a\xca\x03\n0GetTokenPerpetualDistributionLastClaimResponseV0\x12\x9f\x01\n\nlast_claim\x18\x01 \x01(\x0b\x32\x88\x01.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse.GetTokenPerpetualDistributionLastClaimResponseV0.LastClaimInfoH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1ax\n\rLastClaimInfo\x12\x1a\n\x0ctimestamp_ms\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x1a\n\x0c\x62lock_height\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12\x0f\n\x05\x65poch\x18\x03 \x01(\rH\x00\x12\x13\n\traw_bytes\x18\x04 \x01(\x0cH\x00\x42\t\n\x07paid_atB\x08\n\x06resultB\t\n\x07version\"\xca\x01\n\x1aGetTokenTotalSupplyRequest\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetTokenTotalSupplyRequest.GetTokenTotalSupplyRequestV0H\x00\x1a?\n\x1cGetTokenTotalSupplyRequestV0\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xaf\x04\n\x1bGetTokenTotalSupplyResponse\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse.GetTokenTotalSupplyResponseV0H\x00\x1a\xa0\x03\n\x1dGetTokenTotalSupplyResponseV0\x12\x88\x01\n\x12token_total_supply\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse.GetTokenTotalSupplyResponseV0.TokenTotalSupplyEntryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1ax\n\x15TokenTotalSupplyEntry\x12\x10\n\x08token_id\x18\x01 \x01(\x0c\x12\x30\n(total_aggregated_amount_in_user_accounts\x18\x02 \x01(\x04\x12\x1b\n\x13total_system_amount\x18\x03 \x01(\x04\x42\x08\n\x06resultB\t\n\x07version\"\xd2\x01\n\x13GetGroupInfoRequest\x12R\n\x02v0\x18\x01 \x01(\x0b\x32\x44.org.dash.platform.dapi.v0.GetGroupInfoRequest.GetGroupInfoRequestV0H\x00\x1a\\\n\x15GetGroupInfoRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xd4\x05\n\x14GetGroupInfoResponse\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0H\x00\x1a\xda\x04\n\x16GetGroupInfoResponseV0\x12\x66\n\ngroup_info\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupInfoH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x04 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x34\n\x10GroupMemberEntry\x12\x11\n\tmember_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\x98\x01\n\x0eGroupInfoEntry\x12h\n\x07members\x18\x01 \x03(\x0b\x32W.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupMemberEntry\x12\x1c\n\x14group_required_power\x18\x02 \x01(\r\x1a\x8a\x01\n\tGroupInfo\x12n\n\ngroup_info\x18\x01 \x01(\x0b\x32U.org.dash.platform.dapi.v0.GetGroupInfoResponse.GetGroupInfoResponseV0.GroupInfoEntryH\x00\x88\x01\x01\x42\r\n\x0b_group_infoB\x08\n\x06resultB\t\n\x07version\"\xed\x03\n\x14GetGroupInfosRequest\x12T\n\x02v0\x18\x01 \x01(\x0b\x32\x46.org.dash.platform.dapi.v0.GetGroupInfosRequest.GetGroupInfosRequestV0H\x00\x1au\n\x1cStartAtGroupContractPosition\x12%\n\x1dstart_group_contract_position\x18\x01 \x01(\r\x12.\n&start_group_contract_position_included\x18\x02 \x01(\x08\x1a\xfc\x01\n\x16GetGroupInfosRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12{\n start_at_group_contract_position\x18\x02 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetGroupInfosRequest.StartAtGroupContractPositionH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x04 \x01(\x08\x42#\n!_start_at_group_contract_positionB\x08\n\x06_countB\t\n\x07version\"\xff\x05\n\x15GetGroupInfosResponse\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0H\x00\x1a\x82\x05\n\x17GetGroupInfosResponseV0\x12j\n\x0bgroup_infos\x18\x01 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupInfosH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x04 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x34\n\x10GroupMemberEntry\x12\x11\n\tmember_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\xc3\x01\n\x16GroupPositionInfoEntry\x12\x1f\n\x17group_contract_position\x18\x01 \x01(\r\x12j\n\x07members\x18\x02 \x03(\x0b\x32Y.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupMemberEntry\x12\x1c\n\x14group_required_power\x18\x03 \x01(\r\x1a\x82\x01\n\nGroupInfos\x12t\n\x0bgroup_infos\x18\x01 \x03(\x0b\x32_.org.dash.platform.dapi.v0.GetGroupInfosResponse.GetGroupInfosResponseV0.GroupPositionInfoEntryB\x08\n\x06resultB\t\n\x07version\"\xbe\x04\n\x16GetGroupActionsRequest\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetGroupActionsRequest.GetGroupActionsRequestV0H\x00\x1aL\n\x0fStartAtActionId\x12\x17\n\x0fstart_action_id\x18\x01 \x01(\x0c\x12 \n\x18start_action_id_included\x18\x02 \x01(\x08\x1a\xc8\x02\n\x18GetGroupActionsRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12N\n\x06status\x18\x03 \x01(\x0e\x32>.org.dash.platform.dapi.v0.GetGroupActionsRequest.ActionStatus\x12\x62\n\x12start_at_action_id\x18\x04 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetGroupActionsRequest.StartAtActionIdH\x00\x88\x01\x01\x12\x12\n\x05\x63ount\x18\x05 \x01(\rH\x01\x88\x01\x01\x12\r\n\x05prove\x18\x06 \x01(\x08\x42\x15\n\x13_start_at_action_idB\x08\n\x06_count\"&\n\x0c\x41\x63tionStatus\x12\n\n\x06\x41\x43TIVE\x10\x00\x12\n\n\x06\x43LOSED\x10\x01\x42\t\n\x07version\"\xd6\x1e\n\x17GetGroupActionsResponse\x12Z\n\x02v0\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0H\x00\x1a\xd3\x1d\n\x19GetGroupActionsResponseV0\x12r\n\rgroup_actions\x18\x01 \x01(\x0b\x32Y.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a[\n\tMintEvent\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x04\x12\x14\n\x0crecipient_id\x18\x02 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a[\n\tBurnEvent\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x04\x12\x14\n\x0c\x62urn_from_id\x18\x02 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1aJ\n\x0b\x46reezeEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1aL\n\rUnfreezeEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\x66\n\x17\x44\x65stroyFrozenFundsEvent\x12\x11\n\tfrozen_id\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x04\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\x64\n\x13SharedEncryptedNote\x12\x18\n\x10sender_key_index\x18\x01 \x01(\r\x12\x1b\n\x13recipient_key_index\x18\x02 \x01(\r\x12\x16\n\x0e\x65ncrypted_data\x18\x03 \x01(\x0c\x1a{\n\x15PersonalEncryptedNote\x12!\n\x19root_encryption_key_index\x18\x01 \x01(\r\x12\'\n\x1f\x64\x65rivation_encryption_key_index\x18\x02 \x01(\r\x12\x16\n\x0e\x65ncrypted_data\x18\x03 \x01(\x0c\x1a\xe9\x01\n\x14\x45mergencyActionEvent\x12\x81\x01\n\x0b\x61\x63tion_type\x18\x01 \x01(\x0e\x32l.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.EmergencyActionEvent.ActionType\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\"#\n\nActionType\x12\t\n\x05PAUSE\x10\x00\x12\n\n\x06RESUME\x10\x01\x42\x0e\n\x0c_public_note\x1a\x64\n\x16TokenConfigUpdateEvent\x12 \n\x18token_config_update_item\x18\x01 \x01(\x0c\x12\x18\n\x0bpublic_note\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_public_note\x1a\xe6\x03\n\x1eUpdateDirectPurchasePriceEvent\x12\x15\n\x0b\x66ixed_price\x18\x01 \x01(\x04H\x00\x12\x95\x01\n\x0evariable_price\x18\x02 \x01(\x0b\x32{.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEvent.PricingScheduleH\x00\x12\x18\n\x0bpublic_note\x18\x03 \x01(\tH\x01\x88\x01\x01\x1a\x33\n\x10PriceForQuantity\x12\x10\n\x08quantity\x18\x01 \x01(\x04\x12\r\n\x05price\x18\x02 \x01(\x04\x1a\xac\x01\n\x0fPricingSchedule\x12\x98\x01\n\x12price_for_quantity\x18\x01 \x03(\x0b\x32|.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEvent.PriceForQuantityB\x07\n\x05priceB\x0e\n\x0c_public_note\x1a\xfc\x02\n\x10GroupActionEvent\x12n\n\x0btoken_event\x18\x01 \x01(\x0b\x32W.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.TokenEventH\x00\x12t\n\x0e\x64ocument_event\x18\x02 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DocumentEventH\x00\x12t\n\x0e\x63ontract_event\x18\x03 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.ContractEventH\x00\x42\x0c\n\nevent_type\x1a\x8b\x01\n\rDocumentEvent\x12r\n\x06\x63reate\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DocumentCreateEventH\x00\x42\x06\n\x04type\x1a/\n\x13\x44ocumentCreateEvent\x12\x18\n\x10\x63reated_document\x18\x01 \x01(\x0c\x1a/\n\x13\x43ontractUpdateEvent\x12\x18\n\x10updated_contract\x18\x01 \x01(\x0c\x1a\x8b\x01\n\rContractEvent\x12r\n\x06update\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.ContractUpdateEventH\x00\x42\x06\n\x04type\x1a\xd1\x07\n\nTokenEvent\x12\x66\n\x04mint\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.MintEventH\x00\x12\x66\n\x04\x62urn\x18\x02 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.BurnEventH\x00\x12j\n\x06\x66reeze\x18\x03 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.FreezeEventH\x00\x12n\n\x08unfreeze\x18\x04 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UnfreezeEventH\x00\x12\x84\x01\n\x14\x64\x65stroy_frozen_funds\x18\x05 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.DestroyFrozenFundsEventH\x00\x12}\n\x10\x65mergency_action\x18\x06 \x01(\x0b\x32\x61.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.EmergencyActionEventH\x00\x12\x82\x01\n\x13token_config_update\x18\x07 \x01(\x0b\x32\x63.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.TokenConfigUpdateEventH\x00\x12\x83\x01\n\x0cupdate_price\x18\x08 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.UpdateDirectPurchasePriceEventH\x00\x42\x06\n\x04type\x1a\x93\x01\n\x10GroupActionEntry\x12\x11\n\taction_id\x18\x01 \x01(\x0c\x12l\n\x05\x65vent\x18\x02 \x01(\x0b\x32].org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionEvent\x1a\x84\x01\n\x0cGroupActions\x12t\n\rgroup_actions\x18\x01 \x03(\x0b\x32].org.dash.platform.dapi.v0.GetGroupActionsResponse.GetGroupActionsResponseV0.GroupActionEntryB\x08\n\x06resultB\t\n\x07version\"\x88\x03\n\x1cGetGroupActionSignersRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetGroupActionSignersRequest.GetGroupActionSignersRequestV0H\x00\x1a\xce\x01\n\x1eGetGroupActionSignersRequestV0\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x1f\n\x17group_contract_position\x18\x02 \x01(\r\x12T\n\x06status\x18\x03 \x01(\x0e\x32\x44.org.dash.platform.dapi.v0.GetGroupActionSignersRequest.ActionStatus\x12\x11\n\taction_id\x18\x04 \x01(\x0c\x12\r\n\x05prove\x18\x05 \x01(\x08\"&\n\x0c\x41\x63tionStatus\x12\n\n\x06\x41\x43TIVE\x10\x00\x12\n\n\x06\x43LOSED\x10\x01\x42\t\n\x07version\"\x8b\x05\n\x1dGetGroupActionSignersResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0H\x00\x1a\xf6\x03\n\x1fGetGroupActionSignersResponseV0\x12\x8b\x01\n\x14group_action_signers\x18\x01 \x01(\x0b\x32k.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0.GroupActionSignersH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x35\n\x11GroupActionSigner\x12\x11\n\tsigner_id\x18\x01 \x01(\x0c\x12\r\n\x05power\x18\x02 \x01(\r\x1a\x91\x01\n\x12GroupActionSigners\x12{\n\x07signers\x18\x01 \x03(\x0b\x32j.org.dash.platform.dapi.v0.GetGroupActionSignersResponse.GetGroupActionSignersResponseV0.GroupActionSignerB\x08\n\x06resultB\t\n\x07version\"\xb5\x01\n\x15GetAddressInfoRequest\x12V\n\x02v0\x18\x01 \x01(\x0b\x32H.org.dash.platform.dapi.v0.GetAddressInfoRequest.GetAddressInfoRequestV0H\x00\x1a\x39\n\x17GetAddressInfoRequestV0\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x85\x01\n\x10\x41\x64\x64ressInfoEntry\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12J\n\x11\x62\x61lance_and_nonce\x18\x02 \x01(\x0b\x32*.org.dash.platform.dapi.v0.BalanceAndNonceH\x00\x88\x01\x01\x42\x14\n\x12_balance_and_nonce\"1\n\x0f\x42\x61lanceAndNonce\x12\x0f\n\x07\x62\x61lance\x18\x01 \x01(\x04\x12\r\n\x05nonce\x18\x02 \x01(\r\"_\n\x12\x41\x64\x64ressInfoEntries\x12I\n\x14\x61\x64\x64ress_info_entries\x18\x01 \x03(\x0b\x32+.org.dash.platform.dapi.v0.AddressInfoEntry\"m\n\x14\x41\x64\x64ressBalanceChange\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x19\n\x0bset_balance\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12\x1c\n\x0e\x61\x64\x64_to_balance\x18\x03 \x01(\x04\x42\x02\x30\x01H\x00\x42\x0b\n\toperation\"x\n\x1a\x42lockAddressBalanceChanges\x12\x18\n\x0c\x62lock_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12@\n\x07\x63hanges\x18\x02 \x03(\x0b\x32/.org.dash.platform.dapi.v0.AddressBalanceChange\"k\n\x1b\x41\x64\x64ressBalanceUpdateEntries\x12L\n\rblock_changes\x18\x01 \x03(\x0b\x32\x35.org.dash.platform.dapi.v0.BlockAddressBalanceChanges\"\xe1\x02\n\x16GetAddressInfoResponse\x12X\n\x02v0\x18\x01 \x01(\x0b\x32J.org.dash.platform.dapi.v0.GetAddressInfoResponse.GetAddressInfoResponseV0H\x00\x1a\xe1\x01\n\x18GetAddressInfoResponseV0\x12I\n\x12\x61\x64\x64ress_info_entry\x18\x01 \x01(\x0b\x32+.org.dash.platform.dapi.v0.AddressInfoEntryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc3\x01\n\x18GetAddressesInfosRequest\x12\\\n\x02v0\x18\x01 \x01(\x0b\x32N.org.dash.platform.dapi.v0.GetAddressesInfosRequest.GetAddressesInfosRequestV0H\x00\x1a>\n\x1aGetAddressesInfosRequestV0\x12\x11\n\taddresses\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf1\x02\n\x19GetAddressesInfosResponse\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetAddressesInfosResponse.GetAddressesInfosResponseV0H\x00\x1a\xe8\x01\n\x1bGetAddressesInfosResponseV0\x12M\n\x14\x61\x64\x64ress_info_entries\x18\x01 \x01(\x0b\x32-.org.dash.platform.dapi.v0.AddressInfoEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xb5\x01\n\x1dGetAddressesTrunkStateRequest\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetAddressesTrunkStateRequest.GetAddressesTrunkStateRequestV0H\x00\x1a!\n\x1fGetAddressesTrunkStateRequestV0B\t\n\x07version\"\xaa\x02\n\x1eGetAddressesTrunkStateResponse\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetAddressesTrunkStateResponse.GetAddressesTrunkStateResponseV0H\x00\x1a\x92\x01\n GetAddressesTrunkStateResponseV0\x12/\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.Proof\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\t\n\x07version\"\xf0\x01\n\x1eGetAddressesBranchStateRequest\x12h\n\x02v0\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetAddressesBranchStateRequest.GetAddressesBranchStateRequestV0H\x00\x1aY\n GetAddressesBranchStateRequestV0\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12\r\n\x05\x64\x65pth\x18\x02 \x01(\r\x12\x19\n\x11\x63heckpoint_height\x18\x03 \x01(\x04\x42\t\n\x07version\"\xd1\x01\n\x1fGetAddressesBranchStateResponse\x12j\n\x02v0\x18\x01 \x01(\x0b\x32\\.org.dash.platform.dapi.v0.GetAddressesBranchStateResponse.GetAddressesBranchStateResponseV0H\x00\x1a\x37\n!GetAddressesBranchStateResponseV0\x12\x12\n\nmerk_proof\x18\x02 \x01(\x0c\x42\t\n\x07version\"\x9e\x02\n%GetRecentAddressBalanceChangesRequest\x12v\n\x02v0\x18\x01 \x01(\x0b\x32h.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesRequest.GetRecentAddressBalanceChangesRequestV0H\x00\x1ar\n\'GetRecentAddressBalanceChangesRequestV0\x12\x18\n\x0cstart_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x02 \x01(\x08\x12\x1e\n\x16start_height_exclusive\x18\x03 \x01(\x08\x42\t\n\x07version\"\xb8\x03\n&GetRecentAddressBalanceChangesResponse\x12x\n\x02v0\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesResponse.GetRecentAddressBalanceChangesResponseV0H\x00\x1a\x88\x02\n(GetRecentAddressBalanceChangesResponseV0\x12`\n\x1e\x61\x64\x64ress_balance_update_entries\x18\x01 \x01(\x0b\x32\x36.org.dash.platform.dapi.v0.AddressBalanceUpdateEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"G\n\x16\x42lockHeightCreditEntry\x12\x18\n\x0c\x62lock_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x13\n\x07\x63redits\x18\x02 \x01(\x04\x42\x02\x30\x01\"\xb0\x01\n\x1d\x43ompactedAddressBalanceChange\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0c\x12\x19\n\x0bset_credits\x18\x02 \x01(\x04\x42\x02\x30\x01H\x00\x12V\n\x19\x61\x64\x64_to_credits_operations\x18\x03 \x01(\x0b\x32\x31.org.dash.platform.dapi.v0.AddToCreditsOperationsH\x00\x42\x0b\n\toperation\"\\\n\x16\x41\x64\x64ToCreditsOperations\x12\x42\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x31.org.dash.platform.dapi.v0.BlockHeightCreditEntry\"\xae\x01\n#CompactedBlockAddressBalanceChanges\x12\x1e\n\x12start_block_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x1c\n\x10\x65nd_block_height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12I\n\x07\x63hanges\x18\x03 \x03(\x0b\x32\x38.org.dash.platform.dapi.v0.CompactedAddressBalanceChange\"\x87\x01\n$CompactedAddressBalanceUpdateEntries\x12_\n\x17\x63ompacted_block_changes\x18\x01 \x03(\x0b\x32>.org.dash.platform.dapi.v0.CompactedBlockAddressBalanceChanges\"\xa9\x02\n.GetRecentCompactedAddressBalanceChangesRequest\x12\x88\x01\n\x02v0\x18\x01 \x01(\x0b\x32z.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesRequest.GetRecentCompactedAddressBalanceChangesRequestV0H\x00\x1a\x61\n0GetRecentCompactedAddressBalanceChangesRequestV0\x12\x1e\n\x12start_block_height\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\xf0\x03\n/GetRecentCompactedAddressBalanceChangesResponse\x12\x8a\x01\n\x02v0\x18\x01 \x01(\x0b\x32|.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesResponse.GetRecentCompactedAddressBalanceChangesResponseV0H\x00\x1a\xa4\x02\n1GetRecentCompactedAddressBalanceChangesResponseV0\x12s\n(compacted_address_balance_update_entries\x18\x01 \x01(\x0b\x32?.org.dash.platform.dapi.v0.CompactedAddressBalanceUpdateEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xf4\x01\n GetShieldedEncryptedNotesRequest\x12l\n\x02v0\x18\x01 \x01(\x0b\x32^.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesRequest.GetShieldedEncryptedNotesRequestV0H\x00\x1aW\n\"GetShieldedEncryptedNotesRequestV0\x12\x13\n\x0bstart_index\x18\x01 \x01(\x04\x12\r\n\x05\x63ount\x18\x02 \x01(\r\x12\r\n\x05prove\x18\x03 \x01(\x08\x42\t\n\x07version\"\xbc\x05\n!GetShieldedEncryptedNotesResponse\x12n\n\x02v0\x18\x01 \x01(\x0b\x32`.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse.GetShieldedEncryptedNotesResponseV0H\x00\x1a\x9b\x04\n#GetShieldedEncryptedNotesResponseV0\x12\x8a\x01\n\x0f\x65ncrypted_notes\x18\x01 \x01(\x0b\x32o.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse.GetShieldedEncryptedNotesResponseV0.EncryptedNotesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1aW\n\rEncryptedNote\x12\x11\n\tnullifier\x18\x01 \x01(\x0c\x12\x0b\n\x03\x63mx\x18\x02 \x01(\x0c\x12\x16\n\x0e\x65ncrypted_note\x18\x03 \x01(\x0c\x12\x0e\n\x06\x63v_net\x18\x04 \x01(\x0c\x1a\x91\x01\n\x0e\x45ncryptedNotes\x12\x7f\n\x07\x65ntries\x18\x01 \x03(\x0b\x32n.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse.GetShieldedEncryptedNotesResponseV0.EncryptedNoteB\x08\n\x06resultB\t\n\x07version\"\xb4\x01\n\x19GetShieldedAnchorsRequest\x12^\n\x02v0\x18\x01 \x01(\x0b\x32P.org.dash.platform.dapi.v0.GetShieldedAnchorsRequest.GetShieldedAnchorsRequestV0H\x00\x1a,\n\x1bGetShieldedAnchorsRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xb1\x03\n\x1aGetShieldedAnchorsResponse\x12`\n\x02v0\x18\x01 \x01(\x0b\x32R.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse.GetShieldedAnchorsResponseV0H\x00\x1a\xa5\x02\n\x1cGetShieldedAnchorsResponseV0\x12m\n\x07\x61nchors\x18\x01 \x01(\x0b\x32Z.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse.GetShieldedAnchorsResponseV0.AnchorsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\x07\x41nchors\x12\x0f\n\x07\x61nchors\x18\x01 \x03(\x0c\x42\x08\n\x06resultB\t\n\x07version\"\xd8\x01\n\"GetMostRecentShieldedAnchorRequest\x12p\n\x02v0\x18\x01 \x01(\x0b\x32\x62.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorRequest.GetMostRecentShieldedAnchorRequestV0H\x00\x1a\x35\n$GetMostRecentShieldedAnchorRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xdc\x02\n#GetMostRecentShieldedAnchorResponse\x12r\n\x02v0\x18\x01 \x01(\x0b\x32\x64.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorResponse.GetMostRecentShieldedAnchorResponseV0H\x00\x1a\xb5\x01\n%GetMostRecentShieldedAnchorResponseV0\x12\x10\n\x06\x61nchor\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xbc\x01\n\x1bGetShieldedPoolStateRequest\x12\x62\n\x02v0\x18\x01 \x01(\x0b\x32T.org.dash.platform.dapi.v0.GetShieldedPoolStateRequest.GetShieldedPoolStateRequestV0H\x00\x1a.\n\x1dGetShieldedPoolStateRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xcb\x02\n\x1cGetShieldedPoolStateResponse\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedPoolStateResponse.GetShieldedPoolStateResponseV0H\x00\x1a\xb9\x01\n\x1eGetShieldedPoolStateResponseV0\x12\x1b\n\rtotal_balance\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xc0\x01\n\x1cGetShieldedNotesCountRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedNotesCountRequest.GetShieldedNotesCountRequestV0H\x00\x1a/\n\x1eGetShieldedNotesCountRequestV0\x12\r\n\x05prove\x18\x01 \x01(\x08\x42\t\n\x07version\"\xd3\x02\n\x1dGetShieldedNotesCountResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetShieldedNotesCountResponse.GetShieldedNotesCountResponseV0H\x00\x1a\xbe\x01\n\x1fGetShieldedNotesCountResponseV0\x12\x1f\n\x11total_notes_count\x18\x01 \x01(\x04\x42\x02\x30\x01H\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06resultB\t\n\x07version\"\xd4\x01\n\x1cGetShieldedNullifiersRequest\x12\x64\n\x02v0\x18\x01 \x01(\x0b\x32V.org.dash.platform.dapi.v0.GetShieldedNullifiersRequest.GetShieldedNullifiersRequestV0H\x00\x1a\x43\n\x1eGetShieldedNullifiersRequestV0\x12\x12\n\nnullifiers\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\x42\t\n\x07version\"\x86\x05\n\x1dGetShieldedNullifiersResponse\x12\x66\n\x02v0\x18\x01 \x01(\x0b\x32X.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0H\x00\x1a\xf1\x03\n\x1fGetShieldedNullifiersResponseV0\x12\x88\x01\n\x12nullifier_statuses\x18\x01 \x01(\x0b\x32j.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0.NullifierStatusesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x36\n\x0fNullifierStatus\x12\x11\n\tnullifier\x18\x01 \x01(\x0c\x12\x10\n\x08is_spent\x18\x02 \x01(\x08\x1a\x8e\x01\n\x11NullifierStatuses\x12y\n\x07\x65ntries\x18\x01 \x03(\x0b\x32h.org.dash.platform.dapi.v0.GetShieldedNullifiersResponse.GetShieldedNullifiersResponseV0.NullifierStatusB\x08\n\x06resultB\t\n\x07version*Z\n\nKeyPurpose\x12\x12\n\x0e\x41UTHENTICATION\x10\x00\x12\x0e\n\nENCRYPTION\x10\x01\x12\x0e\n\nDECRYPTION\x10\x02\x12\x0c\n\x08TRANSFER\x10\x03\x12\n\n\x06VOTING\x10\x05*\xb9\x01\n\x16\x43ontractModerationList\x12(\n$CONTRACT_MODERATION_LIST_UNSPECIFIED\x10\x00\x12$\n CONTRACT_MODERATION_LIST_BANLIST\x10\x01\x12(\n$CONTRACT_MODERATION_LIST_SUSPENSIONS\x10\x02\x12%\n!CONTRACT_MODERATION_LIST_WARNINGS\x10\x03\x32\xd0P\n\x08Platform\x12\x93\x01\n\x18\x62roadcastStateTransition\x12:.org.dash.platform.dapi.v0.BroadcastStateTransitionRequest\x1a;.org.dash.platform.dapi.v0.BroadcastStateTransitionResponse\x12l\n\x0bgetIdentity\x12-.org.dash.platform.dapi.v0.GetIdentityRequest\x1a..org.dash.platform.dapi.v0.GetIdentityResponse\x12x\n\x0fgetIdentityKeys\x12\x31.org.dash.platform.dapi.v0.GetIdentityKeysRequest\x1a\x32.org.dash.platform.dapi.v0.GetIdentityKeysResponse\x12\x96\x01\n\x19getIdentitiesContractKeys\x12;.org.dash.platform.dapi.v0.GetIdentitiesContractKeysRequest\x1a<.org.dash.platform.dapi.v0.GetIdentitiesContractKeysResponse\x12{\n\x10getIdentityNonce\x12\x32.org.dash.platform.dapi.v0.GetIdentityNonceRequest\x1a\x33.org.dash.platform.dapi.v0.GetIdentityNonceResponse\x12\x93\x01\n\x18getIdentityContractNonce\x12:.org.dash.platform.dapi.v0.GetIdentityContractNonceRequest\x1a;.org.dash.platform.dapi.v0.GetIdentityContractNonceResponse\x12\xa8\x01\n\x1fgetIdentityKeysRemainingBudgets\x12\x41.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsRequest\x1a\x42.org.dash.platform.dapi.v0.GetIdentityKeysRemainingBudgetsResponse\x12\x81\x01\n\x12getIdentityBalance\x12\x34.org.dash.platform.dapi.v0.GetIdentityBalanceRequest\x1a\x35.org.dash.platform.dapi.v0.GetIdentityBalanceResponse\x12\x8a\x01\n\x15getIdentitiesBalances\x12\x37.org.dash.platform.dapi.v0.GetIdentitiesBalancesRequest\x1a\x38.org.dash.platform.dapi.v0.GetIdentitiesBalancesResponse\x12\xa2\x01\n\x1dgetIdentityBalanceAndRevision\x12?.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionRequest\x1a@.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse\x12\xaf\x01\n#getEvonodesProposedEpochBlocksByIds\x12\x45.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByIdsRequest\x1a\x41.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse\x12\xb3\x01\n%getEvonodesProposedEpochBlocksByRange\x12G.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksByRangeRequest\x1a\x41.org.dash.platform.dapi.v0.GetEvonodesProposedEpochBlocksResponse\x12x\n\x0fgetDataContract\x12\x31.org.dash.platform.dapi.v0.GetDataContractRequest\x1a\x32.org.dash.platform.dapi.v0.GetDataContractResponse\x12\x8d\x01\n\x16getDataContractHistory\x12\x38.org.dash.platform.dapi.v0.GetDataContractHistoryRequest\x1a\x39.org.dash.platform.dapi.v0.GetDataContractHistoryResponse\x12\xa5\x01\n\x1egetDataContractsLatestVersions\x12@.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsRequest\x1a\x41.org.dash.platform.dapi.v0.GetDataContractsLatestVersionsResponse\x12{\n\x10getDataContracts\x12\x32.org.dash.platform.dapi.v0.GetDataContractsRequest\x1a\x33.org.dash.platform.dapi.v0.GetDataContractsResponse\x12\x89\x01\n\x17getDataContractsByRange\x12\x39.org.dash.platform.dapi.v0.GetDataContractsByRangeRequest\x1a\x33.org.dash.platform.dapi.v0.GetDataContractsResponse\x12\x87\x01\n\x14getContractGroupInfo\x12\x36.org.dash.platform.dapi.v0.GetContractGroupInfoRequest\x1a\x37.org.dash.platform.dapi.v0.GetContractGroupInfoResponse\x12\x90\x01\n\x17getContractGroupMembers\x12\x39.org.dash.platform.dapi.v0.GetContractGroupMembersRequest\x1a:.org.dash.platform.dapi.v0.GetContractGroupMembersResponse\x12\x9f\x01\n\x1cgetContractGroupsForContract\x12>.org.dash.platform.dapi.v0.GetContractGroupsForContractRequest\x1a?.org.dash.platform.dapi.v0.GetContractGroupsForContractResponse\x12\x9c\x01\n\x1bgetContractModerationStatus\x12=.org.dash.platform.dapi.v0.GetContractModerationStatusRequest\x1a>.org.dash.platform.dapi.v0.GetContractModerationStatusResponse\x12\x9f\x01\n\x1cgetContractModerationEntries\x12>.org.dash.platform.dapi.v0.GetContractModerationEntriesRequest\x1a?.org.dash.platform.dapi.v0.GetContractModerationEntriesResponse\x12\x9c\x01\n\x1bgetContractDocumentRemovals\x12=.org.dash.platform.dapi.v0.GetContractDocumentRemovalsRequest\x1a>.org.dash.platform.dapi.v0.GetContractDocumentRemovalsResponse\x12\x81\x01\n\x12getContractFeePots\x12\x34.org.dash.platform.dapi.v0.GetContractFeePotsRequest\x1a\x35.org.dash.platform.dapi.v0.GetContractFeePotsResponse\x12\x81\x01\n\x12getDocumentHistory\x12\x34.org.dash.platform.dapi.v0.GetDocumentHistoryRequest\x1a\x35.org.dash.platform.dapi.v0.GetDocumentHistoryResponse\x12o\n\x0cgetDocuments\x12..org.dash.platform.dapi.v0.GetDocumentsRequest\x1a/.org.dash.platform.dapi.v0.GetDocumentsResponse\x12\x99\x01\n\x1agetIdentityByPublicKeyHash\x12<.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashRequest\x1a=.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashResponse\x12\xb4\x01\n#getIdentityByNonUniquePublicKeyHash\x12\x45.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashRequest\x1a\x46.org.dash.platform.dapi.v0.GetIdentityByNonUniquePublicKeyHashResponse\x12\x9f\x01\n\x1cwaitForStateTransitionResult\x12>.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest\x1a?.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse\x12\x81\x01\n\x12getConsensusParams\x12\x34.org.dash.platform.dapi.v0.GetConsensusParamsRequest\x1a\x35.org.dash.platform.dapi.v0.GetConsensusParamsResponse\x12\xa5\x01\n\x1egetProtocolVersionUpgradeState\x12@.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateRequest\x1a\x41.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeStateResponse\x12\xb4\x01\n#getProtocolVersionUpgradeVoteStatus\x12\x45.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusRequest\x1a\x46.org.dash.platform.dapi.v0.GetProtocolVersionUpgradeVoteStatusResponse\x12r\n\rgetEpochsInfo\x12/.org.dash.platform.dapi.v0.GetEpochsInfoRequest\x1a\x30.org.dash.platform.dapi.v0.GetEpochsInfoResponse\x12\x8d\x01\n\x16getFinalizedEpochInfos\x12\x38.org.dash.platform.dapi.v0.GetFinalizedEpochInfosRequest\x1a\x39.org.dash.platform.dapi.v0.GetFinalizedEpochInfosResponse\x12\x8a\x01\n\x15getContestedResources\x12\x37.org.dash.platform.dapi.v0.GetContestedResourcesRequest\x1a\x38.org.dash.platform.dapi.v0.GetContestedResourcesResponse\x12\xa2\x01\n\x1dgetContestedResourceVoteState\x12?.org.dash.platform.dapi.v0.GetContestedResourceVoteStateRequest\x1a@.org.dash.platform.dapi.v0.GetContestedResourceVoteStateResponse\x12\xba\x01\n%getContestedResourceVotersForIdentity\x12G.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityRequest\x1aH.org.dash.platform.dapi.v0.GetContestedResourceVotersForIdentityResponse\x12\xae\x01\n!getContestedResourceIdentityVotes\x12\x43.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesRequest\x1a\x44.org.dash.platform.dapi.v0.GetContestedResourceIdentityVotesResponse\x12\x8a\x01\n\x15getVotePollsByEndDate\x12\x37.org.dash.platform.dapi.v0.GetVotePollsByEndDateRequest\x1a\x38.org.dash.platform.dapi.v0.GetVotePollsByEndDateResponse\x12\xa5\x01\n\x1egetPrefundedSpecializedBalance\x12@.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceRequest\x1a\x41.org.dash.platform.dapi.v0.GetPrefundedSpecializedBalanceResponse\x12\x96\x01\n\x19getTotalCreditsInPlatform\x12;.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformRequest\x1a<.org.dash.platform.dapi.v0.GetTotalCreditsInPlatformResponse\x12x\n\x0fgetPathElements\x12\x31.org.dash.platform.dapi.v0.GetPathElementsRequest\x1a\x32.org.dash.platform.dapi.v0.GetPathElementsResponse\x12\x66\n\tgetStatus\x12+.org.dash.platform.dapi.v0.GetStatusRequest\x1a,.org.dash.platform.dapi.v0.GetStatusResponse\x12\x8a\x01\n\x15getCurrentQuorumsInfo\x12\x37.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoRequest\x1a\x38.org.dash.platform.dapi.v0.GetCurrentQuorumsInfoResponse\x12\x93\x01\n\x18getIdentityTokenBalances\x12:.org.dash.platform.dapi.v0.GetIdentityTokenBalancesRequest\x1a;.org.dash.platform.dapi.v0.GetIdentityTokenBalancesResponse\x12\x99\x01\n\x1agetIdentitiesTokenBalances\x12<.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesRequest\x1a=.org.dash.platform.dapi.v0.GetIdentitiesTokenBalancesResponse\x12\x8a\x01\n\x15getIdentityTokenInfos\x12\x37.org.dash.platform.dapi.v0.GetIdentityTokenInfosRequest\x1a\x38.org.dash.platform.dapi.v0.GetIdentityTokenInfosResponse\x12\x90\x01\n\x17getIdentitiesTokenInfos\x12\x39.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosRequest\x1a:.org.dash.platform.dapi.v0.GetIdentitiesTokenInfosResponse\x12{\n\x10getTokenStatuses\x12\x32.org.dash.platform.dapi.v0.GetTokenStatusesRequest\x1a\x33.org.dash.platform.dapi.v0.GetTokenStatusesResponse\x12\x9f\x01\n\x1cgetTokenDirectPurchasePrices\x12>.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesRequest\x1a?.org.dash.platform.dapi.v0.GetTokenDirectPurchasePricesResponse\x12\x87\x01\n\x14getTokenContractInfo\x12\x36.org.dash.platform.dapi.v0.GetTokenContractInfoRequest\x1a\x37.org.dash.platform.dapi.v0.GetTokenContractInfoResponse\x12\xb1\x01\n\"getTokenPreProgrammedDistributions\x12\x44.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsRequest\x1a\x45.org.dash.platform.dapi.v0.GetTokenPreProgrammedDistributionsResponse\x12\xbd\x01\n&getTokenPerpetualDistributionLastClaim\x12H.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimRequest\x1aI.org.dash.platform.dapi.v0.GetTokenPerpetualDistributionLastClaimResponse\x12\x84\x01\n\x13getTokenTotalSupply\x12\x35.org.dash.platform.dapi.v0.GetTokenTotalSupplyRequest\x1a\x36.org.dash.platform.dapi.v0.GetTokenTotalSupplyResponse\x12o\n\x0cgetGroupInfo\x12..org.dash.platform.dapi.v0.GetGroupInfoRequest\x1a/.org.dash.platform.dapi.v0.GetGroupInfoResponse\x12r\n\rgetGroupInfos\x12/.org.dash.platform.dapi.v0.GetGroupInfosRequest\x1a\x30.org.dash.platform.dapi.v0.GetGroupInfosResponse\x12x\n\x0fgetGroupActions\x12\x31.org.dash.platform.dapi.v0.GetGroupActionsRequest\x1a\x32.org.dash.platform.dapi.v0.GetGroupActionsResponse\x12\x8a\x01\n\x15getGroupActionSigners\x12\x37.org.dash.platform.dapi.v0.GetGroupActionSignersRequest\x1a\x38.org.dash.platform.dapi.v0.GetGroupActionSignersResponse\x12u\n\x0egetAddressInfo\x12\x30.org.dash.platform.dapi.v0.GetAddressInfoRequest\x1a\x31.org.dash.platform.dapi.v0.GetAddressInfoResponse\x12~\n\x11getAddressesInfos\x12\x33.org.dash.platform.dapi.v0.GetAddressesInfosRequest\x1a\x34.org.dash.platform.dapi.v0.GetAddressesInfosResponse\x12\x8d\x01\n\x16getAddressesTrunkState\x12\x38.org.dash.platform.dapi.v0.GetAddressesTrunkStateRequest\x1a\x39.org.dash.platform.dapi.v0.GetAddressesTrunkStateResponse\x12\x90\x01\n\x17getAddressesBranchState\x12\x39.org.dash.platform.dapi.v0.GetAddressesBranchStateRequest\x1a:.org.dash.platform.dapi.v0.GetAddressesBranchStateResponse\x12\xa5\x01\n\x1egetRecentAddressBalanceChanges\x12@.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesRequest\x1a\x41.org.dash.platform.dapi.v0.GetRecentAddressBalanceChangesResponse\x12\xc0\x01\n\'getRecentCompactedAddressBalanceChanges\x12I.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesRequest\x1aJ.org.dash.platform.dapi.v0.GetRecentCompactedAddressBalanceChangesResponse\x12\x96\x01\n\x19getShieldedEncryptedNotes\x12;.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesRequest\x1a<.org.dash.platform.dapi.v0.GetShieldedEncryptedNotesResponse\x12\x81\x01\n\x12getShieldedAnchors\x12\x34.org.dash.platform.dapi.v0.GetShieldedAnchorsRequest\x1a\x35.org.dash.platform.dapi.v0.GetShieldedAnchorsResponse\x12\x9c\x01\n\x1bgetMostRecentShieldedAnchor\x12=.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorRequest\x1a>.org.dash.platform.dapi.v0.GetMostRecentShieldedAnchorResponse\x12\x87\x01\n\x14getShieldedPoolState\x12\x36.org.dash.platform.dapi.v0.GetShieldedPoolStateRequest\x1a\x37.org.dash.platform.dapi.v0.GetShieldedPoolStateResponse\x12\x8a\x01\n\x15getShieldedNotesCount\x12\x37.org.dash.platform.dapi.v0.GetShieldedNotesCountRequest\x1a\x38.org.dash.platform.dapi.v0.GetShieldedNotesCountResponse\x12\x8a\x01\n\x15getShieldedNullifiers\x12\x37.org.dash.platform.dapi.v0.GetShieldedNullifiersRequest\x1a\x38.org.dash.platform.dapi.v0.GetShieldedNullifiersResponseb\x06proto3' , dependencies=[google_dot_protobuf_dot_wrappers__pb2.DESCRIPTOR,google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,]) @@ -62,8 +62,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=79514, - serialized_end=79604, + serialized_start=79570, + serialized_end=79660, ) _sym_db.RegisterEnumDescriptor(_KEYPURPOSE) @@ -98,8 +98,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=79607, - serialized_end=79792, + serialized_start=79663, + serialized_end=79848, ) _sym_db.RegisterEnumDescriptor(_CONTRACTMODERATIONLIST) @@ -165,8 +165,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=23228, - serialized_end=23276, + serialized_start=23284, + serialized_end=23332, ) _sym_db.RegisterEnumDescriptor(_GETDOCUMENTSREQUEST_TIMERANGESELECTION_SELECTOR) @@ -195,8 +195,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=23697, - serialized_end=23736, + serialized_start=23753, + serialized_end=23792, ) _sym_db.RegisterEnumDescriptor(_GETDOCUMENTSREQUEST_HAVINGAGGREGATE_FUNCTION) @@ -265,8 +265,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=24011, - serialized_end=24235, + serialized_start=24067, + serialized_end=24291, ) _sym_db.RegisterEnumDescriptor(_GETDOCUMENTSREQUEST_HAVINGCLAUSE_OPERATOR) @@ -310,8 +310,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=25436, - serialized_end=25508, + serialized_start=25492, + serialized_end=25564, ) _sym_db.RegisterEnumDescriptor(_GETDOCUMENTSREQUEST_GETDOCUMENTSREQUESTV1_SELECT_FUNCTION) @@ -335,8 +335,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=26086, - serialized_end=26118, + serialized_start=26142, + serialized_end=26174, ) _sym_db.RegisterEnumDescriptor(_GETDOCUMENTSREQUEST_GETDOCUMENTSREQUESTV1_SUBQUERY_KIND) @@ -410,8 +410,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=26161, - serialized_end=26411, + serialized_start=26217, + serialized_end=26467, ) _sym_db.RegisterEnumDescriptor(_GETDOCUMENTSREQUEST_WHEREOPERATOR) @@ -440,8 +440,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=42224, - serialized_end=42297, + serialized_start=42280, + serialized_end=42353, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEVOTESTATEREQUEST_GETCONTESTEDRESOURCEVOTESTATEREQUESTV0_RESULTTYPE) @@ -470,8 +470,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=43219, - serialized_end=43298, + serialized_start=43275, + serialized_end=43354, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_FINISHEDVOTEINFO_FINISHEDVOTEOUTCOME) @@ -500,8 +500,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=46927, - serialized_end=46988, + serialized_start=46983, + serialized_end=47044, ) _sym_db.RegisterEnumDescriptor(_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_RESOURCEVOTECHOICE_VOTECHOICETYPE) @@ -525,8 +525,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=65552, - serialized_end=65590, + serialized_start=65608, + serialized_end=65646, ) _sym_db.RegisterEnumDescriptor(_GETGROUPACTIONSREQUEST_ACTIONSTATUS) @@ -550,8 +550,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=66837, - serialized_end=66872, + serialized_start=66893, + serialized_end=66928, ) _sym_db.RegisterEnumDescriptor(_GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_EMERGENCYACTIONEVENT_ACTIONTYPE) @@ -575,8 +575,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=65552, - serialized_end=65590, + serialized_start=65608, + serialized_end=65646, ) _sym_db.RegisterEnumDescriptor(_GETGROUPACTIONSIGNERSREQUEST_ACTIONSTATUS) @@ -4466,6 +4466,13 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='reason_document_id', full_name='org.dash.platform.dapi.v0.ContractModerationReason.reason_document_id', index=3, + number=4, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), ], extensions=[ ], @@ -4482,9 +4489,14 @@ index=0, containing_type=None, create_key=_descriptor._internal_create_key, fields=[]), + _descriptor.OneofDescriptor( + name='_reason_document_id', full_name='org.dash.platform.dapi.v0.ContractModerationReason._reason_document_id', + index=1, containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[]), ], serialized_start=13923, - serialized_end=14065, + serialized_end=14121, ) @@ -4522,8 +4534,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14067, - serialized_end=14172, + serialized_start=14123, + serialized_end=14228, ) @@ -4575,8 +4587,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=14328, - serialized_end=14489, + serialized_start=14384, + serialized_end=14545, ) _GETCONTRACTMODERATIONSTATUSREQUEST = _descriptor.Descriptor( @@ -4611,8 +4623,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=14175, - serialized_end=14500, + serialized_start=14231, + serialized_end=14556, ) @@ -4698,8 +4710,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=14659, - serialized_end=15095, + serialized_start=14715, + serialized_end=15151, ) _GETCONTRACTMODERATIONSTATUSRESPONSE_GETCONTRACTMODERATIONSTATUSRESPONSEV0 = _descriptor.Descriptor( @@ -4748,8 +4760,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=15098, - serialized_end=15368, + serialized_start=15154, + serialized_end=15424, ) _GETCONTRACTMODERATIONSTATUSRESPONSE = _descriptor.Descriptor( @@ -4784,8 +4796,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=14503, - serialized_end=15379, + serialized_start=14559, + serialized_end=15435, ) @@ -4854,8 +4866,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=15538, - serialized_end=15750, + serialized_start=15594, + serialized_end=15806, ) _GETCONTRACTMODERATIONENTRIESREQUEST = _descriptor.Descriptor( @@ -4890,8 +4902,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=15382, - serialized_end=15761, + serialized_start=15438, + serialized_end=15817, ) @@ -4948,8 +4960,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=15923, - serialized_end=16130, + serialized_start=15979, + serialized_end=16186, ) _GETCONTRACTMODERATIONENTRIESRESPONSE_CONTRACTMODERATIONENTRIES = _descriptor.Descriptor( @@ -4979,8 +4991,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=16133, - serialized_end=16266, + serialized_start=16189, + serialized_end=16322, ) _GETCONTRACTMODERATIONENTRIESRESPONSE_GETCONTRACTMODERATIONENTRIESRESPONSEV0 = _descriptor.Descriptor( @@ -5029,8 +5041,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=16269, - serialized_end=16543, + serialized_start=16325, + serialized_end=16599, ) _GETCONTRACTMODERATIONENTRIESRESPONSE = _descriptor.Descriptor( @@ -5065,8 +5077,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=15764, - serialized_end=16554, + serialized_start=15820, + serialized_end=16610, ) @@ -5097,8 +5109,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=16709, - serialized_end=16744, + serialized_start=16765, + serialized_end=16800, ) _GETCONTRACTDOCUMENTREMOVALSREQUEST_PAGE = _descriptor.Descriptor( @@ -5145,8 +5157,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=16746, - serialized_end=16824, + serialized_start=16802, + serialized_end=16880, ) _GETCONTRACTDOCUMENTREMOVALSREQUEST_GETCONTRACTDOCUMENTREMOVALSREQUESTV0 = _descriptor.Descriptor( @@ -5209,8 +5221,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=16827, - serialized_end=17125, + serialized_start=16883, + serialized_end=17181, ) _GETCONTRACTDOCUMENTREMOVALSREQUEST = _descriptor.Descriptor( @@ -5245,8 +5257,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=16557, - serialized_end=17136, + serialized_start=16613, + serialized_end=17192, ) @@ -5284,8 +5296,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=17294, - serialized_end=17366, + serialized_start=17350, + serialized_end=17422, ) _GETCONTRACTDOCUMENTREMOVALSRESPONSE_CONTRACTDOCUMENTREMOVAL = _descriptor.Descriptor( @@ -5357,8 +5369,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=17369, - serialized_end=17689, + serialized_start=17425, + serialized_end=17745, ) _GETCONTRACTDOCUMENTREMOVALSRESPONSE_CONTRACTDOCUMENTREMOVALS = _descriptor.Descriptor( @@ -5388,8 +5400,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=17692, - serialized_end=17824, + serialized_start=17748, + serialized_end=17880, ) _GETCONTRACTDOCUMENTREMOVALSRESPONSE_GETCONTRACTDOCUMENTREMOVALSRESPONSEV0 = _descriptor.Descriptor( @@ -5438,8 +5450,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=17827, - serialized_end=18099, + serialized_start=17883, + serialized_end=18155, ) _GETCONTRACTDOCUMENTREMOVALSRESPONSE = _descriptor.Descriptor( @@ -5474,8 +5486,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=17139, - serialized_end=18110, + serialized_start=17195, + serialized_end=18166, ) @@ -5513,8 +5525,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=18238, - serialized_end=18303, + serialized_start=18294, + serialized_end=18359, ) _GETCONTRACTFEEPOTSREQUEST = _descriptor.Descriptor( @@ -5549,8 +5561,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=18113, - serialized_end=18314, + serialized_start=18169, + serialized_end=18370, ) @@ -5595,8 +5607,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=18445, - serialized_end=18527, + serialized_start=18501, + serialized_end=18583, ) _GETCONTRACTFEEPOTSRESPONSE_CONTRACTFEEPOT = _descriptor.Descriptor( @@ -5633,8 +5645,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=18530, - serialized_end=18666, + serialized_start=18586, + serialized_end=18722, ) _GETCONTRACTFEEPOTSRESPONSE_CONTRACTFEEPOTS = _descriptor.Descriptor( @@ -5671,8 +5683,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=18669, - serialized_end=18861, + serialized_start=18725, + serialized_end=18917, ) _GETCONTRACTFEEPOTSRESPONSE_GETCONTRACTFEEPOTSRESPONSEV0 = _descriptor.Descriptor( @@ -5721,8 +5733,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=18864, - serialized_end=19105, + serialized_start=18920, + serialized_end=19161, ) _GETCONTRACTFEEPOTSRESPONSE = _descriptor.Descriptor( @@ -5757,8 +5769,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=18317, - serialized_end=19116, + serialized_start=18373, + serialized_end=19172, ) @@ -5796,8 +5808,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=19274, - serialized_end=19349, + serialized_start=19330, + serialized_end=19405, ) _GETCONTRACTGROUPSFORCONTRACTREQUEST = _descriptor.Descriptor( @@ -5832,8 +5844,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19119, - serialized_end=19360, + serialized_start=19175, + serialized_end=19416, ) @@ -5871,8 +5883,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=19521, - serialized_end=19602, + serialized_start=19577, + serialized_end=19658, ) _GETCONTRACTGROUPSFORCONTRACTRESPONSE_TOKENMEMBERSHIPS = _descriptor.Descriptor( @@ -5909,8 +5921,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=19604, - serialized_end=19674, + serialized_start=19660, + serialized_end=19730, ) _GETCONTRACTGROUPSFORCONTRACTRESPONSE_CONTRACTGROUPMEMBERSHIPS = _descriptor.Descriptor( @@ -5954,8 +5966,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=19677, - serialized_end=19942, + serialized_start=19733, + serialized_end=19998, ) _GETCONTRACTGROUPSFORCONTRACTRESPONSE_GETCONTRACTGROUPSFORCONTRACTRESPONSEV0 = _descriptor.Descriptor( @@ -6004,8 +6016,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19945, - serialized_end=20237, + serialized_start=20001, + serialized_end=20293, ) _GETCONTRACTGROUPSFORCONTRACTRESPONSE = _descriptor.Descriptor( @@ -6040,8 +6052,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=19363, - serialized_end=20248, + serialized_start=19419, + serialized_end=20304, ) @@ -6079,8 +6091,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=20370, - serialized_end=20425, + serialized_start=20426, + serialized_end=20481, ) _GETDATACONTRACTSREQUEST = _descriptor.Descriptor( @@ -6115,8 +6127,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=20251, - serialized_end=20436, + serialized_start=20307, + serialized_end=20492, ) @@ -6185,8 +6197,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=20580, - serialized_end=20729, + serialized_start=20636, + serialized_end=20785, ) _GETDATACONTRACTSBYRANGEREQUEST = _descriptor.Descriptor( @@ -6221,8 +6233,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=20439, - serialized_end=20740, + serialized_start=20495, + serialized_end=20796, ) @@ -6260,8 +6272,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=20865, - serialized_end=20956, + serialized_start=20921, + serialized_end=21012, ) _GETDATACONTRACTSRESPONSE_DATACONTRACTS = _descriptor.Descriptor( @@ -6291,8 +6303,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=20958, - serialized_end=21075, + serialized_start=21014, + serialized_end=21131, ) _GETDATACONTRACTSRESPONSE_GETDATACONTRACTSRESPONSEV0 = _descriptor.Descriptor( @@ -6341,8 +6353,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=21078, - serialized_end=21323, + serialized_start=21134, + serialized_end=21379, ) _GETDATACONTRACTSRESPONSE = _descriptor.Descriptor( @@ -6377,8 +6389,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=20743, - serialized_end=21334, + serialized_start=20799, + serialized_end=21390, ) @@ -6437,8 +6449,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=21475, - serialized_end=21651, + serialized_start=21531, + serialized_end=21707, ) _GETDATACONTRACTHISTORYREQUEST = _descriptor.Descriptor( @@ -6473,8 +6485,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=21337, - serialized_end=21662, + serialized_start=21393, + serialized_end=21718, ) @@ -6512,8 +6524,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=22102, - serialized_end=22161, + serialized_start=22158, + serialized_end=22217, ) _GETDATACONTRACTHISTORYRESPONSE_GETDATACONTRACTHISTORYRESPONSEV0_DATACONTRACTHISTORY = _descriptor.Descriptor( @@ -6543,8 +6555,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=22164, - serialized_end=22334, + serialized_start=22220, + serialized_end=22390, ) _GETDATACONTRACTHISTORYRESPONSE_GETDATACONTRACTHISTORYRESPONSEV0 = _descriptor.Descriptor( @@ -6593,8 +6605,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=21806, - serialized_end=22344, + serialized_start=21862, + serialized_end=22400, ) _GETDATACONTRACTHISTORYRESPONSE = _descriptor.Descriptor( @@ -6629,8 +6641,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=21665, - serialized_end=22355, + serialized_start=21721, + serialized_end=22411, ) @@ -6661,8 +6673,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=22827, - serialized_end=22921, + serialized_start=22883, + serialized_end=22977, ) _GETDOCUMENTSREQUEST_DOCUMENTFIELDVALUE = _descriptor.Descriptor( @@ -6746,8 +6758,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=22550, - serialized_end=22932, + serialized_start=22606, + serialized_end=22988, ) _GETDOCUMENTSREQUEST_TIMERANGESELECTION_GRID = _descriptor.Descriptor( @@ -6791,8 +6803,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=23164, - serialized_end=23226, + serialized_start=23220, + serialized_end=23282, ) _GETDOCUMENTSREQUEST_TIMERANGESELECTION = _descriptor.Descriptor( @@ -6842,8 +6854,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=22935, - serialized_end=23289, + serialized_start=22991, + serialized_end=23345, ) _GETDOCUMENTSREQUEST_WHERECLAUSE = _descriptor.Descriptor( @@ -6894,8 +6906,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=23292, - serialized_end=23569, + serialized_start=23348, + serialized_end=23625, ) _GETDOCUMENTSREQUEST_HAVINGAGGREGATE = _descriptor.Descriptor( @@ -6933,8 +6945,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=23572, - serialized_end=23736, + serialized_start=23628, + serialized_end=23792, ) _GETDOCUMENTSREQUEST_HAVINGCLAUSE = _descriptor.Descriptor( @@ -6984,8 +6996,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=23739, - serialized_end=24244, + serialized_start=23795, + serialized_end=24300, ) _GETDOCUMENTSREQUEST_ORDERCLAUSE = _descriptor.Descriptor( @@ -7034,8 +7046,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=24247, - serialized_end=24391, + serialized_start=24303, + serialized_end=24447, ) _GETDOCUMENTSREQUEST_GETDOCUMENTSREQUESTV0 = _descriptor.Descriptor( @@ -7119,8 +7131,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=24394, - serialized_end=24581, + serialized_start=24450, + serialized_end=24637, ) _GETDOCUMENTSREQUEST_GETDOCUMENTSREQUESTV1_SELECT = _descriptor.Descriptor( @@ -7158,8 +7170,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=25307, - serialized_end=25508, + serialized_start=25363, + serialized_end=25564, ) _GETDOCUMENTSREQUEST_GETDOCUMENTSREQUESTV1_CHAINEDJOIN = _descriptor.Descriptor( @@ -7196,8 +7208,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=25510, - serialized_end=25575, + serialized_start=25566, + serialized_end=25631, ) _GETDOCUMENTSREQUEST_GETDOCUMENTSREQUESTV1_SUBQUERY_BINDING = _descriptor.Descriptor( @@ -7241,8 +7253,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=26019, - serialized_end=26084, + serialized_start=26075, + serialized_end=26140, ) _GETDOCUMENTSREQUEST_GETDOCUMENTSREQUESTV1_SUBQUERY = _descriptor.Descriptor( @@ -7320,8 +7332,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=25578, - serialized_end=26128, + serialized_start=25634, + serialized_end=26184, ) _GETDOCUMENTSREQUEST_GETDOCUMENTSREQUESTV1 = _descriptor.Descriptor( @@ -7457,8 +7469,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=24584, - serialized_end=26158, + serialized_start=24640, + serialized_end=26214, ) _GETDOCUMENTSREQUEST = _descriptor.Descriptor( @@ -7501,8 +7513,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=22358, - serialized_end=26422, + serialized_start=22414, + serialized_end=26478, ) @@ -7533,8 +7545,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=26865, - serialized_end=26895, + serialized_start=26921, + serialized_end=26951, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV0 = _descriptor.Descriptor( @@ -7583,8 +7595,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=26622, - serialized_end=26905, + serialized_start=26678, + serialized_end=26961, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_DOCUMENTS = _descriptor.Descriptor( @@ -7614,8 +7626,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=26865, - serialized_end=26895, + serialized_start=26921, + serialized_end=26951, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_COUNTENTRY = _descriptor.Descriptor( @@ -7664,8 +7676,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=27179, - serialized_end=27255, + serialized_start=27235, + serialized_end=27311, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_COUNTENTRIES = _descriptor.Descriptor( @@ -7695,8 +7707,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=27257, - serialized_end=27371, + serialized_start=27313, + serialized_end=27427, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_COUNTRESULTS = _descriptor.Descriptor( @@ -7738,8 +7750,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=27374, - serialized_end=27534, + serialized_start=27430, + serialized_end=27590, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_SUMENTRY = _descriptor.Descriptor( @@ -7788,8 +7800,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=27536, - serialized_end=27608, + serialized_start=27592, + serialized_end=27664, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_SUMENTRIES = _descriptor.Descriptor( @@ -7819,8 +7831,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=27610, - serialized_end=27720, + serialized_start=27666, + serialized_end=27776, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_SUMRESULTS = _descriptor.Descriptor( @@ -7862,8 +7874,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=27723, - serialized_end=27877, + serialized_start=27779, + serialized_end=27933, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_AVERAGEENTRY = _descriptor.Descriptor( @@ -7919,8 +7931,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=27879, - serialized_end=27974, + serialized_start=27935, + serialized_end=28030, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_AVERAGEENTRIES = _descriptor.Descriptor( @@ -7950,8 +7962,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=27976, - serialized_end=28094, + serialized_start=28032, + serialized_end=28150, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_AVERAGEAGGREGATE = _descriptor.Descriptor( @@ -7988,8 +8000,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=28096, - serialized_end=28150, + serialized_start=28152, + serialized_end=28206, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_AVERAGERESULTS = _descriptor.Descriptor( @@ -8031,8 +8043,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=28153, - serialized_end=28404, + serialized_start=28209, + serialized_end=28460, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RANKEDENTRY = _descriptor.Descriptor( @@ -8100,8 +8112,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=28406, - serialized_end=28528, + serialized_start=28462, + serialized_end=28584, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RANKEDENTRIES = _descriptor.Descriptor( @@ -8143,8 +8155,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=28531, - serialized_end=28685, + serialized_start=28587, + serialized_end=28741, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_RESULTDATA = _descriptor.Descriptor( @@ -8221,8 +8233,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=28688, - serialized_end=29447, + serialized_start=28744, + serialized_end=29503, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_CHAINEDDOCUMENTS = _descriptor.Descriptor( @@ -8266,8 +8278,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=29449, - serialized_end=29544, + serialized_start=29505, + serialized_end=29600, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_COMPOSITEDOCUMENTS_SUBQUERYRESULT = _descriptor.Descriptor( @@ -8316,8 +8328,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=29721, - serialized_end=29974, + serialized_start=29777, + serialized_end=30030, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1_COMPOSITEDOCUMENTS = _descriptor.Descriptor( @@ -8354,8 +8366,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=29547, - serialized_end=29974, + serialized_start=29603, + serialized_end=30030, ) _GETDOCUMENTSRESPONSE_GETDOCUMENTSRESPONSEV1 = _descriptor.Descriptor( @@ -8404,8 +8416,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=26908, - serialized_end=29984, + serialized_start=26964, + serialized_end=30040, ) _GETDOCUMENTSRESPONSE = _descriptor.Descriptor( @@ -8447,8 +8459,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=26425, - serialized_end=29995, + serialized_start=26481, + serialized_end=30051, ) @@ -8521,8 +8533,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=30124, - serialized_end=30359, + serialized_start=30180, + serialized_end=30415, ) _GETDOCUMENTHISTORYREQUEST = _descriptor.Descriptor( @@ -8557,8 +8569,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=29998, - serialized_end=30370, + serialized_start=30054, + serialized_end=30426, ) @@ -8596,8 +8608,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=30776, - serialized_end=30831, + serialized_start=30832, + serialized_end=30887, ) _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0_DOCUMENTHISTORY = _descriptor.Descriptor( @@ -8627,8 +8639,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=30834, - serialized_end=30983, + serialized_start=30890, + serialized_end=31039, ) _GETDOCUMENTHISTORYRESPONSE_GETDOCUMENTHISTORYRESPONSEV0 = _descriptor.Descriptor( @@ -8677,8 +8689,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=30502, - serialized_end=30993, + serialized_start=30558, + serialized_end=31049, ) _GETDOCUMENTHISTORYRESPONSE = _descriptor.Descriptor( @@ -8713,8 +8725,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=30373, - serialized_end=31004, + serialized_start=30429, + serialized_end=31060, ) @@ -8752,8 +8764,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=31156, - serialized_end=31233, + serialized_start=31212, + serialized_end=31289, ) _GETIDENTITYBYPUBLICKEYHASHREQUEST = _descriptor.Descriptor( @@ -8788,8 +8800,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=31007, - serialized_end=31244, + serialized_start=31063, + serialized_end=31300, ) @@ -8839,8 +8851,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=31400, - serialized_end=31582, + serialized_start=31456, + serialized_end=31638, ) _GETIDENTITYBYPUBLICKEYHASHRESPONSE = _descriptor.Descriptor( @@ -8875,8 +8887,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=31247, - serialized_end=31593, + serialized_start=31303, + serialized_end=31649, ) @@ -8926,8 +8938,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=31774, - serialized_end=31902, + serialized_start=31830, + serialized_end=31958, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHREQUEST = _descriptor.Descriptor( @@ -8962,8 +8974,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=31596, - serialized_end=31913, + serialized_start=31652, + serialized_end=31969, ) @@ -8999,8 +9011,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=32526, - serialized_end=32580, + serialized_start=32582, + serialized_end=32636, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSE_GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSEV0_IDENTITYPROVEDRESPONSE = _descriptor.Descriptor( @@ -9042,8 +9054,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=32583, - serialized_end=32749, + serialized_start=32639, + serialized_end=32805, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSE_GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSEV0 = _descriptor.Descriptor( @@ -9092,8 +9104,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=32097, - serialized_end=32759, + serialized_start=32153, + serialized_end=32815, ) _GETIDENTITYBYNONUNIQUEPUBLICKEYHASHRESPONSE = _descriptor.Descriptor( @@ -9128,8 +9140,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=31916, - serialized_end=32770, + serialized_start=31972, + serialized_end=32826, ) @@ -9174,8 +9186,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=32928, - serialized_end=33043, + serialized_start=32984, + serialized_end=33099, ) _WAITFORSTATETRANSITIONRESULTREQUEST = _descriptor.Descriptor( @@ -9210,8 +9222,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=32773, - serialized_end=33054, + serialized_start=32829, + serialized_end=33110, ) @@ -9242,8 +9254,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=33215, - serialized_end=33267, + serialized_start=33271, + serialized_end=33323, ) _WAITFORSTATETRANSITIONRESULTRESPONSE_WAITFORSTATETRANSITIONRESULTRESPONSEV0 = _descriptor.Descriptor( @@ -9299,8 +9311,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=33270, - serialized_end=33636, + serialized_start=33326, + serialized_end=33692, ) _WAITFORSTATETRANSITIONRESULTRESPONSE = _descriptor.Descriptor( @@ -9335,8 +9347,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=33057, - serialized_end=33647, + serialized_start=33113, + serialized_end=33703, ) @@ -9374,8 +9386,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=33775, - serialized_end=33835, + serialized_start=33831, + serialized_end=33891, ) _GETCONSENSUSPARAMSREQUEST = _descriptor.Descriptor( @@ -9410,8 +9422,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=33650, - serialized_end=33846, + serialized_start=33706, + serialized_end=33902, ) @@ -9456,8 +9468,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=33977, - serialized_end=34057, + serialized_start=34033, + serialized_end=34113, ) _GETCONSENSUSPARAMSRESPONSE_CONSENSUSPARAMSEVIDENCE = _descriptor.Descriptor( @@ -9501,8 +9513,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=34059, - serialized_end=34157, + serialized_start=34115, + serialized_end=34213, ) _GETCONSENSUSPARAMSRESPONSE_GETCONSENSUSPARAMSRESPONSEV0 = _descriptor.Descriptor( @@ -9539,8 +9551,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=34160, - serialized_end=34378, + serialized_start=34216, + serialized_end=34434, ) _GETCONSENSUSPARAMSRESPONSE = _descriptor.Descriptor( @@ -9575,8 +9587,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=33849, - serialized_end=34389, + serialized_start=33905, + serialized_end=34445, ) @@ -9607,8 +9619,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=34553, - serialized_end=34609, + serialized_start=34609, + serialized_end=34665, ) _GETPROTOCOLVERSIONUPGRADESTATEREQUEST = _descriptor.Descriptor( @@ -9643,8 +9655,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=34392, - serialized_end=34620, + serialized_start=34448, + serialized_end=34676, ) @@ -9675,8 +9687,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=35085, - serialized_end=35235, + serialized_start=35141, + serialized_end=35291, ) _GETPROTOCOLVERSIONUPGRADESTATERESPONSE_GETPROTOCOLVERSIONUPGRADESTATERESPONSEV0_VERSIONENTRY = _descriptor.Descriptor( @@ -9713,8 +9725,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=35237, - serialized_end=35295, + serialized_start=35293, + serialized_end=35351, ) _GETPROTOCOLVERSIONUPGRADESTATERESPONSE_GETPROTOCOLVERSIONUPGRADESTATERESPONSEV0 = _descriptor.Descriptor( @@ -9763,8 +9775,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=34788, - serialized_end=35305, + serialized_start=34844, + serialized_end=35361, ) _GETPROTOCOLVERSIONUPGRADESTATERESPONSE = _descriptor.Descriptor( @@ -9799,8 +9811,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=34623, - serialized_end=35316, + serialized_start=34679, + serialized_end=35372, ) @@ -9845,8 +9857,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=35496, - serialized_end=35599, + serialized_start=35552, + serialized_end=35655, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSREQUEST = _descriptor.Descriptor( @@ -9881,8 +9893,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=35319, - serialized_end=35610, + serialized_start=35375, + serialized_end=35666, ) @@ -9913,8 +9925,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=36113, - serialized_end=36288, + serialized_start=36169, + serialized_end=36344, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSE_GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSEV0_VERSIONSIGNAL = _descriptor.Descriptor( @@ -9951,8 +9963,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=36290, - serialized_end=36343, + serialized_start=36346, + serialized_end=36399, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSE_GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSEV0 = _descriptor.Descriptor( @@ -10001,8 +10013,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=35794, - serialized_end=36353, + serialized_start=35850, + serialized_end=36409, ) _GETPROTOCOLVERSIONUPGRADEVOTESTATUSRESPONSE = _descriptor.Descriptor( @@ -10037,8 +10049,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=35613, - serialized_end=36364, + serialized_start=35669, + serialized_end=36420, ) @@ -10090,8 +10102,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=36477, - serialized_end=36601, + serialized_start=36533, + serialized_end=36657, ) _GETEPOCHSINFOREQUEST = _descriptor.Descriptor( @@ -10126,8 +10138,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=36367, - serialized_end=36612, + serialized_start=36423, + serialized_end=36668, ) @@ -10158,8 +10170,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=36973, - serialized_end=37090, + serialized_start=37029, + serialized_end=37146, ) _GETEPOCHSINFORESPONSE_GETEPOCHSINFORESPONSEV0_EPOCHINFO = _descriptor.Descriptor( @@ -10224,8 +10236,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=37093, - serialized_end=37259, + serialized_start=37149, + serialized_end=37315, ) _GETEPOCHSINFORESPONSE_GETEPOCHSINFORESPONSEV0 = _descriptor.Descriptor( @@ -10274,8 +10286,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=36729, - serialized_end=37269, + serialized_start=36785, + serialized_end=37325, ) _GETEPOCHSINFORESPONSE = _descriptor.Descriptor( @@ -10310,8 +10322,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=36615, - serialized_end=37280, + serialized_start=36671, + serialized_end=37336, ) @@ -10370,8 +10382,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=37421, - serialized_end=37591, + serialized_start=37477, + serialized_end=37647, ) _GETFINALIZEDEPOCHINFOSREQUEST = _descriptor.Descriptor( @@ -10406,8 +10418,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=37283, - serialized_end=37602, + serialized_start=37339, + serialized_end=37658, ) @@ -10438,8 +10450,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=38028, - serialized_end=38192, + serialized_start=38084, + serialized_end=38248, ) _GETFINALIZEDEPOCHINFOSRESPONSE_GETFINALIZEDEPOCHINFOSRESPONSEV0_FINALIZEDEPOCHINFO = _descriptor.Descriptor( @@ -10553,8 +10565,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=38195, - serialized_end=38738, + serialized_start=38251, + serialized_end=38794, ) _GETFINALIZEDEPOCHINFOSRESPONSE_GETFINALIZEDEPOCHINFOSRESPONSEV0_BLOCKPROPOSER = _descriptor.Descriptor( @@ -10591,8 +10603,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=38740, - serialized_end=38797, + serialized_start=38796, + serialized_end=38853, ) _GETFINALIZEDEPOCHINFOSRESPONSE_GETFINALIZEDEPOCHINFOSRESPONSEV0 = _descriptor.Descriptor( @@ -10641,8 +10653,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=37746, - serialized_end=38807, + serialized_start=37802, + serialized_end=38863, ) _GETFINALIZEDEPOCHINFOSRESPONSE = _descriptor.Descriptor( @@ -10677,8 +10689,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=37605, - serialized_end=38818, + serialized_start=37661, + serialized_end=38874, ) @@ -10716,8 +10728,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=39313, - serialized_end=39382, + serialized_start=39369, + serialized_end=39438, ) _GETCONTESTEDRESOURCESREQUEST_GETCONTESTEDRESOURCESREQUESTV0 = _descriptor.Descriptor( @@ -10813,8 +10825,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=38956, - serialized_end=39416, + serialized_start=39012, + serialized_end=39472, ) _GETCONTESTEDRESOURCESREQUEST = _descriptor.Descriptor( @@ -10849,8 +10861,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=38821, - serialized_end=39427, + serialized_start=38877, + serialized_end=39483, ) @@ -10881,8 +10893,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=39869, - serialized_end=39929, + serialized_start=39925, + serialized_end=39985, ) _GETCONTESTEDRESOURCESRESPONSE_GETCONTESTEDRESOURCESRESPONSEV0 = _descriptor.Descriptor( @@ -10931,8 +10943,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=39568, - serialized_end=39939, + serialized_start=39624, + serialized_end=39995, ) _GETCONTESTEDRESOURCESRESPONSE = _descriptor.Descriptor( @@ -10967,8 +10979,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=39430, - serialized_end=39950, + serialized_start=39486, + serialized_end=40006, ) @@ -11006,8 +11018,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=40463, - serialized_end=40536, + serialized_start=40519, + serialized_end=40592, ) _GETVOTEPOLLSBYENDDATEREQUEST_GETVOTEPOLLSBYENDDATEREQUESTV0_ENDATTIMEINFO = _descriptor.Descriptor( @@ -11044,8 +11056,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=40538, - serialized_end=40605, + serialized_start=40594, + serialized_end=40661, ) _GETVOTEPOLLSBYENDDATEREQUEST_GETVOTEPOLLSBYENDDATEREQUESTV0 = _descriptor.Descriptor( @@ -11130,8 +11142,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=40088, - serialized_end=40664, + serialized_start=40144, + serialized_end=40720, ) _GETVOTEPOLLSBYENDDATEREQUEST = _descriptor.Descriptor( @@ -11166,8 +11178,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=39953, - serialized_end=40675, + serialized_start=40009, + serialized_end=40731, ) @@ -11205,8 +11217,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=41124, - serialized_end=41210, + serialized_start=41180, + serialized_end=41266, ) _GETVOTEPOLLSBYENDDATERESPONSE_GETVOTEPOLLSBYENDDATERESPONSEV0_SERIALIZEDVOTEPOLLSBYTIMESTAMPS = _descriptor.Descriptor( @@ -11243,8 +11255,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=41213, - serialized_end=41428, + serialized_start=41269, + serialized_end=41484, ) _GETVOTEPOLLSBYENDDATERESPONSE_GETVOTEPOLLSBYENDDATERESPONSEV0 = _descriptor.Descriptor( @@ -11293,8 +11305,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=40816, - serialized_end=41438, + serialized_start=40872, + serialized_end=41494, ) _GETVOTEPOLLSBYENDDATERESPONSE = _descriptor.Descriptor( @@ -11329,8 +11341,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=40678, - serialized_end=41449, + serialized_start=40734, + serialized_end=41505, ) @@ -11368,8 +11380,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=42138, - serialized_end=42222, + serialized_start=42194, + serialized_end=42278, ) _GETCONTESTEDRESOURCEVOTESTATEREQUEST_GETCONTESTEDRESOURCEVOTESTATEREQUESTV0 = _descriptor.Descriptor( @@ -11466,8 +11478,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=41611, - serialized_end=42336, + serialized_start=41667, + serialized_end=42392, ) _GETCONTESTEDRESOURCEVOTESTATEREQUEST = _descriptor.Descriptor( @@ -11502,8 +11514,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=41452, - serialized_end=42347, + serialized_start=41508, + serialized_end=42403, ) @@ -11575,8 +11587,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=42847, - serialized_end=43321, + serialized_start=42903, + serialized_end=43377, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_CONTESTEDRESOURCECONTENDERS = _descriptor.Descriptor( @@ -11642,8 +11654,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=43324, - serialized_end=43776, + serialized_start=43380, + serialized_end=43832, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0_CONTENDER = _descriptor.Descriptor( @@ -11697,8 +11709,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=43778, - serialized_end=43885, + serialized_start=43834, + serialized_end=43941, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE_GETCONTESTEDRESOURCEVOTESTATERESPONSEV0 = _descriptor.Descriptor( @@ -11747,8 +11759,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=42512, - serialized_end=43895, + serialized_start=42568, + serialized_end=43951, ) _GETCONTESTEDRESOURCEVOTESTATERESPONSE = _descriptor.Descriptor( @@ -11783,8 +11795,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=42350, - serialized_end=43906, + serialized_start=42406, + serialized_end=43962, ) @@ -11822,8 +11834,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=42138, - serialized_end=42222, + serialized_start=42194, + serialized_end=42278, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYREQUEST_GETCONTESTEDRESOURCEVOTERSFORIDENTITYREQUESTV0 = _descriptor.Descriptor( @@ -11919,8 +11931,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=44093, - serialized_end=44623, + serialized_start=44149, + serialized_end=44679, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYREQUEST = _descriptor.Descriptor( @@ -11955,8 +11967,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=43909, - serialized_end=44634, + serialized_start=43965, + serialized_end=44690, ) @@ -11994,8 +12006,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=45174, - serialized_end=45241, + serialized_start=45230, + serialized_end=45297, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSE_GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSEV0 = _descriptor.Descriptor( @@ -12044,8 +12056,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=44824, - serialized_end=45251, + serialized_start=44880, + serialized_end=45307, ) _GETCONTESTEDRESOURCEVOTERSFORIDENTITYRESPONSE = _descriptor.Descriptor( @@ -12080,8 +12092,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=44637, - serialized_end=45262, + serialized_start=44693, + serialized_end=45318, ) @@ -12119,8 +12131,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=45811, - serialized_end=45908, + serialized_start=45867, + serialized_end=45964, ) _GETCONTESTEDRESOURCEIDENTITYVOTESREQUEST_GETCONTESTEDRESOURCEIDENTITYVOTESREQUESTV0 = _descriptor.Descriptor( @@ -12190,8 +12202,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=45436, - serialized_end=45939, + serialized_start=45492, + serialized_end=45995, ) _GETCONTESTEDRESOURCEIDENTITYVOTESREQUEST = _descriptor.Descriptor( @@ -12226,8 +12238,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=45265, - serialized_end=45950, + serialized_start=45321, + serialized_end=46006, ) @@ -12265,8 +12277,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=46453, - serialized_end=46700, + serialized_start=46509, + serialized_end=46756, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_RESOURCEVOTECHOICE = _descriptor.Descriptor( @@ -12309,8 +12321,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=46703, - serialized_end=47004, + serialized_start=46759, + serialized_end=47060, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0_CONTESTEDRESOURCEIDENTITYVOTE = _descriptor.Descriptor( @@ -12361,8 +12373,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=47007, - serialized_end=47284, + serialized_start=47063, + serialized_end=47340, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE_GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSEV0 = _descriptor.Descriptor( @@ -12411,8 +12423,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=46127, - serialized_end=47294, + serialized_start=46183, + serialized_end=47350, ) _GETCONTESTEDRESOURCEIDENTITYVOTESRESPONSE = _descriptor.Descriptor( @@ -12447,8 +12459,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=45953, - serialized_end=47305, + serialized_start=46009, + serialized_end=47361, ) @@ -12486,8 +12498,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=47469, - serialized_end=47537, + serialized_start=47525, + serialized_end=47593, ) _GETPREFUNDEDSPECIALIZEDBALANCEREQUEST = _descriptor.Descriptor( @@ -12522,8 +12534,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=47308, - serialized_end=47548, + serialized_start=47364, + serialized_end=47604, ) @@ -12573,8 +12585,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=47716, - serialized_end=47905, + serialized_start=47772, + serialized_end=47961, ) _GETPREFUNDEDSPECIALIZEDBALANCERESPONSE = _descriptor.Descriptor( @@ -12609,8 +12621,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=47551, - serialized_end=47916, + serialized_start=47607, + serialized_end=47972, ) @@ -12641,8 +12653,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=48065, - serialized_end=48116, + serialized_start=48121, + serialized_end=48172, ) _GETTOTALCREDITSINPLATFORMREQUEST = _descriptor.Descriptor( @@ -12677,8 +12689,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=47919, - serialized_end=48127, + serialized_start=47975, + serialized_end=48183, ) @@ -12728,8 +12740,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=48280, - serialized_end=48464, + serialized_start=48336, + serialized_end=48520, ) _GETTOTALCREDITSINPLATFORMRESPONSE = _descriptor.Descriptor( @@ -12764,8 +12776,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=48130, - serialized_end=48475, + serialized_start=48186, + serialized_end=48531, ) @@ -12810,8 +12822,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=48594, - serialized_end=48663, + serialized_start=48650, + serialized_end=48719, ) _GETPATHELEMENTSREQUEST = _descriptor.Descriptor( @@ -12846,8 +12858,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=48478, - serialized_end=48674, + serialized_start=48534, + serialized_end=48730, ) @@ -12878,8 +12890,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=49047, - serialized_end=49075, + serialized_start=49103, + serialized_end=49131, ) _GETPATHELEMENTSRESPONSE_GETPATHELEMENTSRESPONSEV0 = _descriptor.Descriptor( @@ -12928,8 +12940,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=48797, - serialized_end=49085, + serialized_start=48853, + serialized_end=49141, ) _GETPATHELEMENTSRESPONSE = _descriptor.Descriptor( @@ -12964,8 +12976,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=48677, - serialized_end=49096, + serialized_start=48733, + serialized_end=49152, ) @@ -12989,8 +13001,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=49197, - serialized_end=49217, + serialized_start=49253, + serialized_end=49273, ) _GETSTATUSREQUEST = _descriptor.Descriptor( @@ -13025,8 +13037,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=49099, - serialized_end=49228, + serialized_start=49155, + serialized_end=49284, ) @@ -13081,8 +13093,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=50105, - serialized_end=50199, + serialized_start=50161, + serialized_end=50255, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION_PROTOCOL_TENDERDASH = _descriptor.Descriptor( @@ -13119,8 +13131,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=50432, - serialized_end=50472, + serialized_start=50488, + serialized_end=50528, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION_PROTOCOL_DRIVE = _descriptor.Descriptor( @@ -13164,8 +13176,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=50474, - serialized_end=50534, + serialized_start=50530, + serialized_end=50590, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION_PROTOCOL = _descriptor.Descriptor( @@ -13202,8 +13214,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=50202, - serialized_end=50534, + serialized_start=50258, + serialized_end=50590, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_VERSION = _descriptor.Descriptor( @@ -13240,8 +13252,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=49892, - serialized_end=50534, + serialized_start=49948, + serialized_end=50590, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_TIME = _descriptor.Descriptor( @@ -13307,8 +13319,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=50536, - serialized_end=50663, + serialized_start=50592, + serialized_end=50719, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_NODE = _descriptor.Descriptor( @@ -13350,8 +13362,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=50665, - serialized_end=50725, + serialized_start=50721, + serialized_end=50781, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_CHAIN = _descriptor.Descriptor( @@ -13442,8 +13454,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=50728, - serialized_end=51035, + serialized_start=50784, + serialized_end=51091, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_NETWORK = _descriptor.Descriptor( @@ -13487,8 +13499,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=51037, - serialized_end=51104, + serialized_start=51093, + serialized_end=51160, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0_STATESYNC = _descriptor.Descriptor( @@ -13567,8 +13579,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=51107, - serialized_end=51368, + serialized_start=51163, + serialized_end=51424, ) _GETSTATUSRESPONSE_GETSTATUSRESPONSEV0 = _descriptor.Descriptor( @@ -13633,8 +13645,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=49333, - serialized_end=51368, + serialized_start=49389, + serialized_end=51424, ) _GETSTATUSRESPONSE = _descriptor.Descriptor( @@ -13669,8 +13681,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=49231, - serialized_end=51379, + serialized_start=49287, + serialized_end=51435, ) @@ -13694,8 +13706,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=51516, - serialized_end=51548, + serialized_start=51572, + serialized_end=51604, ) _GETCURRENTQUORUMSINFOREQUEST = _descriptor.Descriptor( @@ -13730,8 +13742,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=51382, - serialized_end=51559, + serialized_start=51438, + serialized_end=51615, ) @@ -13776,8 +13788,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=51699, - serialized_end=51769, + serialized_start=51755, + serialized_end=51825, ) _GETCURRENTQUORUMSINFORESPONSE_VALIDATORSETV0 = _descriptor.Descriptor( @@ -13828,8 +13840,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=51772, - serialized_end=51947, + serialized_start=51828, + serialized_end=52003, ) _GETCURRENTQUORUMSINFORESPONSE_GETCURRENTQUORUMSINFORESPONSEV0 = _descriptor.Descriptor( @@ -13887,8 +13899,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=51950, - serialized_end=52224, + serialized_start=52006, + serialized_end=52280, ) _GETCURRENTQUORUMSINFORESPONSE = _descriptor.Descriptor( @@ -13923,8 +13935,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=51562, - serialized_end=52235, + serialized_start=51618, + serialized_end=52291, ) @@ -13969,8 +13981,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=52381, - serialized_end=52471, + serialized_start=52437, + serialized_end=52527, ) _GETIDENTITYTOKENBALANCESREQUEST = _descriptor.Descriptor( @@ -14005,8 +14017,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=52238, - serialized_end=52482, + serialized_start=52294, + serialized_end=52538, ) @@ -14049,8 +14061,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=52921, - serialized_end=52992, + serialized_start=52977, + serialized_end=53048, ) _GETIDENTITYTOKENBALANCESRESPONSE_GETIDENTITYTOKENBALANCESRESPONSEV0_TOKENBALANCES = _descriptor.Descriptor( @@ -14080,8 +14092,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=52995, - serialized_end=53149, + serialized_start=53051, + serialized_end=53205, ) _GETIDENTITYTOKENBALANCESRESPONSE_GETIDENTITYTOKENBALANCESRESPONSEV0 = _descriptor.Descriptor( @@ -14130,8 +14142,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=52632, - serialized_end=53159, + serialized_start=52688, + serialized_end=53215, ) _GETIDENTITYTOKENBALANCESRESPONSE = _descriptor.Descriptor( @@ -14166,8 +14178,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=52485, - serialized_end=53170, + serialized_start=52541, + serialized_end=53226, ) @@ -14212,8 +14224,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=53322, - serialized_end=53414, + serialized_start=53378, + serialized_end=53470, ) _GETIDENTITIESTOKENBALANCESREQUEST = _descriptor.Descriptor( @@ -14248,8 +14260,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=53173, - serialized_end=53425, + serialized_start=53229, + serialized_end=53481, ) @@ -14292,8 +14304,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=53893, - serialized_end=53975, + serialized_start=53949, + serialized_end=54031, ) _GETIDENTITIESTOKENBALANCESRESPONSE_GETIDENTITIESTOKENBALANCESRESPONSEV0_IDENTITYTOKENBALANCES = _descriptor.Descriptor( @@ -14323,8 +14335,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=53978, - serialized_end=54161, + serialized_start=54034, + serialized_end=54217, ) _GETIDENTITIESTOKENBALANCESRESPONSE_GETIDENTITIESTOKENBALANCESRESPONSEV0 = _descriptor.Descriptor( @@ -14373,8 +14385,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=53581, - serialized_end=54171, + serialized_start=53637, + serialized_end=54227, ) _GETIDENTITIESTOKENBALANCESRESPONSE = _descriptor.Descriptor( @@ -14409,8 +14421,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=53428, - serialized_end=54182, + serialized_start=53484, + serialized_end=54238, ) @@ -14455,8 +14467,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=54319, - serialized_end=54406, + serialized_start=54375, + serialized_end=54462, ) _GETIDENTITYTOKENINFOSREQUEST = _descriptor.Descriptor( @@ -14491,8 +14503,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=54185, - serialized_end=54417, + serialized_start=54241, + serialized_end=54473, ) @@ -14523,8 +14535,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=54831, - serialized_end=54871, + serialized_start=54887, + serialized_end=54927, ) _GETIDENTITYTOKENINFOSRESPONSE_GETIDENTITYTOKENINFOSRESPONSEV0_TOKENINFOENTRY = _descriptor.Descriptor( @@ -14566,8 +14578,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=54874, - serialized_end=55050, + serialized_start=54930, + serialized_end=55106, ) _GETIDENTITYTOKENINFOSRESPONSE_GETIDENTITYTOKENINFOSRESPONSEV0_TOKENINFOS = _descriptor.Descriptor( @@ -14597,8 +14609,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=55053, - serialized_end=55191, + serialized_start=55109, + serialized_end=55247, ) _GETIDENTITYTOKENINFOSRESPONSE_GETIDENTITYTOKENINFOSRESPONSEV0 = _descriptor.Descriptor( @@ -14647,8 +14659,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=54558, - serialized_end=55201, + serialized_start=54614, + serialized_end=55257, ) _GETIDENTITYTOKENINFOSRESPONSE = _descriptor.Descriptor( @@ -14683,8 +14695,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=54420, - serialized_end=55212, + serialized_start=54476, + serialized_end=55268, ) @@ -14729,8 +14741,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=55355, - serialized_end=55444, + serialized_start=55411, + serialized_end=55500, ) _GETIDENTITIESTOKENINFOSREQUEST = _descriptor.Descriptor( @@ -14765,8 +14777,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=55215, - serialized_end=55455, + serialized_start=55271, + serialized_end=55511, ) @@ -14797,8 +14809,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=54831, - serialized_end=54871, + serialized_start=54887, + serialized_end=54927, ) _GETIDENTITIESTOKENINFOSRESPONSE_GETIDENTITIESTOKENINFOSRESPONSEV0_TOKENINFOENTRY = _descriptor.Descriptor( @@ -14840,8 +14852,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=55942, - serialized_end=56125, + serialized_start=55998, + serialized_end=56181, ) _GETIDENTITIESTOKENINFOSRESPONSE_GETIDENTITIESTOKENINFOSRESPONSEV0_IDENTITYTOKENINFOS = _descriptor.Descriptor( @@ -14871,8 +14883,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=56128, - serialized_end=56279, + serialized_start=56184, + serialized_end=56335, ) _GETIDENTITIESTOKENINFOSRESPONSE_GETIDENTITIESTOKENINFOSRESPONSEV0 = _descriptor.Descriptor( @@ -14921,8 +14933,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=55602, - serialized_end=56289, + serialized_start=55658, + serialized_end=56345, ) _GETIDENTITIESTOKENINFOSRESPONSE = _descriptor.Descriptor( @@ -14957,8 +14969,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=55458, - serialized_end=56300, + serialized_start=55514, + serialized_end=56356, ) @@ -14996,8 +15008,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=56422, - serialized_end=56483, + serialized_start=56478, + serialized_end=56539, ) _GETTOKENSTATUSESREQUEST = _descriptor.Descriptor( @@ -15032,8 +15044,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=56303, - serialized_end=56494, + serialized_start=56359, + serialized_end=56550, ) @@ -15076,8 +15088,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=56884, - serialized_end=56952, + serialized_start=56940, + serialized_end=57008, ) _GETTOKENSTATUSESRESPONSE_GETTOKENSTATUSESRESPONSEV0_TOKENSTATUSES = _descriptor.Descriptor( @@ -15107,8 +15119,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=56955, - serialized_end=57091, + serialized_start=57011, + serialized_end=57147, ) _GETTOKENSTATUSESRESPONSE_GETTOKENSTATUSESRESPONSEV0 = _descriptor.Descriptor( @@ -15157,8 +15169,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=56620, - serialized_end=57101, + serialized_start=56676, + serialized_end=57157, ) _GETTOKENSTATUSESRESPONSE = _descriptor.Descriptor( @@ -15193,8 +15205,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=56497, - serialized_end=57112, + serialized_start=56553, + serialized_end=57168, ) @@ -15232,8 +15244,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=57270, - serialized_end=57343, + serialized_start=57326, + serialized_end=57399, ) _GETTOKENDIRECTPURCHASEPRICESREQUEST = _descriptor.Descriptor( @@ -15268,8 +15280,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=57115, - serialized_end=57354, + serialized_start=57171, + serialized_end=57410, ) @@ -15307,8 +15319,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=57844, - serialized_end=57895, + serialized_start=57900, + serialized_end=57951, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE_GETTOKENDIRECTPURCHASEPRICESRESPONSEV0_PRICINGSCHEDULE = _descriptor.Descriptor( @@ -15338,8 +15350,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=57898, - serialized_end=58065, + serialized_start=57954, + serialized_end=58121, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE_GETTOKENDIRECTPURCHASEPRICESRESPONSEV0_TOKENDIRECTPURCHASEPRICEENTRY = _descriptor.Descriptor( @@ -15388,8 +15400,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=58068, - serialized_end=58296, + serialized_start=58124, + serialized_end=58352, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE_GETTOKENDIRECTPURCHASEPRICESRESPONSEV0_TOKENDIRECTPURCHASEPRICES = _descriptor.Descriptor( @@ -15419,8 +15431,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=58299, - serialized_end=58499, + serialized_start=58355, + serialized_end=58555, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE_GETTOKENDIRECTPURCHASEPRICESRESPONSEV0 = _descriptor.Descriptor( @@ -15469,8 +15481,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=57516, - serialized_end=58509, + serialized_start=57572, + serialized_end=58565, ) _GETTOKENDIRECTPURCHASEPRICESRESPONSE = _descriptor.Descriptor( @@ -15505,8 +15517,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=57357, - serialized_end=58520, + serialized_start=57413, + serialized_end=58576, ) @@ -15544,8 +15556,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=58654, - serialized_end=58718, + serialized_start=58710, + serialized_end=58774, ) _GETTOKENCONTRACTINFOREQUEST = _descriptor.Descriptor( @@ -15580,8 +15592,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=58523, - serialized_end=58729, + serialized_start=58579, + serialized_end=58785, ) @@ -15619,8 +15631,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=59141, - serialized_end=59218, + serialized_start=59197, + serialized_end=59274, ) _GETTOKENCONTRACTINFORESPONSE_GETTOKENCONTRACTINFORESPONSEV0 = _descriptor.Descriptor( @@ -15669,8 +15681,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=58867, - serialized_end=59228, + serialized_start=58923, + serialized_end=59284, ) _GETTOKENCONTRACTINFORESPONSE = _descriptor.Descriptor( @@ -15705,8 +15717,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=58732, - serialized_end=59239, + serialized_start=58788, + serialized_end=59295, ) @@ -15761,8 +15773,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59672, - serialized_end=59826, + serialized_start=59728, + serialized_end=59882, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSREQUEST_GETTOKENPREPROGRAMMEDDISTRIBUTIONSREQUESTV0 = _descriptor.Descriptor( @@ -15823,8 +15835,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59416, - serialized_end=59854, + serialized_start=59472, + serialized_end=59910, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSREQUEST = _descriptor.Descriptor( @@ -15859,8 +15871,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59242, - serialized_end=59865, + serialized_start=59298, + serialized_end=59921, ) @@ -15898,8 +15910,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=60376, - serialized_end=60438, + serialized_start=60432, + serialized_end=60494, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSE_GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSEV0_TOKENTIMEDDISTRIBUTIONENTRY = _descriptor.Descriptor( @@ -15936,8 +15948,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=60441, - serialized_end=60653, + serialized_start=60497, + serialized_end=60709, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSE_GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSEV0_TOKENDISTRIBUTIONS = _descriptor.Descriptor( @@ -15967,8 +15979,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=60656, - serialized_end=60851, + serialized_start=60712, + serialized_end=60907, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSE_GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSEV0 = _descriptor.Descriptor( @@ -16017,8 +16029,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=60046, - serialized_end=60861, + serialized_start=60102, + serialized_end=60917, ) _GETTOKENPREPROGRAMMEDDISTRIBUTIONSRESPONSE = _descriptor.Descriptor( @@ -16053,8 +16065,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=59868, - serialized_end=60872, + serialized_start=59924, + serialized_end=60928, ) @@ -16092,8 +16104,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=61061, - serialized_end=61134, + serialized_start=61117, + serialized_end=61190, ) _GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMREQUEST_GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMREQUESTV0 = _descriptor.Descriptor( @@ -16149,8 +16161,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=61137, - serialized_end=61378, + serialized_start=61193, + serialized_end=61434, ) _GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMREQUEST = _descriptor.Descriptor( @@ -16185,8 +16197,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=60875, - serialized_end=61389, + serialized_start=60931, + serialized_end=61445, ) @@ -16243,8 +16255,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=61910, - serialized_end=62030, + serialized_start=61966, + serialized_end=62086, ) _GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMRESPONSE_GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMRESPONSEV0 = _descriptor.Descriptor( @@ -16293,8 +16305,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=61582, - serialized_end=62040, + serialized_start=61638, + serialized_end=62096, ) _GETTOKENPERPETUALDISTRIBUTIONLASTCLAIMRESPONSE = _descriptor.Descriptor( @@ -16329,8 +16341,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=61392, - serialized_end=62051, + serialized_start=61448, + serialized_end=62107, ) @@ -16368,8 +16380,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=62182, - serialized_end=62245, + serialized_start=62238, + serialized_end=62301, ) _GETTOKENTOTALSUPPLYREQUEST = _descriptor.Descriptor( @@ -16404,8 +16416,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=62054, - serialized_end=62256, + serialized_start=62110, + serialized_end=62312, ) @@ -16450,8 +16462,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=62677, - serialized_end=62797, + serialized_start=62733, + serialized_end=62853, ) _GETTOKENTOTALSUPPLYRESPONSE_GETTOKENTOTALSUPPLYRESPONSEV0 = _descriptor.Descriptor( @@ -16500,8 +16512,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=62391, - serialized_end=62807, + serialized_start=62447, + serialized_end=62863, ) _GETTOKENTOTALSUPPLYRESPONSE = _descriptor.Descriptor( @@ -16536,8 +16548,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=62259, - serialized_end=62818, + serialized_start=62315, + serialized_end=62874, ) @@ -16582,8 +16594,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=62928, - serialized_end=63020, + serialized_start=62984, + serialized_end=63076, ) _GETGROUPINFOREQUEST = _descriptor.Descriptor( @@ -16618,8 +16630,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=62821, - serialized_end=63031, + serialized_start=62877, + serialized_end=63087, ) @@ -16657,8 +16669,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=63389, - serialized_end=63441, + serialized_start=63445, + serialized_end=63497, ) _GETGROUPINFORESPONSE_GETGROUPINFORESPONSEV0_GROUPINFOENTRY = _descriptor.Descriptor( @@ -16695,8 +16707,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=63444, - serialized_end=63596, + serialized_start=63500, + serialized_end=63652, ) _GETGROUPINFORESPONSE_GETGROUPINFORESPONSEV0_GROUPINFO = _descriptor.Descriptor( @@ -16731,8 +16743,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=63599, - serialized_end=63737, + serialized_start=63655, + serialized_end=63793, ) _GETGROUPINFORESPONSE_GETGROUPINFORESPONSEV0 = _descriptor.Descriptor( @@ -16781,8 +16793,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=63145, - serialized_end=63747, + serialized_start=63201, + serialized_end=63803, ) _GETGROUPINFORESPONSE = _descriptor.Descriptor( @@ -16817,8 +16829,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=63034, - serialized_end=63758, + serialized_start=63090, + serialized_end=63814, ) @@ -16856,8 +16868,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=63871, - serialized_end=63988, + serialized_start=63927, + serialized_end=64044, ) _GETGROUPINFOSREQUEST_GETGROUPINFOSREQUESTV0 = _descriptor.Descriptor( @@ -16918,8 +16930,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=63991, - serialized_end=64243, + serialized_start=64047, + serialized_end=64299, ) _GETGROUPINFOSREQUEST = _descriptor.Descriptor( @@ -16954,8 +16966,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=63761, - serialized_end=64254, + serialized_start=63817, + serialized_end=64310, ) @@ -16993,8 +17005,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=63389, - serialized_end=63441, + serialized_start=63445, + serialized_end=63497, ) _GETGROUPINFOSRESPONSE_GETGROUPINFOSRESPONSEV0_GROUPPOSITIONINFOENTRY = _descriptor.Descriptor( @@ -17038,8 +17050,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=64675, - serialized_end=64870, + serialized_start=64731, + serialized_end=64926, ) _GETGROUPINFOSRESPONSE_GETGROUPINFOSRESPONSEV0_GROUPINFOS = _descriptor.Descriptor( @@ -17069,8 +17081,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=64873, - serialized_end=65003, + serialized_start=64929, + serialized_end=65059, ) _GETGROUPINFOSRESPONSE_GETGROUPINFOSRESPONSEV0 = _descriptor.Descriptor( @@ -17119,8 +17131,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=64371, - serialized_end=65013, + serialized_start=64427, + serialized_end=65069, ) _GETGROUPINFOSRESPONSE = _descriptor.Descriptor( @@ -17155,8 +17167,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=64257, - serialized_end=65024, + serialized_start=64313, + serialized_end=65080, ) @@ -17194,8 +17206,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=65143, - serialized_end=65219, + serialized_start=65199, + serialized_end=65275, ) _GETGROUPACTIONSREQUEST_GETGROUPACTIONSREQUESTV0 = _descriptor.Descriptor( @@ -17270,8 +17282,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=65222, - serialized_end=65550, + serialized_start=65278, + serialized_end=65606, ) _GETGROUPACTIONSREQUEST = _descriptor.Descriptor( @@ -17307,8 +17319,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=65027, - serialized_end=65601, + serialized_start=65083, + serialized_end=65657, ) @@ -17358,8 +17370,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=65983, - serialized_end=66074, + serialized_start=66039, + serialized_end=66130, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_BURNEVENT = _descriptor.Descriptor( @@ -17408,8 +17420,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=66076, - serialized_end=66167, + serialized_start=66132, + serialized_end=66223, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_FREEZEEVENT = _descriptor.Descriptor( @@ -17451,8 +17463,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=66169, - serialized_end=66243, + serialized_start=66225, + serialized_end=66299, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_UNFREEZEEVENT = _descriptor.Descriptor( @@ -17494,8 +17506,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=66245, - serialized_end=66321, + serialized_start=66301, + serialized_end=66377, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_DESTROYFROZENFUNDSEVENT = _descriptor.Descriptor( @@ -17544,8 +17556,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=66323, - serialized_end=66425, + serialized_start=66379, + serialized_end=66481, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_SHAREDENCRYPTEDNOTE = _descriptor.Descriptor( @@ -17589,8 +17601,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=66427, - serialized_end=66527, + serialized_start=66483, + serialized_end=66583, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_PERSONALENCRYPTEDNOTE = _descriptor.Descriptor( @@ -17634,8 +17646,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=66529, - serialized_end=66652, + serialized_start=66585, + serialized_end=66708, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_EMERGENCYACTIONEVENT = _descriptor.Descriptor( @@ -17678,8 +17690,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=66655, - serialized_end=66888, + serialized_start=66711, + serialized_end=66944, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_TOKENCONFIGUPDATEEVENT = _descriptor.Descriptor( @@ -17721,8 +17733,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=66890, - serialized_end=66990, + serialized_start=66946, + serialized_end=67046, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_UPDATEDIRECTPURCHASEPRICEEVENT_PRICEFORQUANTITY = _descriptor.Descriptor( @@ -17759,8 +17771,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=57844, - serialized_end=57895, + serialized_start=57900, + serialized_end=57951, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_UPDATEDIRECTPURCHASEPRICEEVENT_PRICINGSCHEDULE = _descriptor.Descriptor( @@ -17790,8 +17802,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=67282, - serialized_end=67454, + serialized_start=67338, + serialized_end=67510, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_UPDATEDIRECTPURCHASEPRICEEVENT = _descriptor.Descriptor( @@ -17845,8 +17857,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=66993, - serialized_end=67479, + serialized_start=67049, + serialized_end=67535, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_GROUPACTIONEVENT = _descriptor.Descriptor( @@ -17895,8 +17907,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=67482, - serialized_end=67862, + serialized_start=67538, + serialized_end=67918, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_DOCUMENTEVENT = _descriptor.Descriptor( @@ -17931,8 +17943,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=67865, - serialized_end=68004, + serialized_start=67921, + serialized_end=68060, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_DOCUMENTCREATEEVENT = _descriptor.Descriptor( @@ -17962,8 +17974,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=68006, - serialized_end=68053, + serialized_start=68062, + serialized_end=68109, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_CONTRACTUPDATEEVENT = _descriptor.Descriptor( @@ -17993,8 +18005,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=68055, - serialized_end=68102, + serialized_start=68111, + serialized_end=68158, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_CONTRACTEVENT = _descriptor.Descriptor( @@ -18029,8 +18041,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=68105, - serialized_end=68244, + serialized_start=68161, + serialized_end=68300, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_TOKENEVENT = _descriptor.Descriptor( @@ -18114,8 +18126,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=68247, - serialized_end=69224, + serialized_start=68303, + serialized_end=69280, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_GROUPACTIONENTRY = _descriptor.Descriptor( @@ -18152,8 +18164,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=69227, - serialized_end=69374, + serialized_start=69283, + serialized_end=69430, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0_GROUPACTIONS = _descriptor.Descriptor( @@ -18183,8 +18195,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=69377, - serialized_end=69509, + serialized_start=69433, + serialized_end=69565, ) _GETGROUPACTIONSRESPONSE_GETGROUPACTIONSRESPONSEV0 = _descriptor.Descriptor( @@ -18233,8 +18245,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=65724, - serialized_end=69519, + serialized_start=65780, + serialized_end=69575, ) _GETGROUPACTIONSRESPONSE = _descriptor.Descriptor( @@ -18269,8 +18281,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=65604, - serialized_end=69530, + serialized_start=65660, + serialized_end=69586, ) @@ -18329,8 +18341,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=69668, - serialized_end=69874, + serialized_start=69724, + serialized_end=69930, ) _GETGROUPACTIONSIGNERSREQUEST = _descriptor.Descriptor( @@ -18366,8 +18378,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=69533, - serialized_end=69925, + serialized_start=69589, + serialized_end=69981, ) @@ -18405,8 +18417,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=70357, - serialized_end=70410, + serialized_start=70413, + serialized_end=70466, ) _GETGROUPACTIONSIGNERSRESPONSE_GETGROUPACTIONSIGNERSRESPONSEV0_GROUPACTIONSIGNERS = _descriptor.Descriptor( @@ -18436,8 +18448,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=70413, - serialized_end=70558, + serialized_start=70469, + serialized_end=70614, ) _GETGROUPACTIONSIGNERSRESPONSE_GETGROUPACTIONSIGNERSRESPONSEV0 = _descriptor.Descriptor( @@ -18486,8 +18498,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=70066, - serialized_end=70568, + serialized_start=70122, + serialized_end=70624, ) _GETGROUPACTIONSIGNERSRESPONSE = _descriptor.Descriptor( @@ -18522,8 +18534,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=69928, - serialized_end=70579, + serialized_start=69984, + serialized_end=70635, ) @@ -18561,8 +18573,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=70695, - serialized_end=70752, + serialized_start=70751, + serialized_end=70808, ) _GETADDRESSINFOREQUEST = _descriptor.Descriptor( @@ -18597,8 +18609,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=70582, - serialized_end=70763, + serialized_start=70638, + serialized_end=70819, ) @@ -18641,8 +18653,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=70766, - serialized_end=70899, + serialized_start=70822, + serialized_end=70955, ) @@ -18680,8 +18692,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=70901, - serialized_end=70950, + serialized_start=70957, + serialized_end=71006, ) @@ -18712,8 +18724,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=70952, - serialized_end=71047, + serialized_start=71008, + serialized_end=71103, ) @@ -18763,8 +18775,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=71049, - serialized_end=71158, + serialized_start=71105, + serialized_end=71214, ) @@ -18802,8 +18814,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=71160, - serialized_end=71280, + serialized_start=71216, + serialized_end=71336, ) @@ -18834,8 +18846,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=71282, - serialized_end=71389, + serialized_start=71338, + serialized_end=71445, ) @@ -18885,8 +18897,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=71509, - serialized_end=71734, + serialized_start=71565, + serialized_end=71790, ) _GETADDRESSINFORESPONSE = _descriptor.Descriptor( @@ -18921,8 +18933,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=71392, - serialized_end=71745, + serialized_start=71448, + serialized_end=71801, ) @@ -18960,8 +18972,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=71870, - serialized_end=71932, + serialized_start=71926, + serialized_end=71988, ) _GETADDRESSESINFOSREQUEST = _descriptor.Descriptor( @@ -18996,8 +19008,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=71748, - serialized_end=71943, + serialized_start=71804, + serialized_end=71999, ) @@ -19047,8 +19059,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=72072, - serialized_end=72304, + serialized_start=72128, + serialized_end=72360, ) _GETADDRESSESINFOSRESPONSE = _descriptor.Descriptor( @@ -19083,8 +19095,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=71946, - serialized_end=72315, + serialized_start=72002, + serialized_end=72371, ) @@ -19108,8 +19120,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=72455, - serialized_end=72488, + serialized_start=72511, + serialized_end=72544, ) _GETADDRESSESTRUNKSTATEREQUEST = _descriptor.Descriptor( @@ -19144,8 +19156,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=72318, - serialized_end=72499, + serialized_start=72374, + serialized_end=72555, ) @@ -19183,8 +19195,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=72643, - serialized_end=72789, + serialized_start=72699, + serialized_end=72845, ) _GETADDRESSESTRUNKSTATERESPONSE = _descriptor.Descriptor( @@ -19219,8 +19231,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=72502, - serialized_end=72800, + serialized_start=72558, + serialized_end=72856, ) @@ -19265,8 +19277,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=72943, - serialized_end=73032, + serialized_start=72999, + serialized_end=73088, ) _GETADDRESSESBRANCHSTATEREQUEST = _descriptor.Descriptor( @@ -19301,8 +19313,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=72803, - serialized_end=73043, + serialized_start=72859, + serialized_end=73099, ) @@ -19333,8 +19345,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=73189, - serialized_end=73244, + serialized_start=73245, + serialized_end=73300, ) _GETADDRESSESBRANCHSTATERESPONSE = _descriptor.Descriptor( @@ -19369,8 +19381,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=73046, - serialized_end=73255, + serialized_start=73102, + serialized_end=73311, ) @@ -19415,8 +19427,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=73419, - serialized_end=73533, + serialized_start=73475, + serialized_end=73589, ) _GETRECENTADDRESSBALANCECHANGESREQUEST = _descriptor.Descriptor( @@ -19451,8 +19463,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=73258, - serialized_end=73544, + serialized_start=73314, + serialized_end=73600, ) @@ -19502,8 +19514,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=73712, - serialized_end=73976, + serialized_start=73768, + serialized_end=74032, ) _GETRECENTADDRESSBALANCECHANGESRESPONSE = _descriptor.Descriptor( @@ -19538,8 +19550,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=73547, - serialized_end=73987, + serialized_start=73603, + serialized_end=74043, ) @@ -19577,8 +19589,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=73989, - serialized_end=74060, + serialized_start=74045, + serialized_end=74116, ) @@ -19628,8 +19640,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=74063, - serialized_end=74239, + serialized_start=74119, + serialized_end=74295, ) @@ -19660,8 +19672,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=74241, - serialized_end=74333, + serialized_start=74297, + serialized_end=74389, ) @@ -19706,8 +19718,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=74336, - serialized_end=74510, + serialized_start=74392, + serialized_end=74566, ) @@ -19738,8 +19750,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=74513, - serialized_end=74648, + serialized_start=74569, + serialized_end=74704, ) @@ -19777,8 +19789,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=74840, - serialized_end=74937, + serialized_start=74896, + serialized_end=74993, ) _GETRECENTCOMPACTEDADDRESSBALANCECHANGESREQUEST = _descriptor.Descriptor( @@ -19813,8 +19825,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=74651, - serialized_end=74948, + serialized_start=74707, + serialized_end=75004, ) @@ -19864,8 +19876,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=75144, - serialized_end=75436, + serialized_start=75200, + serialized_end=75492, ) _GETRECENTCOMPACTEDADDRESSBALANCECHANGESRESPONSE = _descriptor.Descriptor( @@ -19900,8 +19912,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=74951, - serialized_end=75447, + serialized_start=75007, + serialized_end=75503, ) @@ -19946,8 +19958,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=75596, - serialized_end=75683, + serialized_start=75652, + serialized_end=75739, ) _GETSHIELDEDENCRYPTEDNOTESREQUEST = _descriptor.Descriptor( @@ -19982,8 +19994,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=75450, - serialized_end=75694, + serialized_start=75506, + serialized_end=75750, ) @@ -20035,8 +20047,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=76141, - serialized_end=76228, + serialized_start=76197, + serialized_end=76284, ) _GETSHIELDEDENCRYPTEDNOTESRESPONSE_GETSHIELDEDENCRYPTEDNOTESRESPONSEV0_ENCRYPTEDNOTES = _descriptor.Descriptor( @@ -20066,8 +20078,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=76231, - serialized_end=76376, + serialized_start=76287, + serialized_end=76432, ) _GETSHIELDEDENCRYPTEDNOTESRESPONSE_GETSHIELDEDENCRYPTEDNOTESRESPONSEV0 = _descriptor.Descriptor( @@ -20116,8 +20128,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=75847, - serialized_end=76386, + serialized_start=75903, + serialized_end=76442, ) _GETSHIELDEDENCRYPTEDNOTESRESPONSE = _descriptor.Descriptor( @@ -20152,8 +20164,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=75697, - serialized_end=76397, + serialized_start=75753, + serialized_end=76453, ) @@ -20184,8 +20196,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=76525, - serialized_end=76569, + serialized_start=76581, + serialized_end=76625, ) _GETSHIELDEDANCHORSREQUEST = _descriptor.Descriptor( @@ -20220,8 +20232,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=76400, - serialized_end=76580, + serialized_start=76456, + serialized_end=76636, ) @@ -20252,8 +20264,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=76969, - serialized_end=76995, + serialized_start=77025, + serialized_end=77051, ) _GETSHIELDEDANCHORSRESPONSE_GETSHIELDEDANCHORSRESPONSEV0 = _descriptor.Descriptor( @@ -20302,8 +20314,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=76712, - serialized_end=77005, + serialized_start=76768, + serialized_end=77061, ) _GETSHIELDEDANCHORSRESPONSE = _descriptor.Descriptor( @@ -20338,8 +20350,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=76583, - serialized_end=77016, + serialized_start=76639, + serialized_end=77072, ) @@ -20370,8 +20382,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=77171, - serialized_end=77224, + serialized_start=77227, + serialized_end=77280, ) _GETMOSTRECENTSHIELDEDANCHORREQUEST = _descriptor.Descriptor( @@ -20406,8 +20418,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=77019, - serialized_end=77235, + serialized_start=77075, + serialized_end=77291, ) @@ -20457,8 +20469,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=77394, - serialized_end=77575, + serialized_start=77450, + serialized_end=77631, ) _GETMOSTRECENTSHIELDEDANCHORRESPONSE = _descriptor.Descriptor( @@ -20493,8 +20505,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=77238, - serialized_end=77586, + serialized_start=77294, + serialized_end=77642, ) @@ -20525,8 +20537,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=77720, - serialized_end=77766, + serialized_start=77776, + serialized_end=77822, ) _GETSHIELDEDPOOLSTATEREQUEST = _descriptor.Descriptor( @@ -20561,8 +20573,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=77589, - serialized_end=77777, + serialized_start=77645, + serialized_end=77833, ) @@ -20612,8 +20624,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=77915, - serialized_end=78100, + serialized_start=77971, + serialized_end=78156, ) _GETSHIELDEDPOOLSTATERESPONSE = _descriptor.Descriptor( @@ -20648,8 +20660,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=77780, - serialized_end=78111, + serialized_start=77836, + serialized_end=78167, ) @@ -20680,8 +20692,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=78248, - serialized_end=78295, + serialized_start=78304, + serialized_end=78351, ) _GETSHIELDEDNOTESCOUNTREQUEST = _descriptor.Descriptor( @@ -20716,8 +20728,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=78114, - serialized_end=78306, + serialized_start=78170, + serialized_end=78362, ) @@ -20767,8 +20779,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=78447, - serialized_end=78637, + serialized_start=78503, + serialized_end=78693, ) _GETSHIELDEDNOTESCOUNTRESPONSE = _descriptor.Descriptor( @@ -20803,8 +20815,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=78309, - serialized_end=78648, + serialized_start=78365, + serialized_end=78704, ) @@ -20842,8 +20854,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=78785, - serialized_end=78852, + serialized_start=78841, + serialized_end=78908, ) _GETSHIELDEDNULLIFIERSREQUEST = _descriptor.Descriptor( @@ -20878,8 +20890,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=78651, - serialized_end=78863, + serialized_start=78707, + serialized_end=78919, ) @@ -20917,8 +20929,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=79292, - serialized_end=79346, + serialized_start=79348, + serialized_end=79402, ) _GETSHIELDEDNULLIFIERSRESPONSE_GETSHIELDEDNULLIFIERSRESPONSEV0_NULLIFIERSTATUSES = _descriptor.Descriptor( @@ -20948,8 +20960,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=79349, - serialized_end=79491, + serialized_start=79405, + serialized_end=79547, ) _GETSHIELDEDNULLIFIERSRESPONSE_GETSHIELDEDNULLIFIERSRESPONSEV0 = _descriptor.Descriptor( @@ -20998,8 +21010,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=79004, - serialized_end=79501, + serialized_start=79060, + serialized_end=79557, ) _GETSHIELDEDNULLIFIERSRESPONSE = _descriptor.Descriptor( @@ -21034,8 +21046,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=78866, - serialized_end=79512, + serialized_start=78922, + serialized_end=79568, ) _GETIDENTITYREQUEST_GETIDENTITYREQUESTV0.containing_type = _GETIDENTITYREQUEST @@ -21430,6 +21442,9 @@ _CONTRACTMODERATIONREASON.oneofs_by_name['_code'].fields.append( _CONTRACTMODERATIONREASON.fields_by_name['code']) _CONTRACTMODERATIONREASON.fields_by_name['code'].containing_oneof = _CONTRACTMODERATIONREASON.oneofs_by_name['_code'] +_CONTRACTMODERATIONREASON.oneofs_by_name['_reason_document_id'].fields.append( + _CONTRACTMODERATIONREASON.fields_by_name['reason_document_id']) +_CONTRACTMODERATIONREASON.fields_by_name['reason_document_id'].containing_oneof = _CONTRACTMODERATIONREASON.oneofs_by_name['_reason_document_id'] _CONTRACTWARNING.fields_by_name['reason'].message_type = _CONTRACTMODERATIONREASON _GETCONTRACTMODERATIONSTATUSREQUEST_GETCONTRACTMODERATIONSTATUSREQUESTV0.fields_by_name['lists'].enum_type = _CONTRACTMODERATIONLIST _GETCONTRACTMODERATIONSTATUSREQUEST_GETCONTRACTMODERATIONSTATUSREQUESTV0.containing_type = _GETCONTRACTMODERATIONSTATUSREQUEST @@ -27021,8 +27036,8 @@ index=0, serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_start=79795, - serialized_end=90115, + serialized_start=79851, + serialized_end=90171, methods=[ _descriptor.MethodDescriptor( name='broadcastStateTransition', diff --git a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.d.ts b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.d.ts index 6e6804d2716..614dd9ffcd3 100644 --- a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.d.ts +++ b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.d.ts @@ -2808,6 +2808,13 @@ export class ContractModerationReason extends jspb.Message { setDocumentsList(value: Array): void; addDocuments(value?: ContractModerationDocument, index?: number): ContractModerationDocument; + hasReasonDocumentId(): boolean; + clearReasonDocumentId(): void; + getReasonDocumentId(): Uint8Array | string; + getReasonDocumentId_asU8(): Uint8Array; + getReasonDocumentId_asB64(): string; + setReasonDocumentId(value: Uint8Array | string): void; + serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): ContractModerationReason.AsObject; static toObject(includeInstance: boolean, msg: ContractModerationReason): ContractModerationReason.AsObject; @@ -2823,6 +2830,7 @@ export namespace ContractModerationReason { code: number, text: string, documentsList: Array, + reasonDocumentId: Uint8Array | string, } } diff --git a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js index 54dc934ca3e..fa87ce9ee2a 100644 --- a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js +++ b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js @@ -29829,7 +29829,8 @@ proto.org.dash.platform.dapi.v0.ContractModerationReason.toObject = function(inc code: jspb.Message.getFieldWithDefault(msg, 1, 0), text: jspb.Message.getFieldWithDefault(msg, 2, ""), documentsList: jspb.Message.toObjectList(msg.getDocumentsList(), - proto.org.dash.platform.dapi.v0.ContractModerationDocument.toObject, includeInstance) + proto.org.dash.platform.dapi.v0.ContractModerationDocument.toObject, includeInstance), + reasonDocumentId: msg.getReasonDocumentId_asB64() }; if (includeInstance) { @@ -29879,6 +29880,10 @@ proto.org.dash.platform.dapi.v0.ContractModerationReason.deserializeBinaryFromRe reader.readMessage(value,proto.org.dash.platform.dapi.v0.ContractModerationDocument.deserializeBinaryFromReader); msg.addDocuments(value); break; + case 4: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setReasonDocumentId(value); + break; default: reader.skipField(); break; @@ -29930,6 +29935,13 @@ proto.org.dash.platform.dapi.v0.ContractModerationReason.serializeBinaryToWriter proto.org.dash.platform.dapi.v0.ContractModerationDocument.serializeBinaryToWriter ); } + f = /** @type {!(string|Uint8Array)} */ (jspb.Message.getField(message, 4)); + if (f != null) { + writer.writeBytes( + 4, + f + ); + } }; @@ -30025,6 +30037,66 @@ proto.org.dash.platform.dapi.v0.ContractModerationReason.prototype.clearDocument }; +/** + * optional bytes reason_document_id = 4; + * @return {string} + */ +proto.org.dash.platform.dapi.v0.ContractModerationReason.prototype.getReasonDocumentId = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +}; + + +/** + * optional bytes reason_document_id = 4; + * This is a type-conversion wrapper around `getReasonDocumentId()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.ContractModerationReason.prototype.getReasonDocumentId_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getReasonDocumentId())); +}; + + +/** + * optional bytes reason_document_id = 4; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getReasonDocumentId()` + * @return {!Uint8Array} + */ +proto.org.dash.platform.dapi.v0.ContractModerationReason.prototype.getReasonDocumentId_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getReasonDocumentId())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.ContractModerationReason} returns this + */ +proto.org.dash.platform.dapi.v0.ContractModerationReason.prototype.setReasonDocumentId = function(value) { + return jspb.Message.setField(this, 4, value); +}; + + +/** + * Clears the field making it undefined. + * @return {!proto.org.dash.platform.dapi.v0.ContractModerationReason} returns this + */ +proto.org.dash.platform.dapi.v0.ContractModerationReason.prototype.clearReasonDocumentId = function() { + return jspb.Message.setField(this, 4, undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.org.dash.platform.dapi.v0.ContractModerationReason.prototype.hasReasonDocumentId = function() { + return jspb.Message.getField(this, 4) != null; +}; + + diff --git a/packages/dapi-grpc/protos/platform/v0/platform.proto b/packages/dapi-grpc/protos/platform/v0/platform.proto index 8ea042956c1..4368607d55f 100644 --- a/packages/dapi-grpc/protos/platform/v0/platform.proto +++ b/packages/dapi-grpc/protos/platform/v0/platform.proto @@ -722,7 +722,7 @@ message ContractModerationDocument { // Why a moderator banned, suspended or warned an identity, or deleted a // document. Nothing checks what a moderator writes, and the documents cited -// are not looked up. +// are not looked up, except the reason document a seated elected team names. message ContractModerationReason { optional uint32 code = 1; // Reserved for the ban codes a contract may declare in a later @@ -730,6 +730,10 @@ message ContractModerationReason { string text = 2; // Free text, at most 1024 bytes of UTF-8, may be empty repeated ContractModerationDocument documents = 3; // The documents the reason is about, at most 16, none twice + optional bytes reason_document_id = + 4; // The 32-byte id of the moderation charters contract's `reason` + // document the action is taken on; one the seated team's proposal + // lists for a seated elected team's action, unchecked otherwise } // One warning an identity carries on a contract's warning list. diff --git a/packages/rs-dpp/src/data_contract/config/moderation/reason.rs b/packages/rs-dpp/src/data_contract/config/moderation/reason.rs index 58678f389d9..243adb25c84 100644 --- a/packages/rs-dpp/src/data_contract/config/moderation/reason.rs +++ b/packages/rs-dpp/src/data_contract/config/moderation/reason.rs @@ -43,7 +43,9 @@ pub struct ContractModerationDocument { /// /// Nothing checks what a moderator writes: the text is free, so is the code, and the documents /// a reason cites are not looked up. A cited document may have been deleted since, by its -/// author or by a moderator (whose deletion left a record), or may never have existed. +/// author or by a moderator (whose deletion left a record), or may never have existed. The +/// one exception is the reason document a seated elected team names: it must be one its +/// proposal lists. #[derive( Debug, Clone, PartialEq, Eq, Default, Encode, Decode, DecodeUntrusted, Serialize, Deserialize, )] @@ -62,18 +64,32 @@ pub struct ContractModerationReason { /// JSON when there are none. #[serde(default, skip_serializing_if = "Vec::is_empty")] pub documents: Vec, + /// The `reason` document of the moderation charters system contract the action is taken + /// on (protocol version 14). A seated elected team's ban, suspension, warning or document + /// deletion must name one its proposal lists (`ModerationReasonNotListedError`); for every + /// other moderator it is stored as written and checked against nothing. Last, so that a + /// reason written before it existed decodes; left out of the JSON when there is none. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub reason_document_id: Option, } impl ContractModerationReason { - /// A reason without a code, about no document. + /// A reason without a code, about no document, naming no reason document. pub fn from_text(text: impl Into) -> Self { Self { code: None, text: text.into(), documents: vec![], + reason_document_id: None, } } + /// The same reason, naming the reason document `reason_document_id`. + pub fn with_reason_document(mut self, reason_document_id: Identifier) -> Self { + self.reason_document_id = Some(reason_document_id); + self + } + /// The same reason, about `documents`. pub fn with_documents(mut self, documents: Vec) -> Self { self.documents = documents; @@ -151,6 +167,7 @@ mod tests { code: Some(7), text: "spam".to_string(), documents: vec![], + reason_document_id: None, }; let json = serde_json::to_value(&reason).expect("to json"); assert_eq!(json, serde_json::json!({"code": 7, "text": "spam"})); @@ -240,6 +257,24 @@ mod tests { assert!(cited(1).validate(platform_version).is_valid()); } + #[test] + fn should_round_trip_the_reason_document_through_json_and_leave_it_out_when_none() { + let reason = ContractModerationReason::from_text("spam") + .with_reason_document(Identifier::from([4; 32])); + let json = serde_json::to_value(&reason).expect("to json"); + assert_eq!( + json["reasonDocumentId"], + Identifier::from([4; 32]).to_string(Encoding::Base58) + ); + assert_eq!( + serde_json::from_value::(json).expect("from json"), + reason + ); + let json = + serde_json::to_value(ContractModerationReason::from_text("spam")).expect("to json"); + assert!(json.get("reasonDocumentId").is_none()); + } + #[test] fn should_refuse_an_unknown_field() { serde_json::from_value::( @@ -259,6 +294,7 @@ mod tests { code: Some(u16::MAX), text: "é".repeat(max_length / 2), documents: vec![], + reason_document_id: None, }; assert_eq!(reason.text.len(), max_length); assert!(reason.validate(platform_version).is_valid()); diff --git a/packages/rs-dpp/src/errors/consensus/codes.rs b/packages/rs-dpp/src/errors/consensus/codes.rs index 1978313e69c..24534df82c2 100644 --- a/packages/rs-dpp/src/errors/consensus/codes.rs +++ b/packages/rs-dpp/src/errors/consensus/codes.rs @@ -493,6 +493,7 @@ impl ErrorWithCode for StateError { Self::ContractModeratedDocumentTypeNotYetUsableError(_) => 41200, Self::ContractModerationAbilityNotGrantedError(_) => 41201, Self::ModerationCharterAddedModeratorLimitReachedError(_) => 41202, + Self::ModerationReasonNotListedError(_) => 41203, } } } diff --git a/packages/rs-dpp/src/errors/consensus/state/contract_moderation/mod.rs b/packages/rs-dpp/src/errors/consensus/state/contract_moderation/mod.rs index 3bcf056ee76..677987f5f58 100644 --- a/packages/rs-dpp/src/errors/consensus/state/contract_moderation/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/state/contract_moderation/mod.rs @@ -24,6 +24,7 @@ mod document_restore_window_elapsed_error; mod document_type_not_deletable_by_moderators_error; mod identity_not_contract_moderator_error; mod moderation_charter_added_moderator_limit_reached_error; +mod moderation_reason_not_listed_error; pub use contract_document_already_restored_error::*; pub use contract_document_removal_not_found_error::*; @@ -51,3 +52,4 @@ pub use document_restore_window_elapsed_error::*; pub use document_type_not_deletable_by_moderators_error::*; pub use identity_not_contract_moderator_error::*; pub use moderation_charter_added_moderator_limit_reached_error::*; +pub use moderation_reason_not_listed_error::*; diff --git a/packages/rs-dpp/src/errors/consensus/state/contract_moderation/moderation_reason_not_listed_error.rs b/packages/rs-dpp/src/errors/consensus/state/contract_moderation/moderation_reason_not_listed_error.rs new file mode 100644 index 00000000000..96a802c6094 --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/state/contract_moderation/moderation_reason_not_listed_error.rs @@ -0,0 +1,81 @@ +use crate::consensus::state::state_error::StateError; +use crate::consensus::ConsensusError; +use crate::errors::ProtocolError; +use bincode::{Decode, DecodeUntrusted, Encode}; +use platform_serialization_derive::{ + PlatformDeserializeTrusted, PlatformDeserializeUntrusted, PlatformSerialize, +}; +use platform_value::Identifier; +use thiserror::Error; + +/// A ban, a suspension, a warning or a document deletion by a member of a contract's seated +/// moderation team whose reason names no reason document, or one the team's proposal does not +/// list. Every such action of a seated team names a `reason` document of the moderation +/// charters contract that its proposal lists; a proposal that lists none can take no such +/// action. Lifting a ban, a suspension or warnings and restoring a document carry no reason +/// and are not checked, and neither are the moderators a declaration names. +#[derive( + Error, + Debug, + Clone, + PartialEq, + Eq, + Encode, + Decode, + PlatformSerialize, + PlatformDeserializeTrusted, + PlatformDeserializeUntrusted, + DecodeUntrusted, +)] +#[error( + "The moderation of contract {} names {}, which the proposal {} of its seated team does not list", + contract_id, + reason_document_id.map(|id| format!("reason document {}", id)).unwrap_or_else(|| "no reason document".to_string()), + submitted_charter_id +)] +#[platform_serialize(unversioned)] +pub struct ModerationReasonNotListedError { + /* + + DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION + + */ + contract_id: Identifier, + submitted_charter_id: Identifier, + reason_document_id: Option, +} + +impl ModerationReasonNotListedError { + pub fn new( + contract_id: Identifier, + submitted_charter_id: Identifier, + reason_document_id: Option, + ) -> Self { + Self { + contract_id, + submitted_charter_id, + reason_document_id, + } + } + + /// The moderated contract + pub fn contract_id(&self) -> Identifier { + self.contract_id + } + + /// The proposal the seated team runs on, whose `reasons` the action is checked against + pub fn submitted_charter_id(&self) -> Identifier { + self.submitted_charter_id + } + + /// The reason document the action named, `None` when it named none + pub fn reason_document_id(&self) -> Option { + self.reason_document_id + } +} + +impl From for ConsensusError { + fn from(err: ModerationReasonNotListedError) -> Self { + Self::StateError(StateError::ModerationReasonNotListedError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/state/state_error.rs b/packages/rs-dpp/src/errors/consensus/state/state_error.rs index eb4adfe5637..5b1d47ea169 100644 --- a/packages/rs-dpp/src/errors/consensus/state/state_error.rs +++ b/packages/rs-dpp/src/errors/consensus/state/state_error.rs @@ -13,7 +13,7 @@ use crate::consensus::state::shielded::invalid_shielded_proof_error::InvalidShie use crate::consensus::state::shielded::nullifier_already_spent_error::NullifierAlreadySpentError; use crate::consensus::state::contract_moderation::{ ContractModeratedDocumentTypeNotYetUsableError, ContractModerationAbilityNotGrantedError, - ModerationCharterAddedModeratorLimitReachedError, + ModerationCharterAddedModeratorLimitReachedError, ModerationReasonNotListedError, ContractModerationNotEnabledError, ContractModerationTargetNotAllowedError, ContractFeeClaimNotAllowedError, ContractFeesAlreadyClaimedThisEpochError, ContractFeesNothingToClaimError, ContractModerationCounterpartyBarredError, @@ -616,6 +616,11 @@ pub enum StateError { #[error(transparent)] DocumentActionFeeModeratorsShareMismatchError(DocumentActionFeeModeratorsShareMismatchError), + + // A seated moderation team's action names a reason its proposal lists (protocol version + // 14). + #[error(transparent)] + ModerationReasonNotListedError(ModerationReasonNotListedError), } impl From for ConsensusError { @@ -1284,5 +1289,13 @@ mod tests { )), 149 ); + // A seated moderation team's action names a reason its proposal lists (protocol + // version 14): the tail of the enum. + assert_eq!( + discriminant_of(StateError::ModerationReasonNotListedError( + ModerationReasonNotListedError::new(group_id, identity_id, None) + )), + 150 + ); } } diff --git a/packages/rs-dpp/src/state_transition/state_transitions/contract/contract_user_moderation_transition/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/contract/contract_user_moderation_transition/mod.rs index 691212b65df..941f1392d81 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/contract/contract_user_moderation_transition/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/contract/contract_user_moderation_transition/mod.rs @@ -160,6 +160,7 @@ mod test { code: Some(u16::MAX), text: "spam".to_string(), documents: vec![], + reason_document_id: None, }, }, ContractUserModerationAction::Unban { @@ -291,6 +292,7 @@ pub(crate) mod json_convertible_tests { code: Some(12), text: "flooding".to_string(), documents: vec![], + reason_document_id: None, }, }, user_fee_increase: 4, diff --git a/packages/rs-dpp/src/state_transition/state_transitions/contract/contract_user_moderation_transition/v0/mod.rs b/packages/rs-dpp/src/state_transition/state_transitions/contract/contract_user_moderation_transition/v0/mod.rs index 09542572a15..f9f232757dc 100644 --- a/packages/rs-dpp/src/state_transition/state_transitions/contract/contract_user_moderation_transition/v0/mod.rs +++ b/packages/rs-dpp/src/state_transition/state_transitions/contract/contract_user_moderation_transition/v0/mod.rs @@ -343,6 +343,7 @@ mod test { code: Some(4), text: "flooding".to_string(), documents: vec![], + reason_document_id: None, }; let action = ContractUserModerationAction::Suspend { identity_id: target, @@ -409,6 +410,7 @@ mod test { code: Some(2), text: "spam".to_string(), documents: vec![], + reason_document_id: None, }; let action = ContractUserModerationAction::DeleteDocument { document_type_name: "post".to_string(), diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/state/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/state/v0/mod.rs index 3746c2b5565..324397256ac 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/state/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/state/v0/mod.rs @@ -25,6 +25,7 @@ use dpp::consensus::state::contract_moderation::{ ContractUserWarningLimitReachedError, DocumentModerationWindowElapsedError, DocumentRestoreHashMismatchError, DocumentRestoreWindowElapsedError, DocumentTypeNotDeletableByModeratorsError, IdentityNotContractModeratorError, + ModerationReasonNotListedError, }; use dpp::consensus::state::document::document_not_found_error::DocumentNotFoundError; use dpp::consensus::state::state_error::StateError; @@ -229,6 +230,17 @@ impl ContractUserModerationStateTransitionStateValidationV0 for ContractUserMode ContractModerationAbilityNotGrantedError::new(contract_id, ability, None).into(), ); } + if let Some(error) = moderators.unlisted_reason( + action, + contract_id, + platform.drive, + epoch, + execution_context, + tx, + platform_version, + )? { + return refuse(error); + } // Whoever the contract protects (the owner and the moderators, and the owner of an // elected contract whose declaration says so) cannot be put on a list. They can // be taken off one: a contract update may name as moderator an identity that already @@ -400,6 +412,17 @@ fn transform_document_deletion_v0( .into(), ); } + if let Some(error) = moderators.unlisted_reason( + transition.action(), + contract_id, + platform.drive, + epoch, + execution_context, + tx, + platform_version, + )? { + return refuse(error); + } let Some(document) = fetch_document_with_id( platform.drive, @@ -858,6 +881,53 @@ impl<'a> Moderators<'a> { } } + /// The refusal of a seated team's ban, suspension, warning or document deletion whose + /// reason names no reason document its proposal lists (decentralized moderation teams): a + /// team acts only on the grounds it proposed, and a proposal that lists none can take no + /// such action. The proposal is read, billed, only when the reason names a document. A + /// reversal carries no reason and is not checked, and neither are the moderators a + /// declaration names, the interim among them, whose reason document is stored as written. + #[allow(clippy::too_many_arguments)] + fn unlisted_reason( + &self, + action: &ContractUserModerationAction, + contract_id: Identifier, + drive: &Drive, + epoch: &Epoch, + execution_context: &mut StateTransitionExecutionContext, + tx: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result, Error> { + let Moderators::Seated { charter, .. } = self else { + return Ok(None); + }; + let reason = match action { + ContractUserModerationAction::Ban { reason, .. } + | ContractUserModerationAction::Suspend { reason, .. } + | ContractUserModerationAction::Warn { reason, .. } + | ContractUserModerationAction::DeleteDocument { reason, .. } => reason, + ContractUserModerationAction::Unban { .. } + | ContractUserModerationAction::Unsuspend { .. } + | ContractUserModerationAction::ClearWarnings { .. } + | ContractUserModerationAction::RestoreDocument { .. } => return Ok(None), + }; + let listed = match reason.reason_document_id { + None => false, + Some(reason_document_id) => charter + .fetch_proposal(drive, epoch, execution_context, tx, platform_version)? + .reasons + .contains(&reason_document_id), + }; + Ok((!listed).then(|| { + ModerationReasonNotListedError::new( + contract_id, + charter.charter.submitted_charter_id, + reason.reason_document_id, + ) + .into() + })) + } + /// `action`, counted for its signer when a member of a seated team signs a ban, a /// suspension, a warning or a document deletion: the signer's moderation action count since /// the moderators pot was last settled is read (one point read, billed) and the action diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests.rs index 9dc7e8e255c..8c6c4421b6d 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests.rs @@ -737,6 +737,7 @@ fn suspension_reason() -> ContractModerationReason { code: Some(7), text: "flooding".to_string(), documents: vec![], + reason_document_id: None, } } @@ -1792,6 +1793,7 @@ async fn should_store_the_reason_of_a_ban_and_of_a_suspension_with_any_code() { code: Some(u16::MAX), text: "flooding the feed".to_string(), documents: vec![], + reason_document_id: None, }; let transaction = setup.platform.drive.grove.start_transaction(); let suspend = setup @@ -2236,6 +2238,7 @@ fn deletion_reason() -> ContractModerationReason { code: Some(3), text: "spam".to_string(), documents: vec![], + reason_document_id: None, } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team.rs index defcf650db5..103d9388368 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team.rs @@ -32,8 +32,8 @@ use dpp::fee::fee_result::FeeResult; use dpp::moderation_charter::{ moderators_share_of, ElectedCharter, ModerationCharterRewardSplit, SubmittedCharter, ADDED_MODERATOR_DOCUMENT_TYPE_NAME, ELECTED_CHARTER_DOCUMENT_TYPE_NAME, - JOIN_REQUEST_DOCUMENT_TYPE_NAME, REMOVED_MODERATOR_DOCUMENT_TYPE_NAME, - SUBMITTED_CHARTER_DOCUMENT_TYPE_NAME, + JOIN_REQUEST_DOCUMENT_TYPE_NAME, REASON_DOCUMENT_TYPE_NAME, + REMOVED_MODERATOR_DOCUMENT_TYPE_NAME, SUBMITTED_CHARTER_DOCUMENT_TYPE_NAME, }; use dpp::state_transition::batch_transition::accessors::DocumentsBatchTransitionAccessorsV0; use dpp::state_transition::batch_transition::batched_transition::document_transition::DocumentTransition; @@ -55,6 +55,7 @@ use drive::util::object_size_info::{DocumentAndContractInfo, OwnedDocumentInfo}; use std::sync::Arc; mod pot; +mod reasons; const REFERENCED_ENTITY_NOT_FOUND: u32 = 40120; const CONTRACT_MODERATION_ABILITY_NOT_GRANTED: u32 = 41201; @@ -137,6 +138,129 @@ fn discounted() -> Credits { moderators_share_of(MODERATORS_PART, MODERATORS_SHARE) } +/// The `reason` document the team's proposal lists, which every action of the team in these +/// tests names. +const LISTED_REASON: Identifier = Identifier::new([0xE1; 32]); +/// A `reason` document the team's proposal does not list. +const UNLISTED_REASON: Identifier = Identifier::new([0xE2; 32]); + +/// `action` naming the reason document `reason_document_id`, when it carries a reason +fn citing( + action: ContractUserModerationAction, + reason_document_id: Identifier, +) -> ContractUserModerationAction { + match action { + ContractUserModerationAction::Ban { + identity_id, + reason, + } => ContractUserModerationAction::Ban { + identity_id, + reason: reason.with_reason_document(reason_document_id), + }, + ContractUserModerationAction::Suspend { + identity_id, + until, + reason, + } => ContractUserModerationAction::Suspend { + identity_id, + until, + reason: reason.with_reason_document(reason_document_id), + }, + ContractUserModerationAction::Warn { + identity_id, + reason, + } => ContractUserModerationAction::Warn { + identity_id, + reason: reason.with_reason_document(reason_document_id), + }, + ContractUserModerationAction::DeleteDocument { + document_type_name, + document_id, + reason, + } => ContractUserModerationAction::DeleteDocument { + document_type_name, + document_id, + reason: reason.with_reason_document(reason_document_id), + }, + reversal => reversal, + } +} + +// The team's actions name the listed reason: the helpers of the parent module, citing it. +fn ban_action(identity_id: Identifier) -> ContractUserModerationAction { + citing(super::ban_action(identity_id), LISTED_REASON) +} + +fn suspend_action(identity_id: Identifier, until: TimestampMillis) -> ContractUserModerationAction { + citing(super::suspend_action(identity_id, until), LISTED_REASON) +} + +fn warn_action(identity_id: Identifier, text: &str) -> ContractUserModerationAction { + citing(super::warn_action(identity_id, text), LISTED_REASON) +} + +fn delete_action( + document_type_name: &str, + document_id: Identifier, +) -> ContractUserModerationAction { + citing( + super::delete_action(document_type_name, document_id), + LISTED_REASON, + ) +} + +/// The banlist entry `ban_action` leaves +fn banned() -> Option { + Some(ContractBan { + reason: ban_reason().with_reason_document(LISTED_REASON), + }) +} + +/// A `reason` document of the charter contract at `reason_id`, owned by `owner`, written to +/// Drive as a reason create leaves it +fn write_reason( + setup: &Setup, + charters: &DataContract, + reason_id: Identifier, + owner: &Actor, + code: &str, +) { + let platform_version = PlatformVersion::latest(); + let document_type = charters + .document_type_for_name(REASON_DOCUMENT_TYPE_NAME) + .expect("expected the reason type"); + let document = Document::V0(DocumentV0 { + id: reason_id, + owner_id: owner.id(), + properties: BTreeMap::from([ + ("code".to_string(), Value::Text(code.to_string())), + ("label".to_string(), Value::Text(format!("Reason {code}"))), + ]), + created_at: Some(BLOCK_TIME_MS), + ..Default::default() + }); + setup + .platform + .drive + .add_document_for_contract( + DocumentAndContractInfo { + owned_document_info: OwnedDocumentInfo { + document_info: DocumentRefInfo((&document, None)), + owner_id: Some(owner.id().to_buffer()), + }, + contract: charters, + document_type, + }, + false, + BlockInfo::default(), + true, + None, + platform_version, + None, + ) + .expect("expected to write the reason"); +} + /// A contract with an elected declaration and a team on its way: the leader filed a proposal /// and put it to the vote with one member, and three more identities asked to join it. The /// contest is open until `award` ends it. @@ -156,13 +280,19 @@ impl Team { } async fn with_abilities(interim: InterimModerators, abilities: &[ModerationAbility]) -> Self { - Self::build(interim, abilities, false).await + Self::build(interim, abilities, false, vec![LISTED_REASON]).await + } + + /// A team whose proposal lists `reasons` + async fn with_reasons(interim: InterimModerators, reasons: Vec) -> Self { + Self::build(interim, &ALL_ABILITIES, false, reasons).await } async fn build( interim: InterimModerators, abilities: &[ModerationAbility], owner_protected: bool, + reasons: Vec, ) -> Self { let platform_version = PlatformVersion::latest(); let mut setup = Setup::new_at_with( @@ -200,10 +330,14 @@ impl Team { .load_moderation_charters(platform_version) .expect("expected the moderation charters contract"); + // Two grounds anyone may cite; the proposal lists those it was given. + for (reason_id, code) in [(LISTED_REASON, "SPM"), (UNLISTED_REASON, "OFF")] { + write_reason(&setup, &charters, reason_id, &joiners[2], code); + } let proposal = SubmittedCharter { target_contract_id: setup.contract.id(), description: "We keep the posts civil".to_string(), - reasons: vec![], + reasons, moderators_share: Some(MODERATORS_SHARE), reward_split: ModerationCharterRewardSplit { leader: 10, @@ -1175,7 +1309,13 @@ async fn should_stop_the_interim_team_claiming_the_moderators_pot_once_a_charter /// deleted, and it does not moderate. #[tokio::test] async fn should_protect_the_owner_from_a_seated_team_when_the_declaration_says_so() { - let team = Team::build(InterimModerators::ContractOwner, &ALL_ABILITIES, true).await; + let team = Team::build( + InterimModerators::ContractOwner, + &ALL_ABILITIES, + true, + vec![LISTED_REASON], + ) + .await; let setup = &team.setup; let owner_post = team.posted_by(&setup.owner).await; team.award(); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team/reasons.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team/reasons.rs new file mode 100644 index 00000000000..639969b84fa --- /dev/null +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team/reasons.rs @@ -0,0 +1,167 @@ +//! The reasons a seated team acts on (protocol version 14): every ban, suspension, warning and +//! document deletion of the team names a `reason` document its proposal lists, in a block and +//! in the mempool; a proposal that lists none can take no such action. Lifting and restoring +//! carry no reason, and the interim is not bound. + +use super::*; + +const MODERATION_REASON_NOT_LISTED: u32 = 41203; + +/// Every action a seated team is bound in, by the leader, naming `reason_document_id`, none for +/// `None`, over the stranger and a post of the stranger's +fn bound_actions( + setup: &Setup, + post: &Document, + reason_document_id: Option, +) -> Vec { + // The ban last: it would bar a suspension after it. + let actions = vec![ + super::super::suspend_action(setup.stranger.id(), LATER), + super::super::warn_action(setup.stranger.id(), "calm down"), + super::super::delete_action(POST, post.id()), + super::super::ban_action(setup.stranger.id()), + ]; + match reason_document_id { + None => actions, + Some(reason_document_id) => actions + .into_iter() + .map(|action| citing(action, reason_document_id)) + .collect(), + } +} + +/// A ban, a suspension, a warning and a deletion by a member of the seated team is refused, +/// paid, in a block and in the mempool, when its reason names no reason document, or one the +/// proposal does not list, whether it exists or not; the refused action counts for nothing. +/// The listed reason passes, and so does a reversal, which names none. +#[tokio::test] +async fn should_refuse_a_seated_teams_action_that_names_no_listed_reason() { + let team = Team::new(InterimModerators::ContractOwner).await; + let setup = &team.setup; + let post = team.posted_by(&setup.stranger).await; + team.award(); + + let transaction = setup.platform.drive.grove.start_transaction(); + for reason_document_id in [ + None, + Some(UNLISTED_REASON), + Some(Identifier::new([0xEE; 32])), + ] { + for action in bound_actions(setup, &post, reason_document_id) { + let moderation = setup.moderate(&team.leader, action).await; + assert_eq!( + setup + .check_tx(&moderation) + .iter() + .map(|error| error.code()) + .collect::>(), + vec![MODERATION_REASON_NOT_LISTED], + "{reason_document_id:?}" + ); + assert_paid_with_code( + &setup.process(&moderation, &transaction), + MODERATION_REASON_NOT_LISTED, + ); + } + } + assert!(setup + .platform + .drive + .fetch_contract_moderation_action_counts( + setup.contract.id(), + 31, + Some(&transaction), + PlatformVersion::latest(), + ) + .expect("expected to read the counts") + .is_empty()); + + for action in bound_actions(setup, &post, Some(LISTED_REASON)) { + let moderation = setup.moderate(&team.member, action).await; + assert_success(&setup.process(&moderation, &transaction)); + } + // The reason is stored as named. + assert_eq!( + setup + .status_on( + setup.stranger.id(), + &[ContractModerationList::Warnings], + Some(&transaction) + ) + .warnings + .last() + .and_then(|warning| warning.reason.reason_document_id), + Some(LISTED_REASON) + ); + for action in [ + unban_action(setup.stranger.id()), + clear_warnings_action(setup.stranger.id()), + ] { + let moderation = setup.moderate(&team.leader, action).await; + assert_success(&setup.process(&moderation, &transaction)); + } +} + +/// A proposal that lists no reason is a team that can take no bound action; it may still lift +/// what the interim did. +#[tokio::test] +async fn should_let_a_team_whose_proposal_lists_no_reason_take_no_bound_action() { + let team = Team::with_reasons(InterimModerators::ContractOwner, vec![]).await; + let setup = &team.setup; + let post = team.posted_by(&setup.stranger).await; + let transaction = setup.platform.drive.grove.start_transaction(); + let interim_ban = setup + .moderate(&setup.owner, super::super::ban_action(setup.user.id())) + .await; + assert_success(&setup.process(&interim_ban, &transaction)); + setup.commit(transaction); + team.award(); + + let transaction = setup.platform.drive.grove.start_transaction(); + for action in bound_actions(setup, &post, Some(LISTED_REASON)) { + let moderation = setup.moderate(&team.leader, action).await; + assert_paid_with_code( + &setup.process(&moderation, &transaction), + MODERATION_REASON_NOT_LISTED, + ); + } + let unban = setup + .moderate(&team.leader, unban_action(setup.user.id())) + .await; + assert_success(&setup.process(&unban, &transaction)); +} + +/// Until a charter is seated the interim moderates on any reason, a reason document named or +/// not, listed by the contender's proposal or not, and the one it names is stored as written. +#[tokio::test] +async fn should_not_bind_the_interim_to_a_listed_reason() { + let team = Team::new(InterimModerators::ContractOwner).await; + let setup = &team.setup; + let transaction = setup.platform.drive.grove.start_transaction(); + let unnamed = setup + .moderate(&setup.owner, super::super::ban_action(setup.user.id())) + .await; + assert_success(&setup.process(&unnamed, &transaction)); + let unlisted = setup + .moderate( + &setup.owner, + citing( + super::super::warn_action(setup.stranger.id(), "calm down"), + UNLISTED_REASON, + ), + ) + .await; + assert_success(&setup.process(&unlisted, &transaction)); + assert_eq!( + setup + .status_on( + setup.stranger.id(), + &[ContractModerationList::Warnings], + Some(&transaction) + ) + .warnings + .last() + .and_then(|warning| warning.reason.reason_document_id), + Some(UNLISTED_REASON) + ); +} diff --git a/packages/rs-drive-abci/src/query/contract_moderation_queries/contract_document_removals/v0/mod.rs b/packages/rs-drive-abci/src/query/contract_moderation_queries/contract_document_removals/v0/mod.rs index d6af4915296..c904275840a 100644 --- a/packages/rs-drive-abci/src/query/contract_moderation_queries/contract_document_removals/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/contract_moderation_queries/contract_document_removals/v0/mod.rs @@ -223,6 +223,7 @@ mod tests { code: Some(seed as u16), text: "spam".to_string(), documents: vec![], + reason_document_id: None, }, removed_at: 1_000 + seed as u64, document_hash: [seed + 0x20; 32], @@ -294,6 +295,7 @@ mod tests { code: Some(seed as u32), text: "spam".to_string(), documents: vec![], + reason_document_id: None, }), document_hash: removal.document_hash.to_vec(), restoration: removal diff --git a/packages/rs-drive-abci/src/query/contract_moderation_queries/contract_moderation_entries/v0/mod.rs b/packages/rs-drive-abci/src/query/contract_moderation_queries/contract_moderation_entries/v0/mod.rs index 77811ff7106..d63535b838f 100644 --- a/packages/rs-drive-abci/src/query/contract_moderation_queries/contract_moderation_entries/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/contract_moderation_queries/contract_moderation_entries/v0/mod.rs @@ -274,6 +274,7 @@ mod tests { code: None, text: WARNING_REASON.to_string(), documents: vec![], + reason_document_id: None, }) }; assert_eq!(page.entries.len(), 2); @@ -370,6 +371,7 @@ mod tests { code: None, text: BAN_REASON.to_string(), documents: vec![], + reason_document_id: None, }) }; @@ -402,6 +404,7 @@ mod tests { code: Some(SUSPENSION_REASON_CODE as u32), text: SUSPENSION_REASON.to_string(), documents: vec![], + reason_document_id: None, }) )] ); diff --git a/packages/rs-drive-abci/src/query/contract_moderation_queries/contract_moderation_status/v0/mod.rs b/packages/rs-drive-abci/src/query/contract_moderation_queries/contract_moderation_status/v0/mod.rs index 87c38c7efe2..f9d9b1becb6 100644 --- a/packages/rs-drive-abci/src/query/contract_moderation_queries/contract_moderation_status/v0/mod.rs +++ b/packages/rs-drive-abci/src/query/contract_moderation_queries/contract_moderation_status/v0/mod.rs @@ -291,6 +291,7 @@ mod tests { code: Some(SUSPENSION_REASON_CODE), text: SUSPENSION_REASON.to_string(), documents: vec![], + reason_document_id: None, }, }), warnings: vec![], diff --git a/packages/rs-drive-abci/src/query/contract_moderation_queries/mod.rs b/packages/rs-drive-abci/src/query/contract_moderation_queries/mod.rs index ec0c45a8e26..94086b6f5ec 100644 --- a/packages/rs-drive-abci/src/query/contract_moderation_queries/mod.rs +++ b/packages/rs-drive-abci/src/query/contract_moderation_queries/mod.rs @@ -74,6 +74,7 @@ pub(super) fn reason_to_response( document_id: document.document_id.to_vec(), }) .collect(), + reason_document_id: reason.reason_document_id.map(|id| id.to_vec()), } } @@ -256,6 +257,7 @@ pub(super) mod tests { code: Some(SUSPENSION_REASON_CODE), text: SUSPENSION_REASON.to_string(), documents: vec![], + reason_document_id: None, }, false, contract.owner_id(), diff --git a/packages/rs-drive-proof-verifier/src/types/contract_moderation.rs b/packages/rs-drive-proof-verifier/src/types/contract_moderation.rs index d24437be8cb..06777944bf3 100644 --- a/packages/rs-drive-proof-verifier/src/types/contract_moderation.rs +++ b/packages/rs-drive-proof-verifier/src/types/contract_moderation.rs @@ -225,6 +225,7 @@ pub fn reason_from_response( code, text, documents, + reason_document_id, } = reason.ok_or(Error::ResponseDecodeError { error: "contract moderation entry holds no reason".to_string(), })?; @@ -252,10 +253,22 @@ pub fn reason_from_response( }) }) .collect::, Error>>()?; + let reason_document_id = reason_document_id + .map(|id| { + Identifier::from_bytes(&id).map_err(|_| Error::ResponseDecodeError { + error: format!( + "the reason document a contract moderation reason names has an id of {} \ + bytes, not 32", + id.len() + ), + }) + }) + .transpose()?; Ok(ContractModerationReason { code, text, documents, + reason_document_id, }) } @@ -630,6 +643,7 @@ mod tests { code: None, text: "spam".to_string(), documents: vec![], + reason_document_id: None, }), warnings: vec![], }, @@ -640,6 +654,7 @@ mod tests { code: Some(3), text: String::new(), documents: vec![], + reason_document_id: None, }), warnings: vec![], }, @@ -654,6 +669,7 @@ mod tests { code: None, text: "first strike".to_string(), documents: vec![], + reason_document_id: None, }), }, ContractWarningProto { @@ -662,6 +678,7 @@ mod tests { code: None, text: "second strike".to_string(), documents: vec![], + reason_document_id: None, }), }, ], @@ -684,6 +701,7 @@ mod tests { code: Some(3), text: String::new(), documents: vec![], + reason_document_id: None, }, warnings: vec![], }, @@ -768,6 +786,7 @@ mod tests { document_type_name: "post".to_string(), document_id, }], + reason_document_id: None, }) }; let cited = entries_from_response(vec![ContractModerationEntryProto { @@ -805,6 +824,7 @@ mod tests { code: None, text: "x".repeat(4096), documents: vec![], + reason_document_id: None, }), warnings: vec![], }]) @@ -896,6 +916,7 @@ mod tests { code: None, text: "spam".to_string(), documents: vec![], + reason_document_id: None, }), document_hash: removal.document_hash.to_vec(), restoration: removal @@ -1063,6 +1084,7 @@ mod tests { code: Some(u32::from(u16::MAX) + 1), text: String::new(), documents: vec![], + reason_document_id: None, }), ] { let proto = ContractDocumentRemovalProto { diff --git a/packages/rs-drive-proof-verifier/src/unproved.rs b/packages/rs-drive-proof-verifier/src/unproved.rs index 9d07f9bb7d6..f7a3084c754 100644 --- a/packages/rs-drive-proof-verifier/src/unproved.rs +++ b/packages/rs-drive-proof-verifier/src/unproved.rs @@ -1574,11 +1574,13 @@ mod contract_moderation_tests { code: None, text: "spam".to_string(), documents: vec![], + reason_document_id: None, }), suspension_reason: Some(ContractModerationReasonProto { code: Some(9), text: "flooding".to_string(), documents: vec![], + reason_document_id: None, }), warnings: vec![], }, @@ -1600,6 +1602,7 @@ mod contract_moderation_tests { code: Some(9), text: "flooding".to_string(), documents: vec![], + reason_document_id: None, }) ); } @@ -1625,6 +1628,7 @@ mod contract_moderation_tests { code: Some(u16::MAX as u32 + 1), text: String::new(), documents: vec![], + reason_document_id: None, }), ..Default::default() }, @@ -1654,6 +1658,7 @@ mod contract_moderation_tests { code: None, text: text.to_string(), documents: vec![], + reason_document_id: None, }), }; let warned = status( @@ -1768,6 +1773,7 @@ mod contract_moderation_tests { code: None, text: "spam".to_string(), documents: vec![], + reason_document_id: None, }), } } diff --git a/packages/rs-drive/grovedb-structure.json b/packages/rs-drive/grovedb-structure.json index fda302fe679..343665de9b8 100644 --- a/packages/rs-drive/grovedb-structure.json +++ b/packages/rs-drive/grovedb-structure.json @@ -3169,7 +3169,7 @@ "EpochOwned" ], "flags_note": "The owner is the moderator who added the entry. They pay for it, and are refunded when it is removed. A suspension replaced with a longer reason passes to the moderator who replaced it, who pays for the added bytes; replaced with a shorter or an equally long one it stays the first moderator's, who is refunded the removed bytes.", - "value": "the moderator's reason: a tag byte (0 no code, 1 a code), the code as a u16 big endian when tagged, then the text as UTF-8 to the end of the value", + "value": "the moderator's reason: a tag byte (bit 0 a code, bit 1 documents, bit 2 a reason document), the code as a u16 big endian, the 32-byte reason document id and the documents cited (a count byte, then each type name as a length byte and the name, and the 32-byte id) when tagged, then the text as UTF-8 to the end of the value", "since": 14, "presence": "always", "source": "packages/rs-drive/src/drive/contract/paths.rs", diff --git a/packages/rs-drive/src/drive/contract/moderation/document_removal_tests.rs b/packages/rs-drive/src/drive/contract/moderation/document_removal_tests.rs index ed40f115612..127c5ac2fba 100644 --- a/packages/rs-drive/src/drive/contract/moderation/document_removal_tests.rs +++ b/packages/rs-drive/src/drive/contract/moderation/document_removal_tests.rs @@ -144,6 +144,7 @@ fn removal(owner: u8, moderator: u8, text: &str, removed_at: u64) -> ContractDoc code: Some(7), text: text.to_string(), documents: vec![], + reason_document_id: None, }, removed_at, document_hash: [removed_at as u8; 32], diff --git a/packages/rs-drive/src/drive/contract/moderation/mod.rs b/packages/rs-drive/src/drive/contract/moderation/mod.rs index e187d9edd3e..2e65155244f 100644 --- a/packages/rs-drive/src/drive/contract/moderation/mod.rs +++ b/packages/rs-drive/src/drive/contract/moderation/mod.rs @@ -7,6 +7,7 @@ //! ├── [0] the contract (or its history subtree) //! ├── [1] documents //! └── [2] other +//! ├── [48] moderation action counts -> -> Item(count) (elected contracts) //! ├── [64] contract version item //! ├── [128] banlist -> -> Item(reason) (when declared) //! ├── [192] suspensions -> -> Item(until ‖ reason) (when declared) @@ -26,9 +27,12 @@ //! [`types::encode_document_removal`]. The moderator pays for the record and nothing ever //! deletes it; the deleted document's own storage refund goes to nobody. //! -//! `until` is a u64 of block time in milliseconds, big-endian. A reason is a tag byte (`0`: no -//! code, `1`: a code), the code as a big-endian u16 when tagged, and the text as UTF-8 up to -//! the end of the value: see [`types::encode_ban`] and [`types::encode_suspension`]. A warning +//! `until` is a u64 of block time in milliseconds, big-endian. A reason is a tag byte (bit 0: a +//! code, bit 1: documents, bit 2: a reason document), what the tag announces, and the text as +//! UTF-8 up to the end of the value: see [`types::encode_ban`] and +//! [`types::encode_suspension`]. A moderation action count is a u32, big-endian, without +//! storage flags: the seated team's member whose action writes it pays for it, and the settle +//! of the moderators pot that deletes it refunds nobody. A warning //! list entry holds every warning the identity carries, oldest first, each its block time as a //! u64 big-endian, the length of its reason as a u16 big-endian and the reason: see //! [`types::encode_warnings`]. A warning bars nothing. diff --git a/packages/rs-drive/src/drive/contract/moderation/tests.rs b/packages/rs-drive/src/drive/contract/moderation/tests.rs index bad2a9a9dc4..611a942210b 100644 --- a/packages/rs-drive/src/drive/contract/moderation/tests.rs +++ b/packages/rs-drive/src/drive/contract/moderation/tests.rs @@ -954,6 +954,7 @@ fn should_charge_a_ban_by_the_length_of_its_reason() { code: Some(u16::MAX), text: "x".repeat(max_length), documents: vec![], + reason_document_id: None, }; let estimated = ban(0x62, &longest, false); let full = ban(0x62, &longest, true); diff --git a/packages/rs-drive/src/drive/contract/moderation/types.rs b/packages/rs-drive/src/drive/contract/moderation/types.rs index 415f1fa43b7..4b4a5bc6a73 100644 --- a/packages/rs-drive/src/drive/contract/moderation/types.rs +++ b/packages/rs-drive/src/drive/contract/moderation/types.rs @@ -308,19 +308,23 @@ pub fn decode_document_removal(value: &[u8]) -> Result Vec { let mut value = Vec::with_capacity(reason_encoded_size(reason)); encode_reason_into(reason, &mut value); @@ -440,7 +444,14 @@ fn reason_encoded_size(reason: &ContractModerationReason) -> usize { .map(|document| 1 + document.document_type_name.len() + 32) .sum::() }; - 1 + if reason.code.is_some() { 2 } else { 0 } + documents_size + reason.text.len() + 1 + if reason.code.is_some() { 2 } else { 0 } + + if reason.reason_document_id.is_some() { + 32 + } else { + 0 + } + + documents_size + + reason.text.len() } fn encode_reason_into(reason: &ContractModerationReason, value: &mut Vec) { @@ -451,10 +462,16 @@ fn encode_reason_into(reason: &ContractModerationReason, value: &mut Vec) { if !reason.documents.is_empty() { tag |= REASON_WITH_DOCUMENTS; } + if reason.reason_document_id.is_some() { + tag |= REASON_WITH_REASON_DOCUMENT; + } value.push(tag); if let Some(code) = reason.code { value.extend_from_slice(&code.to_be_bytes()); } + if let Some(reason_document_id) = reason.reason_document_id { + value.extend_from_slice(reason_document_id.as_slice()); + } if !reason.documents.is_empty() { // The count and each name fit a byte: the reason's validation bounds both, so a // longer one never reaches a writer. @@ -476,7 +493,7 @@ fn decode_reason(value: &[u8]) -> Result { let Some((&tag, mut rest)) = value.split_first() else { return Ok(ContractModerationReason::default()); }; - if tag & !(REASON_WITH_CODE | REASON_WITH_DOCUMENTS) != 0 { + if tag & !(REASON_WITH_CODE | REASON_WITH_DOCUMENTS | REASON_WITH_REASON_DOCUMENT) != 0 { return Err(format!("moderation reason has unknown tag {}", tag)); } let code = if tag & REASON_WITH_CODE != 0 { @@ -488,6 +505,15 @@ fn decode_reason(value: &[u8]) -> Result { } else { None }; + let reason_document_id = if tag & REASON_WITH_REASON_DOCUMENT != 0 { + let Some((id, after)) = rest.split_first_chunk::<32>() else { + return Err("moderation reason is cut short inside its reason document id".to_string()); + }; + rest = after; + Some(Identifier::from(*id)) + } else { + None + }; let mut documents = Vec::new(); if tag & REASON_WITH_DOCUMENTS != 0 { let Some((&count, after)) = rest.split_first() else { @@ -523,6 +549,7 @@ fn decode_reason(value: &[u8]) -> Result { code, text, documents, + reason_document_id, }) } @@ -543,6 +570,7 @@ mod tests { code: Some(0x0102), text: "spam".to_string(), documents: vec![], + reason_document_id: None, }; assert_eq!(encode_ban(&coded), [&[1u8, 1, 2][..], b"spam"].concat()); assert_eq!( @@ -555,6 +583,48 @@ mod tests { assert_eq!(decode_ban(&[0]).expect("decode").reason, empty); } + #[test] + fn should_round_trip_the_reason_document_a_reason_names() { + let named = ContractModerationReason { + code: Some(0x0102), + text: "spam".to_string(), + documents: vec![ContractModerationDocument { + document_type_name: "post".to_string(), + document_id: Identifier::from([7; 32]), + }], + reason_document_id: Some(Identifier::from([9; 32])), + }; + let value = encode_ban(&named); + // tag with all three bits, the code, the reason document id, then the documents + assert_eq!(value[0], 7); + assert_eq!(&value[1..3], &[1, 2]); + assert_eq!(&value[3..35], &[9; 32]); + assert_eq!(value[35], 1); + assert_eq!(value.len(), reason_encoded_size(&named)); + assert_eq!(decode_ban(&value).expect("decode").reason, named); + + // Alone, right after the tag. + let alone = ContractModerationReason::from_text("spam") + .with_reason_document(Identifier::from([9; 32])); + let value = encode_ban(&alone); + assert_eq!(value[0], 4); + assert_eq!(&value[1..33], &[9; 32]); + assert_eq!(&value[33..], b"spam"); + assert_eq!(decode_ban(&value).expect("decode").reason, alone); + + // A reason written before bit 2 existed reads as naming none, and one cut short + // inside the id is refused. + assert_eq!( + decode_ban(&[&[0u8][..], b"spam"].concat()) + .expect("decode") + .reason + .reason_document_id, + None + ); + assert!(decode_ban(&[4u8, 9, 9]).is_err()); + assert!(decode_ban(&[8u8]).is_err(), "an unknown tag bit is refused"); + } + #[test] fn should_round_trip_the_documents_a_reason_cites() { let cited = ContractModerationReason { @@ -570,6 +640,7 @@ mod tests { document_id: Identifier::from([8; 32]), }, ], + reason_document_id: None, }; let value = encode_ban(&cited); // tag with both bits, the code, the count, then each name (length, bytes) and id @@ -630,6 +701,7 @@ mod tests { code: Some(9), text: "flooding, second time".to_string(), documents: vec![], + reason_document_id: None, }; let value = encode_suspension(77, &reason); assert_eq!(&value[..8], &77u64.to_be_bytes()); @@ -651,6 +723,7 @@ mod tests { code: Some(3), text: String::new(), documents: vec![], + reason_document_id: None, }, }; let value = encode_warnings(&[first.clone(), second.clone()]).expect("encode"); @@ -716,6 +789,7 @@ mod tests { code: Some(3), text: "spam".to_string(), documents: vec![], + reason_document_id: None, }, removed_at: 1_700_000_000_123, document_hash: [4; 32], diff --git a/packages/rs-drive/src/drive/contract/structure.rs b/packages/rs-drive/src/drive/contract/structure.rs index dfe1d7500b0..e812c6f2b95 100644 --- a/packages/rs-drive/src/drive/contract/structure.rs +++ b/packages/rs-drive/src/drive/contract/structure.rs @@ -264,9 +264,12 @@ pub(crate) fn structure() -> StructureNode { .kind(ElementKind::Item) .flags(&[FlagsKind::EpochOwned], MODERATOR_FLAGS) .value( - "the moderator's reason: a tag byte (0 no code, 1 a \ - code), the code as a u16 big endian when tagged, \ - then the text as UTF-8 to the end of the value", + "the moderator's reason: a tag byte (bit 0 a code, bit \ + 1 documents, bit 2 a reason document), the code as a \ + u16 big endian, the 32-byte reason document id and the \ + documents cited (a count byte, then each type name as \ + a length byte and the name, and the 32-byte id) when \ + tagged, then the text as UTF-8 to the end of the value", ) .describe("One ban and why, until an unban."), ), diff --git a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs index 935b6a65d50..793d3dfa764 100644 --- a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs @@ -102,6 +102,7 @@ use dpp::consensus::state::contract_moderation::{ ContractFeeClaimNotAllowedError, ContractFeesAlreadyClaimedThisEpochError, ContractFeesNothingToClaimError, ContractModeratedDocumentTypeNotYetUsableError, ContractModerationAbilityNotGrantedError, ModerationCharterAddedModeratorLimitReachedError, + ModerationReasonNotListedError, ContractModerationNotEnabledError, ContractModerationTargetNotAllowedError, ContractModerationCounterpartyBarredError, ContractModerationTargetNotFoundError, ContractModeratorIdentityNotFoundError, @@ -710,6 +711,9 @@ pub fn from_state_error(state_error: &StateError) -> JsValue { StateError::ModerationCharterAddedModeratorLimitReachedError(e) => { generic_consensus_error!(ModerationCharterAddedModeratorLimitReachedError, e).into() } + StateError::ModerationReasonNotListedError(e) => { + generic_consensus_error!(ModerationReasonNotListedError, e).into() + } StateError::DocumentActionFeeModeratorsShareMismatchError(e) => { generic_consensus_error!(DocumentActionFeeModeratorsShareMismatchError, e).into() } diff --git a/packages/wasm-dpp2/src/data_contract/transitions/user_moderation.rs b/packages/wasm-dpp2/src/data_contract/transitions/user_moderation.rs index b30b5fb06c5..a4014c2ce46 100644 --- a/packages/wasm-dpp2/src/data_contract/transitions/user_moderation.rs +++ b/packages/wasm-dpp2/src/data_contract/transitions/user_moderation.rs @@ -41,7 +41,8 @@ export interface ContractModerationDocument { * Why a moderator banned, suspended or warned an identity, or deleted a document. Every ban, * every suspension, every warning and every document deletion carries one, and it is stored * with the entry or the removal record. Nothing checks what a moderator writes, and the - * documents a reason cites are not looked up. + * documents a reason cites are not looked up, except the reason document a seated elected + * team names, which its proposal must list. */ export interface ContractModerationReason { /** @@ -57,6 +58,13 @@ export interface ContractModerationReason { * none twice. A reason read back carries it only when there are any. */ documents?: ContractModerationDocument[]; + /** + * The `reason` document of the moderation charters contract the action is taken on, as a + * base58 string. A seated elected team's ban, suspension, warning or document deletion + * must name one its proposal lists; for every other moderator it is stored as written. A + * reason read back carries it only when there is one. + */ + reasonDocumentId?: string; } /** One warning an identity carries on a contract's warning list. */ @@ -206,6 +214,13 @@ pub fn moderation_reason_to_js(reason: &ContractModerationReason) -> JsValue { } let _ = js_sys::Reflect::set(&object, &"documents".into(), &documents); } + if let Some(reason_document_id) = reason.reason_document_id { + let _ = js_sys::Reflect::set( + &object, + &"reasonDocumentId".into(), + &JsValue::from_str(&IdentifierWasm::from(reason_document_id).to_base58()), + ); + } object.into() } @@ -252,6 +267,8 @@ pub struct ContractModerationReasonInput { text: String, #[serde(default)] documents: Vec, + #[serde(default)] + reason_document_id: Option, } impl From for ContractModerationReason { @@ -267,6 +284,7 @@ impl From for ContractModerationReason { document_id: document.document_id.into(), }) .collect(), + reason_document_id: input.reason_document_id.map(Into::into), } } } diff --git a/packages/wasm-dpp2/tests/unit/ContractUserModerationTransition.spec.ts b/packages/wasm-dpp2/tests/unit/ContractUserModerationTransition.spec.ts index 831bf2dc411..30a92f92c6b 100644 --- a/packages/wasm-dpp2/tests/unit/ContractUserModerationTransition.spec.ts +++ b/packages/wasm-dpp2/tests/unit/ContractUserModerationTransition.spec.ts @@ -23,7 +23,12 @@ interface ModerationOptions { document?: Uint8Array | null; until?: bigint; /** `null` leaves the reason out; left undefined, a ban, a suspend and a warn get `REASON` */ - reason?: { code?: number; text: string; documents?: { documentTypeName: string; documentId: string }[] } | null; + reason?: { + code?: number; + text: string; + documents?: { documentTypeName: string; documentId: string }[]; + reasonDocumentId?: string; + } | null; identityContractNonce?: bigint; userFeeIncrease?: number; } @@ -210,6 +215,20 @@ describe('ContractUserModeration', () => { expect(createTransition().reason).to.deep.equal({ code: null, text: 'spam' }); }); + it('should name the reason document a reason is taken on, and leave it out when none', () => { + const reason = { text: 'spam', reasonDocumentId: DOCUMENT_ID }; + const transition = createTransition({ action: 'ban', reason }); + + expect(transition.reason).to.deep.equal({ code: null, ...reason }); + expect(transition.toJSON().action.reason).to.deep.equal({ code: null, ...reason }); + expect(wasm.ContractUserModeration.fromBytes(transition.toBytes()).reason).to.deep.equal({ + code: null, + ...reason, + }); + // A reason naming no reason document carries no `reasonDocumentId`, as before. + expect(createTransition().reason).to.deep.equal({ code: null, text: 'spam' }); + }); + it('should keep a reason code as written, and an empty text', () => { const transition = createTransition({ reason: { code: 65535, text: '' } }); From 7ad7878140259a99fe093e00b52bbbcd43f7225e Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 24 Sep 2026 13:59:22 +0700 Subject: [PATCH 3/4] docs(platform): a seated moderation team's pot, action counts and reasons Co-Authored-By: Claude Opus 5.5 --- book/src/data-model/contract-moderation.md | 29 +++++++++++------- book/src/error-handling/error-codes.md | 2 +- docs/protocol/moderation-charters.md | 30 +++++++++++++++---- .../moderation-charters-contract/README.md | 4 +-- .../rs-platform-version/src/version/v14.rs | 21 +++++++++++++ 5 files changed, 67 insertions(+), 19 deletions(-) diff --git a/book/src/data-model/contract-moderation.md b/book/src/data-model/contract-moderation.md index 30efbb97ee3..a59b34f6c35 100644 --- a/book/src/data-model/contract-moderation.md +++ b/book/src/data-model/contract-moderation.md @@ -37,6 +37,7 @@ pub struct ContractModerationReason { pub code: Option, pub text: String, pub documents: Vec, // { document_type_name, document_id } + pub reason_document_id: Option, // a `reason` of the moderation charters contract } pub struct ContractBan { pub reason: ContractModerationReason } @@ -52,7 +53,7 @@ pub struct ContractModerationStatus { `ContractModerationConfig::lists` names the lists a contract keeps, in tree key order (banlist, suspension list, warning list); `barring_lists` the ones whose entries bar, which is every list but the warning list: what the document gate reads and what a ban's proof covers. -Every ban, every suspension and every warning carries a **reason**, stored with the entry so that whoever reads the list reads why. The `text` is free: at most `SystemLimits::max_contract_moderation_reason_length` (1024) bytes of UTF-8, possibly empty. The `code` is reserved for the ban codes a contract may declare in a later protocol version. No contract declares any today, so it is expected to be `None`; a moderator may still write any `u16` there, and nothing checks it against anything. A reason may also cite the **documents** it is about, the posts a warning or a ban is for, each by its document type name and its id: at most `SystemLimits::max_contract_moderation_reason_documents` (16), none twice, with a type name a contract could admit (`InvalidContractModerationReasonDocumentsError`, 10904, unpaid). Nothing looks them up: a cited document may have been deleted since, by its author or by a moderator whose deletion left a record, or may never have existed, and a client that wants to show it fetches it or its removal record. The moderator pays the storage of the reason, documents included, byte for byte, and gets it back when the entry is removed. +Every ban, every suspension and every warning carries a **reason**, stored with the entry so that whoever reads the list reads why. The `text` is free: at most `SystemLimits::max_contract_moderation_reason_length` (1024) bytes of UTF-8, possibly empty. The `code` is reserved for the ban codes a contract may declare in a later protocol version. No contract declares any today, so it is expected to be `None`; a moderator may still write any `u16` there, and nothing checks it against anything. The `reasonDocumentId` names a `reason` document of the moderation charters contract, the ground the action is taken on: a seated elected team's ban, suspension, warning or deletion must name one its proposal lists (see The seated team below); for every other moderator it is stored as written, looked up nowhere. A reason may also cite the **documents** it is about, the posts a warning or a ban is for, each by its document type name and its id: at most `SystemLimits::max_contract_moderation_reason_documents` (16), none twice, with a type name a contract could admit (`InvalidContractModerationReasonDocumentsError`, 10904, unpaid). Nothing looks them up: a cited document may have been deleted since, by its author or by a moderator whose deletion left a record, or may never have existed, and a client that wants to show it fetches it or its removal record. The moderator pays the storage of the reason, documents included, byte for byte, and gets it back when the entry is removed. The config is `DataContractConfig::V2`, a new variant of the config's own bincode enum inside the contract. The config version follows the platform version, as V1 did from protocol version 9: from protocol version 14 every new contract carries a V2 config, moderated or not (`CONTRACT_VERSIONS_V6` sets both `max_version` and `default_current_version` to 2), and an existing V1 contract moves to V2 with its next update. `config_valid_for_platform_version` lowers a V2 only where the platform version does not admit it, never because of what it declares. Lowering would drop a moderation declaration, and moderation can never be turned on later, so that case is refused rather than dropped: serializing a contract whose config declares moderation at a platform version below 14 (`ensure_admitted_by_platform_version`), and parsing a config value with a `moderation` key at such a version, both fail with `ProtocolError::NotSupported`. For the same reason the declaration refuses an unknown key instead of skipping it (`deny_unknown_fields`, and the moderators' `$type` map likewise): a misspelled `suspensions` would otherwise leave the contract without the list for good. A contract create or update carrying a V2 config is active from protocol version 14 only (`StateTransition::active_version_range`): before that a node rejects it at decoding, unpaid, exactly as a binary that cannot decode the V2 discriminant does, so upgraded and older nodes agree on every block before activation. The JSON shape of the moderators is a flat `{"$type": "contractOwner"}`, `{"$type": "appointedModerators", "identities": [...]}` or `{"$type": "elected", ...}` with the declaration's keys beside its `$type`, the style of `AuthorizedActionTakers`. @@ -107,7 +108,7 @@ Deletions (`Delete` and `IndexOnlyDelete`) are never refused: a barred identity ### The Errors -Basic, in their own band (10900-10949): `InvalidContractModerationConfigError` (10900), `ContractModerationSelfTargetError` (10901), `ContractModerationReasonTooLongError` (10903; 10902 is reserved), `InvalidContractModerationReasonDocumentsError` (10904). State, in their own sub-band: `ContractModerationNotEnabledError` (41100), `IdentityNotContractModeratorError` (41101), `ContractModerationTargetNotAllowedError` (41102), `ContractUserAlreadyBannedError` (41103), `ContractUserNotBannedError` (41104), `ContractUserNotSuspendedError` (41105), `ContractSuspensionNotInFutureError` (41106), `ContractUserBannedError` (41107), `ContractUserSuspendedError` (41108), `ContractModerationTargetNotFoundError` (41109), `ContractModeratorIdentityNotFoundError` (41110, from the contract create and update, not from the moderation transition), `ContractModerationCounterpartyBarredError` (41114, from the document gate; 41111 to 41113 are reserved), `ContractUserNotWarnedError` (41117), `ContractUserWarningLimitReachedError` (41118). A contract update that turns a list on or off is refused with the existing `DataContractConfigUpdateError` (40002). Elected moderation has its own band (41200-41299): `ContractModeratedDocumentTypeNotYetUsableError` (41200), `ContractModerationAbilityNotGrantedError` (41201) and `ModerationCharterAddedModeratorLimitReachedError` (41202). A discounted action fee the seated charter does not give is refused with `DocumentActionFeeModeratorsShareMismatchError` (40139), beside the other fee agreement errors. +Basic, in their own band (10900-10949): `InvalidContractModerationConfigError` (10900), `ContractModerationSelfTargetError` (10901), `ContractModerationReasonTooLongError` (10903; 10902 is reserved), `InvalidContractModerationReasonDocumentsError` (10904). State, in their own sub-band: `ContractModerationNotEnabledError` (41100), `IdentityNotContractModeratorError` (41101), `ContractModerationTargetNotAllowedError` (41102), `ContractUserAlreadyBannedError` (41103), `ContractUserNotBannedError` (41104), `ContractUserNotSuspendedError` (41105), `ContractSuspensionNotInFutureError` (41106), `ContractUserBannedError` (41107), `ContractUserSuspendedError` (41108), `ContractModerationTargetNotFoundError` (41109), `ContractModeratorIdentityNotFoundError` (41110, from the contract create and update, not from the moderation transition), `ContractModerationCounterpartyBarredError` (41114, from the document gate; 41111 to 41113 are reserved), `ContractUserNotWarnedError` (41117), `ContractUserWarningLimitReachedError` (41118). A contract update that turns a list on or off is refused with the existing `DataContractConfigUpdateError` (40002). Elected moderation has its own band (41200-41299): `ContractModeratedDocumentTypeNotYetUsableError` (41200), `ContractModerationAbilityNotGrantedError` (41201), `ModerationCharterAddedModeratorLimitReachedError` (41202) and `ModerationReasonNotListedError` (41203). A discounted action fee the seated charter does not give is refused with `DocumentActionFeeModeratorsShareMismatchError` (40139), beside the other fee agreement errors. ## Deleting Documents @@ -189,18 +190,21 @@ Two consequences follow from the document coming back byte for byte. Its `$updat └── [2] other ├── [16] document removals -> -> │ -> Item(owner id ‖ moderator id ‖ removed at ‖ document hash ‖ restored? [‖ restored by ‖ restored at] ‖ reason) (with such a document type) + ├── [48] moderation action counts -> -> Item(count) (elected contracts) ├── [64] contract version item (every contract) ├── [128] banlist -> -> Item(reason) (when declared) ├── [192] suspensions -> -> Item(until ‖ reason) (when declared) └── [224] warnings -> -> Item((warned at ‖ len ‖ reason)+) (when declared) ``` -`until` is a u64 of block time in milliseconds, big-endian. A reason is a tag byte (bit 0: a code follows, bit 1: documents follow), the code as a big-endian u16 when tagged, then when tagged the documents it cites (their count in one byte, then each one's type name as a length byte and the name, and its 32-byte id), then the text as UTF-8 up to the end of the value, so an entry with an empty reason and no code costs one byte more than the bare entry would. A value without the tag byte is an entry written before entries carried a reason and reads as the empty reason; a tag without bit 1 is a reason from before documents could be cited. A warning list entry holds every warning the identity carries, oldest first, each `warned at` as a u64 of block time in milliseconds, big-endian, the length of its encoded reason as a big-endian u16 (the prefix that lets one value hold several reasons, each of which would otherwise run to the end), then the reason as above (`types::encode_warnings`). A warn rewrites the entry one warning longer; a clearWarnings deletes it, so a stored entry never holds fewer than one warning. A document removal is the document owner's id, the moderator's id, `removed at` as a u64 of block time in milliseconds, big-endian, the 32 bytes of the document hash, a tag byte (`0`: not restored, `1`: restored) followed when restored by the restoring moderator's id and `restored at` as a u64, big-endian, then the reason the same way (`types::encode_document_removal`): 105 bytes before the reason, 145 once restored. +`until` is a u64 of block time in milliseconds, big-endian. A reason is a tag byte (bit 0: a code follows, bit 1: documents follow, bit 2: a reason document follows), the code as a big-endian u16 when tagged, the 32-byte id of the reason document when tagged, then when tagged the documents it cites (their count in one byte, then each one's type name as a length byte and the name, and its 32-byte id), then the text as UTF-8 up to the end of the value, so an entry with an empty reason and no code costs one byte more than the bare entry would. A value without the tag byte is an entry written before entries carried a reason and reads as the empty reason; a tag without bit 1 is a reason from before documents could be cited, and one without bit 2 a reason naming no reason document. A warning list entry holds every warning the identity carries, oldest first, each `warned at` as a u64 of block time in milliseconds, big-endian, the length of its encoded reason as a big-endian u16 (the prefix that lets one value hold several reasons, each of which would otherwise run to the end), then the reason as above (`types::encode_warnings`). A warn rewrites the entry one warning longer; a clearWarnings deletes it, so a stored entry never holds fewer than one warning. A document removal is the document owner's id, the moderator's id, `removed at` as a u64 of block time in milliseconds, big-endian, the 32 bytes of the document hash, a tag byte (`0`: not restored, `1`: restored) followed when restored by the restoring moderator's id and `restored at` as a u64, big-endian, then the reason the same way (`types::encode_document_removal`): 105 bytes before the reason, 145 once restored. A removal record is replaced in place, as a suspension is, by the restore that marks it and by the deletion of a restored document, which writes a fresh record over the marked one; the deletion transform reads the record, billed, to know which of the two it writes, and a record that is not marked restored beside a live document is a state no transition produces. The replacement's flags follow GroveDB's flag merge like a suspension's: the restore adds forty bytes and passes the record, with the refund of its removal, to the restoring moderator, who pays for them; the fresh record of a second deletion is shorter and stays with whoever held it. A fee estimate prices a replacement as a fresh insert of the whole record, for the reason a suspension's does, and the records a write walks past are estimated as restored, the larger shape. The document removals tree exists exactly when the contract has a document type that carries `canBeDeletedByModerators`: a contract without one keeps the other tree, and the shape, it would have had. One subtree per such document type is created with the type, by `insert_contract` generation 2 or by `update_contract` generation 2 for a type an update adds, and the tree above them with the first: whether it is there is read off the stored contract, since an existing type never changes the keyword, so the update needs no read. Nothing is created lazily by the first removal. The key sorts below `128`, as a key added later should: a contract that keeps both lists, the one whose other tree then holds four keys, still has the banlist on top. With fewer keys the version item is on top, and the list one level down. +**The moderation action counts** of an elected contract sit at `48`: one item per member of the seated team who signed a counted action since the moderators pot was last settled, its identity id to its count as a big-endian u32 (see The seated team below). The tree is created with the contract, the only time elected moderation can be declared, so it is never made lazily. Each counted action reads its signer's count with one point read and writes it one higher: an insert of 36 bytes for the member's first action of a period, a replacement of the same size after. A settle reads the whole tree, at most one item per identity the team can hold (the leader, the elected members and the additions the target allows), and deletes every item. Per-member items keep the action, far more frequent than a settle, to a four-byte write; one packed item for the team would rewrite every member's count on every action. The items carry no storage flags: the member whose action writes one pays for it, the settle that deletes it refunds nobody, and a settle's fee result carries no refunds for anyone else. The key is below `64`: created with two or three lists it leaves the banlist on top (with every list, where the version item and the suspension list alone had put the suspension list there), with or without the removal records tree; created with the banlist alone, or with the banlist and one other list beside removal records, it puts the version item on top and the banlist a level down. What sits there is read by the team's actions and by a settle, never by a document transition. + The contract's own subtree holds three keys whatever the contract keeps, so its Merk keeps `1`, the documents, on top: every document proof and write goes through that key, and a fourth key beside it would have pushed it one level down (a Merk built from one sorted batch roots at the middle key). Everything else a contract keeps goes into `2`, its **other tree**, which protocol version 14 introduces together with the version item. Inside, the keys are spread like the root tree's, so the tree stays balanced as it fills and the most read entry sits on top: the banlist at `128`, read by every document transition on a moderated contract, the version item at `64`, the suspension list at `192`, the warning list at `224`. A Merk built from one sorted batch roots at the middle key, the upper middle of an even count, so a key added later goes where it keeps `128` the median of the keys created together in the likely combinations: the warning list, which no document transition reads, sits above `192`, which leaves the banlist on top for a contract keeping the banlist and a warning list, with or without the removal records tree at `16`, and for one keeping all three lists with that tree; a contract keeping all three lists and no removal records has the suspension list on top and the banlist one level down. The other tree is written by every contract insertion, and by the migration on the first block of protocol version 14 for the contracts stored before it. A contract update finds it there, so its fee estimate writes none; applied, the update reads key `2` once, billed, rather than fail inside a block: a tree is left alone (it may hold the lists), a missing one is written. The 4.2 betas kept the version item itself at key `2`, before the other tree existed: an update of a contract that still holds that item puts the tree in its place and the item under it (`add_contract_to_storage` generation 1). Until such a contract is updated, the unproved `getDataContractsLatestVersions` reads its version from that item, and the proved form shows no version item for it. @@ -238,22 +242,22 @@ A moderation team can be paid. A document type may charge a fixed fee in credits The pots are not under the contract. The per-block total credits check (`calculate_total_credits_balance`) sums a fixed set of root sum trees, and `DataContractDocuments` is a normal tree: credits parked under a contract would leave that sum and fail every block with `CorruptedCreditsNotBalanced`. `PreFundedSpecializedBalances` is one of the summed trees, so the pots live there, in two sum trees beside the voting balances, created at genesis (state structure 4) and by the upgrade to protocol version 14 through the same helper, one after the other, so that both node populations build the same Merk. A pot is created by the first fee it receives, and so is its tree on a chain that reached protocol version 14 on a build from before the pots: that first fee checks, with a billed read, that the tree is there. The estimation of a voting balance write moves to generation 1 with them, because the prefunded balances layer now holds three trees instead of one. The two last claims are plain items of the contract's other tree, below `128` so the banlist stays on top, written by the first claim and replaced by every later one. A last claim (`ContractFeePotLastClaim`) is 42 bytes: the epoch of the claim, which the next claim is judged against, the time of its block in milliseconds, and the id of the identity that signed it. The owner pot's claimant is always the owner; the moderators pot's is whichever member of the team claimed for all of them, so the team can see who paid them and when. Every last claim has the same size, so a replacement never changes the size of the item, and the item carries no storage flags: it is never removed, and no claim adds bytes for anyone to own. -**The team** that shares the moderators pot is the set of identities the contract appoints, the owner among them only when appointed, and the owner alone when nobody is appointed (`ContractModerators::team`). It is about earnings, not authority: an owner who is not appointed still may moderate. For an elected contract it is the interim's team, and only until a charter is seated (see Elected Moderation below). `ContractFeePot::recipients` names who a payout of a pot goes to: the contract owner for the owner pot, the team for the moderators pot, nobody for the moderators pot of a contract that declares no moderation. +**The team** that shares the moderators pot is the set of identities the contract appoints, the owner among them only when appointed, and the owner alone when nobody is appointed (`ContractModerators::team`). It is about earnings, not authority: an owner who is not appointed still may moderate. For an elected contract it is the interim's team until a charter is seated, and from then on the seated team, which shares the pot by its proposal's reward split (see The seated team below). `ContractFeePot::recipients` names who a payout of a pot goes to: the contract owner for the owner pot, the team for the moderators pot, nobody for the moderators pot of a contract that declares no moderation. `ContractFeeClaim` (state transition type 25) names a contract and a pot and pays the pot out. It is signed with a CRITICAL authentication key under the signer's contract nonce, and the claimant pays its gas like any other transition. | Stage | Check | Error | |---|---|---| | Transform (state, paid) | the contract exists | `DataContractNotPresentError` (10400) | -| | the signer is a recipient of the pot: the owner for the owner pot, a member of the team for the moderators pot | 41113 | +| | the signer is a recipient of the pot: the owner for the owner pot, a member of the team for the moderators pot (the leader or an active member once a charter is seated) | 41113 | | | the pot was not paid out in this epoch yet | 41111 | | | every recipient gets at least a credit | 41112 | -The owner pot goes to the owner whole. The moderators pot is split equally between the team, and what the split leaves over, less than a credit per member, stays in the pot for the next claim, so no member is favoured by the order of the identity ids. Each pot is paid out at most once per epoch and the two are independent: the owner's claim does not use up the team's, nor the reverse. A refused claim is paid for by a nonce bump and leaves the pot and its last claim alone. As for moderation, state validation *is* the transform, so the mempool refuses with the same codes as a block. +The owner pot goes to the owner whole. The moderators pot is split equally between the team, and what the split leaves over, less than a credit per member, stays in the pot for the next claim, so no member is favoured by the order of the identity ids. A seated team's pot is split by its proposal's reward split instead, rounded down the same way. Each pot is paid out at most once per epoch and the two are independent: the owner's claim does not use up the team's, nor the reverse. A refused claim is paid for by a nonce bump and leaves the pot and its last claim alone. As for moderation, state validation *is* the transform, so the mempool refuses with the same codes as a block. The team is read when the claim executes. An owner who changes the appointed set by a contract update and then claims pays the new set: that follows from the owner controlling the contract's config, and is not prevented. The claim credits every recipient's balance, which is why a named moderator must exist (41110): crediting a balance that is not there is an internal error. -The proof of a claim's execution shows the pot with its last claim and the balance of every recipient, which the prover and the verifier both read from the contract. `VerifiedContractFeeClaim` carries the contract id, the pot, that last claim (epoch, block time, claimant), the credits left in the pot and the balances. A pot that was never claimed proves no claim; a later claim of the same pot verifies just the same, so the result is classified as affected state. +The proof of a claim's execution shows the pot with its last claim and the balance of every recipient, which the prover and the verifier both read from the contract. For the moderators pot of an elected contract it shows the claimant's balance alone: the team a seated charter pays is the charter contract's, which the contract does not name, so neither side could list it (`ContractFeePot::claim_proof_identities`). `VerifiedContractFeeClaim` carries the contract id, the pot, that last claim (epoch, block time, claimant), the credits left in the pot and the balances. A pot that was never claimed proves no claim; a later claim of the same pot verifies just the same, so the result is classified as affected state. ### Reading the Pots @@ -300,14 +304,16 @@ The declaration lives in `packages/rs-dpp/src/data_contract/config/moderation/el - **With what.** The team holds the abilities the declaration gives it and no others. A deletion or a restore needs `deleteDocuments` on the document type; a ban, a suspension or a warning, or lifting one, needs the ability on some moderated type, since the lists are contract-wide. Anything else is refused, paid, with `ContractModerationAbilityNotGrantedError` (41201). - **Who is protected.** The leader and the active members can be neither put on a list nor have their documents deleted (41102), and the owner too when the declaration sets `ownerProtected`. The interim moderators lose the protection they had. - **How many join later.** The leader adds members from the proposal's join requests, at most the target's `maxAddedModerators` at a time, counting the charter's additions that exist now: the leader takes an added member off by deleting its addition, which frees the slot. An elected member is taken off with a `removedModerator`, which may only name one of the charter's `members` and puts the member back when deleted. The schema cannot count documents, so the batch's state validation refuses the addition past the cap, paid, with `ModerationCharterAddedModeratorLimitReachedError` (41202), after reading the charter, its target and at most the cap's number of additions, all billed; additions an earlier create of the same batch was accepted for count too. Like a unique index conflict it is judged in the block, not in the mempool, which runs no state validation for a batch. +- **On what grounds.** Every ban, suspension, warning and document deletion of the team names, in its reason's `reasonDocumentId`, a `reason` document its proposal lists: the grounds it asked to be elected on. Any other is refused, paid, in a block and in the mempool (`ModerationReasonNotListedError`, 41203), a reason naming none included; a proposal listing no reason is a team that can take no such action. The proposal is read, billed, only when the reason names a document. Lifting a ban, a suspension or warnings and restoring a document carry no reason and are not checked, and the interim is not bound before the seating. - **What it charges.** An action on a moderated type may agree to the charter's `moderatorsShare` of the declared moderators part instead of the whole of it, and is then charged that (see [Document action fees](../fees/overview.md#document-action-fees)). An action agreeing to the declared amount reads no charter. -- **The pot.** The interim team claims the moderators pot only until a charter is seated; its claim is refused after (41113), so the pot carries over to the seated team, unsettled. How the seated team claims it, split by its proposal's `rewardSplit`, is not built yet. +- **The pot.** The interim team claims the moderators pot only until a charter is seated; its claim is refused after (41113), so the pot carries over to the seated team, unsettled. From then on the leader or an active member claims it for the team, at most once per epoch, and it is paid out by the proposal's `rewardSplit`: the leader share to the leader; the equal share in equal parts to the other active members, or to the leader when it has none; and the action share between the whole team, the leader included, in proportion to the bans, suspensions, warnings and document deletions each one signed since the last settle (the counts of the other tree's key `48`), or equally when nobody acted. Lifting and restoring do not count. Every share and every part rounds down to the credit; the few credits left stay in the pot for the next settle. A claim that would pay nobody a credit is refused (41112). The settle reads the team (the charter's removals and additions), the proposal and the counts, all billed, and deletes the counts. +- **Settled before every change.** An `addedModerator` or `removedModerator` created or deleted pays the pot out to the team as it was first, the same way, and resets the counts: a removed member is paid for what it did, a new one shares nothing earned before it came, one coming back nothing earned while it was away. The settle ignores the once-per-epoch limit and is not a claim: it writes no last claim, and the team may still claim in the same epoch. It is an effect, never a refusal, judged by the batch's state validation once the change passed (the addition its cap too), which the mempool does not run; at most one per target contract per batch. **Referencing an elected contract.** A document type that must point at a contract of this kind says so in its reference: `"refersTo": { "type": "contract", "contractRequirements": { "moderation": "elected" } }`. `contractRequirements` holds what the referenced contract must declare beyond existing, each key an aspect of the contract with a closed set of values or a bound: `moderation: "elected"`, or `moderation: "electionOpen"`, which also requires the contract's own election delay to have passed since its creation, or the contract to declare none (the delay between a contract's creation and the first charter against it, so a team cannot be seated before anyone has seen the contract, set by each contract for itself). Both have a user in the charter contract: a charter proposal only needs the target to be `elected`, so teams can form during the notice, and the charter that opens the contest needs its election `electionOpen`; `minimumAgeSeconds`, a number of seconds the reference fixes, which requires the contract's recorded creation time to be at least that far before the block time of the write; `minimumSecondsSinceUpdate`, the same of the later of the contract's creation and last update times (any update restarts the clock; an elected declaration can not be added by an update, so this one is for other uses than the charter); `owner`, `"self"` requiring the referenced contract to be owned by the writer of the referring document (its `$ownerId`, a write gate like the `$ownerId` property agreement of a document reference) and `"other"` by anyone else (so a charter may forbid an owner from chartering its own team); `readonly: true`, requiring the referenced contract's config to be read-only, one that can never be updated again (which makes `minimumSecondsSinceUpdate` moot for the same target); `keepsHistory: true`, requiring its config to keep history (only `true` is declarable for either flag); and `ownerProtected`, requiring the contract's elected moderation declaration to protect the owner from the team (`true`) or to leave it unprotected (`false`), which implies elected moderation without the schema having to say so, a contract without an elected declaration meeting neither value. A contract created before contracts recorded their creation time never meets a duration, its own election delay included. Consensus checks them when the referring document is written, against the contract it has already fetched for the existence check and the write itself (its owner and block time), so they cost no further read; a contract that exists but does not meet a requirement refuses the write, paid, with `ReferencedContractRequirementNotMetError` (40135) naming the requirement, where a contract that does not exist is still 40120. A changed `contractRequirements` is an incompatible schema change on update, like the rest of a `refersTo`. The charter system contract's `targetContractId` is the first user. **Referencing an identity key with requirements.** The same shape serves the key references the charter contract needs: `"refersTo": { "type": "identityPublicKey", "keyIdProperty": "recipientKeyId", "keyRequirements": { "purpose": "decryption", "boundTo": "submittedCharter" } }`. `keyRequirements` holds what the referenced key must be beyond existing and not being disabled, each key an aspect of the key: `purpose`, the key's purpose by its wire name (`authentication`, `encryption`, `decryption`, `transfer`, `voting` or `owner`; never `system`), and `boundTo`, the name of a document type of the declaring contract, which requires the key's contract bounds to be exactly the declaring contract and that document type; a whole-contract bound or a contract group bound never meets it, even where the group holds the type, since the check reads nothing beyond the key. Registration (`create_document_types_from_document_schemas` 1, a post-pass edited in place since it is inert before protocol version 14, under full validation like the meta-schema) checks that `boundTo` names a document type the contract has, so the write-time check never needs a second contract fetch, and that a key meeting the pair can exist at all: only authentication, encryption and decryption keys carry a document type bound, and Drive registers an encryption or decryption key bound to a document type only when that type declares `requiresIdentityEncryptionBoundedKey` or `requiresIdentityDecryptionBoundedKey`, so a `boundTo` paired with `transfer`, `voting` or `owner`, or with an encryption purpose on a type without the matching keyword, is refused as a requirement no key could ever meet. Consensus checks the requirements when the referring document is written, against the key it has already fetched for the existence check, so they cost no further read; a key that exists and is enabled but does not meet one refuses the write, paid, with `ReferencedIdentityKeyRequirementNotMetError` (40136) naming the document type, the property, the requirement and what the key has, where a missing key is still 40123 and a disabled one 40124. A replace that repoints the reference at another key, through either the identity id or the key id, re-checks them. A changed `keyRequirements` is an incompatible schema change on update, like the rest of a `refersTo`. New requirements (a security level, say) are new keys of the same object, never a new reference type. The charter contract's `joinRequest.recipientId` (a decryption key bound to `submittedCharter`) is the first user. -**What comes next.** The seated team's claim of the moderators pot, split by its proposal's `rewardSplit` with action counters and settled before every change of the team; the check that every moderation action names a reason the seated proposal lists; the election parameters (the windows and the application fund) read from the target contract; and, after protocol version 14, challenges and amendments. Issue #4865 holds the design. +**What comes next.** After protocol version 14, challenges and amendments, and threshold actions. Issue #4865 holds the design. ## Versioning Touchpoints @@ -315,11 +321,11 @@ All in place for protocol version 14: `CONTRACT_VERSIONS_V6` makes config V2 the The document deletion adds, all for protocol version 14 as well: the `canBeDeletedByModerators` keyword in meta-schema v3 (`CONTRACT_VERSIONS_V6` already selects it); five slots in `DriveContractModerationMethodVersions` and one in the verify and query tables; and `batch_operations.apply_drive_operations = 1` in `DRIVE_VERSION_V9`, the generation that forfeits the refund. The transition's own tables do not move: the action joins a transition no release contains. -Elected moderation moves no table: the declaration is a variant of the same config V2, `validate_moderation_config` v0 and `validate_config_update` 2 take it on in place while protocol version 14 is unreleased, `contract_moderation_gate` v0 runs the interim block, and `SYSTEM_LIMITS_V4` gains the four bounds of the windows and the cool-down. The seated team moves none either: the moderation transition's state v0, the claim's, the gate v0 and the batch transformer's state v2 read the charter in place, all generations no release selects; the cap on additions is a hook in the batch's shipped `validate_state` v0 that only a create of the charter contract reaches, a contract absent from state before protocol version 14. +Elected moderation moves no table: the declaration is a variant of the same config V2, `validate_moderation_config` v0 and `validate_config_update` 2 take it on in place while protocol version 14 is unreleased, `contract_moderation_gate` v0 runs the interim block, and `SYSTEM_LIMITS_V4` gains the four bounds of the windows and the cool-down. The seated team moves none either: the moderation transition's state v0, the claim's, the gate v0 and the batch transformer's state v2 read the charter in place, all generations no release selects; the cap on additions is a hook in the batch's shipped `validate_state` v0 that only a create of the charter contract reaches, a contract absent from state before protocol version 14. The pot, the counts and the reasons add four slots to `DriveContractModerationMethodVersions` (`set_contract_moderation_action_count`, `fetch_contract_moderation_action_counts`, `remove_contract_moderation_action_counts` and their estimation), `0` at every version. The forced settle is a second hook in the same `validate_state` v0, reached only by a create or delete of the charter contract's team changes; the claim's action, the moderation transition's action and the batch action carry what they settled into converters no release selects (`contract_fee_claim_transition` 0, `contract_user_moderation_transition` 0, `documents_batch_transition` 1); and the claim's arm of the shipped `prove_state_transition` v0 and `verify_state_transition_was_executed_with_proof` v0 proves the claimant alone for an elected contract, a transition no earlier version admits. ## What Is Not There Yet -Deleting indexOnly documents (the action would have to carry the owner and the values), deleting every document of an identity at once, action fees on token transitions, group-based moderators (`AuthorizedActionTakers::Group` through group actions), keys bound to the contract allowed to sign its moderation, ban codes declared by the contract (the reason's `code` is where they will go), the moderator's id on a ban or a suspension (a warning carries its block time but not who issued it), retracting one warning rather than all, a warning that expires by the clock, a contract-declared strike count that turns warnings into a suspension, the seated team's claim of the moderators pot and the reason its actions must name, challenges and amendments of a seated charter, and the Swift and Kotlin SDKs. The refusal a barred identity receives (41107, 41108, 41114) does not repeat the reason: the status query does. +Deleting indexOnly documents (the action would have to carry the owner and the values), deleting every document of an identity at once, action fees on token transitions, group-based moderators (`AuthorizedActionTakers::Group` through group actions), keys bound to the contract allowed to sign its moderation, ban codes declared by the contract (the reason's `code` is where they will go), the moderator's id on a ban or a suspension (a warning carries its block time but not who issued it), retracting one warning rather than all, a warning that expires by the clock, a contract-declared strike count that turns warnings into a suspension, a query of the moderation action counts (a client reads them with a raw GroveDB proof today), challenges and amendments of a seated charter, and the Swift and Kotlin SDKs. The refusal a barred identity receives (41107, 41108, 41114) does not repeat the reason: the status query does. ## Tests @@ -329,5 +335,6 @@ Deleting indexOnly documents (the action would have to carry the owner and the v - `packages/rs-dpp/src/data_contract/config/moderation/mod.rs` and `config/methods/validate_update/v2`: the declaration's rules and the update rules, the elected declaration's among them (every bound, the moderated set, the envelope, the maximums, the interim set, the wire shape, and an update refused for each field and for entering or leaving); `moderation/elected.rs`: what each interim kind allows. - `packages/rs-drive/src/drive/contract/moderation/tests.rs`: tree creation on insert, the trees and their entries surviving a contract update, every writer with estimation, status and page proofs, paging, the refund going to the first moderator after another one replaces its suspension, a status proof over one list saying nothing about the other, the warning list tree created only when declared, warnings accumulating under the moderator that warned last and cleared with a refund to it, a warn never estimated below its cost up to the fullest entry, and the banlist on top of the other tree with every combination of lists. - `packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/transformer/v0/contract_moderation_gate/mod.rs`: the gate is silent before protocol version 14 and for an unmoderated contract, refuses each barred operation of one batch on its own while keeping the deletions, and blocks the moderated types of an elected contract in its interim without reading the lists for them. +- `packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team/pot.rs`: a seated team's claim split by its reward split with every part rounded down and the remainder left in the pot, the equal split of the action share when nobody acted, the counts per signer (counted actions only, not the interim's) reset by a claim and by a change of the team, the settle before an addition, before a removal and before either is undone (in an epoch already claimed, and leaving the epoch's claim to the team), and the claim's proof with the claimant's balance; `seated_team/reasons.rs`: a seated team's bound action refused without a listed reason in a block and in the mempool, a proposal with no reason, reversals and the interim unbound; `packages/rs-dpp/src/moderation_charter/reward_split.rs`: the split's arithmetic; `packages/rs-drive/src/drive/contract/moderation/action_count_tests.rs`: the counts tree created with an elected contract only, written, read, bounded and reset, and the banlist on top of an elected contract's other tree. - `packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team.rs`: a contest for an elected contract's seat awarded, then the leader and the members moderating instead of the interim, additions and removals, the protection of the team, the cap on additions, abilities the declaration does not give, the interim block ending, a discounted fee charged and read where the declared one reads nothing, every other discount refused in a block and on recheck, and the interim's claim refused once a charter is seated. - `packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests.rs`: the whole pipeline, including a warned user carrying on with its warnings accumulating, proved and cleared, the warning limit and the clearing that lifts it, warnings kept through a ban and out of the gate and the ban's proof, every refusal of a warn, and the warning list fixed at creation; the moderators' window (a deletion to the millisecond it ends on, refused one later for the contract owner too while the author's own still passes, reopened by a replace, measured from `$createdAt` on a type that never changes, fixed on update), a moderator deleting a post (record, execution proof, the author's balance unchanged, and the control where the author deletes it and is refunded), every refusal of a deletion, an update adding a document type moderators can delete from, a permanent reference to such a type refused, the mempool refusal, the lapse sweep, the moderator set, every refusal code, the lists staying as the contract was created with them, a barred identity deleting its own documents in a block and in the mempool, a barred identity refused as the recipient of a transfer and as the seller of a purchase, the ban's proof covering the suspension it removed, lifting the entry of an identity an update made moderator, the per-list execution proof, a named owner, a create or an update naming a moderator that does not exist, an update keeping its moderators, inactivity of the transition and of a moderated contract create or update before protocol version 14, and elected moderation (each interim kind moderating or not, the block of a moderated type next to an unmoderated one in a block and in the mempool, a create refused outside a bound and for an unknown type, and an update refused for a changed field and for entering or leaving). diff --git a/book/src/error-handling/error-codes.md b/book/src/error-handling/error-codes.md index 9461ea31be0..83b58e34750 100644 --- a/book/src/error-handling/error-codes.md +++ b/book/src/error-handling/error-codes.md @@ -118,7 +118,7 @@ The fee category currently has a single code. The 30000 range is reserved for fu | 40900-40904 | Shielded | `InvalidAnchorError` (40900), `NullifierAlreadySpentError` (40901), `InsufficientShieldedFeeError` (40904) | | 41000-41003 | Contract Groups | `ContractGroupAlreadyExistsError` (41000), `ContractGroupNotFoundError` (41001), `IdentityNotContractGroupOwnerOrAdminError` (41002), `ContractGroupAdminNotFoundError` (41003) | | 41100-41122 | Contract Moderation | `ContractModerationNotEnabledError` (41100), `IdentityNotContractModeratorError` (41101), `ContractUserBannedError` (41107), `ContractUserSuspendedError` (41108), `ContractModerationTargetNotFoundError` (41109), `ContractModeratorIdentityNotFoundError` (41110), `ContractFeesAlreadyClaimedThisEpochError` (41111), `ContractFeesNothingToClaimError` (41112), `ContractFeeClaimNotAllowedError` (41113), `ContractModerationCounterpartyBarredError` (41114), `DocumentTypeNotDeletableByModeratorsError` (41115), `DocumentModerationWindowElapsedError` (41116), `ContractUserNotWarnedError` (41117), `ContractUserWarningLimitReachedError` (41118), `ContractDocumentRemovalNotFoundError` (41119), `DocumentRestoreWindowElapsedError` (41120), `DocumentRestoreHashMismatchError` (41121), `ContractDocumentAlreadyRestoredError` (41122) | -| 41200-41299 | Contract Moderation Teams | `ContractModeratedDocumentTypeNotYetUsableError` (41200), `ContractModerationAbilityNotGrantedError` (41201), `ModerationCharterAddedModeratorLimitReachedError` (41202) | +| 41200-41299 | Contract Moderation Teams | `ContractModeratedDocumentTypeNotYetUsableError` (41200), `ContractModerationAbilityNotGrantedError` (41201), `ModerationCharterAddedModeratorLimitReachedError` (41202), `ModerationReasonNotListedError` (41203) | Notice how the `DataTriggerError` sub-enum has its own `ErrorWithCode` implementation that the `StateError` delegates to: diff --git a/docs/protocol/moderation-charters.md b/docs/protocol/moderation-charters.md index 7b4147e9f29..c88c36ce988 100644 --- a/docs/protocol/moderation-charters.md +++ b/docs/protocol/moderation-charters.md @@ -66,7 +66,7 @@ A ground for a moderation action. | Property | Type | Meaning | | --- | --- | --- | -| `code` | string, three uppercase letters, required | Unique among the owner's reasons (`byOwnerCode`, unique on `$ownerId` and `code`); what an action shows | +| `code` | string, three uppercase letters, required | Unique among the owner's reasons (`byOwnerCode`, unique on `$ownerId` and `code`); what an action shows. An action names the reason by its document id, in its reason's `reasonDocumentId` | | `label` | string, 1 to 64 characters, required | The reason's name, such as Spam | | `description` | string, 1 to 1024 characters | What the reason covers and how the team applies it | @@ -85,7 +85,7 @@ bound to it, the key join requests are encrypted to. | `description` | string, 1 to 4096 characters and at most 4096 bytes (`maxBytes`), required | What the team would moderate and how, for joiners and voters. Informational | | `reasons` | typed array of at most 64 unique identifiers, required, each `refersTo` a `reason` | The moderation reasons the team's actions may name; empty is allowed, a team that can take no action; a missing reason refuses the create, naming the element (`reasons[2]`) | | `moderatorsShare` | integer 0 to 100 | The percentage of each moderated document type's declared moderators fee the team takes, rounded down to the credit. Absent is the full amount; a lower number is a discount an action may agree to once the team is seated; 0 is a team that will not moderate and takes no rewards | -| `rewardSplit` | object, required | `leader`, `equal` and `actions`, three percentages summing to 100: the leader's share, the share split equally among the other members, and the share split by each member's action count. The sum is the type's `propertyConstraints` rule `rewardSplitIsWhole`, checked on every create (`DocumentPropertyConstraintViolatedError`, 10422) | +| `rewardSplit` | object, required | `leader`, `equal` and `actions`, three percentages summing to 100: the leader's share, the share split equally among the other members (the leader's when it has none), and the share split between the whole team, the leader included, by each one's action count since the last settle (equally when nobody acted). The sum is the type's `propertyConstraints` rule `rewardSplitIsWhole`, checked on every create (`DocumentPropertyConstraintViolatedError`, 10422) | Indexes: `byTargetContract` (`targetContractId`, `$createdAt`) lists the proposals for a contract in filing order; `byOwner` (`$ownerId`) lists a @@ -226,9 +226,28 @@ replaced). The moderation paths of the target read it: at the cost of the charter lookup and the proposal fetch (`DocumentActionFeeModeratorsShareMismatchError`, 40139, for any other amount, and for a discount with no seated charter). +- **Reasons.** Every ban, suspension, warning and document deletion of the + team names, in its reason's `reasonDocumentId`, a `reason` document the + seated proposal lists; any other is refused, paid, in a block and in the + mempool (`ModerationReasonNotListedError`, 41203), a reason naming none + included, so a proposal listing no reason can take no such action. The + proposal is read, billed, only when a reason document is named. Lifting and + restoring carry no reason and are not checked, and the interim is not bound. - **The pot.** The interim team's claim of the moderators pot is refused once - a charter is seated (41113); the pot waits for the seated team, whose claim - comes in a later pull request. + a charter is seated (41113); the pot carries over to the seated team. The + leader or an active member claims it for the team, at most once per epoch, + and it is paid out by the proposal's `rewardSplit`: the leader share to the + leader, the equal share in equal parts to the other active members (to the + leader when there are none), and the action share between the whole team + by the bans, suspensions, warnings and document deletions each one signed + since the last settle, equally when nobody acted. Every share and every + part rounds down to the credit; what is left stays in the pot. The counts + live under the target contract (key `48` of its other tree) and every + settle deletes them. +- **Settles before team changes.** Creating or deleting an `addedModerator` + or a `removedModerator` first pays the pot out to the team as it was, the + same way, and resets the counts, whatever the epoch's claim: the settle + writes no last claim, and the team may still claim in the same epoch. - **Resignations.** A `resignationRequest` changes nothing by itself: the leader acts on it by deleting the member's `addedModerator`, or with a `removedModerator` for an elected member. @@ -241,7 +260,8 @@ written, the description's 4096-byte cap and the reward split's sum included: `DocumentPropertyMaxBytesExceededError` (10421), and the `propertyConstraints` rule `rewardSplitIsWhole` refuses a split that does not add up to 100 with `DocumentPropertyConstraintViolatedError` (10422). The cap on additions is the -exception (see above). `validate_submitted_charter` in `rs-dpp` +exception (see above), and the settle a team change forces is an effect of the +change, not a rule on it (see [Seating](#seating)). `validate_submitted_charter` in `rs-dpp` (`packages/rs-dpp/src/moderation_charter/`) only reads a proposal, without reading state: diff --git a/packages/moderation-charters-contract/README.md b/packages/moderation-charters-contract/README.md index a2d4e8e1bbe..7e2122d54c5 100644 --- a/packages/moderation-charters-contract/README.md +++ b/packages/moderation-charters-contract/README.md @@ -31,7 +31,7 @@ A ground for a moderation action. Anyone may file one. | Property | Type | Meaning | | --- | --- | --- | -| `code` | string, 3 uppercase letters, required | Unique among the owner's reasons (`byOwnerCode`); what an action shows | +| `code` | string, 3 uppercase letters, required | Unique among the owner's reasons (`byOwnerCode`); what an action shows. An action names a reason by document id (`reasonDocumentId`), and a seated team only one its proposal lists (41203) | | `label` | string, 1 to 64 characters, required | The reason's name | | `description` | string, 1 to 1024 characters | What the reason covers and how the team applies it | @@ -48,7 +48,7 @@ decryption key bound to this type so join requests can be encrypted to it. | `description` | string, 1 to 4096 characters and at most 4096 bytes, required | What the team would moderate and how. Informational | | `reasons` | array of at most 64 unique reason ids, required, each `refersTo` a `reason` | The moderation reasons the team's actions may name; a team with none can take no action | | `moderatorsShare` | integer 0 to 100 | The percentage of each moderated type's declared moderators fee the team takes; absent is the full amount, 0 a team that will not moderate and takes no rewards | -| `rewardSplit` | object, required | `leader`, `equal` and `actions` percentages summing to 100 (the `rewardSplitIsWhole` rule of `propertyConstraints`) | +| `rewardSplit` | object, required | `leader`, `equal` and `actions` percentages summing to 100 (the `rewardSplitIsWhole` rule of `propertyConstraints`): how every settle of the target's moderators pot is paid out, a claim or a team change | Indexes: `byTargetContract` (target, `$createdAt`) lists the proposals for a contract in filing order; `byOwner` lists a leader's proposals. diff --git a/packages/rs-platform-version/src/version/v14.rs b/packages/rs-platform-version/src/version/v14.rs index b55e660d12d..7a7c00bbca3 100644 --- a/packages/rs-platform-version/src/version/v14.rs +++ b/packages/rs-platform-version/src/version/v14.rs @@ -1078,6 +1078,27 @@ pub const PROTOCOL_VERSION_14: ProtocolVersion = 14; /// but for the shipped batch `validate_state` v0, which no batch of an /// earlier version reaches through the new hook. /// +/// 41. **A seated team's pot, action counts and reasons**: the leader or an +/// active member of a seated team claims the moderators pot for the team, +/// and it is split by the proposal's `rewardSplit`: the leader share to the +/// leader, the equal share between the other members (the leader's when it +/// has none), and the action share between the whole team by each one's +/// count of bans, suspensions, warnings and document deletions since the +/// last settle, equally when nobody acted. Every part rounds down and the +/// remainder stays in the pot. The counts are `member id -> u32` items +/// without storage flags under key `48` of an elected contract's other tree, +/// created with the contract (`insert_contract_moderation_trees` v0), and +/// every settle deletes them. An `addedModerator` or `removedModerator` +/// created or deleted settles the pot first, to the team as it was, by a +/// hook in the batch's `validate_state` v0 beside the cap on additions: it +/// ignores the once-per-epoch limit and writes no last claim. The proof of a +/// claim of an elected contract's moderators pot shows the claimant's +/// balance alone. A moderation reason gains `reasonDocumentId` (tag bit 2 +/// where it is stored), and a seated team's ban, suspension, warning or +/// deletion must name a `reason` document its proposal lists +/// (`ModerationReasonNotListedError`, 41203). No table moves but the four +/// new Drive method slots, `0` at every version. +/// /// The app-connect system contract (`SystemDataContract::AppConnect`, schema v1) /// carries only the wallet's `loginKeyResponse`: a flat indexOnly entry keyed by /// the app's ephemeral key hash and the responding identity, with the wallet's From 9995499ffb11892356216e76dd4285aa69de9c30 Mon Sep 17 00:00:00 2001 From: Quantum Explorer Date: Thu, 24 Sep 2026 14:38:38 +0700 Subject: [PATCH 4/4] fix(platform)!: address review of the moderation pot, counts and reasons - An elected contract without a counts tree (stored before the counts existed, on a development network) reads as having no counts, and its team's actions go uncounted, instead of failing inside Drive. - The claim proof shows every recipient the contract names when the claimant is one of them (interim claims keep full coverage), the claimant alone otherwise (a seated team's member). - A seated claim reads the team once; the cap on additions and the settle an addition forces share one read of the charter and its target. - Entry size estimates count the reason document id; the share reader goes through the proposal reader; the batch converter takes its settlements. - SDK docs describe the seated split and the claimant-only proof. Co-Authored-By: Claude Opus 5.5 --- book/src/data-model/contract-moderation.md | 2 +- packages/js-evo-sdk/src/contracts/facade.ts | 9 +- .../document_type/action_fees/mod.rs | 22 ++-- .../common/seated_moderation_charter/mod.rs | 98 ++++++++--------- .../batch/state/v0/added_moderator_cap.rs | 75 +++---------- .../state_transitions/batch/state/v0/mod.rs | 6 ++ .../batch/state/v0/moderators_pot_settle.rs | 59 +++------- .../batch/state/v0/seated_charter_reads.rs | 101 ++++++++++++++++++ .../contract_fee_claim/state/v0/mod.rs | 27 +++-- .../contract_user_moderation/state/v0/mod.rs | 7 +- .../contract/moderation/action_count_tests.rs | 22 +++- .../mod.rs | 9 +- .../v0/mod.rs | 66 +++++++++--- .../src/drive/contract/moderation/types.rs | 10 +- .../prove/prove_state_transition/v0/mod.rs | 12 +-- .../document/documents_batch_transition.rs | 9 +- .../src/state_transition_action/batch/mod.rs | 7 ++ .../v0/mod.rs | 7 +- .../rs-platform-version/src/version/v14.rs | 11 +- .../platform/transition/contract_fee_claim.rs | 13 ++- .../src/state_transitions/contract.rs | 18 ++-- 21 files changed, 366 insertions(+), 224 deletions(-) create mode 100644 packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/seated_charter_reads.rs diff --git a/book/src/data-model/contract-moderation.md b/book/src/data-model/contract-moderation.md index a4e822bb21b..355292ede7c 100644 --- a/book/src/data-model/contract-moderation.md +++ b/book/src/data-model/contract-moderation.md @@ -257,7 +257,7 @@ The owner pot goes to the owner whole. The moderators pot is split equally betwe The team is read when the claim executes. An owner who changes the appointed set by a contract update and then claims pays the new set: that follows from the owner controlling the contract's config, and is not prevented. The claim credits every recipient's balance, which is why a named moderator must exist (41110): crediting a balance that is not there is an internal error. -The proof of a claim's execution shows the pot with its last claim and the balance of every recipient, which the prover and the verifier both read from the contract. For the moderators pot of an elected contract it shows the claimant's balance alone: the team a seated charter pays is the charter contract's, which the contract does not name, so neither side could list it (`ContractFeePot::claim_proof_identities`). `VerifiedContractFeeClaim` carries the contract id, the pot, that last claim (epoch, block time, claimant), the credits left in the pot and the balances. A pot that was never claimed proves no claim; a later claim of the same pot verifies just the same, so the result is classified as affected state. +The proof of a claim's execution shows the pot with its last claim and the balance of every recipient, which the prover and the verifier both read from the contract. When the claimant is not among them, it shows the claimant's balance alone: the claimant is then on a seated elected team, which the charter contract names and the contract does not, so neither side could list the other payees (`ContractFeePot::claim_proof_identities`). An interim team's claim, before a charter is seated, is proved with every recipient's balance as before. `VerifiedContractFeeClaim` carries the contract id, the pot, that last claim (epoch, block time, claimant), the credits left in the pot and the balances. A pot that was never claimed proves no claim; a later claim of the same pot verifies just the same, so the result is classified as affected state. ### Reading the Pots diff --git a/packages/js-evo-sdk/src/contracts/facade.ts b/packages/js-evo-sdk/src/contracts/facade.ts index e350da749b5..d47c4468913 100644 --- a/packages/js-evo-sdk/src/contracts/facade.ts +++ b/packages/js-evo-sdk/src/contracts/facade.ts @@ -264,9 +264,12 @@ export class ContractsFacade { /** * Pays out a fee pot of a contract: the `owner` pot whole to the contract owner, who alone - * may claim it, and the `moderators` pot in equal shares to the contract's moderation team, - * any member of which may claim it for all of them. Signed with a CRITICAL authentication - * key. A pot is paid out at most once per epoch, and an empty pot refuses the claim. + * may claim it, and the `moderators` pot in equal shares to the contract's moderation team + * (by the proposal's reward split for an elected contract's seated team), any member of + * which may claim it for all of them. Signed with a CRITICAL authentication key. A pot is + * paid out at most once per epoch, and an empty pot refuses the claim. The result proves + * the balance of every recipient the contract names, or of the claimant alone for a seated + * elected team, which the contract does not name. */ async claimFees(options: wasm.ContractClaimFeesOptions): Promise { const w = await this.sdk.getWasmSdkConnected(); diff --git a/packages/rs-dpp/src/data_contract/document_type/action_fees/mod.rs b/packages/rs-dpp/src/data_contract/document_type/action_fees/mod.rs index 93c7fd44ebf..2dbcee841b6 100644 --- a/packages/rs-dpp/src/data_contract/document_type/action_fees/mod.rs +++ b/packages/rs-dpp/src/data_contract/document_type/action_fees/mod.rs @@ -129,22 +129,22 @@ impl ContractFeePot { } /// The identities whose balances the proof of a claim of this pot of `contract` by - /// `claimant_id` shows: the recipients, or for the moderators pot of an elected contract - /// the claimant alone. The team a seated charter pays is the charter contract's, which the - /// contract does not say, so neither the prover nor the verifier could name it; the - /// claimant, a member of whichever team claimed, is in the transition. + /// `claimant_id` shows: the recipients the contract names, when the claimant is one of + /// them, as it is for every claim of the owner pot, of a declared team's moderators pot and + /// of an elected contract's interim team before a charter is seated. Otherwise the claimant + /// alone: the claimant of an elected contract's moderators pot is then on the seated team, + /// which the charter contract names and the contract does not, so neither the prover nor + /// the verifier could list the other payees from the contract. pub fn claim_proof_identities( &self, contract: &DataContract, claimant_id: Identifier, ) -> BTreeSet { - let elected = contract - .config() - .moderation() - .is_some_and(|moderation| moderation.moderators.elected().is_some()); - match self { - ContractFeePot::Moderators if elected => BTreeSet::from([claimant_id]), - _ => self.recipients(contract), + let recipients = self.recipients(contract); + if recipients.contains(&claimant_id) { + recipients + } else { + BTreeSet::from([claimant_id]) } } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/common/seated_moderation_charter/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/common/seated_moderation_charter/mod.rs index db7597974a0..406986b9a65 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/common/seated_moderation_charter/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/common/seated_moderation_charter/mod.rs @@ -34,8 +34,8 @@ use dpp::fee::Credits; use dpp::identifier::Identifier; use dpp::moderation_charter::{ property_names, ElectedCharter, SubmittedCharter, ADDED_MODERATOR_DOCUMENT_TYPE_NAME, - ELECTED_CHARTER_DOCUMENT_TYPE_NAME, FULL_MODERATORS_SHARE, - REMOVED_MODERATOR_DOCUMENT_TYPE_NAME, SUBMITTED_CHARTER_DOCUMENT_TYPE_NAME, + ELECTED_CHARTER_DOCUMENT_TYPE_NAME, REMOVED_MODERATOR_DOCUMENT_TYPE_NAME, + SUBMITTED_CHARTER_DOCUMENT_TYPE_NAME, }; use dpp::platform_value::btreemap_extensions::BTreeValueMapHelper; use dpp::platform_value::Value; @@ -188,24 +188,15 @@ impl SeatedModerationCharter { transaction: TransactionArg, platform_version: &PlatformVersion, ) -> Result { - let proposal = self.fetch_proposal_document( - drive, - epoch, - execution_context, - transaction, - platform_version, - )?; - // The share alone is read: nothing else of the proposal decides the discount. The - // schema bounds it to 0 to 100 and leaves it out for the full amount. - let share = proposal - .properties() - .get_optional_integer::(property_names::MODERATORS_SHARE) - .map_err(|_| { - Error::Execution(ExecutionError::DriveIncoherence( - "a stored moderation charter proposal's share is not a percentage", - )) - })?; - Ok(share.unwrap_or(FULL_MODERATORS_SHARE)) + Ok(self + .fetch_proposal( + drive, + epoch, + execution_context, + transaction, + platform_version, + )? + .moderators_share_or_full()) } /// The proposal the team runs on: its reasons, its share and its reward split. One read of @@ -218,31 +209,6 @@ impl SeatedModerationCharter { transaction: TransactionArg, platform_version: &PlatformVersion, ) -> Result { - let proposal = self.fetch_proposal_document( - drive, - epoch, - execution_context, - transaction, - platform_version, - )?; - // The schema admitted the proposal when it was filed, so it reads. - SubmittedCharter::from_document_properties(proposal.properties()) - .into_data() - .map_err(|_| { - Error::Execution(ExecutionError::DriveIncoherence( - "a stored moderation charter proposal does not read as one", - )) - }) - } - - fn fetch_proposal_document( - &self, - drive: &Drive, - epoch: &Epoch, - execution_context: &mut StateTransitionExecutionContext, - transaction: TransactionArg, - platform_version: &PlatformVersion, - ) -> Result { let contract = drive .cache .system_data_contracts @@ -251,7 +217,7 @@ impl SeatedModerationCharter { contract.document_type_for_name(SUBMITTED_CHARTER_DOCUMENT_TYPE_NAME)?; // The elected charter's reference proved the proposal when the charter was filed, and // a proposal can not be deleted. - fetch_document_with_id( + let proposal = fetch_document_with_id( drive, &contract, document_type, @@ -263,7 +229,15 @@ impl SeatedModerationCharter { )? .ok_or(Error::Execution(ExecutionError::DriveIncoherence( "the proposal of a seated charter is not stored", - ))) + )))?; + // The schema admitted the proposal when it was filed, so it reads. + SubmittedCharter::from_document_properties(proposal.properties()) + .into_data() + .map_err(|_| { + Error::Execution(ExecutionError::DriveIncoherence( + "a stored moderation charter proposal does not read as one", + )) + }) } /// The active members of the team besides the leader ([`ElectedCharter::active_members`]): @@ -358,6 +332,34 @@ impl SeatedModerationCharter { transaction, platform_version, )?; + self.settle_moderators_pot_among( + &members, + drive, + contract_id, + pot_credits, + max_added_moderators, + epoch, + execution_context, + transaction, + platform_version, + ) + } + + /// [`SeatedModerationCharter::settle_moderators_pot`] with the active members already read + /// ([`SeatedModerationCharter::fetch_active_members`]): reads the proposal and the counts. + #[allow(clippy::too_many_arguments)] + pub(crate) fn settle_moderators_pot_among( + &self, + members: &BTreeSet, + drive: &Drive, + contract_id: Identifier, + pot_credits: Credits, + max_added_moderators: u16, + epoch: &Epoch, + execution_context: &mut StateTransitionExecutionContext, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result { let proposal = self.fetch_proposal( drive, epoch, @@ -380,7 +382,7 @@ impl SeatedModerationCharter { execution_context.add_operation(ValidationOperation::PrecalculatedOperation(fee)); let payouts = proposal .reward_split - .payouts(pot_credits, self.leader_id, &members, &action_counts) + .payouts(pot_credits, self.leader_id, members, &action_counts) .map_err(|_| { Error::Execution(ExecutionError::DriveIncoherence( "a stored moderation charter proposal's reward split adds up to 100", diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/added_moderator_cap.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/added_moderator_cap.rs index 739fa06f568..9035260c235 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/added_moderator_cap.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/added_moderator_cap.rs @@ -27,22 +27,17 @@ use crate::error::execution::ExecutionError; use crate::error::Error; -use crate::execution::types::execution_operation::ValidationOperation; -use crate::execution::types::state_transition_execution_context::{ - StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0, -}; +use crate::execution::types::state_transition_execution_context::StateTransitionExecutionContext; use crate::execution::validation::state_transition::common::seated_moderation_charter::count_added_moderators; -use crate::execution::validation::state_transition::state_transitions::batch::fetch_document_with_id; +use crate::execution::validation::state_transition::state_transitions::batch::state::v0::seated_charter_reads::{ + SeatedCharterRead, SeatedCharterReads, +}; use crate::platform_types::platform::PlatformStateRef; use dpp::block::block_info::BlockInfo; use dpp::consensus::state::contract_moderation::ModerationCharterAddedModeratorLimitReachedError; -use dpp::data_contract::accessors::v0::DataContractV0Getters; -use dpp::data_contract::config::v2::DataContractConfigGettersV2; -use dpp::document::DocumentV0Getters; use dpp::identifier::Identifier; use dpp::moderation_charter::{ - property_names, ADDED_MODERATOR_DOCUMENT_TYPE_NAME, ELECTED_CHARTER_DOCUMENT_TYPE_NAME, - MODERATION_CHARTERS_CONTRACT_ID, + property_names, ADDED_MODERATOR_DOCUMENT_TYPE_NAME, MODERATION_CHARTERS_CONTRACT_ID, }; use dpp::platform_value::btreemap_extensions::BTreeValueMapHelper; use dpp::validation::SimpleConsensusValidationResult; @@ -67,11 +62,14 @@ impl AddedModeratorCap { /// counts it otherwise. Call it only for a create state validation accepted. A no-op, with /// nothing read, for every other create. /// - /// The reads are billed: the elected charter by id, its target contract, and the additions - /// of the charter, at most the cap of them. + /// The reads are billed: the elected charter by id and its target contract (once per batch, + /// shared with the settle the addition forces), and the additions of the charter, at most + /// the cap of them. + #[allow(clippy::too_many_arguments)] pub(super) fn validate_and_record_create( &mut self, create_action: &DocumentCreateTransitionAction, + seated_charters: &mut SeatedCharterReads, platform: &PlatformStateRef, block_info: &BlockInfo, execution_context: &mut StateTransitionExecutionContext, @@ -95,58 +93,19 @@ impl AddedModeratorCap { )) })?; - let charters_contract = &base.data_contract_fetch_info_ref().contract; - let elected_charter = fetch_document_with_id( - platform.drive, - charters_contract, - charters_contract.document_type_for_name(ELECTED_CHARTER_DOCUMENT_TYPE_NAME)?, + let SeatedCharterRead { + charter, + max_added_moderators, + } = seated_charters.read( elected_charter_id, + platform, epoch, execution_context, transaction, platform_version, - )? - .ok_or(Error::Execution(ExecutionError::CorruptedCodeExecution( - "the elected charter an addedModerator refers to was found by its reference", - )))?; - let target_contract_id = elected_charter - .properties() - .get_identifier(property_names::TARGET_CONTRACT_ID) - .map_err(|_| { - Error::Execution(ExecutionError::DriveIncoherence( - "a stored elected charter names its target contract", - )) - })?; - - // The fee this call returns is billed, never the one a cached fetch info carries, - // which depends on the cache. - let (fee, target_contract) = platform.drive.get_contract_with_fetch_info_and_fee( - target_contract_id.to_buffer(), - Some(epoch), - false, - transaction, - platform_version, )?; - let fee = fee.ok_or(Error::Execution(ExecutionError::CorruptedCodeExecution( - "fee must exist when fetching a contract with an epoch", - )))?; - execution_context.add_operation(ValidationOperation::PrecalculatedOperation(fee)); - // A charter is only filed for a contract that declares elected moderation (its - // `electionOpen` requirement), which is fixed at the contract's creation, and a contract - // is never deleted. - let max_added_moderators = target_contract - .as_ref() - .and_then(|fetch_info| { - fetch_info - .contract - .config() - .moderation() - .and_then(|moderation| moderation.moderators.elected()) - .map(|elected| elected.max_added_moderators) - }) - .ok_or(Error::Execution(ExecutionError::DriveIncoherence( - "the target of a stored elected charter declares elected moderation", - )))?; + let target_contract_id = charter.charter.target_contract_id; + let max_added_moderators = *max_added_moderators; let accepted_in_batch = self .accepted_in_batch diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/mod.rs index 76ff507d41f..28f531a6a81 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/mod.rs @@ -37,6 +37,7 @@ use crate::execution::validation::state_transition::batch::data_triggers::{data_ use crate::execution::validation::state_transition::batch::state::v0::added_moderator_cap::AddedModeratorCap; use crate::execution::validation::state_transition::batch::state::v0::index_only_batch_entries::IndexOnlyBatchEntries; use crate::execution::validation::state_transition::batch::state::v0::moderators_pot_settle::ModeratorsPotSettles; +use crate::execution::validation::state_transition::batch::state::v0::seated_charter_reads::SeatedCharterReads; use drive::state_transition_action::batch::batched_transition::document_transition::document_create_transition_action::DocumentCreateTransitionActionAccessorsV0; use crate::platform_types::platform::{PlatformStateRef}; use crate::execution::validation::state_transition::state_transitions::batch::transformer::v0::BatchTransitionTransformerV0; @@ -48,6 +49,7 @@ pub mod fetch_contender; pub mod fetch_documents; mod index_only_batch_entries; mod moderators_pot_settle; +mod seated_charter_reads; pub(in crate::execution::validation::state_transition::state_transitions::batch) trait DocumentsBatchStateTransitionStateValidationV0 { @@ -110,6 +112,8 @@ impl DocumentsBatchStateTransitionStateValidationV0 for BatchTransition { // delete of the moderation charters contract's team changes takes this path, and that // contract is in state from protocol version 14 only, so no earlier batch does. let mut moderators_pot_settles = ModeratorsPotSettles::default(); + // The seated charters those two read, each read once per batch. + let mut seated_charter_reads = SeatedCharterReads::default(); // Next we need to validate the structure of all actions (this means with the data contract) for transition in state_transition_action.transitions_take() { @@ -404,6 +408,7 @@ impl DocumentsBatchStateTransitionStateValidationV0 for BatchTransition { // `maxAddedModerators` members: a count the schema can not express. let cap_result = added_moderator_cap.validate_and_record_create( create_action, + &mut seated_charter_reads, platform, block_info, execution_context, @@ -427,6 +432,7 @@ impl DocumentsBatchStateTransitionStateValidationV0 for BatchTransition { // A change of a seated moderation team settles the team's moderators pot first. moderators_pot_settles.settle_before_team_change( &transition, + &mut seated_charter_reads, platform, block_info, execution_context, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/moderators_pot_settle.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/moderators_pot_settle.rs index f3404713f71..f59f4c08cdc 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/moderators_pot_settle.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/moderators_pot_settle.rs @@ -16,7 +16,7 @@ //! state validation (and for an addition the cap on additions) accepted it, and the batch //! carries what it pays, for the batch converter to write before the change. Like the cap it //! runs in state validation, which check tx does not run for a batch: the mempool admits the -//! change without reading the pot. At most one settle per target contract per batch: a later +//! change without reading the pot, and prices it without the settle's reads and writes. At most one settle per target contract per batch: a later //! change of the same batch finds the pot paid out and the counts reset. That is dormant while //! `max_transitions_in_documents_batch` is 1, as it is at every protocol version. //! @@ -33,12 +33,13 @@ use crate::execution::types::execution_operation::ValidationOperation; use crate::execution::types::state_transition_execution_context::{ StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0, }; -use crate::execution::validation::state_transition::common::seated_moderation_charter::fetch_moderation_charter_by_id; use crate::execution::validation::state_transition::state_transitions::batch::fetch_document_with_id; +use crate::execution::validation::state_transition::state_transitions::batch::state::v0::seated_charter_reads::{ + SeatedCharterRead, SeatedCharterReads, +}; use crate::platform_types::platform::PlatformStateRef; use dpp::block::block_info::BlockInfo; use dpp::data_contract::accessors::v0::DataContractV0Getters; -use dpp::data_contract::config::v2::DataContractConfigGettersV2; use dpp::data_contract::document_type::action_fees::ContractFeePot; use dpp::document::DocumentV0Getters; use dpp::identifier::Identifier; @@ -70,11 +71,13 @@ impl ModeratorsPotSettles { /// every other transition. Call it only for a transition state validation accepted. /// /// The reads are billed: for a delete the team change being deleted, the elected charter by - /// id, its target contract, the pot, and what the settle reads (the team, the proposal and - /// the action counts). + /// id and its target contract (once per batch, shared with the cap on additions), the pot, + /// and what the settle reads (the team, the proposal and the action counts). + #[allow(clippy::too_many_arguments)] pub(super) fn settle_before_team_change( &mut self, transition: &BatchedTransitionAction, + seated_charters: &mut SeatedCharterReads, platform: &PlatformStateRef, block_info: &BlockInfo, execution_context: &mut StateTransitionExecutionContext, @@ -128,52 +131,24 @@ impl ModeratorsPotSettles { }; // A team change can only name a stored elected charter, which is a seated one: only a - // contest's winner is ever written to the type's storage. - let charter = fetch_moderation_charter_by_id( - platform.drive, + // contest's winner is ever written to the type's storage. The cap on additions read it + // already for an addition. + let SeatedCharterRead { + charter, + max_added_moderators, + } = seated_charters.read( elected_charter_id, + platform, epoch, execution_context, transaction, platform_version, - )? - .ok_or(Error::Execution(ExecutionError::CorruptedCodeExecution( - "the elected charter a moderation team change refers to was found by its reference", - )))?; + )?; let target_contract_id = charter.charter.target_contract_id; if !self.settled_targets.insert(target_contract_id) { return Ok(()); } - // The fee this call returns is billed, never the one a cached fetch info carries, - // which depends on the cache. - let (fee, target_contract) = platform.drive.get_contract_with_fetch_info_and_fee( - target_contract_id.to_buffer(), - Some(epoch), - false, - transaction, - platform_version, - )?; - let fee = fee.ok_or(Error::Execution(ExecutionError::CorruptedCodeExecution( - "fee must exist when fetching a contract with an epoch", - )))?; - execution_context.add_operation(ValidationOperation::PrecalculatedOperation(fee)); - // A charter is only filed for a contract that declares elected moderation, which is - // fixed at the contract's creation, and a contract is never deleted. - let max_added_moderators = target_contract - .as_ref() - .and_then(|fetch_info| { - fetch_info - .contract - .config() - .moderation() - .and_then(|moderation| moderation.moderators.elected()) - .map(|elected| elected.max_added_moderators) - }) - .ok_or(Error::Execution(ExecutionError::DriveIncoherence( - "the target of a stored elected charter declares elected moderation", - )))?; - let (fee, fee_pot) = platform.drive.fetch_contract_fee_pot_with_fee( target_contract_id, ContractFeePot::Moderators, @@ -187,7 +162,7 @@ impl ModeratorsPotSettles { platform.drive, target_contract_id, fee_pot.credits, - max_added_moderators, + *max_added_moderators, epoch, execution_context, transaction, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/seated_charter_reads.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/seated_charter_reads.rs new file mode 100644 index 00000000000..049e3ebedb7 --- /dev/null +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/seated_charter_reads.rs @@ -0,0 +1,101 @@ +//! The seated moderation charters the state validation of one batch reads for the team changes +//! it validates (`addedModerator` and `removedModerator` of the moderation charters contract), +//! each with its target's `maxAddedModerators`: the cap on additions and the settle a change +//! forces read them once between them. + +use crate::error::execution::ExecutionError; +use crate::error::Error; +use crate::execution::types::execution_operation::ValidationOperation; +use crate::execution::types::state_transition_execution_context::{ + StateTransitionExecutionContext, StateTransitionExecutionContextMethodsV0, +}; +use crate::execution::validation::state_transition::common::seated_moderation_charter::{ + fetch_moderation_charter_by_id, SeatedModerationCharter, +}; +use crate::platform_types::platform::PlatformStateRef; +use dpp::block::epoch::Epoch; +use dpp::data_contract::accessors::v0::DataContractV0Getters; +use dpp::data_contract::config::v2::DataContractConfigGettersV2; +use dpp::identifier::Identifier; +use dpp::version::PlatformVersion; +use drive::grovedb::TransactionArg; +use std::collections::btree_map::Entry; +use std::collections::BTreeMap; + +/// A seated charter with the `maxAddedModerators` its target declares. +pub(super) struct SeatedCharterRead { + pub(super) charter: SeatedModerationCharter, + pub(super) max_added_moderators: u16, +} + +/// The seated charters read by one batch state validation, by elected charter id. +#[derive(Default)] +pub(super) struct SeatedCharterReads { + reads: BTreeMap, +} + +impl SeatedCharterReads { + /// The seated charter `elected_charter_id` a team change of the batch names, read the + /// first time with its target contract (both billed), and from this batch's reads after. + /// Call it only for a change whose own state validation passed: its reference then proved + /// the charter stored, which means seated (only a contest's winner is written to the type's + /// storage). + pub(super) fn read( + &mut self, + elected_charter_id: Identifier, + platform: &PlatformStateRef, + epoch: &Epoch, + execution_context: &mut StateTransitionExecutionContext, + transaction: TransactionArg, + platform_version: &PlatformVersion, + ) -> Result<&SeatedCharterRead, Error> { + let entry = match self.reads.entry(elected_charter_id) { + Entry::Occupied(entry) => return Ok(entry.into_mut()), + Entry::Vacant(entry) => entry, + }; + let charter = fetch_moderation_charter_by_id( + platform.drive, + elected_charter_id, + epoch, + execution_context, + transaction, + platform_version, + )? + .ok_or(Error::Execution(ExecutionError::CorruptedCodeExecution( + "the elected charter a moderation team change refers to was found by its reference", + )))?; + // The fee this call returns is billed, never the one a cached fetch info carries, which + // depends on the cache. + let (fee, target_contract) = platform.drive.get_contract_with_fetch_info_and_fee( + charter.charter.target_contract_id.to_buffer(), + Some(epoch), + false, + transaction, + platform_version, + )?; + let fee = fee.ok_or(Error::Execution(ExecutionError::CorruptedCodeExecution( + "fee must exist when fetching a contract with an epoch", + )))?; + execution_context.add_operation(ValidationOperation::PrecalculatedOperation(fee)); + // A charter is only filed for a contract that declares elected moderation (its + // `electionOpen` requirement), which is fixed at the contract's creation, and a contract + // is never deleted. + let max_added_moderators = target_contract + .as_ref() + .and_then(|fetch_info| { + fetch_info + .contract + .config() + .moderation() + .and_then(|moderation| moderation.moderators.elected()) + .map(|elected| elected.max_added_moderators) + }) + .ok_or(Error::Execution(ExecutionError::DriveIncoherence( + "the target of a stored elected charter declares elected moderation", + )))?; + Ok(entry.insert(SeatedCharterRead { + charter, + max_added_moderators, + })) + } +} diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_fee_claim/state/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_fee_claim/state/v0/mod.rs index fc77c1aa85d..3044c81303d 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_fee_claim/state/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_fee_claim/state/v0/mod.rs @@ -50,6 +50,12 @@ impl ContractFeeClaimStateTransitionStateValidationV0 for ContractFeeClaimTransi /// by bumping the signer's contract nonce, and a refused claim leaves the pot's last claim /// epoch alone. /// + /// The moderators pot of an elected contract is read first for its seated charter (the + /// `byTargetContract` query, billed) whoever claims, since any identity may be on a seated + /// team: with one seated, the claim is the team's (see `claim_seated_moderators_pot_v0`), + /// and without, the interim team's as the declaration names it. A claim refused for a + /// signer who is neither therefore pays that query too. + /// /// The action carries what each recipient is paid, so Drive pays the pot out without /// reading it again, and the mempool, which transforms without a state validation stage, /// refuses with the same consensus codes as a block. @@ -184,10 +190,10 @@ impl ContractFeeClaimStateTransitionStateValidationV0 for ContractFeeClaimTransi /// The claim of the moderators pot of an elected contract with a seated charter: the /// signer is the leader or an active member of the seated team, the pot was not claimed in -/// this epoch yet, and the proposal's reward split pays someone at least a credit. The -/// split reads the team, the proposal and the team's moderation action counts, all billed, -/// and the claim resets the counts. Every refusal is paid for by bumping the signer's -/// contract nonce. +/// this epoch yet, and the proposal's reward split pays someone at least a credit. The team +/// is read once (the charter's removals and additions), then the pot, the proposal and the +/// team's moderation action counts, all billed, and the claim resets the counts. Every +/// refusal is paid for by bumping the signer's contract nonce. #[allow(clippy::too_many_arguments)] fn claim_seated_moderators_pot_v0( transition: &ContractFeeClaimTransition, @@ -214,15 +220,17 @@ fn claim_seated_moderators_pot_v0( )) }; - // The interim moderators, the owner among them, claim no more once a charter is seated. - if !charter.seats( + // The team is read once: whether the claimant is on it, and who the split pays. The + // interim moderators, the owner among them, claim no more once a charter is seated. + let members = charter.fetch_active_members( platform.drive, - claimant_id, + max_added_moderators, epoch, execution_context, tx, platform_version, - )? { + )?; + if claimant_id != charter.leader_id && !members.contains(&claimant_id) { return refuse(ContractFeeClaimNotAllowedError::new(contract_id, pot, claimant_id).into()); } @@ -242,7 +250,8 @@ fn claim_seated_moderators_pot_v0( ); } - let settlement = charter.settle_moderators_pot( + let settlement = charter.settle_moderators_pot_among( + &members, platform.drive, contract_id, fee_pot.credits, diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/state/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/state/v0/mod.rs index 324397256ac..bff338957c2 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/state/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/state/v0/mod.rs @@ -966,7 +966,12 @@ impl<'a> Moderators<'a> { platform_version, )?; execution_context.add_operation(ValidationOperation::PrecalculatedOperation(fee)); - Ok(action.with_moderation_action_count(count.saturating_add(1))) + // A contract stored elected before the counts existed has nowhere to count: its team's + // actions go uncounted, and a settle splits the action share equally. + Ok(match count { + Some(count) => action.with_moderation_action_count(count.saturating_add(1)), + None => action, + }) } /// Whether a seated team lacks `ability`: on `document_type_name` for a deletion or a diff --git a/packages/rs-drive/src/drive/contract/moderation/action_count_tests.rs b/packages/rs-drive/src/drive/contract/moderation/action_count_tests.rs index 138f520dce2..056337791df 100644 --- a/packages/rs-drive/src/drive/contract/moderation/action_count_tests.rs +++ b/packages/rs-drive/src/drive/contract/moderation/action_count_tests.rs @@ -141,6 +141,24 @@ fn should_create_the_action_counts_tree_with_an_elected_contract_only() { ) .expect("expected to insert the contract"); assert!(!has_counts_tree(&drive, owned_contract.id())); + + // A contract without the tree (an elected one stored before the counts existed reads the + // same) has no counts rather than a failing read. + let epoch = Epoch::new(0).expect("epoch"); + let (_, count) = drive + .fetch_contract_moderation_action_count_with_fee( + owned_contract.id(), + member(1), + &epoch, + None, + platform_version, + ) + .expect("expected the read to find no tree"); + assert_eq!(count, None); + assert!(drive + .fetch_contract_moderation_action_counts(owned_contract.id(), 31, None, platform_version) + .expect("expected the read to find no tree") + .is_empty()); } #[test] @@ -185,7 +203,7 @@ fn should_write_read_and_reset_the_action_counts() { platform_version, ) .expect("expected to read a count"); - assert_eq!(count, 5); + assert_eq!(count, Some(5)); let (_, count) = drive .fetch_contract_moderation_action_count_with_fee( contract_id, @@ -195,7 +213,7 @@ fn should_write_read_and_reset_the_action_counts() { platform_version, ) .expect("expected to read a count"); - assert_eq!(count, 0, "a member that did not act has no count"); + assert_eq!(count, Some(0), "a member that did not act has no count"); // The limit bounds the read. assert_eq!( diff --git a/packages/rs-drive/src/drive/contract/moderation/fetch_contract_moderation_action_counts/mod.rs b/packages/rs-drive/src/drive/contract/moderation/fetch_contract_moderation_action_counts/mod.rs index defccf7ab3d..97cc0b4a99c 100644 --- a/packages/rs-drive/src/drive/contract/moderation/fetch_contract_moderation_action_counts/mod.rs +++ b/packages/rs-drive/src/drive/contract/moderation/fetch_contract_moderation_action_counts/mod.rs @@ -115,7 +115,9 @@ impl Drive { /// Reads one member's moderation action count on the elected contract `contract_id`, with /// the fee of the read: 0 when the member signed no counted action since the moderators pot - /// was last settled. + /// was last settled, `None` when the contract has no counts tree (an elected contract + /// stored before the counts existed, on a development network), in which case its team's + /// actions are not counted. The read of every count likewise finds none there. /// /// # Parameters /// @@ -127,7 +129,8 @@ impl Drive { /// /// # Returns /// - /// * `Ok((FeeResult, u32))` with the fee and the count. + /// * `Ok((FeeResult, Option))` with the fee and the count, `None` without a counts + /// tree. /// * `Err(Error)` when the version is unknown, the read fails or the count is malformed. pub fn fetch_contract_moderation_action_count_with_fee( &self, @@ -136,7 +139,7 @@ impl Drive { epoch: &Epoch, transaction: TransactionArg, platform_version: &PlatformVersion, - ) -> Result<(FeeResult, u32), Error> { + ) -> Result<(FeeResult, Option), Error> { match platform_version .drive .methods diff --git a/packages/rs-drive/src/drive/contract/moderation/fetch_contract_moderation_action_counts/v0/mod.rs b/packages/rs-drive/src/drive/contract/moderation/fetch_contract_moderation_action_counts/v0/mod.rs index abeefb736ad..6bd9bc7e317 100644 --- a/packages/rs-drive/src/drive/contract/moderation/fetch_contract_moderation_action_counts/v0/mod.rs +++ b/packages/rs-drive/src/drive/contract/moderation/fetch_contract_moderation_action_counts/v0/mod.rs @@ -35,13 +35,19 @@ impl Drive { offset: None, }, }; - let (results, _) = self.grove_get_raw_path_query( + let results = match self.grove_get_raw_path_query( &path_query, transaction, QueryResultType::QueryKeyElementPairResultType, drive_operations, &platform_version.drive, - )?; + ) { + Ok((results, _)) => results, + // An elected contract stored before the counts existed has no tree: no counts. The + // cost of the lookup is billed all the same. + Err(error) if is_missing_counts_tree(&error) => return Ok(BTreeMap::new()), + Err(error) => return Err(error), + }; results .to_key_elements() .into_iter() @@ -73,25 +79,55 @@ impl Drive { transaction: TransactionArg, drive_operations: &mut Vec, platform_version: &PlatformVersion, - ) -> Result { + ) -> Result, Error> { let path = contract_moderation_action_counts_path(contract_id.as_slice()); - self.grove_get_raw_optional_item( + // The plain read tells a member without a count (the key is missing) from a contract + // without the tree (its parent is), at the cost of the one read the optional read + // would make: GroveDB's optional read finds nothing either way. + let element = match self.grove_get_raw( (&path).into(), identity_id.as_slice(), DirectQueryType::StatefulDirectQuery, transaction, drive_operations, &platform_version.drive, - )? - .map(|value| { - decode_moderation_action_count(&value).map_err(|description| { - Error::Drive(DriveError::CorruptedDriveState(format!( - "moderation action count of {} on contract {} is malformed: {}", - identity_id, contract_id, description - ))) - }) - }) - .transpose() - .map(Option::unwrap_or_default) + ) { + Ok(element) => element, + Err(Error::GroveDB(error)) if matches!(*error, grovedb::Error::PathKeyNotFound(_)) => { + return Ok(Some(0)) + } + // An elected contract stored before the counts existed has no tree to count in. + // The cost of the lookup is billed all the same. + Err(error) if is_missing_counts_tree(&error) => return Ok(None), + Err(error) => return Err(error), + }; + let malformed = |description: String| { + Error::Drive(DriveError::CorruptedDriveState(format!( + "moderation action count of {} on contract {} is malformed: {}", + identity_id, contract_id, description + ))) + }; + match element { + Some(Element::Item(value, _)) => decode_moderation_action_count(&value) + .map(Some) + .map_err(malformed), + Some(_) => Err(malformed("not an item".to_string())), + None => Ok(Some(0)), + } } } + +/// Whether `error` is GroveDB not finding the counts tree of a contract: one stored, elected +/// already, before protocol version 14 counted actions (a development network's), which +/// `insert_contract_moderation_trees` did not give one. +fn is_missing_counts_tree(error: &Error) -> bool { + matches!( + error, + Error::GroveDB(error) if matches!( + **error, + grovedb::Error::PathParentLayerNotFound(_) + | grovedb::Error::PathNotFound(_) + | grovedb::Error::InvalidParentLayerPath(_) + ) + ) +} diff --git a/packages/rs-drive/src/drive/contract/moderation/types.rs b/packages/rs-drive/src/drive/contract/moderation/types.rs index 4b4a5bc6a73..af55d512790 100644 --- a/packages/rs-drive/src/drive/contract/moderation/types.rs +++ b/packages/rs-drive/src/drive/contract/moderation/types.rs @@ -99,6 +99,10 @@ pub const ESTIMATED_CONTRACT_WARNINGS_PER_ENTRY: u32 = 2; /// The most bytes a reason's code takes in an entry: the tag and the u16. pub const CONTRACT_MODERATION_REASON_CODE_MAX_SIZE: u32 = 3; +/// The bytes a reason's reason document id takes in an entry. Every entry a seated elected team +/// writes carries one, so an entry whose value is not known is estimated with it. +pub const CONTRACT_MODERATION_REASON_DOCUMENT_ID_SIZE: u32 = 32; + /// The length a reason's text is estimated at when it is not known: a sentence. Estimating /// every entry at the longest reason the protocol admits made the dry-run processing fee of a /// moderation some 25 times the applied one. @@ -108,8 +112,9 @@ pub const ESTIMATED_CONTRACT_MODERATION_REASON_TEXT_SIZE: u32 = 128; /// write walks past, and the entry a delete removes. An entry being written is priced by its /// own size. pub fn estimated_entry_value_size(list: ContractModerationList) -> u32 { - let reason_size = - CONTRACT_MODERATION_REASON_CODE_MAX_SIZE + ESTIMATED_CONTRACT_MODERATION_REASON_TEXT_SIZE; + let reason_size = CONTRACT_MODERATION_REASON_CODE_MAX_SIZE + + CONTRACT_MODERATION_REASON_DOCUMENT_ID_SIZE + + ESTIMATED_CONTRACT_MODERATION_REASON_TEXT_SIZE; match list { ContractModerationList::Banlist => reason_size, ContractModerationList::Suspensions => CONTRACT_SUSPENSION_UNTIL_SIZE as u32 + reason_size, @@ -219,6 +224,7 @@ const RESTORED: u8 = 1; pub fn estimated_document_removal_value_size() -> u32 { (CONTRACT_DOCUMENT_REMOVAL_FIXED_SIZE + CONTRACT_DOCUMENT_RESTORATION_SIZE) as u32 + CONTRACT_MODERATION_REASON_CODE_MAX_SIZE + + CONTRACT_MODERATION_REASON_DOCUMENT_ID_SIZE + ESTIMATED_CONTRACT_MODERATION_REASON_TEXT_SIZE } diff --git a/packages/rs-drive/src/prove/prove_state_transition/v0/mod.rs b/packages/rs-drive/src/prove/prove_state_transition/v0/mod.rs index f42ceacc6f8..e5c4936fd19 100644 --- a/packages/rs-drive/src/prove/prove_state_transition/v0/mod.rs +++ b/packages/rs-drive/src/prove/prove_state_transition/v0/mod.rs @@ -377,8 +377,8 @@ impl Drive { } } // The pot the claim paid out with its last claim (epoch, time, claimant), and the balance - // of every identity a payout of that pot goes to, or the claimant's alone for the - // moderators pot of an elected contract. + // of every identity the contract names as a recipient of that pot, or the claimant's + // alone when the contract does not name it (a seated moderation team's member). StateTransition::ContractFeeClaim(st) => { let contract_id = st.data_contract_id(); let Some(contract_fetch_info) = self.get_contract_with_fetch_info( @@ -393,10 +393,10 @@ impl Drive { contract_id )))); }; - // The moderators pot of an elected contract proves the claimant's balance - // alone: the team a seated charter pays is not in the contract. Only a - // contract fee claim takes this arm, a transition protocol version 14 - // introduced, so no earlier proof changes. + // A claimant the contract does not name as a recipient is on a seated + // moderation team, which the contract does not name either: its balance alone + // is proved. Only a contract fee claim takes this arm, a transition protocol + // version 14 introduced, so no earlier proof changes. let recipients: Vec<[u8; 32]> = st .pot() .claim_proof_identities(&contract_fetch_info.contract, st.owner_id()) diff --git a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/documents_batch_transition.rs b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/documents_batch_transition.rs index 15e22067639..4bf4a57b6a7 100644 --- a/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/documents_batch_transition.rs +++ b/packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/documents_batch_transition.rs @@ -44,10 +44,11 @@ impl DriveHighLevelOperationConverter for BatchTransitionAction { // its state validation settled and the reset of the action counts, operations on // other keys than the change's own. 1 => { - let owner_id = self.owner_id(); - let lapsed_suspensions = self.lapsed_suspensions().clone(); - let settlements = self.moderators_pot_settlements().to_vec(); - let transitions = self.transitions_owned(); + let mut action = self; + let owner_id = action.owner_id(); + let lapsed_suspensions = action.lapsed_suspensions().clone(); + let settlements = action.take_moderators_pot_settlements(); + let transitions = action.transitions_owned(); let mut operations = settlements .into_iter() .map(|settlement| settlement.into_drive_operations()) diff --git a/packages/rs-drive/src/state_transition_action/batch/mod.rs b/packages/rs-drive/src/state_transition_action/batch/mod.rs index 1bab5ccbb55..a858d9ada60 100644 --- a/packages/rs-drive/src/state_transition_action/batch/mod.rs +++ b/packages/rs-drive/src/state_transition_action/batch/mod.rs @@ -275,6 +275,13 @@ impl BatchTransitionAction { } } + /// Takes the settles of moderators pots out of the batch, for its conversion to operations + pub fn take_moderators_pot_settlements(&mut self) -> Vec { + match self { + BatchTransitionAction::V0(v0) => std::mem::take(&mut v0.moderators_pot_settlements), + } + } + /// Records the settles of moderators pots the batch forces before it changes a seated /// team pub fn set_moderators_pot_settlements(&mut self, settlements: Vec) { diff --git a/packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs b/packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs index 99da1122a03..99dd5d23168 100644 --- a/packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs +++ b/packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs @@ -1375,9 +1375,10 @@ impl Drive { contract_id )), ))?; - // The prover's identities: the moderators pot of an elected contract proves - // the claimant's balance alone (a contract fee claim exists from protocol - // version 14 only, so no earlier proof changes). + // The prover's identities: the recipients the contract names when the claimant + // is one, the claimant alone otherwise (a seated moderation team's member). A + // contract fee claim exists from protocol version 14 only, so no earlier proof + // changes. let recipients: Vec<[u8; 32]> = pot .claim_proof_identities(&contract, transition.owner_id()) .into_iter() diff --git a/packages/rs-platform-version/src/version/v14.rs b/packages/rs-platform-version/src/version/v14.rs index b4202ce5555..0f198f03e3b 100644 --- a/packages/rs-platform-version/src/version/v14.rs +++ b/packages/rs-platform-version/src/version/v14.rs @@ -1100,11 +1100,12 @@ pub const PROTOCOL_VERSION_14: ProtocolVersion = 14; /// created or deleted settles the pot first, to the team as it was, by a /// hook in the batch's `validate_state` v0 beside the cap on additions: it /// ignores the once-per-epoch limit and writes no last claim. The proof of a -/// claim of an elected contract's moderators pot shows the claimant's -/// balance alone. A moderation reason gains `reasonDocumentId` (tag bit 2 -/// where it is stored), and a seated team's ban, suspension, warning or -/// deletion must name a `reason` document its proposal lists -/// (`ModerationReasonNotListedError`, 41203). No table moves but the four +/// claim by a seated team's member, whom the contract does not name as a +/// recipient, shows the claimant's balance alone. A moderation reason gains +/// `reasonDocumentId` (tag bit 2 where it is stored), and a seated team's +/// ban, suspension, warning or deletion must name a `reason` document its +/// proposal lists (`ModerationReasonNotListedError`, 41203). No table moves +/// but the four /// new Drive method slots, `0` at every version. /// /// The app-connect system contract (`SystemDataContract::AppConnect`, schema v1) diff --git a/packages/rs-sdk/src/platform/transition/contract_fee_claim.rs b/packages/rs-sdk/src/platform/transition/contract_fee_claim.rs index b0dfdb9568e..24ffff61222 100644 --- a/packages/rs-sdk/src/platform/transition/contract_fee_claim.rs +++ b/packages/rs-sdk/src/platform/transition/contract_fee_claim.rs @@ -4,8 +4,9 @@ //! `actionFees` keyword). The `owner` parts collect in the contract's owner pot and the //! `moderators` parts in its moderators pot. A [`ContractFeeClaimTransition`], signed by a //! CRITICAL authentication key, pays a pot out: the owner pot to the contract owner, who alone -//! may claim it, and the moderators pot in equal shares to the contract's moderation team, any -//! member of which may claim it. A pot is paid out at most once per epoch. +//! may claim it, and the moderators pot in equal shares to the contract's moderation team (by +//! the proposal's reward split for an elected contract's seated team), any member of which may +//! claim it. A pot is paid out at most once per epoch. //! //! ```ignore //! let claim = moderator_identity @@ -45,10 +46,12 @@ pub struct ClaimedContractFees { /// The last claim of the pot, which is this claim unless the pot was claimed again since: /// its epoch, the time of its block and the identity that signed it pub last_claim: ContractFeePotLastClaim, - /// The credits left in the pot: what an equal split left over, and any fee collected - /// since the claim + /// The credits left in the pot: what the split left over, and any fee collected since the + /// claim pub remaining_credits: Credits, - /// The balance, after the claim, of every identity a payout of the pot goes to + /// The balance, after the claim, of every identity the contract names as a recipient of the + /// pot; for a claim by a member of an elected contract's seated team, which the contract + /// does not name, the claimant's balance alone pub balances: BTreeMap, } diff --git a/packages/wasm-sdk/src/state_transitions/contract.rs b/packages/wasm-sdk/src/state_transitions/contract.rs index fead990339e..200329619e1 100644 --- a/packages/wasm-sdk/src/state_transitions/contract.rs +++ b/packages/wasm-sdk/src/state_transitions/contract.rs @@ -782,9 +782,13 @@ export interface ContractClaimFeesResult { lastClaimTimeMs: bigint; /** The identity that signed the last claim of the pot: the claiming identity, unless it was claimed again since */ lastClaimantId: Identifier; - /** The credits left in the pot: what an equal split left over, and any fee collected since */ + /** The credits left in the pot: what the split left over, and any fee collected since */ remainingCredits: bigint; - /** The balance, after the claim, of every identity the pot pays, keyed by base58 identity id */ + /** + * The balance, after the claim, of every identity the contract names as a recipient of the + * pot, keyed by base58 identity id; for a claim by a member of an elected contract's seated + * team, which the contract does not name, the claimant's balance alone + */ balances: Map; } "#; @@ -807,12 +811,14 @@ struct ContractClaimFeesOptionsInput { #[wasm_bindgen] impl WasmSdk { /// Pays out a fee pot of a data contract: the owner pot whole to the contract owner, the - /// moderators pot in equal shares to the contract's moderation team, whichever member - /// claims it. A pot is paid out at most once per epoch; `getContractFeePots` tells what a - /// claim would pay and when the pot was last paid out. + /// moderators pot in equal shares to the contract's moderation team, or for an elected + /// contract with a seated team by its proposal's reward split, whichever member claims it. + /// A pot is paid out at most once per epoch; `getContractFeePots` tells what a claim would + /// pay and when the pot was last paid out. /// /// @param options - The claiming identity, the contract, the `pot` and the signer - /// @returns The pot and the balances of the identities it paid, proved + /// @returns The pot and the balances it proved: of every recipient the contract names, or + /// of the claimant alone for a seated elected team #[wasm_bindgen(js_name = "contractClaimFees")] pub async fn contract_claim_fees( &self,