Giter Club home page Giter Club logo

aragon-court's Introduction

Aragon Client

Build Status All Contributors

πŸŒŽπŸš€ Trusted by over 1500 organizations, securing more than $300MM in funds. Try it out.

Quick start

Install with yarn and launch the app with yarn start. By default, the app is configured to connect to the Ethereum Goerli testnet.

For connecting to other chains / deployments, a few useful npm scripts are provided:

  • Ethereum Mainnet: yarn start:mainnet will launch the app, configured to connect to the Ethereum mainnet
  • Local development: yarn start:local will launch the app, configured to connect to our aragen local development environment. It will also use the local IPFS daemon, if it detects one exists. If you're using the aragonCLI, you'll want to run this to connect to its local chain.

Note: Windows users may need to install the windows-build-tools before installing this project's dependencies.

More configuration options are available, and depending on your needs, you may find the frontend development setup guide helpful.

Releases

The Aragon client is automatically deployed to IPFS with each new commit to master, via Fleek. The latest builds are available at client.aragon.org or through an IPFS gateway, like ipfs.io/ipns/client.aragon.org.

aragonPM

"Checkpointed" releases, tagged in our releases page, are published on-chain onto the aragon.aragonpm.eth aragonPM repository for all supported Ethereum environments (mainnet and Goerli testnet).

For a long time (2018-2020), these releases were our primary "official" builds. With Fleek, however, we now relegate these on-chain deployments as historical backups in case a user wants to use an older version.

Secrets

A number of environment secrets are required during publishing and these are sometimes different per network.

You may either specify these secrets as environment variables or use a .env.

Contributing

πŸ‘‹ Get started contributing with a good first issue.

πŸŽ“ You may be interested in the Aragon client architecture guide if you're not familiar with how the project is set up.

Don't be shy to contribute even the smallest tweak. 🐲 There are still some dragons to be aware of, but we'll be here to help you get started!

For other details about contributing to Aragon, more information is available in the contributing guide.

Issues

If you come across an issue with Aragon, do a search in the Issues tab of this repo and the Aragon Apps Issues to make sure it hasn't been reported before. Follow these steps to help us prevent duplicate issues and unnecessary notifications going to the many people watching this repo:

  • If the issue you found has been reported and is still open, and the details match your issue, give a "thumbs up" to the relevant posts in the issue thread to signal that you have the same issue. No further action is required on your part.
  • If the issue you found has been reported and is still open, but the issue is missing some details, you can add a comment to the issue thread describing the additional details.
  • If the issue you found has been reported but has been closed, you can comment on the closed issue thread and ask to have the issue reopened because you are still experiencing the issue. Alternatively, you can open a new issue, reference the closed issue by number or link, and state that you are still experiencing the issue. Provide any additional details in your post so we can better understand the issue and how to fix it.

Contributors

Thanks goes to these wonderful people (emoji key):


Pierre Bertet

πŸ’»

Brett Sun

πŸ’»

Gorka Ludlow

πŸ’»

Jorge Izquierdo

πŸ’»

Luis IvΓ‘n Cuende

πŸ’» 🎨 πŸ€”

Oliver

πŸ’»

ßingen

πŸ’»

Daniel Norman

πŸ’»

John Light

πŸ“– πŸ›

Tatu

πŸ“–

Patricia Davila

🎨 πŸ““

Jouni Helminen

🎨 πŸ““

Luke Duncan

πŸ€”

Daniel Constantin

πŸ’»

RJ Ewing

πŸ’»

Paul Henschel

πŸ’»

Rodrigo Perez

πŸ’»

gasolin

πŸ’»

Adam Soltys

πŸ’»

Arun Kumar

πŸ’»

Beer van der Drift

πŸ’»

Daniel Caballero

πŸ’»

Deam

πŸ’»

Ilia Smirnov

πŸ“– πŸ”§

julsar

πŸ“–

Pascal Precht

πŸ”§

Rudy Godoy

πŸ“–

Yalda Mousavinia

πŸ’»

decodedbrain

πŸ’»

jvluso

πŸ’»

mark g romano

πŸ’»

mul53

πŸ’»

Jon

πŸ’»

