Skip to content

Commit

Permalink
[fix] change community wallet default n-of-m to reduce threshold (0LN…
Browse files Browse the repository at this point in the history
…etworkCommunity#172)

Co-authored-by: 0o-de-lally <1364012+0o-de-lally@users.noreply.github.com>
  • Loading branch information
0xzoz and 0o-de-lally committed Aug 17, 2024
1 parent 30e7f9e commit 82dc487
Show file tree
Hide file tree
Showing 15 changed files with 3,353 additions and 3,337 deletions.
44 changes: 26 additions & 18 deletions framework/libra-framework/sources/ol_sources/community_wallet.move
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

/// 2. The Multisig account holders do not have common ancestry. This is important to prevent an account holder from trivially creating sybil accounts to qualify as a community wallet. Sybils are possibly without common ancestry, but it is much harder.

/// 3. The multisig account has a minimum of 5 Authorities, and a threshold of 3 signatures. If there are more authorities, a 3/5 ratio or more should be preserved.
/// MINIMUM_SIGS. The multisig account has a minimum of MINIMUM_AUTH Authorities, and a threshold of MINIMUM_SIGS signatures. If there are more authorities, a MINIMUM_SIGS/MINIMUM_AUTH ratio or more should be preserved.

/// 4. CommunityWallets have a high threshold for sybils: all multisig authorities must be unrelated in their permission trees, per ancestry.

Expand All @@ -33,28 +33,34 @@ module ol_framework::community_wallet {
use ol_framework::match_index;
use diem_framework::system_addresses;

// use diem_std::debug::print;
use diem_std::debug::print;

/// not authorized to operate on this account
const ENOT_AUTHORIZED: u64 = 1;
/// does not meet criteria for community wallet
const ENOT_QUALIFY_COMMUNITY_WALLET: u64 = 2;
/// Recipient does not have a slow wallet
const EPAYEE_NOT_SLOW_WALLET: u64 = 8;
/// Too few signers for Match Index
const ETOO_FEW_SIGNERS: u64 = 9;
/// This account needs to be donor directed.
const ENOT_donor_voice: u64 = 3;
const ENOT_DONOR_VOICE: u64 = 3;
/// This account needs a multisig enabled
const ENOT_MULTISIG: u64 = 4;
/// The multisig does not have minimum 5 signers and 3 approvals in config
/// The multisig does not have minimum MINIMUM_AUTH signers and MINIMUM_SIGS approvals in config
const ESIG_THRESHOLD: u64 = 5;
/// The multisig threshold does not equal 3/5
/// The multisig threshold does not equal MINIMUM_SIGS/MINIMUM_AUTH
const ESIG_THRESHOLD_RATIO: u64 = 6;
/// Signers may be sybil
const ESIGNERS_SYBIL: u64 = 7;
/// Recipient does not have a slow wallet
const EPAYEE_NOT_SLOW_WALLET: u64 = 8;
/// Too few signers for Match Index
const ETOO_FEW_SIGNERS: u64 = 9;


// STATICS
/// minimum n signatures for a transaction
const MINIMUM_SIGS: u64 = 2;
/// minimum m authorities for a wallet
const MINIMUM_AUTH: u64 = 3;

// A flag on the account that it wants to be considered a community wallet
struct CommunityWallet has key { }

Expand All @@ -64,7 +70,7 @@ module ol_framework::community_wallet {
}
public fun set_comm_wallet(sender: &signer) {
let addr = signer::address_of(sender);
assert!(donor_voice::is_donor_voice(addr), error::invalid_state(ENOT_donor_voice));
assert!(donor_voice::is_donor_voice(addr), error::invalid_state(ENOT_DONOR_VOICE));

if (is_init(addr)) {
move_to(sender, CommunityWallet{});
Expand All @@ -90,7 +96,7 @@ module ol_framework::community_wallet {
donor_voice::is_liquidate_to_match_index(addr) &&
// has multi_action instantialized
multi_action::is_multi_action(addr) &&
// multisig has minimum requirement of 3 signatures, and minimum list of 5 signers, and a minimum of 3/5 threshold. I.e. OK to have 4/5 signatures.
// multisig has minimum requirement of MINIMUM_SIGS signatures, and minimum list of MINIMUM_AUTH signers, and a minimum of MINIMUM_SIGS/MINIMUM_AUTH threshold. I.e. OK to have 4/MINIMUM_AUTH signatures.
multisig_thresh(addr)
&&
// the multisig authorities are unrelated per ancestry
Expand All @@ -101,12 +107,12 @@ module ol_framework::community_wallet {
let (n, m) = multi_action::get_threshold(addr);

// can't have less than three signatures
if (n < 3) return false;
if (n < MINIMUM_SIGS) return false;
// can't have less than five authorities
// pentapedal locomotion https://www.youtube.com/watch?v=bgWJ9DN1Qak
if (m < 5) return false;
if (m < MINIMUM_AUTH) return false;

let r = fixed_point32::create_from_rational(3, 5);
let r = fixed_point32::create_from_rational(MINIMUM_SIGS, MINIMUM_AUTH);
let pct_baseline = fixed_point32::multiply_u64(100, r);
let r = fixed_point32::create_from_rational(n, m);
let pct = fixed_point32::multiply_u64(100, r);
Expand Down Expand Up @@ -149,12 +155,14 @@ module ol_framework::community_wallet {
sig: &signer,
init_signers: vector<address>
) {
// policy is to have at least 5 signers as auths on the account.
// policy is to have at least m signers as auths on the account.
let len = vector::length(&init_signers);
assert!(len > 4, error::invalid_argument(ETOO_FEW_SIGNERS));
assert!(len >= MINIMUM_AUTH, error::invalid_argument(ETOO_FEW_SIGNERS));
print(&len);

// enforce 3/5 multi auth
let n = (3 * len) / 5;
// enforce n/m multi auth
let n = (MINIMUM_SIGS * len) / MINIMUM_AUTH;
print(&n);

let (fam, _, _) = ancestry::any_family_in_list(*&init_signers);
assert!(!fam, error::invalid_argument(ESIGNERS_SYBIL));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -473,23 +473,23 @@ module ol_framework::test_donor_voice {
}

#[test(root = @ol_framework, community = @0x10011, alice = @0x1000a, bob =
@0x1000b, carol = @0x1000c, dave = @0x1000d, eve = @0x1000e)]
@0x1000b, carol = @0x1000c)]
fun migrate_cw_bug(root: &signer, community: &signer, alice: &signer, bob:
&signer, carol: &signer, dave: &signer, eve: &signer) {
&signer, carol: &signer) {

// create genesis and fund accounts
mock::genesis_n_vals(root, 5);
mock::ol_initialize_coin_and_fund_vals(root, 10000000, true);


// create resource account for community wallet
let (comm_resource_sig, _cap) = ol_account::ol_create_resource_account(community, b"senior sword vocal target latin rug ship summer bar suit cake derive pluck sunset can scorpion tornado hungry erosion heart away suggest glad seek");
let community_wallet_resource_address = signer::address_of(&comm_resource_sig);

let community_wallet_address = signer::address_of(community);

// verify resource account was created succesfully for the community wallet
assert!(resource_account::is_resource_account(community_wallet_resource_address), 7357003);
assert!(resource_account::is_resource_account(community_wallet_resource_address), 7357000);
assert!(!community_wallet::is_init(community_wallet_address), 100); //TODO: find appropriate error codes


Expand All @@ -500,15 +500,15 @@ module ol_framework::test_donor_voice {
ol_account::transfer(bob, community_wallet_resource_address, bob_donation);
let (_, bob_balance) = ol_account::balance(@0x1000b);

assert!(bob_balance == 9999958, 7357001);
assert!(bob_balance == 9999958, 7357002);
let (_, community_wallet_balance) = ol_account::balance(community_wallet_resource_address);
assert!(community_wallet_balance == 42, 7357001);
assert!(community_wallet_balance == 42, 7357003);

// migrate community wallet
community_wallet::migrate_community_wallet_account(root, community);

// verify correct migration of community wallet
assert!(community_wallet::is_init(community_wallet_address), 101); //TODO: find appropriate error codes
assert!(community_wallet::is_init(community_wallet_address), 7357004); //TODO: find appropriate error codes


let _b = donor_voice::is_liquidate_to_match_index(community_wallet_address);
Expand All @@ -517,76 +517,77 @@ module ol_framework::test_donor_voice {
let alice_addr = signer::address_of(alice);
let bob_addr = signer::address_of(bob);
let carol_addr = signer::address_of(carol);
let dave_addr = signer::address_of(dave);
let eve_addr = signer::address_of(eve);
// let dave_addr = signer::address_of(dave);
// let eve_addr = signer::address_of(eve);

let addrs = vector::singleton(alice_addr);
vector::push_back(&mut addrs, bob_addr);
vector::push_back(&mut addrs, carol_addr);
vector::push_back(&mut addrs, dave_addr);
vector::push_back(&mut addrs, eve_addr);
// vector::push_back(&mut addrs, dave_addr);
// vector::push_back(&mut addrs, eve_addr);

ancestry::fork_migrate(root, alice, vector::singleton(alice_addr));
ancestry::fork_migrate(root, bob, vector::singleton(bob_addr));
ancestry::fork_migrate(root, carol, vector::singleton(carol_addr));
ancestry::fork_migrate(root, dave, vector::singleton(dave_addr));
ancestry::fork_migrate(root, eve, vector::singleton(eve_addr));
// ancestry::fork_migrate(root, dave, vector::singleton(dave_addr));
// ancestry::fork_migrate(root, eve, vector::singleton(eve_addr));

// wake up and initialize community wallet as a multi sig, donor voice account
// wake up and initialize community wallet as a multi sig, donor voice account
community_wallet::init_community(&comm_resource_sig, addrs);

// verify wallet is a initialized correctly
assert!(donor_voice::is_donor_voice(signer::address_of(&comm_resource_sig)), 102);
assert!(cumulative_deposits::is_init_cumu_tracking(community_wallet_resource_address), 100);
assert!(donor_voice::is_donor_voice(signer::address_of(&comm_resource_sig)), 7357005);
assert!(cumulative_deposits::is_init_cumu_tracking(community_wallet_resource_address), 7357006);

// make a transaction and have signers execute
// make a transaction and have signers execute
mock::trigger_epoch(root); // into epoch 1

let uid = donor_voice::propose_payment(bob, community_wallet_resource_address, @0x1000b, 42, b"thanks bob");
let (found, idx, status_enum, completed) = donor_voice::get_multisig_proposal_state(community_wallet_resource_address, &uid);
assert!(found, 7357004);
assert!(idx == 0, 7357005);
assert!(status_enum == 1, 7357006);
assert!(!completed, 7357007);
assert!(found, 7357007);
assert!(idx == 0, 7357006);
assert!(status_enum == 1, 7357009);
assert!(!completed, 7357010);

// it is not yet scheduled, it's still only a proposal by an admin
assert!(!donor_voice::is_scheduled(community_wallet_resource_address, &uid), 7357008);
assert!(!donor_voice::is_scheduled(community_wallet_resource_address, &uid), 7357011);


// have another 2 signers sign the proposal
donor_voice::propose_payment(carol, community_wallet_resource_address, @0x1000b, 42, b"thanks bob");
let uid = donor_voice::propose_payment(alice, community_wallet_resource_address, @0x1000b, 42, b"thanks bob");
donor_voice::propose_payment(carol, community_wallet_resource_address,
@0x1000b, 42, b"thanks bob");
// Commit Note: Two votes are enough.
let (found, idx, status_enum, completed) = donor_voice::get_multisig_proposal_state(community_wallet_resource_address, &uid);
assert!(found, 7357004);
assert!(idx == 0, 7357005);
assert!(status_enum == 1, 7357006);
assert!(completed, 7357007); // now completed
assert!(found, 7357012);
assert!(idx == 0, 7357013);
assert!(status_enum == 1, 7357014);
assert!(completed, 7357015); // now completed

// confirm it is scheduled
assert!(donor_voice::is_scheduled(community_wallet_resource_address, &uid), 7357008);
assert!(donor_voice::is_scheduled(community_wallet_resource_address, &uid), 7357016);

// the default timed payment is 4 epochs, we are in epoch 2
let list = donor_voice::find_by_deadline(community_wallet_resource_address, 4);
assert!(vector::contains(&list, &uid), 7357009);
assert!(vector::contains(&list, &uid), 7357017);

// simulate another 2 epochs, we are in epoxh 4
mock::trigger_epoch(root);
mock::trigger_epoch(root);

// verify payment has not been processed
let (_, bob_balance_pre_scheduled_epoch) = ol_account::balance(@0x1000b);
assert!(bob_balance_pre_scheduled_epoch == 10999958, 7357001); //increase by 1000000 due to amount recieved in epoch 1
assert!(bob_balance_pre_scheduled_epoch == 10999958, 7357018); //increase by 1000000 due to amount recieved in epoch 1
let (_, community_wallet_balance_pre_scheduled_epoch) = ol_account::balance(community_wallet_resource_address);
assert!(community_wallet_balance_pre_scheduled_epoch == 42, 7357001);
assert!(community_wallet_balance_pre_scheduled_epoch == 42, 7357019);

// simulate another 2 epochs, we are in epoch 6
mock::trigger_epoch(root);
mock::trigger_epoch(root);

let (_, bob_balance_processed_payment) = ol_account::balance(@0x1000b);
assert!(bob_balance_processed_payment == 11000000, 7357001);
assert!(bob_balance_processed_payment == 11000000, 7357020);
let (_, community_wallet_balance_processed_payment) = ol_account::balance(community_wallet_resource_address);
assert!(community_wallet_balance_processed_payment == 0, 7357001);
assert!(community_wallet_balance_processed_payment == 0, 7357021);

}
}
Binary file modified framework/releases/head.mrb
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2a6c36efe858195b4774fb33a50fbdca73aa2c5ac5c43e9d573e853d98a0b384
fa42905a0cc3e72f263deba3a3397cf773260d0274d2ffb4f904d2bb60b823ec
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Upgrade proposal for package `MoveStdlib`

// Framework commit hash: a08e5536f77a9a9f4b1e0344a965bbb68e428dc5
// Framework commit hash: aa95b5827cb4ce38db81ece0e7789dafde9dc39b
// Builder commit hash: db1137ba1f8e7301e325021f71f740063daaf76e

// Next step script hash: 4b328fdd686a7929427b0100f471d93545f40997d72856524542dc20dec2b14f
// Next step script hash: 7852564d22179f6b34d005a5df30ddb5edea85b4772f6b45eced454c715cc104

// source digest: CD5C8655F0340314CC68657DF89A58E257A0A88218E2B07A278A20B843E7A09E
script {
Expand All @@ -17,7 +17,7 @@ script {
let framework_signer = diem_governance::resolve_multi_step_proposal(
proposal_id,
@0000000000000000000000000000000000000000000000000000000000000001,
vector[75u8,50u8,143u8,221u8,104u8,106u8,121u8,41u8,66u8,123u8,1u8,0u8,244u8,113u8,217u8,53u8,69u8,244u8,9u8,151u8,215u8,40u8,86u8,82u8,69u8,66u8,220u8,32u8,222u8,194u8,177u8,79u8,],
vector[120u8,82u8,86u8,77u8,34u8,23u8,159u8,107u8,52u8,208u8,5u8,165u8,223u8,48u8,221u8,181u8,237u8,234u8,133u8,180u8,119u8,47u8,107u8,69u8,236u8,237u8,69u8,76u8,113u8,92u8,193u8,4u8,],
);
let code = vector::empty();
let code_chunk0 =
Expand Down Expand Up @@ -1545,6 +1545,6 @@ script {
13u8,0u8,0u8,0u8,0u8,0u8,0u8,
];
code::publish_package_txn(&framework_signer, metadata_chunk1, code);
version::upgrade_set_git(&framework_signer, x"a08e5536f77a9a9f4b1e0344a965bbb68e428dc5")
version::upgrade_set_git(&framework_signer, x"aa95b5827cb4ce38db81ece0e7789dafde9dc39b")
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4b328fdd686a7929427b0100f471d93545f40997d72856524542dc20dec2b14f
7852564d22179f6b34d005a5df30ddb5edea85b4772f6b45eced454c715cc104
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Upgrade proposal for package `VendorStdlib`

// Framework commit hash: a08e5536f77a9a9f4b1e0344a965bbb68e428dc5
// Framework commit hash: aa95b5827cb4ce38db81ece0e7789dafde9dc39b
// Builder commit hash: db1137ba1f8e7301e325021f71f740063daaf76e

// Next step script hash: f4521b01f82714fff409a13a29a48c5286fc09f25d217f4e11368b5eb83322ca
// Next step script hash: 3f3bef41f1e0ffc7668106f2193f8f0adb8aa05dfc3f231f40cd1d701611d120

// source digest: 5E12DDD8987B153D75378183FB77218A1FAB6038899EB9121ECD4BE94EC1D598
script {
Expand All @@ -17,7 +17,7 @@ script {
let framework_signer = diem_governance::resolve_multi_step_proposal(
proposal_id,
@0000000000000000000000000000000000000000000000000000000000000001,
vector[244u8,82u8,27u8,1u8,248u8,39u8,20u8,255u8,244u8,9u8,161u8,58u8,41u8,164u8,140u8,82u8,134u8,252u8,9u8,242u8,93u8,33u8,127u8,78u8,17u8,54u8,139u8,94u8,184u8,51u8,34u8,202u8,],
vector[63u8,59u8,239u8,65u8,241u8,224u8,255u8,199u8,102u8,129u8,6u8,242u8,25u8,63u8,143u8,10u8,219u8,138u8,160u8,93u8,252u8,63u8,35u8,31u8,64u8,205u8,29u8,112u8,22u8,17u8,209u8,32u8,],
);
let code = vector::empty();
let code_chunk0 =
Expand Down Expand Up @@ -7332,6 +7332,6 @@ script {
vector::append(&mut metadata_chunk1, metadata_chunk2);
vector::append(&mut metadata_chunk1, metadata_chunk3);
code::publish_package_txn(&framework_signer, metadata_chunk1, code);
version::upgrade_set_git(&framework_signer, x"a08e5536f77a9a9f4b1e0344a965bbb68e428dc5")
version::upgrade_set_git(&framework_signer, x"aa95b5827cb4ce38db81ece0e7789dafde9dc39b")
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
f4521b01f82714fff409a13a29a48c5286fc09f25d217f4e11368b5eb83322ca
3f3bef41f1e0ffc7668106f2193f8f0adb8aa05dfc3f231f40cd1d701611d120
Loading

0 comments on commit 82dc487

Please sign in to comment.