proftomwbell / Ulex

For version control of Ulex, the open source legal system
Other
79 stars 16 forks source link

Draft Ethereum contract for Ulex procedural rules #23

Open Physes opened 5 years ago

Physes commented 5 years ago

Overview

This is a basic Ethereum smart contract for managing procedural rules of Ulex cases. I'd like to see versions of the procedural rules in other platforms (e.g. EOS, Holochain, Bitcoin, etc.) also.

Every case has a bytes32 identifier which is used to look up case matter in the Ethereum state. The current iteration lacks sufficient controls for each step in the procedure and leaves it fairly open, only enforcing msg.sender checks for each party. The tiebreak method could probably be improved. Also there are no events yet (e.g. for returning case id's after initiate). Suggestions welcome.

In case matter arrays (parties and remedies mappings), index 0 pertains to the plaintiff, and index 1 pertains to the defendant. In the 'judges' mapping, index 0 is the judge chosen by the plaintiff, and index 1 is chosen by the defendant. Index 2 is the tiebreaker chosen by both judges.

Methods

The methods are written in logical order of procedure:

  1. initiate: The plaintiff invokes this method along with the given address of the defendant.
  2. propose: Each party can propose a remedy.
  3. nominate: Each party is able to nominate a judge by address.
  4. tiebreak: The judges can nominate a third judge to act as a tiebreaker.
  5. vote: Each judge can cast a vote. A true vote means plaintiff wins, false means defendant wins.
  6. decide: Calculates the winning remedy based on votes. If vote a and vote b are unanimous, the remedy is decided automatically. If they differ, then vote c is used to decide the outcome of the case. This essentially choses the index number of the winning party (0 or 1) and sets it to the winners mapping.
  7. outcome: A public view function which allows the public to look up the winning party's remedy.

Contract

pragma solidity ^0.4.23;

contract Ulex {

    // Maps case id to parties array. 
    // By default, Index 0 is the plaintiff, Index 1 is the defendant.
    mapping(bytes32 => address[]) private parties;

    // Maps case id to judges array.
    // Index 0 is chosen by the plaintiff, index 1  is chosen by defendant.
    mapping(bytes32 => address[]) private judges;

    // Maps case id to remedies array.
    // Index 0 is the remedy proposed by plaintiff
    // Index 1 is the remedy proposed by the defendant.
    // String can either be a statement stored in state or a link to external document.
    mapping(bytes32 => string[]) private remedies;

    // Maps case id to votes array (booleans).
    // If vote is true, plaintiff wins. If false, defendant wins.
    mapping(bytes32 => bool[]) private votes;

    // Maps case id to the index number of winning party.
    // This can be used to reveal the winning remedy.
    mapping(bytes32 => uint256) private winners;

    // Allows a plaintiff to initiate a case.
    function initiate(address _plaintiff, address _defendant) public {
        bytes memory _digest = abi.encodePacked(_plaintiff, block.timestamp);
        bytes32 _case = keccak256(_digest);

        parties[_case][0] = _plaintiff;
        parties[_case][1] = _defendant;
    }

    // Allows each party to propose a remedy to resolve the case.
    function propose(bytes32 _case, string _remedy, uint256 _index) public {
        require(parties[_case][_index] == msg.sender);
        remedies[_case][_index] = _remedy;
    }

    // Allows each party to nominate a judge.
    function nominate(bytes32 _case, address _judge, uint256 _index) public {
        require(parties[_case][_index] == msg.sender);
        require(judges[_case][_index] == address(0));
        judges[_case][_index] = _judge;
    }

    // Allows the judges to nominate a third tiebreaker. 
    function tiebreak(bytes32 _case, address _tiebreaker, uint256 _index) public {
        require(judges[_case][_index] == msg.sender);
        require(judges[_case][2] == address(0));
        judges[_case][2] = _tiebreaker;
    }

    // If true, the plaintiff wins. If false, the defendant wins.
    function vote(bytes32 _case, bool _vote, uint256 _index) public {
        require(judges[_case][_index] == msg.sender);
        votes[_case][_index] = _vote;
    }

    // Votes are added up and winning remedy is chosen.
    function decide(bytes32 _case) public {
        bool vote_a = votes[_case][0];
        bool vote_b = votes[_case][1];
        bool vote_c = votes[_case][2];

        if(vote_a == vote_b) {
            if(vote_a == true) {
                winners[_case] = 0;
            } else {
                winners[_case] = 1;
            }
        } else {
            if(vote_c == true) {
                winners[_case] = 0;
            } else {
                winners[_case] = 1;
            }
        } 
    }

    // After decision, shows the winning remedy of a given case.
    function outcome(bytes32 _case) public view returns(string) {
        uint256 _remedy = winners[_case];
        return remedies[_case][_remedy];
    }
}
proftomwbell commented 5 years ago

Excellent. What do you propose functionally speaking at this time? That I assign to you? (Pardon newbieness of query.)

gititGoro commented 5 years ago

This is exactly the type of thing I had in mind as a core skeletal contract, Philip. Tom created an Ethereum branch on Ulex. Perhaps you could write this as a starting template. I'm planning to formulate an evolving white paper for "bringing Ulex to Ethereum" on the Ethereum branch. The white paper could include this snippet as an example of what we indent for Ulex Core, the blockchain procedural component as a first step.

Physes commented 5 years ago

Thanks. Am going to make some changes and add a basic dapp frontend. Should we have different repos for different platforms? E.G. UlexEthereum, UlexTezos etc.

Physes commented 5 years ago

@proftomwbell I was going to add a mapping of case matter that would be a link to a document describing the case when it is created. What would this be called?

proftomwbell commented 5 years ago

Sounds like it could be a case abstract, if describing a case, case number if identifying litigation, or a case file, if a collection of documents.

On Tue, Sep 25, 2018 at 10:11 AM Philip Saunders notifications@github.com wrote:

@proftomwbell https://github.com/proftomwbell I was going to add a mapping of case matter that would be a link to a document describing the case when it is created. What would this be called?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/proftomwbell/Ulex/issues/23#issuecomment-424424247, or mute the thread https://github.com/notifications/unsubscribe-auth/AkogLGbWeeBqSAXIKnA6S49CyGmQSY1lks5uemPSgaJpZM4W1irE .

-- Tom W. Bell www.tomwbell.com

proftomwbell commented 5 years ago

Though it is not part of Ulex v. 1.1, in practice it will likely become customary for adjudicating fora to have the parties do sets of reveals of their proposed remedies. Something like: plaintiff files with proposed remedy1; within a set period, defendant answers with remedy 2; within a set period, plaintiff can propose remedy 3; if there was a remedy 3, within a set period, defendant can offer remedy 4; if there was a remedy 4, within a set period, plaintiff can offer remedy 5; If there was a remedy 5, within a set period, defendant can offer remedy 6.

Within a set period after the last remedy to go unanswered or remedy 6, the court issues its opinion by choosing one of the last two proposed remedies.

Again: that's not part of Ulex. It does look idea for stimulating peaceful resolution, but is a bit granular.

gititGoro commented 5 years ago

@Physes regarding the separate repos, that's not a trivial question. On the one hand, keeping technological implementation separate from the Ulex source makes sense. One could also think of them as different distros of Ulex. On the other, creating branches for Ethereum, Tezos etc at least keeps it all together. Perhaps a tree like structure via forking is the best? So we create an Ethereum fork of Ulex so that the rules and the implementation are bundled together and so that if the main trunk diverges from the Ethereum implementation, it's not a train smash since the implementation is subject to the rules in its repository rather than the parent it forked from. However, if we create separate repos or forks these have to be hosted with certain accounts. The question then becomes which accounts are appropriate? Does Tom create all sub-repos going forward?

The benefit to creating branches for each technology is that individuals can fork and submit pull requests quite naturally to the particular branch they're interested in contributing to. The downside is that the Ulex repo becomes a rainbow of branches.

@proftomwbell Warning: my legal knowledge is lacking so I might use the incorrect terms. Let me define my language first: I'll use court system when referring to the adjudication process and restatements when referring to all the other stuff. Is it likely that we'd expect many flavours of court systems being deployed, each with subtle variations around the the concept of "3 judges with remedies"? I notice that you use language like "become customary" and "good idea" as opposed to "these are the clear cut rules."

Because if that's the case, it appears the evolution of Ulex's restatements will differ from the evolution of the court system. In the court system we'd expect a core akin to the linux repository and then multiple incantations of this akin to the distributions of linux (red hat, ubuntu, arch etc). On the other hand, the restatements are independent of the court system and can be hooked into via any of the distributions of the Ulex court system. Their evolution would stem from precedents in the normal way common law evolves.

This all leads me to believe that there's a natural separation between procedure and restatement where procedure represents the mechanics and restatement represents the human (or AI) interpretation of precedent and context. Should the representation of Ulex on Github not reflect this where we have a clear separation "in the code" so to speak? Or am I simplifying a subtle relationship too much? I guess I'm constantly trying to figure out 3 things simultaneously:

  1. The legal technicalities of Ulex
  2. What the blockchain can do directly with regards to the above and indirectly via second layer tech like IPFS and incentives
  3. How to translate (1) into code to achieve (2).
Physes commented 5 years ago

Though it is not part of Ulex v. 1.1, in practice it will likely become customary for adjudicating fora to have the parties do sets of reveals of their proposed remedies. Something like: plaintiff files with proposed remedy1; within a set period, defendant answers with remedy 2; within a set period, plaintiff can propose remedy 3; if there was a remedy 3, within a set period, defendant can offer remedy 4; if there was a remedy 4, within a set period, plaintiff can offer remedy 5; If there was a remedy 5, within a set period, defendant can offer remedy 6.

Within a set period after the last remedy to go unanswered or remedy 6, the court issues its opinion by choosing one of the last two proposed remedies.

Again: that's not part of Ulex. It does look idea for stimulating peaceful resolution, but is a bit granular.

Should the remedies be secret or known during the process?

Physes commented 5 years ago

@gititGoro It might be a good idea to have a GitHub Ulex organization where you can have multiple repositories for different aspects. Although I kind of like the idea of keeping it here in one repo.

It's a good question as to whether this should be done through different repos within a Ulex Github Org or whether it should be kept in the same place, with different branches for different platforms. We'll add a directory for UIP's, and other stuff, as well as a Ulex API.

The "official" version could be an Ethereum + Git + Holochain implementation, and other devs can fork and implement it on other platforms if they wish (just like you have the canonical version of the Git source while also having other repos around with Python or Javascript implementations).

Not sure. Right now I'm working on a draft of UIP1 and going to make a pull request.

Physes commented 5 years ago

Some improvements to the procedural contract.

Added: case abstracts, getter functions, cleaned up the voting function.

I will send a pull request in the next few days with tests and deployment scripts.

pragma solidity ^0.4.23;

contract Ulex {

    // Maps case id to parties array. 
    // By default, Index 0 is the plaintiff, Index 1 is the defendant.
    mapping(bytes32 => address[]) private parties;

    // Maps case id to judges array.
    // Index 0 is chosen by the plaintiff, index 1  is chosen by defendant.
    mapping(bytes32 => address[]) private judges;

    // Maps the case id to the case abstract.
    // Stored as a string, which links to external document accessible publicly.
    mapping(bytes32 => string) private abstracts;

    // Maps case id to remedies array.
    // Index 0 is the remedy proposed by plaintiff
    // Index 1 is the remedy proposed by the defendant.
    mapping(bytes32 => string[]) private remedies;

    // Maps case id to votes array (booleans).
    // If vote is true, plaintiff wins. If false, defendant wins.
    mapping(bytes32 => bool[]) private votes;

    // Maps case id to the index number of winning party.
    // This can be used to reveal the winning remedy.
    mapping(bytes32 => uint256) private winners;

    // Emitted when case is created
    event NewCase(
        bytes32 CaseId, 
        address Plaintiff, 
        address Defendant,
        string Abstract);

    // Emitted when case is closed
    event CaseClosed(
        bytes32 CaseId,
        uint256 Winner,
        string Remedy);

    // Allows a plaintiff to initiate a case.
    function initiate(address _plaintiff, address _defendant, string _abstract) public {
        bytes memory _digest = abi.encodePacked(_plaintiff, block.timestamp);
        bytes32 _case = keccak256(_digest);

        parties[_case][0] = _plaintiff;
        parties[_case][1] = _defendant;

        abstracts[_case] = _abstract;

        emit NewCase(_case, _plaintiff, _defendant, _abstract);
    }

    // Allows each party to propose a remedy to resolve the case.
    function propose(bytes32 _case, string _remedy, uint256 _index) public {
        require(getParty(_case, _index) == msg.sender);
        remedies[_case][_index] = _remedy;
    }

    // Allows each party to nominate a judge.
    function nominate(bytes32 _case, address _judge, uint256 _index) public {
        require(getParty(_case, _index) == msg.sender);
        require(getJudge(_case, _index) == address(0));
        judges[_case][_index] = _judge;
    }

    // Allows the judges to nominate a third tiebreaker. 
    function tiebreaker(bytes32 _case, address _tiebreaker, uint256 _index) public {
        require(getJudge(_case, _index) == msg.sender);
        require(judges[_case][2] == address(0));
        judges[_case][2] = _tiebreaker;
    }

    // If true, the plaintiff wins. If false, the defendant wins.
    function vote(bytes32 _case, bool _vote, uint256 _index) public {
        require(getJudge(_case, _index) == msg.sender);
        votes[_case][_index] = _vote;
    }

    // Votes are added up and winning remedy is chosen.
    function decide(bytes32 _case) public {
        bool vote_a = getVote(_case, 0);
        bool vote_b = getVote(_case, 1);
        bool vote_c = getVote(_case, 2);

        uint256 _winner;
        string _remedy;

        if(vote_a == vote_b) {
            if(vote_a == true) {
                _winner = 0;
            } else {
                _winner = 1;
            }
        } else {
            if(vote_c == true) {
                _winner = 0;
            } else {
                _winner = 1;
            }
        }

        winners[_case] = _winner;
        _remedy = getRemedy(_case, _winner)

        emit CaseClosed(_case, _winner, _remedy);
    }

    // Getter function taking case id and index of party
    function getParty(bytes32 _case, uint256 _index) public view returns(address) {
        return parties[_case][_index];
    }

    // Getter function taking case id and index of judge
    function getJudge(bytes32 _case, uint256 _index) public view returns(address) {
        return judges[_case][_index];
    }

    // Getter function returning the case abstract
    function getAbstract(bytes32 _case) public view returns(string) {
        return abstracts[_case];
    }

    // Getter function return the remedy at index of party
    function getRemedy(bytes32 _case, uint256 _index) public view returns(string) {
        return remedies[_case][_index];
    }

    // Getter function returning the boolean vote by judges
    function getVote(bytes32 _case, uint256 _index) public view returns(bool) {
        return votes[_case][_index];
    }

    // After decision, shows the winning remedy of a given case
    function getWinner(bytes32 _case) public view returns(string) {
        return winners[_case];
    }
}
proftomwbell commented 5 years ago

Climbing back up the messages. From @gititGoro :

Does Tom create all sub-repos going forward?

I propose sharing control of this repository. Presumably that would allow others to create sub-repos.

From @gititGoro :

procedure represents the mechanics and restatement represents the human (or AI) interpretation of precedent and context. Should the representation of Ulex on Github not reflect this where we have a clear separation "in the code" so to speak?

Agreed that Ulex's procedures might evolve differently from its substantive rules, and that its representation on Github should reflect that. Maybe meta-rules (that being the third big division in the core Ulex), likewise. The form must follow function.

I guess I'm constantly trying to figure out 3 things simultaneously:

  1. The legal technicalities of Ulex
  2. What the blockchain can do directly with regards to the above and indirectly via second layer tech like IPFS and incentives
  3. How to translate (1) into code to achieve (2).

You seem to be on the right track, coding Ulex's procedural rules with callouts to parties, agents, etc. This version does not however reference any body of law. That is to say, it seems to presume that the contesting parties have already agreed that some particular version of Ulex applies.

In the real world, to generalize, litigation or arbitration begins with the plaintiff filing suit in a particular forum and the defendant being put on notice. Early on, the forum determines whether it has jurisdiction over the parties and what law applies. It usually in effect does both at once, as law is typically jurisdiction-based. But exceptions exist, as when a U.S. federal court decides a relatively minor question of state law in the course of resolving a predominantly federal case.

A more comprehensive procedural protocol might thus require inputs proving jurisdiction over each party (probably by way of reference to some separate agreement) and the applicable version of Ulex (which would by the present one by default but which the parties might by stipulation have set for a particular version).

Those two details go at the front of the process. At the backend, the output must be a decision. As written, it does not seem that the system has any coercive force. It merely acts as an oracle. That could be changed, such as by requiring the parties to post stake (invoking their prior agreement to do so). But such complications can wait.

The more pressing question: Should the adjudication output be made public? In the real world, public (i.e. political) court decisions by default are published broadly and freely. Private arbitrations by default begin and end in secret. What approach should fora running Ulex follow?

It seems likely, but remains a technical question for others to resolve, that given the nature of the proceedings and forum, the results must be made public insofar as "public" means "agents with access to the blockchain database supporting the forum". Does that seem right to those of you who know the technical aspects better?

At all events, the adjudication should leave some sort of record that can be tapped to help develop an organic common law. The Restatements are just the seed, dropped into a supersaturated solution. This implementation of Ulex should generate outputs ready-made to feed a legal community. But how?

A side-but-not-unimportant-note: Judges will need to show some qualifications; they cannot be mere random agents but will have posted stake and/or reputation of performing specified functions.

proftomwbell commented 5 years ago

Asks @Physes:

Should the remedies be secret or known during the process?

Known among the parties, certainly. The parties need to know what each other proposes in successive rounds as it will shape their own proposals.

Should the remedy exchange also be known to the forum and/or judges? Perhaps. It might drive the parties more towards private peace if they know the judges will see intransigence. But why favor "private peace" in this context? At some limit, after all, it might represent a reluctant concession to end an annoying, irrational, or vindictive process. Ulex procedures should aim at efficiently reconciling legitimate claims without neglecting victims of abuse of legal process.

Query whether pre-resolution exchanges of remedies should be kept off of the main chain. It says a lot that in the real world, negotiations between adverse parties seldom take place in public. The game theoretic dynamics of information exchange between the parties and the public bear careful consideration. Given the whole cat-bag dynamic, it would probably be best to set the default at "exchange of remedies exposed only to contesting parties".

How about this for the Ulex forum's rules (consistent with the core Ulex rules but not mandated by them): The plaintiff files suit in the forum. The filing would require the plaintiff to show that jurisdiction applies to him/her/it and what version of Ulex applies to the dispute in question. Either the plaintiff or the forum would establish that jurisdiction over the defendant obtains. If so, the plaintiff's filing would give notice to the defendant actually and/or constructively. This notice would likely obtain in the form of a ding on the defendant's reputation stake, accessible to the forum via the larger institutional framework through which the defendant agreed to the court's jurisdiction. The public (i.e. relevant blockchain community) would then know that plaintiff had filed an unanswered suit against the defendant.

The plaintiff would make a private demand to the defendant in the form of a proposed remedy, presumably accompanied with a justification. A legal service community will probably arise to help write justifications that, by reciting the facts and applying the relevant rules, convince defendants to concede. This need not be made public.

The defendant can reply to the plaintiff's demand with silence, a counter-remedy, or by accepting the proposed remedy and conceding the suit. Only the last result need be made public, as the forum would report that the plaintiff had filed suit and that the parties had settled. Defendant's reputation rating would get reset.

If instead of conceding, the defendant answers with silence or a counter-remedy, the plaintiff could withdraw suit. In so doing, the plaintiff would presumably sacrifice stake and/or reputation. All this could occur before the parties call up judges, thus avoiding that expense.

If the plaintiff proceeds, he/she/it ("hsi" one might say, haha) would finally have to choose a judge. The plaintiff could send another proposed remedy to the defendant, etc.

Whether or not the judges should get to review the record of the negotiations between the parties remains unclear. They of course need to see the final offers, if the process makes it through the three rounds proposed. These will presumably come with justifications crafted by the parties, perhaps through their counsels. For a SOOPER stripped-down version of a precedent-building system, the Ulex forum could output the parties, the remedy, and the justification attached to it.

Over time, the (presumably searchable) record of decisions would itself generate a body of authority. Where that takes Ulex remains to be seen. Again, though, it seems likely that the Restatements and other artifacts of this world will serve merely as seeds dropped in a supersaturated medium, and that the Ulex community will grow from and around that core into forms beyond present imagination. We here need only make sure to make room for that organic growth.

proftomwbell commented 5 years ago

None of that is to say it is time to code such features now. Running code in-hand always beats waiting for the perfect version. But theorizing has its charms, and sometimes even its uses.

gititGoro commented 5 years ago

@Physes I'm enjoying your iterations on the ulex procedural contract. A few comments and questions:

Remedies as strings

The remedies are represented as string. Should they not be something more interpretable by code such as a hash? This would interface nicely with an external hash based storage like IPFS. It's also hard for ethereum contracts to act on strings. I can't make up my mind on this one. For instance, suppose the remedies were strictly token amounts rather than complex arrangements? I realize this narrows down the use a bit... I guess if remedies are strings then external smart contracts plugging into ulex can have arrays of strings that map to blockchain actions. For instance if a remedy is "washmycar" then a DAO using ulex can have a mapping(string=>bool) remediesActedOn where its members vote on whether remediesActedOn["washmycar"] has been fulfilled by the guilty party.

Asymmetric Judges

So the judges can cast their votes on a public blockchain individually and aren't required to cast at the same time. Is this not an avenue for attacks? Is there some way to mix judge votes off chain into a verdict that is submitted on chain by 1 of the judges acting as a representative? I'm fairly sure there's something cryptographic that can be done off chain such as each judge signing a verdict. If the judge who reports the verdict lies, the other 2 can prove it with their private keys.

boolean simplification

In your function decide, you can simplify that if statement to: uint winner = (vote_a&&vote_b&&vote_c)? 0: 1

@proftomwbell Thank you for those explanations and explorations. It's good to know that the remedy bargaining can happen out of court and mostly offchain using cryptographic tools with blockchain hooks, and rather leaving the dispute resolution as a backstop. This is already a big improvement over Kleros.

Physes commented 5 years ago

@gititGoro re: strings, the intention here is to record URI's in a similar format as the NFT standard (which also uses strings for URI's).

An example using IPFS for abstracts or remedies would be /ipfs/0x123...xyz. Since IPFS addresses are variable length (sometimes longer than bytes32) this wouldn't be suitable. Keeping it as a string also keeps it open to other kinds of URI's.

Also agree with using a ternary operator. Feel free to suggest a code snippet.