Skip to content

Conversation

@shamil-gadelshin
Copy link
Contributor

Copied PR to the development branch: original PR and commit history can be found here -
mnaamani#2

- add iteration 2 codex and engine modules
- delete codex/Cargo.lock
- delete engine/Cargo.lock
- update gitignore
@bedeho bedeho self-requested a review February 11, 2020 14:01
Copy link
Member

@bedeho bedeho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Execution model: The model seems very complex, and its not clear how exactly to naturally use it for different types. I already see that the proposal_code is not per say meant to be literal WASM code fragments, and it would be very impractical to expect that sort of heavy setup and handling in a codex module. I think the much simpler approach of passing a dispatchable, like is done in democracy, is extremely simple and clean. The codex would simply hold the dispatchables it wanted to run, and guard with root origin check.

  • We did not actually properly define what the side-effect of the text proposal should be. I think we should not confuse the proposal body, with the main proposition itself, as the body will possibly include a broader rationale, links to referecnes etc. The actual text proposal being voted on should be a standalone parameter I think. The side-effect would be that the proposal text is stored as in some state in the codex engine. In the future perhaps it should be stored somewhere else, but for now we may as well put it there, although I do like the idea of the codex being stateless.

  • As I point out later in the review, actors should not be identified with accounts, but with some configurable role identifier, at least in the engine. In the runtime, we probably want ot use the membership id for the proposer type, and the council member id for the voter type.

  • Just to confirm, is it the case that the codex crate is only consuming anything in the proposals engine crate via crate based dependency management? There is no use of relative paths of modules in the directory tree?

@shamil-gadelshin
Copy link
Contributor Author

1. Execution model

I'm not sure it is possible. There are no dispatchable extrinsic before runtime compilation. In democracy, proposal associated type defined as

pub trait Trait: system::Trait + Sized {
	type Proposal: Parameter + Dispatchable<Origin=Self::Origin>;
...
}

and instantiated variant is

impl democracy::Trait for Runtime {
	type Proposal = Call;
...
}

Where Call is 'outer call' for the runtime:
https://substrate.dev/docs/en/runtime/types/call-enum

And you cannot have serialized extrinsic call inside of the neighbor extrinsic. I tried to do that in my first iteration. And this exactly the reason why I suggest to create proposal parameters on the frontend - to be able to pack extrinsic call together with parameters and create a proposal like 'democracy' does.

Current implementation reintroduces such approach with full control over the code.

Not fully understand about WASM. The code can be compiled with no_std and works in runtime.

2. Text proposal

For now, it is no more than the model of the actual proposals.
Do we have exact requirements for it?

From your comments:

  • add another 'text' parameter
  • store the text of the proposal in the codex storage

3. Actors and accounts

I can introduce a separate entity not connected with account_id, but we still need an account_id to place a stake. Current stakes module depends on Currency which is bound to the AccountId. And what should we do when account_id changes when we have an ongoing proposal?

4. Codex and engine crates

Not sure I understood you properly:

  • engine and codex are in separate crates
  • engine crate is independent (only substrate dependencies to the moment)
  • codex meant to be dependent on joystream crates
  • dependency path can be relative or git-based or any other
  • for now, I assume the 'path variant'

- introduce ProposalId type
- change BTreeSet to the linked_map
- change VoteExistsByProposalByAccount to proposal_id first key
- clear cache on proposal finalization
- rename and refactor tally() method in functional style
- introduce internal type FinalizedProposalData
@shamil-gadelshin
Copy link
Contributor Author

On account change during active proposal:
#154

@shamil-gadelshin
Copy link
Contributor Author

I will implement max active proposals as a new feature during the current iteration.

@shamil-gadelshin
Copy link
Contributor Author

On 'voter' and 'proposer': for now, I added associated types ProposerId and VoterId and removed account_id dependency. The exact relation between ProposerId and ProposerOrigin (VoterId and VoterOrigin) I will elaborate after Rome - when I connect council and membership modules to the codex.

Copy link
Member

@bedeho bedeho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I see that you opt to have mutable variables in a few places. I think we should try to minimize this.

  2. Something struck me as I was reviewing this about how we would do slashing: I recall we agreed that there should be a separate quorum and threshold for this action. If this is the case, then we must wait the full voting period before trying to decide whether to accept or slash a proposal, otherwise the engine is sensitive to the accidental order in which people may choose to vote. Please check my logic here.

pub tally_results: Option<TallyResult<BlockNumber>>,

/// Votes for the proposal
pub votes: Vec<Vote<VoterId>>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. This is OK, but its starts to become a performance issue if the engine is to be used with a large number of voters, as you will have to load/write back all current votes each time anyone votes. I did not mean for this field to be lifted out of storage, but in practice I think it will be OK, at least for us.

  2. Make this a BTreeMap, using the VoterId as key, then we get greater semantic clarity, and runtime guarantees of no double voting, and checks for past voting in O(nlogn) time, rather than O(n).

  3. Drop VoterId property from Vote, it is redundant, and opens up room for bugs, where a vote has different id value than key that maps to it.

--

Updated

Above I assumed that votes had replaced VoteExistsByProposalByVoter, which actually was not needed, but I see now that it has not. Now it is very unclear to me what the purpose is? it seems related to the computation in update_tally_results, which also appears needlessly complicated. I suspect I am missing something, so let me outline what I would have thought was the obvious approach.

  1. Proposal has fields for counting abstentions, approvals and rejections. This is fine, because it is always well defined to have these in life cycle of a proposal. Initial values are set to 0.

  2. Whenever a vote is submitted, increment the relevant counter. If quorum is reached, then we can update the state suitably.

  3. In on_finalized check all active proposals for whether they may have expired in this block, in which case, update the state suitablly

Is this not sufficient?

pub status: ProposalStatus,

/// Tally result for the proposal
pub tally_results: Option<TallyResult<BlockNumber>>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this an optional?

For all states of a proposal, it is well defined to have cumulative counter values set, this type choice gives the impression that there is some set of states

Even the TallyResult type seems to have little value at this point.

Migrating from TallyResults and vote calculation in the end of block to vote calculation on the vote() extrinsic call.
Migrating out from TallyResults
- refactor map-filter-map pattern to the filter_map
- add comments
Copy link
Member

@bedeho bedeho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@bedeho bedeho merged commit 6b447b6 into Joystream:proposals_v2 Feb 17, 2020
mnaamani pushed a commit to mnaamani/joystream that referenced this pull request Apr 16, 2020
@shamil-gadelshin shamil-gadelshin deleted the proposals_v2_iteration2_review branch June 25, 2020 14:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants