aeternity / elixir-node

Elixir full node implementation of the aeternity specification
ISC License
213 stars 38 forks source link

Prototype - Proof of Stake Voting #190

Closed thepiwo closed 6 years ago

thepiwo commented 6 years ago

Basis Proof of Stake Voting

Idea

Let accounts, make on-chain transactions representing votes to a given question. The mechanism for counting votes should be the amount of tokens held by the account determining the weight of the vote.

Implementation Proposal

Question Transaction Any account can create a transaction, asking a question to hold the vote over. It should specify an question as plain text, as well as an close_block_height at which the voting on this is closed. Otherwise the transaction should include the normal fee, nonce and from_account fields and signature. These questions can either be boolean, yes - no questions or the transaction could include an array of possible answers.

These questions can be indexed in the chain_state for easy referencing and providing apis.

Vote Transaction Any account can vote on previously opened questions using a vote transaction. This should include the hash of the question transaction, as well as the answer, either boolean or referencing one of the possible answers. Otherwise the transaction should include the normal fee, nonce and from_account fields and signature.

These answers can be indexed in the chain_state for easy referencing and providing apis.

Closing Vote (Proposal 1) The account that created the question transaction, creates an close vote transaction after the close_block_height of the transaction, publishing the results of the question. In counting the results he consideres vote transactions by weight of tokens held in the block of close_block_height.

Closing Vote (Proposal 2) It is each clients task to count the results by the chain_state in the block of close_block_height.

Advanced Topics

meivantodorov commented 6 years ago

What this prototype does:

Add three new transaction data structures: VotingQuestionTransaction, VotingAswerTransaction and VotingTansaction.

VotingQuestionTransaction

We are registering new question in chainstate by his hash.

VotingAnswerTransaction

We are registering new answer for a question by providing his hash

VotingTransaction

It is a wrapper for the VotingAnswerTransaction and VotingQuestionTransaction. We are makeing SignedTx from VotingTransaction

Registering voting question

Any account can register a question. The requester has to provide:

Registering voting answer

Any account can register an answer. The voter has to provide:

Voting mechanism

This is very simple voting mechanism where after question has been registered there is time interval specified with start_block_height and stop_block_height. During this interval users can give their votes. After each new block has been added to the chain, the result for all opened questions is recalculated. The idea is the voters to check whats the current state of a voting. When the question is closed, then the last result is considered as final. The result is map that has all answers and the tokens for each of them.

Each registered question is stored into the chain state in map structure looks like that: %{hash_question1: %{data: %VotingQuestion{}, answers: [%VotingAnswer{}], result: %{answer, tokens} }}

Each registered answer will be added into the other answers that belong to this question hash

Validation

Json schema validation is used to ensure the correct structure of the requests.

Examples

Deadline : 09.02.18

thepiwo commented 6 years ago

What does the VotingTransaction wrap, whats the purpose?

meivantodorov commented 6 years ago

The purpose is not to check for many voting transactions but only for one. Otherwise we will need to pattern match more.

thepiwo commented 6 years ago

@meivantodorov @Artur64 whats the progress here?

thepiwo commented 6 years ago

@DanielaIvanova @Artur64 whats the progress here? you set yourself the deadline on 09.02. could yourself a new one? Maybe the end of the week?

DanielaIvanova commented 6 years ago

Ivan told as to fix:

thepiwo commented 6 years ago

As this is your (@DanielaIvanova and @Artur64) task, I'd like you to be self-sovereign about finishing it, as Ivan is on holiday now. What new deadline would you like to give yourselves?

DanielaIvanova commented 6 years ago

We will try to finish with Voting Prototype by 28.02.

DanielaIvanova commented 6 years ago

Voting Prototype and How to use it

The Voting Prototype provides a possibility to register voting question/answer transactions on the chain. Every account who wants to answer the question and has enough money to pay a fee can make an answer transaction on the chain. The mechanism for counting votes is the amount of tokens held by the account.

Registering voting question

Any account can register a question. Question structure:

Stop the miner:

Aecore.Miner.Worker.suspend

Check the chain state:

Aecore.Chain.Worker.chain_state

Registering voting question:

pubkey = elem(Aecore.Keys.Worker.pubkey(), 1)
data = %{question: "Is it raining?", possible_answer_count: 1, answers: ["yes", "no"], from_acc: pubkey, start_block_height: 2, close_block_height: 13, fee: 10, nonce: Map.get(Aecore.Chain.Worker.chain_state, pubkey, %{nonce: 0}).nonce + 1} Aecore.VotingPrototype.Manager.register({:question, data})

Check the pool:

Aecore.Txs.Pool.Worker.get_pool

Start mining a block:

Aecore.Miner.Worker.mine_sync_block_to_chain

Check top block:

Aecore.Chain.Worker.top_block

Check the chain state:

Aecore.Chain.Worker.chain_state

Registering Voting Answer:

q = Aecore.Chain.Worker.all_registered_voting_questions [q] = Map.keys(q)

pubkey = elem(Aecore.Keys.Worker.pubkey(), 1)
data = %{hash_question: q, answer: ["no"], from_acc: pubkey, fee: 10, nonce: Map.get(Aecore.Chain.Worker.chain_state, pubkey, %{nonce: 0}).nonce + 1} Aecore.VotingPrototype.Manager.register_answer(data)

Check the pool:

Aecore.Txs.Pool.Worker.get_pool

Start mining a block:

Aecore.Miner.Worker.mine_sync_block_to_chain

Get Voting Results for a question:

Aecore.Chain.Worker.get_voting_result_for_a_question q

Example p2p communication

You have to have two copies of the project.

First copy (node_0) of the project you should run: iex -S mix phx.server

In the second copy (node_1) in the project you have to change dev.exs file in node_1/apps/aehttpserver/config/dev.exs

port = case System.get_env("PORT") do nil -> 4001 env -> env end

And after that you should run: iex -S mix phx.server

We have to connect both nodes together. On node_0 you should run:

Aecore.Peers.Worker.add_peer "localhost:4001"

Now both nodes are connected and you can test the core and p2p communication.

thepiwo commented 6 years ago

good documentation, is this prototype finished?

DanielaIvanova commented 6 years ago

We found something that is not working properly and we will try to fix now.

thepiwo commented 6 years ago

can you mention cytadela8 and me, once you are done?

DanielaIvanova commented 6 years ago

@thepiwo @cytadela8 At this moment we are ready with Voting Prototype.

thepiwo commented 6 years ago

this prototype is finished (excluding PR #245 comments), but will be abandoned