Files
darkfi/bin/drk/dao.sql
2024-02-14 15:25:00 +02:00

170 lines
5.7 KiB
SQL

-- # DAO::mint()
--
-- First one person will create the DAO
--
-- $ drk dao create_dao \
-- PROPOSER_LIMIT \
-- QUORUM \
-- APPROVAL_RATIO_BASE \
-- APPROVAL_RATIO_QUOTIENT \
-- GOV_TOKEN_ID > dao.dat
--
-- dat.dat contains:
--
-- * DAO parameters as listed above
-- * secret key for the DAO
-- * bulla blind
--
-- We can view the data like so:
--
-- $ drk dao view_dao < dao.dat
--
-- Now everyone inside the DAO exchanges dao.dat out of band will import
-- it into their wallets.
--
-- $ drk dao import_dao DAO_NAME < dao.dat
-- Imported DAO ccb8XXX8af6
--
-- Where ccb8XXX8af6 is the DAO's bulla.
--
-- Next one person will mint it on chain
--
-- $ drk dao mint DAO_NAME
-- Broadcasted DAO ccb8XXX8af6
--
-- And then the others will receive confirmation that the DAO they imported
-- into their wallet has also been accepted on chain.
-- # Minting and Receiving Coin
--
-- Assume that the governance tokens have been created and distributed
-- appropriately among DAO members. We will skip that part here.
--
-- Now the DAO can receive coins into its treasury. These coins simply
-- have both the coin's spend_hook and user_data fields set correctly
-- otherwise they are rejected as invalid/malformed.
-- # DAO::propose()
--
-- Create a proposal for the DAO
--
-- $ drk dao propose \
-- DAO_NAME \
-- RECV_PUBKEY \
-- AMOUNT \
-- SERIAL \
-- SENDCOIN_TOKEN_ID
--
-- If we don't have enough tokens to meet the proposer_limit threshold
-- then this call will simply fail with an error message. Nothing will
-- be added to the database or sent to the network.
--
-- The other participants should automatically receive the proposal
-- ready to vote on it.
-- # DAO::vote()
--
-- You have received a proposal which is active. You can now vote on it.
--
-- $ drk dao proposals DAO_NAME
-- [0] f6cae63ced53d02b372206a8d3ed5ac03fde18da306a520285fd56e8d031f6cf
-- [1] 1372622f4a38be6eb1c90fa67864474c6603d9f8d4228106e20e2d0d04f2395e
-- [2] 88b18cbc38dbd3af8d25237af3903e985f70ea06d1e25966bf98e3f08e23c992
--
-- $ drk dao show_proposal 1
-- Proposal: 1372622f4a38be6eb1c90fa67864474c6603d9f8d4228106e20e2d0d04f2395e
-- destination: ...
-- amount: ...
-- token_id: ...
-- dao_name: DAO_NAME
-- dao_bulla: ...
-- Current yes votes: X
-- Current no votes: Y
-- Total votes: X + Y
-- [================ ] 45.56%
-- DAO quorum threshold: Z
-- DAO approval ratio: 60%
--
-- $ drk dao vote 1 yes
-- # DAO::exec()
--
-- Once there are enough yes votes to satisfy the quorum and approval ratio,
-- then any DAO member can execute the payment out of the treasury.
--
-- $ drk dao exec 1
--
-- FUTURE NOTE: We have to assume that 2 people could try to exec at once.
-- So if our exec fails, then the tx fee we pay should be returned
-- to our wallet.
-- We should design our tables for exec accordingly.
-- For now I didn't put anything, but we should keep this minor
-- point in mind and ruminate on it for later.
PRAGMA foreign_keys = ON;
CREATE TABLE IF NOT EXISTS Fd8kfCuqU8BoFFp6GcXv5pC8XXRkBK7gUPQX5XDz7iXj_dao_daos (
dao_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
name BLOB UNIQUE NOT NULL,
proposer_limit BLOB NOT NULL,
-- minimum threshold for total number of votes for proposal to pass.
-- If there's too little activity then it cannot pass.
quorum BLOB NOT NULL,
-- Needed ratio of yes/total for proposal to pass.
-- approval_ratio = approval_ratio_quot / approval_ratio_base
approval_ratio_base INTEGER NOT NULL,
approval_ratio_quot INTEGER NOT NULL,
gov_token_id BLOB NOT NULL,
secret BLOB NOT NULL,
bulla_blind BLOB NOT NULL,
-- these values are NULL until the DAO is minted on chain and received
leaf_position BLOB,
tx_hash BLOB,
call_index INTEGER
);
-- The merkle tree containing DAO bullas
CREATE TABLE IF NOT EXISTS Fd8kfCuqU8BoFFp6GcXv5pC8XXRkBK7gUPQX5XDz7iXj_dao_trees (
daos_tree BLOB NOT NULL,
proposals_tree BLOB NOT NULL
);
CREATE TABLE IF NOT EXISTS Fd8kfCuqU8BoFFp6GcXv5pC8XXRkBK7gUPQX5XDz7iXj_dao_proposals (
proposal_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
dao_id INTEGER NOT NULL,
-- Public key of person that would receive the funds
recv_public BLOB NOT NULL,
-- Amount of funds that would be sent
amount BLOB NOT NULL,
-- Token ID we propose to send
sendcoin_token_id BLOB NOT NULL,
bulla_blind BLOB NOT NULL,
-- these values are NULL until the proposal is minted on chain
-- and received by the DAO
leaf_position BLOB,
money_snapshot_tree BLOB,
tx_hash BLOB,
call_index INTEGER,
-- this is NULL until we have voted on this proposal
our_vote_id INTEGER UNIQUE,
FOREIGN KEY(our_vote_id) REFERENCES Fd8kfCuqU8BoFFp6GcXv5pC8XXRkBK7gUPQX5XDz7iXj_dao_votes(vote_id) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY(dao_id) REFERENCES Fd8kfCuqU8BoFFp6GcXv5pC8XXRkBK7gUPQX5XDz7iXj_dao_daos(dao_id) ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE TABLE IF NOT EXISTS Fd8kfCuqU8BoFFp6GcXv5pC8XXRkBK7gUPQX5XDz7iXj_dao_votes (
vote_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
proposal_id INTEGER NOT NULL,
vote_option INTEGER NOT NULL,
yes_vote_blind BLOB NOT NULL,
all_vote_value BLOB NOT NULL,
all_vote_blind BLOB NOT NULL,
-- these values are NULL until the vote is minted on chain
-- and received by the DAO
tx_hash BLOB,
call_index INTEGER,
-- My code has votes merkle tree and position for votes, but
-- that might be a mistake...
FOREIGN KEY(proposal_id) REFERENCES Fd8kfCuqU8BoFFp6GcXv5pC8XXRkBK7gUPQX5XDz7iXj_dao_proposals(proposal_id) ON DELETE CASCADE ON UPDATE CASCADE
);