Skip to content
Gene Vayngrib edited this page Apr 23, 2015 · 11 revisions

This protocol defines how objects are put on-chain. By on-chain we do not mean we put the whole object on the blockchain as it is very expensive. We put a pointer in the blockchain transaction and the rest of the data into additional storage, e.g. DHT + bittorrent. To make the protocol blockchain agnostic we will need special binding to Bitcoin, Ethereum, and other blockchains. Below is the binding to Bitcoin.

This is a version 0.5.

Binding to Bitcoin

Bitcoin blockchain provides limited metadata space in OP_RETURN. An OP_RETURN is used to put the word "Tradle" followed by a hash of the object in the DHT

Tradle semantic_version tx_type hash

or

Tradle semantic_version tx_type encrypted_hash 

Where semantic_version is 3 bytes: major version, minor version, patch number Where tx_type is defined in TransactionData.types

Note that there is no space between tokens above, it is used here only for clarity

Object

Every Object has these properties:


/** 
 *  All properties starting with "_" are object metadata. See [metadata](...)
 *  Stringified JSON must have properties in alphabetical order (json-stable-stringify)
 *  _t is a type 
 *  _n specifies a blockchain network on which this object originated.
 *  TBTC = bitcoin testnet (3)
 *  BTC  = bitcoin
 *  ETH  = Ethereum
 *  TETH = Ethereum testnet
 *  FTM  = Factom
 *  TFTM = Factom testnet
 *  We will need to define a registry of blockchains later.
 *  _v is a [semantic_version](http://semver.org/) of the protocol used to create this object.
 *  _m is a merkle root of all objects created by this Identity, if not anonymous (described later).
**/
{
  "_t": "tradle.food.Jellybean:original_hash:current_hash",
  "_n": "TBTC",
  "_v": "0.5",
  "_m": "merkle root"
}

Versions

Each object points to a previous object version (_p) and the blockchain transaction that created previous version (_p_tx). Each object also specifies the latest observed block height (_h), to aid in finding the tx that created it.

Note that it would be cool to point to the tx itself, but this would create a circular dependency in calculating a tx hash.

{
  "_p": "hash",
  "_p_tx": "tx_hash",
  "_h": "323018"
}

Validation of clear text objects

Validation of objects and Identities on bitcoin chain is done by the bitjoe plugin. This means invalid objects can be put on chain. Each client node performs the validation and throws away bad objects.

Later we could post a proof on chain of the origins of the bad objects, creating an audit trail for bad actors.

On Ethereum the validation is done by the Identity contract.

  1. check that the _p hash points to the last version of the object.
  2. check that the _p_tx points to the tx that has an OP_RETURN which has a hash of the last version of the object.
  3. Scan the chain for 10 blocks starting with _h block height for the tx which has an OP_RETURN with the hash of this object.
  4. check that the object is signed by the owner of this object. If the object is Identity and it is the first version of this object, the signature must match the "verify" key on that object. Every subsequent version of Identity object must match the "verify" key of the previous version of this Identity object.

Identity

Identity is a special type of object. It's main purpose is to create a continuity of actions for people, organizations, devices, programs. Continuity is achieved by signing objects with Identity's "verify" private key. Prior to the first Identity object, the Identity model needs to be put on chain.

/** 
 * Identity is used to sign and encrypt objects.
 * Identity objects include all the general object metadata, like network, height, etc. 
 * (not repeated in the example below for succinctness)
 * 
 * The "verify" public key is used to verify objects signed by this identity's "verify" private key.
 * 
 * Sender uses the "encrypt" public key to encrypt objects, 
 * so that the owner of this identity could decrypt them.
 *
 * Signature (_s) is generated from the hash of the Identity object 
 * (with _s property removed) and a "verify" private key. 
 *
 * Name is optional, and can be real person's name, an alias, company name, etc. 
 * Uniqueness of the name is not enforced, make sure to verify the Identity object before using it.
 * address is a bitcoin address, Ethereum address, i.e. an address on a network specified above.
 *
**/
{
  "_s": "...signature of this object ...",
  "_t": "tradle.base.Identity:original_hash:current_hash",
  "name": "Jo Jo",
  "address": "mvKXWXidparr7DQdnX4EkEAy5wN5aH1f9L",
  "encrypt": "024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34",
  "verify": "0291a8e280faa818fd61d9661f4c4ad47cc6d868c9679c378ce8439fe8042b2169"

}

