{"action":"created","comment":{"url":"https://api.github.com/repos/ripple/rippled/pulls/comments/34296601","id":34296601,"diff_hunk":"@@ -0,0 +1,589 @@\n+//------------------------------------------------------------------------------\n+/*\n+    This file is part of rippled: https://github.com/ripple/rippled\n+    Copyright (c) 2012, 2013 Ripple Labs Inc.\n+\n+    Permission to use, copy, modify, and/or distribute this software for any\n+    purpose  with  or without fee is hereby granted, provided that the above\n+    copyright notice and this permission notice appear in all copies.\n+\n+    THE  SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n+    WITH  REGARD  TO  THIS  SOFTWARE  INCLUDING  ALL  IMPLIED  WARRANTIES  OF\n+    MERCHANTABILITY  AND  FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n+    ANY  SPECIAL ,  DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n+    WHATSOEVER  RESULTING  FROM  LOSS  OF USE, DATA OR PROFITS, WHETHER IN AN\n+    ACTION  OF  CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n+*/\n+//==============================================================================\n+\n+#include <BeastConfig.h>\n+#include <ripple/ledger/detail/ApplyStateTable.h>\n+#include <ripple/basics/contract.h>\n+#include <ripple/basics/Log.h>\n+#include <ripple/json/to_string.h>\n+#include <cassert>\n+\n+namespace ripple {\n+namespace detail {\n+\n+void\n+ApplyStateTable::apply (RawView& to) const\n+{\n+    to.rawDestroyXRP(dropsDestroyed_);\n+    for (auto const& item : items_)\n+    {\n+        auto const& sle =\n+            item.second.second;\n+        switch(item.second.first)\n+        {\n+        case Action::cache:\n+            break;\n+        case Action::erase:\n+            to.rawErase(sle);\n+            break;\n+        case Action::insert:\n+            to.rawInsert(sle);\n+            break;\n+        case Action::modify:\n+            to.rawReplace(sle);\n+            break;\n+        };\n+    }\n+}\n+\n+void\n+ApplyStateTable::apply (OpenView& to,\n+    STTx const& tx, TER ter,\n+        boost::optional<STAmount> const& deliver,\n+            beast::Journal j)\n+{\n+    // Build metadata and insert\n+    auto const sTx =\n+        std::make_shared<Serializer>();\n+    tx.add(*sTx);\n+    std::shared_ptr<Serializer> sMeta;\n+    if (to.closed())\n+    {\n+        TxMeta meta;\n+        // VFALCO Shouldn't TxMeta ctor do this?\n+        meta.init (tx.getTransactionID(), to.seq());\n+        if (deliver)\n+            meta.setDeliveredAmount(*deliver);\n+        Mods newMod;\n+        // VFALCO NOTE getForMod can insert items with\n+        //             Action::cache during the loop.\n+        for (auto& item : items_)\n+        {\n+            SField const* type;\n+            switch (item.second.first)\n+            {\n+            default:\n+            case Action::cache:\n+                continue;\n+            case Action::erase:\n+                type = &sfDeletedNode;\n+                break;\n+            case Action::insert:\n+                type = &sfCreatedNode;\n+                break;\n+            case Action::modify:\n+                type = &sfModifiedNode;\n+                break;\n+            }\n+            auto const origNode =\n+                to.read(keylet::unchecked(item.first));\n+            auto curNode = item.second.second;\n+            if ((type == &sfModifiedNode) && (*curNode == *origNode))\n+                continue;\n+            std::uint16_t nodeType = curNode\n+                ? curNode->getFieldU16 (sfLedgerEntryType)\n+                : origNode->getFieldU16 (sfLedgerEntryType);\n+            meta.setAffectedNode (item.first, *type, nodeType);\n+            if (type == &sfDeletedNode)\n+            {\n+                assert (origNode && curNode);\n+                threadOwners (to, meta, origNode, newMod, j);\n+\n+                STObject prevs (sfPreviousFields);\n+                for (auto const& obj : *origNode)\n+                {\n+                    // go through the original node for\n+                    // modified  fields saved on modification\n+                    if (obj.getFName().shouldMeta(\n+                            SField::sMD_ChangeOrig) &&\n+                                ! curNode->hasMatchingEntry (obj))\n+                        prevs.emplace_back (obj);\n+                }\n+\n+                if (!prevs.empty ())\n+                    meta.getAffectedNode(item.first).emplace_back(std::move(prevs));\n+\n+                STObject finals (sfFinalFields);\n+                for (auto const& obj : *curNode)\n+                {\n+                    // go through the final node for final fields\n+                    if (obj.getFName().shouldMeta(\n+                            SField::sMD_Always | SField::sMD_DeleteFinal))\n+                        finals.emplace_back (obj);\n+                }\n+\n+                if (!finals.empty ())\n+                    meta.getAffectedNode (item.first).emplace_back (std::move(finals));\n+            }\n+            else if (type == &sfModifiedNode)\n+            {\n+                assert (curNode && origNode);\n+\n+                if (curNode->isThreadedType ()) // thread transaction to node item modified\n+                    threadTx (meta, curNode, newMod);\n+\n+                STObject prevs (sfPreviousFields);\n+                for (auto const& obj : *origNode)\n+                {\n+                    // search the original node for values saved on modify\n+                    if (obj.getFName ().shouldMeta (SField::sMD_ChangeOrig) && !curNode->hasMatchingEntry (obj))\n+                        prevs.emplace_back (obj);\n+                }\n+\n+                if (!prevs.empty ())\n+                    meta.getAffectedNode (item.first).emplace_back (std::move(prevs));\n+\n+                STObject finals (sfFinalFields);\n+                for (auto const& obj : *curNode)\n+                {\n+                    // search the final node for values saved always\n+                    if (obj.getFName ().shouldMeta (SField::sMD_Always | SField::sMD_ChangeNew))\n+                        finals.emplace_back (obj);\n+                }\n+\n+                if (!finals.empty ())\n+                    meta.getAffectedNode (item.first).emplace_back (std::move(finals));\n+            }\n+            else if (type == &sfCreatedNode) // if created, thread to owner(s)\n+            {\n+                assert (curNode && !origNode);\n+                threadOwners (to, meta, curNode, newMod, j);\n+\n+                if (curNode->isThreadedType ()) // always thread to self\n+                    threadTx (meta, curNode, newMod);\n+\n+                STObject news (sfNewFields);\n+                for (auto const& obj : *curNode)\n+                {\n+                    // save non-default values\n+                    if (!obj.isDefault () &&\n+                            obj.getFName().shouldMeta(\n+                                SField::sMD_Create | SField::sMD_Always))\n+                        news.emplace_back (obj);\n+                }\n+\n+                if (!news.empty ())\n+                    meta.getAffectedNode (item.first).emplace_back (std::move(news));\n+            }\n+            else\n+            {\n+                assert (false);\n+            }\n+        }\n+\n+        // add any new modified nodes to the modification set\n+        for (auto& mod : newMod)\n+            update (to, mod.second);\n+\n+        sMeta = std::make_shared<Serializer>();\n+        meta.addRaw (*sMeta, ter, to.txCount());\n+\n+        // VFALCO For diagnostics do we want to show\n+        //        metadata even when the base view is open?\n+        JLOG(j.trace) <<\n+            \"metadata \" << meta.getJson (0);\n+    }\n+    to.rawTxInsert(\n+        tx.getTransactionID(),\n+            sTx, sMeta);\n+    apply(to);\n+}\n+\n+//---\n+\n+bool\n+ApplyStateTable::exists (ReadView const& base,\n+    Keylet const& k) const\n+{\n+    auto const iter = items_.find(k.key);\n+    if (iter == items_.end())\n+        return base.exists(k);\n+    auto const& item = iter->second;\n+    auto const& sle = item.second;\n+    switch (item.first)\n+    {\n+    case Action::erase:\n+        return false;\n+    case Action::cache:\n+    case Action::insert:\n+    case Action::modify:\n+        break;\n+    }\n+    if (! k.check(*sle))\n+        return false;\n+    return true;\n+}\n+\n+auto\n+ApplyStateTable::succ (ReadView const& base,\n+    key_type const& key, boost::optional<\n+        key_type> const& last) const ->\n+            boost::optional<key_type>\n+{\n+    boost::optional<key_type> next = key;\n+    items_t::const_iterator iter;\n+    // Find base successor that is\n+    // not also deleted in our list\n+    do\n+    {\n+        next = base.succ(*next, last);\n+        if (! next)\n+            break;\n+        iter = items_.find(*next);\n+    }\n+    while (iter != items_.end() &&\n+        iter->second.first == Action::erase);\n+    // Find non-deleted successor in our list\n+    for (iter = items_.upper_bound(key);\n+        iter != items_.end (); ++iter)\n+    {\n+        if (iter->second.first != Action::erase)\n+        {\n+            // Found both, return the lower key\n+            if (! next || next > iter->first)\n+                next = iter->first;\n+            break;\n+        }\n+    }\n+    // Nothing in our list, return\n+    // what we got from the parent.\n+    if (last && next >= last)\n+        return boost::none;\n+    return next;\n+}\n+\n+std::shared_ptr<SLE const>\n+ApplyStateTable::read (ReadView const& base,\n+    Keylet const& k) const\n+{\n+    auto const iter = items_.find(k.key);\n+    if (iter == items_.end())\n+        return base.read(k);\n+    auto const& item = iter->second;\n+    auto const& sle = item.second;\n+    switch (item.first)\n+    {\n+    case Action::erase:\n+        return nullptr;\n+    case Action::cache:\n+    case Action::insert:\n+    case Action::modify:\n+        break;\n+    };\n+    if (! k.check(*sle))\n+        return nullptr;\n+    return sle;\n+}\n+\n+std::shared_ptr<SLE>\n+ApplyStateTable::peek (ReadView const& base,\n+    Keylet const& k)\n+{\n+    auto iter = items_.lower_bound(k.key);\n+    if (iter == items_.end() ||\n+        iter->first != k.key)\n+    {\n+        auto const sle = base.read(k);\n+        if (! sle)\n+            return nullptr;\n+        // Make our own copy\n+        using namespace std;\n+        iter = items_.emplace_hint (iter,\n+            piecewise_construct,\n+                forward_as_tuple(sle->key()),\n+                    forward_as_tuple(Action::cache,\n+                        make_shared<SLE>(*sle)));\n+        return iter->second.second;\n+    }\n+    auto const& item = iter->second;\n+    auto const& sle = item.second;\n+    switch (item.first)\n+    {\n+    case Action::erase:\n+        return nullptr;\n+    case Action::cache:\n+    case Action::insert:\n+    case Action::modify:\n+        break;\n+    };\n+    if (! k.check(*sle))\n+        return nullptr;\n+    return sle;\n+}\n+\n+void\n+ApplyStateTable::erase(\n+    ReadView const& base,\n+        std::shared_ptr<SLE> const& sle)\n+{\n+    auto const iter =\n+        items_.find(sle->key());\n+    if (iter == items_.end())\n+        LogicError(\"ApplyStateTable::erase: missing key\");\n+    auto& item = iter->second;\n+    if (item.second != sle)\n+        LogicError(\"ApplyStateTable::erase: unknown SLE\");\n+    switch(item.first)\n+    {\n+    case Action::erase:\n+        LogicError(\"ApplyStateTable::erase: double erase\");\n+        break;\n+    case Action::insert:\n+        items_.erase(iter);\n+        break;\n+    case Action::cache:\n+    case Action::modify:\n+        item.first = Action::erase;\n+        break;\n+    }\n+}\n+\n+void\n+ApplyStateTable::rawErase (ReadView const& base,\n+    std::shared_ptr<SLE> const& sle)\n+{\n+    using namespace std;\n+    auto const result = items_.emplace(\n+        piecewise_construct,\n+            forward_as_tuple(sle->key()),\n+                forward_as_tuple(Action::erase, sle));\n+    if (result.second)\n+        return;\n+    auto& item = result.first->second;\n+    switch(item.first)\n+    {\n+    case Action::erase:\n+        LogicError(\"ApplyStateTable::rawErase: double erase\");\n+        break;\n+    case Action::insert:\n+        items_.erase(result.first);\n+        break;\n+    case Action::cache:\n+    case Action::modify:\n+        item.first = Action::erase;\n+        item.second = sle;\n+        break;\n+    }\n+}\n+\n+void\n+ApplyStateTable::insert (ReadView const& base,\n+    std::shared_ptr<SLE> const& sle)\n+{\n+    auto const iter =\n+        items_.lower_bound(sle->key());\n+    if (iter == items_.end() ||\n+        iter->first != sle->key())\n+    {\n+        using namespace std;\n+        items_.emplace_hint(iter,\n+            piecewise_construct,\n+                forward_as_tuple(sle->key()),\n+                    forward_as_tuple(Action::insert, sle));\n+        return;\n+    }\n+    auto& item = iter->second;\n+    switch(item.first)\n+    {\n+    case Action::cache:\n+        LogicError(\"ApplyStateTable::insert: already cached\");\n+    case Action::insert:\n+        LogicError(\"ApplyStateTable::insert: already inserted\");        ","path":"src/ripple/ledger/impl/ApplyStateTable.cpp","position":407,"original_position":407,"commit_id":"a690352cf16172894277c6a5fac4b7f28e5a1dc2","original_commit_id":"a690352cf16172894277c6a5fac4b7f28e5a1dc2","user":{"login":"JoelKatz","id":877549,"avatar_url":"https://avatars.githubusercontent.com/u/877549?v=3","gravatar_id":"","url":"https://api.github.com/users/JoelKatz","html_url":"https://github.com/JoelKatz","followers_url":"https://api.github.com/users/JoelKatz/followers","following_url":"https://api.github.com/users/JoelKatz/following{/other_user}","gists_url":"https://api.github.com/users/JoelKatz/gists{/gist_id}","starred_url":"https://api.github.com/users/JoelKatz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JoelKatz/subscriptions","organizations_url":"https://api.github.com/users/JoelKatz/orgs","repos_url":"https://api.github.com/users/JoelKatz/repos","events_url":"https://api.github.com/users/JoelKatz/events{/privacy}","received_events_url":"https://api.github.com/users/JoelKatz/received_events","type":"User","site_admin":false},"body":"Same reason. The postcondition is not that the item exists but that the item was created and that the metadata will reflect this creation. There's a very, very tight set of API rules that must be followed when modifying the ledger and we definitely do not want code that breaches these rules to have its changes committed to an immutable, public ledger.","created_at":"2015-07-09T19:59:15Z","updated_at":"2015-07-09T19:59:15Z","html_url":"https://github.com/ripple/rippled/pull/1169#discussion_r34296601","pull_request_url":"https://api.github.com/repos/ripple/rippled/pulls/1169","_links":{"self":{"href":"https://api.github.com/repos/ripple/rippled/pulls/comments/34296601"},"html":{"href":"https://github.com/ripple/rippled/pull/1169#discussion_r34296601"},"pull_request":{"href":"https://api.github.com/repos/ripple/rippled/pulls/1169"}}},"pull_request":{"url":"https://api.github.com/repos/ripple/rippled/pulls/1169","id":39411334,"html_url":"https://github.com/ripple/rippled/pull/1169","diff_url":"https://github.com/ripple/rippled/pull/1169.diff","patch_url":"https://github.com/ripple/rippled/pull/1169.patch","issue_url":"https://api.github.com/repos/ripple/rippled/issues/1169","number":1169,"state":"open","locked":false,"title":"OpenLedger and View refactoring","user":{"login":"vinniefalco","id":1503976,"avatar_url":"https://avatars.githubusercontent.com/u/1503976?v=3","gravatar_id":"","url":"https://api.github.com/users/vinniefalco","html_url":"https://github.com/vinniefalco","followers_url":"https://api.github.com/users/vinniefalco/followers","following_url":"https://api.github.com/users/vinniefalco/following{/other_user}","gists_url":"https://api.github.com/users/vinniefalco/gists{/gist_id}","starred_url":"https://api.github.com/users/vinniefalco/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vinniefalco/subscriptions","organizations_url":"https://api.github.com/users/vinniefalco/orgs","repos_url":"https://api.github.com/users/vinniefalco/repos","events_url":"https://api.github.com/users/vinniefalco/events{/privacy}","received_events_url":"https://api.github.com/users/vinniefalco/received_events","type":"User","site_admin":false},"body":"This adds the `OpenLedger` singleton, designed to replace the current open ledger code. It is disabled, and can be turned on with `#define RIPPLE_OPEN_LEDGER 1`. When on it builds an open ledger in parallel and writes discrepancies to the log file. Currently, it runs without discrepancy. Which means it builds new open ledgers identically to the existing code.\r\n\r\nThis also includes a full refactoring of the `View` hierarchy of classes.\r\n","created_at":"2015-07-07T20:11:54Z","updated_at":"2015-07-09T19:59:15Z","closed_at":null,"merged_at":null,"merge_commit_sha":"56a8a5979128b9b0fc59d428a2f2a7d90f1e4c82","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/ripple/rippled/pulls/1169/commits","review_comments_url":"https://api.github.com/repos/ripple/rippled/pulls/1169/comments","review_comment_url":"https://api.github.com/repos/ripple/rippled/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ripple/rippled/issues/1169/comments","statuses_url":"https://api.github.com/repos/ripple/rippled/statuses/a690352cf16172894277c6a5fac4b7f28e5a1dc2","head":{"label":"vinniefalco:openview","ref":"openview","sha":"a690352cf16172894277c6a5fac4b7f28e5a1dc2","user":{"login":"vinniefalco","id":1503976,"avatar_url":"https://avatars.githubusercontent.com/u/1503976?v=3","gravatar_id":"","url":"https://api.github.com/users/vinniefalco","html_url":"https://github.com/vinniefalco","followers_url":"https://api.github.com/users/vinniefalco/followers","following_url":"https://api.github.com/users/vinniefalco/following{/other_user}","gists_url":"https://api.github.com/users/vinniefalco/gists{/gist_id}","starred_url":"https://api.github.com/users/vinniefalco/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vinniefalco/subscriptions","organizations_url":"https://api.github.com/users/vinniefalco/orgs","repos_url":"https://api.github.com/users/vinniefalco/repos","events_url":"https://api.github.com/users/vinniefalco/events{/privacy}","received_events_url":"https://api.github.com/users/vinniefalco/received_events","type":"User","site_admin":false},"repo":{"id":10961863,"name":"rippled","full_name":"vinniefalco/rippled","owner":{"login":"vinniefalco","id":1503976,"avatar_url":"https://avatars.githubusercontent.com/u/1503976?v=3","gravatar_id":"","url":"https://api.github.com/users/vinniefalco","html_url":"https://github.com/vinniefalco","followers_url":"https://api.github.com/users/vinniefalco/followers","following_url":"https://api.github.com/users/vinniefalco/following{/other_user}","gists_url":"https://api.github.com/users/vinniefalco/gists{/gist_id}","starred_url":"https://api.github.com/users/vinniefalco/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vinniefalco/subscriptions","organizations_url":"https://api.github.com/users/vinniefalco/orgs","repos_url":"https://api.github.com/users/vinniefalco/repos","events_url":"https://api.github.com/users/vinniefalco/events{/privacy}","received_events_url":"https://api.github.com/users/vinniefalco/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/vinniefalco/rippled","description":"Ripple peer-to-peer network daemon","fork":true,"url":"https://api.github.com/repos/vinniefalco/rippled","forks_url":"https://api.github.com/repos/vinniefalco/rippled/forks","keys_url":"https://api.github.com/repos/vinniefalco/rippled/keys{/key_id}","collaborators_url":"https://api.github.com/repos/vinniefalco/rippled/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/vinniefalco/rippled/teams","hooks_url":"https://api.github.com/repos/vinniefalco/rippled/hooks","issue_events_url":"https://api.github.com/repos/vinniefalco/rippled/issues/events{/number}","events_url":"https://api.github.com/repos/vinniefalco/rippled/events","assignees_url":"https://api.github.com/repos/vinniefalco/rippled/assignees{/user}","branches_url":"https://api.github.com/repos/vinniefalco/rippled/branches{/branch}","tags_url":"https://api.github.com/repos/vinniefalco/rippled/tags","blobs_url":"https://api.github.com/repos/vinniefalco/rippled/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/vinniefalco/rippled/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/vinniefalco/rippled/git/refs{/sha}","trees_url":"https://api.github.com/repos/vinniefalco/rippled/git/trees{/sha}","statuses_url":"https://api.github.com/repos/vinniefalco/rippled/statuses/{sha}","languages_url":"https://api.github.com/repos/vinniefalco/rippled/languages","stargazers_url":"https://api.github.com/repos/vinniefalco/rippled/stargazers","contributors_url":"https://api.github.com/repos/vinniefalco/rippled/contributors","subscribers_url":"https://api.github.com/repos/vinniefalco/rippled/subscribers","subscription_url":"https://api.github.com/repos/vinniefalco/rippled/subscription","commits_url":"https://api.github.com/repos/vinniefalco/rippled/commits{/sha}","git_commits_url":"https://api.github.com/repos/vinniefalco/rippled/git/commits{/sha}","comments_url":"https://api.github.com/repos/vinniefalco/rippled/comments{/number}","issue_comment_url":"https://api.github.com/repos/vinniefalco/rippled/issues/comments{/number}","contents_url":"https://api.github.com/repos/vinniefalco/rippled/contents/{+path}","compare_url":"https://api.github.com/repos/vinniefalco/rippled/compare/{base}...{head}","merges_url":"https://api.github.com/repos/vinniefalco/rippled/merges","archive_url":"https://api.github.com/repos/vinniefalco/rippled/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/vinniefalco/rippled/downloads","issues_url":"https://api.github.com/repos/vinniefalco/rippled/issues{/number}","pulls_url":"https://api.github.com/repos/vinniefalco/rippled/pulls{/number}","milestones_url":"https://api.github.com/repos/vinniefalco/rippled/milestones{/number}","notifications_url":"https://api.github.com/repos/vinniefalco/rippled/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/vinniefalco/rippled/labels{/name}","releases_url":"https://api.github.com/repos/vinniefalco/rippled/releases{/id}","created_at":"2013-06-26T07:51:04Z","updated_at":"2015-05-07T17:26:52Z","pushed_at":"2015-07-09T15:52:31Z","git_url":"git://github.com/vinniefalco/rippled.git","ssh_url":"git@github.com:vinniefalco/rippled.git","clone_url":"https://github.com/vinniefalco/rippled.git","svn_url":"https://github.com/vinniefalco/rippled","homepage":"https://ripple.com","size":71150,"stargazers_count":3,"watchers_count":3,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":0,"forks":1,"open_issues":0,"watchers":3,"default_branch":"develop"}},"base":{"label":"ripple:develop","ref":"develop","sha":"73d64bbafc9e04bf47cd38c1d104eb836b2a9c66","user":{"login":"ripple","id":3165523,"avatar_url":"https://avatars.githubusercontent.com/u/3165523?v=3","gravatar_id":"","url":"https://api.github.com/users/ripple","html_url":"https://github.com/ripple","followers_url":"https://api.github.com/users/ripple/followers","following_url":"https://api.github.com/users/ripple/following{/other_user}","gists_url":"https://api.github.com/users/ripple/gists{/gist_id}","starred_url":"https://api.github.com/users/ripple/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ripple/subscriptions","organizations_url":"https://api.github.com/users/ripple/orgs","repos_url":"https://api.github.com/users/ripple/repos","events_url":"https://api.github.com/users/ripple/events{/privacy}","received_events_url":"https://api.github.com/users/ripple/received_events","type":"Organization","site_admin":false},"repo":{"id":2724167,"name":"rippled","full_name":"ripple/rippled","owner":{"login":"ripple","id":3165523,"avatar_url":"https://avatars.githubusercontent.com/u/3165523?v=3","gravatar_id":"","url":"https://api.github.com/users/ripple","html_url":"https://github.com/ripple","followers_url":"https://api.github.com/users/ripple/followers","following_url":"https://api.github.com/users/ripple/following{/other_user}","gists_url":"https://api.github.com/users/ripple/gists{/gist_id}","starred_url":"https://api.github.com/users/ripple/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ripple/subscriptions","organizations_url":"https://api.github.com/users/ripple/orgs","repos_url":"https://api.github.com/users/ripple/repos","events_url":"https://api.github.com/users/ripple/events{/privacy}","received_events_url":"https://api.github.com/users/ripple/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ripple/rippled","description":"Ripple peer-to-peer network daemon","fork":false,"url":"https://api.github.com/repos/ripple/rippled","forks_url":"https://api.github.com/repos/ripple/rippled/forks","keys_url":"https://api.github.com/repos/ripple/rippled/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ripple/rippled/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ripple/rippled/teams","hooks_url":"https://api.github.com/repos/ripple/rippled/hooks","issue_events_url":"https://api.github.com/repos/ripple/rippled/issues/events{/number}","events_url":"https://api.github.com/repos/ripple/rippled/events","assignees_url":"https://api.github.com/repos/ripple/rippled/assignees{/user}","branches_url":"https://api.github.com/repos/ripple/rippled/branches{/branch}","tags_url":"https://api.github.com/repos/ripple/rippled/tags","blobs_url":"https://api.github.com/repos/ripple/rippled/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ripple/rippled/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ripple/rippled/git/refs{/sha}","trees_url":"https://api.github.com/repos/ripple/rippled/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ripple/rippled/statuses/{sha}","languages_url":"https://api.github.com/repos/ripple/rippled/languages","stargazers_url":"https://api.github.com/repos/ripple/rippled/stargazers","contributors_url":"https://api.github.com/repos/ripple/rippled/contributors","subscribers_url":"https://api.github.com/repos/ripple/rippled/subscribers","subscription_url":"https://api.github.com/repos/ripple/rippled/subscription","commits_url":"https://api.github.com/repos/ripple/rippled/commits{/sha}","git_commits_url":"https://api.github.com/repos/ripple/rippled/git/commits{/sha}","comments_url":"https://api.github.com/repos/ripple/rippled/comments{/number}","issue_comment_url":"https://api.github.com/repos/ripple/rippled/issues/comments{/number}","contents_url":"https://api.github.com/repos/ripple/rippled/contents/{+path}","compare_url":"https://api.github.com/repos/ripple/rippled/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ripple/rippled/merges","archive_url":"https://api.github.com/repos/ripple/rippled/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ripple/rippled/downloads","issues_url":"https://api.github.com/repos/ripple/rippled/issues{/number}","pulls_url":"https://api.github.com/repos/ripple/rippled/pulls{/number}","milestones_url":"https://api.github.com/repos/ripple/rippled/milestones{/number}","notifications_url":"https://api.github.com/repos/ripple/rippled/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ripple/rippled/labels{/name}","releases_url":"https://api.github.com/repos/ripple/rippled/releases{/id}","created_at":"2011-11-07T04:40:15Z","updated_at":"2015-07-06T16:12:51Z","pushed_at":"2015-07-09T18:24:47Z","git_url":"git://github.com/ripple/rippled.git","ssh_url":"git@github.com:ripple/rippled.git","clone_url":"https://github.com/ripple/rippled.git","svn_url":"https://github.com/ripple/rippled","homepage":"https://ripple.com","size":118250,"stargazers_count":967,"watchers_count":967,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":271,"mirror_url":null,"open_issues_count":132,"forks":271,"open_issues":132,"watchers":967,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/ripple/rippled/pulls/1169"},"html":{"href":"https://github.com/ripple/rippled/pull/1169"},"issue":{"href":"https://api.github.com/repos/ripple/rippled/issues/1169"},"comments":{"href":"https://api.github.com/repos/ripple/rippled/issues/1169/comments"},"review_comments":{"href":"https://api.github.com/repos/ripple/rippled/pulls/1169/comments"},"review_comment":{"href":"https://api.github.com/repos/ripple/rippled/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ripple/rippled/pulls/1169/commits"},"statuses":{"href":"https://api.github.com/repos/ripple/rippled/statuses/a690352cf16172894277c6a5fac4b7f28e5a1dc2"}}}}