Abhinav Sagar

🚧

geleeroyale

πŸ“–

Otto G

πŸ’»

Adam Boro

πŸ’»

Emilio Silva Schlenker

πŸ’»

Olivier Sarrouy

πŸ’»

delfipolito

πŸ’»

Enrique Ortiz

πŸ’»

Fabrizio Vigevani

πŸ’»

Mathew Cormier

πŸ’»

Mick de Graaf

πŸ’Ό

iwaduarte

πŸ’»

EC Wireless

πŸ’»

owisixseven

🎨

Andy Hook

πŸ’»

This project follows the all-contributors specification. Contributions of any kind welcome!

Re-usable foundations

Amongst other dependencies, the Aragon client is built upon these packages that you may also find useful for your projects:

  • aragonUI: React component library used to build user interfaces within the Aragon design system
  • token-amount: utility class for encapsulating and formatting a token amount
  • use-inside: React utility that allows a component to be aware of being "inside" the subtree of another component
  • use-token: React utility for fetching information related to tokens on Ethereum
  • use-viewport: React utility providing the current window size and convenient functions for responsive apps
  • use-wallet: React utility aiming to make the integration between your dapp and your users' web3 wallets as straightforward as possible
  • web3-react: a simple, maximally extensible React framework for supporting arbitrary web3 wallets

aragon-court's People

Contributors

facuspagnuolo avatar izqui avatar macor161 avatar sohkai avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aragon-court's Issues

Court: Add term limits to config changes

  • Enforce that config changes need to be scheduled at least a certain number of terms in advance. This limit (MIN_SCHEDULE_CONFIG_CHANGE_TERMS) should be a constant in the Court and needs to be higher or equal to the number of terms that a dispute (or appeal round) can be scheduled in advance.

  • At the moment when changing the config, if there was already a scheduled config change, it is overridden by the new incoming config. This can be problematic if the term in which the config was scheduled to change is close enough to the current term that there can be disputes or appeal rounds initiated with the fee schedule of a future config which can be cancelled by scheduling a new config change. Config changes shouldn't be possible if there is a pending config change scheduled to happen in less than MIN_SCHEDULE_CONFIG_CHANGE_TERMS

Court: Slash jurors voting for the losing outcome in final rounds

Look here:
https://github.com/aragon/aragon-court/blob/split_staking_3/contracts/Court.sol#L646
and here:
https://github.com/aragon/aragon-court/blob/split_staking_3/contracts/Court.sol#L656
Let's say that jurorMinStake = 10, that FINAL_ROUND_WEIGHT_PRECISION = 1000, that juror stake was 9 and penalytPct is 10%.
Then first line will give: weight = 1000*9/10 = 900.
Weight will be >0, so it will get into the 2nd one, which will give:
weightedPenalty = 10*10/100 * 900 / 1000 = 1 * 900 / 1000 = 0 (due to Solidity rounding).
So it will be able to vote but it won't be slashed at all.

Registry: Analyze removing jurors grouping when drafting

See #73 for reference:

"We may consider not grouping at all on CourtStaking.draft function, avoiding the use of weights there. Depending on the nature of data it may be better: if jurors are often repeated, size of arrays passed through contracts would be smaller, but if they are not, we would save weights array and simplify logic on one side (as right now we are checking duplicates twice, in different ways)"

Tree: Write full-coverage unit tests

Please follow the convention used for the JurorsRegistry tests, some of them are:

  • Avoid mocking unnecessarily, only when there is no other option
  • Use test-helpers module provided by @aragon
  • Implement reusable helpers stuff instead of custom non-exported functions
  • Use let scoped variables instead of properties to define test variables

Registry: Allow for partial activation and deactivation

Right now, when jurors activate and deactivate, all their stake goes in to and out of the tree.
The idea is that if jurors earn tokens from their work, they may want to withdraw some not to be drafted so often (as work time is limited) or just to cash out.
Currently they can do that by deactivating, partially withdrawing and then activating again, but it's definitely not user friendly and they could miss the chance of being drafted for some terms during this process.

Court: Expose external config setter

Currently it is just an internal function used to set the initial configuration, but the governor should be able to change the config.