Recognizing object sent to you

Your node needs a mechanism to understand which transactions are sent to you and from you to others. Lookup is done by the recipient's blockchain address.

WARNING: this section is not complete yet

Encryption

Objects can be encrypted for privacy. In this case the hash of the object that is put on chain is encrypted too. We also create intermediate Permission Objects that allows to distribute access rights to the same encrypted object to multiple parties.

  1. Create a shared key from senders private key and receiver's public key using EC math.
   sender's private key + receiver's public key = receiver's private key + sender's public key

Receiver constructs the shared key according to the right side of the equation.

  1. Generate AES 256 bit key.

  2. Encrypt a signed object with the AES key.

  3. Create a permissions object and sign it.

{
   "key": "aes key",
   "hash": "object's hash"
}
  1. Encrypt Permission Object with a shared key.

  2. Put Object and a Permission Object into the DHT.

  3. Encrypt Permission Object hash with shared key.

  4. Put above hash on chain.

Light client

Warning - this section is incomplete.

On Ethereum, all clear text objects can be validated. Thus the Object contract contains the last correct version of the object. This allows to construct a light client for clear text objects, such as Identities. Note: The concern is that to retrieve that version, we need to execute the transaction.

Object Validation rules

Warning - this section is incomplete.

  1. Objects size is limited to 7k.

  2. Ideally invalid objects should not be stored in DHT as DHT nodes would validate every put request. Encrypted objects present a problem for validation...

Attachments

Our goal is to create a global transaction log, not a file storage. For your distributed file storage needs look at Maidsafe, Storj, IPFS and other projects. That said objects very often need some media file, like a profile image or a short video, a product image, a photo of the house, PDFs of the contract agreement, etc. So we provide support for object attachments.

If object does not have attachments, it is just a JSON file, otherwise it is multipart/form-data spec file, with the first part being the JSON file. The model for the object must have a property with the type as one of the known mime types.

Object's property points to a specific attachment, like this:

    myProfilePhoto: "{type: file; hash:<hash of the file>}"

Property can point to a list of attachments:

    myHouseImageGallery: "[{type: file; hash:<hash of the 1st file>},
                           {type: file; hash:<hash of the 2nd file>}]"

Attachment filenames are not included. Including the same attachments more than once is not allowed. i.e. attachemnt hashes must be unique. Multipart boundary contains Object property as name and hash as a filename.

    <boundary>name:myProfilePhoto filename: <hash of this file>

###Deterministic packaging of attachments It is important to understand that unlike with the HTTP multipart protocol, we must provide the deterministic algorithm for packaging of attachments so that the final hash of the object is calculated the same way across many implementations of this spec.

  1. hash each attachment
  2. sort attachments lexicographically by their respective hash
  3. provide a unique boundary between attachments. Multipart spec requires a string to be used as a boundary between parts. We calculate the boundary as a hash of concatenated hashes of all attachments. One complication though: the boundary string must ne unique, it can not occur anywhere inside the attachments. So we check if it does (very unlikely to happen), then we hash the hash itself and repeat the test.

Signature of the object with attachments

Signature of the object is calculated from a string that contains the JSON object (sans the _s property) concatenated with the hashes of the attachments sorted in the same order they are packaged in the final file.

The incentives model for larger objects

Objects with attachments are substantially larger, so the incentives need to reflect the size. Validation rules to prevent spam and attacks need to be developed. At this point, we just limit each file to 5MB and a number of attachments to 10.

Future work on Privacy

  • forward secrecy by using new keys for every data item
  • erasure coding to make passive eavesdropping harder
  • regular re-encryption to avoid keeping the files with old encryption scheme around for 5-10 years when it may not be strong enough anymore
  • rescinding/revoking the right to access the object. Revocation transaction must be published on-chain and the DHT will need to check if the key was revoked.
Clone this wiki locally