Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 119 additions & 25 deletions packages/rs-drive-abci/tests/strategy_tests/strategy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use strategy_tests::operations::FinalizeBlockOperation::IdentityAddKeys;
use strategy_tests::operations::{
AmountRange, DocumentAction, DocumentOp, ExtraKeys, FinalizeBlockOperation, IdentityUpdateOp,
MaybeOutputAmount, OperationType, OutputCountRange, TokenOp,
UseExistingAddressesAsOutputChance,
UseExistingAddressesAsOutputChance, YesNoVoteOp,
};
use strategy_tests::KeyMaps;

Expand Down Expand Up @@ -105,12 +105,16 @@ use dpp::state_transition::masternode_vote_transition::MasternodeVoteTransition;
use dpp::tokens::calculate_token_id;
use dpp::tokens::token_event::TokenEvent;
use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice;
use dpp::voting::vote_choices::yes_no_abstain_vote_choice::YesNoAbstainVoteChoice;
use dpp::voting::vote_polls::VotePoll;
use dpp::voting::votes::resource_vote::v0::ResourceVoteV0;
use dpp::voting::votes::resource_vote::ResourceVote;
use dpp::voting::votes::yes_no_vote::v0::YesNoVoteV0;
use dpp::voting::votes::yes_no_vote::YesNoVote;
use dpp::voting::votes::Vote;
use dpp::withdrawal::Pooling;
use drive::drive::document::query::QueryDocumentsOutcomeV0Methods;
use drive::drive::votes::PreviousVoteCount;
use drive::query::DriveDocumentQuery;
use drive_abci::abci::app::FullAbciApplication;
use drive_abci::config::PlatformConfig;
Expand Down Expand Up @@ -1711,42 +1715,93 @@ impl NetworkStrategy {
continue;
}

let identity_public_key = IdentityPublicKey::V0(IdentityPublicKeyV0 {
id: 0,
purpose: Purpose::VOTING,
security_level: SecurityLevel::MEDIUM,
contract_bounds: None,
key_type: KeyType::ECDSA_HASH160,
read_only: false,
data: voting_address.to_vec().into(),
disabled_at: None,
});

let vote = Vote::ResourceVote(ResourceVote::V0(ResourceVoteV0 {
vote_poll: VotePoll::ContestedDocumentResourceVotePoll(
resource_vote_op.resolved_vote_poll.clone().into(),
),
resource_vote_choice,
}));

let identity_nonce =
identity_nonce_counter.entry(voting_identifier).or_default();
*identity_nonce += 1;
let state_transition = signed_masternode_vote(
vote,
pro_tx_hash_bytes,
voting_address,
signer,
identity_nonce_counter,
platform_version,
)
.await;

let state_transition =
MasternodeVoteTransition::try_from_vote_with_signer(
vote,
signer,
vote_poll_votes.insert(voting_identifier, resource_vote_choice);

operations.push(state_transition);
}
}
OperationType::YesNoVote(yes_no_vote_op)
if block_info.time_ms < yes_no_vote_op.end_date =>
{
let YesNoVoteOp { vote_poll_id, .. } = yes_no_vote_op;
let state = maybe_state.get_or_insert(platform.state.load());
let full_masternode_list = state.full_masternode_list();
let votes_allowed_per_masternode = platform_version
.dpp
.validation
.voting
.votes_allowed_per_masternode;
// A masternode answers the poll at most once a block: each vote's
// proof is checked against the state the block leaves, which holds only
// the masternode's last answer
let mut answered_in_this_block: HashSet<[u8; 32]> = HashSet::new();
for _ in 0..count {
let rand_index = rng.gen_range(0..full_masternode_list.len());
let (pro_tx_hash, masternode_list_item) =
full_masternode_list.iter().nth(rand_index).unwrap();
let pro_tx_hash_bytes: [u8; 32] = pro_tx_hash.to_byte_array();
if answered_in_this_block.contains(&pro_tx_hash_bytes) {
continue;
}

let vote_choice = yes_no_vote_op.choose_weighted_choice(rng);

// The same answer again, or one past the masternode's allowance,
// would be refused
let previous_answer: Option<(
YesNoAbstainVoteChoice,
PreviousVoteCount,
)> = platform
.drive
.fetch_identity_yes_no_vote(
Identifier::from(pro_tx_hash_bytes),
&identity_public_key,
*identity_nonce,
platform_version,
*vote_poll_id,
None,
&mut vec![],
platform_version,
)
.await
.expect("expected to make a masternode vote transition");
.expect("expected to read the masternode's answer");
if let Some((previous_choice, previous_count)) = previous_answer {
if previous_choice == vote_choice
|| previous_count >= votes_allowed_per_masternode
{
continue;
}
}

vote_poll_votes.insert(voting_identifier, resource_vote_choice);
let vote = Vote::YesNoVote(YesNoVote::V0(YesNoVoteV0 {
vote_poll_id: *vote_poll_id,
vote_choice,
}));

let state_transition = signed_masternode_vote(
vote,
pro_tx_hash_bytes,
masternode_list_item.state.voting_address,
signer,
identity_nonce_counter,
platform_version,
)
.await;

answered_in_this_block.insert(pro_tx_hash_bytes);

operations.push(state_transition);
}
Expand Down Expand Up @@ -3146,6 +3201,45 @@ pub struct ChainExecutionParameters {
pub current_addresses_with_balance: AddressesWithBalance,
}

/// `vote` signed with the voting key of the masternode `pro_tx_hash`, at the masternode's next
/// identity nonce
async fn signed_masternode_vote(
vote: Vote,
pro_tx_hash: [u8; 32],
voting_address: [u8; 20],
signer: &SimpleSigner,
identity_nonce_counter: &mut BTreeMap<Identifier, u64>,
platform_version: &PlatformVersion,
) -> StateTransition {
let voting_identifier = Identifier::create_voter_identifier(&pro_tx_hash, &voting_address);

let identity_public_key = IdentityPublicKey::V0(IdentityPublicKeyV0 {
id: 0,
purpose: Purpose::VOTING,
security_level: SecurityLevel::MEDIUM,
contract_bounds: None,
key_type: KeyType::ECDSA_HASH160,
read_only: false,
data: voting_address.to_vec().into(),
disabled_at: None,
});

let identity_nonce = identity_nonce_counter.entry(voting_identifier).or_default();
*identity_nonce += 1;

MasternodeVoteTransition::try_from_vote_with_signer(
vote,
signer,
Identifier::from(pro_tx_hash),
&identity_public_key,
*identity_nonce,
platform_version,
None,
)
.await
.expect("expected to make a masternode vote transition")
}

fn create_signed_instant_asset_lock_proofs_for_identities(
identities: Vec<Identity>,
balance_range: &RangeInclusive<Credits>,
Expand Down
Loading
Loading