There should be a threshold of terms during which no config changes are allowed, if there is an incoming configuration change happening within the threshold, a configuration change overriding it should not be allowed either.

The logic for changing the config after setting it for the first time should also be reviewed, as I believe that both

require(configChangeTerm > term || term == ZERO_TERM, ERROR_PAST_TERM_FEE_CHANGE);
and
terms[configChangeTerm].courtConfigId = courtConfigId;
should use _fromTermId instead of configChangeTermId

Court: Implement final appeal

After the maximum number of appeals has been reached, if a new appeal is created, the final ruling by the Court should be decided with a stake-weighted vote of all active jurors.

Subscriptions: Remove governance fee share for incentivized calls

Some maintenance function calls like heartbeat, draftAdjudicationRound or settleRoundSlashing can reward the sender with a fee for executing them to ensure that the Court state is kept up to date.

At the moment, like all other fees, the governor of the contract gets a share of these fees when they are paid. Removing the governance cut from these will allow us to make these cheaper and remove some extra storage costs when awarding the fee.

Contracts: Write inline documentation

Add proper documentation for all the contracts of the court:

  • Interface documentation (function, parameters, return values)
  • Radspec description when needed
  • Clarify non-trivial logic

Contracts that MUST be documented

  • Main Court contract (#103)
  • Jurors registry (#72)
  • CR Voting (#96)
  • HexSumTree (#104)
  • Checkpointing (#104)
  • Accounting (#67)
  • Subscriptions (#135)

Chore: Run unit tests against a geth node

We should have scripts to run the test suite against a geth node as well.
Explore if we should do this only for certain scenarios in the CI to avoid waiting a lot to merge PRs.

Explore ways to split Court into multiple contracts

For simplicity, the Court implementation has been done in just one contract as the state of the contract is quite interdependent between most parts of the mechanism. An idea for separating concerns would be to split the general court state from the dispute management and adjudication.

We are still well below the block gas limit (at the moment ~5.5m gas), but as we keep implementing new functionality, we will start approaching the limit.

Agreements: Manage staking locks

Agreement should implement the generic management of stake locks:

  • On the constructor or initialize, pass the lock requirements for both parties in the dispute.
  • A new commit(...) function that ensures the sender has a valid lock and exposes the sender to potential challenges during a period of time.
  • A new challenge(...) function that will ensure the sender has a valid lock and creates a dispute in the Court.
  • On rule(...): if the Court issues a valid ruling (not Missing or RefuseRuling), it should perform a transfer from the lock of the losing party to the lock of the winning party, and mark both locks as unlocked (so Agreement will return true to canUnlock). We should consider allowing for contracts inheriting from Agreement to specify a different distribution for locks depending on the ruling, for example in case of a proposal agreement, if the court rules in favor of the proposer, a part of the challenger's deposit could be sent to the DAO (as everyone in the DAO suffered from deferring the vote).

Chore: npm run test - Error: Exceeds block gas limit

Added to scripts:

  "scripts": {
    "test": "TRUFFLE_TEST=true npm run ganache-cli:test",
    "analysis:tree": "TRUFFLE_TEST=true SUMTREE_GAS_ANALYSIS=true npm run ganache-cli:test",
    "ganache-cli:test": "./node_modules/@aragon/test-helpers/ganache-cli.sh",
    "version": "./node_modules/ganache-cli/cli.js --version"
  },
npm run version

> @aragon/[email protected] version /Users/ms/Code/aragon-court
> ./node_modules/ganache-cli/cli.js --version

Ganache CLI v6.4.3 (ganache-core: 2.5.5)

When trying to run tests getting:

Error: Exceeds block gas limit
    at Object.InvalidResponse (/Users/ms/Code/aragon-court/node_modules/truffle/build/webpack:/~/web3/lib/web3/errors.js:38:1)
    at /Users/ms/Code/aragon-court/node_modules/truffle/build/webpack:/~/web3/lib/web3/requestmanager.js:86:1
    at /Users/ms/Code/aragon-court/node_modules/truffle/build/webpack:/packages/truffle-migrate/index.js:225:1
    at /Users/ms/Code/aragon-court/node_modules/truffle/build/webpack:/packages/truffle-provider/wrapper.js:134:1
    at XMLHttpRequest.request.onreadystatechange (/Users/ms/Code/aragon-court/node_modules/truffle/build/webpack:/~/web3/lib/web3/httpprovider.js:128:1)
    at XMLHttpRequestEventTarget.dispatchEvent (/Users/ms/Code/aragon-court/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:64:1)
    at XMLHttpRequest._setReadyState (/Users/ms/Code/aragon-court/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:354:1)
    at XMLHttpRequest._onHttpResponseEnd (/Users/ms/Code/aragon-court/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:509:1)
    at IncomingMessage.<anonymous> (/Users/ms/Code/aragon-court/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:469:1)
    at IncomingMessage.emit (events.js:194:15)
    at endReadableNT (_stream_readable.js:1125:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)

Contracts: Stack too deep issues

Fix stack too deep issues in Court contract:

  • draftAdjudicationRound
  • settleRoundSlashing

Once it's fixed, optimize SSTORE and SLOAD use.

See comments here and here for more context.

Chore: Some errors when installing dependencies? (potentially Python issue)

I would like to npm install and run the thing.

Recently installed Python 3 because I had to run some other stuff.

Worried it is breaking now.

Before I start messing with it again (undoing) can you verify if this is Python issue or something else?

Maybe you have experience how to troubleshoot?

usr/local/opt/python/libexec/bin/python
Python 3.7.3 (default, Mar 27 2019, 09:23:15)

2nd run

$ npm install

> [email protected] preinstall /Users/ms/Code/aragon-court/node_modules/scrypt
> node node-scrypt-preinstall.js


> [email protected] install /Users/ms/Code/aragon-court/node_modules/scrypt
> node-gyp rebuild

gyp ERR! configure error
gyp ERR! stack Error: Command failed: /usr/local/opt/python/libexec/bin/python -c import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack   File "<string>", line 1
gyp ERR! stack     import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack                                ^
gyp ERR! stack SyntaxError: invalid syntax
gyp ERR! stack
gyp ERR! stack     at ChildProcess.exithandler (child_process.js:294:12)
gyp ERR! stack     at ChildProcess.emit (events.js:189:13)
gyp ERR! stack     at maybeClose (internal/child_process.js:970:16)
gyp ERR! stack     at Socket.stream.socket.on (internal/child_process.js:389:11)
gyp ERR! stack     at Socket.emit (events.js:189:13)
gyp ERR! stack     at Pipe._handle.close (net.js:597:12)
gyp ERR! System Darwin 18.5.0
gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/ms/Code/aragon-court/node_modules/scrypt
gyp ERR! node -v v10.15.3
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok
npm WARN @aragon/[email protected] requires a peer of solidity-coverage@^0.5.11 but none is installed. You must install peer dependencies yourself.
npm WARN @aragon/[email protected] No repository field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules/scrypt):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] install: `node-gyp rebuild`
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: Exit status 1

audited 8757 packages in 8.037s
found 0 vulnerabilities

1st run

$ git clone https://github.com/aragon/aragon-court.git
Cloning into 'aragon-court'...
remote: Enumerating objects: 54, done.
remote: Counting objects: 100% (54/54), done.
remote: Compressing objects: 100% (28/28), done.
remote: Total 456 (delta 30), reused 40 (delta 26), pack-reused 402
Receiving objects: 100% (456/456), 138.22 KiB | 68.00 KiB/s, done.
Resolving deltas: 100% (275/275), done.

$ cd aragon-court/

$ npm install

> [email protected] preinstall /Users/ms/Code/aragon-court/node_modules/scrypt
> node node-scrypt-preinstall.js


> [email protected] install /Users/ms/Code/aragon-court/node_modules/keccak
> npm run rebuild || echo "Keccak bindings compilation fail. Pure JS implementation will be used."


> [email protected] rebuild /Users/ms/Code/aragon-court/node_modules/keccak
> node-gyp rebuild

gyp ERR! configure error
gyp ERR! stack Error: Command failed: /usr/local/opt/python/libexec/bin/python -c import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack   File "<string>", line 1
gyp ERR! stack     import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack                                ^
gyp ERR! stack SyntaxError: invalid syntax
gyp ERR! stack
gyp ERR! stack     at ChildProcess.exithandler (child_process.js:294:12)
gyp ERR! stack     at ChildProcess.emit (events.js:189:13)
gyp ERR! stack     at maybeClose (internal/child_process.js:970:16)
gyp ERR! stack     at Socket.stream.socket.on (internal/child_process.js:389:11)
gyp ERR! stack     at Socket.emit (events.js:189:13)
gyp ERR! stack     at Pipe._handle.close (net.js:597:12)
gyp ERR! System Darwin 18.5.0
gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/ms/Code/aragon-court/node_modules/keccak
gyp ERR! node -v v10.15.3
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] rebuild: `node-gyp rebuild`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] rebuild script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to install?

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/ms/.npm/_logs/2019-05-06T12_06_23_585Z-debug.log
Keccak bindings compilation fail. Pure JS implementation will be used.

> [email protected] install /Users/ms/Code/aragon-court/node_modules/scrypt
> node-gyp rebuild

gyp ERR! configure error
gyp ERR! stack Error: Command failed: /usr/local/opt/python/libexec/bin/python -c import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack   File "<string>", line 1
gyp ERR! stack     import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack                                ^
gyp ERR! stack SyntaxError: invalid syntax
gyp ERR! stack
gyp ERR! stack     at ChildProcess.exithandler (child_process.js:294:12)
gyp ERR! stack     at ChildProcess.emit (events.js:189:13)
gyp ERR! stack     at maybeClose (internal/child_process.js:970:16)
gyp ERR! stack     at Socket.stream.socket.on (internal/child_process.js:389:11)
gyp ERR! stack     at Socket.emit (events.js:189:13)
gyp ERR! stack     at Pipe._handle.close (net.js:597:12)
gyp ERR! System Darwin 18.5.0
gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/ms/Code/aragon-court/node_modules/scrypt
gyp ERR! node -v v10.15.3
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok

> [email protected] install /Users/ms/Code/aragon-court/node_modules/secp256k1
> npm run rebuild || echo "Secp256k1 bindings compilation fail. Pure JS implementation will be used."


> [email protected] rebuild /Users/ms/Code/aragon-court/node_modules/secp256k1
> node-gyp rebuild

gyp ERR! configure error
gyp ERR! stack Error: Command failed: /usr/local/opt/python/libexec/bin/python -c import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack   File "<string>", line 1
gyp ERR! stack     import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack                                ^
gyp ERR! stack SyntaxError: invalid syntax
gyp ERR! stack
gyp ERR! stack     at ChildProcess.exithandler (child_process.js:294:12)
gyp ERR! stack     at ChildProcess.emit (events.js:189:13)
gyp ERR! stack     at maybeClose (internal/child_process.js:970:16)
gyp ERR! stack     at Socket.stream.socket.on (internal/child_process.js:389:11)
gyp ERR! stack     at Socket.emit (events.js:189:13)
gyp ERR! stack     at Pipe._handle.close (net.js:597:12)
gyp ERR! System Darwin 18.5.0
gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/ms/Code/aragon-court/node_modules/secp256k1
gyp ERR! node -v v10.15.3
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] rebuild: `node-gyp rebuild`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] rebuild script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm WARN Local package.json exists, but node_modules missing, did you mean to install?

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/ms/.npm/_logs/2019-05-06T12_06_24_443Z-debug.log
Secp256k1 bindings compilation fail. Pure JS implementation will be used.
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN @aragon/[email protected] requires a peer of solidity-coverage@^0.5.11 but none is installed. You must install peer dependencies yourself.
npm WARN @aragon/[email protected] No repository field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules/scrypt):
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] install: `node-gyp rebuild`
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: Exit status 1

