{"action":"created","comment":{"url":"https://api.github.com/repos/ipfs/specs/pulls/comments/31345545","id":31345545,"diff_hunk":"@@ -0,0 +1,220 @@\n+# IPRS - InterPlanetary Record System spec\n+Authors: [Juan Benet](github.com/jbenet)\n+\n+Reviewers:\n+\n+- [Kristoffer Strom](github.com/krl)\n+- [Jeromy Johnson](github.com/whyrusleeping)\n+\n+* * *\n+\n+The [Spec](../) for IPRS.\n+\n+This spec defines IPRS (InterPlanetary Record System) a system for distributed record keeping meant to operate across networks that may span massive distances (>1AU) or suffer long partitions (>1 earth yr).\n+IPRS is meant to establish a common record-keeping layer to solve common problems. It is a well-layered protocol: it is agnostic to underlying replication and transport systems, and it supports a variety of different applications.\n+IPRS is part of the InterPlanetary File System Project, and is general enough to be used in a variery of other systems.\n+\n+## Definitions\n+\n+### Records\n+\n+A (distributed) `record` is a piece of data meant to be transmitted and stored in various computers across a network. It carries a `value` external to the record-keeping system, which clients of the record system use. For example: a namespace record may store the value of a name. All record systems include a notion of _record validity_, which allows users of the record system to verify whether the value of a record is correct and valid under the user's circumstances. For example, a record's validity may depend upon a cryptographic signature, a range of spacetime, et-cetera.\n+\n+### Record System\n+\n+A (distributed) `record system` is a protocol which defines a method for crafting, formating, distributing, verifying, and using records over computer networks. (e.g. the Domain Name System).\n+\n+\n+- `crafting` - construction of a record (the process of calculating the values of a record)\n+- `formating` - serializing of a record into a bitstring.\n+- `distributing` - transportation of a record from one set of computers to another.\n+- `verifying` - checking a record's values to ensure correctness and validity.\n+\n+\n+### Validity Schemes\n+\n+A `validity scheme` is a small sub-protocol that defines how a record's _validity_ is to be calculated. `Validity` is the quality of a record being usable by a user at a particular set of circumstances (e.g. a range of time). It is distinct from `correctness` in that `correctness` governs whether the record was correctly constructed, and `validity` governs whether a record may still be used. All _valid_ records must be _correct_. For simplicity, the process of checking correctness is included in the `validity scheme`.\n+\n+For example, suppose Alice and Bob want to store records on a public bulletin board. To make sure their records are not tampered with, Alice and Bob decide they will include cryptographic signatures. This can ensure correctness. Further, they also agree to add new records every day, to detect whether their records are being replayed or censored. Thus, their `validity scheme` might be:\n+\n+```go\n+type Record struct {\n+  Value     []byte\n+  Expires   time.Duration\n+  Signature []byte\n+}\n+\n+func signablePart(rec *Record) []byte {\n+  var sigbuf bytes.Buffer\n+  sigbuf.Write(r.Value)\n+  sigbuf.Write(r.Expires)\n+  return sugbuf.Bytes()\n+}\n+\n+func MakeRecord(value []byte, authorKey crypto.PrivateKey) Record {\n+  rec := Record{}\n+  rec.Value = value\n+\n+  // establish an expiration date\n+  rec.Expires = time.Now() + time.Day\n+\n+  // cryptographically sign the record\n+  rec.Signature = authorKey.Sign(signablePart(rec))\n+\n+  return rec\n+}\n+\n+func VerifyRecord(rec Record, authorKey crypto.PublicKey) (ok bool) {\n+\n+  // always check the signature first\n+  sigok := authorKey.Verify(rec.Signature, signablePart(rec))\n+  if !sigok {\n+    return false // sig did not check out! forged record?\n+  }\n+\n+  // check the expiration.\n+  if rec.Expires < time.Now() {\n+    return false // not valid anymore :(\n+  }\n+\n+  // everything seems ok!\n+  return true\n+}\n+```\n+\n+Note that even in such a simple system, we already called out to two other systems Alice and Bob are subscribing to:\n+\n+- a _Public Key Infrastructure_ (PKI) that lets Alice and Bob know each other's keys, and verify the validity of messages authored by each other.\n+- a _Time Infrastructure_ (TI) that lets Alice and Bob agree upon a common notion of time intervals and validity durations.\n+\n+Both of these are large systems on their own, which impose constraints and security parameters on the record system. For example, if Alice and Bob think that NTP timestamps are a good TI, the validity of their records is dependent on their ability to establish an accurate NTP timestamp scurely (i.e. they need secure access to shared clocks). Another TI might be to \"use the last observed record\", and this also is dependent on having a secure announcement channel.\n+\n+IPRS is _Validity Scheme Agnostic_, meaning that it seeks to establish a common way to craft and distribute records for users of a system without necessarily tying them down to specific world-views (e.g. \"NTP is a secure way to keep time\", \"The CA system is a secure PKI\"), or _forcing_ them to work around specific system choices that impose constraints unreasonable for their use case (e.g. \"Real-Time Video Over TOR\")\n+\n+### Merkle DAG and IPFS Objects\n+\n+A merkle dag is a directed acyclic graph whose links are (a) hashes of the edge target, and (b) contained within the edge source. (syn. merkle tree, hash tree)\n+\n+In this spec, _the merkle dag_ (specific one) refers to the IPFS merkle dag. _IPFS Object_ refers to objects in the merkle dag, which follow the IPFS merkledag format. (Read those specs)\n+\n+\n+## Constraints\n+\n+IPRS has the following _hard_ constraints:\n+\n+- **MUST** be transport agnostic. (transport refers to how computers communicate).\n+- **MUST** be replication agnostic. (replication refers to the protocol computers use to transfer and propagate whole records and other objects)\n+- **MUST** be validity scheme agnostic. (validity scheme includes PKI, TI, and other \"agreed upon\" trusted infrastructure)\n+- **MUST** be trustless: no trusted third parties are imposed by IPRS (though some may be adopted by a validity scheme. e.g. root CAs in the CA system PKI, or a blockchain in a blockchain TI). In most cases, users may have to trust each other (as they must trust the record value -- e.g. DNS), but in some cases there may be cryptographic schemes that enable full trustlessness.\n+\n+\n+It is easy to be agnostic to transport, replication, and validity scheme as long as users can expect to control or agree upon the programs or protocols used in concert with IPRS. Concretely, the user can select specific transports or validity schemes to suit the user's application constraints. It is the user's responsibility to ensure both record crafters and verifiers agree upon these selections.\n+\n+## Construction\n+\n+### The Objects\n+\n+IPRS records are expressed as [merkledag](../merkledag) objects. This means that the records are linked authenticated data structures, and can be natively replicated over IPFS itself and other merkledag distribution systems.\n+\n+The objects:\n+\n+- A `Record` object expresses a value, a validity scheme, and validity data.\n+- A `Signature` object could be used to sign and authenticate a record.\n+- An `Encryption` object could be used to encrypt a record.\n+\n+```go\n+Record Node {\n+  Scheme   Link // link to a validity scheme\n+  Value    Link // link to an object representing the value.\n+  Validity Data // data needed to satisfy the validity scheme\n+}\n+```\n+\n+To achieve good performance, record storage and transfer should bundle all the necessary objects and transmit them together. While \"the record object\" is only one of the dag objects, \"the full record\" means a bundle of all objects needed to fully represent, verify, and use the record. (This recommendation does not necessarily include data that records _describe_, for example an ipfs provider record (which signals to consumers that certain data is available) would not include the data itself as part of \"the full record\").","path":"records/README.md","position":133,"original_position":133,"commit_id":"e89c6d155812f7af77a2422c25e156f4c586aebe","original_commit_id":"e89c6d155812f7af77a2422c25e156f4c586aebe","user":{"login":"wking","id":209920,"avatar_url":"https://avatars.githubusercontent.com/u/209920?v=3","gravatar_id":"","url":"https://api.github.com/users/wking","html_url":"https://github.com/wking","followers_url":"https://api.github.com/users/wking/followers","following_url":"https://api.github.com/users/wking/following{/other_user}","gists_url":"https://api.github.com/users/wking/gists{/gist_id}","starred_url":"https://api.github.com/users/wking/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wking/subscriptions","organizations_url":"https://api.github.com/users/wking/orgs","repos_url":"https://api.github.com/users/wking/repos","events_url":"https://api.github.com/users/wking/events{/privacy}","received_events_url":"https://api.github.com/users/wking/received_events","type":"User","site_admin":false},"body":"Maybe drop “and use” from the “full record” definition, since that's so wishy.  To get past verification you'll need the Record, linked Scheme, and any further objects needed to validate the Validity data (which you may also want to store as links?  E.g. to public keys, etc?).  The only thing the “full record” does not need to bundle is stuff down the Value link.","created_at":"2015-05-29T17:26:50Z","updated_at":"2015-05-29T17:26:50Z","html_url":"https://github.com/ipfs/specs/pull/7#discussion_r31345545","pull_request_url":"https://api.github.com/repos/ipfs/specs/pulls/7","_links":{"self":{"href":"https://api.github.com/repos/ipfs/specs/pulls/comments/31345545"},"html":{"href":"https://github.com/ipfs/specs/pull/7#discussion_r31345545"},"pull_request":{"href":"https://api.github.com/repos/ipfs/specs/pulls/7"}}},"pull_request":{"url":"https://api.github.com/repos/ipfs/specs/pulls/7","id":36476441,"html_url":"https://github.com/ipfs/specs/pull/7","diff_url":"https://github.com/ipfs/specs/pull/7.diff","patch_url":"https://github.com/ipfs/specs/pull/7.patch","issue_url":"https://api.github.com/repos/ipfs/specs/issues/7","number":7,"state":"open","locked":false,"title":"(WIP) records + merkledag specs","user":{"login":"jbenet","id":138401,"avatar_url":"https://avatars.githubusercontent.com/u/138401?v=3","gravatar_id":"","url":"https://api.github.com/users/jbenet","html_url":"https://github.com/jbenet","followers_url":"https://api.github.com/users/jbenet/followers","following_url":"https://api.github.com/users/jbenet/following{/other_user}","gists_url":"https://api.github.com/users/jbenet/gists{/gist_id}","starred_url":"https://api.github.com/users/jbenet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jbenet/subscriptions","organizations_url":"https://api.github.com/users/jbenet/orgs","repos_url":"https://api.github.com/users/jbenet/repos","events_url":"https://api.github.com/users/jbenet/events{/privacy}","received_events_url":"https://api.github.com/users/jbenet/received_events","type":"User","site_admin":false},"body":"includes also keychain types.\n\nthis is all very much WIP","created_at":"2015-05-29T06:06:51Z","updated_at":"2015-05-29T17:26:50Z","closed_at":null,"merged_at":null,"merge_commit_sha":"75fd822d945d22c36d97b960b6ac2e105d3b78ec","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/ipfs/specs/pulls/7/commits","review_comments_url":"https://api.github.com/repos/ipfs/specs/pulls/7/comments","review_comment_url":"https://api.github.com/repos/ipfs/specs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ipfs/specs/issues/7/comments","statuses_url":"https://api.github.com/repos/ipfs/specs/statuses/e89c6d155812f7af77a2422c25e156f4c586aebe","head":{"label":"ipfs:iprs","ref":"iprs","sha":"e89c6d155812f7af77a2422c25e156f4c586aebe","user":{"login":"ipfs","id":10536621,"avatar_url":"https://avatars.githubusercontent.com/u/10536621?v=3","gravatar_id":"","url":"https://api.github.com/users/ipfs","html_url":"https://github.com/ipfs","followers_url":"https://api.github.com/users/ipfs/followers","following_url":"https://api.github.com/users/ipfs/following{/other_user}","gists_url":"https://api.github.com/users/ipfs/gists{/gist_id}","starred_url":"https://api.github.com/users/ipfs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ipfs/subscriptions","organizations_url":"https://api.github.com/users/ipfs/orgs","repos_url":"https://api.github.com/users/ipfs/repos","events_url":"https://api.github.com/users/ipfs/events{/privacy}","received_events_url":"https://api.github.com/users/ipfs/received_events","type":"Organization","site_admin":false},"repo":{"id":32023078,"name":"specs","full_name":"ipfs/specs","owner":{"login":"ipfs","id":10536621,"avatar_url":"https://avatars.githubusercontent.com/u/10536621?v=3","gravatar_id":"","url":"https://api.github.com/users/ipfs","html_url":"https://github.com/ipfs","followers_url":"https://api.github.com/users/ipfs/followers","following_url":"https://api.github.com/users/ipfs/following{/other_user}","gists_url":"https://api.github.com/users/ipfs/gists{/gist_id}","starred_url":"https://api.github.com/users/ipfs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ipfs/subscriptions","organizations_url":"https://api.github.com/users/ipfs/orgs","repos_url":"https://api.github.com/users/ipfs/repos","events_url":"https://api.github.com/users/ipfs/events{/privacy}","received_events_url":"https://api.github.com/users/ipfs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ipfs/specs","description":"Specs for IPFS","fork":false,"url":"https://api.github.com/repos/ipfs/specs","forks_url":"https://api.github.com/repos/ipfs/specs/forks","keys_url":"https://api.github.com/repos/ipfs/specs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ipfs/specs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ipfs/specs/teams","hooks_url":"https://api.github.com/repos/ipfs/specs/hooks","issue_events_url":"https://api.github.com/repos/ipfs/specs/issues/events{/number}","events_url":"https://api.github.com/repos/ipfs/specs/events","assignees_url":"https://api.github.com/repos/ipfs/specs/assignees{/user}","branches_url":"https://api.github.com/repos/ipfs/specs/branches{/branch}","tags_url":"https://api.github.com/repos/ipfs/specs/tags","blobs_url":"https://api.github.com/repos/ipfs/specs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ipfs/specs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ipfs/specs/git/refs{/sha}","trees_url":"https://api.github.com/repos/ipfs/specs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ipfs/specs/statuses/{sha}","languages_url":"https://api.github.com/repos/ipfs/specs/languages","stargazers_url":"https://api.github.com/repos/ipfs/specs/stargazers","contributors_url":"https://api.github.com/repos/ipfs/specs/contributors","subscribers_url":"https://api.github.com/repos/ipfs/specs/subscribers","subscription_url":"https://api.github.com/repos/ipfs/specs/subscription","commits_url":"https://api.github.com/repos/ipfs/specs/commits{/sha}","git_commits_url":"https://api.github.com/repos/ipfs/specs/git/commits{/sha}","comments_url":"https://api.github.com/repos/ipfs/specs/comments{/number}","issue_comment_url":"https://api.github.com/repos/ipfs/specs/issues/comments{/number}","contents_url":"https://api.github.com/repos/ipfs/specs/contents/{+path}","compare_url":"https://api.github.com/repos/ipfs/specs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ipfs/specs/merges","archive_url":"https://api.github.com/repos/ipfs/specs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ipfs/specs/downloads","issues_url":"https://api.github.com/repos/ipfs/specs/issues{/number}","pulls_url":"https://api.github.com/repos/ipfs/specs/pulls{/number}","milestones_url":"https://api.github.com/repos/ipfs/specs/milestones{/number}","notifications_url":"https://api.github.com/repos/ipfs/specs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ipfs/specs/labels{/name}","releases_url":"https://api.github.com/repos/ipfs/specs/releases{/id}","created_at":"2015-03-11T14:47:16Z","updated_at":"2015-05-27T11:26:20Z","pushed_at":"2015-05-29T06:06:51Z","git_url":"git://github.com/ipfs/specs.git","ssh_url":"git@github.com:ipfs/specs.git","clone_url":"https://github.com/ipfs/specs.git","svn_url":"https://github.com/ipfs/specs","homepage":"http://ipfs.io","size":9297,"stargazers_count":52,"watchers_count":52,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"open_issues_count":6,"forks":3,"open_issues":6,"watchers":52,"default_branch":"master"}},"base":{"label":"ipfs:master","ref":"master","sha":"fe43824e107d6194b7d78071717097358ada67a8","user":{"login":"ipfs","id":10536621,"avatar_url":"https://avatars.githubusercontent.com/u/10536621?v=3","gravatar_id":"","url":"https://api.github.com/users/ipfs","html_url":"https://github.com/ipfs","followers_url":"https://api.github.com/users/ipfs/followers","following_url":"https://api.github.com/users/ipfs/following{/other_user}","gists_url":"https://api.github.com/users/ipfs/gists{/gist_id}","starred_url":"https://api.github.com/users/ipfs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ipfs/subscriptions","organizations_url":"https://api.github.com/users/ipfs/orgs","repos_url":"https://api.github.com/users/ipfs/repos","events_url":"https://api.github.com/users/ipfs/events{/privacy}","received_events_url":"https://api.github.com/users/ipfs/received_events","type":"Organization","site_admin":false},"repo":{"id":32023078,"name":"specs","full_name":"ipfs/specs","owner":{"login":"ipfs","id":10536621,"avatar_url":"https://avatars.githubusercontent.com/u/10536621?v=3","gravatar_id":"","url":"https://api.github.com/users/ipfs","html_url":"https://github.com/ipfs","followers_url":"https://api.github.com/users/ipfs/followers","following_url":"https://api.github.com/users/ipfs/following{/other_user}","gists_url":"https://api.github.com/users/ipfs/gists{/gist_id}","starred_url":"https://api.github.com/users/ipfs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ipfs/subscriptions","organizations_url":"https://api.github.com/users/ipfs/orgs","repos_url":"https://api.github.com/users/ipfs/repos","events_url":"https://api.github.com/users/ipfs/events{/privacy}","received_events_url":"https://api.github.com/users/ipfs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ipfs/specs","description":"Specs for IPFS","fork":false,"url":"https://api.github.com/repos/ipfs/specs","forks_url":"https://api.github.com/repos/ipfs/specs/forks","keys_url":"https://api.github.com/repos/ipfs/specs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ipfs/specs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ipfs/specs/teams","hooks_url":"https://api.github.com/repos/ipfs/specs/hooks","issue_events_url":"https://api.github.com/repos/ipfs/specs/issues/events{/number}","events_url":"https://api.github.com/repos/ipfs/specs/events","assignees_url":"https://api.github.com/repos/ipfs/specs/assignees{/user}","branches_url":"https://api.github.com/repos/ipfs/specs/branches{/branch}","tags_url":"https://api.github.com/repos/ipfs/specs/tags","blobs_url":"https://api.github.com/repos/ipfs/specs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ipfs/specs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ipfs/specs/git/refs{/sha}","trees_url":"https://api.github.com/repos/ipfs/specs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ipfs/specs/statuses/{sha}","languages_url":"https://api.github.com/repos/ipfs/specs/languages","stargazers_url":"https://api.github.com/repos/ipfs/specs/stargazers","contributors_url":"https://api.github.com/repos/ipfs/specs/contributors","subscribers_url":"https://api.github.com/repos/ipfs/specs/subscribers","subscription_url":"https://api.github.com/repos/ipfs/specs/subscription","commits_url":"https://api.github.com/repos/ipfs/specs/commits{/sha}","git_commits_url":"https://api.github.com/repos/ipfs/specs/git/commits{/sha}","comments_url":"https://api.github.com/repos/ipfs/specs/comments{/number}","issue_comment_url":"https://api.github.com/repos/ipfs/specs/issues/comments{/number}","contents_url":"https://api.github.com/repos/ipfs/specs/contents/{+path}","compare_url":"https://api.github.com/repos/ipfs/specs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ipfs/specs/merges","archive_url":"https://api.github.com/repos/ipfs/specs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ipfs/specs/downloads","issues_url":"https://api.github.com/repos/ipfs/specs/issues{/number}","pulls_url":"https://api.github.com/repos/ipfs/specs/pulls{/number}","milestones_url":"https://api.github.com/repos/ipfs/specs/milestones{/number}","notifications_url":"https://api.github.com/repos/ipfs/specs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ipfs/specs/labels{/name}","releases_url":"https://api.github.com/repos/ipfs/specs/releases{/id}","created_at":"2015-03-11T14:47:16Z","updated_at":"2015-05-27T11:26:20Z","pushed_at":"2015-05-29T06:06:51Z","git_url":"git://github.com/ipfs/specs.git","ssh_url":"git@github.com:ipfs/specs.git","clone_url":"https://github.com/ipfs/specs.git","svn_url":"https://github.com/ipfs/specs","homepage":"http://ipfs.io","size":9297,"stargazers_count":52,"watchers_count":52,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"open_issues_count":6,"forks":3,"open_issues":6,"watchers":52,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ipfs/specs/pulls/7"},"html":{"href":"https://github.com/ipfs/specs/pull/7"},"issue":{"href":"https://api.github.com/repos/ipfs/specs/issues/7"},"comments":{"href":"https://api.github.com/repos/ipfs/specs/issues/7/comments"},"review_comments":{"href":"https://api.github.com/repos/ipfs/specs/pulls/7/comments"},"review_comment":{"href":"https://api.github.com/repos/ipfs/specs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ipfs/specs/pulls/7/commits"},"statuses":{"href":"https://api.github.com/repos/ipfs/specs/statuses/e89c6d155812f7af77a2422c25e156f4c586aebe"}}}}