Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Evaluator reputation update #158

Merged
merged 21 commits into from Feb 19, 2018
Merged

Evaluator reputation update #158

merged 21 commits into from Feb 19, 2018

Conversation

lazovicff
Copy link
Contributor

@lazovicff lazovicff commented Feb 15, 2018

Implements evaluator reputation update part for #38

  • Setting rating of the evaluator when reputation is calculated.
  • Updating reputation for every role using loop.
  • Introduced payout for evaluator and updated tests accordingly.
  • Split setTaskPayout to 3 functions, each for every role. Reviews are needed for setTaskEvaluatorPayout and setTaskWorkerPayout.
  • setTaskManagerPayout can be only called by a manager of the task.
  • Updated gas costs.

@elenadimitrova elenadimitrova self-assigned this Feb 15, 2018
tasks[_id].roles[_role] = Role({
user: _user,
rated: false,
rating: 0
rating: initialRating
Copy link
Contributor

Choose a reason for hiding this comment

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

I know this looks 'clean' when used in the context with other role ratings but it will cost ~20,000 gas. Scaling the implementation is one of our biggest concerns so we get twitchy when it comes to gas costs.
It will still be good design if you extracted role.rating into a local memory variable (which costs little) when you're doing calculations and selectively assign it to 50 there.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, initially it was done just before calculating the reputation.

I don't know exactly how objections will work, but the reason i decided to do it this way is because maybe we would want to allow objections to the evaluator rating to be made before actual calculation of the reputation.

Copy link
Contributor

Choose a reason for hiding this comment

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

You're right, objections will be done before reputation calculation but the evaluator rating won't be needed there still.

// TODO Reputation changes for other relevant roles, domains.

updateReputation(_id, EVALUATOR, skillId);
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see the benefit of calling another function 3 times from here. This incurs some unnecessary extra reads from storage. We can refactor out the internal function in cases where the logic lies in multiple functions but here it's all within finalizeTask. Plus with the suggestion from above of balancing gas costs and design you best keep it all in this function.

Copy link
Contributor

Choose a reason for hiding this comment

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

A small note here to switch the order in which appendReputationUpdateLog is called to match the order of role ids, i.e. manager (roleId = 0), evaluator (roleId = 1), worker (roleId = 2). Just so when getting the respective reputation log entries, it's more intuitive.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was getting the 'stack too deep' error as i mentioned in description, because of too much local variables (16 is max i think).

I will try to bring back everything into finalizeTask, but i will probably remove some local variables like this one or this one and access them directly here.
What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

I had problems when I tried to do that if I remember correctly. But otherwise yes, try cutting down some of the local variables.

Copy link
Contributor

Choose a reason for hiding this comment

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

skillId does not need to be explicit as well.

txData = await colony.contract.setTaskPayout.getData(taskId, EVALUATOR_ROLE, tokenAddress, evaluatorPayout.toString());
await colony.proposeTaskChange(txData, 0, MANAGER_ROLE);
transactionId = await colony.getTransactionCount.call();
await colony.approveTaskChange(transactionId, WORKER_ROLE, { from: worker });
Copy link
Contributor

Choose a reason for hiding this comment

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

Note that setTaskPayout transaction reviewers are currently the task Manager and Worker. However when setting the Evaluator the reviewers logically have to be the Manager and Evaluator. With the current ColonyTransactionReviewer design this is not possible. So we have to either:
a) Split the setTaskPayout in two functions, e.g. setTaskWorkerPayout and setTaskEvaluatorPayout. The disadvantage here is that for additional roles we may want to support in future, i.e. in addition to manager, evaluator and worker, we'll have to keep introducing new functions so we lose 1 level of abstraction.

b) We refactor the ColonyTransactionReviewer to support this model.

I haven't explored option b) so feel free to experiment. Overall I'd prefer option a) for simplicity but I want to hear what @area thinks about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For now i created separate functions for every role. I will try to find better solution after this PR is merged, because these changes are required for #154.

@elenadimitrova
Copy link
Contributor

@lazoviccorp This works for the taskFinalize logic I think

    Task storage task = tasks[_id];
    IColonyNetwork colonyNetworkContract = IColonyNetwork(colonyNetworkAddress);

    for (uint8 roleId = 0; roleId <= 2; roleId ++) {
      uint payout = task.payouts[roleId][token];
      Role storage role = task.roles[roleId];
      uint8 rating = (roleId == EVALUATOR) ? 50 : role.rating;
      int divider = (roleId == WORKER) ? 30 : 50;
      int reputation = SafeMath.mulInt(int(payout), (int(rating)*2 - 50)) / divider;
      //TODO: Change the skillId to represent the task domain
      colonyNetworkContract.appendReputationUpdateLog(role.user, reputation, task.skills[0]);
    }

    task.finalized = true;

Note that this doesn't implement the todo fix

@@ -48,7 +48,9 @@ contract Colony is ColonyStorage {
// Initialise the task update reviewers
IColony(this).setFunctionReviewers(0xda4db249, 0, 2); // setTaskBrief => manager, worker
IColony(this).setFunctionReviewers(0xcae960fe, 0, 2); // setTaskDueDate => manager, worker
IColony(this).setFunctionReviewers(0xbe2320af, 0, 2); // setTaskPayout => manager, worker
IColony(this).setFunctionReviewers(0x6aaf4a77, 0, 2); // setTaskManagerPayout => manager, worker
Copy link
Contributor

Choose a reason for hiding this comment

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

It doesn't make sense to get the worker to agree to what the manager payout should be. Just don't permission the setTaskManagerPayout function for now.

@elenadimitrova elenadimitrova merged commit 0f2bd75 into JoinColony:develop Feb 19, 2018
@elenadimitrova elenadimitrova mentioned this pull request Apr 5, 2018
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.

None yet

2 participants