added 487 packages from 600 contributors and audited 8757 packages in 119.19s
found 0 vulnerabilities

Court: Add checks to ensure dispute and round exist

In most functions we are doing:

        Dispute storage dispute = disputes[_disputeId];

Since this is a mapping, should we check that the dispute actually exists? (Downside being adding more code, of course)

The same for:

        AdjudicationRound storage round = dispute.rounds[_roundId];

In a lot of them we are then doing too:

        AdjudicationRound storage round = dispute.rounds[dispute.rounds.length - 1];

Which would fail because rounds length is zero, but it would be nice to have a proper error message.

Consider checkpointing HexSumTree every term

Currently the HexSumTree is a singleton-type object which we only modify in the heartbeat() function so the state of the tree stays constant during the term allowing deterministic juror drafts throughout the term. This comes with the following drawbacks:

  • Because all modifications to the tree are batched for the heartbeat() of a future term, we need to limit how many mutations can be performed in a given term to avoid heartbeat() to require more gas than the block gas limit and bricking the court.

  • Disputes need to draft their jurors strictly during the correct term because the juror sum tree can mutate in the transition to the next term. If the jurors of a dispute aren't drafted during the term, the dispute needs to be rescheduled for a future term.

By checkpointing the state of the tree every term we would be able to:

  • Immediately perform tree modifications for the next term, no longer scheduling modifications to a future term's heartbeat().

  • Draft jurors for a dispute at any term in the future, as the drafting function would be able to perform sortition on a past state of the tree.

  • Being able to prove to a contract how many tokens a juror had active and for how long, which would be really useful for distributing passive rewards (as discussed in #9)

Downsides:

  • Gas cost:

    • I am particularly worried about the added SLOAD cost while traversing the tree performing a sortition, as for every node in the tree we'd need to get its checkpointed value (even though it is a binary search, it would increase the number SLOADs by at least a factor of 2 and grows logarithmically with the number of balance updates of a juror has had).

    • The SSTORE cost for modifying tree entries wouldn't be that different for trees of a reasonable size specially taking into account that the Court would no longer have to manage queues in storage. The SSTORE overhead would be an extra ~20k * log16(N) (N being the number of jurors) in the worst case (the first update for the next term), which would add up to an extra ~100k gas for a tree of ~1.04M (16 ^ 5) jurors. A positive side-effect is that this gas would be paid by the juror directly in almost all instances.

  • Removing the requirement to draft an adjudication round during an specific term, presents some challenges of its own with the current design:

    • Deferred juror unstaking: because at the time drafting can only happen during one specific term and adjudication rounds that fail to draft on time need to be rescheduled, the moment a juror is deactivated we know exactly how many tokens they have at stake (and we can allow them to withdraw all their tokens that aren't at risk of being slashed). If an adjudication round no longer needs to be drafted during an specific term, we'd need to prevent the juror from unstaking for at least the duration of a full adjudication round (commit + reveal + appeal) which is a reasonable time span for cancelling/rescheduling the round if the draft didn't happen.

    • Higher risk of missing block hashes: the block hash used as a randomness seed for a term needs to be queried and saved within 257 blocks after the term is transitioned. If a round no longer needs to be drafted within the term, we may need to add an extra incentive to perform a secondary hearbeat() to store the randomness seed for all terms with adjudication rounds.

  • Scheduling: at the moment, jurors can schedule their activation and deactivation to a custom term. This is a nice side-effect of not being able to perform activations immediately, as we don't care whether a modification happens in the next term because it needs to be scheduled anyway. If we were to add checkpointing, we'd likely remove the ability to schedule activations and deactivations.

Court: Increase economic security in appeals

As explained in 3rd open issue here:

At the moment, all jurors selected for adjudicating a dispute can have the same maximum penalty in case that they vote for a losing ruling. This results in the fact that the security of disputes grows linearly with the number of jurors that can be drafted in the multiple adjudication rounds. And in the current implementation there is a limit (due to gas) to how many jurors can be drafted for to rule in a round, which is in the 100-150 juror range.

Even though the potential final appeal in which all active jurors are required to vote increases the security (at the expense of inefficiency as potentially thousands of people will need to vote), during the regular appeals rounds the maximum amount of tokens at stake will be just two orders of magnitude more than the minimum token amount for juror activation (assuming a quite unlikely 100% penalization ratio), which will likely not be much.

It’d be positive to increase the juror stakes as the appeal rounds advance. A couple of options for doing this:

  • Increase the penalty ratio over time: because we would be using the same minimum activation tokens as the base for the penalty, this wouldn’t be a big change (maybe an order of magnitude compared to the early rounds).
  • Increase the minimum token amount required to be drafted on certain rounds: this would allow us to introduce a steeper increase in penalties, while at the same time allowing jurors with less tokens to participate in the earlier rounds. A way to implement this could be to split the sortition tree into multiple sub-trees that ensure that their nodes are within certain ranges, and when performing sortition it would only do it in a subset of sub-trees depending on the minimum individual node value required.

Court: Improve court settings change flow

Currently, the Court settings are updated simply for a given term id. This allows some weird scenarios such as:

  • Changing the court settings during a dispute (different rounds could use different settings)
  • Having fees and term settings together, it may be interesting if it could help to have different flows to update each of them
  • Jurors will have to face different periods for each case if their corresponding settings get updated.

Explore how to reward all active jurors in a given term

A couple of interesting mechanisms (like having a participation rate target) to incentivize juror participation would require having a way to reward all the jurors that were active at a given term. Some options:

  • Checkpointing the sum tree, to allow historical queries for its state at any term. This would also remove the need of rescheduling disputes when their draft transaction doesn't occur during the term. Checkpointing would make tree transitions even more expensive to maintain gas-wise.

  • Using EVM Storage Proofs: would require performing an account proof of the Court at least every term (at the same block number that we request the randomness for). It would break when multiple term transitions occur in the same block (as the storage proofs can only look at the storage of a contract after all transactions in a block have been processed).

An immediate first step would be to save the total number of tokens that are active for a term in the term state, and then figure out a way for distributing rewards proportionally among jurors.

Contracts: Use SafeMath for balance updates

Decouple HexSumTree gas analysis from tests

Currently running test/hex-tree.js takes a lot of time given that we are adding a lot of entries to the tree to test the gas usage.

We should be doing this in a separate script and not in theΒ unit tests.

Court: Implement appeal collaterals

For an appeal to occur, both parties of the appeal must offer collateral. If the current ruling for a dispute was X and one of the parties adds collateral in favor of another ruling Y but the other party does not back X with collateral, the final ruling will be Y. If both parties back their appeal with collateral, a new dispute round gets created.

Court: Implement more getters to fetch state

Right now most of the Court's state can be reconstructed checking the logs of the contract, but we should provide some getters (external views) that allow for quickly fetching the state of a dispute, adjudication round and juror accounts.

Court: Write full-coverage unit tests

Please follow the convention used for the JurorsRegistry tests, some of them are:

  • Avoid mocking unnecessarily, only when there is no other option
  • Use test-helpers module provided by @aragon
  • Implement reusable helpers stuff instead of custom non-exported functions
  • Use let scoped variables instead of properties to define test variables

Prevent drafts happening without a randomness seed

Right now, if the first draft of a term happens more than 256 blocks after the term starts, the blockhash that will be returned for the randomnessBN of the term will be 0.

Options to work around this problem:

  • Treat this as a round being drafted in the wrong term and require rescheduling as in #14
  • Implement a secondary heartbeat() function (which can be called one block after the actual heartbeat) that stores the randomness for the term. The caller could get the current dependingDrafts * heartbeatFee that is being paid to the heartbeat() caller and pay heartbeat fees just from activation, updates and deactivation fees (#7)

Voting: Write full-coverage unit tests

Please follow the convention used for the JurorsRegistry tests, some of them are:

  • Avoid mocking unnecessarily, only when there is no other option
  • Use test-helpers module provided by @aragon
  • Implement reusable helpers stuff instead of custom non-exported functions
  • Use let scoped variables instead of properties to define test variables

Reschedule adjudication rounds if the draft term was missed

At the moment, and unless something like #11 is implemented, an adjudication round's jurors can only be drafted during a specific term that was known in advance.

Even though there is an economic incentive for executing the draft, it could fail to be drafted on time. In this case the round should be rescheduled to be drafted at a later term (could be as soon as term + 1 when the reschedule function is called)

We could consider requiring the caller to pay another heartbeat fee for the term it is rescheduled to, this fee could also be extracted from the draft fee.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.