include "Vote.aes"
contract interface Voting =
stateful entrypoint init : (address, list(address), int, int, int) => unit
stateful entrypoint propose : (Vote.id) => Vote.outcome
stateful entrypoint cast_vote : (Vote.id, Vote.ballot) => Vote.outcome
entrypoint count_results : (Vote.id) => (int * int)
stateful entrypoint add_voter : (address) => unit
stateful entrypoint remove_voter : (address) => unit
entrypoint is_voter : (address) => bool
stateful entrypoint set_miner_threshold : (int) => unit
stateful entrypoint set_witness_threshold : (int) => unit
stateful entrypoint set_voter_threshold : (int) => unit
entrypoint validate_custom : (string, list(int), list(address), list(string)) => unit
stateful entrypoint process_custom : (string, list(int), list(address), list(string)) => unit
contract interface Witnessing =
stateful entrypoint init : (address, list(address)) => unit
stateful entrypoint add_witness : (address) => unit
stateful entrypoint remove_witness : (address) => unit
entrypoint is_witness : (address) => bool
entrypoint is_eligible : (address) => bool
entrypoint threshold : () => int
entrypoint validate_custom : (string, list(int), list(address), list(string)) => unit
stateful entrypoint process_custom : (string, list(int), list(address), list(string)) => unit
stateful entrypoint set_threshold_percents : (int) => unit
contract interface WhitelistMining =
stateful entrypoint init : (address, list(address)) => unit
stateful entrypoint add_miner : (address) => unit
stateful entrypoint remove_miner : (address) => unit
entrypoint is_miner: (address) => bool
entrypoint can_mine : (address) => bool
entrypoint validate_custom : (string, list(int), list(address), list(string)) => unit
stateful entrypoint process_custom : (string, list(int), list(address), list(string)) => unit
main contract GajumaruMain =
record state =
{ vote_ct : Voting,
mine_ct : WhitelistMining,
witness_ct : Witnessing
}
stateful entrypoint init(voting_ct : Voting, witnessing_ct : Witnessing, mining_ct : WhitelistMining) =
{vote_ct = voting_ct,
witness_ct = witnessing_ct,
mine_ct = mining_ct
}
stateful entrypoint propose_vote(v : Vote.id) =
assert_consistency(v)
maybe_finalise(v, state.vote_ct.propose(v))
stateful entrypoint cast_vote(v : Vote.id, ballot : Vote.ballot) =
maybe_finalise(v, state.vote_ct.cast_vote(v, ballot))
entrypoint count_results(v : Vote.id) =
state.vote_ct.count_results(v)
entrypoint can_mine(miner : address) =
state.mine_ct.can_mine(miner)
entrypoint is_eligible_to_witness(w : address) =
state.witness_ct.is_eligible(w)
entrypoint witnessing_threshold() : int =
state.witness_ct.threshold()
entrypoint contracts() : (Voting * WhitelistMining * Witnessing) =
(state.vote_ct, state.mine_ct, state.witness_ct)
// private functions
stateful function maybe_finalise(v : Vote.id, outcome : Vote.outcome) =
switch (outcome)
Vote.PASSED => process_vote_passed(v)
Vote.FAILED => ()
Vote.STILL_ONGOING => ()
stateful function process_vote_passed(id : Vote.id) =
switch (Vote.category(id))
Vote.USER =>
let (action, beneficiary) = Vote.extract_user_change(id)
switch (action)
Vote.ADD_VOTER =>
state.vote_ct.add_voter(beneficiary)
Vote.REMOVE_VOTER =>
state.vote_ct.remove_voter(beneficiary)
Vote.ADD_MINER =>
state.mine_ct.add_miner(beneficiary)
Vote.REMOVE_MINER =>
state.mine_ct.remove_miner(beneficiary)
Vote.ADD_WITNESS =>
state.witness_ct.add_witness(beneficiary)
Vote.REMOVE_WITNESS =>
state.witness_ct.remove_witness(beneficiary)
Vote.THRESHOLD =>
let (action, val) = Vote.extract_threshold_change(id)
switch (action)
Vote.CHANGE_MINER_THRESHOLD =>
state.vote_ct.set_miner_threshold(val)
Vote.CHANGE_WITNESS_THRESHOLD =>
state.vote_ct.set_witness_threshold(val)
Vote.CHANGE_VOTER_THRESHOLD =>
state.vote_ct.set_voter_threshold(val)
Vote.CONTRACT =>
let (action, addr) = Vote.extract_contract_change(id)
switch (action)
Vote.CHANGE_VOTER_CONTRACT =>
let ct : Voting = Address.to_contract(addr)
put(state{vote_ct = ct})
Vote.CHANGE_MINER_CONTRACT =>
let ct : WhitelistMining = Address.to_contract(addr)
put(state{mine_ct = ct})
Vote.CHANGE_WITNESS_CONTRACT =>
let ct : Witnessing = Address.to_contract(addr)
put(state{witness_ct = ct})
Vote.WITNESS =>
let threshold = Vote.extract_witness_change(id)
state.witness_ct.set_threshold_percents(threshold)
Vote.CUSTOM =>
let (recipient, action, ints, addresses, strings) = Vote.extract_custom_change(id)
switch(recipient)
Vote.VOTING =>
state.vote_ct.process_custom(action, ints, addresses, strings)
Vote.WITNESSING =>
state.witness_ct.process_custom(action, ints, addresses, strings)
Vote.MINING =>
state.mine_ct.process_custom(action, ints, addresses, strings)
()
function assert_consistency(id : Vote.id) =
switch (Vote.category(id))
Vote.USER =>
let (action, beneficiary) = Vote.extract_user_change(id)
switch (action)
Vote.ADD_VOTER =>
require(!is_voter(beneficiary), "Already a voter")
Vote.REMOVE_VOTER =>
require(is_voter(beneficiary), "An unknown voter")
Vote.ADD_MINER =>
require(!is_miner(beneficiary), "Already a miner")
Vote.REMOVE_MINER =>
require(is_miner(beneficiary), "An unknown miner")
Vote.ADD_WITNESS =>
require(!is_witness(beneficiary), "Already a witness")
Vote.REMOVE_WITNESS =>
require(is_witness(beneficiary), "An unknown witness")
Vote.THRESHOLD =>
let (action, val) = Vote.extract_threshold_change(id)
assert_threshold_boundaries(val)
Vote.CONTRACT =>
let (action, addr) = Vote.extract_contract_change(id)
require(Address.is_contract(addr), "No such contract")
Vote.WITNESS =>
let val = Vote.extract_witness_change(id)
assert_threshold_boundaries(val)
require(val > 50, "The witnessing contract threshold must be above 50 in order to protect from forks")
Vote.CUSTOM =>
let (recipient, action, ints, addresses, strings) = Vote.extract_custom_change(id)
switch(recipient)
Vote.VOTING =>
state.vote_ct.validate_custom(action, ints, addresses, strings)
Vote.WITNESSING =>
state.witness_ct.validate_custom(action, ints, addresses, strings)
Vote.MINING =>
state.mine_ct.validate_custom(action, ints, addresses, strings)
function is_voter(a : address) =
state.vote_ct.is_voter(a)
function is_miner(a : address) =
state.mine_ct.is_miner(a)
function is_witness(a : address) =
state.witness_ct.is_witness(a)
function assert_threshold_boundaries(t : int) =
require(t > 0 && t < 101, "Invalid percentage")