drk: Initial DAO commands layout.

This commit is contained in:
parazyd
2023-01-09 15:42:44 +01:00
parent 0c292e524e
commit d860174fc8
2 changed files with 203 additions and 2 deletions

40
bin/drk/src/dao.rs Normal file
View File

@@ -0,0 +1,40 @@
/* This file is part of DarkFi (https://dark.fi)
*
* Copyright (C) 2020-2023 Dyne.org foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use darkfi_sdk::{
crypto::{SecretKey, TokenId},
pasta::pallas,
};
use darkfi_serial::{SerialDecodable, SerialEncodable};
#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
pub struct DaoParams {
/// The minimum amount of governance tokens needed to open a proposal
pub proposer_limit: u64,
/// Minimal threshold of participating total tokens needed for a proposal to pass
pub quorum: u64,
/// The ratio of winning/total votes needed for a proposal to pass
pub approval_ratio_base: u64,
pub approval_ratio_quot: u64,
/// DAO's governance token ID
pub gov_token_id: TokenId,
/// Secret key for the DAO
pub secret_key: SecretKey,
/// DAO bulla blind
pub bulla_blind: pallas::Base,
}

View File

@@ -25,14 +25,15 @@ use std::{
use anyhow::{anyhow, Context, Result};
use clap::{Parser, Subcommand};
use darkfi::tx::Transaction;
use darkfi::{tx::Transaction, zk::halo2::Field};
use darkfi_money_contract::client::Coin;
use darkfi_sdk::{
crypto::{PublicKey, TokenId},
crypto::{PublicKey, SecretKey, TokenId},
pasta::{group::ff::PrimeField, pallas},
};
use darkfi_serial::{deserialize, serialize};
use prettytable::{format, row, Table};
use rand::rngs::OsRng;
use serde_json::json;
use simplelog::{ColorChoice, TermLogger, TerminalMode};
use url::Url;
@@ -66,6 +67,10 @@ mod rpc_wallet;
mod cli_util;
use cli_util::{parse_token_pair, parse_value_pair};
/// DAO aux functionality
mod dao;
use dao::DaoParams;
#[derive(Parser)]
#[command(about = cli_desc!())]
struct Args {
@@ -173,6 +178,10 @@ enum Subcmd {
/// find coins sent to us and fill our wallet with the necessary metadata.
Subscribe,
/// DAO functionalities
#[command(subcommand)]
Dao(DaoSubcmd),
/// Scan the blockchain and parse relevant transactions
Scan {
#[arg(long)]
@@ -212,6 +221,92 @@ enum OtcSubcmd {
Sign,
}
#[derive(Subcommand)]
enum DaoSubcmd {
/// Create DAO parameters
Create {
/// The minimum amount of governance tokens needed to open a proposal for this DAO
proposer_limit: u64,
/// Minimal threshold of participating total tokens needed for a proposal to pass
quorum: u64,
/// The ratio of winning votes/total votes needed for a proposal to pass (2 decimals),
approval_ratio: f64,
/// DAO's governance token ID
gov_token_id: String,
},
/// View DAO data from stdin
View,
/// List imported DAOs
List,
/// Import DAO data from stdin
Import {
/// Named identifier for the DAO
dao_name: String,
},
/// Mint a DAO on-chain
Mint {
/// Named identifier for the DAO
dao_name: String,
},
/// Create a proposal for a DAO
Propose {
/// Named identifier for the DAO
dao_name: String,
/// Pubkey to send tokens to with proposal success
recv_pubkey: String,
/// Amount to send from DAO with proposal success
amount: u64,
/// Token ID to send from DAO with proposal success
token_id: String,
serial: u64,
},
/// List DAO proposals
Proposals {
/// Named identifier for the DAO
dao_name: String,
},
/// View a DAO proposal data
Proposal {
/// Named identifier for the DAO
dao_name: String,
/// Proposal identifier
proposal: String,
},
/// Vote on a given proposal
Vote {
/// Named identifier for the DAO
dao_name: String,
/// Proposal identifier
proposal: String,
/// Vote
vote: String,
},
/// Execute a DAO proposal
Exec {
/// Named identifier for the DAO
dao_name: String,
/// Proposal identifier
proposal: String,
},
}
pub struct Drk {
pub rpc_client: RpcClient,
}
@@ -592,5 +687,71 @@ async fn main() -> Result<()> {
Ok(())
}
Subcmd::Dao(cmd) => match cmd {
DaoSubcmd::Create { proposer_limit, quorum, approval_ratio, gov_token_id } => {
if approval_ratio > 1.0 {
eprintln!("Error: Approval ratio cannot be >1.0");
exit(1);
}
let approval_ratio_quot = 100_u64;
let approval_ratio_base = (approval_ratio * approval_ratio_quot as f64) as u64;
let gov_token_id =
TokenId::try_from(gov_token_id.as_str()).with_context(|| "Invalid Token ID")?;
let secret_key = SecretKey::random(&mut OsRng);
let bulla_blind = pallas::Base::random(&mut OsRng);
let dao_params = DaoParams {
proposer_limit,
quorum,
approval_ratio_base,
approval_ratio_quot,
gov_token_id,
secret_key,
bulla_blind,
};
let encoded = bs58::encode(&serialize(&dao_params)).into_string();
println!("{}", encoded);
Ok(())
}
DaoSubcmd::View => {
let mut buf = String::new();
stdin().read_to_string(&mut buf)?;
let bytes = bs58::decode(&buf.trim()).into_vec()?;
let dao_params: DaoParams = deserialize(&bytes)?;
println!("DAO Parameters:");
println!("Proposer limit: {}", dao_params.proposer_limit);
println!("Quorum: {}", dao_params.quorum);
println!(
"Approval ratio: {}",
dao_params.approval_ratio_base as f64 / dao_params.approval_ratio_quot as f64
);
println!("Governance token ID: {}", dao_params.gov_token_id);
println!("Secret key: {}", dao_params.secret_key);
println!("Bulla blind: {:?}", dao_params.bulla_blind);
Ok(())
}
DaoSubcmd::Import { dao_name } => todo!(),
DaoSubcmd::List => todo!(),
DaoSubcmd::Mint { dao_name } => todo!(),
DaoSubcmd::Propose { dao_name, recv_pubkey, amount, token_id, serial } => todo!(),
DaoSubcmd::Proposals { dao_name } => todo!(),
DaoSubcmd::Proposal { dao_name, proposal } => todo!(),
DaoSubcmd::Vote { dao_name, proposal, vote } => todo!(),
DaoSubcmd::Exec { dao_name, proposal } => todo!(),
},
}
}