Skip to content

Instantly share code, notes, and snippets.

@Renelvon
Last active August 29, 2015 14:10
Show Gist options
  • Save Renelvon/7e2a2def5e15bc47d091 to your computer and use it in GitHub Desktop.
Save Renelvon/7e2a2def5e15bc47d091 to your computer and use it in GitHub Desktop.
Thoughts on designing an API for Contracts in the OpenBazaar platform.

This is how I envision the Contract API in OpenBazaar.

Disclaimer: I may not be staying completely within the bounds of Ricardian Contracts; I am prioritizing flexibility and ease of use above formality, because I would like to have a working prototype soon, and polish it for FOSDEM. The structure will accept plugins that will ultimately enable OpenBazaar to support diverse kinds of business.

The new Contract API comprises of 3 major types of Classes: ContractParts, Contracts and Trades. Here's a breakdown:

Contract parts

A ContractPart is the smallest autonomous part of a contract, and as such, it is meant to be used as a building block. Each ContractPart represents exactly one step towards the materialization of the contract. Subclasses of ContractPart will be tailored to the semantic role of the relevant part/step. So, there can be a BuyerContractPart, a SellerContractPart, a NotaryContractPart, etc. Each such subclass shall be mapped to a JSON object in a 1-1 way. For this reason, the subclass shall provide a specific a JSON schema to be used for validation purposes during deserialization. The JSON representation makes the sending and receiving of parts trivial and compatible with any kind of platform, while the Python representation makes the processing easier and amenable to testing.

Anyone can create a new subclass of ContractPart to fit a specific financial role. For example, there could be a MommyContractPart, which would be necessary in a transaction where the buyer or seller is a minor. Such functionality can easily be provided via plugins.

Note: There is a special subclass of ContractPart that contains all the metadata about the contract, the GenesisContractPart. This one makes the processing of contracts easier but may have other uses we haven't dreamt of yet. I will explain it in more detail later.

Contracts

A Contract is a really dumb, lawyer-friendly object, meant to represent a contract in its various stages of materialization. A Contract can be mapped in a 1-1 way into a JSON array. This is a departure from the Ricardian scheme, where a contract is a multi-signed GPG document. The GPG way is more formal but hinders processing; we shall devise an equally safe but more machine-friendly scheme. Here is a proposal:

A Contract is a container of ContractParts, which it arranges in a (cryptographic) chain. A ContactPart verifies its predecessors in the chain in the following way: Each ContractPart has a special field called acksig. The first ContractPart, which shall be the GenesisContractPart, has its acksig set to an arbitrary value, which may or may not be semantically important. When a financial agent wants to expand a Contract, they first make a GPG signature of the JSON representation of the last ContractPart in the received contract. Then, they create a ContractPart with all the relevant info, and set the acksig attribute of the new part to the signature just made. They then proceed to send the new Contract (or --for efficiency and other reasons-- just the new part(s)) to other financial agents, who iterate in the chain in the same way. Each round of iteration has the meaning "I acknowledge the contract so far and add these terms; you can accept them by counter-signing". Though the financial agent doesn't technically sign the terms they add, this should be considered implicitly true, as they identify themselves via GPG signing the rest of the Contract. If this doesn't pack enough legal punch, we can revisit the design.

The Contract class includes some utility functions to facilitate all these operations but is otherwise ignorant to what the nature of the contract is. It is not meant to be extended or subclassed, except for performance reasons (if all parties in a Contract are unique, it is easy to implement it with an OrderedDict, otherwise a list is needed).

Trades

The Trade class is where the fun really happens. Each subclass of the Trade class represents a specific kind of trade. For example, there can be an Item4ItemTrade, a BTC4ItemTrade, an AuctionTrade, etc, whatever the market needs, extended via a plugin system. This class manages an evolving Contract through some specified stages tailored to the purpose of the class. Because this class knows what kind of Contract is handles, it is the right spot to do all sorts of dirty I/O work, aka interacting with the network and the DB, handling errors, producing QR codes, etc. I don't yet have a plan for what kind of Trade classes we will need; for the first iteration I 'll just aim to replace the whole orders.py module without much fuss.

I 've been mentally working on that design for about a week, but this is the first time I sat to write it down. All criticism accepted. Thanks for reading through!

@theblacksquid
Copy link

Just a question, would the ContractPart be something that looks like

class ContractPart:
    __init__(self, party, sig):    # party is the person signing
        self.party = party         # the ContractPart with param sig
        self.sig = sig

?

@iangfc
Copy link

iangfc commented Dec 14, 2014

The Ricardian text form v. use of JSON is somewhat finessable within the context of the canonicalisation. I.e., you can create two canonicalisations, one of which goes to the open text form, the other of which goes to JSON. And, lock both forms to the hash/signature with care of course.

Whether this is worth anything or not, I don't know. In my work I've found it easier to work from the text because any processing from String to class is about the same work as JSON to class, and the straight text has the advantage of readability -> disputability. YMMV.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment