{"action":"created","comment":{"url":"https://api.github.com/repos/ethersphere/go-ethereum/pulls/comments/203617513","pull_request_review_id":138540912,"id":203617513,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwMzYxNzUxMw==","diff_hunk":"@@ -562,3 +563,89 @@ func (c *Client) MultipartUpload(hash string, uploader Uploader) (string, error)\n \t}\n \treturn string(data), nil\n }\n+\n+// CreateResource creates a Mutable Resource with the given name and frequency, initializing it with the provided\n+// data. Data is interpreted as multihash or not depending on the multihash parameter.\n+// startTime=0 means \"now\"\n+// Returns the resulting Mutable Resource manifest address that you can use to include in an ENS Resolver (setContent)\n+// or reference future updates (Client.UpdateResource)\n+func (c *Client) CreateResource(request *mru.Request) (string, error) {\n+\tresponseStream, err := c.updateResource(request)\n+\tif err != nil {\n+\t\treturn \"\", err\n+\t}\n+\tdefer responseStream.Close()\n+\n+\tbody, err := ioutil.ReadAll(responseStream)\n+\tif err != nil {\n+\t\treturn \"\", err\n+\t}\n+\n+\tvar manifestAddress string\n+\tif err = json.Unmarshal(body, &manifestAddress); err != nil {\n+\t\treturn \"\", err\n+\t}\n+\treturn manifestAddress, nil\n+}\n+\n+// UpdateResource allows you to send a new version of your content\n+func (c *Client) UpdateResource(request *mru.Request) error {\n+\t_, err := c.updateResource(request)\n+\treturn err\n+}\n+\n+func (c *Client) updateResource(request *mru.Request) (io.ReadCloser, error) {\n+\tbody, err := request.MarshalJSON()\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\treq, err := http.NewRequest(\"POST\", c.Gateway+\"/bzz-resource:/\", bytes.NewBuffer(body))\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\tres, err := http.DefaultClient.Do(req)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\treturn res.Body, nil\n+\n+}\n+\n+// GetResource returns a byte stream with the raw content of the resource\n+// manifestAddressOrDomain is the address you obtained in CreateResource or an ENS domain whose Resolver\n+// points to that address\n+func (c *Client) GetResource(manifestAddressOrDomain string) (io.ReadCloser, error) {\n+\n+\tres, err := http.Get(c.Gateway + \"/bzz-resource:/\" + manifestAddressOrDomain)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\treturn res.Body, nil\n+\n+}\n+\n+// GetResourceMetadata returns a structure that describes the Mutable Resource\n+// manifestAddressOrDomain is the address you obtained in CreateResource or an ENS domain whose Resolver\n+// points to that address\n+func (c *Client) GetResourceMetadata(manifestAddressOrDomain string) (*mru.Request, error) {\n+\n+\tresponseStream, err := c.GetResource(manifestAddressOrDomain + \"/meta\")","path":"swarm/api/client/client.go","position":81,"original_position":81,"commit_id":"78d2a0d3f5315e8d6c259a8000fdc4305159eeed","original_commit_id":"64851562a49ffbc3d7e44e663af9647c1fc4bcbc","user":{"login":"nolash","id":9886925,"node_id":"MDQ6VXNlcjk4ODY5MjU=","avatar_url":"https://avatars1.githubusercontent.com/u/9886925?v=4","gravatar_id":"","url":"https://api.github.com/users/nolash","html_url":"https://github.com/nolash","followers_url":"https://api.github.com/users/nolash/followers","following_url":"https://api.github.com/users/nolash/following{/other_user}","gists_url":"https://api.github.com/users/nolash/gists{/gist_id}","starred_url":"https://api.github.com/users/nolash/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nolash/subscriptions","organizations_url":"https://api.github.com/users/nolash/orgs","repos_url":"https://api.github.com/users/nolash/repos","events_url":"https://api.github.com/users/nolash/events{/privacy}","received_events_url":"https://api.github.com/users/nolash/received_events","type":"User","site_admin":false},"body":"Yes, you are right, paths are irrelevant outside of `bzz:`. Still, this doesn't sit quite right by me. I think query string would be more natural. But to echo a common plea in this PR; let's make it a new PR.","created_at":"2018-07-19T06:49:41Z","updated_at":"2018-07-19T06:49:41Z","html_url":"https://github.com/ethersphere/go-ethereum/pull/784#discussion_r203617513","pull_request_url":"https://api.github.com/repos/ethersphere/go-ethereum/pulls/784","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/ethersphere/go-ethereum/pulls/comments/203617513"},"html":{"href":"https://github.com/ethersphere/go-ethereum/pull/784#discussion_r203617513"},"pull_request":{"href":"https://api.github.com/repos/ethersphere/go-ethereum/pulls/784"}},"in_reply_to_id":203293644},"pull_request":{"url":"https://api.github.com/repos/ethersphere/go-ethereum/pulls/784","id":200758761,"node_id":"MDExOlB1bGxSZXF1ZXN0MjAwNzU4NzYx","html_url":"https://github.com/ethersphere/go-ethereum/pull/784","diff_url":"https://github.com/ethersphere/go-ethereum/pull/784.diff","patch_url":"https://github.com/ethersphere/go-ethereum/pull/784.patch","issue_url":"https://api.github.com/repos/ethersphere/go-ethereum/issues/784","number":784,"state":"open","locked":false,"title":"Client-side MRU signatures","user":{"login":"jpeletier","id":11574521,"node_id":"MDQ6VXNlcjExNTc0NTIx","avatar_url":"https://avatars0.githubusercontent.com/u/11574521?v=4","gravatar_id":"","url":"https://api.github.com/users/jpeletier","html_url":"https://github.com/jpeletier","followers_url":"https://api.github.com/users/jpeletier/followers","following_url":"https://api.github.com/users/jpeletier/following{/other_user}","gists_url":"https://api.github.com/users/jpeletier/gists{/gist_id}","starred_url":"https://api.github.com/users/jpeletier/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jpeletier/subscriptions","organizations_url":"https://api.github.com/users/jpeletier/orgs","repos_url":"https://api.github.com/users/jpeletier/repos","events_url":"https://api.github.com/users/jpeletier/events{/privacy}","received_events_url":"https://api.github.com/users/jpeletier/received_events","type":"User","site_admin":false},"body":"# Client-side MRU signatures\r\n### Note:\r\nThis is the final step for reviewing the client-side-MRU PR. This PR was reviewed in 5 steps, and this is the final review prior to merging into `develop`.\r\n\r\nThe already completed steps were:\r\n* **Step 1** : (PR #732) Minimum set of changes for client-side MRU signatures to work + system-time based MRUs. This was the status roughly 8 days ago.\r\n* **Step 2**: (PR #733) Documentation, refactors and new, more concrete unit tests for the new structures\r\n* **Step 3**: (PR #734) Refactor `LookupParams` so that the different combinations are documented. Moved LookupParams to its own file. Reorder code and create separate files for a few structures\r\n* **Step 4** (PR #748): Final refactors. Refactor serialization for extensibility. Refactor Timestamp to a \"Timestamp\" struct rather than a lone uint64. More comments throughout.\r\n* **Step 5**: (PR #704) Rewrite CLI and simplify client and internal object structure according to comments to decouple resource creation from updating.\r\n\r\n## Abstract\r\nThe current implementation of MRU uses the running node's private key to sign all MRUs that are requested to that node. This is a limitation for environments in which a node is shared among different users (for example, a company-wide node) and also does not allow people using public nodes to test MRUs, Swarm's Power of the Dark Side!\r\n\r\nThis PR moves MRU signatures to the client, so anyone can create and update resources with their private/public key through any node, including support for Web3 browsers such as Mist and plug-ins like Metamask. Indeed, **this would allow to update content directly from your browser**!\r\n\r\nThis PR's continues @nolash's work that detaches ENS for authorization. **WARNING**: merging this PR will automatically merge @nolash's #743 !!\r\n\r\n### Additionally, this PR adds the following:\r\n* Fully removes ENS dependencies, such as having to name resources after domain names. The resource name is now a completely independent convenience user field.\r\n* Command-line tool (`swarm resource`) to manage creating, updating resources and reading their metadata easily\r\n* Code clean-up and refactoring. Segregated the metadata from updates in easily upgradeable structures\r\n* Refactored chunk serialization/deserialization for extensibility\r\n* Strong verification that the user updating a resource indeed owns the private key associated to it via a 2-step hash algorithm. There was a bug in the current implementation that allowed anyone to update your resource!!\r\n* Removed blockchain dependency for timing. Update frequencies are now expressed in seconds. This was implemented as an abstraction with a `timestampProvider` interface, so really any source of timing can be used, or time can be \"frozen\" for testing.\r\n* Added support for MRUs in the client (`client.go`), so MRUs can be used from other golang applications, including Swarm's cli.\r\n* Allow the user to set a start time in the future. This allows to publish a resource that won't resolve until the clock hits that time.\r\n* Documentation update\r\n\r\nSupport for **_automatically_** signing MRUs by the node's `bzzaccount` private key has been removed from the server side. However, the API easily allows the node itself to use MRUs with its own private key. The `swarm` command line tool (client) can pick your local account from the same place, so regular users wouldn't notice where signing is actually taking place.\r\n\r\n## Code refactoring and terminology standarization\r\n\r\nThroughout the package, the code has been refactored with the following reusable and extensible structures. To avoid confusion, the use of ambiguous terms such as `addr`or `key` has been removed.\r\n\r\n### Main structures:\r\n\r\n* `resourceUpdate`: encapsulates the information sent as part of a resource update: period, version, multihash flag, the data payload and a reference to the Mutable Resource's metadata chunk.\r\n* `resourceMetadata`: carries the immutable information about a mutable resource: start time, frequency, name and owner.\r\n* `resource`: `resourceUpdate` + `resourceMetadata`. Caches resource data. When synced it contains the most recent version of the resource data and the metadata of its root chunk\r\n* `SignedResourceUpdate`: `resourceUpdate` + signature\r\n* `Request` message: `SignedResourceUpdate` + `resourceMetadata`. Serializable structure used to issue Mutable Resource creation and update messages.\r\n### Terms:\r\n* `ownerAddr`: Address of the resource owner. Type: `storage.Address`\r\n* `metaHash` is the SHA3 hash of the encoded `resourceMetadata`, excluding `ownerAddr`\r\n* `rootAddr`: this is the key of the chunk that contains the Mutable Resource metadata. Calculated as the SHA3 hash of `ownerAddr` and `metaHash`. Type: `storage.Address`\r\n* `updateAddr`: this is the key of the chunk that contains the Mutable Resource update. Calculated as the SHA3 hash of `period`, `version` and `rootAddr`. Type: `storage.Address`\r\n\r\n### Chunk Validator refactor\r\n\r\nThe chunk validator (`Validate` method) has been rewritten to:\r\n\r\n* Validate medatata chunks, whose key is content-addressed not as a direct Swarm hash of the content, but rather as `SHA3(ownerAddr, metaHash)` where `metaHash = SHA3(resource name, frequency, startTime)`.\r\n* Validate update chunks verifying signatures and proof of ownership of the resource to be updated without having to lookup/download the referenced metadata chunk.\r\n\t* Ownership is proven if the following holds true `rootAddr == SHA3(signature_address, metaHash)`, where `signature_address` is the recovered address from the signature of the update chunk digest; `digest = SHA3(updateAddr, metaHash, data)`, where `updateAddr` is the update chunk address, `updateAddr = SHA3(period, version, rootAddr)`.\r\n\r\n## HTTP API\r\n\r\nThe HTTP API for resources (`/bzz-resource:/`) now works as follows:\r\n\r\n#### Resource creation:\r\n `POST /bzz-resource:/` with the following JSON as payload: \r\n```\r\n{\r\n  \"name\": string,\r\n  \"frequency\": number,\r\n  \"startTime\": number,\r\n  \"ownerAddr\" : hex string,\r\n}\r\n```\r\nwhere:\r\n* `name` Resource name. This is a user field. You can use any name\r\n* `frequency` Time interval the resource is expected to update at, in seconds.\r\n* `startTime` Time the resource is valid from, in Unix time (seconds). Set to the current epoch.\r\n  * Advanced: you can also put a `startTime` in the past or in the future. Setting it in the future will prevent nodes from finding content until the clock hits `startTime`. Setting it in the past allows you to create a history for the resource retroactively.\r\n* `ownerAddr` is the address derived from your public key. Hex encoded, prefixed with `0x`.\r\n\r\nReturns: **MRU Manifest Key**, as a quoted string. As before, this key can be put in an ENS Resolver contract with `setContent`.\r\nThe MRU Manifest Key resolves to a manifest that points to the metadata root chunk (`rootAddr`).\r\n\r\nNote that this method only creates the resource. The resource will not return any data until a first update is submitted. You will usually create resources and initialize them. To do that, use the following:\r\n\r\n#### Simultaneous resource creation and data initialization:\r\n `POST /bzz-resource:/` with the following JSON as payload: \r\n```\r\n{\r\n  \"name\": string,\r\n  \"frequency\": number,\r\n  \"startTime\": number,\r\n  \"rootAddr\" : hex string,\r\n  \"data\": hex string,\r\n  \"multihash\": boolean,\r\n  \"period\": number,\r\n  \"version\": number,\r\n  \"signature\": hex string\r\n}\r\n```\r\nwhere:\r\n* `multihash` is a flag indicating whether the `data` field should be interpreted as raw data or a multihash\r\n* `data` contains hex-encoded raw data or a multihash of the content the mutable resource will be initialized with. Prefixed with `0x`\r\n* `period` indicates for what period we are signing. This must be set to `1`.\r\n* `version` indicates what resource version of the period we are signing. Must be set to `1` for creation.\r\n* `signature` Signature of the digest. Hex encoded. Prefixed with `0x`. The signature is calculated as follows `digest = H(period, version, rootAddr, metaHash, multihash, data)`, where:\r\n  * `H()` is the `SHA3` algorithm.\r\n  * `period`, `version` are encoded as little-endian `uint64`\r\n  * `rootAddr` is encoded as a 32 byte array\r\n  * `metaHash` is encoded as a 32 byte array\r\n  * `multihash` is encoded as the least significant bit of a flags byte\r\n  * `data` is the plain data byte array.\r\n\r\nReturns: **MRU Manifest Key**, as a quoted hex string. As before, this key can be put in an ENS Resolver contract with `setContent`.\r\nThe MRU Manifest Key resolves to a manifest that points to the metadata root chunk (`rootAddr`)\r\n\r\n### To update a resource:\r\n#### Step 1:\r\neither\r\n    `GET /bzz-resource:/<MRU_MANIFEST_KEY>/meta`\r\n-or-\r\n    `GET /bzz-resource:/<DOMAIN THAT POINTS TO MRU_MANIFEST_KEY>/meta`\r\n\r\nThis produces a response like this:\r\n```\r\n{\r\n  \"name\": \"myresource\",\r\n  \"frequency\": 300,\r\n  \"startTime\": 1528722352,\r\n  \"ownerAddr\": \"0x7a2e393025c567ec4089d34f393ae6b5c234536a\",\r\n  \"rootAddr\": \"0x0c5acf8e3176900bc5b7b732261b5ebafc05a56da3b01c044214408e841f4ded\",\r\n  \"metaHash\": \"0x0d6968416844245d605b5e4205858e9a4779936fc3a279dce2d38415de91d79f\",\r\n  \"version\": 1,\r\n  \"period\": 8,\r\n  \"multiHash\": true\r\n}\r\n```\r\nwhere:\r\n* **Metadata Fields**\r\n\t* `name`: filled with the original value used to create the resource\r\n\t* `frequency`: filled with the original value used to create the resource\r\n\t* `startTime`: filled with the original value used to create the resource\r\n\t* `ownerAddr`: filled with the original value used to create the resource\r\n\t* `metaHash` Metadata hash, calculated as `metaHash=H(len(metadata), startTime, frequency,name)`. Hex encoded\r\n\t* `rootAddr` Metadata Root Chunk Address, calculated as `rootAddr = H(metaHash, ownerAddr)`. This scheme effectively locks the root chunk so that only the owner of the private key that `ownerAddr` was derived from can sign updates.\r\n* **Information about current update**\r\n\t*  `version`: filled with the version number of the MRU that must be used for the next update to be successful. \r\n\t* `period`: filled with the period number of the MRU that must be used for the next update to be successful\r\n\t* `multihash`: whether the current data pointed to by the resource is multihash\r\n\r\n#### Step 2:\r\nTo update the resource, create a new flat JSON with the following fields:\r\n* `data`: new data you want to set\r\n* `multihash`: whether the new data should be considered a multihash\r\n* `period`: use the suggested period from Step 1.\r\n* `version`: use the suggested version from Step 1.\r\n* `signature`, calculated in the same way as explained above for simultaneous resource creation and update.\r\n\r\nThen, POST the resulting JSON to:\r\n `POST /bzz-resource:/`\r\n\r\n**do not change version/period values**, changing these values may cause that users can't find your latest update or some users seeing different versions of your content. \r\n\r\nPhew! That looks like a lot of stuff! But don't worry, we got you covered with API and tools. See below.\r\n\r\n### Reading a resource\r\nThis is unchanged, you can still use as before:\r\n* `GET /bzz-resource:/<MRU_MANIFEST_KEY>/` \r\n* `GET /bzz-resource://<MRU_MANIFEST_KEY>` - get latest update\r\n* `GET /bzz-resource://<MRU_MANIFEST_KEY>/<n>` - get latest update on period n\r\n* `GET /bzz-resource://<MRU_MANIFEST_KEY>/<n>/<m>` - get update version m of period n\r\n\r\n## Go API\r\nSwarm client (package `swarm/api/client`) has been updated with the following new methods:\r\n* `CreateResource(Request)`\r\n\t* `CreateResource` creates a Mutable Resource according to the data included in the `Request` parameter. To create a `Request`, use the `mru.NewCreateRequest()` function.\r\n\t* Returns the resulting Mutable Resource manifest address that you can use to include in an ENS Resolver (`setContent`) or reference future updates (`Client.UpdateResource`)\r\n* `UpdateResource(Request)`\r\n\t* `UpdateResource` allows you to send a new version of your content\r\n* `GetResource(manifestAddressOrDomain string) (io.ReadCloser, error)`\r\n\t* Returns the latest data currently contained in the resource as an octect stream. TODO: allow to get specific period/version \r\n* `GetResourceMetadata(manifestAddressOrDomain string) (*mru.UpdateRequest, error)`\r\n\t* Returns a `Request` object that describes the resource and can be used to construct an update. Typically you will call this method to obtain a `Request` and then:\r\n      * call `Request.SetData()` to put the new data in\r\n      * call `Request.Sign()` to sign the update\r\n      * call `UpdateResource()` above to send the update off.\r\n\r\n## Command line tools:\r\nIn this first version, the `swarm` cli interface has been updated with a new (advanced) command `resource` to manage resources, with this syntax:\r\n\r\n#### Create:\r\n`swarm --bzzaccount=\"<account>\" resource create <frequency> [--name <name>] [--data <0x hex data> [--multihash=true/false]]`\r\n\r\nIf successful, this command will output a Manifest Address that can be used in ENS's `setContent` or directly in your browser via http://localhost:8500/bzz:/MANIFEST_ADDRESS\r\n#### Update:\r\n`swarm --bzzaccount=\"<account>\" resource update <Manifest Address or ENS domain> <0x Hexdata> [--multihash=true/false]` \r\n\r\nthe `--multihash=false` flag sets `multihash` to false. By default the data is considered to be a multihash (`--multihash=true`). If you want to use the output of `swarm up`, prefix it with `0x1b20` to indicate a keccak256 hash.\r\n\r\n## Quick and dirty test:\r\n```\r\n$ MH=$(swarm up file.jpg) && swarm --bzzaccount \"your public key\" resource create 300 --name myresource --data 0x1b20${MH}\r\n```\r\nThis uploads `file.jpg` and creates a resource that is expected to update every 5 minutes.\r\n## Final notes:\r\nPlease let me know your feedback, questions and test issues while I document and clean up the code. I hope you like this feature. I am available on Gitter (@jpeletier). Enjoy!!\r\n\r\n### PR Review guide:\r\n[Client-side MRU signing.pdf](https://github.com/ethersphere/go-ethereum/files/2118843/Client-side.MRU.signing.pdf)\r\n","created_at":"2018-07-11T16:30:56Z","updated_at":"2018-07-19T06:49:41Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0e0af0d296b78d43218b43e685356d32595c50c7","assignee":{"login":"jpeletier","id":11574521,"node_id":"MDQ6VXNlcjExNTc0NTIx","avatar_url":"https://avatars0.githubusercontent.com/u/11574521?v=4","gravatar_id":"","url":"https://api.github.com/users/jpeletier","html_url":"https://github.com/jpeletier","followers_url":"https://api.github.com/users/jpeletier/followers","following_url":"https://api.github.com/users/jpeletier/following{/other_user}","gists_url":"https://api.github.com/users/jpeletier/gists{/gist_id}","starred_url":"https://api.github.com/users/jpeletier/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jpeletier/subscriptions","organizations_url":"https://api.github.com/users/jpeletier/orgs","repos_url":"https://api.github.com/users/jpeletier/repos","events_url":"https://api.github.com/users/jpeletier/events{/privacy}","received_events_url":"https://api.github.com/users/jpeletier/received_events","type":"User","site_admin":false},"assignees":[{"login":"jpeletier","id":11574521,"node_id":"MDQ6VXNlcjExNTc0NTIx","avatar_url":"https://avatars0.githubusercontent.com/u/11574521?v=4","gravatar_id":"","url":"https://api.github.com/users/jpeletier","html_url":"https://github.com/jpeletier","followers_url":"https://api.github.com/users/jpeletier/followers","following_url":"https://api.github.com/users/jpeletier/following{/other_user}","gists_url":"https://api.github.com/users/jpeletier/gists{/gist_id}","starred_url":"https://api.github.com/users/jpeletier/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jpeletier/subscriptions","organizations_url":"https://api.github.com/users/jpeletier/orgs","repos_url":"https://api.github.com/users/jpeletier/repos","events_url":"https://api.github.com/users/jpeletier/events{/privacy}","received_events_url":"https://api.github.com/users/jpeletier/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":86320164,"node_id":"MDU6TGFiZWw4NjMyMDE2NA==","url":"https://api.github.com/repos/ethersphere/go-ethereum/labels/enhancement","name":"enhancement","color":"84b6eb","default":true},{"id":718019424,"node_id":"MDU6TGFiZWw3MTgwMTk0MjQ=","url":"https://api.github.com/repos/ethersphere/go-ethereum/labels/ready%20for%20review","name":"ready for review","color":"44aa25","default":false},{"id":816294318,"node_id":"MDU6TGFiZWw4MTYyOTQzMTg=","url":"https://api.github.com/repos/ethersphere/go-ethereum/labels/resource%20update","name":"resource update","color":"c947e0","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/ethersphere/go-ethereum/pulls/784/commits","review_comments_url":"https://api.github.com/repos/ethersphere/go-ethereum/pulls/784/comments","review_comment_url":"https://api.github.com/repos/ethersphere/go-ethereum/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ethersphere/go-ethereum/issues/784/comments","statuses_url":"https://api.github.com/repos/ethersphere/go-ethereum/statuses/78d2a0d3f5315e8d6c259a8000fdc4305159eeed","head":{"label":"epiclabs-io:client-side-mru","ref":"client-side-mru","sha":"78d2a0d3f5315e8d6c259a8000fdc4305159eeed","user":{"login":"epiclabs-io","id":11574532,"node_id":"MDEyOk9yZ2FuaXphdGlvbjExNTc0NTMy","avatar_url":"https://avatars1.githubusercontent.com/u/11574532?v=4","gravatar_id":"","url":"https://api.github.com/users/epiclabs-io","html_url":"https://github.com/epiclabs-io","followers_url":"https://api.github.com/users/epiclabs-io/followers","following_url":"https://api.github.com/users/epiclabs-io/following{/other_user}","gists_url":"https://api.github.com/users/epiclabs-io/gists{/gist_id}","starred_url":"https://api.github.com/users/epiclabs-io/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/epiclabs-io/subscriptions","organizations_url":"https://api.github.com/users/epiclabs-io/orgs","repos_url":"https://api.github.com/users/epiclabs-io/repos","events_url":"https://api.github.com/users/epiclabs-io/events{/privacy}","received_events_url":"https://api.github.com/users/epiclabs-io/received_events","type":"Organization","site_admin":false},"repo":{"id":121309381,"node_id":"MDEwOlJlcG9zaXRvcnkxMjEzMDkzODE=","name":"go-ethereum","full_name":"epiclabs-io/go-ethereum","owner":{"login":"epiclabs-io","id":11574532,"node_id":"MDEyOk9yZ2FuaXphdGlvbjExNTc0NTMy","avatar_url":"https://avatars1.githubusercontent.com/u/11574532?v=4","gravatar_id":"","url":"https://api.github.com/users/epiclabs-io","html_url":"https://github.com/epiclabs-io","followers_url":"https://api.github.com/users/epiclabs-io/followers","following_url":"https://api.github.com/users/epiclabs-io/following{/other_user}","gists_url":"https://api.github.com/users/epiclabs-io/gists{/gist_id}","starred_url":"https://api.github.com/users/epiclabs-io/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/epiclabs-io/subscriptions","organizations_url":"https://api.github.com/users/epiclabs-io/orgs","repos_url":"https://api.github.com/users/epiclabs-io/repos","events_url":"https://api.github.com/users/epiclabs-io/events{/privacy}","received_events_url":"https://api.github.com/users/epiclabs-io/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/epiclabs-io/go-ethereum","description":"Official Go implementation of the Ethereum protocol","fork":true,"url":"https://api.github.com/repos/epiclabs-io/go-ethereum","forks_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/forks","keys_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/keys{/key_id}","collaborators_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/teams","hooks_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/hooks","issue_events_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/issues/events{/number}","events_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/events","assignees_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/assignees{/user}","branches_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/branches{/branch}","tags_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/tags","blobs_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/git/refs{/sha}","trees_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/git/trees{/sha}","statuses_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/statuses/{sha}","languages_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/languages","stargazers_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/stargazers","contributors_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/contributors","subscribers_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/subscribers","subscription_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/subscription","commits_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/commits{/sha}","git_commits_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/git/commits{/sha}","comments_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/comments{/number}","issue_comment_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/issues/comments{/number}","contents_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/contents/{+path}","compare_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/compare/{base}...{head}","merges_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/merges","archive_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/downloads","issues_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/issues{/number}","pulls_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/pulls{/number}","milestones_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/milestones{/number}","notifications_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/labels{/name}","releases_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/releases{/id}","deployments_url":"https://api.github.com/repos/epiclabs-io/go-ethereum/deployments","created_at":"2018-02-12T22:18:49Z","updated_at":"2018-02-12T22:18:56Z","pushed_at":"2018-07-18T10:52:55Z","git_url":"git://github.com/epiclabs-io/go-ethereum.git","ssh_url":"git@github.com:epiclabs-io/go-ethereum.git","clone_url":"https://github.com/epiclabs-io/go-ethereum.git","svn_url":"https://github.com/epiclabs-io/go-ethereum","homepage":"https://geth.ethereum.org","size":103577,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"lgpl-3.0","name":"GNU Lesser General Public License v3.0","spdx_id":"LGPL-3.0","url":"https://api.github.com/licenses/lgpl-3.0","node_id":"MDc6TGljZW5zZTEy"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"ethersphere:develop","ref":"develop","sha":"6110b4431af2b3bc1aa7759f018a6d37d926e88d","user":{"login":"ethersphere","id":6946989,"node_id":"MDEyOk9yZ2FuaXphdGlvbjY5NDY5ODk=","avatar_url":"https://avatars2.githubusercontent.com/u/6946989?v=4","gravatar_id":"","url":"https://api.github.com/users/ethersphere","html_url":"https://github.com/ethersphere","followers_url":"https://api.github.com/users/ethersphere/followers","following_url":"https://api.github.com/users/ethersphere/following{/other_user}","gists_url":"https://api.github.com/users/ethersphere/gists{/gist_id}","starred_url":"https://api.github.com/users/ethersphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ethersphere/subscriptions","organizations_url":"https://api.github.com/users/ethersphere/orgs","repos_url":"https://api.github.com/users/ethersphere/repos","events_url":"https://api.github.com/users/ethersphere/events{/privacy}","received_events_url":"https://api.github.com/users/ethersphere/received_events","type":"Organization","site_admin":false},"repo":{"id":17790136,"node_id":"MDEwOlJlcG9zaXRvcnkxNzc5MDEzNg==","name":"go-ethereum","full_name":"ethersphere/go-ethereum","owner":{"login":"ethersphere","id":6946989,"node_id":"MDEyOk9yZ2FuaXphdGlvbjY5NDY5ODk=","avatar_url":"https://avatars2.githubusercontent.com/u/6946989?v=4","gravatar_id":"","url":"https://api.github.com/users/ethersphere","html_url":"https://github.com/ethersphere","followers_url":"https://api.github.com/users/ethersphere/followers","following_url":"https://api.github.com/users/ethersphere/following{/other_user}","gists_url":"https://api.github.com/users/ethersphere/gists{/gist_id}","starred_url":"https://api.github.com/users/ethersphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ethersphere/subscriptions","organizations_url":"https://api.github.com/users/ethersphere/orgs","repos_url":"https://api.github.com/users/ethersphere/repos","events_url":"https://api.github.com/users/ethersphere/events{/privacy}","received_events_url":"https://api.github.com/users/ethersphere/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ethersphere/go-ethereum","description":"Ethereum Go","fork":true,"url":"https://api.github.com/repos/ethersphere/go-ethereum","forks_url":"https://api.github.com/repos/ethersphere/go-ethereum/forks","keys_url":"https://api.github.com/repos/ethersphere/go-ethereum/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ethersphere/go-ethereum/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ethersphere/go-ethereum/teams","hooks_url":"https://api.github.com/repos/ethersphere/go-ethereum/hooks","issue_events_url":"https://api.github.com/repos/ethersphere/go-ethereum/issues/events{/number}","events_url":"https://api.github.com/repos/ethersphere/go-ethereum/events","assignees_url":"https://api.github.com/repos/ethersphere/go-ethereum/assignees{/user}","branches_url":"https://api.github.com/repos/ethersphere/go-ethereum/branches{/branch}","tags_url":"https://api.github.com/repos/ethersphere/go-ethereum/tags","blobs_url":"https://api.github.com/repos/ethersphere/go-ethereum/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ethersphere/go-ethereum/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ethersphere/go-ethereum/git/refs{/sha}","trees_url":"https://api.github.com/repos/ethersphere/go-ethereum/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ethersphere/go-ethereum/statuses/{sha}","languages_url":"https://api.github.com/repos/ethersphere/go-ethereum/languages","stargazers_url":"https://api.github.com/repos/ethersphere/go-ethereum/stargazers","contributors_url":"https://api.github.com/repos/ethersphere/go-ethereum/contributors","subscribers_url":"https://api.github.com/repos/ethersphere/go-ethereum/subscribers","subscription_url":"https://api.github.com/repos/ethersphere/go-ethereum/subscription","commits_url":"https://api.github.com/repos/ethersphere/go-ethereum/commits{/sha}","git_commits_url":"https://api.github.com/repos/ethersphere/go-ethereum/git/commits{/sha}","comments_url":"https://api.github.com/repos/ethersphere/go-ethereum/comments{/number}","issue_comment_url":"https://api.github.com/repos/ethersphere/go-ethereum/issues/comments{/number}","contents_url":"https://api.github.com/repos/ethersphere/go-ethereum/contents/{+path}","compare_url":"https://api.github.com/repos/ethersphere/go-ethereum/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ethersphere/go-ethereum/merges","archive_url":"https://api.github.com/repos/ethersphere/go-ethereum/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ethersphere/go-ethereum/downloads","issues_url":"https://api.github.com/repos/ethersphere/go-ethereum/issues{/number}","pulls_url":"https://api.github.com/repos/ethersphere/go-ethereum/pulls{/number}","milestones_url":"https://api.github.com/repos/ethersphere/go-ethereum/milestones{/number}","notifications_url":"https://api.github.com/repos/ethersphere/go-ethereum/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ethersphere/go-ethereum/labels{/name}","releases_url":"https://api.github.com/repos/ethersphere/go-ethereum/releases{/id}","deployments_url":"https://api.github.com/repos/ethersphere/go-ethereum/deployments","created_at":"2014-03-16T02:06:34Z","updated_at":"2018-07-18T16:23:25Z","pushed_at":"2018-07-18T21:20:23Z","git_url":"git://github.com/ethersphere/go-ethereum.git","ssh_url":"git@github.com:ethersphere/go-ethereum.git","clone_url":"https://github.com/ethersphere/go-ethereum.git","svn_url":"https://github.com/ethersphere/go-ethereum","homepage":"","size":97644,"stargazers_count":107,"watchers_count":107,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":31,"mirror_url":null,"archived":false,"open_issues_count":176,"license":{"key":"lgpl-3.0","name":"GNU Lesser General Public License v3.0","spdx_id":"LGPL-3.0","url":"https://api.github.com/licenses/lgpl-3.0","node_id":"MDc6TGljZW5zZTEy"},"forks":31,"open_issues":176,"watchers":107,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/ethersphere/go-ethereum/pulls/784"},"html":{"href":"https://github.com/ethersphere/go-ethereum/pull/784"},"issue":{"href":"https://api.github.com/repos/ethersphere/go-ethereum/issues/784"},"comments":{"href":"https://api.github.com/repos/ethersphere/go-ethereum/issues/784/comments"},"review_comments":{"href":"https://api.github.com/repos/ethersphere/go-ethereum/pulls/784/comments"},"review_comment":{"href":"https://api.github.com/repos/ethersphere/go-ethereum/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ethersphere/go-ethereum/pulls/784/commits"},"statuses":{"href":"https://api.github.com/repos/ethersphere/go-ethereum/statuses/78d2a0d3f5315e8d6c259a8000fdc4305159eeed"}},"author_association":"NONE"}}
{"actor":{"display_login":"nolash"}}